diff --git a/tests/core/manifest/ThemeResourceLoaderTest.php b/tests/core/manifest/ThemeResourceLoaderTest.php index 1d9cddc2e..f8df70355 100644 --- a/tests/core/manifest/ThemeResourceLoaderTest.php +++ b/tests/core/manifest/ThemeResourceLoaderTest.php @@ -75,6 +75,54 @@ class ThemeResourceLoaderTest extends SapphireTest { ); } + public function testFindTemplateByType() { + // Test that "type" is respected properly + $this->assertEquals( + "{$this->base}/module/templates/MyNamespace/Layout/MyClass.ss", + $this->loader->findTemplate( + [ + [ + 'type' => 'Layout', + 'MyNamespace/NonExistantTemplate' + ], + [ + 'type' => 'Layout', + 'MyNamespace/MyClass' + ], + 'MyNamespace/MyClass' + ], + [ + 'silverstripe/module:subtheme', + 'theme', + '$default', + ] + ) + ); + + // Non-typed template can be found even if looking for typed theme at a lower priority + $this->assertEquals( + "{$this->base}/module/templates/MyNamespace/MyClass.ss", + $this->loader->findTemplate( + [ + [ + 'type' => 'Layout', + 'MyNamespace/NonExistantTemplate' + ], + 'MyNamespace/MyClass', + [ + 'type' => 'Layout', + 'MyNamespace/MyClass' + ] + ], + [ + 'silverstripe/module', + 'theme', + '$default', + ] + ) + ); + } + /** * Test that 'main' and 'Layout' templates are loaded from set theme */ diff --git a/view/SSViewer.php b/view/SSViewer.php index eec59d597..818baa4ee 100644 --- a/view/SSViewer.php +++ b/view/SSViewer.php @@ -880,8 +880,8 @@ class SSViewer implements Flushable { $template = $class . $suffix; if(SSViewer::hasTemplate($template)) { $templates[] = $template; - } elseif(SSViewer::hasTemplate('Includes/'.$template)) { - $templates[] = 'Includes/'.$template; + } elseif(SSViewer::hasTemplate($template = ['type' => 'Includes', $template])) { + $templates[] = $template; } // If the class is "Page_Controller", look for Page.ss @@ -1038,7 +1038,7 @@ class SSViewer implements Flushable { * * @return string Full system path to a template file */ - public static function getTemplateFileByType($identifier, $type) { + public static function getTemplateFileByType($identifier, $type = null) { return ThemeResourceLoader::instance()->findTemplate(['type' => $type, $identifier], self::get_themes()); } diff --git a/view/ThemeResourceLoader.php b/view/ThemeResourceLoader.php index 28afd3f96..2dfbe7500 100644 --- a/view/ThemeResourceLoader.php +++ b/view/ThemeResourceLoader.php @@ -132,7 +132,7 @@ class ThemeResourceLoader { * @param string|array $template Template name, or template spec in array format with the keys * 'type' (type string) and 'templates' (template hierarchy in order of precedence). * If 'templates' is ommitted then any other item in the array will be treated as the template - * list. + * list, or list of templates each in the array spec given. * Templates with an .ss extension will be treated as file paths, and will bypass * theme-coupled resolution. * @param array $themes List of themes to use to resolve themes. In most cases @@ -158,11 +158,21 @@ class ThemeResourceLoader { // If we have an .ss extension, this is a path, not a template name. We should // pass in templates without extensions in order for template manifest to find // files dynamically. - if(count($templateList) == 1 && substr($templateList[0], -3) == '.ss') { + if(count($templateList) == 1 && is_string($templateList[0]) && substr($templateList[0], -3) == '.ss') { return $templateList[0]; } foreach($templateList as $i => $template) { + // Check if passed list of templates in array format + if (is_array($template)) { + $path = $this->findTemplate($template, $themes); + if ($path) { + return $path; + } + continue; + } + + // Check string template identifier $template = str_replace('\\', '/', $template); $parts = explode('/', $template);