Commit 0f9e323d by Jordi Boggiano

Added support for nested blocks for template inheritance, block names must be…

Added support for nested blocks for template inheritance, block names must be unique, overriding of any block is done at the top level. Fixes #7
parent e659e084
[2010--] 1.2.0
[2011--] 1.2.0
! BC Break: Dwoo_Core::isArray had to be fixed and it has been split up
in 3 methods, isArray (for array access), isTraversable (for foreach)
and count (just a helper that counts anything). It won't affect you
......@@ -12,6 +12,9 @@
evaluating a template already, this only affects you if you built your
own include-like plugin, see the changes to include plugin in revision
346 [http://bugs.dwoo.org/dwoo/browse_code/revision/345] for more infos
+ Added support for nested blocks for template inheritance, block names
must be unique, overriding of any block is done at the top level, thanks
to Ian Carpenter for the patch
+ Added {return} plugin that allows any included template to return
variables into the one that included it, or to the main controller
code via $dwoo->getReturnValues()
......
......@@ -19,17 +19,30 @@
class Dwoo_Plugin_extends extends Dwoo_Plugin implements Dwoo_ICompilable
{
protected static $childSource;
protected static $regex;
protected static $l;
protected static $lraw;
protected static $r;
protected static $rraw;
protected static $lastReplacement;
public static function compile(Dwoo_Compiler $compiler, $file)
{
list(self::$lraw, self::$rraw) = $compiler->getDelimiters();
self::$l = preg_quote(self::$lraw,'/');
self::$r = preg_quote(self::$rraw,'/');
list($l, $r) = $compiler->getDelimiters();
self::$l = preg_quote($l,'/');
self::$r = preg_quote($r,'/');
self::$regex = '%
'.self::$l.'block\s(["\']?)(.+?)\1'.self::$r.'(?:\r?\n?)
((?:
(?R)
|
[^'.self::$l.']*
(?:
(?! '.self::$l.'/?block\b )
'.self::$l.'
[^'.self::$l.']*+
)*
)*)
'.self::$l.'\/block'.self::$r.'
%six';
if ($compiler->getLooseOpeningHandling()) {
self::$l .= '\s*';
......@@ -98,53 +111,51 @@ class Dwoo_Plugin_extends extends Dwoo_Plugin implements Dwoo_ICompilable
if (!isset($newSource)) {
$newSource = $parent['source'];
}
// TODO parse blocks tree for child source and new source
// TODO replace blocks that are found in the child and in the parent recursively
$firstL = preg_quote(self::$lraw[0], '/');
$restL = preg_quote(substr(self::$lraw, 1), '/');
$newSource = preg_replace_callback('/'.self::$l.'block (["\']?)(.+?)\1'.self::$r.'(?:\r?\n?)((?:[^'.$firstL.']*|'.$firstL.'(?!'.$restL.'\/block'.self::$r.'))*)'.self::$l.'\/block'.self::$r.'/is', array('Dwoo_Plugin_extends', 'replaceBlock'), $newSource);
$newSource = self::$lraw.'do extendsCheck("'.$parent['resource'].':'.$parent['identifier'].'")'.self::$rraw.$newSource;
$newSource = preg_replace_callback(self::$regex, array('Dwoo_Plugin_extends', 'replaceBlock'), $newSource);
$newSource = $l.'do extendsCheck("'.$parent['resource'].':'.$parent['identifier'].'")'.$r.$newSource;
if (self::$lastReplacement) {
break;
}
}
$compiler->setTemplateSource($newSource);
$compiler->recompile();
}
protected static function replaceBlock(array $matches)
{
$matches[3] = self::cleanTrailingCRLF($matches[3]);
$firstL = preg_quote(self::$lraw[0], '/');
$restL = preg_quote(substr(self::$lraw, 1), '/');
if (preg_match('/'.self::$l.'block (["\']?)'.preg_quote($matches[2],'/').'\1'.self::$r.'(?:\r?\n?)((?:[^'.$firstL.']*|'.$firstL.'(?!'.$restL.'\/block'.self::$r.'))*)'.self::$l.'\/block'.self::$r.'/is', self::$childSource, $override)) {
$override[2] = self::cleanTrailingCRLF($override[2]);
$matches[3] = self::removeTrailingNewline($matches[3]);
if (preg_match_all(self::$regex, self::$childSource, $override) && in_array($matches[2], $override[2])) {
$key = array_search($matches[2], $override[2]);
$override = self::removeTrailingNewline($override[3][$key]);
$l = stripslashes(self::$l);
$r = stripslashes(self::$r);
if (self::$lastReplacement) {
return preg_replace('/'.self::$l.'\$dwoo\.parent'.self::$r.'/is', $matches[3], $override[2]);
} else {
return self::$lraw.'block '.$matches[1].$matches[2].$matches[1].self::$rraw.preg_replace('/'.self::$l.'\$dwoo\.parent'.self::$r.'/is', $matches[3], $override[2]).self::$lraw.'/block'.self::$rraw;
return preg_replace('/'.self::$l.'\$dwoo\.parent'.self::$r.'/is', $matches[3], $override);
}
} else {
return $l.'block '.$matches[1].$matches[2].$matches[1].$r.preg_replace('/'.self::$l.'\$dwoo\.parent'.self::$r.'/is', $matches[3], $override).$l.'/block'.$r;
}
if (preg_match(self::$regex, $matches[3])) {
return preg_replace_callback(self::$regex, array('Dwoo_Plugin_extends', 'replaceBlock'), $matches[3] );
}
if (self::$lastReplacement) {
return $matches[3];
} else {
return $matches[0];
}
}
return $matches[0];
}
protected static function cleanTrailingCRLF($input)
protected static function removeTrailingNewline($text)
{
if (substr($input, -1) === "\n") {
if (substr($input, -2, 1) === "\r") {
return substr($input, 0, -2);
}
return substr($input, 0, -1);
}
return $input;
return substr($text, -1) === "\n"
? substr($text, -2, 1) === "\r"
? substr($text, 0, -2)
: substr($text, 0, -1)
: $text;
}
}
\ No newline at end of file
......@@ -179,6 +179,36 @@ FOObartoplevelContent2
baz"));
}
public function testExtendsWithNestedBlocks()
{
$tpl = new Dwoo_Template_File(dirname(__FILE__).'/resources/extends_nested/child.html');
$tpl->forceCompilation();
$this->assertThat($this->dwoo->get($tpl, array(), $this->compiler), new DwooConstraintStringEquals("<html>
Root
Child Header
Root Subcontent
"."
lala
Parent Footer
</html>
"));
}
public function testExtendsWithNestedBlocks2()
{
$tpl = new Dwoo_Template_File(dirname(__FILE__).'/resources/extends_nested/child2.html');
$tpl->forceCompilation();
$this->assertThat($this->dwoo->get($tpl, array(), $this->compiler), new DwooConstraintStringEquals("<html>
Parent Content
lala
Root Footer
</html>
"));
}
public function testIf ()
{
$tpl = new Dwoo_Template_String('{if "BAR"==reverse($foo|reverse|upper)}true{/if}');
......
{extends "parent.html"}
{block "header"}
Child Header
{/block}
\ No newline at end of file
{extends "parent2.html"}
{block "header"}
Child Header
{/block}
\ No newline at end of file
{extends 'root.html'}
{block "footer"}
Parent Footer
{/block}
\ No newline at end of file
{extends 'root.html'}
{block "content"}
Parent Content
{/block}
\ No newline at end of file
<html>
{block "content"}
Root
{block "header"}
Root Header
{/block}
{block "subcontent"}
Root Subcontent
{/block}
{/block}
lala
{block footer}Root Footer{/block}
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment