ENHANCEMENT: Parse template includes at runtime, so that recursive templates and automatic recompilation of included templates work

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@100972 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Sam Minnee 2010-03-12 03:08:59 +00:00
parent c604341a1d
commit fa016ed6b9
3 changed files with 52 additions and 15 deletions

View File

@ -388,6 +388,15 @@ class SSViewer {
return $output;
}
/**
* Execute the given template, passing it the given data.
* Used by the <% include %> template tag to process templates.
*/
static function execute_template($template, $data) {
$v = new SSViewer($template);
return $v->process($data);
}
static function parseTemplateContent($content, $template="") {
// Remove UTF-8 byte order mark:
// This is only necessary if you don't have zend-multibyte enabled.
@ -406,21 +415,6 @@ class SSViewer {
}
}
while(true) {
$oldContent = $content;
// Add include filename comments on dev sites
if(Director::isDev() && self::$source_file_comments) $replacementCode = 'return "<!-- include " . SSViewer::getTemplateFile($matches[1]) . " -->\n"
. SSViewer::getTemplateContent($matches[1])
. "\n<!-- end include " . SSViewer::getTemplateFile($matches[1]) . " -->";';
else $replacementCode = 'return SSViewer::getTemplateContent($matches[1]);';
$content = preg_replace_callback('/<' . '% include +([A-Za-z0-9_]+) +%' . '>/', create_function(
'$matches', $replacementCode
), $content);
if($oldContent == $content) break;
}
// $val, $val.property, $val(param), etc.
$replacements = array(
'/<%--.*--%>/U' => '',
@ -531,6 +525,17 @@ class SSViewer {
// add all requirements to the $requirements array
preg_match_all('/<% require ([a-zA-Z]+)\(([^\)]+)\) %>/', $content, $requirements);
$content = preg_replace('/<% require .* %>/', null, $content);
// Add include filename comments on dev sites
if(Director::isDev() && self::$source_file_comments) $replacementCode = 'return "<!-- include " . SSViewer::getTemplateFile($matches[1]) . " -->\n"
. "<?= SSViewer::parse_template(\\"" . $matches[1] . "\", \$item); ?>"
. "\n<!-- end include " . SSViewer::getTemplateFile($matches[1]) . " -->";';
else $replacementCode = 'return "<?= SSViewer::execute_template(\\"" . $matches[1] . "\", \$item); ?>";';
$content = preg_replace_callback('/<' . '% include +([A-Za-z0-9_]+) +%' . '>/', create_function(
'$matches', $replacementCode
), $content);
// legacy
$content = ereg_replace('<!-- +if +([A-Za-z0-9_]+) +-->', '<? if($item->cachedCall("\\1")) { ?>', $content);

View File

@ -280,6 +280,32 @@ after')
$negotiator->xhtml($response);
$this->assertRegExp('/<head><base href=".*"><\/base><\/head>/', $response->getBody());
}
function testRecursiveInclude() {
$view = new SSViewer(array('SSViewerTestRecursiveInclude'));
$data = new ArrayData(array(
'Title' => 'A',
'Children' => new DataObjectSet(array(
new ArrayData(array(
'Title' => 'A1',
'Children' => new DataObjectSet(array(
new ArrayData(array( 'Title' => 'A1 i', )),
new ArrayData(array( 'Title' => 'A1 ii', )),
)),
)),
new ArrayData(array( 'Title' => 'A2', )),
new ArrayData(array( 'Title' => 'A3', )),
)),
));
$result = $view->process($data);
// We don't care about whitespace
$rationalisedResult = trim(preg_replace('/\s+/', ' ', $result));
$this->assertEquals('A A1 A1 i A1 ii A2 A3', $rationalisedResult);
}
}
/**

View File

@ -0,0 +1,6 @@
$Title
<% if Children %>
<% control Children %>
<% include SSViewerTestRecursiveInclude %>
<% end_control %>
<% end_if %>