diff --git a/manifest/TemplateManifest.php b/manifest/TemplateManifest.php new file mode 100644 index 000000000..d1e29dace --- /dev/null +++ b/manifest/TemplateManifest.php @@ -0,0 +1,154 @@ +base = $base; + $this->tests = $includeTests; + + $this->cacheKey = $this->tests ? 'manifest_tests' : 'manifest'; + $this->forceRegen = $forceRegen; + + $this->cache = SS_Cache::factory('SS_TemplateManifest', 'Core', array( + 'automatic_serialization' => true, + 'lifetime' => null + )); + } + + /** + * Returns a map of all template information. The map is in the following + * format: + * + * + * array( + * 'moduletemplate' => array( + * 'main' => '/path/to/module/templates/Main.ss' + * ), + * 'include' => array( + * 'include' => '/path/to/module/templates/Includes/Include.ss' + * ), + * 'page' => array( + * 'themes' => array( + * 'blackcandy' => array( + * 'main' => '/path/to/theme/Page.ss' + * 'Layout' => '/path/to/theme/Layout/Page.ss' + * ) + * ) + * ) + * ) + * + * + * @return array + */ + public function getTemplates() { + if (!$this->inited) { + $this->init(); + } + + return $this->templates; + } + + /** + * Returns a set of possible candidate templates that match a certain + * template name. + * + * This is the same as extracting an individual array element from + * {@link SS_TemplateManifest::getTemplates()}. + * + * @param string $name + * @return array + */ + public function getTemplate($name) { + if (!$this->inited) { + $this->init(); + } + + $name = strtolower($name); + + if (array_key_exists($name, $this->templates)) { + return $this->templates[$name]; + } else { + return array(); + } + } + + /** + * Regenerates the manifest by scanning the base path. + * + * @param bool $cache + */ + public function regenerate($cache = true) { + $finder = new ManifestFileFinder(); + $finder->setOptions(array( + 'name_regex' => '/\.ss$/', + 'include_themes' => true, + 'ignore_tests' => !$this->tests, + 'file_callback' => array($this, 'handleFile') + )); + $finder->find($this->base); + + if ($cache) { + $this->cache->save($this->templates, $this->cacheKey); + } + + $this->inited = true; + } + + public function handleFile($basename, $pathname, $depth) { + if (strpos($pathname, $this->base . '/' . THEMES_DIR) === 0) { + $start = strlen($this->base . '/' . THEMES_DIR) + 1; + $theme = substr($pathname, $start); + $theme = substr($theme, 0, strpos($theme, '/')); + $theme = strtok($theme, '_'); + } else { + $theme = null; + } + + $type = basename(dirname($pathname)); + $name = strtolower(substr($basename, 0, -3)); + + if ($type == self::TEMPLATES_DIR) { + $type = 'main'; + } + + if ($theme) { + $this->templates[$name]['themes'][$theme][$type] = $pathname; + } else { + $this->templates[$name][$type] = $pathname; + } + } + + protected function init() { + if (!$this->forceRegen && $data = $this->cache->load($this->cacheKey)) { + $this->templates = $data; + $this->inited = true; + } else { + $this->regenerate(); + } + } + +} \ No newline at end of file diff --git a/tests/manifest/TemplateManifestTest.php b/tests/manifest/TemplateManifestTest.php new file mode 100644 index 000000000..444a233b2 --- /dev/null +++ b/tests/manifest/TemplateManifestTest.php @@ -0,0 +1,98 @@ +base = dirname(__FILE__) . '/fixtures/templatemanifest'; + $this->manifest = new SS_TemplateManifest($this->base); + $this->manifestTests = new SS_TemplateManifest($this->base, true); + + $this->manifest->regenerate(false); + $this->manifestTests->regenerate(false); + } + + public function testGetTemplates() { + $expect = array( + 'root' => array( + 'module' => "{$this->base}/module/Root.ss" + ), + 'page' => array( + 'main' => "{$this->base}/module/templates/Page.ss", + 'Layout' => "{$this->base}/module/templates/Layout/Page.ss", + 'themes' => array('theme' => array( + 'main' => "{$this->base}/themes/theme/templates/Page.ss", + 'Layout' => "{$this->base}/themes/theme/templates/Layout/Page.ss" + )) + ), + 'custompage' => array( + 'Layout' => "{$this->base}/module/templates/Layout/CustomPage.ss" + ), + 'subfolder' => array( + 'main' => "{$this->base}/module/subfolder/templates/Subfolder.ss" + ), + 'include' => array('themes' => array( + 'theme' => array( + 'Includes' => "{$this->base}/themes/theme/templates/Includes/Include.ss" + ) + )) + ); + + $expectTests = $expect; + $expectTests['test'] = array( + 'main' => "{$this->base}/module/tests/templates/Test.ss" + ); + + $manifest = $this->manifest->getTemplates(); + $manifestTests = $this->manifestTests->getTemplates(); + + ksort($expect); + ksort($expectTests); + ksort($manifest); + ksort($manifestTests); + + $this->assertEquals( + $expect, $manifest, + 'All templates are correctly loaded in the manifest.' + ); + + $this->assertEquals( + $expectTests, $manifestTests, + 'The test manifest is the same, but includes test templates.' + ); + } + + public function testGetTemplate() { + $expectPage = array( + 'main' => "{$this->base}/module/templates/Page.ss", + 'Layout' => "{$this->base}/module/templates/Layout/Page.ss", + 'themes' => array('theme' => array( + 'main' => "{$this->base}/themes/theme/templates/Page.ss", + 'Layout' => "{$this->base}/themes/theme/templates/Layout/Page.ss" + )) + ); + + $expectTests = array( + 'main' => "{$this->base}/module/tests/templates/Test.ss" + ); + + $this->assertEquals($expectPage, $this->manifest->getTemplate('Page')); + $this->assertEquals($expectPage, $this->manifest->getTemplate('PAGE')); + $this->assertEquals($expectPage, $this->manifestTests->getTemplate('Page')); + $this->assertEquals($expectPage, $this->manifestTests->getTemplate('PAGE')); + + $this->assertEquals(array(), $this->manifest->getTemplate('Test')); + $this->assertEquals($expectTests, $this->manifestTests->getTemplate('Test')); + } + +} \ No newline at end of file diff --git a/tests/manifest/fixtures/templatemanifest/module/Root.ss b/tests/manifest/fixtures/templatemanifest/module/Root.ss new file mode 100644 index 000000000..e69de29bb diff --git a/tests/manifest/fixtures/templatemanifest/module/_config.php b/tests/manifest/fixtures/templatemanifest/module/_config.php new file mode 100644 index 000000000..e69de29bb diff --git a/tests/manifest/fixtures/templatemanifest/module/subfolder/templates/Subfolder.ss b/tests/manifest/fixtures/templatemanifest/module/subfolder/templates/Subfolder.ss new file mode 100644 index 000000000..e69de29bb diff --git a/tests/manifest/fixtures/templatemanifest/module/templates/Layout/CustomPage.ss b/tests/manifest/fixtures/templatemanifest/module/templates/Layout/CustomPage.ss new file mode 100644 index 000000000..e69de29bb diff --git a/tests/manifest/fixtures/templatemanifest/module/templates/Layout/Page.ss b/tests/manifest/fixtures/templatemanifest/module/templates/Layout/Page.ss new file mode 100644 index 000000000..e69de29bb diff --git a/tests/manifest/fixtures/templatemanifest/module/templates/Page.ss b/tests/manifest/fixtures/templatemanifest/module/templates/Page.ss new file mode 100644 index 000000000..e69de29bb diff --git a/tests/manifest/fixtures/templatemanifest/module/tests/templates/Test.ss b/tests/manifest/fixtures/templatemanifest/module/tests/templates/Test.ss new file mode 100644 index 000000000..e69de29bb diff --git a/tests/manifest/fixtures/templatemanifest/themes/theme/templates/Includes/Include.ss b/tests/manifest/fixtures/templatemanifest/themes/theme/templates/Includes/Include.ss new file mode 100644 index 000000000..e69de29bb diff --git a/tests/manifest/fixtures/templatemanifest/themes/theme/templates/Layout/Page.ss b/tests/manifest/fixtures/templatemanifest/themes/theme/templates/Layout/Page.ss new file mode 100644 index 000000000..e69de29bb diff --git a/tests/manifest/fixtures/templatemanifest/themes/theme/templates/Page.ss b/tests/manifest/fixtures/templatemanifest/themes/theme/templates/Page.ss new file mode 100644 index 000000000..e69de29bb