From c34105438c31e21a3e3247848db8601e7469f273 Mon Sep 17 00:00:00 2001 From: ajshort Date: Thu, 24 Mar 2011 21:30:57 +1100 Subject: [PATCH] FEATURE: Replaced the template manifest with SS_TemplateLoader, which finds templates from a stack of SS_TemplateManifest objects. --- core/Core.php | 6 ++ core/SSViewer.php | 97 +++------------------------ dev/TestRunner.php | 8 ++- manifest/TemplateLoader.php | 95 ++++++++++++++++++++++++++ tests/manifest/TemplateLoaderTest.php | 46 +++++++++++++ 5 files changed, 163 insertions(+), 89 deletions(-) create mode 100644 manifest/TemplateLoader.php create mode 100644 tests/manifest/TemplateLoaderTest.php diff --git a/core/Core.php b/core/Core.php index 66060e437..a9a523547 100644 --- a/core/Core.php +++ b/core/Core.php @@ -210,6 +210,8 @@ require_once 'filesystem/FileFinder.php'; require_once 'manifest/ClassLoader.php'; require_once 'manifest/ClassManifest.php'; require_once 'manifest/ManifestFileFinder.php'; +require_once 'manifest/TemplateLoader.php'; +require_once 'manifest/TemplateManifest.php'; require_once 'manifest/TokenisedRegularExpression.php'; /////////////////////////////////////////////////////////////////////////////// @@ -227,6 +229,10 @@ $loader = SS_ClassLoader::instance(); $loader->registerAutoloader(); $loader->pushManifest($manifest); +SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest( + BASE_PATH, false, isset($_GET['flush']) +)); + // If this is a dev site, enable php error reporting // This is necessary to force developers to acknowledge and fix // notice level errors (you can override this directive in your _config.php) diff --git a/core/SSViewer.php b/core/SSViewer.php index 3b89c664e..66ed596fc 100644 --- a/core/SSViewer.php +++ b/core/SSViewer.php @@ -182,46 +182,10 @@ class SSViewer_DataPresenter extends SSViewer_Scope { * * Compiled templates are cached via {@link SS_Cache}, usually on the filesystem. * If you put ?flush=all on your URL, it will force the template to be recompiled. - * - * Manifest File and Structure - * - * Works with the global $_TEMPLATE_MANIFEST which is compiled by {@link ManifestBuilder->getTemplateManifest()}. - * This associative array lists all template filepaths by "identifier", meaning the name - * of the template without its path or extension. - * - * Example: - * - * array( - * 'LeftAndMain' => - * array ( - * 'main' => '/my/system/path/cms/templates/LeftAndMain.ss', - * ), - * 'CMSMain_left' => - * array ( - * 'Includes' => '/my/system/path/cms/templates/Includes/CMSMain_left.ss', - * ), - * 'Page' => - * array ( - * 'themes' => - * array ( - * 'blackcandy' => - * array ( - * 'Layout' => '/my/system/path/themes/blackcandy/templates/Layout/Page.ss', - * 'main' => '/my/system/path/themes/blackcandy/templates/Page.ss', - * ), - * 'blue' => - * array ( - * 'Layout' => '/my/system/path/themes/mysite/templates/Layout/Page.ss', - * 'main' => '/my/system/path/themes/mysite/templates/Page.ss', - * ), - * ), - * ), - * // ... - * ) - * * * @see http://doc.silverstripe.org/themes * @see http://doc.silverstripe.org/themes:developing + * * @package sapphire * @subpackage view @@ -346,8 +310,6 @@ class SSViewer { * */ public function __construct($templateList) { - global $_TEMPLATE_MANIFEST; - // flush template manifest cache if requested if (isset($_GET['flush']) && $_GET['flush'] == 'all') { if(Director::isDev() || Director::is_cli() || Permission::check('ADMIN')) { @@ -360,64 +322,25 @@ class SSViewer { if(substr((string) $templateList,-3) == '.ss') { $this->chosenTemplates['main'] = $templateList; } else { - if(!is_array($templateList)) $templateList = array($templateList); - - if(isset($_GET['debug_request'])) Debug::message("Selecting templates from the following list: " . implode(", ", $templateList)); - - foreach($templateList as $template) { - // if passed as a partial directory (e.g. "Layout/Page"), split into folder and template components - if(strpos($template,'/') !== false) list($templateFolder, $template) = explode('/', $template, 2); - else $templateFolder = null; - - // Use the theme template if available - if(self::current_theme() && isset($_TEMPLATE_MANIFEST[$template]['themes'][self::current_theme()])) { - $this->chosenTemplates = array_merge( - $_TEMPLATE_MANIFEST[$template]['themes'][self::current_theme()], - $this->chosenTemplates - ); - - if(isset($_GET['debug_request'])) Debug::message("Found template '$template' from main theme '" . self::current_theme() . "': " . var_export($_TEMPLATE_MANIFEST[$template]['themes'][self::current_theme()], true)); - } - - // Fall back to unthemed base templates - if(isset($_TEMPLATE_MANIFEST[$template]) && (array_keys($_TEMPLATE_MANIFEST[$template]) != array('themes'))) { - $this->chosenTemplates = array_merge( - $_TEMPLATE_MANIFEST[$template], - $this->chosenTemplates - ); - - if(isset($_GET['debug_request'])) Debug::message("Found template '$template' from main template archive, containing the following items: " . var_export($_TEMPLATE_MANIFEST[$template], true)); - - unset($this->chosenTemplates['themes']); - } - - if($templateFolder) { - $this->chosenTemplates['main'] = $this->chosenTemplates[$templateFolder]; - unset($this->chosenTemplates[$templateFolder]); - } - } - - if(isset($_GET['debug_request'])) Debug::message("Final template selections made: " . var_export($this->chosenTemplates, true)); - + $this->chosenTemplates = SS_TemplateLoader::instance()->findTemplates( + $templateList, self::current_theme() + ); } if(!$this->chosenTemplates) user_error("None of these templates can be found in theme '" . self::current_theme() . "': ". implode(".ss, ", $templateList) . ".ss", E_USER_WARNING); - } /** * Returns true if at least one of the listed templates exists */ - static function hasTemplate($templateList) { - if(!is_array($templateList)) $templateList = array($templateList); - - global $_TEMPLATE_MANIFEST; - foreach($templateList as $template) { - if(strpos($template,'/') !== false) list($templateFolder, $template) = explode('/', $template, 2); - if(isset($_TEMPLATE_MANIFEST[$template])) return true; + public static function hasTemplate($templates) { + $manifest = SS_TemplateLoader::instance()->getManifest(); + + foreach ((array) $templates as $template) { + if ($manifest->getTemplate($template)) return true; } - + return false; } diff --git a/dev/TestRunner.php b/dev/TestRunner.php index b6224d442..167f02e56 100644 --- a/dev/TestRunner.php +++ b/dev/TestRunner.php @@ -81,13 +81,17 @@ class TestRunner extends Controller { } /** - * Pushes a class manifest instance that uses tests onto the top of the - * autoloader stack. + * Pushes a class and template manifest instance that include tests onto the + * top of the loader stacks. */ public static function use_test_manifest() { SS_ClassLoader::instance()->pushManifest(new SS_ClassManifest( BASE_PATH, true, isset($_GET['flush']) )); + + SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest( + BASE_PATH, true, isset($_GET['flush']) + )); } function init() { diff --git a/manifest/TemplateLoader.php b/manifest/TemplateLoader.php new file mode 100644 index 000000000..10226f733 --- /dev/null +++ b/manifest/TemplateLoader.php @@ -0,0 +1,95 @@ +manifests[count($this->manifests) - 1]; + } + + /** + * @param SS_TemplateManifest $manifest + */ + public function pushManifest(SS_TemplateManifest $manifest) { + $this->manifests[] = $manifest; + } + + /** + * @return SS_TemplateManifest + */ + public function popManifest() { + return array_pop($this->manifests); + } + + /** + * Attempts to find possible candidate templates from a set of template + * names and a theme. + * + * The template names can be passed in as plain strings, or be in the + * format "type/name", where type is the type of template to search for + * (e.g. Includes, Layout). + * + * @param string|array $templates + * @param string $theme + * @return array + */ + public function findTemplates($templates, $theme = null) { + $result = array(); + + foreach ((array) $templates as $template) { + $found = false; + + if (strpos($template, '/')) { + list($type, $template) = explode('/', $template, 2); + } else { + $type = null; + } + + if ($candidates = $this->getManifest()->getTemplate($template)) { + if ($theme && isset($candidates['themes'][$theme])) { + $found = $candidates['themes'][$theme]; + } else { + unset($candidates['themes']); + $found = $candidates; + } + + if ($found) { + if ($type && isset($found[$type])) { + $found = array('main' => $found[$type]); + } + + $result = array_merge($found, $result); + } + } + } + + return $result; + } + +} \ No newline at end of file diff --git a/tests/manifest/TemplateLoaderTest.php b/tests/manifest/TemplateLoaderTest.php new file mode 100644 index 000000000..9f180803a --- /dev/null +++ b/tests/manifest/TemplateLoaderTest.php @@ -0,0 +1,46 @@ +regenerate(false); + $loader->pushManifest($manifest); + + $expectPage = array( + 'main' => "$base/module/templates/Page.ss", + 'Layout' => "$base/module/templates/Layout/Page.ss" + ); + $expectPageThemed = array( + 'main' => "$base/themes/theme/templates/Page.ss", + 'Layout' => "$base/themes/theme/templates/Layout/Page.ss" + ); + + $this->assertEquals($expectPage, $loader->findTemplates('Page')); + $this->assertEquals($expectPage, $loader->findTemplates(array('Foo', 'Page'))); + $this->assertEquals($expectPage, $loader->findTemplates('PAGE')); + $this->assertEquals($expectPageThemed, $loader->findTemplates('Page', 'theme')); + + $expectPageLayout = array('main' => "$base/module/templates/Layout/Page.ss"); + $expectPageLayoutThemed = array('main' => "$base/themes/theme/templates/Layout/Page.ss"); + + $this->assertEquals($expectPageLayout, $loader->findTemplates('Layout/Page')); + $this->assertEquals($expectPageLayout, $loader->findTemplates('Layout/PAGE')); + $this->assertEquals($expectPageLayoutThemed, $loader->findTemplates('Layout/Page', 'theme')); + + $expectCustomPage = array( + 'main' => "$base/module/templates/Page.ss", + 'Layout' => "$base/module/templates/Layout/CustomPage.ss" + ); + $this->assertEquals($expectCustomPage, $loader->findTemplates(array('CustomPage', 'Page'))); + } + +} \ No newline at end of file