From 951cba5ebeee57ba9cc5eb0ec869304be639389c Mon Sep 17 00:00:00 2001 From: Olivier Gorzalka Date: Tue, 29 Sep 2026 16:59:18 +0200 Subject: [PATCH] feat: offer Buzz as the magazine template of pollora:make:theme A third built-in template, next to default and ecommerce: a Full Site Editing block theme. The prompt's labels move to TEMPLATE_LABELS, keyed like TEMPLATES, and a test keeps the two in step. The missing-theme page and admin notice list it too. --- CHANGELOG.md | 3 +++ resources/views/theme-missing.blade.php | 6 ++++++ src/Theme/UI/Console/MakeThemeCommand.php | 13 ++++++++++-- src/Theme/UI/Http/MissingThemeNotice.php | 7 +++++-- .../Theme/MissingThemeGuidanceTest.php | 8 +++++-- .../Theme/MakeThemeCommandTemplatesTest.php | 21 +++++++++++++++++++ 6 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 tests/Unit/Theme/MakeThemeCommandTemplatesTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a534a21..7168d147 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://github.com/Pollora/framework/compare/v13.32.0-beta.9...develop) +### Added +- A third `pollora:make:theme` template, **Magazine** (`magazine` → `pollora/theme-buzz`): a Full Site Editing block theme whose templates, parts and patterns are edited in the Site Editor, next to `default` and `ecommerce`. The missing-theme page and admin notice list it too + ### Fixed - A Vite script was printed before WordPress's import map, which Firefox and Safari then ignore: any WordPress script module on the page — the navigation block's, the search block's, the image lightbox's — failed on `@wordpress/interactivity was a bare specifier`, so the block did nothing. Chromium tolerates the order, which hid it. In a classic theme the import map is always in the footer, so any theme with a Vite script in the head was affected as soon as an author inserted such a block. The Vite client of the dev server had the same problem - A block theme's own `404.html` answered with HTTP 200. WordPress core resolves it to `wp-includes/template-canvas.php`, which is never a Blade view, so it always rendered through `FrontendController`'s raw-PHP-template branch — the only branch that never looked at `is_404()`. Measured on a fresh block theme: right content, wrong status diff --git a/resources/views/theme-missing.blade.php b/resources/views/theme-missing.blade.php index f33815f4..d955c5da 100644 --- a/resources/views/theme-missing.blade.php +++ b/resources/views/theme-missing.blade.php @@ -128,6 +128,12 @@
{{ $prefix }}php artisan pollora:make:theme my-shop --repository=pollora/theme-apiary
+
+

Start from the magazine theme

+

A Full Site Editing block theme: its templates are edited in the Site Editor.

+
{{ $prefix }}php artisan pollora:make:theme my-journal --repository=pollora/theme-buzz
+
+

The command downloads the theme, fills in its metadata, installs its npm dependencies and builds its assets, then activates it in WordPress. Run it from the project root, then reload this page. diff --git a/src/Theme/UI/Console/MakeThemeCommand.php b/src/Theme/UI/Console/MakeThemeCommand.php index 777cdb6d..8985c65e 100755 --- a/src/Theme/UI/Console/MakeThemeCommand.php +++ b/src/Theme/UI/Console/MakeThemeCommand.php @@ -489,6 +489,16 @@ protected function promptForMissingArgumentsUsing(): array protected const TEMPLATES = [ 'default' => 'pollora/theme-default', 'ecommerce' => 'pollora/theme-apiary', + 'magazine' => 'pollora/theme-buzz', + ]; + + /** + * What the prompt says of each built-in template, keyed like TEMPLATES. + */ + protected const TEMPLATE_LABELS = [ + 'default' => 'Default — Basic starter theme', + 'ecommerce' => 'E-commerce — WooCommerce theme (Tailwind CSS, Alpine.js)', + 'magazine' => 'Magazine — Full Site Editing block theme, edited in the Site Editor (Tailwind CSS)', ]; /** @@ -503,8 +513,7 @@ protected function promptForRepository(): ?string $choice = select( label: 'Which theme template would you like to use?', options: [ - 'default' => 'Default — Basic starter theme', - 'ecommerce' => 'E-commerce — WooCommerce theme (Tailwind CSS, Alpine.js)', + ...self::TEMPLATE_LABELS, 'repository' => 'Custom — Download from a GitHub repository', ], default: 'default' diff --git a/src/Theme/UI/Http/MissingThemeNotice.php b/src/Theme/UI/Http/MissingThemeNotice.php index ab75014a..5d38ad28 100644 --- a/src/Theme/UI/Http/MissingThemeNotice.php +++ b/src/Theme/UI/Http/MissingThemeNotice.php @@ -27,15 +27,18 @@ public function render(): void $intro = __('No theme is installed, so the front end of this site cannot be rendered. Generate one from the project root:', 'pollora'); $default = __('Default theme', 'pollora'); $ecommerce = __('E-commerce theme (WooCommerce)', 'pollora'); + $magazine = __('Magazine theme (Full Site Editing)', 'pollora'); printf( - '

%s

%s

%s
%s

%s
%s

', + '

%s

%s

%s
%s

%s
%s

%s
%s

', esc_html__('Pollora: no theme installed', 'pollora'), esc_html($intro), esc_html($default), esc_html($prefix.'php artisan pollora:make:theme my-theme --repository=pollora/theme-default'), esc_html($ecommerce), - esc_html($prefix.'php artisan pollora:make:theme my-shop --repository=pollora/theme-apiary') + esc_html($prefix.'php artisan pollora:make:theme my-shop --repository=pollora/theme-apiary'), + esc_html($magazine), + esc_html($prefix.'php artisan pollora:make:theme my-journal --repository=pollora/theme-buzz') ); } } diff --git a/tests/Feature/Theme/MissingThemeGuidanceTest.php b/tests/Feature/Theme/MissingThemeGuidanceTest.php index f5bb5fd1..1e42292a 100644 --- a/tests/Feature/Theme/MissingThemeGuidanceTest.php +++ b/tests/Feature/Theme/MissingThemeGuidanceTest.php @@ -61,7 +61,8 @@ function viewNotFound(string $view = 'home'): InvalidArgumentException expect($response)->toBeInstanceOf(Response::class) ->and($response->getStatusCode())->toBe(503) ->and($response->getContent())->toContain('pollora/theme-default') - ->and($response->getContent())->toContain('pollora/theme-apiary'); + ->and($response->getContent())->toContain('pollora/theme-apiary') + ->and($response->getContent())->toContain('pollora/theme-buzz'); }); it('leaves the exception alone when a theme is installed', function (): void { @@ -140,7 +141,10 @@ function viewNotFound(string $view = 'home'): InvalidArgumentException expect($output)->toContain('notice-warning') ->and($output)->toContain('no theme installed') - ->and($output)->toContain('pollora:make:theme'); + ->and($output)->toContain('pollora:make:theme') + ->and($output)->toContain('pollora/theme-default') + ->and($output)->toContain('pollora/theme-apiary') + ->and($output)->toContain('pollora/theme-buzz'); }); it('stays silent once a theme is installed', function (): void { diff --git a/tests/Unit/Theme/MakeThemeCommandTemplatesTest.php b/tests/Unit/Theme/MakeThemeCommandTemplatesTest.php new file mode 100644 index 00000000..70969537 --- /dev/null +++ b/tests/Unit/Theme/MakeThemeCommandTemplatesTest.php @@ -0,0 +1,21 @@ + (new ReflectionClassConstant(MakeThemeCommand::class, $name))->getValue(); + + it('offers every built-in template in the prompt, and nothing that has no repository', function () use ($constant): void { + expect(array_keys($constant('TEMPLATE_LABELS')))->toBe(array_keys($constant('TEMPLATES'))); + }); + + it('offers Buzz as the magazine template', function () use ($constant): void { + expect($constant('TEMPLATES'))->toMatchArray([ + 'default' => 'pollora/theme-default', + 'ecommerce' => 'pollora/theme-apiary', + 'magazine' => 'pollora/theme-buzz', + ]); + }); +});