From b2f56c1f9196bef44e00794107a1f889e0b5cd8d Mon Sep 17 00:00:00 2001 From: Oliver Mesieh Date: Fri, 28 Mar 2025 10:58:34 +0100 Subject: [PATCH 1/3] Add configurable `@blueprint` template base path Adds a new configuration option to customize where Statamic looks for templates when using `@blueprint` in collections. --- config/system.php | 14 ++++++++++++++ src/Entries/Entry.php | 5 ++++- tests/Data/Entries/EntryTest.php | 20 ++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/config/system.php b/config/system.php index fc04ee4b024..8ac907b4055 100644 --- a/config/system.php +++ b/config/system.php @@ -218,4 +218,18 @@ 'layout' => env('STATAMIC_LAYOUT', 'layout'), + /* + |-------------------------------------------------------------------------- + | Blueprint Template Base Path + |-------------------------------------------------------------------------- + | + | When using @blueprint in a collection's template setting, Statamic looks for + | templates in /resources/views/{collection}/{blueprint}.antlers.html. Set this + | value to use a different base path + | (e.g. 'templates' for /resources/views/templates/). + | + */ + + 'blueprint_template_base_path' => env('STATAMIC_BLUEPRINT_TEMPLATE_PATH', null), + ]; diff --git a/src/Entries/Entry.php b/src/Entries/Entry.php index 27493c2bd4f..55fafc22663 100644 --- a/src/Entries/Entry.php +++ b/src/Entries/Entry.php @@ -528,7 +528,10 @@ public function template($template = null) protected function inferTemplateFromBlueprint() { - $template = $this->collection()->handle().'.'.$this->blueprint(); + $basePath = config('statamic.system.blueprint_template_base_path'); + $prefix = $basePath ?: $this->collection()->handle(); + + $template = $prefix.'.'.$this->blueprint(); $slugifiedTemplate = str_replace('_', '-', $template); diff --git a/tests/Data/Entries/EntryTest.php b/tests/Data/Entries/EntryTest.php index ca48dd407db..de04a57ac28 100644 --- a/tests/Data/Entries/EntryTest.php +++ b/tests/Data/Entries/EntryTest.php @@ -1915,6 +1915,26 @@ public function it_gets_and_sets_an_inferred_template_from_blueprint() $this->assertEquals('articles.custom', $entry->template()); } + #[Test] + public function it_respects_custom_blueprint_template_base_path() + { + // Set custom base path for test + config(['statamic.system.blueprint_template_base_path' => 'custom.path']); + + $collection = tap(Collection::make('articles')->template('@blueprint'))->save(); + $blueprint = tap(Blueprint::make('standard_article')->setNamespace('collections.articles'))->save(); + $entry = Entry::make('test')->collection($collection)->blueprint($blueprint->handle()); + + // entry uses the custom path instead of collection handle + $this->assertEquals('custom.path.standard_article', $entry->template()); + + // entry uses slugified custom path when that template exists + View::shouldReceive('exists')->with('custom.path.standard-article')->andReturn(true); + $this->assertEquals('custom.path.standard-article', $entry->template()); + + config(['statamic.system.blueprint_template_base_path' => null]); + } + #[Test] public function it_gets_and_sets_the_layout() { From 5ed6d7410bb3a542a4d3a545f2042a3559c0f3cb Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 11 May 2026 17:03:00 -0400 Subject: [PATCH 2/3] Switch @blueprint template path to a per-collection map Replaces the global blueprint_template_base_path config with a blueprint_templates map keyed by collection handle, so individual collections can opt in without changing behavior for the rest. Co-Authored-By: Claude Opus 4.7 (1M context) --- config/system.php | 15 +++++++++------ src/Entries/Entry.php | 4 ++-- tests/Data/Entries/EntryTest.php | 29 +++++++++++++++++++---------- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/config/system.php b/config/system.php index c4151f4478a..9deeef431e3 100644 --- a/config/system.php +++ b/config/system.php @@ -271,16 +271,19 @@ /* |-------------------------------------------------------------------------- - | Blueprint Template Base Path + | Blueprint Templates |-------------------------------------------------------------------------- | - | When using @blueprint in a collection's template setting, Statamic looks for - | templates in /resources/views/{collection}/{blueprint}.antlers.html. Set this - | value to use a different base path - | (e.g. 'templates' for /resources/views/templates/). + | When an entry's template is set to `@blueprint`, Statamic will look for + | a view named `{collection}.{blueprint}`. You may override this logic + | on a per-collection basis here. + | + | https://statamic.dev/content-modeling/collections#templates | */ - 'blueprint_template_base_path' => env('STATAMIC_BLUEPRINT_TEMPLATE_PATH', null), + 'blueprint_templates' => [ + // + ], ]; diff --git a/src/Entries/Entry.php b/src/Entries/Entry.php index 1d12ccf6a47..c8315f48ef4 100644 --- a/src/Entries/Entry.php +++ b/src/Entries/Entry.php @@ -583,8 +583,8 @@ public function template($template = null) protected function inferTemplateFromBlueprint() { - $basePath = config('statamic.system.blueprint_template_base_path'); - $prefix = $basePath ?: $this->collection()->handle(); + $handle = $this->collection()->handle(); + $prefix = config('statamic.system.blueprint_templates.'.$handle, $handle); $template = $prefix.'.'.$this->blueprint(); diff --git a/tests/Data/Entries/EntryTest.php b/tests/Data/Entries/EntryTest.php index 2b0d098d573..e93fce2ddbc 100644 --- a/tests/Data/Entries/EntryTest.php +++ b/tests/Data/Entries/EntryTest.php @@ -2049,23 +2049,32 @@ public function it_gets_and_sets_an_inferred_template_from_blueprint() } #[Test] - public function it_respects_custom_blueprint_template_base_path() + public function it_respects_custom_blueprint_template_path_per_collection() { - // Set custom base path for test - config(['statamic.system.blueprint_template_base_path' => 'custom.path']); + config(['statamic.system.blueprint_templates' => [ + 'articles' => 'custom.path', + ]]); - $collection = tap(Collection::make('articles')->template('@blueprint'))->save(); + $articles = tap(Collection::make('articles')->template('@blueprint'))->save(); + $pages = tap(Collection::make('pages')->template('@blueprint'))->save(); $blueprint = tap(Blueprint::make('standard_article')->setNamespace('collections.articles'))->save(); - $entry = Entry::make('test')->collection($collection)->blueprint($blueprint->handle()); - // entry uses the custom path instead of collection handle - $this->assertEquals('custom.path.standard_article', $entry->template()); + $articleEntry = Entry::make('test')->collection($articles)->blueprint($blueprint->handle()); + $pageEntry = Entry::make('test')->collection($pages)->blueprint($blueprint->handle()); + + // mapped collection uses the mapped prefix instead of the collection handle + $this->assertEquals('custom.path.standard_article', $articleEntry->template()); + + // unmapped collection still uses its handle as the prefix + $this->assertEquals('pages.standard_article', $pageEntry->template()); - // entry uses slugified custom path when that template exists + // mapped collection uses slugified prefix when that template exists View::shouldReceive('exists')->with('custom.path.standard-article')->andReturn(true); - $this->assertEquals('custom.path.standard-article', $entry->template()); + $this->assertEquals('custom.path.standard-article', $articleEntry->template()); - config(['statamic.system.blueprint_template_base_path' => null]); + // entry level template still overrides @blueprint + $articleEntry->template('articles.custom'); + $this->assertEquals('articles.custom', $articleEntry->template()); } #[Test] From 66447d2e482805d8b5774aeb90d1de402f9a7b14 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Tue, 12 May 2026 14:35:50 -0400 Subject: [PATCH 3/3] Remove trailing whitespace in config comment Co-Authored-By: Claude Opus 4.7 (1M context) --- config/system.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/system.php b/config/system.php index 9deeef431e3..a8777f14064 100644 --- a/config/system.php +++ b/config/system.php @@ -274,7 +274,7 @@ | Blueprint Templates |-------------------------------------------------------------------------- | - | When an entry's template is set to `@blueprint`, Statamic will look for + | When an entry's template is set to `@blueprint`, Statamic will look for | a view named `{collection}.{blueprint}`. You may override this logic | on a per-collection basis here. |