Author: Raymond Bosman Date: 2007-02-27 13:09:47 +0100 (Tue, 27 Feb 2007) New Revision: 4690
Log: - Added {cache_block} and tests. Added: trunk/Template/tests/templates/cache_block2.tpl trunk/Template/tests/templates/cache_block_dynamic.tpl trunk/Template/tests/templates/cache_block_in_cache_block.tpl trunk/Template/tests/templates/cache_block_in_cache_template.tpl trunk/Template/tests/templates/cache_block_in_dynamic.tpl trunk/Template/tests/templates/cache_block_in_loop.tpl trunk/Template/tests/templates/cache_block_ttl.tpl trunk/Template/tests/templates/cache_block_with_keys.tpl Modified: trunk/Template/src/error_messages.php trunk/Template/src/parsers/tst_to_ast/implementations/tst_to_ast_cached_transformer.php trunk/Template/src/syntax_trees/tst/nodes/cache_block.php trunk/Template/tests/cache_test.php trunk/Template/tests/templates/cache_block.tpl Modified: trunk/Template/src/error_messages.php =================================================================== --- trunk/Template/src/error_messages.php 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/src/error_messages.php 2007-02-27 12:09:47 UTC (rev 4690) @@ -108,6 +108,9 @@ const MSG_EXPECT_CLOSING_BLOCK_COMMENT = "Could not find the closing block comment '*}' that belongs to this opening block comment."; const MSG_EXPECT_CLOSING_MULTILINE_COMMENT = "Could not find the closing comment '*/' that belongs to this opening comment."; + const MSG_CACHE_BLOCK_IN_DYNAMIC_BLOCK = "Cache block cannot be used inside a dynamic block."; + const MSG_CACHE_BLOCK_IN_CACHE_BLOCK = "Cache block cannot be used inside another cache block or inside cache_template."; + // Inconsistencies with eZ publish 3. const LNG_INVALID_NAMESPACE_MARKER = "The namespace marker (:) was used in template engine in eZ publish 3.x but is no longer allowed."; const LNG_INVALID_NAMESPACE_ROOT_MARKER = "The namespace-root marker (#) was used in the template engine of eZ publish 3.x but it's no longer allowed."; Modified: trunk/Template/src/parsers/tst_to_ast/implementations/tst_to_ast_cached_transformer.php =================================================================== --- trunk/Template/src/parsers/tst_to_ast/implementations/tst_to_ast_cached_transformer.php 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/src/parsers/tst_to_ast/implementations/tst_to_ast_cached_transformer.php 2007-02-27 12:09:47 UTC (rev 4690) @@ -31,9 +31,16 @@ private $isInDynamicBlock = false; + /** + * True when in {cache_template} or inside a {cache_block}. + */ + private $isInCacheBlock = false; + private $cacheBaseName = null; + protected $cacheBlockCounter = 0; + public function __construct( $parser, $cacheTemplate, $preparedCache ) { parent::__construct( $parser ); @@ -44,7 +51,6 @@ // XXX $this->template = $parser->template; //$this->cacheSystem = $parser->template->configuration->cacheSystem; - } @@ -279,10 +285,33 @@ $cb->appendStatement( $this->_fwritePhpOpen() ); // fwrite( $fp, "<" . "?php\n" ); $cb->appendStatement( $this->_assignEmptyString("total") ); // $total = "" - $cb->appendStatement( $this->_fwriteLiteral( "\$" . self::INTERNAL_PREFIX . "output = '';\n") ); // fwrite( $fp, "\\\$_ezcTemplate_output = '';\\n" ); + //$cb->appendStatement( $this->_fwriteLiteral( "\$" . self::INTERNAL_PREFIX . "output = '';\n") ); + //$cb->appendStatement( $this->_assign( self::INTERNAL_PREFIX. "output") ); // $total = "" + $cb->appendStatement( $this->_assignEmptyString( self::INTERNAL_PREFIX. "output") ); // $total = "" + } + // TEST VERSION for cacheblock. + protected function startCachingCacheBlock( $cb ) + { + /// startCaching(); + $cplen = strlen( $this->parser->template->configuration->compilePath ); + if ($this->template->configuration->cacheManager !== false ) + { + $cb->appendStatement( new ezcTemplateGenericStatementAstNode( new ezcTemplateFunctionCallAstNode( "\$this->template->configuration->cacheManager->startCaching", array( new ezcTemplateVariableAstNode("this->template"), new ezcTemplateLiteralAstNode( $this->parser->template->stream ), new ezcTemplateVariableAstNode("_ezcTemplateCache" ), new ezcTemplateVariableAstNode("_ezcCacheKeys") ) ) ) ); + } + + $cb->appendStatement( $this->_fopenCacheFileWriteMode() ); // $fp = fopen( $this->cache, "w" ); + + $cb->appendStatement( $this->_fwritePhpOpen() ); // fwrite( $fp, "<" . "?php\n" ); + //$cb->appendStatement( $this->_assignEmptyString("total") ); // $total = "" + $cb->appendStatement( $this->_assignVariable(self::INTERNAL_PREFIX . "output", "total") ); // $total = "" + //$cb->appendStatement( $this->_fwriteLiteral( "\$" . self::INTERNAL_PREFIX . "output = '';\n") ); + //$cb->appendStatement( $this->_assign( self::INTERNAL_PREFIX. "output") ); // $total = "" + $cb->appendStatement( $this->_assignEmptyString( self::INTERNAL_PREFIX. "output") ); // $total = "" + } + protected function insertInCache( $cb, $type ) { foreach ( $type->elements as $element ) @@ -302,7 +331,7 @@ } } - protected function stopCaching($cb) + protected function stopCaching($cb, $addReturn = true) { $cb->appendStatement( $this->_fwriteVarExportVariable( self::INTERNAL_PREFIX . "output", true, true) ); @@ -314,7 +343,11 @@ // $_ezcTemplate_output = $total; $cb->appendStatement( $this->_assignVariable( "total", self::INTERNAL_PREFIX . "output" ) ); - $cb->appendStatement( new ezcTemplateReturnAstNode( $this->outputVariable->getAst()) ); + if ($addReturn) + { + $cb->appendStatement( new ezcTemplateReturnAstNode( $this->outputVariable->getAst()) ); + } + } protected function addUseVariables() @@ -347,6 +380,10 @@ return parent::visitProgramTstNode($type); } + // Cache the whole template. + $this->isInCacheBlock = true; + + $this->prepareProgram(); // Program operations, nothing to do with caching. $cacheKeys = $this->translateCacheKeys($this->cacheTemplate->keys); @@ -397,24 +434,23 @@ $this->programNode->appendStatement( new ezcTemplateReturnAstNode( $this->outputVariable->getAst()) ); } - protected function addCacheKeys( $programNode, $cacheKeys ) + protected function addCacheKeys( $programNode, $cacheKeys, $cacheBlock = false ) { $hasCacheKey = false; $programNode->appendStatement( new ezcTemplatePhpCodeAstNode( '$_ezcCacheKeys = array();' ."\n" ) ); + $cacheBlock = $cacheBlock === false ? "" : "[cb".$cacheBlock . "]"; + foreach ( $cacheKeys as $key => $value ) { $programNode->appendStatement( new ezcTemplatePhpCodeAstNode( '$_ezcCacheKeys[\''.$key.'\'] = '. 'is_object( $'.$value.' ) && method_exists( $'.$value.', "cacheKey" ) ? $'.$value.'->cacheKey() : $'. $value . ";\n" ) ); -// $programNode->appendStatement( new ezcTemplatePhpCodeAstNode( '$_ezcCacheKeys[\''.$value.'\'] = '. 'md5( var_export( is_object( $'.$value.' ) && method_exists( $'.$value.', "cacheKey" ) ? $'.$value.'->cacheKey() : $'. $value . ', true ) )' . ";\n" ) ); - - $hasCacheKey = true; } if( $hasCacheKey ) { - $code = '$_ezcTemplateCache = \'' . $this->getCacheBaseName() . "'" ; + $code = '$_ezcTemplateCache = \'' . $this->getCacheBaseName() . $cacheBlock ."'" ; foreach ( $cacheKeys as $key => $value ) { $code .= " . '-'". '. md5( var_export( $_ezcCacheKeys[\''.$key.'\'], true ))'; @@ -424,7 +460,7 @@ } else { - $programNode->appendStatement(new ezcTemplatePhpCodeAstNode( '$_ezcTemplateCache = \'' . $this->getCacheBaseName() . "';\n" ) ); + $programNode->appendStatement(new ezcTemplatePhpCodeAstNode( '$_ezcTemplateCache = \'' . $this->getCacheBaseName() . $cacheBlock . "';\n" ) ); } } @@ -625,8 +661,83 @@ public function visitCacheBlockTstNode( ezcTemplateCacheBlockTstNode $type ) { + if ( $this->isInDynamicBlock ) + { + throw new ezcTemplateParserException( $type->source, $type->endCursor, $type->endCursor, ezcTemplateSourceToTstErrorMessages::MSG_CACHE_BLOCK_IN_DYNAMIC_BLOCK ); + } + + if( $this->isInCacheBlock ) + { + throw new ezcTemplateParserException( $type->source, $type->endCursor, $type->endCursor, ezcTemplateSourceToTstErrorMessages::MSG_CACHE_BLOCK_IN_CACHE_BLOCK ); + } + + $this->isInCacheBlock = true; + + $statements = new ezcTemplateBodyAstNode(); + + $cacheKeys = $this->translateCacheKeys($type->keys); + + $this->addUseVariables(); + $this->addCacheKeys( $statements, $cacheKeys, $this->cacheBlockCounter++ ); + + $ttl = $this->translateTTL($type->ttl); + + $ttlStatements = $this->checkTTL( $ttl, $cacheKeys ); + foreach ( $ttlStatements as $s ) + { + $statements->appendStatement( $s ); + } + + $this->createCacheDir(); + $this->deleteOldCache(); + + // Create the if statement that checks whether the cache file exists. + $if = new ezcTemplateIfAstNode(); + $if->conditions[] = $cb = new ezcTemplateConditionBodyAstNode(); + + $cb->condition = $this->notFileExistsCache(); + $cb->body = new ezcTemplateBodyAstNode(); + + $this->startCachingCacheBlock($cb->body); + $this->insertInCache( $cb->body, $type ); + + // Create the 'else' part. The else should 'include' (and execute) the cached file. + $if->conditions[] = $else = new ezcTemplateConditionBodyAstNode(); + $else->body = new ezcTemplateBodyAstNode(); + + $else->body->statements = array(); + $else->body->statements[] = $this->_includeCache(); + + + if ($this->template->configuration->cacheManager !== false ) + { + $cb->body->appendStatement( new ezcTemplateGenericStatementAstNode( new ezcTemplateFunctionCallAstNode( "\$this->template->configuration->cacheManager->stopCaching", array() ))); + } + + $this->stopCaching($cb->body, false); + + // Outside. + $statements->appendStatement( $if ); + + // RETURN STATEMENT outside.. + //$statements->appendStatement( new ezcTemplateReturnAstNode( $this->outputVariable->getAst()) ); + + + $this->isInCacheBlock = false; + + return $statements->statements; + + + + + + + + + + + /* $newStatement = array(); - $newStatement[] = $this->_comment(" ---> start {cache_block}"); @@ -741,6 +852,7 @@ $newStatement[] = $this->_comment(" <--- stop {/cache_block}"); return $newStatement; + */ } } Modified: trunk/Template/src/syntax_trees/tst/nodes/cache_block.php =================================================================== --- trunk/Template/src/syntax_trees/tst/nodes/cache_block.php 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/src/syntax_trees/tst/nodes/cache_block.php 2007-02-27 12:09:47 UTC (rev 4690) @@ -24,6 +24,7 @@ public $isClosingBlock = false; public $keys = array(); + public $ttl = null; /** * Modified: trunk/Template/tests/cache_test.php =================================================================== --- trunk/Template/tests/cache_test.php 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/tests/cache_test.php 2007-02-27 12:09:47 UTC (rev 4690) @@ -78,18 +78,228 @@ // } // } - /* + public function testCacheBlock() { $t = new ezcTemplate(); $t->send->user = new TestUser( "Bernard", "Black" ); - echo "\n" . $t->configuration->compilePath . "\n"; $out = $t->process( "cache_block.tpl"); - echo $out; + $this->assertEquals( +<<<EOM +Before: [Bernard Black] + +Cache block 0: [Bernard Black] + +Between cb 0 and 1: [Bernard Black] + +Cache block 1: [Bernard Black] + +After: [Bernard Black] + +EOM +, $out); + + $t->send->user = new TestUser( "Roger", "Rabbit" ); + $out = $t->process( "cache_block.tpl"); + $this->assertEquals( +<<<EOM +Before: [Roger Rabbit] + +Cache block 0: [Bernard Black] + +Between cb 0 and 1: [Roger Rabbit] + +Cache block 1: [Bernard Black] + +After: [Roger Rabbit] + +EOM +, $out); + } - */ + + public function testCacheBlockWithDynamic() + { + $t = new ezcTemplate(); + $t->send->user = new TestUser( "Homer", "Simpson" ); + + $out = $t->process( "cache_block_dynamic.tpl"); + $this->assertEquals( +<<<EOM +[Homer Simpson] + +1. Homer Simpson +dyn: Homer Simpson + +[Homer Simpson] + +2. Homer Simpson +dyn: Homer Simpson + +[Homer Simpson] + +EOM +, $out); + + $t->send->user = new TestUser( "Bart", "Simpson" ); + $out = $t->process( "cache_block_dynamic.tpl"); + $this->assertEquals( +<<<EOM +[Bart Simpson] + +1. Homer Simpson +dyn: Bart Simpson + +[Bart Simpson] + +2. Homer Simpson +dyn: Bart Simpson + +[Bart Simpson] + +EOM +, $out); + } + + + public function testCacheBlockInDynamic() + { + $t = new ezcTemplate(); + $t->send->user = new TestUser( "Bernard", "Black" ); + + try + { + $out = $t->process( "cache_block_in_dynamic.tpl"); + $this->fail("Expected an exception"); + } + catch( ezcTemplateParserException $e ) + { + } + } + + + public function testCacheBlockWithKeys() + { + $t = new ezcTemplate(); + $t->send->user = new TestUser( "Homer", "Simpson" ); + + $out = $t->process( "cache_block_with_keys.tpl"); + $this->assertEquals( "\n[Homer Simpson]\n", $out); + + $t->send->user = new TestUser( "Bart", "Simpson" ); + $out = $t->process( "cache_block_with_keys.tpl"); + $this->assertEquals( "\n[Homer Simpson]\n", $out); // Still cached. + + $t->send->user = new TestUser( "Bart", "Simpson" , 2); // New ID, cache key no longer valid. + $out = $t->process( "cache_block_with_keys.tpl"); + $this->assertEquals( "\n[Bart Simpson]\n", $out); + } + + public function testCacheBlockInCacheBlock() + { + $t = new ezcTemplate(); + $t->send->user = new TestUser( "Homer", "Simpson" ); + + try + { + $out = $t->process( "cache_block_in_cache_block.tpl"); + $this->fail("Expected an exception"); + } + catch( ezcTemplateParserException $e ) + { + } + + try + { + $out = $t->process( "cache_block_in_cache_template.tpl"); + $this->fail("Expected an exception"); + } + catch( ezcTemplateParserException $e ) + { + } + } + + + + public function testCacheBlockIndependently() + { + $t = new ezcTemplate(); + $t->send->user = new TestUser( "Homer", "Simpson" ); + $t->send->user2 = new TestUser( "Bart", "Simpson" ); + + $out = $t->process( "cache_block2.tpl"); + $this->assertEquals( +<<<EOM +[Homer Simpson][Bart Simpson] + +1.[Homer Simpson] +1.[Bart Simpson] + +[Homer Simpson][Bart Simpson] + +2.[Homer Simpson] +2.[Bart Simpson] + +[Homer Simpson][Bart Simpson] + +EOM +, $out); + + $t->send->user = new TestUser( "Marge", "Simpson", 2 ); + $out = $t->process( "cache_block2.tpl"); + + // Keep the second, since the cache-key changed only for 'Homer' to 'Marge'. + $this->assertEquals( +<<<EOM +[Marge Simpson][Bart Simpson] + +1.[Marge Simpson] +1.[Bart Simpson] + +[Marge Simpson][Bart Simpson] + +2.[Homer Simpson] +2.[Bart Simpson] + +[Marge Simpson][Bart Simpson] + +EOM +, $out); + } + + public function testCacheBlockTimeToLive() + { + $t = new ezcTemplate(); + $t->send->username = "Bernard"; + $out = $t->process( "cache_block_ttl.tpl"); + $this->assertEquals( "[Bernard]\n--\n[Bernard]\n", $out ); + $timer = time(); + + while (time() - $timer < 2 ) + { + usleep( 300000 ); // 300 ms. + } + + // Check whether the template is removed after the TTL exceeded. + $t->send->username = "Guybrush"; + $out = $t->process( "cache_block_ttl.tpl"); + $this->assertEquals( "[Guybrush]\n--\n[Bernard]\n", $out ); + } + + public function testCacheBlockInLoop() + { + $t = new ezcTemplate(); + $t->send->username = "Bernard"; + $out = $t->process( "cache_block_in_loop.tpl"); + + $this->assertEquals( "\n1\n1\n1\n1\n1\n\n1\n2\n3\n4\n5\n", $out); + } + + + //echo "\n" . $t->configuration->compilePath . "\n"; + public function testCacheBlockWithBeginText() { $t = new ezcTemplate( ); @@ -117,7 +327,6 @@ $t->send->user = new TestUser( "Guybrush", "Threepwood" ); $out = $t->process( "cache_dynamic.tpl"); $this->assertEquals( "\n[Bernard Black]\n[Guybrush Threepwood]\n", $out ); - } // - Test whether the all the dynamic block changes when the {use} variable changes. Modified: trunk/Template/tests/templates/cache_block.tpl =================================================================== --- trunk/Template/tests/templates/cache_block.tpl 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/tests/templates/cache_block.tpl 2007-02-27 12:09:47 UTC (rev 4690) @@ -1,8 +1,14 @@ {use $user} -[{$user->name}] -{var $a} +Before: [{$user->name}] {cache_block} - {$a = 2} - [{$user->name}] + Cache block 0: [{$user->name}] {/cache_block} + +Between cb 0 and 1: [{$user->name}] + +{cache_block} + Cache block 1: [{$user->name}] +{/cache_block} + +After: [{$user->name}] Added: trunk/Template/tests/templates/cache_block2.tpl =================================================================== --- trunk/Template/tests/templates/cache_block2.tpl 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/tests/templates/cache_block2.tpl 2007-02-27 12:09:47 UTC (rev 4690) @@ -0,0 +1,16 @@ +{use $user, $user2} +[{$user->name}][{$user2->name}] + +{cache_block keys $user} + 1.[{$user->name}] + 1.[{$user2->name}] +{/cache_block} + +[{$user->name}][{$user2->name}] + +{cache_block keys $user2} + 2.[{$user->name}] + 2.[{$user2->name}] +{/cache_block} + +[{$user->name}][{$user2->name}] Property changes on: trunk/Template/tests/templates/cache_block2.tpl ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/Template/tests/templates/cache_block_dynamic.tpl =================================================================== --- trunk/Template/tests/templates/cache_block_dynamic.tpl 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/tests/templates/cache_block_dynamic.tpl 2007-02-27 12:09:47 UTC (rev 4690) @@ -0,0 +1,20 @@ +{use $user} +[{$user->name}] + +{cache_block} + 1. {$user->name} + {dynamic} + dyn: {$user->name} + {/dynamic} +{/cache_block} + +[{$user->name}] + +{cache_block} + 2. {$user->name} + {dynamic} + dyn: {$user->name} + {/dynamic} +{/cache_block} + +[{$user->name}] Property changes on: trunk/Template/tests/templates/cache_block_dynamic.tpl ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/Template/tests/templates/cache_block_in_cache_block.tpl =================================================================== --- trunk/Template/tests/templates/cache_block_in_cache_block.tpl 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/tests/templates/cache_block_in_cache_block.tpl 2007-02-27 12:09:47 UTC (rev 4690) @@ -0,0 +1,8 @@ +{use $user} + +Hello +{cache_block} + {cache_block} + {$user->name} + {/cache_block} +{/cache_block} Property changes on: trunk/Template/tests/templates/cache_block_in_cache_block.tpl ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/Template/tests/templates/cache_block_in_cache_template.tpl =================================================================== --- trunk/Template/tests/templates/cache_block_in_cache_template.tpl 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/tests/templates/cache_block_in_cache_template.tpl 2007-02-27 12:09:47 UTC (rev 4690) @@ -0,0 +1,7 @@ +{use $user} +{cache_template} + +Hello +{cache_block} + {$user->name} +{/cache_block} Property changes on: trunk/Template/tests/templates/cache_block_in_cache_template.tpl ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/Template/tests/templates/cache_block_in_dynamic.tpl =================================================================== --- trunk/Template/tests/templates/cache_block_in_dynamic.tpl 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/tests/templates/cache_block_in_dynamic.tpl 2007-02-27 12:09:47 UTC (rev 4690) @@ -0,0 +1,8 @@ +{use $user} + +Hello +{dynamic} + {cache_block} + {$user->name} + {/cache_block} +{/dynamic} Property changes on: trunk/Template/tests/templates/cache_block_in_dynamic.tpl ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/Template/tests/templates/cache_block_in_loop.tpl =================================================================== --- trunk/Template/tests/templates/cache_block_in_loop.tpl 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/tests/templates/cache_block_in_loop.tpl 2007-02-27 12:09:47 UTC (rev 4690) @@ -0,0 +1,13 @@ +{use $username} + +{foreach 1..5 as $i} + {cache_block} + {$i} + {/cache_block} +{/foreach} + +{foreach 1..5 as $i} + {cache_block keys $i} + {$i} + {/cache_block} +{/foreach} Property changes on: trunk/Template/tests/templates/cache_block_in_loop.tpl ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/Template/tests/templates/cache_block_ttl.tpl =================================================================== --- trunk/Template/tests/templates/cache_block_ttl.tpl 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/tests/templates/cache_block_ttl.tpl 2007-02-27 12:09:47 UTC (rev 4690) @@ -0,0 +1,8 @@ +{use $username} +{cache_block ttl 1} + [{$username}] +{/cache_block} +-- +{cache_block} + [{$username}] +{/cache_block} Property changes on: trunk/Template/tests/templates/cache_block_ttl.tpl ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/Template/tests/templates/cache_block_with_keys.tpl =================================================================== --- trunk/Template/tests/templates/cache_block_with_keys.tpl 2007-02-27 09:35:27 UTC (rev 4689) +++ trunk/Template/tests/templates/cache_block_with_keys.tpl 2007-02-27 12:09:47 UTC (rev 4690) @@ -0,0 +1,5 @@ +{use $user} + +{cache_block keys $user} +[{$user->name}] +{/cache_block} Property changes on: trunk/Template/tests/templates/cache_block_with_keys.tpl ___________________________________________________________________ Name: svn:eol-style + native -- svn-components mailing list svn-components@lists.ez.no http://lists.ez.no/mailman/listinfo/svn-components