From 04299df8863fd19ba37fa0f52833f62a2b98903f Mon Sep 17 00:00:00 2001 From: Hamish Friedlander Date: Tue, 30 Mar 2010 02:36:54 +0000 Subject: [PATCH] API CHANGE: Allow cached blocks within control and if blocks, as long as that control or if block is contained within an uncached block, not a cached block git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.4@101833 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- core/SSViewer.php | 87 ++++++++++++++++++-------------- tests/SSViewerCacheBlockTest.php | 13 +++-- 2 files changed, 59 insertions(+), 41 deletions(-) diff --git a/core/SSViewer.php b/core/SSViewer.php index 23def2511..18dbaa5d0 100755 --- a/core/SSViewer.php +++ b/core/SSViewer.php @@ -686,33 +686,21 @@ class SSViewer_PartialParser { /xS'; static function process($template, $content) { - $parser = new SSViewer_PartialParser($template, $content, 0, array(), 'if', 'false'); + $parser = new SSViewer_PartialParser($template, $content, 0); $parser->parse(); return $parser->generate(); } - function __construct($template, $content, $offset, $keyparts, $conditional, $condition) { + function __construct($template, $content, $offset) { $this->template = $template; $this->content = $content; $this->offset = $offset; - $this->keyparts = $keyparts; - $this->conditional = $conditional; - $this->condition = $condition; - $this->blocks = array(); } function controlcheck($text) { - $ifs = preg_match_all('/<'.'% +if +/', $text, $matches); - $end_ifs = preg_match_all('/<'.'% +end_if +/', $text, $matches); - - if ($ifs != $end_ifs) throw new Exception('You can\'t have cached or uncached blocks within condition structures'); - - $controls = preg_match_all('/<'.'% +control +/', $text, $matches); - $end_controls = preg_match_all('/<'.'% +end_control +/', $text, $matches); - - if ($controls != $end_controls) throw new Exception('You can\'t have cached or uncached blocks within control structures'); + // NOP - hook for Cached_PartialParser } function parse() { @@ -735,12 +723,12 @@ class SSViewer_PartialParser { if ($tag == 'cached' || $tag == 'cacheblock') { list($keyparts, $conditional, $condition) = $this->parseargs(@$matches[2][0]); + $parser = new SSViewer_Cached_PartialParser($this->template, $this->content, $endpos, $keyparts, $conditional, $condition); } else { - $keyparts = array(); $conditional = 'if'; $condition = 'false'; + $parser = new SSViewer_PartialParser($this->template, $this->content, $endpos); } - $parser = new SSViewer_PartialParser($this->template, $this->content, $endpos, $keyparts, $conditional, $condition); $parser->parse(); $this->blocks[] = $parser; $this->offset = $parser->offset; @@ -824,13 +812,49 @@ class SSViewer_PartialParser { return array($parts, $conditional, $condition); } + function generate() { + $res = array(); + + foreach ($this->blocks as $i => $block) { + if ($block instanceof SSViewer_PartialParser) + $res[] = $block->generate(); + else { + $res[] = $block; + } + } + + return implode('', $res); + } +} + +class SSViewer_Cached_PartialParser extends SSViewer_PartialParser { + + function __construct($template, $content, $offset, $keyparts, $conditional, $condition) { + $this->keyparts = $keyparts; + $this->conditional = $conditional; + $this->condition = $condition; + + parent::__construct($template, $content, $offset); + } + + function controlcheck($text) { + $ifs = preg_match_all('/<'.'% +if +/', $text, $matches); + $end_ifs = preg_match_all('/<'.'% +end_if +/', $text, $matches); + + if ($ifs != $end_ifs) throw new Exception('You can\'t have cached or uncached blocks within condition structures'); + + $controls = preg_match_all('/<'.'% +control +/', $text, $matches); + $end_controls = preg_match_all('/<'.'% +end_control +/', $text, $matches); + + if ($controls != $end_controls) throw new Exception('You can\'t have cached or uncached blocks within control structures'); + } + function key() { if (empty($this->keyparts)) return "''"; return 'sha1(' . implode(".'_'.", $this->keyparts) . ')'; } function generate() { - $res = array(); $key = $this->key(); @@ -855,26 +879,15 @@ class SSViewer_PartialParser { // of cache blocks, and invalidation of the cache when the template changes $partialkey = "'".sha1($this->template . $block)."_'.$key.'_$i'"; - $knownUncached = array( - 'if' => array('false', '0'), - 'unless' => array('true', '1') - ); + // Try to load from cache + $res[] = "load('.$partialkey.'))) $val .= $partial;'."\n"; - // Optimized version if we know condition is false - if ($this->conditional && in_array($this->condition, $knownUncached[$this->conditional])) { - $res[] = $block; - } - else { - // Try to load from cache - $res[] = "load('.$partialkey.'))) $val .= $partial;'."\n"; - - // Cache miss - regenerate - $res[] = "else {\n"; - $res[] = '$oldval = $val; $val = "";'."\n"; - $res[] = "\n?>" . $block . "save($val); $val = $oldval . $val ;'."\n"; - $res[] = "}\n?>"; - } + // Cache miss - regenerate + $res[] = "else {\n"; + $res[] = '$oldval = $val; $val = "";'."\n"; + $res[] = "\n?>" . $block . "save($val); $val = $oldval . $val ;'."\n"; + $res[] = "}\n?>"; } } diff --git a/tests/SSViewerCacheBlockTest.php b/tests/SSViewerCacheBlockTest.php index 856fff3c5..5500ca584 100644 --- a/tests/SSViewerCacheBlockTest.php +++ b/tests/SSViewerCacheBlockTest.php @@ -189,17 +189,22 @@ class SSViewerCacheBlockTest extends SapphireTest { /** * @expectedException Exception */ - function testErrorMessageForCacheWithinControl() { + function testErrorMessageForCachedWithinControlWithinCached() { $this->_reset(true); - $this->_runtemplate('<% control Foo %><% cached %>$Bar<% end_cached %><% end_control %>'); + $this->_runtemplate('<% cached %><% control Foo %><% cached %>$Bar<% end_cached %><% end_control %><% end_cached %>'); + } + + function testNoErrorMessageForCachedWithinControlWithinUncached() { + $this->_reset(true); + $this->_runtemplate('<% uncached %><% control Foo %><% cached %>$Bar<% end_cached %><% end_control %><% end_uncached %>'); } /** * @expectedException Exception */ - function testErrorMessageForCacheWithinIf() { + function testErrorMessageForCachedWithinIf() { $this->_reset(true); - $this->_runtemplate('<% if Foo %><% cached %>$Bar<% end_cached %><% end_if %>'); + $this->_runtemplate('<% cached %><% if Foo %><% cached %>$Bar<% end_cached %><% end_if %><% end_cached %>'); } /**