|
eZ Publish
[trunk]
|
00001 <?php 00002 /** 00003 * File containing the eZTemplateCompiler class. 00004 * 00005 * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved. 00006 * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2 00007 * @version //autogentag// 00008 * @package lib 00009 */ 00010 00011 /*! 00012 \class eZTemplateCompiler eztemplatecompiler.php 00013 \brief Creates compiled PHP code from templates to speed up template usage. 00014 00015 Various optimizations that can be done are: 00016 00017 Data: 00018 - Is constant, generate static data 00019 - Is variable, generate direct variable extraction 00020 - Has operators 00021 - Has attributes 00022 00023 Attributes: 00024 - Is constant, generate static data 00025 00026 Operators: 00027 - Supports input 00028 - Supports output 00029 - Supports parameters 00030 - Generates static data (true, false) 00031 - Custom PHP code 00032 - Modifies template variables, if possible name which ones. Allows 00033 for caching of variables in the script. 00034 00035 Functions: 00036 - Supports parameters 00037 - Supports children (set? no, section? yes) 00038 - Generates static data (ldelim,rdelim) 00039 - Children usage, no result(set-block) | copy(let,default) | dynamic(conditional, repeated etc.) 00040 - Children tree, requires original tree | allows custom processing 00041 - Custom PHP code 00042 - Deflate/transform tree, create new non-nested tree (let, default) 00043 - Modifies template variables, if possible name which ones. Allows 00044 for caching of variables in the script. 00045 */ 00046 00047 class eZTemplateCompiler 00048 { 00049 const CODE_DATE = 1074699607; 00050 00051 /*! 00052 \static 00053 Returns the prefix for file names 00054 */ 00055 static function TemplatePrefix() 00056 { 00057 $templatePrefix = ''; 00058 $ini = eZINI::instance(); 00059 if ( $ini->variable( 'TemplateSettings', 'TemplateCompression' ) == 'enabled' ) 00060 { 00061 $templatePrefix = 'compress.zlib://'; 00062 } 00063 return $templatePrefix; 00064 } 00065 /*! 00066 \static 00067 Sets/unsets various compiler settings. To set a setting add a key in the \a $settingsMap 00068 with the wanted value, to unset it use \c null as the value. 00069 00070 The following values can be set. 00071 - compile - boolean, whether to compile templates or not 00072 - comments - boolean, whether to include comments in templates 00073 - accumulators - boolean, whether to include debug accumulators in templates 00074 - timingpoints - boolean, whether to include debug timingpoints in templates 00075 - fallbackresource - boolean, whether to include the fallback resource code 00076 - nodeplacement - boolean, whether to include information on placement of all nodes 00077 - execution - boolean, whether to execute the compiled templates or not 00078 - generate - boolean, whether to always generate the compiled files, or only when template is changed 00079 - compilation-directory - string, where to place compiled files, the path will be relative from the 00080 eZ Publish directory and not the var/cache directory. 00081 */ 00082 static function setSettings( $settingsMap ) 00083 { 00084 $existingMap = array(); 00085 if ( isset( $GLOBALS['eZTemplateCompilerSettings'] ) ) 00086 { 00087 $existingMap = $GLOBALS['eZTemplateCompilerSettings']; 00088 } 00089 $GLOBALS['eZTemplateCompilerSettings'] = array_merge( $existingMap, $settingsMap ); 00090 } 00091 00092 /*! 00093 \static 00094 \return true if template compiling is enabled. 00095 \note To change this setting edit settings/site.ini and locate the group TemplateSettings and the entry TemplateCompile. 00096 */ 00097 static function isCompilationEnabled() 00098 { 00099 if ( isset( $GLOBALS['eZSiteBasics'] ) ) 00100 { 00101 $siteBasics = $GLOBALS['eZSiteBasics']; 00102 if ( isset( $siteBasics['no-cache-adviced'] ) and 00103 $siteBasics['no-cache-adviced'] ) 00104 { 00105 return false; 00106 } 00107 } 00108 00109 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['compile'] ) and 00110 $GLOBALS['eZTemplateCompilerSettings']['compile'] !== null ) 00111 { 00112 return $GLOBALS['eZTemplateCompilerSettings']['compile']; 00113 } 00114 00115 $ini = eZINI::instance(); 00116 $compilationEnabled = $ini->variable( 'TemplateSettings', 'TemplateCompile' ) == 'enabled'; 00117 return $compilationEnabled; 00118 } 00119 00120 /*! 00121 \static 00122 \return true if template compilation should include comments. 00123 */ 00124 static function isCommentsEnabled() 00125 { 00126 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['comments'] ) and 00127 $GLOBALS['eZTemplateCompilerSettings']['comments'] !== null ) 00128 { 00129 return $GLOBALS['eZTemplateCompilerSettings']['comments']; 00130 } 00131 00132 $ini = eZINI::instance(); 00133 $commentsEnabled = $ini->variable( 'TemplateSettings', 'CompileComments' ) == 'enabled'; 00134 return $commentsEnabled; 00135 } 00136 00137 /*! 00138 \static 00139 \return true if template compilation should run in development mode. 00140 00141 When in development mode the system will perform additional checks, e.g. for 00142 modification time of compiled file vs original source file. 00143 This mode is quite useful for development since it requires less 00144 clear-cache calls but has additional file checks and should be turned off 00145 for live sites. 00146 */ 00147 static function isDevelopmentModeEnabled() 00148 { 00149 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['development_mode'] ) and 00150 $GLOBALS['eZTemplateCompilerSettings']['development_mode'] !== null ) 00151 { 00152 return $GLOBALS['eZTemplateCompilerSettings']['development_mode']; 00153 } 00154 00155 $ini = eZINI::instance(); 00156 $developmentModeEnabled = $ini->variable( 'TemplateSettings', 'DevelopmentMode' ) == 'enabled'; 00157 return $developmentModeEnabled; 00158 } 00159 00160 /*! 00161 \static 00162 \return true if template compilation should include debug accumulators. 00163 */ 00164 static function isAccumulatorsEnabled() 00165 { 00166 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['accumulators'] ) and 00167 $GLOBALS['eZTemplateCompilerSettings']['accumulators'] !== null ) 00168 { 00169 return $GLOBALS['eZTemplateCompilerSettings']['accumulators']; 00170 } 00171 00172 $ini = eZINI::instance(); 00173 $enabled = $ini->variable( 'TemplateSettings', 'CompileAccumulators' ) == 'enabled'; 00174 return $enabled; 00175 } 00176 00177 /*! 00178 \static 00179 \return true if template compilation should include debug timing points. 00180 */ 00181 static function isTimingPointsEnabled() 00182 { 00183 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['timingpoints'] ) and 00184 $GLOBALS['eZTemplateCompilerSettings']['timingpoints'] !== null ) 00185 { 00186 return $GLOBALS['eZTemplateCompilerSettings']['timingpoints']; 00187 } 00188 00189 $ini = eZINI::instance(); 00190 $enabled = $ini->variable( 'TemplateSettings', 'CompileTimingPoints' ) == 'enabled'; 00191 return $enabled; 00192 } 00193 00194 /*! 00195 \static 00196 \return true if resource fallback code should be included. 00197 */ 00198 static function isFallbackResourceCodeEnabled() 00199 { 00200 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['fallbackresource'] ) and 00201 $GLOBALS['eZTemplateCompilerSettings']['fallbackresource'] !== null ) 00202 { 00203 return $GLOBALS['eZTemplateCompilerSettings']['fallbackresource']; 00204 } 00205 00206 $ini = eZINI::instance(); 00207 $enabled = $ini->variable( 'TemplateSettings', 'CompileResourceFallback' ) == 'enabled'; 00208 return $enabled; 00209 } 00210 00211 /*! 00212 \static 00213 \return true if template compilation should include comments. 00214 */ 00215 static function isNodePlacementEnabled() 00216 { 00217 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['nodeplacement'] ) and 00218 $GLOBALS['eZTemplateCompilerSettings']['nodeplacement'] !== null ) 00219 { 00220 return $GLOBALS['eZTemplateCompilerSettings']['nodeplacement']; 00221 } 00222 00223 $ini = eZINI::instance(); 00224 $nodePlacementEnabled = $ini->variable( 'TemplateSettings', 'CompileNodePlacements' ) == 'enabled'; 00225 return $nodePlacementEnabled; 00226 } 00227 00228 /*! 00229 \static 00230 \return true if the compiled template execution is enabled. 00231 */ 00232 static function isExecutionEnabled() 00233 { 00234 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['execution'] ) and 00235 $GLOBALS['eZTemplateCompilerSettings']['execution'] !== null ) 00236 { 00237 return $GLOBALS['eZTemplateCompilerSettings']['execution']; 00238 } 00239 00240 $ini = eZINI::instance(); 00241 $execution = $ini->variable( 'TemplateSettings', 'CompileExecution' ) == 'enabled'; 00242 return $execution; 00243 } 00244 00245 /*! 00246 \static 00247 \return true if template compilation should always be run even if a sufficient compilation already exists. 00248 */ 00249 static function alwaysGenerate() 00250 { 00251 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['generate'] ) and 00252 $GLOBALS['eZTemplateCompilerSettings']['generate'] !== null ) 00253 { 00254 return $GLOBALS['eZTemplateCompilerSettings']['generate']; 00255 } 00256 00257 $ini = eZINI::instance(); 00258 $alwaysGenerate = $ini->variable( 'TemplateSettings', 'CompileAlwaysGenerate' ) == 'enabled'; 00259 return $alwaysGenerate; 00260 } 00261 00262 /*! 00263 \static 00264 \return true if template node tree named \a $treeName should be included the compiled template. 00265 */ 00266 static function isTreeEnabled( $treeName ) 00267 { 00268 $ini = eZINI::instance(); 00269 $treeList = $ini->variable( 'TemplateSettings', 'CompileIncludeNodeTree' ); 00270 return in_array( $treeName, $treeList ); 00271 } 00272 00273 /*! 00274 \static 00275 \return the directory for compiled templates. 00276 */ 00277 static function compilationDirectory() 00278 { 00279 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['compilation-directory'] ) and 00280 $GLOBALS['eZTemplateCompilerSettings']['compilation-directory'] !== null ) 00281 { 00282 return $GLOBALS['eZTemplateCompilerSettings']['compilation-directory']; 00283 } 00284 00285 $compilationDirectory =& $GLOBALS['eZTemplateCompilerDirectory']; 00286 if ( !isset( $compilationDirectory ) ) 00287 { 00288 $ini = eZINI::instance(); 00289 $shareTemplates = $ini->hasVariable( 'TemplateSettings', 'ShareCompiledTemplates' ) ? 00290 $ini->variable( 'TemplateSettings', 'ShareCompiledTemplates' ) == 'enabled' : 00291 false; 00292 if ( $shareTemplates && 00293 $ini->hasVariable( 'TemplateSettings', 'SharedCompiledTemplatesDir' ) && 00294 trim( $ini->variable( 'TemplateSettings', 'SharedCompiledTemplatesDir' ) ) != '' ) 00295 { 00296 $compilationDirectory = eZDir::path( array( $ini->variable( 'TemplateSettings', 'SharedCompiledTemplatesDir' ) ) ); 00297 } 00298 else 00299 { 00300 $compilationDirectory = eZDir::path( array( eZSys::cacheDirectory(), 'template/compiled' ) ); 00301 } 00302 } 00303 return $compilationDirectory; 00304 } 00305 00306 /*! 00307 Creates the name for the compiled template and returns it. 00308 The name conists of original filename with the md5 of the key and charset appended. 00309 */ 00310 static function compilationFilename( $key, $resourceData ) 00311 { 00312 $internalCharset = eZTextCodec::internalCharset(); 00313 $templateFilepath = $resourceData['template-filename']; 00314 $extraName = ''; 00315 if ( preg_match( "#^.+/(.*)\.tpl$#", $templateFilepath, $matches ) ) 00316 $extraName = $matches[1] . '-'; 00317 else if ( preg_match( "#^(.*)\.tpl$#", $templateFilepath, $matches ) ) 00318 $extraName = $matches[1] . '-'; 00319 $accessText = false; 00320 if ( isset( $GLOBALS['eZCurrentAccess']['name'] ) ) 00321 $accessText = '-' . $GLOBALS['eZCurrentAccess']['name']; 00322 $locale = eZLocale::instance(); 00323 $language = $locale->localeFullCode(); 00324 $http = eZHTTPTool::instance(); 00325 $useFullUrlText = $http->UseFullUrl ? 'full' : 'relative'; 00326 00327 $pageLayoutVariable = ""; 00328 if ( isset( $GLOBALS['eZCustomPageLayout'] ) ) 00329 $pageLayoutVariable = $GLOBALS['eZCustomPageLayout']; 00330 00331 $ini = eZINI::instance(); 00332 00333 $shareTemplates = $ini->hasVariable( 'TemplateSettings', 'ShareCompiledTemplates' ) ? 00334 $ini->variable( 'TemplateSettings', 'ShareCompiledTemplates' ) == 'enabled' : 00335 false; 00336 00337 if ( $shareTemplates ) 00338 $cacheFileKey = $key . '-' . $language; 00339 else 00340 $cacheFileKey = $key . '-' . $internalCharset . '-' . $language . '-' . $useFullUrlText . $accessText . "-" . $pageLayoutVariable . '-' . eZSys::indexFile(); 00341 00342 $cacheFileName = $extraName . md5( $cacheFileKey ) . '.php'; 00343 return $cacheFileName; 00344 } 00345 00346 /*! 00347 \static 00348 \return true if the compiled template with the key \a $key exists. 00349 A compiled template is found usable when it exists and has a timestamp 00350 higher or equal to \a $timestamp. 00351 */ 00352 static function hasCompiledTemplate( $key, $timestamp, &$resourceData ) 00353 { 00354 if ( !eZTemplateCompiler::isCompilationEnabled() ) 00355 return false; 00356 if ( eZTemplateCompiler::alwaysGenerate() ) 00357 return false; 00358 00359 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $resourceData ); 00360 00361 $php = new eZPHPCreator( eZTemplateCompiler::compilationDirectory(), $cacheFileName, eZTemplateCompiler::TemplatePrefix() ); 00362 $canRestore = $php->canRestore( $timestamp ); 00363 $uri = false; 00364 if ( $canRestore ) 00365 eZDebugSetting::writeDebug( 'eztemplate-compile', "Cache hit for uri '$uri' with key '$key'", 'eZTemplateCompiler::hasCompiledTemplate' ); 00366 else 00367 eZDebugSetting::writeDebug( 'eztemplate-compile', "Cache miss for uri '$uri' with key '$key'", 'eZTemplateCompiler::hasCompiledTemplate' ); 00368 return $canRestore; 00369 } 00370 00371 /*! 00372 Tries to execute the compiled template and returns \c true if succsesful. 00373 Returns \c false if caching is disabled or the compiled template could not be executed. 00374 */ 00375 static function executeCompilation( $tpl, &$textElements, $key, &$resourceData, 00376 $rootNamespace, $currentNamespace ) 00377 { 00378 if ( !eZTemplateCompiler::isCompilationEnabled() ) 00379 return false; 00380 if ( !eZTemplateCompiler::isExecutionEnabled() ) 00381 return false; 00382 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $resourceData ); 00383 $resourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled(); 00384 00385 $directory = eZTemplateCompiler::compilationDirectory(); 00386 $phpScript = eZDir::path( array( $directory, $cacheFileName ) ); 00387 if ( file_exists( $phpScript ) ) 00388 { 00389 $text = false; 00390 $helperStatus = eZTemplateCompiler::executeCompilationHelper( $phpScript, $text, 00391 $tpl, $key, $resourceData, 00392 $rootNamespace, $currentNamespace ); 00393 if ( $helperStatus ) 00394 { 00395 $textElements[] = $text; 00396 return true; 00397 } 00398 else 00399 eZDebug::writeError( "Failed executing compiled template '$phpScript'", __METHOD__ ); 00400 } 00401 else 00402 eZDebug::writeError( "Unknown compiled template '$phpScript'", __METHOD__ ); 00403 return false; 00404 } 00405 00406 /*! 00407 Helper function for executeCompilation. Will execute the script \a $phpScript and 00408 set the result text in \a $text. 00409 The parameters \a $tpl, \a $resourceData, \a $rootNamespace and \a $currentNamespace 00410 are passed to the executed template compilation script. 00411 \return true if a text result was created. 00412 */ 00413 static function executeCompilationHelper( $phpScript, &$text, 00414 $tpl, $key, &$resourceData, 00415 $rootNamespace, $currentNamespace ) 00416 { 00417 $vars =& $tpl->Variables; 00418 00419 /* We use $setArray to detect if execution failed, and not $text, 00420 * because an empty template does not return any $text and this is not 00421 * an error. */ 00422 $setArray = null; 00423 $namespaceStack = array(); 00424 00425 $tpl->createLocalVariablesList(); 00426 include( eZTemplateCompiler::TemplatePrefix() . $phpScript ); 00427 $tpl->unsetLocalVariables(); 00428 $tpl->destroyLocalVariablesList(); 00429 00430 if ( $setArray !== null ) 00431 { 00432 return true; 00433 } 00434 return false; 00435 } 00436 00437 /*! 00438 \static 00439 Generates the cache which will be used for handling optimized processing using the key \a $key. 00440 \note Each call to this will set the PHP time limit to 30 00441 \return false if the cache does not exist. 00442 */ 00443 static function compileTemplate( $tpl, $key, &$resourceData ) 00444 { 00445 if ( !eZTemplateCompiler::isCompilationEnabled() ) 00446 return false; 00447 00448 $resourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled(); 00449 00450 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $resourceData ); 00451 $resourceData['uniqid'] = md5( $resourceData['template-filename']. uniqid( "ezp". getmypid(), true ) ); 00452 00453 // Time limit #1: 00454 // We reset the time limit to 30 seconds to ensure that templates 00455 // have enough time to compile 00456 // However if time limit is unlimited (0) we leave it be 00457 // Time limit will also be reset after subtemplates are compiled 00458 $maxExecutionTime = ini_get( 'max_execution_time' ); 00459 if ( $maxExecutionTime != 0 && $maxExecutionTime < 30 ) 00460 { 00461 @set_time_limit( 30 ); 00462 } 00463 00464 $rootNode =& $resourceData['root-node']; 00465 if ( !$rootNode ) 00466 return false; 00467 00468 $GLOBALS['eZTemplateCompilerResourceCache'][$resourceData['template-filename']] =& $resourceData; 00469 00470 $useComments = eZTemplateCompiler::isCommentsEnabled(); 00471 00472 if ( !$resourceData['test-compile'] ) 00473 { 00474 eZTemplateCompiler::createCommonCompileTemplate(); 00475 } 00476 00477 /* Check if we need to disable the generation of spacing for the compiled templates */ 00478 $ini = eZINI::instance(); 00479 $spacing = 'disabled'; 00480 if ( $ini->variable( 'TemplateSettings', 'UseFormatting' ) == 'enabled' ) 00481 { 00482 $spacing = 'enabled'; 00483 } 00484 00485 $php = new eZPHPCreator( eZTemplateCompiler::compilationDirectory(), $cacheFileName, 00486 eZTemplateCompiler::TemplatePrefix(), array( 'spacing' => $spacing ) ); 00487 $php->addComment( 'URI: ' . $resourceData['uri'] ); 00488 $php->addComment( 'Filename: ' . $resourceData['template-filename'] ); 00489 $php->addComment( 'Timestamp: ' . $resourceData['time-stamp'] . ' (' . date( 'D M j G:i:s T Y', $resourceData['time-stamp'] ) . ')' ); 00490 00491 $php->addCodePiece("\$oldSetArray_{$resourceData['uniqid']} = isset( \$setArray ) ? \$setArray : array();\n". 00492 "\$setArray = array();\n"); 00493 // Code to decrement include level of the templates 00494 $php->addCodePiece( "\$tpl->Level++;\n" ); 00495 $php->addCodePiece( "if ( \$tpl->Level > $tpl->MaxLevel )\n". 00496 "{\n". 00497 "\$text = \$tpl->MaxLevelWarning;". 00498 "\$tpl->Level--;\n". 00499 "return;\n". 00500 "}\n" ); 00501 if ( $resourceData['locales'] && count( $resourceData['locales'] ) ) 00502 { 00503 $php->addComment( 'Locales: ' . join( ', ', $resourceData['locales'] ) ); 00504 00505 $php->addCodePiece( 00506 '$locales = array( "'. join( '", "', $resourceData['locales'] ) . "\" );\n". 00507 '$oldLocale_'. $resourceData['uniqid']. ' = setlocale( LC_CTYPE, null );'. "\n". 00508 '$currentLocale_'. $resourceData['uniqid']. ' = setlocale( LC_CTYPE, $locales );'. "\n" 00509 ); 00510 } 00511 // $php->addCodePiece( "print( \"" . $resourceData['template-filename'] . " ($cacheFileName)<br/>\n\" );" ); 00512 if ( $useComments ) 00513 { 00514 $templateFilename = $resourceData['template-filename']; 00515 if ( file_exists( $templateFilename ) ) 00516 { 00517 $fd = fopen( $templateFilename, 'rb' ); 00518 if ( $fd ) 00519 { 00520 $templateText = fread( $fd, filesize( $templateFilename ) ); 00521 $php->addComment( "Original code:\n" . $templateText ); 00522 fclose( $fd ); 00523 } 00524 } 00525 } 00526 $php->addVariable( 'eZTemplateCompilerCodeDate', eZTemplateCompiler::CODE_DATE ); 00527 $php->addCodePiece( "if ( !defined( 'EZ_TEMPLATE_COMPILER_COMMON_CODE' ) )\n" ); 00528 $php->addInclude( eZTemplateCompiler::compilationDirectory() . '/common.php', eZPHPCreator::INCLUDE_ONCE_STATEMENT, array( 'spacing' => 4 ) ); 00529 $php->addSpace(); 00530 00531 if ( eZTemplateCompiler::isAccumulatorsEnabled() ) 00532 { 00533 $php->addCodePiece( "eZDebug::accumulatorStart( 'template_compiled_execution', 'template_total', 'Template compiled execution', true );\n" ); 00534 } 00535 if ( eZTemplateCompiler::isTimingPointsEnabled() ) 00536 { 00537 $php->addCodePiece( "eZDebug::addTimingPoint( 'Script start $cacheFileName' );\n" ); 00538 } 00539 00540 // $php->addCodePiece( "if ( !isset( \$vars ) )\n \$vars =& \$tpl->Variables;\n" ); 00541 // $php->addSpace(); 00542 00543 $parameters = array(); 00544 $textName = eZTemplateCompiler::currentTextName( $parameters ); 00545 00546 // $php->addCodePiece( "if ( !isset( \$$textName ) )\n \$$textName = '';\n" ); 00547 // $php->addSpace(); 00548 00549 $transformedTree = array(); 00550 eZTemplateCompiler::processNodeTransformation( $useComments, $php, $tpl, $rootNode, $resourceData, $transformedTree ); 00551 00552 if ( $ini->variable( 'TemplateSettings', 'TemplateOptimization' ) == 'enabled' ) 00553 { 00554 /* Retrieve class information for the attribute lookup table */ 00555 if ( isset( $resourceData['handler']->Keys ) and isset( $resourceData['handler']->Keys['class'] ) ) { 00556 $resourceData['class-info'] = eZTemplateOptimizer::fetchClassDeclaration( $resourceData['handler']->Keys['class'] ); 00557 } 00558 /* Run the optimizations */ 00559 eZTemplateOptimizer::optimize( $useComments, $php, $tpl, $transformedTree, $resourceData ); 00560 } 00561 00562 $staticTree = array(); 00563 eZTemplateCompiler::processStaticOptimizations( $useComments, $php, $tpl, $transformedTree, $resourceData, $staticTree ); 00564 00565 $combinedTree = array(); 00566 eZTemplateCompiler::processNodeCombining( $useComments, $php, $tpl, $staticTree, $resourceData, $combinedTree ); 00567 00568 $finalTree = $combinedTree; 00569 if ( !eZTemplateCompiler::isNodePlacementEnabled() ) 00570 eZTemplateCompiler::processRemoveNodePlacement( $finalTree ); 00571 00572 eZTemplateCompiler::generatePHPCode( $useComments, $php, $tpl, $finalTree, $resourceData ); 00573 00574 if ( eZTemplateCompiler::isTreeEnabled( 'final' ) ) 00575 $php->addVariable( 'finalTree', $finalTree, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) ); 00576 if ( eZTemplateCompiler::isTreeEnabled( 'combined' ) ) 00577 $php->addVariable( 'combinedTree', $combinedTree, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) ); 00578 if ( eZTemplateCompiler::isTreeEnabled( 'static' ) ) 00579 $php->addVariable( 'staticTree', $staticTree, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) ); 00580 if ( eZTemplateCompiler::isTreeEnabled( 'transformed' ) ) 00581 $php->addVariable( 'transformedTree', $transformedTree, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) ); 00582 if ( eZTemplateCompiler::isTreeEnabled( 'original' ) ) 00583 $php->addVariable( 'originalTree', $rootNode, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) ); 00584 00585 if ( eZTemplateCompiler::isTimingPointsEnabled() ) 00586 $php->addCodePiece( "eZDebug::addTimingPoint( 'Script end $cacheFileName' );\n" ); 00587 if ( eZTemplateCompiler::isAccumulatorsEnabled() ) 00588 $php->addCodePiece( "eZDebug::accumulatorStop( 'template_compiled_execution', true );\n" ); 00589 00590 if ( $resourceData['locales'] && count( $resourceData['locales'] ) ) 00591 { 00592 $php->addCodePiece( 00593 'setlocale( LC_CTYPE, $oldLocale_'. $resourceData['uniqid']. ' );'. "\n" 00594 ); 00595 } 00596 $php->addCodePiece('$setArray = $oldSetArray_'. $resourceData['uniqid']. ";\n"); 00597 00598 // Code to decrement include level of the templates 00599 $php->addCodePiece("\$tpl->Level--;\n" ); 00600 00601 /* 00602 // dump names of all defined PHP variables 00603 $php->addCodePiece( "echo \"defined vars in $resourceData[uri]:<br/><pre>\\n\";\n" ); 00604 $php->addCodePiece( 'foreach ( array_keys( get_defined_vars() ) as $var_name ) echo "- $var_name\n";' ); 00605 // dump tpl vars 00606 $php->addCodePiece( 'echo "\n-----------------------------------------------------------\nvars: ";' ); 00607 $php->addCodePiece( 'var_dump( $vars );' ); 00608 $php->addCodePiece( 'echo "</pre><hr/>\n";' ); 00609 */ 00610 00611 if ( !$resourceData['test-compile'] ) 00612 { 00613 $php->store( true ); 00614 } 00615 00616 return true; 00617 } 00618 00619 /*! 00620 Iterates over the template node tree and tries to combine multiple static siblings 00621 into one element. The original tree is specified in \a $node and the new 00622 combined tree will be present in \a $newNode. 00623 \sa processNodeCombiningChildren 00624 */ 00625 static function processNodeCombining( $useComments, $php, $tpl, &$node, &$resourceData, &$newNode ) 00626 { 00627 $nodeType = $node[0]; 00628 if ( $nodeType == eZTemplate::NODE_ROOT ) 00629 { 00630 $children = $node[1]; 00631 $newNode[0] = $nodeType; 00632 $newNode[1] = false; 00633 if ( $children ) 00634 { 00635 eZTemplateCompiler::processNodeCombiningChildren( $useComments, $php, $tpl, $children, $resourceData, $newNode ); 00636 } 00637 } 00638 else 00639 $tpl->error( 'processNodeCombining', "Unknown root type $nodeType, should be " . eZTemplate::NODE_ROOT ); 00640 } 00641 00642 /*! 00643 Does node combining on the children \a $nodeChildren. 00644 \sa processNodeCombining 00645 */ 00646 static function processNodeCombiningChildren( $useComments, $php, $tpl, &$nodeChildren, &$resourceData, &$parentNode ) 00647 { 00648 $newNodeChildren = array(); 00649 $lastNode = false; 00650 foreach ( $nodeChildren as $node ) 00651 { 00652 $newNode = false; 00653 if ( !isset( $node[0] ) ) 00654 continue; 00655 $nodeType = $node[0]; 00656 if ( $nodeType == eZTemplate::NODE_ROOT ) 00657 { 00658 $children = $node[1]; 00659 $newNode = array( $nodeType, 00660 false ); 00661 if ( $children ) 00662 { 00663 eZTemplateCompiler::processNodeCombiningChildren( $useComments, $php, $tpl, $children, $resourceData, $newNode ); 00664 } 00665 } 00666 else if ( $nodeType == eZTemplate::NODE_TEXT ) 00667 { 00668 $text = $node[2]; 00669 $placement = $node[3]; 00670 00671 $newNode = array( $nodeType, 00672 false, 00673 $text, 00674 $placement ); 00675 eZTemplateCompiler::combineStaticNodes( $tpl, $resourceData, $lastNode, $newNode ); 00676 } 00677 else if ( $nodeType == eZTemplate::NODE_VARIABLE ) 00678 { 00679 $variableCustom = $node[1]; 00680 $variableData = $node[2]; 00681 $variablePlacement = $node[3]; 00682 $variableParameters = false; 00683 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 00684 $variableData, $variablePlacement, 00685 $resourceData ); 00686 $newNode = $node; 00687 $newNode[1] = $variableCustom; 00688 unset( $dataInspection ); 00689 eZTemplateCompiler::combineStaticNodes( $tpl, $resourceData, $lastNode, $newNode ); 00690 } 00691 else if ( $nodeType == eZTemplate::NODE_FUNCTION ) 00692 { 00693 $functionChildren = $node[1]; 00694 $functionName = $node[2]; 00695 $functionParameters = $node[3]; 00696 $functionPlacement = $node[4]; 00697 00698 $newNode = array( $nodeType, 00699 false, 00700 $functionName, 00701 $functionParameters, 00702 $functionPlacement ); 00703 if ( isset( $node[5] ) ) 00704 $newNode[5] = $node[5]; 00705 00706 if ( is_array( $functionChildren ) ) 00707 { 00708 eZTemplateCompiler::processNodeCombiningChildren( $useComments, $php, $tpl, 00709 $functionChildren, $resourceData, $newNode ); 00710 } 00711 00712 } 00713 else 00714 $newNode = $node; 00715 if ( $lastNode != false ) 00716 { 00717 $newNodeChildren[] = $lastNode; 00718 $lastNode = false; 00719 } 00720 if ( $newNode != false ) 00721 $lastNode = $newNode; 00722 } 00723 if ( $lastNode != false ) 00724 { 00725 $newNodeChildren[] = $lastNode; 00726 $lastNode = false; 00727 } 00728 $parentNode[1] = $newNodeChildren; 00729 } 00730 00731 /*! 00732 Tries to combine the node \a $lastNode and the node \a $newNode 00733 into one new text node. If possible the new node is created in \a $newNode 00734 and \a $lastNode will be set to \c false. 00735 Combining nodes only works for text nodes and variable nodes without 00736 variable lookup, attributes and operators. 00737 */ 00738 static function combineStaticNodes( $tpl, &$resourceData, &$lastNode, &$newNode ) 00739 { 00740 if ( $lastNode == false or 00741 $newNode == false ) 00742 return false; 00743 $lastNodeType = $lastNode[0]; 00744 $newNodeType = $newNode[0]; 00745 if ( !in_array( $lastNodeType, array( eZTemplate::NODE_TEXT, 00746 eZTemplate::NODE_VARIABLE ) ) or 00747 !in_array( $newNodeType, array( eZTemplate::NODE_TEXT, 00748 eZTemplate::NODE_VARIABLE ) ) ) 00749 return false; 00750 if ( $lastNodeType == eZTemplate::NODE_VARIABLE ) 00751 { 00752 if ( is_array( $lastNode[1] ) ) 00753 return false; 00754 $lastDataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 00755 $lastNode[2], $lastNode[3], 00756 $resourceData ); 00757 if ( !$lastDataInspection['is-constant'] or 00758 $lastDataInspection['is-variable'] or 00759 $lastDataInspection['has-attributes'] or 00760 $lastDataInspection['has-operators'] ) 00761 return false; 00762 if ( isset( $lastNode[4] ) and 00763 isset( $lastNode[4]['text-result'] ) and 00764 !$lastNode[4]['text-result'] ) 00765 return false; 00766 } 00767 if ( $newNodeType == eZTemplate::NODE_VARIABLE ) 00768 { 00769 if ( is_array( $newNode[1] ) ) 00770 return false; 00771 $newDataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 00772 $newNode[2], $newNode[3], 00773 $resourceData ); 00774 if ( !$newDataInspection['is-constant'] or 00775 $newDataInspection['is-variable'] or 00776 $newDataInspection['has-attributes'] or 00777 $newDataInspection['has-operators'] ) 00778 return false; 00779 if ( isset( $newNode[4] ) and 00780 isset( $newNode[4]['text-result'] ) and 00781 !$newNode[4]['text-result'] ) 00782 return false; 00783 if ( isset( $newNode[1] ) and 00784 $newNode[1] !== false ) 00785 return false; 00786 } 00787 $textElements = array(); 00788 $lastNodeData = eZTemplateCompiler::staticNodeData( $lastNode ); 00789 $newNodeData = eZTemplateCompiler::staticNodeData( $newNode ); 00790 $tpl->appendElementText( $textElements, $lastNodeData, false, false ); 00791 $tpl->appendElementText( $textElements, $newNodeData, false, false ); 00792 $newData = implode( '', $textElements ); 00793 $newPlacement = $lastNode[3]; 00794 if ( !is_array( $newPlacement ) ) 00795 { 00796 $newPlacement = $newNode[3]; 00797 } 00798 else 00799 { 00800 $newPlacement[1][0] = $newNode[3][1][0]; // Line end 00801 $newPlacement[1][1] = $newNode[3][1][1]; // Column end 00802 $newPlacement[1][2] = $newNode[3][1][2]; // Position end 00803 } 00804 $lastNode = false; 00805 $newNode = array( eZTemplate::NODE_TEXT, 00806 false, 00807 $newData, 00808 $newPlacement ); 00809 } 00810 00811 /*! 00812 \return the static data for the node \a $node or \c false if 00813 no data could be fetched. 00814 Will only return data from text nodes and variables nodes 00815 without variable lookup, attribute lookup or operators. 00816 */ 00817 static function staticNodeData( $node ) 00818 { 00819 $nodeType = $node[0]; 00820 if ( $nodeType == eZTemplate::NODE_TEXT ) 00821 { 00822 return $node[2]; 00823 } 00824 else if ( $nodeType == eZTemplate::NODE_VARIABLE ) 00825 { 00826 $data = $node[2]; 00827 if ( is_array( $data ) and 00828 count( $data ) > 0 ) 00829 { 00830 $dataType = $data[0][0]; 00831 if ( $dataType == eZTemplate::TYPE_STRING or 00832 $dataType == eZTemplate::TYPE_NUMERIC or 00833 $dataType == eZTemplate::TYPE_IDENTIFIER or 00834 $dataType == eZTemplate::TYPE_ARRAY or 00835 $dataType == eZTemplate::TYPE_BOOLEAN ) 00836 { 00837 return $data[0][1]; 00838 } 00839 } 00840 } 00841 return null; 00842 } 00843 00844 /*! 00845 Iterates over the items in the tree \a $node and tries to extract static data 00846 from operators which supports it. 00847 */ 00848 static function processStaticOptimizations( $useComments, $php, $tpl, &$node, &$resourceData, &$newNode ) 00849 { 00850 $nodeType = $node[0]; 00851 if ( $nodeType == eZTemplate::NODE_ROOT ) 00852 { 00853 $children = $node[1]; 00854 $newNode[0] = $nodeType; 00855 $newNode[1] = false; 00856 if ( $children ) 00857 { 00858 $newNode[1] = array(); 00859 foreach ( $children as $child ) 00860 { 00861 $newChild = array(); 00862 eZTemplateCompiler::processStaticOptimizations( $useComments, $php, $tpl, $child, $resourceData, $newChild ); 00863 $newNode[1][] = $newChild; 00864 } 00865 } 00866 } 00867 else if ( $nodeType == eZTemplate::NODE_TEXT ) 00868 { 00869 $text = $node[2]; 00870 $placement = $node[3]; 00871 00872 $newNode[0] = $nodeType; 00873 $newNode[1] = false; 00874 $newNode[2] = $text; 00875 $newNode[3] = $placement; 00876 } 00877 else if ( $nodeType == eZTemplate::NODE_VARIABLE ) 00878 { 00879 $variableCustom = $node[1]; 00880 $variableData = $node[2]; 00881 $variablePlacement = $node[3]; 00882 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 00883 $variableData, $variablePlacement, 00884 $resourceData ); 00885 if ( isset( $dataInspection['new-data'] ) ) 00886 { 00887 $variableData = $dataInspection['new-data']; 00888 } 00889 $newNode = $node; 00890 $newNode[1] = $variableCustom; 00891 $newNode[2] = $variableData; 00892 unset( $dataInspection ); 00893 } 00894 else if ( $nodeType == eZTemplate::NODE_FUNCTION ) 00895 { 00896 $functionChildren = $node[1]; 00897 $functionName = $node[2]; 00898 $functionParameters = $node[3]; 00899 $functionPlacement = $node[4]; 00900 00901 $newFunctionChildren = array(); 00902 if ( is_array( $functionChildren ) ) 00903 { 00904 foreach ( $functionChildren as $functionChild ) 00905 { 00906 $newChild = array(); 00907 eZTemplateCompiler::processStaticOptimizations( $useComments, $php, $tpl, 00908 $functionChild, $resourceData, $newChild ); 00909 $newFunctionChildren[] = $newChild; 00910 } 00911 $functionChildren = $newFunctionChildren; 00912 } 00913 00914 $newFunctionParameters = array(); 00915 if ( $functionParameters ) 00916 { 00917 foreach ( $functionParameters as $functionParameterName => $functionParameterData ) 00918 { 00919 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 00920 $functionParameterData, false, 00921 $resourceData ); 00922 if ( isset( $dataInspection['new-data'] ) ) 00923 { 00924 $functionParameterData = $dataInspection['new-data']; 00925 } 00926 $newFunctionParameters[$functionParameterName] = $functionParameterData; 00927 } 00928 $functionParameters = $newFunctionParameters; 00929 } 00930 00931 $newNode[0] = $nodeType; 00932 $newNode[1] = $functionChildren; 00933 $newNode[2] = $functionName; 00934 $newNode[3] = $functionParameters; 00935 $newNode[4] = $functionPlacement; 00936 if ( isset( $node[5] ) ) 00937 $newNode[5] = $node[5]; 00938 } 00939 else 00940 $newNode = $node; 00941 } 00942 00943 /*! 00944 Iterates over the template node tree \a $node and returns a new transformed 00945 tree in \a $newNode. 00946 \sa processNodeTransformationRoot, processNodeTransformationChild 00947 */ 00948 static function processNodeTransformation( $useComments, $php, $tpl, &$node, &$resourceData, &$newNode ) 00949 { 00950 $newNode = eZTemplateCompiler::processNodeTransformationRoot( $useComments, $php, $tpl, $node, $resourceData ); 00951 } 00952 00953 /*! 00954 Iterates over the nodes \a $nodes and does transformation on them. 00955 \sa processNodeTransformationChildren 00956 \note This method can be called from operator and functions as long as they have the \a $privateData parameter. 00957 */ 00958 static function processNodeTransformationNodes( $tpl, &$node, &$nodes, &$privateData ) 00959 { 00960 $useComments = $privateData['use-comments']; 00961 $php =& $privateData['php-creator']; 00962 $resourceData =& $privateData['resource-data']; 00963 return eZTemplateCompiler::processNodeTransformationChildren( $useComments, $php, $tpl, $node, $nodes, $resourceData ); 00964 } 00965 00966 /*! 00967 Iterates over the children \a $children and does transformation on them. 00968 \sa processNodeTransformation, processNodeTransformationChild 00969 */ 00970 static function processNodeTransformationChildren( $useComments, $php, $tpl, &$node, &$children, &$resourceData ) 00971 { 00972 if ( $children ) 00973 { 00974 $newChildren = array(); 00975 foreach ( $children as $childNode ) 00976 { 00977 $newChildNode = eZTemplateCompiler::processNodeTransformationChild( $useComments, $php, $tpl, $childNode, $resourceData ); 00978 if ( !$newChildNode ) 00979 $newChildren[] = $childNode; 00980 else 00981 $newChildren = array_merge( $newChildren, $newChildNode ); 00982 } 00983 if ( count( $newChildren ) > 0 ) 00984 return $newChildren; 00985 } 00986 return $children; 00987 } 00988 00989 /*! 00990 Iterates over the children of the root node \a $node and does transformation on them. 00991 \sa processNodeTransformation, processNodeTransformationChild 00992 */ 00993 static function processNodeTransformationRoot( $useComments, $php, $tpl, &$node, &$resourceData ) 00994 { 00995 $nodeType = $node[0]; 00996 if ( $nodeType == eZTemplate::NODE_ROOT ) 00997 { 00998 $children = $node[1]; 00999 $newNode = array( $nodeType, 01000 false ); 01001 if ( $children ) 01002 { 01003 $newChildren = array(); 01004 foreach ( $children as $childNode ) 01005 { 01006 $newChildNode = eZTemplateCompiler::processNodeTransformationChild( $useComments, $php, $tpl, $childNode, $resourceData ); 01007 if ( !$newChildNode ) 01008 $newChildren[] = $childNode; 01009 else 01010 $newChildren = array_merge( $newChildren, $newChildNode ); 01011 } 01012 if ( count( $newChildren ) > 0 ) 01013 $newNode[1] = $newChildren; 01014 } 01015 return $newNode; 01016 } 01017 else 01018 $tpl->error( 'processNodeTransformation', "Unknown root type $nodeType, should be " . eZTemplate::NODE_ROOT ); 01019 return false; 01020 } 01021 01022 /*! 01023 Iterates over the children of the function node \a $node and transforms the tree. 01024 If the node is not a function it will return \c false. 01025 \sa processNodeTransformationRoot, processNodeTransformationChild 01026 */ 01027 static function processNodeTransformationChild( $useComments, $php, $tpl, &$node, &$resourceData ) 01028 { 01029 $nodeType = $node[0]; 01030 if ( $nodeType == eZTemplate::NODE_FUNCTION ) 01031 { 01032 $nodeCopy = $node; 01033 $functionChildren = $node[1]; 01034 $functionName = $node[2]; 01035 $functionParameters = $node[3]; 01036 $functionPlacement = $node[4]; 01037 if ( !isset( $tpl->Functions[$functionName] ) ) 01038 return false; 01039 01040 if ( is_array( $tpl->Functions[$functionName] ) ) 01041 { 01042 $tpl->loadAndRegisterFunctions( $tpl->Functions[$functionName] ); 01043 } 01044 $functionObject =& $tpl->Functions[$functionName]; 01045 if ( is_object( $functionObject ) ) 01046 { 01047 $hasTransformationSupport = false; 01048 $transformChildren = true; 01049 $transformParameters = false; 01050 if ( method_exists( $functionObject, 'functionTemplateHints' ) ) 01051 { 01052 $hints = $functionObject->functionTemplateHints(); 01053 if ( isset( $hints[$functionName] ) and 01054 isset( $hints[$functionName]['tree-transformation'] ) and 01055 $hints[$functionName]['tree-transformation'] ) 01056 $hasTransformationSupport = true; 01057 if ( isset( $hints[$functionName] ) and 01058 isset( $hints[$functionName]['transform-children'] ) ) 01059 $transformChildren = $hints[$functionName]['transform-children']; 01060 if ( isset( $hints[$functionName] ) and 01061 isset( $hints[$functionName]['transform-parameters'] ) ) 01062 $transformParameters = $hints[$functionName]['transform-parameters']; 01063 } 01064 if ( $hasTransformationSupport and 01065 method_exists( $functionObject, 'templateNodeTransformation' ) ) 01066 { 01067 if ( $transformChildren and 01068 $functionChildren ) 01069 { 01070 $newChildren = array(); 01071 foreach ( $functionChildren as $childNode ) 01072 { 01073 $newChildNode = eZTemplateCompiler::processNodeTransformationChild( $useComments, $php, $tpl, $childNode, $resourceData ); 01074 if ( !$newChildNode ) 01075 $newChildren[] = $childNode; 01076 else if ( !is_array( $newChildNode ) ) 01077 $newChildren[] = $newChildNode; 01078 else 01079 $newChildren = array_merge( $newChildren, $newChildNode ); 01080 } 01081 if ( count( $newChildren ) > 0 ) 01082 $node[1] = $newChildren; 01083 } 01084 01085 if ( $transformParameters and 01086 $functionParameters ) 01087 { 01088 $newParameters = array(); 01089 foreach ( $functionParameters as $parameterName => $parameterElementList ) 01090 { 01091 $elementTree = $parameterElementList; 01092 $elementList = $elementTree; 01093 $newParamNode = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node, 01094 $elementTree, $elementList, $resourceData ); 01095 if ( !$newParamNode || !is_array( $newParamNode ) ) 01096 $newParameters[$parameterName] = $parameterElementList; 01097 else 01098 $newParameters[$parameterName] = $newParamNode; 01099 } 01100 if ( count( $newParameters ) > 0 ) 01101 { 01102 $node[3] = $newParameters; 01103 $functionParameters = $newParameters; 01104 } 01105 } 01106 01107 $privateData = array( 'use-comments' => $useComments, 01108 'php-creator' => $php, 01109 'resource-data' => &$resourceData ); 01110 $newNodes = $functionObject->templateNodeTransformation( $functionName, $node, 01111 $tpl, $functionParameters, $privateData ); 01112 unset( $privateData ); 01113 if ( !$newNodes ) 01114 { 01115 $node = $nodeCopy; 01116 $node[1] = $functionChildren; 01117 return false; 01118 return $node; 01119 } 01120 return $newNodes; 01121 } 01122 } 01123 else if ( $resourceData['test-compile'] ) 01124 { 01125 $tpl->warning( '', "Function '$functionName' is not registered.", $functionPlacement ); 01126 } 01127 01128 return false; 01129 } 01130 else if ( $nodeType == eZTemplate::NODE_VARIABLE ) 01131 { 01132 $elementTree = $node[2]; 01133 $elementList = $elementTree; 01134 01135 $newParameterElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node, 01136 $elementTree, $elementList, $resourceData ); 01137 if ( $newParameterElements ) 01138 { 01139 $newNode = $node; 01140 $newNode[2] = $newParameterElements; 01141 $newNodes = array( $newNode ); 01142 return $newNodes; 01143 } 01144 } 01145 else if ( $nodeType == eZTemplate::NODE_ROOT ) 01146 { 01147 return eZTemplateCompiler::processNodeTransformationRoot( $useComments, $php, $tpl, $node, $resourceData ); 01148 } 01149 else 01150 return false; 01151 } 01152 01153 /*! 01154 Iterates over the element list \a $elements and transforms them. 01155 \sa processElementTransformationChild 01156 */ 01157 static function processElementTransformationList( $tpl, &$node, $elements, &$privateData ) 01158 { 01159 $useComments = $privateData['use-comments']; 01160 $php =& $privateData['php-creator']; 01161 $resourceData =& $privateData['resource-data']; 01162 $elementTree = $elements; 01163 $newElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node, 01164 $elementTree, $elements, $resourceData ); 01165 if ( $newElements ) 01166 return $newElements; 01167 return $elements; 01168 } 01169 01170 /*! 01171 Iterates over the children of the function node \a $node and transforms the tree. 01172 If the node is not a function it will return \c false. 01173 \sa processNodeTransformationRoot, processNodeTransformationChild 01174 */ 01175 static function processElementTransformationChild( $useComments, $php, $tpl, &$node, 01176 $elementTree, $elementList, &$resourceData ) 01177 { 01178 $count = count( $elementList ); 01179 $lastElement = null; 01180 $newElementList = array(); 01181 for ( $i = 0; $i < $count; ++$i ) 01182 { 01183 $element =& $elementList[$i]; 01184 $elementType = $element[0]; 01185 if ( $elementType == eZTemplate::TYPE_OPERATOR ) 01186 { 01187 $operatorName = $element[1][0]; 01188 $operatorParameters = array_slice( $element[1], 1 ); 01189 if ( !isset( $tpl->Operators[$operatorName] ) ) 01190 return false; 01191 01192 if ( is_array( $tpl->Operators[$operatorName] ) ) 01193 { 01194 $tpl->loadAndRegisterOperators( $tpl->Operators[$operatorName] ); 01195 } 01196 $operatorObject =& $tpl->Operators[$operatorName]; 01197 if ( is_object( $operatorObject ) ) 01198 { 01199 $hasTransformationSupport = false; 01200 $transformParameters = false; 01201 $inputAsParameter = false; 01202 $knownType = 'static'; 01203 if ( method_exists( $operatorObject, 'operatorTemplateHints' ) ) 01204 { 01205 $hints = $operatorObject->operatorTemplateHints(); 01206 if ( isset( $hints[$operatorName] ) and 01207 isset( $hints[$operatorName]['element-transformation'] ) and 01208 $hints[$operatorName]['element-transformation'] ) 01209 { 01210 $hasTransformationSupport = true; 01211 } 01212 01213 if ( $hasTransformationSupport and 01214 isset( $hints[$operatorName]['element-transformation-func'] ) ) 01215 { 01216 $transformationMethod = $hints[$operatorName]['element-transformation-func']; 01217 } 01218 else 01219 { 01220 $transformationMethod = 'templateElementTransformation'; 01221 } 01222 01223 if ( isset( $hints[$operatorName] ) and 01224 isset( $hints[$operatorName]['transform-parameters'] ) ) 01225 { 01226 $transformParameters = $hints[$operatorName]['transform-parameters']; 01227 } 01228 01229 if ( isset( $hints[$operatorName] ) and 01230 isset( $hints[$operatorName]['input-as-parameter'] ) ) 01231 { 01232 $inputAsParameter = $hints[$operatorName]['input-as-parameter']; 01233 } 01234 01235 if ( isset( $hints[$operatorName]['output'] ) and !$hints[$operatorName]['output'] ) 01236 { 01237 $knownType = 'null'; 01238 } 01239 else if ( isset( $hints[$operatorName]['output-type'] ) ) 01240 { 01241 $knownType = $hints[$operatorName]['output-type']; 01242 } 01243 } 01244 if ( $hasTransformationSupport and 01245 method_exists( $operatorObject, $transformationMethod ) ) 01246 { 01247 $resetNewElementList = false; 01248 if ( $transformParameters ) 01249 { 01250 $newParameters = array(); 01251 if ( $inputAsParameter ) 01252 { 01253 $newParameterElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node, 01254 $elementTree, $newElementList, $resourceData ); 01255 if ( count( $newParameterElements ) > 0 or 01256 $inputAsParameter === 'always' ) 01257 { 01258 $newParameters[] = $newParameterElements; 01259 $resetNewElementList = true; 01260 } 01261 } 01262 01263 foreach ( $operatorParameters as $operatorParameter ) 01264 { 01265 $newParameterElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node, 01266 $elementTree, $operatorParameter, $resourceData ); 01267 if ( !$newParameterElements ) 01268 $newParameters[] = $operatorParameter; 01269 else 01270 $newParameters[] = $newParameterElements; 01271 } 01272 $operatorParameters = $newParameters; 01273 } 01274 01275 $newElements = $operatorObject->$transformationMethod( $operatorName, $node, $tpl, $resourceData, 01276 $element, $lastElement, $elementList, $elementTree, 01277 $operatorParameters ); 01278 if ( is_array( $newElements ) ) 01279 { 01280 if ( $resetNewElementList ) 01281 { 01282 $newElementList = $newElements; 01283 } 01284 else 01285 { 01286 $newElementList = array_merge( $newElementList, $newElements ); 01287 } 01288 } 01289 else 01290 { 01291 $newElementList[] = $element; 01292 } 01293 } 01294 else 01295 { 01296 $newElementList[] = $element; 01297 } 01298 } 01299 else if ( $resourceData['test-compile'] ) 01300 { 01301 $tpl->warning( '', "Operator '$operatorName' is not registered." ); 01302 } 01303 } 01304 else 01305 { 01306 $newElementList[] = $element; 01307 } 01308 $lastElement = $element; 01309 } 01310 return $newElementList; 01311 } 01312 01313 /*! 01314 Iterates over the node tree and removes all placement information. 01315 */ 01316 static function processRemoveNodePlacement( &$node ) 01317 { 01318 $nodeType = $node[0]; 01319 if ( $nodeType == eZTemplate::NODE_ROOT ) 01320 { 01321 $nodeChildren =& $node[1]; 01322 for ( $i = 0; $i < count( $nodeChildren ); ++$i ) 01323 { 01324 $nodeChild =& $nodeChildren[$i]; 01325 eZTemplateCompiler::processRemoveNodePlacement( $nodeChild ); 01326 } 01327 } 01328 else if ( $nodeType == eZTemplate::NODE_TEXT ) 01329 { 01330 $node[3] = false; 01331 } 01332 else if ( $nodeType == eZTemplate::NODE_VARIABLE ) 01333 { 01334 $node[3] = false; 01335 } 01336 else if ( $nodeType == eZTemplate::NODE_FUNCTION ) 01337 { 01338 $node[4] = false; 01339 $nodeChildren =& $node[1]; 01340 if ( $nodeChildren ) 01341 { 01342 for ( $i = 0; $i < count( $nodeChildren ); ++$i ) 01343 { 01344 $nodeChild =& $nodeChildren[$i]; 01345 eZTemplateCompiler::processRemoveNodePlacement( $nodeChild ); 01346 } 01347 } 01348 } 01349 else if ( $nodeType == eZTemplate::NODE_OPERATOR ) 01350 { 01351 } 01352 } 01353 01354 /*! 01355 Looks over the variable data \a $variableData and returns an array with 01356 information on the structure. 01357 The following entries are generated. 01358 - is-constant - true if the variable data contains constant data like text and numerics 01359 - is-variable - true if the variable data is a variable lookup 01360 - has-operators - true if operators are present 01361 - has-attributes - true if attributes are used 01362 */ 01363 static function inspectVariableData( $tpl, $variableData, $variablePlacement, &$resourceData ) 01364 { 01365 $dataInspection = array( 'is-constant' => false, 01366 'is-variable' => false, 01367 'has-operators' => false, 01368 'has-attributes' => false ); 01369 if ( !is_array( $variableData ) ) 01370 return $dataInspection; 01371 $newVariableData = array(); 01372 // Static optimizations, the following items are done: 01373 // - Recognize static data 01374 // - Extract static data, if possible, from operators 01375 // - Remove parameters and input which not be used. 01376 foreach ( $variableData as $variableItem ) 01377 { 01378 $variableItemType = $variableItem[0]; 01379 $variableItemData = $variableItem[1]; 01380 $variableItemPlacement = $variableItem[2]; 01381 if ( $variableItemType == eZTemplate::TYPE_STRING or 01382 $variableItemType == eZTemplate::TYPE_IDENTIFIER ) 01383 { 01384 $dataInspection['is-constant'] = true; 01385 $dataInspection['is-variable'] = false; 01386 $newVariableData[] = $variableItem; 01387 } 01388 else if ( $variableItemType == eZTemplate::TYPE_NUMERIC ) 01389 { 01390 $dataInspection['is-constant'] = true; 01391 $dataInspection['is-variable'] = false; 01392 $newVariableData[] = $variableItem; 01393 } 01394 else if ( $variableItemType == eZTemplate::TYPE_BOOLEAN ) 01395 { 01396 $dataInspection['is-constant'] = true; 01397 $dataInspection['is-variable'] = false; 01398 $newVariableData[] = $variableItem; 01399 } 01400 else if ( $variableItemType == eZTemplate::TYPE_DYNAMIC_ARRAY ) 01401 { 01402 $dataInspection['is-constant'] = false; 01403 $dataInspection['is-variable'] = true; 01404 $newVariableData[] = $variableItem; 01405 } 01406 else if ( $variableItemType == eZTemplate::TYPE_ARRAY ) 01407 { 01408 $dataInspection['is-constant'] = true; 01409 $dataInspection['is-variable'] = false; 01410 $newVariableData[] = $variableItem; 01411 } 01412 else if ( $variableItemType == eZTemplate::TYPE_VARIABLE ) 01413 { 01414 $dataInspection['is-constant'] = false; 01415 $dataInspection['is-variable'] = true; 01416 $newVariableData[] = $variableItem; 01417 } 01418 else if ( $variableItemType == eZTemplate::TYPE_ATTRIBUTE ) 01419 { 01420 $dataInspection['has-attributes'] = true; 01421 $newDataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 01422 $variableItemData, $variableItemPlacement, 01423 $resourceData ); 01424 if ( isset( $newDataInspection['new-data'] ) ) 01425 { 01426 $variableItemData = $newDataInspection['new-data']; 01427 } 01428 $variableItem[1] = $variableItemData; 01429 unset( $newDataInspection ); 01430 $newVariableData[] = $variableItem; 01431 } 01432 else if ( $variableItemType == eZTemplate::TYPE_OPERATOR ) 01433 { 01434 $dataInspection['has-operators'] = true; 01435 $operatorName = $variableItemData[0]; 01436 $operatorHint = eZTemplateCompiler::operatorHint( $tpl, $operatorName ); 01437 $newVariableItem = $variableItem; 01438 if ( $operatorHint and 01439 isset( $operatorHint['input'] ) and 01440 isset( $operatorHint['output'] ) and 01441 isset( $operatorHint['parameters'] ) ) 01442 { 01443 if ( !$operatorHint['input'] and 01444 $operatorHint['output'] ) 01445 $newVariableData = array(); 01446 if ( !isset( $operatorHint) or !$operatorHint['parameters'] ) 01447 $newVariableItem[1] = array( $operatorName ); 01448 if ( isset ( $operatorHint['static'] ) and 01449 $operatorHint['static'] ) 01450 { 01451 $operatorStaticData = eZTemplateCompiler::operatorStaticData( $tpl, $operatorName ); 01452 $newVariableItem = eZTemplateCompiler::createStaticVariableData( $tpl, $operatorStaticData, $variableItemPlacement ); 01453 $dataInspection['is-constant'] = true; 01454 $dataInspection['is-variable'] = false; 01455 $dataInspection['has-operators'] = false; 01456 } 01457 } 01458 if ( $newVariableItem[0] == eZTemplate::TYPE_OPERATOR ) 01459 { 01460 $tmpVariableItem = $newVariableItem[1]; 01461 $newVariableItem[1] = array( $operatorName ); 01462 for ( $i = 1; $i < count( $tmpVariableItem ); ++$i ) 01463 { 01464 $operatorParameter = $tmpVariableItem[$i]; 01465 $newDataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 01466 $operatorParameter, false, 01467 $resourceData ); 01468 if ( isset( $newDataInspection['new-data'] ) ) 01469 { 01470 $operatorParameter = $newDataInspection['new-data']; 01471 } 01472 $newVariableItem[1][] = $operatorParameter; 01473 } 01474 } 01475 $newVariableData[] = $newVariableItem; 01476 } 01477 else if ( $variableItemType == eZTemplate::TYPE_VOID ) 01478 { 01479 $tpl->warning( 'TemplateCompiler', "Void datatype should not be used, ignoring it" ); 01480 } 01481 else if ( $variableItemType > eZTemplate::TYPE_INTERNAL and 01482 $variableItemType < eZTemplate::TYPE_INTERNAL_STOP ) 01483 { 01484 $newVariableData[] = $variableItem; 01485 } 01486 else 01487 { 01488 $tpl->warning( 'TemplateCompiler', "Unknown data type $variableItemType, ignoring it" ); 01489 } 01490 } 01491 $dataInspection['new-data'] = $newVariableData; 01492 return $dataInspection; 01493 } 01494 01495 /*! 01496 \return the operator hint for the operator \a $operatorName, or \c false if 01497 the operator does not exist or has no hints. 01498 */ 01499 static function operatorHint( $tpl, $operatorName ) 01500 { 01501 if ( isset( $tpl->Operators[$operatorName] ) and 01502 is_array( $tpl->Operators[$operatorName] ) ) 01503 { 01504 $tpl->loadAndRegisterOperators( $tpl->Operators[$operatorName] ); 01505 } 01506 $operatorObject =& $tpl->Operators[$operatorName]; 01507 $operatorHint = false; 01508 if ( is_object( $operatorObject ) ) 01509 { 01510 if ( method_exists( $operatorObject, 'operatorTemplateHints' ) ) 01511 { 01512 $operatorHintArray = $operatorObject->operatorTemplateHints(); 01513 if ( isset( $operatorHintArray[$operatorName] ) ) 01514 { 01515 $operatorHint = $operatorHintArray[$operatorName]; 01516 } 01517 } 01518 } 01519 else if ( $tpl->testCompile() ) 01520 { 01521 $tpl->warning( '', "Operator '$operatorName' is not registered." ); 01522 } 01523 01524 return $operatorHint; 01525 } 01526 01527 /*! 01528 \return static data from operators which support returning static data, 01529 or \c null if no static data could be extracted. 01530 The operator is specified in \a $operatorName. 01531 01532 */ 01533 static function operatorStaticData( $tpl, $operatorName ) 01534 { 01535 if ( is_array( $tpl->Operators[$operatorName] ) ) 01536 { 01537 $tpl->loadAndRegisterOperators( $tpl->Operators[$operatorName] ); 01538 } 01539 $operatorObject =& $tpl->Operators[$operatorName]; 01540 $operatorData = null; 01541 if ( is_object( $operatorObject ) ) 01542 { 01543 if ( method_exists( $operatorObject, 'operatorCompiledStaticData' ) ) 01544 { 01545 $operatorData = $operatorObject->operatorCompiledStaticData( $operatorName ); 01546 } 01547 } 01548 else if ( $tpl->testCompile() ) 01549 { 01550 $tpl->warning( '', "Operator '$operatorName' is not registered." ); 01551 } 01552 01553 return $operatorData; 01554 } 01555 01556 /*! 01557 Creates a variable data element for the data \a $staticData and returns it. 01558 The type of element depends on the type of the data, strings and booleans 01559 are returned as eZTemplate::TYPE_STRING and eZTemplate::TYPE_NUMERIC while other 01560 types are turned into text and returned as eZTemplate::TYPE_STRING. 01561 */ 01562 static function createStaticVariableData( $tpl, $staticData, $variableItemPlacement ) 01563 { 01564 if ( is_string( $staticData ) ) 01565 return array( eZTemplate::TYPE_STRING, 01566 $staticData, 01567 $variableItemPlacement ); 01568 else if ( is_bool( $staticData ) ) 01569 return array( eZTemplate::TYPE_BOOLEAN, 01570 $staticData, 01571 $variableItemPlacement ); 01572 else if ( is_bool( $staticData ) or is_numeric( $staticData ) ) 01573 return array( eZTemplate::TYPE_NUMERIC, 01574 $staticData, 01575 $variableItemPlacement ); 01576 else if ( is_array( $staticData ) ) 01577 return array( eZTemplate::TYPE_ARRAY, 01578 $staticData, 01579 $variableItemPlacement ); 01580 else 01581 return array( eZTemplate::TYPE_STRING, 01582 "$staticData", 01583 $variableItemPlacement ); 01584 } 01585 01586 /*! 01587 Opens the template files specified in \a $placementData 01588 and fetches the text portion defined by the 01589 start and end position. The text is returned or \c null if the 01590 text could not be fetched. 01591 */ 01592 static function fetchTemplatePiece( $placementData ) 01593 { 01594 if ( !isset( $placementData[0] ) or 01595 !isset( $placementData[1] ) or 01596 !isset( $placementData[2] ) ) 01597 return null; 01598 $file = $placementData[2]; 01599 $startPosition = $placementData[0][2]; 01600 $endPosition = $placementData[1][2]; 01601 $length = $endPosition - $startPosition; 01602 if ( file_exists( $file ) ) 01603 { 01604 if ( $length > 0 ) 01605 { 01606 $fd = fopen( $file, 'rb' ); 01607 fseek( $fd, $startPosition ); 01608 $text = fread( $fd, $length ); 01609 fclose( $fd ); 01610 return $text; 01611 } 01612 else 01613 { 01614 return ''; 01615 } 01616 } 01617 return null; 01618 } 01619 01620 /*! 01621 Creates the common.php file which has common functions for compiled templates. 01622 If the file already exists if will not create it. 01623 */ 01624 static function createCommonCompileTemplate() 01625 { 01626 $php = new eZPHPCreator( eZTemplateCompiler::compilationDirectory(), 'common.php' ); 01627 if ( $php->exists() ) 01628 return; 01629 01630 $php->addComment( "This file contains functions which are common to all compiled templates.\n\n" . 01631 'NOTE: This file is autogenerated and should not be modified, any changes will be lost!' ); 01632 $php->addSpace(); 01633 $php->addDefine( 'EZ_TEMPLATE_COMPILER_COMMON_CODE', true ); 01634 $php->addSpace(); 01635 01636 $namespaceStack = array(); 01637 $php->addCodePiece( "if ( !isset( \$namespaceStack ) )\n" ); 01638 $php->addVariable( 'namespaceStack', $namespaceStack, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'spacing' => 4 ) ); 01639 $php->addSpace(); 01640 01641 $lbracket = '{'; 01642 $rbracket = '}'; 01643 $initText = "if ( !function_exists( 'compiledfetchvariable' ) ) 01644 $lbracket 01645 function compiledFetchVariable( \$vars, \$namespace, \$name ) 01646 $lbracket 01647 \$exists = ( array_key_exists( \$namespace, \$vars ) and 01648 array_key_exists( \$name, \$vars[\$namespace] ) ); 01649 if ( \$exists ) 01650 $lbracket 01651 return \$vars[\$namespace][\$name]; 01652 $rbracket 01653 return null; 01654 $rbracket 01655 $rbracket 01656 if ( !function_exists( 'compiledfetchtext' ) ) 01657 $lbracket 01658 function compiledFetchText( \$tpl, \$rootNamespace, \$currentNamespace, \$namespace, \$var ) 01659 $lbracket 01660 \$text = ''; 01661 \$tpl->appendElement( \$text, \$var, \$rootNamespace, \$currentNamespace ); 01662 return \$text; 01663 $rbracket 01664 $rbracket 01665 if ( !function_exists( 'compiledAcquireResource' ) ) 01666 $lbracket 01667 function compiledAcquireResource( \$phpScript, \$key, &\$originalText, 01668 \$tpl, \$rootNamespace, \$currentNamespace ) 01669 { 01670 include( '" . eZTemplateCompiler::TemplatePrefix() . "' . \$phpScript ); 01671 if ( isset( \$text ) ) 01672 { 01673 \$originalText .= \$text; 01674 return true; 01675 } 01676 return false; 01677 } 01678 $rbracket 01679 if ( !function_exists( 'compiledfetchattribute' ) ) 01680 $lbracket 01681 function compiledFetchAttribute( \$value, \$attributeValue ) 01682 $lbracket 01683 if ( is_object( \$value ) ) 01684 $lbracket 01685 if ( method_exists( \$value, \"attribute\" ) and 01686 method_exists( \$value, \"hasAttribute\" ) ) 01687 $lbracket 01688 if ( \$value->hasAttribute( \$attributeValue ) ) 01689 $lbracket 01690 return \$value->attribute( \$attributeValue ); 01691 $rbracket 01692 $rbracket 01693 $rbracket 01694 else if ( is_array( \$value ) ) 01695 $lbracket 01696 if ( isset( \$value[\$attributeValue] ) ) 01697 $lbracket 01698 return \$value[\$attributeValue]; 01699 $rbracket 01700 $rbracket 01701 return null; 01702 $rbracket 01703 $rbracket 01704 "; 01705 $php->addCodePiece( $initText ); 01706 $php->store( true ); 01707 } 01708 01709 /*! 01710 Figures out the current text name to use in compiled template code and return it. 01711 The names will be text, text1, text2 etc. 01712 */ 01713 static function currentTextName( $parameters ) 01714 { 01715 $textData = array( 'variable' => 'text', 01716 'counter' => 0 ); 01717 if ( isset( $parameters['text-data'] ) ) 01718 $textData = $parameters['text-data']; 01719 $name = $textData['variable']; 01720 if ( $textData['counter'] > 0 ) 01721 $name .= $textData['counter']; 01722 return $name; 01723 } 01724 01725 static function boundVariableName( $variableID, $parameters ) 01726 { 01727 $bindMap =& $parameters['variable-bind']['map'][$variableID]; 01728 if ( isset( $bindMap ) ) 01729 $bindMap = array(); 01730 } 01731 01732 /*! 01733 Generates the PHP code defined in the template node tree \a $node. 01734 The code is generated using the php creator specified in \a $php. 01735 */ 01736 01737 static function generatePHPCode( $useComments, $php, $tpl, &$node, &$resourceData ) 01738 { 01739 $parameters = array(); 01740 $currentParameters = array( 'spacing' => 0 ); 01741 $nodeType = $node[0]; 01742 if ( $nodeType == eZTemplate::NODE_ROOT ) 01743 { 01744 $children = $node[1]; 01745 if ( $children ) 01746 { 01747 eZTemplateCompiler::generatePHPCodeChildren( $useComments, $php, $tpl, $children, $resourceData, $parameters, $currentParameters ); 01748 } 01749 } 01750 else 01751 $tpl->error( 'generatePHPCode', "Unknown root type $nodeType, should be " . eZTemplate::NODE_ROOT ); 01752 $php->addSpace(); 01753 } 01754 01755 /*! 01756 Generates the PHP code for all node children specified in \a $nodeChildren. 01757 \sa generatePHPCode 01758 */ 01759 static function generatePHPCodeChildren( $useComments, $php, $tpl, &$nodeChildren, &$resourceData, &$parameters, $currentParameters ) 01760 { 01761 foreach ( $nodeChildren as $node ) 01762 { 01763 $newNode = false; 01764 $nodeType = $node[0]; 01765 if ( $nodeType > eZTemplate::NODE_USER_CUSTOM ) 01766 { 01767 // Do custom nodes 01768 } 01769 else if ( $nodeType > eZTemplate::NODE_INTERNAL ) 01770 { 01771 // Do custom internal nodes 01772 if ( $nodeType == eZTemplate::NODE_INTERNAL_CODE_PIECE ) 01773 { 01774 $codePiece = $node[1]; 01775 $spacing = $currentParameters['spacing']; 01776 if ( isset( $node[2]['spacing'] ) ) 01777 $spacing += $node[2]['spacing']; 01778 $php->addCodePiece( $codePiece, array( 'spacing' => $spacing ) ); 01779 } 01780 else if ( $nodeType == eZTemplate::NODE_INTERNAL_WARNING ) 01781 { 01782 $warningText = $php->thisVariableText( $node[1], 23, 0, false ); 01783 $warningLabel = false; 01784 $warningLabelText = ''; 01785 if ( isset( $node[2] ) ) 01786 $warningLabelText = $php->thisVariableText( $node[2], 0, 0, false ); 01787 $spacing = $currentParameters['spacing']; 01788 if ( isset( $node[3]['spacing'] ) ) 01789 $spacing += $node[3]['spacing']; 01790 $placementText = 'false'; 01791 if ( isset( $node[4] ) ) 01792 $placementText = $php->thisVariableText( $node[4], 0, 0, false ); 01793 $php->addCodePiece( "\$tpl->warning( " . $warningLabelText . ", " . $warningText . ", " . $placementText . " );", array( 'spacing' => $spacing ) ); 01794 } 01795 else if ( $nodeType == eZTemplate::NODE_INTERNAL_ERROR ) 01796 { 01797 $errorText = $php->thisVariableText( $node[1], 21, 0, false ); 01798 $errorLabel = false; 01799 $errorLabelText = ''; 01800 if ( isset( $node[2] ) ) 01801 $errorLabelText = $php->thisVariableText( $node[2], 0, 0, false ); 01802 $spacing = $currentParameters['spacing']; 01803 if ( isset( $node[3]['spacing'] ) ) 01804 $spacing += $node[3]['spacing']; 01805 $placementText = 'false'; 01806 if ( isset( $node[4] ) ) 01807 $placementText = $php->thisVariableText( $node[4], 0, 0, false ); 01808 $php->addCodePiece( "\$tpl->error( " . $errorLabelText . ", " . $errorText . ", " . $placementText . " );", array( 'spacing' => $spacing ) ); 01809 } 01810 else if ( $nodeType == eZTemplate::NODE_INTERNAL_OUTPUT_READ ) 01811 { 01812 $variableName = $node[1]; 01813 $spacing = $currentParameters['spacing']; 01814 if ( isset( $node[2]['spacing'] ) ) 01815 $spacing += $node[2]['spacing']; 01816 $textName = eZTemplateCompiler::currentTextName( $parameters ); 01817 $assignmentType = $node[3]; 01818 $assignmentText = $php->variableNameText( $variableName, $assignmentType, $node[2] ); 01819 $php->addCodePiece( "$assignmentText\$$textName;", array( 'spacing' => $spacing ) ); 01820 } 01821 else if ( $nodeType == eZTemplate::NODE_INTERNAL_OUTPUT_ASSIGN ) 01822 { 01823 $variableName = $node[1]; 01824 $spacing = $currentParameters['spacing']; 01825 if ( isset( $node[2]['spacing'] ) ) 01826 $spacing += $node[2]['spacing']; 01827 $textName = eZTemplateCompiler::currentTextName( $parameters ); 01828 $assignmentType = $node[3]; 01829 $assignmentText = $php->variableNameText( $textName, $assignmentType, $node[2] ); 01830 $php->addCodePiece( "$assignmentText\$$variableName;", array( 'spacing' => $spacing ) ); 01831 } 01832 else if ( $nodeType == eZTemplate::NODE_INTERNAL_OUTPUT_INCREASE ) 01833 { 01834 $spacing = $currentParameters['spacing']; 01835 if ( isset( $node[1]['spacing'] ) ) 01836 $spacing += $node[1]['spacing']; 01837 $textName = eZTemplateCompiler::currentTextName( $parameters ); 01838 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( !isset( \$textStack ) )\n" . 01839 " \$textStack = array();\n" . 01840 "\$textStack[] = \$$textName;\n" . 01841 "\$$textName = '';", array( 'spacing' => $spacing ) ); 01842 } 01843 else if ( $nodeType == eZTemplate::NODE_INTERNAL_OUTPUT_DECREASE ) 01844 { 01845 $spacing = $currentParameters['spacing']; 01846 if ( isset( $node[1]['spacing'] ) ) 01847 $spacing += $node[1]['spacing']; 01848 $textName = eZTemplateCompiler::currentTextName( $parameters ); 01849 $php->addCodePiece( "\$$textName = array_pop( \$textStack );", array( 'spacing' => $spacing ) ); 01850 } 01851 else if ( $nodeType == eZTemplate::NODE_INTERNAL_OUTPUT_SPACING_INCREASE ) 01852 { 01853 $spacing = $node[1]; 01854 $currentParameters['spacing'] += $spacing; 01855 continue; 01856 } 01857 else if ( $nodeType == eZTemplate::NODE_INTERNAL_SPACING_DECREASE ) 01858 { 01859 $spacing = $node[1]; 01860 $currentParameters['spacing'] -= $spacing; 01861 continue; 01862 } 01863 else if ( $nodeType == eZTemplate::NODE_INTERNAL_VARIABLE_SET ) 01864 { 01865 $variableName = $node[1]; 01866 $variableValue = $node[2]; 01867 $spacing = $currentParameters['spacing']; 01868 if ( isset( $node[3]['spacing'] ) ) 01869 $spacing += $node[3]['spacing']; 01870 $php->addVariable( $variableName, $variableValue, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'spacing' => $spacing ) ); 01871 } 01872 else if ( $nodeType == eZTemplate::NODE_INTERNAL_VARIABLE_UNSET ) 01873 { 01874 $variableName = $node[1]; 01875 $spacing = $currentParameters['spacing']; 01876 if ( isset( $node[2]['spacing'] ) ) 01877 $spacing += $node[2]['spacing']; 01878 01879 if ( is_array( $variableName ) ) 01880 { 01881 $namespace = $variableName[0]; 01882 $namespaceScope = $variableName[1]; 01883 $variableName = $variableName[2]; 01884 $namespaceText = eZTemplateCompiler::generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, array( 'spacing' => $spacing ), true ); 01885 if ( !is_string( $namespaceText ) ) 01886 $namespaceText = "\$namespace"; 01887 $variableNameText = $php->thisVariableText( $variableName, 0, 0, false ); 01888 if ( isset( $node[2]['remember_set'] ) and $node[2]['remember_set'] ) 01889 { 01890 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( isset( \$setArray[$namespaceText][$variableNameText] ) )\n". 01891 "{\n" ); 01892 $spacing += 4; 01893 } 01894 if ( isset( $node[2]['local-variable'] ) ) 01895 { 01896 $php->addCodePiece( "\$tpl->unsetLocalVariable( $variableNameText, $namespaceText );\n", 01897 array( 'spacing' => $spacing ) ); 01898 } 01899 else 01900 { 01901 $php->addCodePiece( "unset( \$vars[$namespaceText][$variableNameText] );", 01902 array( 'spacing' => $spacing ) ); 01903 } 01904 01905 if ( isset( $node[2]['remember_set'] ) and $node[2]['remember_set'] ) 01906 { 01907 $php->addCodePiece( "\n}\n" ); 01908 $spacing -= 4; 01909 } 01910 } 01911 else 01912 { 01913 $php->addVariableUnset( $variableName, array( 'spacing' => $spacing ) ); 01914 } 01915 } 01916 else if ( ( $nodeType == eZTemplate::NODE_INTERNAL_RESOURCE_ACQUISITION ) || 01917 ( $nodeType == eZTemplate::NODE_OPTIMIZED_RESOURCE_ACQUISITION ) ) 01918 { 01919 $resource = $node[1]; 01920 $resourceObject = $tpl->resourceHandler( $resource ); 01921 if ( !$resourceObject ) 01922 continue; 01923 01924 $spacing = $currentParameters['spacing']; 01925 if ( isset( $node[7]['spacing'] ) ) 01926 $spacing += $node[7]['spacing']; 01927 $newRootNamespace = $node[8]; 01928 $resourceVariableName = $node[9]; 01929 $resourceFilename = isset( $node[10] ) ? $node[10] : false; 01930 01931 /* We can only use fallback code if we know upfront which 01932 * template is included; it does not work if we are using 01933 * something from the ezobjectforwarder which makes the 01934 * uriMap an array */ 01935 $useFallbackCode = true; 01936 $uriMap = $node[2]; 01937 if ( is_string( $uriMap ) ) 01938 { 01939 $uriMap = array( $uriMap ); 01940 } 01941 else 01942 { 01943 $useFallbackCode = false; 01944 } 01945 01946 $resourceMap = array(); 01947 $hasCompiledCode = false; 01948 if ( is_array( $uriMap ) ) 01949 { 01950 foreach ( $uriMap as $uriKey => $originalURI ) 01951 { 01952 $uri = $originalURI; 01953 if ( $resource ) 01954 $uri = $resource . ':' . $uri; 01955 unset( $tmpResourceData ); 01956 $tmpResourceData = $tpl->resourceData( $resourceObject, $uri, $node[1], $originalURI ); 01957 $uriText = $php->thisVariableText( $uri, 0, 0, false ); 01958 01959 $resourceCanCache = true; 01960 if ( !$resourceObject->servesStaticData() ) 01961 $resourceCanCache = false; 01962 if ( !$tpl->isCachingAllowed() ) 01963 $resourceCanCache = false; 01964 01965 $tmpResourceData['text'] = null; 01966 $tmpResourceData['root-node'] = null; 01967 $tmpResourceData['compiled-template'] = false; 01968 $tmpResourceData['time-stamp'] = null; 01969 $tmpResourceData['key-data'] = null; 01970 $tmpResourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled(); 01971 $subSpacing = 0; 01972 $hasResourceData = false; 01973 01974 $savedLocale = setlocale( LC_CTYPE, null ); 01975 if ( isset( $GLOBALS['eZTemplateCompilerResourceCache'][$tmpResourceData['template-filename']] ) ) 01976 { 01977 $tmpFileName = $tmpResourceData['template-filename']; 01978 unset( $tmpResourceData ); 01979 $tmpResourceData = $GLOBALS['eZTemplateCompilerResourceCache'][$tmpFileName]; 01980 $tmpResourceData['compiled-template'] = true; 01981 $tmpResourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled(); 01982 $hasResourceData = true; 01983 $hasCompiledCode = true; 01984 } 01985 else if ( $useFallbackCode ) 01986 { 01987 // If we can use fallback code we don't need to compile the templates in advance 01988 // Simply fake that it has been compiled by setting some variables 01989 // Note: Yes this is a hack, but rewriting this code is not an easy task 01990 if ( $resourceObject->handleResource( $tpl, $tmpResourceData, $node[4], $node[5] ) ) 01991 { 01992 $tmpResourceData['compiled-template'] = true; 01993 $hasResourceData = true; 01994 $hasCompiledCode = true; 01995 } 01996 } 01997 else 01998 { 01999 if ( $resourceObject->handleResource( $tpl, $tmpResourceData, $node[4], $node[5] ) ) 02000 { 02001 if ( !$tmpResourceData['compiled-template'] and 02002 $tmpResourceData['root-node'] === null ) 02003 { 02004 $root =& $tmpResourceData['root-node']; 02005 $root = array( eZTemplate::NODE_ROOT, false ); 02006 $templateText =& $tmpResourceData["text"]; 02007 $keyData = $tmpResourceData['key-data']; 02008 $rootNamespace = ''; 02009 $tpl->parse( $templateText, $root, $rootNamespace, $tmpResourceData ); 02010 $hasResourceData = false; 02011 } 02012 02013 /* We always DO need to execute this part if we 02014 * don't have any fallback code. If we can 02015 * generate the fallback code we make the 02016 * included template compile on demand */ 02017 if ( !$tmpResourceData['compiled-template'] and 02018 $resourceCanCache and 02019 $tpl->canCompileTemplate( $tmpResourceData, $node[5] ) and 02020 !$useFallbackCode ) 02021 { 02022 $generateStatus = $tpl->compileTemplate( $tmpResourceData, $node[5] ); 02023 02024 // Time limit #2: 02025 /* We reset the time limit to 60 seconds to 02026 * ensure that remaining template has 02027 * enough time to compile. However if time 02028 * limit is unlimited (0) we leave it be */ 02029 $maxExecutionTime = ini_get( 'max_execution_time' ); 02030 if ( $maxExecutionTime != 0 && $maxExecutionTime < 60 ) 02031 { 02032 @set_time_limit( 60 ); 02033 } 02034 02035 if ( $generateStatus ) 02036 $tmpResourceData['compiled-template'] = true; 02037 } 02038 } 02039 $GLOBALS['eZTemplateCompilerResourceCache'][$tmpResourceData['template-filename']] =& $tmpResourceData; 02040 } 02041 setlocale( LC_CTYPE, $savedLocale ); 02042 $textName = eZTemplateCompiler::currentTextName( $parameters ); 02043 if ( $tmpResourceData['compiled-template'] ) 02044 { 02045 $hasCompiledCode = true; 02046 // if ( !eZTemplateCompiler::isFallbackResourceCodeEnabled() ) 02047 // $useFallbackCode = false; 02048 $keyData = $tmpResourceData['key-data']; 02049 $templatePath = $tmpResourceData['template-name']; 02050 $key = $resourceObject->cacheKey( $keyData, $tmpResourceData, $templatePath, $node[5] ); 02051 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $tmpResourceData ); 02052 02053 $directory = eZTemplateCompiler::compilationDirectory(); 02054 $phpScript = eZDir::path( array( $directory, $cacheFileName ) ); 02055 $phpScriptText = $php->thisVariableText( $phpScript, 0, 0, false ); 02056 $resourceMap[$uriKey] = array( 'key' => $uriKey, 02057 'uri' => $uri, 02058 'phpscript' => $phpScript ); 02059 } 02060 } 02061 } 02062 02063 if ( $useComments ) 02064 { 02065 $variablePlacement = $node[6]; 02066 if ( $variablePlacement ) 02067 { 02068 $originalText = eZTemplateCompiler::fetchTemplatePiece( $variablePlacement ); 02069 $php->addComment( "Resource Acquisition:", true, true, array( 'spacing' => $spacing ) ); 02070 $php->addComment( $originalText, true, true, array( 'spacing' => $spacing ) ); 02071 } 02072 } 02073 02074 if ( $hasCompiledCode ) 02075 { 02076 if ( $resourceVariableName ) 02077 { 02078 $phpScriptText = '$phpScript'; 02079 $phpScriptArray = array(); 02080 02081 foreach ( $resourceMap as $resourceMapItem ) 02082 { 02083 $phpScriptArray[$resourceMapItem['key']] = $resourceMapItem['phpscript']; 02084 } 02085 02086 if ( !$resourceFilename ) /* Not optimized version */ 02087 { 02088 $php->addVariable( "phpScriptArray", $phpScriptArray, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'spacing' => $spacing ) ); 02089 $resourceVariableNameText = "\$$resourceVariableName"; 02090 $php->addCodePiece( "\$phpScript = isset( \$phpScriptArray[$resourceVariableNameText] ) ? \$phpScriptArray[$resourceVariableNameText] : false;\n", array( 'spacing' => $spacing ) ); 02091 } 02092 else /* Optimised version */ 02093 { 02094 $php->addVariable( "phpScript", $phpScriptArray[$node[10]], eZPHPCreator::VARIABLE_ASSIGNMENT, array('spacing' => $spacing ) ); 02095 } 02096 02097 // The default is to only check if it exists 02098 $modificationCheckText = "file_exists( $phpScriptText )"; 02099 if ( eZTemplateCompiler::isDevelopmentModeEnabled() ) 02100 { 02101 $modificationCheckText = "file_exists( $phpScriptText ) && filemtime( $phpScriptText ) > filemtime( $uriText )"; 02102 } 02103 $php->addCodePiece( "\$resourceFound = false;\nif " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( $phpScriptText !== false and $modificationCheckText )\n{\n", array( 'spacing' => $spacing ) ); 02104 } 02105 else 02106 { 02107 $php->addCodePiece( "\$resourceFound = false;\n", array( 'spacing' => $spacing ) ); 02108 $phpScript = $resourceMap[0]['phpscript']; 02109 $phpScriptText = $php->thisVariableText( $phpScript, 0, 0, false ); 02110 // Not sure where this should come from 02111 // if ( $resourceIndex > 0 ) 02112 // $php->addCodePiece( "else " ); 02113 // The default is to only check if it exists 02114 $modificationCheckText = "file_exists( $phpScriptText )"; 02115 if ( eZTemplateCompiler::isDevelopmentModeEnabled() ) 02116 { 02117 $modificationCheckText = "file_exists( $phpScriptText ) && filemtime( $phpScriptText ) > filemtime( $uriText )"; 02118 } 02119 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( $modificationCheckText )\n{\n", array( 'spacing' => $spacing ) ); 02120 02121 } 02122 02123 /* Generate code to do a namespace switch and includes the template */ 02124 $code = "\$resourceFound = true;\n\$namespaceStack[] = array( \$rootNamespace, \$currentNamespace );\n"; 02125 if ( $newRootNamespace ) 02126 { 02127 $newRootNamespaceText = $php->thisVariableText( $newRootNamespace, 0, 0, false ); 02128 $code .= "\$currentNamespace = \$rootNamespace = !\$currentNamespace ? $newRootNamespaceText : ( \$currentNamespace . ':' . $newRootNamespaceText );\n"; 02129 } 02130 else 02131 { 02132 $code .= "\$rootNamespace = \$currentNamespace;\n"; 02133 } 02134 02135 $code .= 02136 "\$tpl->createLocalVariablesList();\n" . 02137 "\$tpl->appendTemplateFetch( $uriText );\n" . // Make sure the template file is recorded, like in loadURIRoot 02138 "include( '" . eZTemplateCompiler::TemplatePrefix() . "' . $phpScriptText );\n" . 02139 "\$tpl->unsetLocalVariables();\n" . 02140 "\$tpl->destroyLocalVariablesList();\n" . 02141 "list( \$rootNamespace, \$currentNamespace ) = array_pop( \$namespaceStack );\n"; 02142 02143 $php->addCodePiece( $code, array( 'spacing' => $spacing + 4 ) ); 02144 if ( $useFallbackCode ) 02145 $php->addCodePiece( "}\nelse\n{\n \$resourceFound = true;\n", array( 'spacing' => $spacing ) ); 02146 else 02147 $php->addCodePiece( "}\n", array( 'spacing' => $spacing ) ); 02148 $subSpacing = 4; 02149 } 02150 else 02151 { 02152 /* Yes, this is a hack, but it is required because 02153 * sometimes the generated nodes after this one emit an 02154 * else statement while there is no accompanied if */ 02155 $php->addCodePiece( "\nif " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "(false)\n{\n}\n" ); 02156 } 02157 02158 /* The fallback code will be added if we need to process an 02159 * URI, this will also compile a template then. We need to 02160 * do the namespace switch manually here otherwise the 02161 * processed template will be run on the node from which 02162 * the template was included from. */ 02163 if ( $useFallbackCode ) 02164 { 02165 $code = "\$resourceFound = true;\n\$namespaceStack[] = array( \$rootNamespace, \$currentNamespace );\n"; 02166 if ( $newRootNamespace ) 02167 { 02168 $newRootNamespaceText = $php->thisVariableText( $newRootNamespace, 0, 0, false ); 02169 $code .= "\$currentNamespace = \$rootNamespace = !\$currentNamespace ? $newRootNamespaceText : ( \$currentNamespace . ':' . $newRootNamespaceText );\n"; 02170 } 02171 else 02172 { 02173 $code .= "\$rootNamespace = \$currentNamespace;\n"; 02174 } 02175 $php->addCodePiece( $code ); 02176 02177 $php->addCodePiece( "\$textElements = array();\n\$extraParameters = array();\n\$tpl->processURI( $uriText, true, \$extraParameters, \$textElements, \$rootNamespace, \$currentNamespace );\n\$$textName .= implode( '', \$textElements );\n", array( 'spacing' => $spacing + $subSpacing ) ); 02178 $php->addCodePiece( "list( \$rootNamespace, \$currentNamespace ) = array_pop( \$namespaceStack );\n" ); 02179 } 02180 02181 if ( $hasCompiledCode and $useFallbackCode ) 02182 { 02183 $php->addCodePiece( "}\n", array( 'spacing' => $spacing ) ); 02184 } 02185 } 02186 else if ( $nodeType == eZTemplate::NODE_INTERNAL_NAMESPACE_CHANGE ) 02187 { 02188 $variableData = $node[1]; 02189 $spacing = $currentParameters['spacing']; 02190 if ( isset( $node[2]['spacing'] ) ) 02191 $spacing += $node[2]['spacing']; 02192 $php->addCodePiece( "\$namespaceStack[] = \$currentNamespace;\n", array( 'spacing' => $spacing ) ); 02193 $php->addCodePiece( '$currentNamespace .= ( $currentNamespace ? ":" : "" ) . \''. $variableData[0][1] . '\';' . "\n", array( 'spacing' => $spacing ) ); 02194 } 02195 else if ( $nodeType == eZTemplate::NODE_INTERNAL_NAMESPACE_RESTORE ) 02196 { 02197 $spacing = $currentParameters['spacing']; 02198 if ( isset( $node[1]['spacing'] ) ) 02199 $spacing += $node[1]['spacing']; 02200 $php->addCodePiece( "\$currentNamespace = array_pop( \$namespaceStack );\n", array( 'spacing' => $spacing ) ); 02201 } 02202 else if ( $nodeType == eZTemplate::NODE_OPTIMIZED_INIT ) 02203 { 02204 $code = <<<END 02205 \$node = ( array_key_exists( \$rootNamespace, \$vars ) and array_key_exists( "node", \$vars[\$rootNamespace] ) ) ? \$vars[\$rootNamespace]["node"] : null; 02206 if ( is_object( \$node ) ) 02207 \$object = \$node->attribute( 'object' ); 02208 if ( isset( \$object ) && is_object( \$object ) ) 02209 \$nod_{$resourceData['uniqid']} = \$object->attribute( 'data_map' ); 02210 else 02211 \$nod_{$resourceData['uniqid']} = false; 02212 unset( \$node, \$object ); 02213 02214 END; 02215 $php->addCodePiece($code); 02216 // Tell the rest of the system that we have create the nod_* variable 02217 $resourceData['node-object-cached'] = true; 02218 } 02219 else 02220 eZDebug::writeWarning( "Unknown internal template node type $nodeType, ignoring node for code generation", 02221 'eZTemplateCompiler:generatePHPCodeChildren' ); 02222 } 02223 else if ( $nodeType == eZTemplate::NODE_ROOT ) 02224 { 02225 $children = $node[1]; 02226 if ( $children ) 02227 { 02228 $newCurrentParameters = $currentParameters; 02229 $newCurrentParameters['spacing'] += 4; 02230 eZTemplateCompiler::generatePHPCodeChildren( $useComments, $php, $tpl, $children, $resourceData, $parameters, $newCurrentParameters ); 02231 } 02232 continue; 02233 } 02234 else if ( $nodeType == eZTemplate::NODE_TEXT ) 02235 { 02236 $text = $node[2]; 02237 if ( $text != '' ) 02238 { 02239 $variablePlacement = $node[3]; 02240 $originalText = eZTemplateCompiler::fetchTemplatePiece( $variablePlacement ); 02241 if ( $useComments ) 02242 { 02243 $php->addComment( "Text start:", true, true, array( 'spacing' => $currentParameters['spacing'] ) ); 02244 $php->addComment( $originalText, true, true, array( 'spacing' => $currentParameters['spacing'] ) ); 02245 $php->addComment( "Text end:", true, true, array( 'spacing' => $currentParameters['spacing'] ) ); 02246 } 02247 $php->addVariable( eZTemplateCompiler::currentTextName( $parameters ), 02248 $text, eZPHPCreator::VARIABLE_APPEND_TEXT, 02249 array( 'spacing' => $currentParameters['spacing'] ) ); 02250 } 02251 continue; 02252 } 02253 else if ( $nodeType == eZTemplate::NODE_VARIABLE ) 02254 { 02255 $variableAssignmentName = $node[1]; 02256 $variableData = $node[2]; 02257 $variablePlacement = $node[3]; 02258 02259 $variableParameters = array(); 02260 if ( isset( $node[4] ) and 02261 $node[4] ) 02262 $variableParameters = $node[4]; 02263 $variableOnlyExisting = isset( $node[5] ) ? $node[5] : false; 02264 $variableOverWrite = isset( $node[6] ) ? $node[6] : false; 02265 $rememberSet = isset( $node[7] ) ? $node[7] : false; 02266 02267 $spacing = $currentParameters['spacing']; 02268 if ( isset( $variableParameters['spacing'] ) ) 02269 $spacing += $variableParameters['spacing']; 02270 $variableParameters = array_merge( array( 'variable-name' => 'var', 02271 'text-result' => true ), 02272 $variableParameters ); 02273 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 02274 $variableData, $variablePlacement, 02275 $resourceData ); 02276 $newNode = $node; 02277 $newNode[1] = false; 02278 02279 $treatVariableDataAsNonObject = isset( $variableParameters['treat-value-as-non-object'] ) && $variableParameters['treat-value-as-non-object']; 02280 02281 if ( $useComments ) 02282 { 02283 $php->addComment( "Variable data: " . 02284 "Is constant: " . ( $dataInspection['is-constant'] ? 'Yes' : 'No' ) . 02285 " Is variable: " . ( $dataInspection['is-variable'] ? 'Yes' : 'No' ) . 02286 " Has attributes: " . ( $dataInspection['has-attributes'] ? 'Yes' : 'No' ) . 02287 " Has operators: " . ( $dataInspection['has-operators'] ? 'Yes' : 'No' ), 02288 true, true, array( 'spacing' => $spacing ) 02289 ); 02290 $originalText = eZTemplateCompiler::fetchTemplatePiece( $variablePlacement ); 02291 $php->addComment( '{' . $originalText . '}', true, true, array( 'spacing' => $spacing ) ); 02292 } 02293 $generatedVariableName = $variableParameters['variable-name']; 02294 $assignVariable = false; 02295 if ( $variableAssignmentName !== false ) 02296 { 02297 if ( is_array( $variableAssignmentName ) ) 02298 { 02299 $variableParameters['text-result'] = false; 02300 $assignVariable = true; 02301 } 02302 else 02303 { 02304 $generatedVariableName = $variableAssignmentName; 02305 $variableParameters['text-result'] = false; 02306 } 02307 } 02308 02309 $isStaticElement = false; 02310 $nodeElements = $node[2]; 02311 $knownTypes = array(); 02312 if ( eZTemplateNodeTool::isConstantElement( $nodeElements ) and 02313 !$variableParameters['text-result'] ) 02314 { 02315 $variableText = $php->thisVariableText( eZTemplateNodeTool::elementConstantValue( $nodeElements ), 0, 0, false ); 02316 $isStaticElement = true; 02317 } 02318 else if ( eZTemplateNodeTool::isPHPVariableElement( $nodeElements ) and 02319 !$variableParameters['text-result'] ) 02320 { 02321 $variableText = '$' . eZTemplateNodeTool::elementConstantValue( $nodeElements ); 02322 $isStaticElement = true; 02323 } 02324 else 02325 { 02326 $variableText = "\$$generatedVariableName"; 02327 eZTemplateCompiler::generateVariableCode( $php, $tpl, $node, $knownTypes, $dataInspection, 02328 array( 'spacing' => $spacing, 02329 'variable' => $generatedVariableName, 02330 'treat-value-as-non-object' => $treatVariableDataAsNonObject, 02331 'counter' => 0 ), 02332 $resourceData ); 02333 } 02334 02335 if ( $variableParameters['text-result'] ) 02336 { 02337 $textName = eZTemplateCompiler::currentTextName( $parameters ); 02338 if ( count( $knownTypes ) == 0 or in_array( 'objectproxy', $knownTypes ) ) 02339 { 02340 $php->addCodePiece( "\$$textName .= ( is_object( \$$generatedVariableName ) ? compiledFetchText( \$tpl, \$rootNamespace, \$currentNamespace, false, \$$generatedVariableName ) : \$$generatedVariableName );" . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "\n" . 02341 "unset( \$$generatedVariableName );\n", array( 'spacing' => $spacing ) ); 02342 } 02343 else 02344 { 02345 $php->addCodePiece( "\$$textName .= \$$generatedVariableName;\n" . 02346 "unset( \$$generatedVariableName );\n", array( 'spacing' => $spacing ) ); 02347 } 02348 } 02349 else if ( $assignVariable ) 02350 { 02351 $namespace = $variableAssignmentName[0]; 02352 $namespaceScope = $variableAssignmentName[1]; 02353 $variableName = $variableAssignmentName[2]; 02354 $namespaceText = eZTemplateCompiler::generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, array( 'spacing' => $spacing ), true ); 02355 if ( !is_string( $namespaceText ) ) 02356 $namespaceText = "\$namespace"; 02357 $variableNameText = $php->thisVariableText( $variableName, 0, 0, false ); 02358 $unsetVariableText = false; 02359 if ( $variableOnlyExisting ) 02360 { 02361 if ( !$isStaticElement ) 02362 $unsetVariableText = "\n unset( $variableText );"; 02363 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( array_key_exists( $namespaceText, \$vars ) && array_key_exists( $variableNameText, \$vars[$namespaceText] ) )\n". 02364 "{\n". 02365 " \$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText\n". 02366 "}", 02367 array( 'spacing' => $spacing ) ); 02368 } 02369 else if ( $variableOverWrite ) 02370 { 02371 if ( !$isStaticElement ) 02372 $unsetVariableText = "\nunset( $variableText );"; 02373 if ( isset( $variableParameters['local-variable'] ) ) 02374 { 02375 $php->addCodePiece( "if ( \$tpl->hasVariable( $variableNameText, $namespaceText ) )\n{\n" ); // if the variable already exists 02376 $php->addCodePiece( " \$tpl->warning( '" . eZTemplateDefFunction::DEF_FUNCTION_NAME . "', \"Variable '$variableName' is already defined.\", " . $php->thisVariableText( $variablePlacement ) . " );\n" ); 02377 $php->addCodePiece( " \$tpl->setVariable( $variableNameText, $variableText, $namespaceText );\n}\nelse\n{\n" ); 02378 $php->addCodePiece( " \$tpl->setLocalVariable( $variableNameText, $variableText, $namespaceText );\n}\n" , 02379 array( 'spacing' => $spacing ) ); 02380 } 02381 else 02382 { 02383 $php->addCodePiece( "\$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText", 02384 array( 'spacing' => $spacing ) ); 02385 } 02386 02387 } 02388 else if ( $rememberSet ) 02389 { 02390 if ( !$isStaticElement ) 02391 $unsetVariableText = "\n unset( $variableText );"; 02392 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( !isset( \$vars[$namespaceText][$variableNameText] ) )\n". 02393 "{\n". 02394 " \$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText\n". 02395 " \$setArray[$namespaceText][$variableNameText] = true;\n". 02396 "}\n", 02397 array( 'spacing' => $spacing ) ); 02398 } 02399 else 02400 { 02401 if ( !$isStaticElement ) 02402 $unsetVariableText = "\n unset( $variableText );"; 02403 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( !isset( \$vars[$namespaceText][$variableNameText] ) )\n{\n \$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText\n}", 02404 array( 'spacing' => $spacing ) ); 02405 } 02406 } 02407 else if ( $variableAssignmentName !== false and $isStaticElement ) 02408 { 02409 $php->addCodePiece( "\$$generatedVariableName = $variableText;", array( 'spacing' => $spacing ) ); 02410 } 02411 else if ( $variableAssignmentName !== false and !$isStaticElement and !$treatVariableDataAsNonObject ) 02412 { 02413 // Normal assignment from an expression, no need to anything extra 02414 } 02415 unset( $dataInspection ); 02416 } 02417 else if ( $nodeType == eZTemplate::NODE_FUNCTION ) 02418 { 02419 $functionChildren = $node[1]; 02420 $functionName = $node[2]; 02421 $functionParameters = $node[3]; 02422 $functionPlacement = $node[4]; 02423 02424 $newNode = array( $nodeType, 02425 false, 02426 $functionName, 02427 $functionParameters, 02428 $functionPlacement ); 02429 02430 $parameterText = 'No parameters'; 02431 if ( $functionParameters ) 02432 { 02433 $parameterText = "Parameters: ". implode( ', ', array_keys( $functionParameters ) ); 02434 } 02435 if ( $useComments ) 02436 { 02437 $php->addComment( "Function: $functionName, $parameterText", true, true, array( 'spacing' => $currentParameters['spacing'] ) ); 02438 $originalText = eZTemplateCompiler::fetchTemplatePiece( $functionPlacement ); 02439 $php->addComment( '{' . $originalText . '}', true, true, array( 'spacing' => $currentParameters['spacing'] ) ); 02440 } 02441 if ( isset( $node[5] ) ) 02442 { 02443 $functionHook = $node[5]; 02444 $functionHookCustomFunction = $functionHook['function']; 02445 if ( $functionHookCustomFunction ) 02446 { 02447 $functionHookCustomFunction = array_merge( array( 'add-function-name' => false, 02448 'add-hook-name' => false, 02449 'add-template-handler' => true, 02450 'add-function-hook-data' => false, 02451 'add-function-parameters' => true, 02452 'add-function-placement' => false, 02453 'add-calculated-namespace' => false, 02454 'add-namespace' => true, 02455 'add-input' => false, 02456 'return-value' => false ), 02457 $functionHookCustomFunction ); 02458 if ( !isset( $parameters['hook-result-variable-counter'][$functionName] ) ) 02459 $parameters['hook-result-variable-counter'][$functionName] = 0; 02460 if ( $functionHookCustomFunction['return-value'] ) 02461 $parameters['hook-result-variable-counter'][$functionName]++; 02462 $hookResultName = $functionName . 'Result' . $parameters['hook-result-variable-counter'][$functionName]; 02463 if ( $functionHookCustomFunction['add-input'] ) 02464 $parameters['hook-result-variable-counter'][$functionName]--; 02465 $functionHookCustomFunctionName = $functionHookCustomFunction['name']; 02466 $codeText = ''; 02467 if ( $functionHookCustomFunction['return-value'] ) 02468 $codeText = "\$$hookResultName = "; 02469 if ( $functionHookCustomFunction['static'] ) 02470 { 02471 $hookClassName = $functionHookCustomFunction['class-name']; 02472 $codeText .= "$hookClassName::$functionHookCustomFunctionName( "; 02473 } 02474 else 02475 $codeText .= "\$functionObject->$functionHookCustomFunctionName( "; 02476 $codeTextLength = strlen( $codeText ); 02477 02478 $functionNameText = $php->thisVariableText( $functionName, 0, 0, false ); 02479 $functionChildrenText = $php->thisVariableText( $functionChildren, $codeTextLength, 0, false ); 02480 02481 $inputFunctionParameters = $functionParameters; 02482 if ( $functionHookCustomFunction['add-calculated-namespace'] ) 02483 unset( $inputFunctionParameters['name'] ); 02484 $functionParametersText = $php->thisVariableText( $inputFunctionParameters, $codeTextLength, 0, false ); 02485 02486 $functionPlacementText = $php->thisVariableText( $functionPlacement, $codeTextLength, 0, false ); 02487 $functionHookText = $php->thisVariableText( $functionHook, $codeTextLength, 0, false ); 02488 02489 $functionHookName = $functionHook['name']; 02490 $functionHookNameText = $php->thisVariableText( $functionHookName, 0, 0, false ); 02491 02492 $codeParameters = array(); 02493 if ( $functionHookCustomFunction['add-function-name'] ) 02494 $codeParameters[] = $functionNameText; 02495 if ( $functionHookCustomFunction['add-hook-name'] ) 02496 $codeParameters[] = $functionHookNameText; 02497 if ( $functionHookCustomFunction['add-function-hook-data'] ) 02498 $codeParameters[] = $functionHookText; 02499 if ( $functionHookCustomFunction['add-template-handler'] ) 02500 $codeParameters[] = "\$tpl"; 02501 if ( $functionHookCustomFunction['add-function-parameters'] ) 02502 $codeParameters[] = $functionParametersText; 02503 if ( $functionHookCustomFunction['add-function-placement'] ) 02504 $codeParameters[] = $functionPlacementText; 02505 if ( $functionHookCustomFunction['add-calculated-namespace'] ) 02506 { 02507 $name = ''; 02508 if ( isset( $functionParameters['name'] ) ) 02509 { 02510 $nameParameter = $functionParameters['name']; 02511 $nameInspection = eZTemplateCompiler::inspectVariableData( $tpl, 02512 $nameParameter, $functionPlacement, 02513 $resourceData ); 02514 if ( $nameInspection['is-constant'] and 02515 !$nameInspection['is-variable'] and 02516 !$nameInspection['has-attributes'] and 02517 !$nameInspection['has-operators'] ) 02518 { 02519 $nameData = $nameParameter[0][1]; 02520 $nameText = $php->thisVariableText( $nameData, 0, 0, false ); 02521 $php->addCodePiece( "if ( \$currentNamespace != '' ) 02522 \$name = \$currentNamespace . ':' . $nameText; 02523 else 02524 \$name = $nameText;\n", array( 'spacing' => $currentParameters['spacing'] ) ); 02525 $codeParameters[] = "\$name"; 02526 } 02527 else 02528 { 02529 $persistence = array(); 02530 $knownTypes = array(); 02531 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $nameParameter, $knownTypes, $nameInspection, 02532 $persistence, 02533 array( 'variable' => 'name', 02534 'counter' => 0 ), 02535 $resourceData ); 02536 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( \$currentNamespace != '' ) 02537 { 02538 if ( \$name != '' ) 02539 \$name = \"\$currentNamespace:\$name\"; 02540 else 02541 \$name = \$currentNamespace; 02542 }\n", array( 'spacing' => $currentParameters['spacing'] ) ); 02543 $codeParameters[] = "\$name"; 02544 } 02545 } 02546 else 02547 { 02548 $codeParameters[] = "\$currentNamespace"; 02549 } 02550 } 02551 if ( $functionHookCustomFunction['add-namespace'] ) 02552 $codeParameters[] = "\$rootNamespace, \$currentNamespace"; 02553 if ( $functionHookCustomFunction['add-input'] ) 02554 $codeParameters[] = "\$$hookResultName"; 02555 $codeText .= implode( ",\n" . str_repeat( ' ', $codeTextLength ), 02556 $codeParameters ); 02557 $codeText .= " );\n"; 02558 if ( $functionHookCustomFunction['static'] ) 02559 { 02560 $hookFile = $functionHookCustomFunction['php-file']; 02561 $hookFileText = $php->thisVariableText( $hookFile, 0, 0, false ); 02562 $php->addCodePiece( "include_once( $hookFileText );\n", array( 'spacing' => $currentParameters['spacing'] ) ); 02563 } 02564 else 02565 $php->addCodePiece( "\$functionObject = \$tpl->fetchFunctionObject( $functionNameText );\n", array( 'spacing' => $currentParameters['spacing'] ) ); 02566 $php->addCodePiece( $codeText, array( 'spacing' => $currentParameters['spacing'] ) ); 02567 } 02568 else 02569 { 02570 $functionNameText = $php->thisVariableText( $functionName, 0, 0, false ); 02571 $functionChildrenText = $php->thisVariableText( $functionChildren, 52, 0, false ); 02572 $functionParametersText = $php->thisVariableText( $functionParameters, 52, 0, false ); 02573 $functionPlacementText = $php->thisVariableText( $functionPlacement, 52, 0, false ); 02574 02575 $functionHookText = $php->thisVariableText( $functionHook, 52, 0, false ); 02576 $functionHookName = $functionHook['name']; 02577 $functionHookNameText = $php->thisVariableText( $functionHookName, 0, 0, false ); 02578 $functionHookParameters = $functionHook['parameters']; 02579 $php->addCodePiece( "\$functionObject = \$tpl->fetchFunctionObject( $functionNameText ); 02580 \$hookResult = \$functionObject->templateHookProcess( $functionNameText, $functionHookNameText, 02581 $functionHookText, 02582 \$tpl, 02583 $functionParametersText, 02584 $functionPlacementText, 02585 \$rootNamespace, \$currentNamespace ); 02586 ", array( 'spacing' => $currentParameters['spacing'] ) ); 02587 } 02588 } 02589 else 02590 { 02591 $textName = eZTemplateCompiler::currentTextName( $parameters ); 02592 $functionNameText = $php->thisVariableText( $functionName, 0, 0, false ); 02593 $functionChildrenText = $php->thisVariableText( $functionChildren, 22, 0, false ); 02594 $functionParametersText = $php->thisVariableText( $functionParameters, 22, 0, false ); 02595 $functionPlacementText = $php->thisVariableText( $functionPlacement, 22, 0, false ); 02596 $php->addCodePiece( "\$textElements = array(); 02597 \$tpl->processFunction( $functionNameText, \$textElements, 02598 $functionChildrenText, 02599 $functionParametersText, 02600 $functionPlacementText, 02601 \$rootNamespace, \$currentNamespace ); 02602 \$$textName .= implode( '', \$textElements );\n", array( 'spacing' => $currentParameters['spacing'] ) ); 02603 } 02604 } 02605 $php->addSpace(); 02606 } 02607 } 02608 02609 /*! 02610 Generates PHP code which will do namespace merging. 02611 The namespace to merge with is specified in \a $namespace and 02612 the scope of the merging is defined by \a $namespaceScope. 02613 */ 02614 static function generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, $parameters = array(), $skipSimpleAssignment = false ) 02615 { 02616 if ( $namespace != '' ) 02617 { 02618 if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_GLOBAL ) 02619 { 02620 $php->addVariable( 'namespace', $namespace, eZPHPCreator::VARIABLE_ASSIGNMENT, $parameters ); 02621 } 02622 else if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_LOCAL ) 02623 { 02624 $php->addCodePiece( "\$namespace = \$rootNamespace; 02625 if ( \$namespace == '' ) 02626 \$namespace = \"$namespace\"; 02627 else 02628 \$namespace .= ':$namespace'; 02629 ", $parameters ); 02630 } 02631 else if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_RELATIVE ) 02632 { 02633 $php->addCodePiece( "\$namespace = \$currentNamespace; 02634 if ( \$namespace == '' ) 02635 \$namespace = \"$namespace\"; 02636 else 02637 \$namespace .= ':$namespace'; 02638 ", $parameters ); 02639 } 02640 } 02641 else 02642 { 02643 if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_GLOBAL ) 02644 { 02645 if ( $skipSimpleAssignment ) 02646 return "''"; 02647 $php->addVariable( 'namespace', '', eZPHPCreator::VARIABLE_ASSIGNMENT, $parameters ); 02648 } 02649 else if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_LOCAL ) 02650 { 02651 if ( $skipSimpleAssignment ) 02652 return "\$rootNamespace"; 02653 $php->addCodePiece( "\$namespace = \$rootNamespace;\n", $parameters ); 02654 } 02655 else if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_RELATIVE ) 02656 { 02657 if ( $skipSimpleAssignment ) 02658 return "\$currentNamespace"; 02659 $php->addCodePiece( "\$namespace = \$currentNamespace;\n", $parameters ); 02660 } 02661 } 02662 return true; 02663 } 02664 02665 /*! 02666 Generates PHP code for the variable node \a $node. 02667 Use generateVariableDataCode if you want to create code for arbitrary variable data structures. 02668 */ 02669 static function generateVariableCode( $php, $tpl, $node, &$knownTypes, $dataInspection, $parameters, &$resourceData ) 02670 { 02671 $variableData = $node[2]; 02672 $persistence = array(); 02673 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $variableData, $knownTypes, $dataInspection, $persistence, $parameters, $resourceData ); 02674 } 02675 02676 /*! 02677 Generates PHP code for the variable tree structure in \a $variableData. 02678 The code will contain string, numeric and identifier assignment, 02679 variable lookup, attribute lookup and operator execution. 02680 Use generateVariableCode if you want to create code for a variable tree node. 02681 */ 02682 static function generateVariableDataCode( $php, $tpl, $variableData, &$knownTypes, $dataInspection, &$persistence, $parameters, &$resourceData ) 02683 { 02684 $staticTypeMap = array( eZTemplate::TYPE_STRING => 'string', 02685 eZTemplate::TYPE_NUMERIC => 'numeric', 02686 eZTemplate::TYPE_IDENTIFIER => 'string', 02687 eZTemplate::TYPE_ARRAY => 'array', 02688 eZTemplate::TYPE_BOOLEAN => 'boolean' ); 02689 02690 $variableAssignmentName = $parameters['variable']; 02691 $variableAssignmentCounter = $parameters['counter']; 02692 $spacing = 0; 02693 $optimizeNode = false; 02694 if ( isset( $parameters['spacing'] ) ) 02695 $spacing = $parameters['spacing']; 02696 if ( $variableAssignmentCounter > 0 ) 02697 $variableAssignmentName .= $variableAssignmentCounter; 02698 02699 // We need to unset the assignment variable before any elements are processed 02700 // This ensures that we don't work on existing variables 02701 $php->addCodePiece( "unset( \$$variableAssignmentName );\n", array( 'spacing' => $spacing ) ); 02702 02703 if ( is_array( $variableData ) ) 02704 { 02705 foreach ( $variableData as $index => $variableDataItem ) 02706 { 02707 $variableDataType = $variableDataItem[0]; 02708 if ( $variableDataType == eZTemplate::TYPE_STRING or 02709 $variableDataType == eZTemplate::TYPE_NUMERIC or 02710 $variableDataType == eZTemplate::TYPE_IDENTIFIER or 02711 $variableDataType == eZTemplate::TYPE_ARRAY or 02712 $variableDataType == eZTemplate::TYPE_BOOLEAN ) 02713 { 02714 $knownTypes = array_unique( array_merge( $knownTypes, array( $staticTypeMap[$variableDataType] ) ) ); 02715 $dataValue = $variableDataItem[1]; 02716 $dataText = $php->thisVariableText( $dataValue, 0, 0, false ); 02717 $php->addCodePiece( "\$$variableAssignmentName = $dataText;\n", array( 'spacing' => $spacing ) ); 02718 } 02719 else if ( $variableDataType == eZTemplate::TYPE_OPTIMIZED_NODE ) 02720 { 02721 $optimizeNode = true; 02722 if ( !isset( $resourceData['node-object-cached'] ) ) 02723 $tpl->error( "eZTemplateCompiler" . ( $resourceData['use-comments'] ? ( ":" . __LINE__ ) : "" ), "Attribute node-object-cached of variable \$resourceData was not found but variable node eZTemplate::TYPE_OPTIMIZED_NODE is still present. This should not happen" ); 02724 $php->addCodePiece("\$$variableAssignmentName = \$nod_{$resourceData['uniqid']};\n"); 02725 02726 // If optimized node is not set, use unoptimized code. 02727 $php->addCodePiece( "if ( !\$$variableAssignmentName )\n{\n" ); 02728 } 02729 else if ( $variableDataType == eZTemplate::TYPE_OPTIMIZED_ARRAY_LOOKUP ) 02730 { 02731 $code = ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/\n" ) : "" ); 02732 02733 // This code is used a lot so we create a variable for it 02734 $phpVar = "\$$variableAssignmentName"; 02735 $indexName = "'{$variableDataItem[1][0][1]}'"; 02736 02737 // Add sanity checking 02738 $code .= ( "if ( !isset( {$phpVar}[{$indexName}] ) )\n" . 02739 "{\n" . 02740 " \$tpl->error( 'eZTemplateCompiler" . ( $resourceData['use-comments'] ? ( ":" . __LINE__ ) : "" ) . "', \"PHP variable \\$phpVar"."[{$indexName}] does not exist, cannot fetch the value.\" );\n" . 02741 " $phpVar = null;\n" . 02742 "}\n" . 02743 "else\n " ); 02744 02745 // Add the actual code 02746 $code .= "$phpVar = {$phpVar}[{$indexName}];\n"; 02747 02748 $php->addCodePiece( $code ); 02749 } 02750 else if ( $variableDataType == eZTemplate::TYPE_OPTIMIZED_ATTRIBUTE_LOOKUP ) 02751 { 02752 $code = ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/\n" ) : "" ); 02753 $code .= <<<END 02754 if ( !is_object( \${$variableAssignmentName} ) ) 02755 { 02756 \${$variableAssignmentName} = null; 02757 } 02758 else if ( \${$variableAssignmentName}->hasAttribute( "{$variableDataItem[1][0][1]}" ) ) 02759 { 02760 \${$variableAssignmentName} = \${$variableAssignmentName}->attribute( "{$variableDataItem[1][0][1]}" ); 02761 } 02762 02763 END; 02764 $php->addCodePiece($code); 02765 } 02766 else if ( $variableDataType == eZTemplate::TYPE_OPTIMIZED_CONTENT_CALL ) 02767 { 02768 // Line number comment 02769 $code = ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/\n" ) : "" ); 02770 02771 // This code is used a lot so we create a variable for it 02772 $phpVar = "\$$variableAssignmentName"; 02773 02774 // Add sanity checking 02775 $code .= ( "if ( !is_object( $phpVar ) )\n" . 02776 "{\n" . 02777 " \$tpl->error( 'eZTemplateCompiler" . ( $resourceData['use-comments'] ? ( ":" . __LINE__ ) : "" ) . "', \"PHP variable \\$phpVar is not an object, cannot fetch content()\" );\n" . 02778 " $phpVar = null;\n" . 02779 "}\n" . 02780 "else\n" . 02781 "{\n" ); 02782 02783 // Add the actual code 02784 $code .= " {$phpVar}Tmp = {$phpVar}->content();\n" . 02785 " unset( $phpVar );\n" . 02786 " $phpVar = {$phpVar}Tmp;\n" . 02787 " unset( {$phpVar}Tmp );\n}\n"; 02788 02789 $php->addCodePiece( $code ); 02790 } 02791 else if ( $variableDataType == eZTemplate::TYPE_PHP_VARIABLE ) 02792 { 02793 $knownTypes = array(); 02794 $phpVariableName = $variableDataItem[1]; 02795 $php->addCodePiece( "\$$variableAssignmentName = \$$phpVariableName;\n", array( 'spacing' => $spacing ) ); 02796 } 02797 else if ( $variableDataType == eZTemplate::TYPE_VARIABLE ) 02798 { 02799 $knownTypes = array(); 02800 $namespace = $variableDataItem[1][0]; 02801 $namespaceScope = $variableDataItem[1][1]; 02802 $variableName = $variableDataItem[1][2]; 02803 $namespaceText = eZTemplateCompiler::generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, array( 'spacing' => $spacing ), true ); 02804 if ( !is_string( $namespaceText ) ) 02805 $namespaceText = "\$namespace"; 02806 $variableNameText = $php->thisVariableText( $variableName, 0, 0, false ); 02807 $code = "unset( \$$variableAssignmentName );\n"; 02808 $code .= "\$$variableAssignmentName = ( array_key_exists( $namespaceText, \$vars ) and array_key_exists( $variableNameText, \$vars[$namespaceText] ) ) ? \$vars[$namespaceText][$variableNameText] : null;\n"; 02809 $php->addCodePiece( $code, 02810 array( 'spacing' => $spacing ) ); 02811 } 02812 else if ( $variableDataType == eZTemplate::TYPE_ATTRIBUTE ) 02813 { 02814 $knownTypes = array(); 02815 $newParameters = $parameters; 02816 $newParameters['counter'] += 1; 02817 $tmpVariableAssignmentName = $newParameters['variable']; 02818 $tmpVariableAssignmentCounter = $newParameters['counter']; 02819 if ( $tmpVariableAssignmentCounter > 0 ) 02820 $tmpVariableAssignmentName .= $tmpVariableAssignmentCounter; 02821 if ( eZTemplateNodeTool::isConstantElement( $variableDataItem[1] ) ) 02822 { 02823 $attributeStaticValue = eZTemplateNodeTool::elementConstantValue( $variableDataItem[1] ); 02824 $attributeText = $php->thisVariableText( $attributeStaticValue, 0, 0, false ); 02825 } 02826 else 02827 { 02828 $newParameters['counter'] += 1; 02829 $tmpKnownTypes = array(); 02830 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $variableDataItem[1], $tmpKnownTypes, $dataInspection, 02831 $persistence, $newParameters, $resourceData ); 02832 $newVariableAssignmentName = $newParameters['variable']; 02833 $newVariableAssignmentCounter = $newParameters['counter']; 02834 if ( $newVariableAssignmentCounter > 0 ) 02835 $newVariableAssignmentName .= $newVariableAssignmentCounter; 02836 $attributeText = "\$$newVariableAssignmentName"; 02837 } 02838 $php->addCodePiece( "\$$tmpVariableAssignmentName = compiledFetchAttribute( \$$variableAssignmentName, $attributeText );\n" . 02839 "unset( \$$variableAssignmentName );\n" . 02840 "\$$variableAssignmentName = \$$tmpVariableAssignmentName;\n", 02841 array( 'spacing' => $spacing ) ); 02842 02843 // End if optimized node object is null/false. See also eZTemplateOptimizer::optimizeVariable() 02844 if ( $optimizeNode && 02845 $index == 3 ) 02846 { 02847 $php->addCodePiece( "}\n" ); 02848 } 02849 } 02850 else if ( $variableDataType == eZTemplate::TYPE_OPERATOR ) 02851 { 02852 $knownTypes = array(); 02853 $operatorParameters = $variableDataItem[1]; 02854 $operatorName = $operatorParameters[0]; 02855 $operatorParameters = array_splice( $operatorParameters, 1 ); 02856 $operatorNameText = $php->thisVariableText( $operatorName, 0, 0, false ); 02857 $operatorParametersText = $php->thisVariableText( $operatorParameters, 23, 0, false ); 02858 02859 $operatorHint = eZTemplateCompiler::operatorHint( $tpl, $operatorName ); 02860 if ( isset( $operatorHint['output'] ) and $operatorHint['output'] ) 02861 { 02862 if ( isset( $operatorHint['output-type'] ) ) 02863 { 02864 $knownType = $operatorHint['output-type']; 02865 if ( is_array( $knownType ) ) 02866 $knownTypes = array_merge( $knownTypes, $knownType ); 02867 else 02868 $knownTypes[] = $knownType; 02869 $knownTypes = array_unique( $knownTypes ); 02870 } 02871 else 02872 $knownTypes[] = 'static'; 02873 } 02874 02875 $php->addCodePiece( "if (! isset( \$$variableAssignmentName ) ) \$$variableAssignmentName = NULL;\n", array ( 'spacing' => $spacing ) ); 02876 $php->addCodePiece( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$variableAssignmentName ) and method_exists( \$$variableAssignmentName, 'templateValue' ) )\n" . 02877 " \$$variableAssignmentName = \$$variableAssignmentName" . "->templateValue();\n" ); 02878 $php->addCodePiece( "\$" . $variableAssignmentName . "Data = array( 'value' => \$$variableAssignmentName ); 02879 \$tpl->processOperator( $operatorNameText, 02880 $operatorParametersText, 02881 \$rootNamespace, \$currentNamespace, \$" . $variableAssignmentName . "Data, false, false ); 02882 \$$variableAssignmentName = \$" . $variableAssignmentName . "Data['value']; 02883 unset( \$" . $variableAssignmentName . "Data );\n", 02884 array( 'spacing' => $spacing ) ); 02885 } 02886 else if ( $variableDataType == eZTemplate::TYPE_VOID ) 02887 { 02888 } 02889 else if ( $variableDataType == eZTemplate::TYPE_DYNAMIC_ARRAY ) 02890 { 02891 $knownTypes = array_unique( array_merge( $knownTypes, array( 'array' ) ) ); 02892 $code = '%output% = array( '; 02893 02894 $matchMap = array( '%input%', '%output%' ); 02895 $replaceMap = array( '$' . $variableAssignmentName, '$' . $variableAssignmentName ); 02896 $unsetList = array(); 02897 $counter = 1; 02898 $paramCount = 0; 02899 02900 $values = $variableDataItem[2]; 02901 $newParameters = $parameters; 02902 foreach ( $values as $key => $value ) 02903 { 02904 if ( $paramCount != 0 ) 02905 { 02906 $code .= ', '; 02907 } 02908 ++$paramCount; 02909 $code .= '\'' . $key . '\' => '; 02910 if( eZTemplateNodeTool::isConstantElement( $value ) ) 02911 { 02912 $code .= eZPHPCreator::variableText( eZTemplateNodeTool::elementConstantValue( $value ), 0, 0, false ); 02913 continue; 02914 } 02915 $code .= '%' . $counter . '%'; 02916 $newParameters['counter'] += 1; 02917 $newVariableAssignmentName = $newParameters['variable']; 02918 $newVariableAssignmentCounter = $newParameters['counter']; 02919 if ( $newVariableAssignmentCounter > 0 ) 02920 $newVariableAssignmentName .= $newVariableAssignmentCounter; 02921 $matchMap[] = '%' . $counter . '%'; 02922 $replaceMap[] = '$' . $newVariableAssignmentName; 02923 $unsetList[] = $newVariableAssignmentName; 02924 $tmpKnownTypes = array(); 02925 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $value, $tmpKnownTypes, $dataInspection, 02926 $persistence, $newParameters, $resourceData ); 02927 ++$counter; 02928 } 02929 02930 $code .= ' );'; 02931 $code = str_replace( $matchMap, $replaceMap, $code ); 02932 $php->addCodePiece( $code, array( 'spacing' => $spacing ) ); 02933 $php->addVariableUnsetList( $unsetList, array( 'spacing' => $spacing ) ); 02934 } 02935 else if ( $variableDataType == eZTemplate::TYPE_INTERNAL_CODE_PIECE ) 02936 { 02937 $code = $variableDataItem[1]; 02938 $values = false; 02939 $matchMap = array( '%input%', '%output%' ); 02940 $replaceMap = array( '$' . $variableAssignmentName, '$' . $variableAssignmentName ); 02941 $unsetList = array(); 02942 $counter = 1; 02943 if ( isset( $variableDataItem[3] ) && is_array( $variableDataItem[3] ) ) 02944 { 02945 $newParameters = $parameters; 02946 $values = $variableDataItem[3]; 02947 foreach ( $values as $value ) 02948 { 02949 $newParameters['counter'] += 1; 02950 $newVariableAssignmentName = $newParameters['variable']; 02951 $newVariableAssignmentCounter = $newParameters['counter']; 02952 if ( $newVariableAssignmentCounter > 0 ) 02953 $newVariableAssignmentName .= $newVariableAssignmentCounter; 02954 if ( eZTemplateNodeTool::isConstantElement( $value ) ) 02955 { 02956 $staticValue = eZTemplateNodeTool::elementConstantValue( $value ); 02957 $staticValueText = $php->thisVariableText( $staticValue, 0, 0, false ); 02958 if ( preg_match( "/%code$counter%/", $code ) ) 02959 { 02960 $matchMap[] = '%code' . $counter . '%'; 02961 $replaceMap[] = ''; 02962 } 02963 $matchMap[] = '%' . $counter . '%'; 02964 $replaceMap[] = $staticValueText; 02965 } 02966 else 02967 { 02968 $matchMap[] = '%' . $counter . '%'; 02969 $replaceMap[] = '$' . $newVariableAssignmentName; 02970 $unsetList[] = $newVariableAssignmentName; 02971 if ( preg_match( "/%code$counter%/", $code ) ) 02972 { 02973 $tmpPHP = new eZPHPCreator( '', '', eZTemplateCompiler::TemplatePrefix() ); 02974 $tmpKnownTypes = array(); 02975 eZTemplateCompiler::generateVariableDataCode( $tmpPHP, $tpl, $value, $tmpKnownTypes, $dataInspection, 02976 $persistence, $newParameters, $resourceData ); 02977 $newCode = $tmpPHP->fetch( false ); 02978 if ( count( $tmpKnownTypes ) == 0 or in_array( 'objectproxy', $tmpKnownTypes ) ) 02979 { 02980 $newCode .= ( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$newVariableAssignmentName ) and method_exists( \$$newVariableAssignmentName, 'templateValue' ) )\n" . 02981 " \$$newVariableAssignmentName = \$$newVariableAssignmentName" . "->templateValue();\n" ); 02982 } 02983 $matchMap[] = '%code' . $counter . '%'; 02984 $replaceMap[] = $newCode; 02985 } 02986 else 02987 { 02988 $tmpKnownTypes = array(); 02989 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $value, $tmpKnownTypes, $dataInspection, 02990 $persistence, $newParameters, $resourceData ); 02991 if ( !$parameters['treat-value-as-non-object'] and ( count( $tmpKnownTypes ) == 0 or in_array( 'objectproxy', $tmpKnownTypes ) ) ) 02992 { 02993 $php->addCodePiece( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$newVariableAssignmentName ) and method_exists( \$$newVariableAssignmentName, 'templateValue' ) )\n" . 02994 " \$$newVariableAssignmentName = \$$newVariableAssignmentName" . "->templateValue();\n", 02995 array( 'spacing' => $spacing ) ); 02996 } 02997 } 02998 } 02999 ++$counter; 03000 } 03001 } 03002 if ( isset( $variableDataItem[4] ) && ( $variableDataItem[4] !== false ) ) 03003 { 03004 $values = $variableDataItem[4]; 03005 03006 for ( $i = 0; $i < $values; $i++ ) 03007 { 03008 $newParameters['counter'] += 1; 03009 $newVariableAssignmentName = $newParameters['variable']; 03010 $newVariableAssignmentCounter = $newParameters['counter']; 03011 if ( $newVariableAssignmentCounter > 0 ) 03012 $newVariableAssignmentName .= $newVariableAssignmentCounter; 03013 $matchMap[] = '%tmp' . ( $i + 1 ) . '%'; 03014 $replaceMap[] = '$' . $newVariableAssignmentName; 03015 $unsetList[] = $newVariableAssignmentName; 03016 } 03017 } 03018 if ( isset( $variableDataItem[5] ) and $variableDataItem[5] ) 03019 { 03020 if ( is_array( $variableDataItem[5] ) ) 03021 $knownTypes = array_unique( array_merge( $knownTypes, $variableDataItem[5] ) ); 03022 else if ( is_string( $variableDataItem[5] ) ) 03023 $knownTypes = array_unique( array_merge( $knownTypes, array( $variableDataItem[5] ) ) ); 03024 else 03025 $knownTypes = array_unique( array_merge( $knownTypes, array( 'static' ) ) ); 03026 } 03027 $code = str_replace( $matchMap, $replaceMap, $code ); 03028 $php->addCodePiece( $code, array( 'spacing' => $spacing ) ); 03029 $php->addVariableUnsetList( $unsetList, array( 'spacing' => $spacing ) ); 03030 } 03031 } 03032 } 03033 // After the entire expression line is done we try to extract the actual value if proxies are used 03034 $php->addCodePiece( "if (! isset( \$$variableAssignmentName ) ) \$$variableAssignmentName = NULL;\n" ); 03035 $php->addCodePiece( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$variableAssignmentName ) and method_exists( \$$variableAssignmentName, 'templateValue' ) )\n" . 03036 " \$$variableAssignmentName = \$$variableAssignmentName" . "->templateValue();\n" ); 03037 } 03038 } 03039 03040 ?>