Permalink
Browse files

API Explicitly load project template files after modules

Resolves an issue where if not using the themes directory (i.e just a single app folder) you cannot override module templates.
Changes the SS_TemplateManifest constructor with a new $project argument.
  • Loading branch information...
1 parent a108f67 commit 683db8dc1d9f2133af447d763df47713c2a0f0e2 @wilr wilr committed with chillu Nov 2, 2012
View
2 core/Core.php
@@ -290,7 +290,7 @@
Config::inst()->pushConfigManifest($configManifest);
SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest(
- BASE_PATH, false, isset($_GET['flush'])
+ BASE_PATH, project(), false, isset($_GET['flush'])
));
// If in live mode, ensure deprecation, strict and notices are not reported
View
26 core/manifest/TemplateLoader.php
@@ -49,18 +49,21 @@ public function popManifest() {
/**
* Attempts to find possible candidate templates from a set of template
- * names and a theme.
+ * names from modules, current theme directory and finally the application
+ * folder.
*
* 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();
+ $project = project();
foreach ((array) $templates as $template) {
$found = false;
@@ -71,21 +74,14 @@ public function findTemplates($templates, $theme = null) {
$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);
+ if ($found = $this->getManifest()->getCandidateTemplate($template, $theme)) {
+ if ($type && isset($found[$type])) {
+ $found = array(
+ 'main' => $found[$type]
+ );
}
+
+ $result = array_merge($found, $result);
}
}
View
43 core/manifest/TemplateManifest.php
@@ -14,6 +14,7 @@ class SS_TemplateManifest {
protected $tests;
protected $cache;
protected $cacheKey;
+ protected $project;
protected $inited;
protected $forceRegen;
protected $templates = array();
@@ -23,13 +24,17 @@ class SS_TemplateManifest {
* or loaded from cache until needed.
*
* @param string $base The base path.
+ * @param string $project Path to application code
+ *
* @param bool $includeTests Include tests in the manifest.
* @param bool $forceRegen Force the manifest to be regenerated.
*/
- public function __construct($base, $includeTests = false, $forceRegen = false) {
+ public function __construct($base, $project, $includeTests = false, $forceRegen = false) {
$this->base = $base;
$this->tests = $includeTests;
+ $this->project = $project;
+
$this->cacheKey = $this->tests ? 'manifest_tests' : 'manifest';
$this->forceRegen = $forceRegen;
@@ -97,6 +102,30 @@ public function getTemplate($name) {
}
/**
+ * Returns the correct candidate template. In order of importance, application
+ * project code, current theme and finally modules.
+ *
+ * @param string $name
+ * @param string $theme - theme name
+ *
+ * @return array
+ */
+ public function getCandidateTemplate($name, $theme = null) {
+ $candidates = $this->getTemplate($name);
+
+ if ($this->project && isset($candidates[$this->project])) {
+ $found = $candidates[$this->project];
+ } else if ($theme && isset($candidates['themes'][$theme])) {
+ $found = $candidates['themes'][$theme];
+ } else {
+ unset($candidates['themes']);
+ $found = $candidates;
+ }
+
+ return $found;
+ }
+
+ /**
* Regenerates the manifest by scanning the base path.
*
* @param bool $cache
@@ -109,6 +138,7 @@ public function regenerate($cache = true) {
'ignore_tests' => !$this->tests,
'file_callback' => array($this, 'handleFile')
));
+
$finder->find($this->base);
if ($cache) {
@@ -119,13 +149,16 @@ public function regenerate($cache = true) {
}
public function handleFile($basename, $pathname, $depth) {
+ $projectFile = false;
+ $theme = null;
+
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;
+ } else if($this->project && (strpos($pathname, $this->base . '/' . $this->project .'/') === 0)) {
+ $projectFile = true;
}
$type = basename(dirname($pathname));
@@ -137,9 +170,12 @@ public function handleFile($basename, $pathname, $depth) {
if ($theme) {
$this->templates[$name]['themes'][$theme][$type] = $pathname;
+ } else if($projectFile) {
+ $this->templates[$name][$this->project][$type] = $pathname;
} else {
$this->templates[$name][$type] = $pathname;
}
+
}
protected function init() {
@@ -150,5 +186,4 @@ protected function init() {
$this->regenerate();
}
}
-
}
View
2 dev/TestRunner.php
@@ -94,7 +94,7 @@ public static function use_test_manifest() {
SapphireTest::set_test_class_manifest($classManifest);
SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest(
- BASE_PATH, true, isset($_GET['flush'])
+ BASE_PATH, project(), true, isset($_GET['flush'])
));
}
View
18 tests/core/manifest/TemplateLoaderTest.php
@@ -9,7 +9,7 @@ class TemplateLoaderTest extends SapphireTest {
public function testFindTemplates() {
$base = dirname(__FILE__) . '/fixtures/templatemanifest';
- $manifest = new SS_TemplateManifest($base, false, true);
+ $manifest = new SS_TemplateManifest($base, 'myproject', false, true);
$loader = new SS_TemplateLoader();
$manifest->regenerate(false);
@@ -40,7 +40,23 @@ public function testFindTemplates() {
'main' => "$base/module/templates/Page.ss",
'Layout' => "$base/module/templates/Layout/CustomPage.ss"
);
+
$this->assertEquals($expectCustomPage, $loader->findTemplates(array('CustomPage', 'Page')));
}
+ public function testFindTemplatesApplicationOverridesModule() {
+ $base = dirname(__FILE__) . '/fixtures/templatemanifest';
+ $manifest = new SS_TemplateManifest($base, 'myproject', false, true);
+ $loader = new SS_TemplateLoader();
+
+ $manifest->regenerate(false);
+ $loader->pushManifest($manifest);
+
+ $expectPage = array(
+ 'main' => "$base/myproject/templates/CustomTemplate.ss"
+ );
+
+ $this->assertEquals($expectPage, $loader->findTemplates('CustomTemplate'));
+ }
+
}
View
16 tests/core/manifest/TemplateManifestTest.php
@@ -15,8 +15,8 @@ public function setUp() {
parent::setUp();
$this->base = dirname(__FILE__) . '/fixtures/templatemanifest';
- $this->manifest = new SS_TemplateManifest($this->base);
- $this->manifestTests = new SS_TemplateManifest($this->base, true);
+ $this->manifest = new SS_TemplateManifest($this->base, 'myproject');
+ $this->manifestTests = new SS_TemplateManifest($this->base, 'myproject', true);
$this->manifest->regenerate(false);
$this->manifestTests->regenerate(false);
@@ -38,6 +38,12 @@ public function testGetTemplates() {
'custompage' => array(
'Layout' => "{$this->base}/module/templates/Layout/CustomPage.ss"
),
+ 'customtemplate' => array(
+ 'main' => "{$this->base}/module/templates/CustomTemplate.ss",
+ 'myproject' => array(
+ 'main' => "{$this->base}/myproject/templates/CustomTemplate.ss"
+ )
+ ),
'subfolder' => array(
'main' => "{$this->base}/module/subfolder/templates/Subfolder.ss"
),
@@ -93,6 +99,12 @@ public function testGetTemplate() {
$this->assertEquals(array(), $this->manifest->getTemplate('Test'));
$this->assertEquals($expectTests, $this->manifestTests->getTemplate('Test'));
+
+ $this->assertEquals(array(
+ 'main' => "{$this->base}/module/templates/CustomTemplate.ss",
+ 'myproject' => array(
+ 'main' => "{$this->base}/myproject/templates/CustomTemplate.ss"
+ )), $this->manifestTests->getTemplate('CustomTemplate'));
}
}
View
1 tests/core/manifest/fixtures/templatemanifest/module/templates/CustomTemplate.ss
@@ -0,0 +1 @@
+Custom Template
View
1 tests/core/manifest/fixtures/templatemanifest/myproject/_config.php
@@ -0,0 +1 @@
+<?php
View
1 tests/core/manifest/fixtures/templatemanifest/myproject/templates/CustomTemplate.ss
@@ -0,0 +1 @@
+App version
View
4 tests/i18n/i18nSSLegacyAdapterTest.php
@@ -15,13 +15,13 @@ public function setUp() {
Director::setBaseFolder($this->alternateBasePath);
// Push a template loader running from the fake webroot onto the stack.
- $templateManifest = new SS_TemplateManifest($this->alternateBasePath, false, true);
+ $templateManifest = new SS_TemplateManifest($this->alternateBasePath, null, false, true);
$templateManifest->regenerate(false);
SS_TemplateLoader::instance()->pushManifest($templateManifest);
$this->_oldTheme = SSViewer::current_theme();
SSViewer::set_theme('testtheme1');
- $classManifest = new SS_ClassManifest($this->alternateBasePath, true, true, false);
+ $classManifest = new SS_ClassManifest($this->alternateBasePath, null, true, true, false);
SS_ClassLoader::instance()->pushManifest($classManifest);
$this->originalLocale = i18n::get_locale();
View
2 tests/i18n/i18nTest.php
@@ -34,7 +34,7 @@ public function setUp() {
Director::setBaseFolder($this->alternateBasePath);
// Push a template loader running from the fake webroot onto the stack.
- $templateManifest = new SS_TemplateManifest($this->alternateBasePath, false, true);
+ $templateManifest = new SS_TemplateManifest($this->alternateBasePath, null, false, true);
$templateManifest->regenerate(false);
SS_TemplateLoader::instance()->pushManifest($templateManifest);
$this->_oldTheme = SSViewer::current_theme();
View
2 tests/i18n/i18nTextCollectorTest.php
@@ -33,7 +33,7 @@ public function setUp() {
$this->alternateBasePath, false, true, false
);
- $manifest = new SS_TemplateManifest($this->alternateBasePath, false, true);
+ $manifest = new SS_TemplateManifest($this->alternateBasePath, null, false, true);
$manifest->regenerate(false);
SS_TemplateLoader::instance()->pushManifest($manifest);
}

0 comments on commit 683db8d

Please sign in to comment.