| [ Index ] |
|
Code source de eZ Publish 3.9.0 |
1 <?php 2 // 3 // Definition of eZTemplateCompiler class 4 // 5 // Created on: <06-Dec-2002 14:17:10 amos> 6 // 7 // SOFTWARE NAME: eZ publish 8 // SOFTWARE RELEASE: 3.9.0 9 // BUILD VERSION: 17785 10 // COPYRIGHT NOTICE: Copyright (C) 1999-2006 eZ systems AS 11 // SOFTWARE LICENSE: GNU General Public License v2.0 12 // NOTICE: > 13 // This program is free software; you can redistribute it and/or 14 // modify it under the terms of version 2.0 of the GNU General 15 // Public License as published by the Free Software Foundation. 16 // 17 // This program is distributed in the hope that it will be useful, 18 // but WITHOUT ANY WARRANTY; without even the implied warranty of 19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 // GNU General Public License for more details. 21 // 22 // You should have received a copy of version 2.0 of the GNU General 23 // Public License along with this program; if not, write to the Free 24 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 25 // MA 02110-1301, USA. 26 // 27 // 28 29 /*! \file eztemplatecompiler.php 30 */ 31 32 /*! 33 \class eZTemplateCompiler eztemplatecompiler.php 34 \brief Creates compiled PHP code from templates to speed up template usage. 35 36 Various optimizations that can be done are: 37 38 Data: 39 - Is constant, generate static data 40 - Is variable, generate direct variable extraction 41 - Has operators 42 - Has attributes 43 44 Attributes: 45 - Is constant, generate static data 46 47 Operators: 48 - Supports input 49 - Supports output 50 - Supports parameters 51 - Generates static data (true, false) 52 - Custom PHP code 53 - Modifies template variables, if possible name which ones. Allows 54 for caching of variables in the script. 55 56 Functions: 57 - Supports parameters 58 - Supports children (set? no, section? yes) 59 - Generates static data (ldelim,rdelim) 60 - Children usage, no result(set-block) | copy(let,default) | dynamic(conditional, repeated etc.) 61 - Children tree, requires original tree | allows custom processing 62 - Custom PHP code 63 - Deflate/transform tree, create new non-nested tree (let, default) 64 - Modifies template variables, if possible name which ones. Allows 65 for caching of variables in the script. 66 */ 67 68 include_once ( 'lib/ezutils/classes/ezdebug.php' ); 69 70 define( 'EZ_TEMPLATE_COMPILE_CODE_DATE', 1074699607 ); 71 72 class eZTemplateCompiler 73 { 74 /*! 75 Constructor 76 */ 77 function eZTemplateCompiler() 78 { 79 } 80 81 /*! 82 \static 83 Returns the prefix for file names 84 */ 85 function TemplatePrefix() 86 { 87 $templatePrefix = ''; 88 include_once ( 'lib/ezutils/classes/ezini.php' ); 89 $ini =& eZINI::instance(); 90 if ( $ini->variable( 'TemplateSettings', 'TemplateCompression' ) == 'enabled' ) 91 { 92 $templatePrefix = 'compress.zlib://'; 93 } 94 return $templatePrefix; 95 } 96 /*! 97 \static 98 Sets/unsets various compiler settings. To set a setting add a key in the \a $settingsMap 99 with the wanted value, to unset it use \c null as the value. 100 101 The following values can be set. 102 - compile - boolean, whether to compile templates or not 103 - comments - boolean, whether to include comments in templates 104 - accumulators - boolean, whether to include debug accumulators in templates 105 - timingpoints - boolean, whether to include debug timingpoints in templates 106 - fallbackresource - boolean, whether to include the fallback resource code 107 - nodeplacement - boolean, whether to include information on placement of all nodes 108 - execution - boolean, whether to execute the compiled templates or not 109 - generate - boolean, whether to always generate the compiled files, or only when template is changed 110 - compilation-directory - string, where to place compiled files, the path will be relative from the 111 eZ publish directory and not the var/cache directory. 112 */ 113 function setSettings( $settingsMap ) 114 { 115 $existingMap = array(); 116 if ( isset( $GLOBALS['eZTemplateCompilerSettings'] ) ) 117 { 118 $existingMap = $GLOBALS['eZTemplateCompilerSettings']; 119 } 120 $GLOBALS['eZTemplateCompilerSettings'] = array_merge( $existingMap, $settingsMap ); 121 } 122 123 /*! 124 \static 125 \return true if template compiling is enabled. 126 \note To change this setting edit settings/site.ini and locate the group TemplateSettings and the entry TemplateCompile. 127 */ 128 function isCompilationEnabled() 129 { 130 if ( isset( $GLOBALS['eZSiteBasics'] ) ) 131 { 132 $siteBasics = $GLOBALS['eZSiteBasics']; 133 if ( isset( $siteBasics['no-cache-adviced'] ) and 134 $siteBasics['no-cache-adviced'] ) 135 { 136 return false; 137 } 138 } 139 140 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['compile'] ) and 141 $GLOBALS['eZTemplateCompilerSettings']['compile'] !== null ) 142 { 143 return $GLOBALS['eZTemplateCompilerSettings']['compile']; 144 } 145 146 include_once ( 'lib/ezutils/classes/ezini.php' ); 147 $ini =& eZINI::instance(); 148 $compilationEnabled = $ini->variable( 'TemplateSettings', 'TemplateCompile' ) == 'enabled'; 149 return $compilationEnabled; 150 } 151 152 /*! 153 \static 154 \return true if template compilation should include comments. 155 */ 156 function isCommentsEnabled() 157 { 158 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['comments'] ) and 159 $GLOBALS['eZTemplateCompilerSettings']['comments'] !== null ) 160 { 161 return $GLOBALS['eZTemplateCompilerSettings']['comments']; 162 } 163 164 include_once ( 'lib/ezutils/classes/ezini.php' ); 165 $ini =& eZINI::instance(); 166 $commentsEnabled = $ini->variable( 'TemplateSettings', 'CompileComments' ) == 'enabled'; 167 return $commentsEnabled; 168 } 169 170 /*! 171 \static 172 \return true if template compilation should run in development mode. 173 174 When in development mode the system will perform additional checks, e.g. for 175 modification time of compiled file vs original source file. 176 This mode is quite useful for development since it requires less 177 clear-cache calls but has additional file checks and should be turned off 178 for live sites. 179 */ 180 function isDevelopmentModeEnabled() 181 { 182 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['development_mode'] ) and 183 $GLOBALS['eZTemplateCompilerSettings']['development_mode'] !== null ) 184 { 185 return $GLOBALS['eZTemplateCompilerSettings']['development_mode']; 186 } 187 188 include_once ( 'lib/ezutils/classes/ezini.php' ); 189 $ini =& eZINI::instance(); 190 $developmentModeEnabled = $ini->variable( 'TemplateSettings', 'DevelopmentMode' ) == 'enabled'; 191 return $developmentModeEnabled; 192 } 193 194 /*! 195 \static 196 \return true if template compilation should include debug accumulators. 197 */ 198 function isAccumulatorsEnabled() 199 { 200 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['accumulators'] ) and 201 $GLOBALS['eZTemplateCompilerSettings']['accumulators'] !== null ) 202 { 203 return $GLOBALS['eZTemplateCompilerSettings']['accumulators']; 204 } 205 206 include_once ( 'lib/ezutils/classes/ezini.php' ); 207 $ini =& eZINI::instance(); 208 $enabled = $ini->variable( 'TemplateSettings', 'CompileAccumulators' ) == 'enabled'; 209 return $enabled; 210 } 211 212 /*! 213 \static 214 \return true if template compilation should include debug timing points. 215 */ 216 function isTimingPointsEnabled() 217 { 218 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['timingpoints'] ) and 219 $GLOBALS['eZTemplateCompilerSettings']['timingpoints'] !== null ) 220 { 221 return $GLOBALS['eZTemplateCompilerSettings']['timingpoints']; 222 } 223 224 include_once ( 'lib/ezutils/classes/ezini.php' ); 225 $ini =& eZINI::instance(); 226 $enabled = $ini->variable( 'TemplateSettings', 'CompileTimingPoints' ) == 'enabled'; 227 return $enabled; 228 } 229 230 /*! 231 \static 232 \return true if resource fallback code should be included. 233 */ 234 function isFallbackResourceCodeEnabled() 235 { 236 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['fallbackresource'] ) and 237 $GLOBALS['eZTemplateCompilerSettings']['fallbackresource'] !== null ) 238 { 239 return $GLOBALS['eZTemplateCompilerSettings']['fallbackresource']; 240 } 241 242 include_once ( 'lib/ezutils/classes/ezini.php' ); 243 $ini =& eZINI::instance(); 244 $enabled = $ini->variable( 'TemplateSettings', 'CompileResourceFallback' ) == 'enabled'; 245 return $enabled; 246 } 247 248 /*! 249 \static 250 \return true if template compilation should include comments. 251 */ 252 function isNodePlacementEnabled() 253 { 254 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['nodeplacement'] ) and 255 $GLOBALS['eZTemplateCompilerSettings']['nodeplacement'] !== null ) 256 { 257 return $GLOBALS['eZTemplateCompilerSettings']['nodeplacement']; 258 } 259 260 include_once ( 'lib/ezutils/classes/ezini.php' ); 261 $ini =& eZINI::instance(); 262 $nodePlacementEnabled = $ini->variable( 'TemplateSettings', 'CompileNodePlacements' ) == 'enabled'; 263 return $nodePlacementEnabled; 264 } 265 266 /*! 267 \static 268 \return true if the compiled template execution is enabled. 269 */ 270 function isExecutionEnabled() 271 { 272 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['execution'] ) and 273 $GLOBALS['eZTemplateCompilerSettings']['execution'] !== null ) 274 { 275 return $GLOBALS['eZTemplateCompilerSettings']['execution']; 276 } 277 278 include_once ( 'lib/ezutils/classes/ezini.php' ); 279 $ini =& eZINI::instance(); 280 $execution = $ini->variable( 'TemplateSettings', 'CompileExecution' ) == 'enabled'; 281 return $execution; 282 } 283 284 /*! 285 \static 286 \return true if template compilation should always be run even if a sufficient compilation already exists. 287 */ 288 function alwaysGenerate() 289 { 290 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['generate'] ) and 291 $GLOBALS['eZTemplateCompilerSettings']['generate'] !== null ) 292 { 293 return $GLOBALS['eZTemplateCompilerSettings']['generate']; 294 } 295 296 include_once ( 'lib/ezutils/classes/ezini.php' ); 297 $ini =& eZINI::instance(); 298 $alwaysGenerate = $ini->variable( 'TemplateSettings', 'CompileAlwaysGenerate' ) == 'enabled'; 299 return $alwaysGenerate; 300 } 301 302 /*! 303 \static 304 \return true if template node tree named \a $treeName should be included the compiled template. 305 */ 306 function isTreeEnabled( $treeName ) 307 { 308 include_once ( 'lib/ezutils/classes/ezini.php' ); 309 $ini =& eZINI::instance(); 310 $treeList = $ini->variable( 'TemplateSettings', 'CompileIncludeNodeTree' ); 311 return in_array( $treeName, $treeList ); 312 } 313 314 /*! 315 \static 316 \return the directory for compiled templates. 317 */ 318 function compilationDirectory() 319 { 320 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['compilation-directory'] ) and 321 $GLOBALS['eZTemplateCompilerSettings']['compilation-directory'] !== null ) 322 { 323 return $GLOBALS['eZTemplateCompilerSettings']['compilation-directory']; 324 } 325 326 $compilationDirectory =& $GLOBALS['eZTemplateCompilerDirectory']; 327 if ( !isset( $compilationDirectory ) ) 328 { 329 include_once ( 'lib/ezfile/classes/ezdir.php' ); 330 include_once ( 'lib/ezutils/classes/ezsys.php' ); 331 $compilationDirectory = eZDir::path( array( eZSys::cacheDirectory(), 'template/compiled' ) ); 332 } 333 return $compilationDirectory; 334 } 335 336 /*! 337 Creates the name for the compiled template and returns it. 338 The name conists of original filename with the md5 of the key and charset appended. 339 */ 340 function compilationFilename( $key, $resourceData ) 341 { 342 $internalCharset = eZTextCodec::internalCharset(); 343 $templateFilepath = $resourceData['template-filename']; 344 $extraName = ''; 345 if ( preg_match( "#^.+/(.*)\.tpl$#", $templateFilepath, $matches ) ) 346 $extraName = $matches[1] . '-'; 347 else if ( preg_match( "#^(.*)\.tpl$#", $templateFilepath, $matches ) ) 348 $extraName = $matches[1] . '-'; 349 $accessText = false; 350 if ( isset( $GLOBALS['eZCurrentAccess']['name'] ) ) 351 $accessText = '-' . $GLOBALS['eZCurrentAccess']['name']; 352 include_once ( 'lib/ezlocale/classes/ezlocale.php' ); 353 $locale =& eZLocale::instance(); 354 $language = $locale->translationCode(); 355 include_once ( 'lib/ezutils/classes/ezhttptool.php' ); 356 $http =& eZHTTPTool::instance(); 357 $useFullUrlText = $http->UseFullUrl ? 'full' : 'relative'; 358 359 $pageLayoutVariable = ""; 360 if ( isset( $GLOBALS['eZCustomPageLayout'] ) ) 361 $pageLayoutVariable = $GLOBALS['eZCustomPageLayout']; 362 $cacheFileKey = $key . '-' . $internalCharset . '-' . $language . '-' . $useFullUrlText . $accessText . "-" . $pageLayoutVariable . '-' . eZSys::indexFile(); 363 $cacheFileName = $extraName . md5( $cacheFileKey ) . '.php'; 364 return $cacheFileName; 365 } 366 367 /*! 368 \static 369 \return true if the compiled template with the key \a $key exists. 370 A compiled template is found usable when it exists and has a timestamp 371 higher or equal to \a $timestamp. 372 */ 373 function hasCompiledTemplate( $key, $timestamp, &$resourceData ) 374 { 375 if ( !eZTemplateCompiler::isCompilationEnabled() ) 376 return false; 377 if ( eZTemplateCompiler::alwaysGenerate() ) 378 return false; 379 380 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $resourceData ); 381 382 include_once ( 'lib/ezutils/classes/ezphpcreator.php' ); 383 384 $php = new eZPHPCreator( eZTemplateCompiler::compilationDirectory(), $cacheFileName, eZTemplateCompiler::TemplatePrefix() ); 385 $canRestore = $php->canRestore( $timestamp ); 386 $uri = false; 387 if ( $canRestore ) 388 eZDebugSetting::writeDebug( 'eztemplate-compile', "Cache hit for uri '$uri' with key '$key'", 'eZTemplateCompiler::hasCompiledTemplate' ); 389 else 390 eZDebugSetting::writeDebug( 'eztemplate-compile', "Cache miss for uri '$uri' with key '$key'", 'eZTemplateCompiler::hasCompiledTemplate' ); 391 return $canRestore; 392 } 393 394 /*! 395 Tries to execute the compiled template and returns \c true if succsesful. 396 Returns \c false if caching is disabled or the compiled template could not be executed. 397 */ 398 function executeCompilation( &$tpl, &$textElements, $key, &$resourceData, 399 $rootNamespace, $currentNamespace ) 400 { 401 if ( !eZTemplateCompiler::isCompilationEnabled() ) 402 return false; 403 if ( !eZTemplateCompiler::isExecutionEnabled() ) 404 return false; 405 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $resourceData ); 406 $resourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled(); 407 408 $directory = eZTemplateCompiler::compilationDirectory(); 409 $phpScript = eZDir::path( array( $directory, $cacheFileName ) ); 410 if ( file_exists( $phpScript ) ) 411 { 412 $text = false; 413 $helperStatus = eZTemplateCompiler::executeCompilationHelper( $phpScript, $text, 414 $tpl, $key, $resourceData, 415 $rootNamespace, $currentNamespace ); 416 if ( $helperStatus ) 417 { 418 $textElements[] = $text; 419 return true; 420 } 421 else 422 eZDebug::writeError( "Failed executing compiled template '$phpScript'", 'eZTemplateCompiler::executeCompilation' ); 423 } 424 else 425 eZDebug::writeError( "Unknown compiled template '$phpScript'", 'eZTemplateCompiler::executeCompilation' ); 426 return false; 427 } 428 429 /*! 430 Helper function for executeCompilation. Will execute the script \a $phpScript and 431 set the result text in \a $text. 432 The parameters \a $tpl, \a $resourceData, \a $rootNamespace and \a $currentNamespace 433 are passed to the executed template compilation script. 434 \return true if a text result was created. 435 */ 436 function executeCompilationHelper( $phpScript, &$text, 437 &$tpl, $key, &$resourceData, 438 $rootNamespace, $currentNamespace ) 439 { 440 $vars =& $tpl->Variables; 441 442 /* We use $setArray to detect if execution failed, and not $text, 443 * because an empty template does not return any $text and this is not 444 * an error. */ 445 $setArray = null; 446 $namespaceStack = array(); 447 448 $tpl->createLocalVariablesList(); 449 include( eZTemplateCompiler::TemplatePrefix() . $phpScript ); 450 $tpl->unsetLocalVariables(); 451 $tpl->destroyLocalVariablesList(); 452 453 if ( $setArray !== null ) 454 { 455 return true; 456 } 457 return false; 458 } 459 460 /*! 461 \static 462 Generates the cache which will be used for handling optimized processing using the key \a $key. 463 \note Each call to this will set the PHP time limit to 30 464 \return false if the cache does not exist. 465 */ 466 function compileTemplate( &$tpl, $key, &$resourceData ) 467 { 468 if ( !eZTemplateCompiler::isCompilationEnabled() ) 469 return false; 470 471 $resourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled(); 472 473 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $resourceData ); 474 $resourceData['uniqid'] = md5( $resourceData['template-filename']. uniqid( "ezp". getmypid(), true ) ); 475 476 // Time limit #1: 477 // We reset the time limit to 30 seconds to ensure that templates 478 // have enough time to compile 479 // However if time limit is unlimited (0) we leave it be 480 // Time limit will also be reset after subtemplates are compiled 481 $maxExecutionTime = ini_get( 'max_execution_time' ); 482 if ( $maxExecutionTime != 0 && $maxExecutionTime < 30 ) 483 { 484 @set_time_limit( 30 ); 485 } 486 487 $rootNode =& $resourceData['root-node']; 488 if ( !$rootNode ) 489 return false; 490 491 include_once ( 'lib/eztemplate/classes/eztemplatenodetool.php' ); 492 include_once ( 'lib/ezutils/classes/ezphpcreator.php' ); 493 494 $GLOBALS['eZTemplateCompilerResourceCache'][$resourceData['template-filename']] =& $resourceData; 495 496 $useComments = eZTemplateCompiler::isCommentsEnabled(); 497 498 if ( !$resourceData['test-compile'] ) 499 { 500 eZTemplateCompiler::createCommonCompileTemplate(); 501 } 502 503 /* Check if we need to disable the generation of spacing for the compiled templates */ 504 $ini =& eZINI::instance(); 505 $spacing = 'disabled'; 506 if ( $ini->variable( 'TemplateSettings', 'UseFormatting' ) == 'enabled' ) 507 { 508 $spacing = 'enabled'; 509 } 510 511 $php = new eZPHPCreator( eZTemplateCompiler::compilationDirectory(), $cacheFileName, 512 eZTemplateCompiler::TemplatePrefix(), array( 'spacing' => $spacing ) ); 513 $php->addComment( 'URI: ' . $resourceData['uri'] ); 514 $php->addComment( 'Filename: ' . $resourceData['template-filename'] ); 515 $php->addComment( 'Timestamp: ' . $resourceData['time-stamp'] . ' (' . date( 'D M j G:i:s T Y', $resourceData['time-stamp'] ) . ')' ); 516 517 $php->addCodePiece("\$oldSetArray_{$resourceData['uniqid']} = isset( \$setArray ) ? \$setArray : array();\n". 518 "\$setArray = array();\n"); 519 // Code to decrement include level of the templates 520 $php->addCodePiece( "\$tpl->Level++;\n" ); 521 $php->addCodePiece( "if ( \$tpl->Level > $tpl->MaxLevel )\n". 522 "{\n". 523 "\$text = \$tpl->MaxLevelWarning;". 524 "\$tpl->Level--;\n". 525 "return;\n". 526 "}\n" ); 527 if ( $resourceData['locales'] && count( $resourceData['locales'] ) ) 528 { 529 $php->addComment( 'Locales: ' . join( ', ', $resourceData['locales'] ) ); 530 531 $php->addCodePiece( 532 '$locales = array( "'. join( '", "', $resourceData['locales'] ) . "\" );\n". 533 '$oldLocale_'. $resourceData['uniqid']. ' = setlocale( LC_CTYPE, null );'. "\n". 534 '$currentLocale_'. $resourceData['uniqid']. ' = setlocale( LC_CTYPE, $locales );'. "\n" 535 ); 536 } 537 // $php->addCodePiece( "print( \"" . $resourceData['template-filename'] . " ($cacheFileName)<br/>\n\" );" ); 538 if ( $useComments ) 539 { 540 $templateFilename = $resourceData['template-filename']; 541 if ( file_exists( $templateFilename ) ) 542 { 543 $fd = fopen( $templateFilename, 'rb' ); 544 if ( $fd ) 545 { 546 $templateText = fread( $fd, filesize( $templateFilename ) ); 547 $php->addComment( "Original code:\n" . $templateText ); 548 fclose( $fd ); 549 } 550 } 551 } 552 $php->addVariable( 'eZTemplateCompilerCodeDate', EZ_TEMPLATE_COMPILE_CODE_DATE ); 553 $php->addCodePiece( "if ( !defined( 'EZ_TEMPLATE_COMPILER_COMMON_CODE' ) )\n" ); 554 $php->addInclude( eZTemplateCompiler::compilationDirectory() . '/common.php', EZ_PHPCREATOR_INCLUDE_ONCE, array( 'spacing' => 4 ) ); 555 $php->addSpace(); 556 557 if ( eZTemplateCompiler::isAccumulatorsEnabled() ) 558 $php->addCodePiece( "eZDebug::accumulatorStart( 'template_compiled_execution', 'template_total', 'Template compiled execution', true );\n" ); 559 if ( eZTemplateCompiler::isTimingPointsEnabled() ) 560 $php->addCodePiece( "eZDebug::addTimingPoint( 'Script start $cacheFileName' );\n" ); 561 562 // $php->addCodePiece( "if ( !isset( \$vars ) )\n \$vars =& \$tpl->Variables;\n" ); 563 // $php->addSpace(); 564 565 $parameters = array(); 566 $textName = eZTemplateCompiler::currentTextName( $parameters ); 567 568 // $php->addCodePiece( "if ( !isset( \$$textName ) )\n \$$textName = '';\n" ); 569 // $php->addSpace(); 570 571 // $variableStats = array(); 572 // eZTemplateCompiler::prepareVariableStatistics( $tpl, $resourceData, $variableStats ); 573 // eZTemplateCompiler::calculateVariableStatistics( $tpl, $rootNode, $resourceData, $variableStats ); 574 // print_r( $variableStats ); 575 576 $transformedTree = array(); 577 eZTemplateCompiler::processNodeTransformation( $useComments, $php, $tpl, $rootNode, $resourceData, $transformedTree ); 578 579 if ( $ini->variable( 'TemplateSettings', 'TemplateOptimization' ) == 'enabled' ) 580 { 581 require_once ('lib/eztemplate/classes/eztemplateoptimizer.php'); 582 /* Retrieve class information for the attribute lookup table */ 583 if ( isset( $resourceData['handler']->Keys ) and isset( $resourceData['handler']->Keys['class'] ) ) { 584 $resourceData['class-info'] = eZTemplateOptimizer::fetchClassDeclaration( $resourceData['handler']->Keys['class'] ); 585 } 586 /* Run the optimizations */ 587 eZTemplateOptimizer::optimize( $useComments, $php, $tpl, $transformedTree, $resourceData ); 588 } 589 590 $staticTree = array(); 591 eZTemplateCompiler::processStaticOptimizations( $useComments, $php, $tpl, $transformedTree, $resourceData, $staticTree ); 592 593 $combinedTree = array(); 594 eZTemplateCompiler::processNodeCombining( $useComments, $php, $tpl, $staticTree, $resourceData, $combinedTree ); 595 596 $finalTree = $combinedTree; 597 if ( !eZTemplateCompiler::isNodePlacementEnabled() ) 598 eZTemplateCompiler::processRemoveNodePlacement( $finalTree ); 599 600 eZTemplateCompiler::generatePHPCode( $useComments, $php, $tpl, $finalTree, $resourceData ); 601 602 if ( eZTemplateCompiler::isTreeEnabled( 'final' ) ) 603 $php->addVariable( 'finalTree', $finalTree, EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) ); 604 if ( eZTemplateCompiler::isTreeEnabled( 'combined' ) ) 605 $php->addVariable( 'combinedTree', $combinedTree, EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) ); 606 if ( eZTemplateCompiler::isTreeEnabled( 'static' ) ) 607 $php->addVariable( 'staticTree', $staticTree, EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) ); 608 if ( eZTemplateCompiler::isTreeEnabled( 'transformed' ) ) 609 $php->addVariable( 'transformedTree', $transformedTree, EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) ); 610 if ( eZTemplateCompiler::isTreeEnabled( 'original' ) ) 611 $php->addVariable( 'originalTree', $rootNode, EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) ); 612 613 if ( eZTemplateCompiler::isTimingPointsEnabled() ) 614 $php->addCodePiece( "eZDebug::addTimingPoint( 'Script end $cacheFileName' );\n" ); 615 if ( eZTemplateCompiler::isAccumulatorsEnabled() ) 616 $php->addCodePiece( "eZDebug::accumulatorStop( 'template_compiled_execution', true );\n" ); 617 618 if ( $resourceData['locales'] && count( $resourceData['locales'] ) ) 619 { 620 $php->addCodePiece( 621 'setlocale( LC_CTYPE, $oldLocale_'. $resourceData['uniqid']. ' );'. "\n" 622 ); 623 } 624 $php->addCodePiece('$setArray = $oldSetArray_'. $resourceData['uniqid']. ";\n"); 625 626 // Code to decrement include level of the templates 627 $php->addCodePiece("\$tpl->Level--;\n" ); 628 629 /* 630 // dump names of all defined PHP variables 631 $php->addCodePiece( "echo \"defined vars in $resourceData[uri]:<br/><pre>\\n\";\n" ); 632 $php->addCodePiece( 'foreach ( array_keys( get_defined_vars() ) as $var_name ) echo "- $var_name\n";' ); 633 // dump tpl vars 634 $php->addCodePiece( 'echo "\n-----------------------------------------------------------\nvars: ";' ); 635 $php->addCodePiece( 'var_dump( $vars );' ); 636 $php->addCodePiece( 'echo "</pre><hr/>\n";' ); 637 */ 638 639 if ( !$resourceData['test-compile'] ) 640 { 641 $php->store( true ); 642 } 643 644 return true; 645 } 646 647 function prepareVariableStatistics( &$tpl, &$resourceData, &$stats ) 648 { 649 // $path = $resourceData['template-filename']; 650 // $info =& $GLOBALS['eZTemplateCompileVariableInfo'][$path]; 651 if ( isset( $resourceData['variable-info'] ) ) 652 { 653 } 654 } 655 656 /*! 657 */ 658 function calculateVariableStatistics( &$tpl, &$node, &$resourceData, &$stats ) 659 { 660 $nodeType = $node[0]; 661 if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 662 { 663 $children = $node[1]; 664 $namespace = ''; 665 if ( $children ) 666 { 667 eZTemplateCompiler::calculateVariableStatisticsChildren( $tpl, $children, $resourceData, $namespace, $stats ); 668 } 669 } 670 else 671 $tpl->error( 'calculateVariableStatistics', "Unknown root type $nodeType, should be " . EZ_TEMPLATE_NODE_ROOT ); 672 } 673 674 function calculateVariableStatisticsChildren( &$tpl, &$nodeChildren, &$resourceData, $namespace, &$stats ) 675 { 676 foreach ( $nodeChildren as $node ) 677 { 678 if ( !isset( $node[0] ) ) 679 continue; 680 $nodeType = $node[0]; 681 if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 682 { 683 $children = $node[1]; 684 if ( $children ) 685 { 686 eZTemplateCompiler::calculateVariableStatisticsChildren( $tpl, $children, $resourceData, $namespace, $stats ); 687 } 688 } 689 else if ( $nodeType == EZ_TEMPLATE_NODE_TEXT ) 690 { 691 $text = $node[2]; 692 $placement = $node[3]; 693 } 694 else if ( $nodeType == EZ_TEMPLATE_NODE_VARIABLE ) 695 { 696 $variableData = $node[2]; 697 $variablePlacement = $node[3]; 698 $variableParameters = false; 699 eZTemplateCompiler::calculateVariableNodeStatistics( $tpl, $variableData, $variablePlacement, $resourceData, $namespace, $stats ); 700 } 701 else if ( $nodeType == EZ_TEMPLATE_NODE_FUNCTION ) 702 { 703 $functionChildren = $node[1]; 704 $functionName = $node[2]; 705 $functionParameters = $node[3]; 706 $functionPlacement = $node[4]; 707 708 if ( !isset( $tpl->Functions[$functionName] ) ) 709 continue; 710 711 if ( is_array( $tpl->Functions[$functionName] ) ) 712 { 713 $tpl->loadAndRegisterOperators( $tpl->Functions[$functionName] ); 714 } 715 $functionObject =& $tpl->Functions[$functionName]; 716 if ( is_object( $functionObject ) ) 717 { 718 $hasTransformationSupport = false; 719 $transformChildren = true; 720 if ( method_exists( $functionObject, 'functionTemplateStatistics' ) ) 721 { 722 $functionObject->functionTemplateStatistics( $functionName, $node, $tpl, $resourceData, $namespace, $stats ); 723 } 724 } 725 else if ( $resourceData['test-compile'] ) 726 { 727 $tpl->warning( '', "Operator '$operatorName' is not registered.", $functionPlacement ); 728 } 729 } 730 } 731 } 732 733 function calculateVariableNodeStatistics( &$tpl, $variableData, $variablePlacement, &$resourceData, $namespace, &$stats ) 734 { 735 if ( !is_array( $variableData ) ) 736 return false; 737 foreach ( $variableData as $variableItem ) 738 { 739 $variableItemType = $variableItem[0]; 740 $variableItemData = $variableItem[1]; 741 $variableItemPlacement = $variableItem[2]; 742 if ( $variableItemType == EZ_TEMPLATE_TYPE_STRING or 743 $variableItemType == EZ_TEMPLATE_TYPE_IDENTIFIER ) 744 { 745 } 746 else if ( $variableItemType == EZ_TEMPLATE_TYPE_NUMERIC ) 747 { 748 } 749 else if ( $variableItemType == EZ_TEMPLATE_TYPE_ARRAY ) 750 { 751 } 752 else if ( $variableItemType == EZ_TEMPLATE_TYPE_BOOLEAN ) 753 { 754 } 755 else if ( $variableItemType == EZ_TEMPLATE_TYPE_VARIABLE ) 756 { 757 $variableNamespace = $variableItemData[0]; 758 $variableNamespaceScope = $variableItemData[1]; 759 $variableName = $variableItemData[2]; 760 if ( $variableNamespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_GLOBAL ) 761 $newNamespace = $variableNamespace; 762 else if ( $variableNamespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_LOCAL ) 763 $newNamespace = $variableNamespace; 764 else if ( $variableNamespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_RELATIVE ) 765 $newNamespace = $tpl->mergeNamespace( $namespace, $variableNamespace ); 766 else 767 $newNamespace = false; 768 eZTemplateCompiler::setVariableStatistics( $stats, $newNamespace, $variableName, array( 'is_accessed' => true ) ); 769 } 770 else if ( $variableItemType == EZ_TEMPLATE_TYPE_ATTRIBUTE ) 771 { 772 eZTemplateCompiler::calculateVariableNodeStatistics( $tpl, $variableItemData, $variableItemPlacement, $resourceData, $namespace, $stats ); 773 } 774 else if ( $variableItemType == EZ_TEMPLATE_TYPE_OPERATOR ) 775 { 776 $operatorName = $variableItemData[0]; 777 778 if ( !isset( $tpl->Operators[$operatorName] ) ) 779 continue; 780 781 if ( is_array( $tpl->Operators[$operatorName] ) ) 782 { 783 $tpl->loadAndRegisterOperators( $tpl->Operators[$operatorName] ); 784 } 785 $operator =& $tpl->Operators[$operatorName]; 786 787 if ( is_object( $operator ) ) 788 { 789 $hasStats = false; 790 if ( method_exists( $operator, 'operatorTemplateHints' ) ) 791 { 792 $hints = $operator->operatorTemplateHints(); 793 if ( isset( $hints[$operatorName] ) ) 794 { 795 $operatorHints = $hints[$operatorName]; 796 $hasParameters = false; 797 if ( isset( $operatorHints['parameters'] ) ) 798 $hasParameters = $operatorHints['parameters']; 799 if ( $hasParameters === true ) 800 { 801 $parameters = $variableItemData; 802 $count = count( $parameters ) - 1; 803 for ( $i = 0; $i < $count; ++$i ) 804 { 805 $parameter =& $parameters[$i + 1]; 806 $parameterData = $parameter[1]; 807 $parameterPlacement = $parameter[2]; 808 eZTemplateCompiler::calculateVariableNodeStatistics( $tpl, $parameter, $parameterPlacement, 809 $resourceData, $namespace, $stats ); 810 } 811 } 812 else if ( is_integer( $hasParameters ) ) 813 { 814 $parameters = $variableItemData; 815 $count = min( count( $parameters ) - 1, $hasParameters ); 816 for ( $i = 0; $i < $count; ++$i ) 817 { 818 $parameter =& $parameters[$i + 1]; 819 $parameterData = $parameter[1]; 820 $parameterPlacement = $parameter[2]; 821 eZTemplateCompiler::calculateVariableNodeStatistics( $tpl, $parameter, $parameterPlacement, 822 $resourceData, $namespace, $stats ); 823 } 824 } 825 $hasStats = true; 826 } 827 } 828 if ( !$hasStats and method_exists( $operator, 'operatorTemplateStatistics' ) ) 829 { 830 $hasStats = $operator->operatorTemplateStatistics( $operatorName, $variableItem, $variablePlacement, $tpl, $resourceData, $namespace, $stats ); 831 } 832 if ( !$hasStats and method_exists( $operator, 'namedParameterList' ) ) 833 { 834 $namedParameterList = $operator->namedParameterList(); 835 if ( method_exists( $operator, 'namedParameterPerOperator' ) and 836 $operator->namedParameterPerOperator() ) 837 { 838 $namedParameterList = $namedParameterList[$operatorName]; 839 } 840 $operatorParameters = array_slice( $variableItemData, 1 ); 841 $count = 0; 842 foreach ( $namedParameterList as $parameterName => $parameterDefinition ) 843 { 844 $operatorParameter = $operatorParameters[$count]; 845 eZTemplateCompiler::calculateVariableNodeStatistics( $tpl, $operatorParameter, $variablePlacement, $resourceData, $namespace, $stats ); 846 ++$count; 847 } 848 $hasStats = true; 849 } 850 } 851 else if ( $resourceData['test-compile'] ) 852 { 853 $tpl->warning( '', "Operator '$operatorName' is not registered." ); 854 } 855 } 856 else if ( $variableItemType == EZ_TEMPLATE_TYPE_VOID ) 857 { 858 $tpl->warning( 'TemplateCompiler::calculateOperatorStatistics', "Void datatype should not be used, ignoring it" ); 859 } 860 else 861 { 862 $tpl->warning( 'TemplateCompiler::calculateOperatorStatistics', "Unknown data type $variableItemType, ignoring it" ); 863 } 864 } 865 return true; 866 } 867 868 function setVariableStatistics( &$stats, $namespace, $variableName, $changes ) 869 { 870 if ( isset( $stats['variables'][$namespace][$variableName] ) ) 871 { 872 $variableStats =& $stats['variables'][$namespace][$variableName]; 873 } 874 else 875 { 876 $variableStats = array( 'is_accessed' => false, 877 'is_created' => false, 878 'is_modified' => false, 879 'is_removed' => false, 880 'is_local' => false, 881 'is_input' => false, 882 'namespace' => $namespace, 883 'namespace_scope' => false, 884 'type' => false ); 885 $stats['variables'][$namespace][$variableName] =& $variableStats; 886 } 887 if ( isset( $changes['invalid_access'] ) and $changes['invalid_access'] !== false ) 888 $variableStats['invalid_access'] = $changes['invalid_access']; 889 if ( isset( $changes['is_accessed'] ) and $changes['is_accessed'] !== false ) 890 $variableStats['is_accessed'] = $changes['is_accessed']; 891 if ( isset( $changes['is_created'] ) and $changes['is_created'] !== false ) 892 $variableStats['is_created'] = $changes['is_created']; 893 if ( isset( $changes['is_modified'] ) and $changes['is_modified'] !== false ) 894 $variableStats['is_modified'] = $changes['is_modified']; 895 if ( isset( $changes['is_removed'] ) and $changes['is_removed'] !== false ) 896 $variableStats['is_removed'] = $changes['is_removed']; 897 if ( isset( $changes['is_local'] ) and $changes['is_local'] !== false ) 898 $variableStats['is_local'] = $changes['is_local']; 899 if ( isset( $changes['is_input'] ) and $changes['is_input'] !== false ) 900 $variableStats['is_input'] = $changes['is_input']; 901 if ( isset( $changes['namespace'] ) ) 902 $variableStats['namespace'] = $changes['namespace']; 903 if ( isset( $changes['namespace_scope'] ) ) 904 $variableStats['namespace_scope'] = $changes['namespace_scope']; 905 if ( isset( $changes['type'] ) ) 906 $variableStats['type'] = $changes['type']; 907 } 908 909 /*! 910 Iterates over the template node tree and tries to combine multiple static siblings 911 into one element. The original tree is specified in \a $node and the new 912 combined tree will be present in \a $newNode. 913 \sa processNodeCombiningChildren 914 */ 915 function processNodeCombining( $useComments, &$php, &$tpl, &$node, &$resourceData, &$newNode ) 916 { 917 $nodeType = $node[0]; 918 if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 919 { 920 $children = $node[1]; 921 $newNode[0] = $nodeType; 922 $newNode[1] = false; 923 if ( $children ) 924 { 925 eZTemplateCompiler::processNodeCombiningChildren( $useComments, $php, $tpl, $children, $resourceData, $newNode ); 926 } 927 } 928 else 929 $tpl->error( 'processNodeCombining', "Unknown root type $nodeType, should be " . EZ_TEMPLATE_NODE_ROOT ); 930 } 931 932 /*! 933 Does node combining on the children \a $nodeChildren. 934 \sa processNodeCombining 935 */ 936 function processNodeCombiningChildren( $useComments, &$php, &$tpl, &$nodeChildren, &$resourceData, &$parentNode ) 937 { 938 $newNodeChildren = array(); 939 $lastNode = false; 940 foreach ( $nodeChildren as $node ) 941 { 942 $newNode = false; 943 if ( !isset( $node[0] ) ) 944 continue; 945 $nodeType = $node[0]; 946 if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 947 { 948 $children = $node[1]; 949 $newNode = array( $nodeType, 950 false ); 951 if ( $children ) 952 { 953 eZTemplateCompiler::processNodeCombiningChildren( $useComments, $php, $tpl, $children, $resourceData, $newNode ); 954 } 955 } 956 else if ( $nodeType == EZ_TEMPLATE_NODE_TEXT ) 957 { 958 $text = $node[2]; 959 $placement = $node[3]; 960 961 $newNode = array( $nodeType, 962 false, 963 $text, 964 $placement ); 965 eZTemplateCompiler::combineStaticNodes( $tpl, $resourceData, $lastNode, $newNode ); 966 } 967 else if ( $nodeType == EZ_TEMPLATE_NODE_VARIABLE ) 968 { 969 $variableCustom = $node[1]; 970 $variableData = $node[2]; 971 $variablePlacement = $node[3]; 972 $variableParameters = false; 973 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 974 $variableData, $variablePlacement, 975 $resourceData ); 976 $newNode = $node; 977 $newNode[1] = $variableCustom; 978 unset( $dataInspection ); 979 eZTemplateCompiler::combineStaticNodes( $tpl, $resourceData, $lastNode, $newNode ); 980 } 981 else if ( $nodeType == EZ_TEMPLATE_NODE_FUNCTION ) 982 { 983 $functionChildren = $node[1]; 984 $functionName = $node[2]; 985 $functionParameters = $node[3]; 986 $functionPlacement = $node[4]; 987 988 $newNode = array( $nodeType, 989 false, 990 $functionName, 991 $functionParameters, 992 $functionPlacement ); 993 if ( isset( $node[5] ) ) 994 $newNode[5] = $node[5]; 995 996 if ( is_array( $functionChildren ) ) 997 { 998 eZTemplateCompiler::processNodeCombiningChildren( $useComments, $php, $tpl, 999 $functionChildren, $resourceData, $newNode ); 1000 } 1001 1002 } 1003 else 1004 $newNode = $node; 1005 if ( $lastNode != false ) 1006 { 1007 $newNodeChildren[] = $lastNode; 1008 $lastNode = false; 1009 } 1010 if ( $newNode != false ) 1011 $lastNode = $newNode; 1012 } 1013 if ( $lastNode != false ) 1014 { 1015 $newNodeChildren[] = $lastNode; 1016 $lastNode = false; 1017 } 1018 $parentNode[1] = $newNodeChildren; 1019 } 1020 1021 /*! 1022 Tries to combine the node \a $lastNode and the node \a $newNode 1023 into one new text node. If possible the new node is created in \a $newNode 1024 and \a $lastNode will be set to \c false. 1025 Combining nodes only works for text nodes and variable nodes without 1026 variable lookup, attributes and operators. 1027 */ 1028 function combineStaticNodes( &$tpl, &$resourceData, &$lastNode, &$newNode ) 1029 { 1030 if ( $lastNode == false or 1031 $newNode == false ) 1032 return false; 1033 $lastNodeType = $lastNode[0]; 1034 $newNodeType = $newNode[0]; 1035 if ( !in_array( $lastNodeType, array( EZ_TEMPLATE_NODE_TEXT, 1036 EZ_TEMPLATE_NODE_VARIABLE ) ) or 1037 !in_array( $newNodeType, array( EZ_TEMPLATE_NODE_TEXT, 1038 EZ_TEMPLATE_NODE_VARIABLE ) ) ) 1039 return false; 1040 if ( $lastNodeType == EZ_TEMPLATE_NODE_VARIABLE ) 1041 { 1042 if ( is_array( $lastNode[1] ) ) 1043 return false; 1044 $lastDataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 1045 $lastNode[2], $lastNode[3], 1046 $resourceData ); 1047 if ( !$lastDataInspection['is-constant'] or 1048 $lastDataInspection['is-variable'] or 1049 $lastDataInspection['has-attributes'] or 1050 $lastDataInspection['has-operators'] ) 1051 return false; 1052 if ( isset( $lastNode[4] ) and 1053 isset( $lastNode[4]['text-result'] ) and 1054 !$lastNode[4]['text-result'] ) 1055 return false; 1056 } 1057 if ( $newNodeType == EZ_TEMPLATE_NODE_VARIABLE ) 1058 { 1059 if ( is_array( $newNode[1] ) ) 1060 return false; 1061 $newDataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 1062 $newNode[2], $newNode[3], 1063 $resourceData ); 1064 if ( !$newDataInspection['is-constant'] or 1065 $newDataInspection['is-variable'] or 1066 $newDataInspection['has-attributes'] or 1067 $newDataInspection['has-operators'] ) 1068 return false; 1069 if ( isset( $newNode[4] ) and 1070 isset( $newNode[4]['text-result'] ) and 1071 !$newNode[4]['text-result'] ) 1072 return false; 1073 if ( isset( $newNode[1] ) and 1074 $newNode[1] !== false ) 1075 return false; 1076 } 1077 $textElements = array(); 1078 $lastNodeData = eZTemplateCompiler::staticNodeData( $lastNode ); 1079 $newNodeData = eZTemplateCompiler::staticNodeData( $newNode ); 1080 $tpl->appendElementText( $textElements, $lastNodeData, false, false ); 1081 $tpl->appendElementText( $textElements, $newNodeData, false, false ); 1082 $newData = implode( '', $textElements ); 1083 $newPlacement = $lastNode[3]; 1084 if ( !is_array( $newPlacement ) ) 1085 { 1086 $newPlacement = $newNode[3]; 1087 } 1088 else 1089 { 1090 $newPlacement[1][0] = $newNode[3][1][0]; // Line end 1091 $newPlacement[1][1] = $newNode[3][1][1]; // Column end 1092 $newPlacement[1][2] = $newNode[3][1][2]; // Position end 1093 } 1094 $lastNode = false; 1095 $newNode = array( EZ_TEMPLATE_NODE_TEXT, 1096 false, 1097 $newData, 1098 $newPlacement ); 1099 } 1100 1101 /*! 1102 \return the static data for the node \a $node or \c false if 1103 no data could be fetched. 1104 Will only return data from text nodes and variables nodes 1105 without variable lookup, attribute lookup or operators. 1106 */ 1107 function staticNodeData( $node ) 1108 { 1109 $nodeType = $node[0]; 1110 if ( $nodeType == EZ_TEMPLATE_NODE_TEXT ) 1111 { 1112 return $node[2]; 1113 } 1114 else if ( $nodeType == EZ_TEMPLATE_NODE_VARIABLE ) 1115 { 1116 $data = $node[2]; 1117 if ( is_array( $data ) and 1118 count( $data ) > 0 ) 1119 { 1120 $dataType = $data[0][0]; 1121 if ( $dataType == EZ_TEMPLATE_TYPE_STRING or 1122 $dataType == EZ_TEMPLATE_TYPE_NUMERIC or 1123 $dataType == EZ_TEMPLATE_TYPE_IDENTIFIER or 1124 $dataType == EZ_TEMPLATE_TYPE_ARRAY or 1125 $dataType == EZ_TEMPLATE_TYPE_BOOLEAN ) 1126 { 1127 return $data[0][1]; 1128 } 1129 } 1130 } 1131 return null; 1132 } 1133 1134 /*! 1135 Iterates over the items in the tree \a $node and tries to extract static data 1136 from operators which supports it. 1137 */ 1138 function processStaticOptimizations( $useComments, &$php, &$tpl, &$node, &$resourceData, &$newNode ) 1139 { 1140 $nodeType = $node[0]; 1141 if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 1142 { 1143 $children = $node[1]; 1144 $newNode[0] = $nodeType; 1145 $newNode[1] = false; 1146 if ( $children ) 1147 { 1148 $newNode[1] = array(); 1149 foreach ( $children as $child ) 1150 { 1151 $newChild = array(); 1152 eZTemplateCompiler::processStaticOptimizations( $useComments, $php, $tpl, $child, $resourceData, $newChild ); 1153 $newNode[1][] = $newChild; 1154 } 1155 } 1156 } 1157 else if ( $nodeType == EZ_TEMPLATE_NODE_TEXT ) 1158 { 1159 $text = $node[2]; 1160 $placement = $node[3]; 1161 1162 $newNode[0] = $nodeType; 1163 $newNode[1] = false; 1164 $newNode[2] = $text; 1165 $newNode[3] = $placement; 1166 } 1167 else if ( $nodeType == EZ_TEMPLATE_NODE_VARIABLE ) 1168 { 1169 $variableCustom = $node[1]; 1170 $variableData = $node[2]; 1171 $variablePlacement = $node[3]; 1172 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 1173 $variableData, $variablePlacement, 1174 $resourceData ); 1175 if ( isset( $dataInspection['new-data'] ) ) 1176 { 1177 $variableData = $dataInspection['new-data']; 1178 } 1179 $newNode = $node; 1180 $newNode[1] = $variableCustom; 1181 $newNode[2] = $variableData; 1182 unset( $dataInspection ); 1183 } 1184 else if ( $nodeType == EZ_TEMPLATE_NODE_FUNCTION ) 1185 { 1186 $functionChildren = $node[1]; 1187 $functionName = $node[2]; 1188 $functionParameters = $node[3]; 1189 $functionPlacement = $node[4]; 1190 1191 $newFunctionChildren = array(); 1192 if ( is_array( $functionChildren ) ) 1193 { 1194 foreach ( $functionChildren as $functionChild ) 1195 { 1196 $newChild = array(); 1197 eZTemplateCompiler::processStaticOptimizations( $useComments, $php, $tpl, 1198 $functionChild, $resourceData, $newChild ); 1199 $newFunctionChildren[] = $newChild; 1200 } 1201 $functionChildren = $newFunctionChildren; 1202 } 1203 1204 $newFunctionParameters = array(); 1205 if ( $functionParameters ) 1206 { 1207 foreach ( $functionParameters as $functionParameterName => $functionParameterData ) 1208 { 1209 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 1210 $functionParameterData, false, 1211 $resourceData ); 1212 if ( isset( $dataInspection['new-data'] ) ) 1213 { 1214 $functionParameterData = $dataInspection['new-data']; 1215 } 1216 $newFunctionParameters[$functionParameterName] = $functionParameterData; 1217 } 1218 $functionParameters = $newFunctionParameters; 1219 } 1220 1221 $newNode[0] = $nodeType; 1222 $newNode[1] = $functionChildren; 1223 $newNode[2] = $functionName; 1224 $newNode[3] = $functionParameters; 1225 $newNode[4] = $functionPlacement; 1226 if ( isset( $node[5] ) ) 1227 $newNode[5] = $node[5]; 1228 } 1229 else 1230 $newNode = $node; 1231 } 1232 1233 /*! 1234 Iterates over the template node tree \a $node and returns a new transformed 1235 tree in \a $newNode. 1236 \sa processNodeTransformationRoot, processNodeTransformationChild 1237 */ 1238 function processNodeTransformation( $useComments, &$php, &$tpl, &$node, &$resourceData, &$newNode ) 1239 { 1240 $newNode = eZTemplateCompiler::processNodeTransformationRoot( $useComments, $php, $tpl, $node, $resourceData ); 1241 } 1242 1243 /*! 1244 Iterates over the nodes \a $nodes and does transformation on them. 1245 \sa processNodeTransformationChildren 1246 \note This method can be called from operator and functions as long as they have the \a $privateData parameter. 1247 */ 1248 function processNodeTransformationNodes( &$tpl, &$node, &$nodes, &$privateData ) 1249 { 1250 $useComments = $privateData['use-comments']; 1251 $php =& $privateData['php-creator']; 1252 $resourceData =& $privateData['resource-data']; 1253 return eZTemplateCompiler::processNodeTransformationChildren( $useComments, $php, $tpl, $node, $nodes, $resourceData ); 1254 } 1255 1256 /*! 1257 Iterates over the children \a $children and does transformation on them. 1258 \sa processNodeTransformation, processNodeTransformationChild 1259 */ 1260 function processNodeTransformationChildren( $useComments, &$php, &$tpl, &$node, &$children, &$resourceData ) 1261 { 1262 if ( $children ) 1263 { 1264 $newChildren = array(); 1265 foreach ( $children as $childNode ) 1266 { 1267 $newChildNode = eZTemplateCompiler::processNodeTransformationChild( $useComments, $php, $tpl, $childNode, $resourceData ); 1268 if ( !$newChildNode ) 1269 $newChildren[] = $childNode; 1270 else 1271 $newChildren = array_merge( $newChildren, $newChildNode ); 1272 } 1273 if ( count( $newChildren ) > 0 ) 1274 return $newChildren; 1275 } 1276 return $children; 1277 } 1278 1279 /*! 1280 Iterates over the children of the root node \a $node and does transformation on them. 1281 \sa processNodeTransformation, processNodeTransformationChild 1282 */ 1283 function processNodeTransformationRoot( $useComments, &$php, &$tpl, &$node, &$resourceData ) 1284 { 1285 $nodeType = $node[0]; 1286 if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 1287 { 1288 $children = $node[1]; 1289 $newNode = array( $nodeType, 1290 false ); 1291 if ( $children ) 1292 { 1293 $newChildren = array(); 1294 foreach ( $children as $childNode ) 1295 { 1296 $newChildNode = eZTemplateCompiler::processNodeTransformationChild( $useComments, $php, $tpl, $childNode, $resourceData ); 1297 if ( !$newChildNode ) 1298 $newChildren[] = $childNode; 1299 else 1300 $newChildren = array_merge( $newChildren, $newChildNode ); 1301 } 1302 if ( count( $newChildren ) > 0 ) 1303 $newNode[1] = $newChildren; 1304 } 1305 return $newNode; 1306 } 1307 else 1308 $tpl->error( 'processNodeTransformation', "Unknown root type $nodeType, should be " . EZ_TEMPLATE_NODE_ROOT ); 1309 return false; 1310 } 1311 1312 /*! 1313 Iterates over the children of the function node \a $node and transforms the tree. 1314 If the node is not a function it will return \c false. 1315 \sa processNodeTransformationRoot, processNodeTransformationChild 1316 */ 1317 function processNodeTransformationChild( $useComments, &$php, &$tpl, &$node, &$resourceData ) 1318 { 1319 $nodeType = $node[0]; 1320 if ( $nodeType == EZ_TEMPLATE_NODE_FUNCTION ) 1321 { 1322 $nodeCopy = $node; 1323 $functionChildren = $node[1]; 1324 $functionName = $node[2]; 1325 $functionParameters = $node[3]; 1326 $functionPlacement = $node[4]; 1327 if ( !isset( $tpl->Functions[$functionName] ) ) 1328 return false; 1329 1330 if ( is_array( $tpl->Functions[$functionName] ) ) 1331 { 1332 $tpl->loadAndRegisterFunctions( $tpl->Functions[$functionName] ); 1333 } 1334 $functionObject =& $tpl->Functions[$functionName]; 1335 if ( is_object( $functionObject ) ) 1336 { 1337 $hasTransformationSupport = false; 1338 $transformChildren = true; 1339 $transformParameters = false; 1340 if ( method_exists( $functionObject, 'functionTemplateHints' ) ) 1341 { 1342 $hints = $functionObject->functionTemplateHints(); 1343 if ( isset( $hints[$functionName] ) and 1344 isset( $hints[$functionName]['tree-transformation'] ) and 1345 $hints[$functionName]['tree-transformation'] ) 1346 $hasTransformationSupport = true; 1347 if ( isset( $hints[$functionName] ) and 1348 isset( $hints[$functionName]['transform-children'] ) ) 1349 $transformChildren = $hints[$functionName]['transform-children']; 1350 if ( isset( $hints[$functionName] ) and 1351 isset( $hints[$functionName]['transform-parameters'] ) ) 1352 $transformParameters = $hints[$functionName]['transform-parameters']; 1353 } 1354 if ( $hasTransformationSupport and 1355 method_exists( $functionObject, 'templateNodeTransformation' ) ) 1356 { 1357 if ( $transformChildren and 1358 $functionChildren ) 1359 { 1360 $newChildren = array(); 1361 foreach ( $functionChildren as $childNode ) 1362 { 1363 $newChildNode = eZTemplateCompiler::processNodeTransformationChild( $useComments, $php, $tpl, $childNode, $resourceData ); 1364 if ( !$newChildNode ) 1365 $newChildren[] = $childNode; 1366 else if ( !is_array( $newChildNode ) ) 1367 $newChildren[] = $newChildNode; 1368 else 1369 $newChildren = array_merge( $newChildren, $newChildNode ); 1370 } 1371 if ( count( $newChildren ) > 0 ) 1372 $node[1] = $newChildren; 1373 } 1374 1375 if ( $transformParameters and 1376 $functionParameters ) 1377 { 1378 $newParameters = array(); 1379 foreach ( $functionParameters as $parameterName => $parameterElementList ) 1380 { 1381 $elementTree = $parameterElementList; 1382 $elementList = $elementTree; 1383 $newParamNode = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node, 1384 $elementTree, $elementList, $resourceData ); 1385 if ( !$newParamNode || !is_array( $newParamNode ) ) 1386 $newParameters[$parameterName] = $parameterElementList; 1387 else 1388 $newParameters[$parameterName] = $newParamNode; 1389 } 1390 if ( count( $newParameters ) > 0 ) 1391 { 1392 $node[3] = $newParameters; 1393 $functionParameters = $newParameters; 1394 } 1395 } 1396 1397 $privateData = array( 'use-comments' => $useComments, 1398 'php-creator' => &$php, 1399 'resource-data' => &$resourceData ); 1400 $newNodes = $functionObject->templateNodeTransformation( $functionName, $node, 1401 $tpl, $functionParameters, $privateData ); 1402 unset( $privateData ); 1403 if ( !$newNodes ) 1404 { 1405 $node = $nodeCopy; 1406 $node[1] = $functionChildren; 1407 return false; 1408 return $node; 1409 } 1410 return $newNodes; 1411 } 1412 } 1413 else if ( $resourceData['test-compile'] ) 1414 { 1415 $tpl->warning( '', "Function '$functionName' is not registered.", $functionPlacement ); 1416 } 1417 1418 return false; 1419 } 1420 else if ( $nodeType == EZ_TEMPLATE_NODE_VARIABLE ) 1421 { 1422 $elementTree = $node[2]; 1423 $elementList = $elementTree; 1424 1425 $newParameterElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node, 1426 $elementTree, $elementList, $resourceData ); 1427 if ( $newParameterElements ) 1428 { 1429 $newNode = $node; 1430 $newNode[2] = $newParameterElements; 1431 $newNodes = array( $newNode ); 1432 return $newNodes; 1433 } 1434 } 1435 else if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 1436 { 1437 return eZTemplateCompiler::processNodeTransformationRoot( $useComments, $php, $tpl, $node, $resourceData ); 1438 } 1439 else 1440 return false; 1441 } 1442 1443 /*! 1444 Iterates over the element list \a $elements and transforms them. 1445 \sa processElementTransformationChild 1446 */ 1447 function processElementTransformationList( &$tpl, &$node, &$elements, &$privateData ) 1448 { 1449 $useComments = $privateData['use-comments']; 1450 $php =& $privateData['php-creator']; 1451 $resourceData =& $privateData['resource-data']; 1452 $elementTree = $elements; 1453 $newElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node, 1454 $elementTree, $elements, $resourceData ); 1455 if ( $newElements ) 1456 return $newElements; 1457 return $elements; 1458 } 1459 1460 /*! 1461 Iterates over the children of the function node \a $node and transforms the tree. 1462 If the node is not a function it will return \c false. 1463 \sa processNodeTransformationRoot, processNodeTransformationChild 1464 */ 1465 function processElementTransformationChild( $useComments, &$php, &$tpl, &$node, 1466 &$elementTree, &$elementList, &$resourceData ) 1467 { 1468 $count = count( $elementList ); 1469 $lastElement = null; 1470 $newElementList = array(); 1471 for ( $i = 0; $i < $count; ++$i ) 1472 { 1473 $element =& $elementList[$i]; 1474 $elementType = $element[0]; 1475 if ( $elementType == EZ_TEMPLATE_TYPE_OPERATOR ) 1476 { 1477 $operatorName = $element[1][0]; 1478 $operatorParameters = array_slice( $element[1], 1 ); 1479 if ( !isset( $tpl->Operators[$operatorName] ) ) 1480 return false; 1481 1482 if ( is_array( $tpl->Operators[$operatorName] ) ) 1483 { 1484 $tpl->loadAndRegisterOperators( $tpl->Operators[$operatorName] ); 1485 } 1486 $operatorObject =& $tpl->Operators[$operatorName]; 1487 if ( is_object( $operatorObject ) ) 1488 { 1489 $hasTransformationSupport = false; 1490 $transformParameters = false; 1491 $inputAsParameter = false; 1492 $knownType = 'static'; 1493 if ( method_exists( $operatorObject, 'operatorTemplateHints' ) ) 1494 { 1495 $hints = $operatorObject->operatorTemplateHints(); 1496 if ( isset( $hints[$operatorName] ) and 1497 isset( $hints[$operatorName]['element-transformation'] ) and 1498 $hints[$operatorName]['element-transformation'] ) 1499 { 1500 $hasTransformationSupport = true; 1501 } 1502 1503 if ( $hasTransformationSupport and 1504 isset( $hints[$operatorName]['element-transformation-func'] ) ) 1505 { 1506 $transformationMethod = $hints[$operatorName]['element-transformation-func']; 1507 } 1508 else 1509 { 1510 $transformationMethod = 'templateElementTransformation'; 1511 } 1512 1513 if ( isset( $hints[$operatorName] ) and 1514 isset( $hints[$operatorName]['transform-parameters'] ) ) 1515 { 1516 $transformParameters = $hints[$operatorName]['transform-parameters']; 1517 } 1518 1519 if ( isset( $hints[$operatorName] ) and 1520 isset( $hints[$operatorName]['input-as-parameter'] ) ) 1521 { 1522 $inputAsParameter = $hints[$operatorName]['input-as-parameter']; 1523 } 1524 1525 if ( isset( $hints[$operatorName]['output'] ) and !$hints[$operatorName]['output'] ) 1526 { 1527 $knownType = 'null'; 1528 } 1529 else if ( isset( $hints[$operatorName]['output-type'] ) ) 1530 { 1531 $knownType = $hints[$operatorName]['output-type']; 1532 } 1533 } 1534 if ( $hasTransformationSupport and 1535 method_exists( $operatorObject, $transformationMethod ) ) 1536 { 1537 $resetNewElementList = false; 1538 if ( $transformParameters ) 1539 { 1540 $newParameters = array(); 1541 if ( $inputAsParameter ) 1542 { 1543 $newParameterElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node, 1544 $elementTree, $newElementList, $resourceData ); 1545 if ( count( $newParameterElements ) > 0 or 1546 $inputAsParameter === 'always' ) 1547 { 1548 $newParameters[] = $newParameterElements; 1549 $resetNewElementList = true; 1550 } 1551 } 1552 1553 foreach ( $operatorParameters as $operatorParameter ) 1554 { 1555 $newParameterElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node, 1556 $elementTree, $operatorParameter, $resourceData ); 1557 if ( !$newParameterElements ) 1558 $newParameters[] = $operatorParameter; 1559 else 1560 $newParameters[] = $newParameterElements; 1561 } 1562 $operatorParameters = $newParameters; 1563 } 1564 1565 $newElements = $operatorObject->$transformationMethod( $operatorName, $node, $tpl, $resourceData, 1566 $element, $lastElement, $elementList, $elementTree, 1567 $operatorParameters ); 1568 if ( is_array( $newElements ) ) 1569 { 1570 if ( $resetNewElementList ) 1571 { 1572 $newElementList = $newElements; 1573 } 1574 else 1575 { 1576 $newElementList = array_merge( $newElementList, $newElements ); 1577 } 1578 } 1579 else 1580 { 1581 $newElementList[] = $element; 1582 } 1583 } 1584 else 1585 { 1586 $newElementList[] = $element; 1587 } 1588 } 1589 else if ( $resourceData['test-compile'] ) 1590 { 1591 $tpl->warning( '', "Operator '$operatorName' is not registered." ); 1592 } 1593 } 1594 else 1595 { 1596 $newElementList[] = $element; 1597 } 1598 $lastElement = $element; 1599 } 1600 return $newElementList; 1601 } 1602 1603 /*! 1604 Iterates over the node tree and removes all placement information. 1605 */ 1606 function processRemoveNodePlacement( &$node ) 1607 { 1608 $nodeType = $node[0]; 1609 if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 1610 { 1611 $nodeChildren =& $node[1]; 1612 for ( $i = 0; $i < count( $nodeChildren ); ++$i ) 1613 { 1614 $nodeChild =& $nodeChildren[$i]; 1615 eZTemplateCompiler::processRemoveNodePlacement( $nodeChild ); 1616 } 1617 } 1618 else if ( $nodeType == EZ_TEMPLATE_NODE_TEXT ) 1619 { 1620 $node[3] = false; 1621 } 1622 else if ( $nodeType == EZ_TEMPLATE_NODE_VARIABLE ) 1623 { 1624 $node[3] = false; 1625 } 1626 else if ( $nodeType == EZ_TEMPLATE_NODE_FUNCTION ) 1627 { 1628 $node[4] = false; 1629 $nodeChildren =& $node[1]; 1630 if ( $nodeChildren ) 1631 { 1632 for ( $i = 0; $i < count( $nodeChildren ); ++$i ) 1633 { 1634 $nodeChild =& $nodeChildren[$i]; 1635 eZTemplateCompiler::processRemoveNodePlacement( $nodeChild ); 1636 } 1637 } 1638 } 1639 else if ( $nodeType == EZ_TEMPLATE_NODE_OPERATOR ) 1640 { 1641 } 1642 } 1643 1644 /*! 1645 Looks over the variable data \a $variableData and returns an array with 1646 information on the structure. 1647 The following entries are generated. 1648 - is-constant - true if the variable data contains constant data like text and numerics 1649 - is-variable - true if the variable data is a variable lookup 1650 - has-operators - true if operators are present 1651 - has-attributes - true if attributes are used 1652 */ 1653 function inspectVariableData( &$tpl, $variableData, $variablePlacement, &$resourceData ) 1654 { 1655 $dataInspection = array( 'is-constant' => false, 1656 'is-variable' => false, 1657 'has-operators' => false, 1658 'has-attributes' => false ); 1659 if ( !is_array( $variableData ) ) 1660 return $dataInspection; 1661 $newVariableData = array(); 1662 // Static optimizations, the following items are done: 1663 // - Recognize static data 1664 // - Extract static data, if possible, from operators 1665 // - Remove parameters and input which not be used. 1666 foreach ( $variableData as $variableItem ) 1667 { 1668 $variableItemType = $variableItem[0]; 1669 $variableItemData = $variableItem[1]; 1670 $variableItemPlacement = $variableItem[2]; 1671 if ( $variableItemType == EZ_TEMPLATE_TYPE_STRING or 1672 $variableItemType == EZ_TEMPLATE_TYPE_IDENTIFIER ) 1673 { 1674 $dataInspection['is-constant'] = true; 1675 $dataInspection['is-variable'] = false; 1676 $newVariableData[] = $variableItem; 1677 } 1678 else if ( $variableItemType == EZ_TEMPLATE_TYPE_NUMERIC ) 1679 { 1680 $dataInspection['is-constant'] = true; 1681 $dataInspection['is-variable'] = false; 1682 $newVariableData[] = $variableItem; 1683 } 1684 else if ( $variableItemType == EZ_TEMPLATE_TYPE_BOOLEAN ) 1685 { 1686 $dataInspection['is-constant'] = true; 1687 $dataInspection['is-variable'] = false; 1688 $newVariableData[] = $variableItem; 1689 } 1690 else if ( $variableItemType == EZ_TEMPLATE_TYPE_DYNAMIC_ARRAY ) 1691 { 1692 $dataInspection['is-constant'] = false; 1693 $dataInspection['is-variable'] = true; 1694 $newVariableData[] = $variableItem; 1695 } 1696 else if ( $variableItemType == EZ_TEMPLATE_TYPE_ARRAY ) 1697 { 1698 $dataInspection['is-constant'] = true; 1699 $dataInspection['is-variable'] = false; 1700 $newVariableData[] = $variableItem; 1701 } 1702 else if ( $variableItemType == EZ_TEMPLATE_TYPE_VARIABLE ) 1703 { 1704 $dataInspection['is-constant'] = false; 1705 $dataInspection['is-variable'] = true; 1706 $newVariableData[] = $variableItem; 1707 } 1708 else if ( $variableItemType == EZ_TEMPLATE_TYPE_ATTRIBUTE ) 1709 { 1710 $dataInspection['has-attributes'] = true; 1711 $newDataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 1712 $variableItemData, $variableItemPlacement, 1713 $resourceData ); 1714 if ( isset( $newDataInspection['new-data'] ) ) 1715 { 1716 $variableItemData = $newDataInspection['new-data']; 1717 } 1718 $variableItem[1] = $variableItemData; 1719 unset( $newDataInspection ); 1720 $newVariableData[] = $variableItem; 1721 } 1722 else if ( $variableItemType == EZ_TEMPLATE_TYPE_OPERATOR ) 1723 { 1724 $dataInspection['has-operators'] = true; 1725 $operatorName = $variableItemData[0]; 1726 $operatorHint = eZTemplateCompiler::operatorHint( $tpl, $operatorName ); 1727 $newVariableItem = $variableItem; 1728 if ( $operatorHint and 1729 isset( $operatorHint['input'] ) and 1730 isset( $operatorHint['output'] ) and 1731 isset( $operatorHint['parameters'] ) ) 1732 { 1733 if ( !$operatorHint['input'] and 1734 $operatorHint['output'] ) 1735 $newVariableData = array(); 1736 if ( !isset( $operatorHint) or !$operatorHint['parameters'] ) 1737 $newVariableItem[1] = array( $operatorName ); 1738 if ( isset ( $operatorHint['static'] ) and 1739 $operatorHint['static'] ) 1740 { 1741 $operatorStaticData = eZTemplateCompiler::operatorStaticData( $tpl, $operatorName ); 1742 $newVariableItem = eZTemplateCompiler::createStaticVariableData( $tpl, $operatorStaticData, $variableItemPlacement ); 1743 $dataInspection['is-constant'] = true; 1744 $dataInspection['is-variable'] = false; 1745 $dataInspection['has-operators'] = false; 1746 } 1747 } 1748 if ( $newVariableItem[0] == EZ_TEMPLATE_TYPE_OPERATOR ) 1749 { 1750 $tmpVariableItem = $newVariableItem[1]; 1751 $newVariableItem[1] = array( $operatorName ); 1752 for ( $i = 1; $i < count( $tmpVariableItem ); ++$i ) 1753 { 1754 $operatorParameter = $tmpVariableItem[$i]; 1755 $newDataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 1756 $operatorParameter, false, 1757 $resourceData ); 1758 if ( isset( $newDataInspection['new-data'] ) ) 1759 { 1760 $operatorParameter = $newDataInspection['new-data']; 1761 } 1762 $newVariableItem[1][] = $operatorParameter; 1763 } 1764 } 1765 $newVariableData[] = $newVariableItem; 1766 } 1767 else if ( $variableItemType == EZ_TEMPLATE_TYPE_VOID ) 1768 { 1769 $tpl->warning( 'TemplateCompiler', "Void datatype should not be used, ignoring it" ); 1770 } 1771 else if ( $variableItemType > EZ_TEMPLATE_TYPE_INTERNAL and 1772 $variableItemType < EZ_TEMPLATE_TYPE_INTERNAL_STOP ) 1773 { 1774 $newVariableData[] = $variableItem; 1775 } 1776 else 1777 { 1778 $tpl->warning( 'TemplateCompiler', "Unknown data type $variableItemType, ignoring it" ); 1779 } 1780 } 1781 $dataInspection['new-data'] = $newVariableData; 1782 return $dataInspection; 1783 } 1784 1785 /*! 1786 \return the operator hint for the operator \a $operatorName, or \c false if 1787 the operator does not exist or has no hints. 1788 */ 1789 function operatorHint( &$tpl, $operatorName ) 1790 { 1791 if ( isset( $tpl->Operators[$operatorName] ) and 1792 is_array( $tpl->Operators[$operatorName] ) ) 1793 { 1794 $tpl->loadAndRegisterOperators( $tpl->Operators[$operatorName] ); 1795 } 1796 $operatorObject =& $tpl->Operators[$operatorName]; 1797 $operatorHint = false; 1798 if ( is_object( $operatorObject ) ) 1799 { 1800 if ( method_exists( $operatorObject, 'operatorTemplateHints' ) ) 1801 { 1802 $operatorHintArray = $operatorObject->operatorTemplateHints(); 1803 if ( isset( $operatorHintArray[$operatorName] ) ) 1804 { 1805 $operatorHint = $operatorHintArray[$operatorName]; 1806 } 1807 } 1808 } 1809 else if ( $tpl->testCompile() ) 1810 { 1811 $tpl->warning( '', "Operator '$operatorName' is not registered." ); 1812 } 1813 1814 return $operatorHint; 1815 } 1816 1817 /*! 1818 \return static data from operators which support returning static data, 1819 or \c null if no static data could be extracted. 1820 The operator is specified in \a $operatorName. 1821 1822 */ 1823 function operatorStaticData( &$tpl, $operatorName ) 1824 { 1825 if ( is_array( $tpl->Operators[$operatorName] ) ) 1826 { 1827 $tpl->loadAndRegisterOperators( $tpl->Operators[$operatorName] ); 1828 } 1829 $operatorObject =& $tpl->Operators[$operatorName]; 1830 $operatorData = null; 1831 if ( is_object( $operatorObject ) ) 1832 { 1833 if ( method_exists( $operatorObject, 'operatorCompiledStaticData' ) ) 1834 { 1835 $operatorData = $operatorObject->operatorCompiledStaticData( $operatorName ); 1836 } 1837 } 1838 else if ( $tpl->testCompile() ) 1839 { 1840 $tpl->warning( '', "Operator '$operatorName' is not registered." ); 1841 } 1842 1843 return $operatorData; 1844 } 1845 1846 /*! 1847 Creates a variable data element for the data \a $staticData and returns it. 1848 The type of element depends on the type of the data, strings and booleans 1849 are returned as EZ_TEMPLATE_TYPE_TEXT and EZ_TEMPLATE_TYPE_NUMERIC while other 1850 types are turned into text and returned as EZ_TEMPLATE_TYPE_TEXT. 1851 */ 1852 function createStaticVariableData( &$tpl, $staticData, $variableItemPlacement ) 1853 { 1854 if ( is_string( $staticData ) ) 1855 return array( EZ_TEMPLATE_TYPE_TEXT, 1856 $staticData, 1857 $variableItemPlacement ); 1858 else if ( is_bool( $staticData ) ) 1859 return array( EZ_TEMPLATE_TYPE_BOOLEAN, 1860 $staticData, 1861 $variableItemPlacement ); 1862 else if ( is_bool( $staticData ) or is_numeric( $staticData ) ) 1863 return array( EZ_TEMPLATE_TYPE_NUMERIC, 1864 $staticData, 1865 $variableItemPlacement ); 1866 else if ( is_array( $staticData ) ) 1867 return array( EZ_TEMPLATE_TYPE_ARRAY, 1868 $staticData, 1869 $variableItemPlacement ); 1870 else 1871 return array( EZ_TEMPLATE_TYPE_TEXT, 1872 "$staticData", 1873 $variableItemPlacement ); 1874 } 1875 1876 /*! 1877 Opens the template files specified in \a $placementData 1878 and fetches the text portion defined by the 1879 start and end position. The text is returned or \c null if the 1880 text could not be fetched. 1881 */ 1882 function fetchTemplatePiece( $placementData ) 1883 { 1884 if ( !isset( $placementData[0] ) or 1885 !isset( $placementData[1] ) or 1886 !isset( $placementData[2] ) ) 1887 return null; 1888 $file = $placementData[2]; 1889 $startPosition = $placementData[0][2]; 1890 $endPosition = $placementData[1][2]; 1891 $length = $endPosition - $startPosition; 1892 if ( file_exists( $file ) ) 1893 { 1894 if ( $length > 0 ) 1895 { 1896 $fd = fopen( $file, 'rb' ); 1897 fseek( $fd, $startPosition ); 1898 $text = fread( $fd, $length ); 1899 fclose( $fd ); 1900 return $text; 1901 } 1902 else 1903 { 1904 return ''; 1905 } 1906 } 1907 return null; 1908 } 1909 1910 /*! 1911 Creates the common.php file which has common functions for compiled templates. 1912 If the file already exists if will not create it. 1913 */ 1914 function createCommonCompileTemplate() 1915 { 1916 $php = new eZPHPCreator( eZTemplateCompiler::compilationDirectory(), 'common.php' ); 1917 if ( $php->exists() ) 1918 return; 1919 1920 $php->addComment( "This file contains functions which are common to all compiled templates.\n\n" . 1921 'NOTE: This file is autogenerated and should not be modified, any changes will be lost!' ); 1922 $php->addSpace(); 1923 $php->addDefine( 'EZ_TEMPLATE_COMPILER_COMMON_CODE', true ); 1924 $php->addSpace(); 1925 1926 $namespaceStack = array(); 1927 $php->addCodePiece( "if ( !isset( \$namespaceStack ) )\n" ); 1928 $php->addVariable( 'namespaceStack', $namespaceStack, EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, array( 'spacing' => 4 ) ); 1929 $php->addSpace(); 1930 1931 $lbracket = '{'; 1932 $rbracket = '}'; 1933 $initText = "if ( !function_exists( 'compiledfetchvariable' ) ) 1934 $lbracket 1935 function compiledFetchVariable( &\$vars, \$namespace, \$name ) 1936 $lbracket 1937 \$exists = ( array_key_exists( \$namespace, \$vars ) and 1938 array_key_exists( \$name, \$vars[\$namespace] ) ); 1939 if ( \$exists ) 1940 $lbracket 1941 \$var = \$vars[\$namespace][\$name]; 1942 $rbracket 1943 else 1944 \$var = null; 1945 return \$var; 1946 $rbracket 1947 $rbracket 1948 if ( !function_exists( 'compiledfetchtext' ) ) 1949 $lbracket 1950 function compiledFetchText( &\$tpl, \$rootNamespace, \$currentNamespace, \$namespace, &\$var ) 1951 $lbracket 1952 \$text = ''; 1953 \$tpl->appendElement( \$text, \$var, \$rootNamespace, \$currentNamespace ); 1954 return \$text; 1955 $rbracket 1956 $rbracket 1957 if ( !function_exists( 'compiledAcquireResource' ) ) 1958 $lbracket 1959 function compiledAcquireResource( \$phpScript, \$key, &\$originalText, 1960 &\$tpl, \$rootNamespace, \$currentNamespace ) 1961 { 1962 include( '" . eZTemplateCompiler::TemplatePrefix() . "' . \$phpScript ); 1963 if ( isset( \$text ) ) 1964 { 1965 \$originalText .= \$text; 1966 return true; 1967 } 1968 return false; 1969 } 1970 $rbracket 1971 if ( !function_exists( 'compiledfetchattribute' ) ) 1972 $lbracket 1973 function compiledFetchAttribute( &\$value, \$attributeValue ) 1974 $lbracket 1975 if ( is_object( \$value ) ) 1976 $lbracket 1977 if ( method_exists( \$value, \"attribute\" ) and 1978 method_exists( \$value, \"hasattribute\" ) ) 1979 $lbracket 1980 if ( \$value->hasAttribute( \$attributeValue ) ) 1981 $lbracket 1982 unset( \$tempValue ); 1983 \$tempValue = \$value->attribute( \$attributeValue ); 1984 return \$tempValue; 1985 $rbracket 1986 $rbracket 1987 $rbracket 1988 else if ( is_array( \$value ) ) 1989 $lbracket 1990 if ( isset( \$value[\$attributeValue] ) ) 1991 $lbracket 1992 unset( \$tempValue ); 1993 \$tempValue = \$value[\$attributeValue]; 1994 return \$tempValue; 1995 $rbracket 1996 $rbracket 1997 return null; 1998 $rbracket 1999 $rbracket 2000 "; 2001 $php->addCodePiece( $initText ); 2002 $php->store( true ); 2003 } 2004 2005 /*! 2006 Figures out the current text name to use in compiled template code and return it. 2007 The names will be text, text1, text2 etc. 2008 */ 2009 function currentTextName( $parameters ) 2010 { 2011 $textData = array( 'variable' => 'text', 2012 'counter' => 0 ); 2013 if ( isset( $parameters['text-data'] ) ) 2014 $textData = $parameters['text-data']; 2015 $name = $textData['variable']; 2016 if ( $textData['counter'] > 0 ) 2017 $name .= $textData['counter']; 2018 return $name; 2019 } 2020 2021 /*! 2022 Increases the counter for the current text name, this ensure a uniqe name for it. 2023 */ 2024 function increaseCurrentTextName( &$parameters ) 2025 { 2026 $textData = array( 'variable' => 'text', 2027 'counter' => 0 ); 2028 if ( !isset( $parameters['text-data'] ) ) 2029 $parameters['text-data'] = $textData; 2030 2031 $parameters['text-data']['counter']++; 2032 } 2033 2034 /*! 2035 Decreases a previosuly increased counter for the current text name. 2036 */ 2037 function decreaseCurrentTextName( &$parameters ) 2038 { 2039 $textData = array( 'variable' => 'text', 2040 'counter' => 0 ); 2041 if ( !isset( $parameters['text-data'] ) ) 2042 { 2043 $parameters['text-data'] = $textData; 2044 return; 2045 } 2046 2047 $parameters['text-data']['counter']--; 2048 } 2049 2050 function boundVariableName( $variableID, $parameters ) 2051 { 2052 $bindMap =& $parameters['variable-bind']['map'][$variableID]; 2053 if ( isset( $bindMap ) ) 2054 $bindMap = array(); 2055 } 2056 2057 /*! 2058 Generates the PHP code defined in the template node tree \a $node. 2059 The code is generated using the php creator specified in \a $php. 2060 */ 2061 2062 function generatePHPCode( $useComments, &$php, &$tpl, &$node, &$resourceData ) 2063 { 2064 $parameters = array(); 2065 $currentParameters = array( 'spacing' => 0 ); 2066 $nodeType = $node[0]; 2067 if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 2068 { 2069 $children = $node[1]; 2070 if ( $children ) 2071 { 2072 eZTemplateCompiler::generatePHPCodeChildren( $useComments, $php, $tpl, $children, $resourceData, $parameters, $currentParameters ); 2073 } 2074 } 2075 else 2076 $tpl->error( 'generatePHPCode', "Unknown root type $nodeType, should be " . EZ_TEMPLATE_NODE_ROOT ); 2077 $php->addSpace(); 2078 } 2079 2080 /*! 2081 Generates the PHP code for all node children specified in \a $nodeChildren. 2082 \sa generatePHPCode 2083 */ 2084 function generatePHPCodeChildren( $useComments, &$php, &$tpl, &$nodeChildren, &$resourceData, &$parameters, $currentParameters ) 2085 { 2086 foreach ( $nodeChildren as $node ) 2087 { 2088 $newNode = false; 2089 $nodeType = $node[0]; 2090 if ( $nodeType > EZ_TEMPLATE_NODE_USER_CUSTOM ) 2091 { 2092 // Do custom nodes 2093 } 2094 else if ( $nodeType > EZ_TEMPLATE_NODE_INTERNAL ) 2095 { 2096 // Do custom internal nodes 2097 if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_CODE_PIECE ) 2098 { 2099 $codePiece = $node[1]; 2100 $spacing = $currentParameters['spacing']; 2101 if ( isset( $node[2]['spacing'] ) ) 2102 $spacing += $node[2]['spacing']; 2103 $php->addCodePiece( $codePiece, array( 'spacing' => $spacing ) ); 2104 } 2105 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_WARNING ) 2106 { 2107 $warningText = $php->variableText( $node[1], 23, 0, false ); 2108 $warningLabel = false; 2109 $warningLabelText = ''; 2110 if ( isset( $node[2] ) ) 2111 $warningLabelText = $php->variableText( $node[2], 0, 0, false ); 2112 $spacing = $currentParameters['spacing']; 2113 if ( isset( $node[3]['spacing'] ) ) 2114 $spacing += $node[3]['spacing']; 2115 $placementText = 'false'; 2116 if ( isset( $node[4] ) ) 2117 $placementText = $php->variableText( $node[4], 0, 0, false ); 2118 $php->addCodePiece( "\$tpl->warning( " . $warningLabelText . ", " . $warningText . ", " . $placementText . " );", array( 'spacing' => $spacing ) ); 2119 } 2120 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_ERROR ) 2121 { 2122 $errorText = $php->variableText( $node[1], 21, 0, false ); 2123 $errorLabel = false; 2124 $errorLabelText = ''; 2125 if ( isset( $node[2] ) ) 2126 $errorLabelText = $php->variableText( $node[2], 0, 0, false ); 2127 $spacing = $currentParameters['spacing']; 2128 if ( isset( $node[3]['spacing'] ) ) 2129 $spacing += $node[3]['spacing']; 2130 $placementText = 'false'; 2131 if ( isset( $node[4] ) ) 2132 $placementText = $php->variableText( $node[4], 0, 0, false ); 2133 $php->addCodePiece( "\$tpl->error( " . $errorLabelText . ", " . $errorText . ", " . $placementText . " );", array( 'spacing' => $spacing ) ); 2134 } 2135 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_OUTPUT_READ ) 2136 { 2137 $variableName = $node[1]; 2138 $spacing = $currentParameters['spacing']; 2139 if ( isset( $node[2]['spacing'] ) ) 2140 $spacing += $node[2]['spacing']; 2141 $textName = eZTemplateCompiler::currentTextName( $parameters ); 2142 $assignmentType = $node[3]; 2143 $assignmentText = $php->variableNameText( $variableName, $assignmentType, $node[2] ); 2144 $php->addCodePiece( "$assignmentText\$$textName;", array( 'spacing' => $spacing ) ); 2145 } 2146 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_OUTPUT_ASSIGN ) 2147 { 2148 $variableName = $node[1]; 2149 $spacing = $currentParameters['spacing']; 2150 if ( isset( $node[2]['spacing'] ) ) 2151 $spacing += $node[2]['spacing']; 2152 $textName = eZTemplateCompiler::currentTextName( $parameters ); 2153 $assignmentType = $node[3]; 2154 $assignmentText = $php->variableNameText( $textName, $assignmentType, $node[2] ); 2155 $php->addCodePiece( "$assignmentText\$$variableName;", array( 'spacing' => $spacing ) ); 2156 } 2157 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_OUTPUT_INCREASE ) 2158 { 2159 $spacing = $currentParameters['spacing']; 2160 if ( isset( $node[1]['spacing'] ) ) 2161 $spacing += $node[1]['spacing']; 2162 $textName = eZTemplateCompiler::currentTextName( $parameters ); 2163 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( !isset( \$textStack ) )\n" . 2164 " \$textStack = array();\n" . 2165 "\$textStack[] = \$$textName;\n" . 2166 "\$$textName = '';", array( 'spacing' => $spacing ) ); 2167 } 2168 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_OUTPUT_DECREASE ) 2169 { 2170 $spacing = $currentParameters['spacing']; 2171 if ( isset( $node[1]['spacing'] ) ) 2172 $spacing += $node[1]['spacing']; 2173 $textName = eZTemplateCompiler::currentTextName( $parameters ); 2174 $php->addCodePiece( "\$$textName = array_pop( \$textStack );", array( 'spacing' => $spacing ) ); 2175 } 2176 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_SPACING_INCREASE ) 2177 { 2178 $spacing = $node[1]; 2179 $currentParameters['spacing'] += $spacing; 2180 continue; 2181 } 2182 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_SPACING_DECREASE ) 2183 { 2184 $spacing = $node[1]; 2185 $currentParameters['spacing'] -= $spacing; 2186 continue; 2187 } 2188 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_VARIABLE_SET ) 2189 { 2190 $variableName = $node[1]; 2191 $variableValue = $node[2]; 2192 $spacing = $currentParameters['spacing']; 2193 if ( isset( $node[3]['spacing'] ) ) 2194 $spacing += $node[3]['spacing']; 2195 $php->addVariable( $variableName, $variableValue, EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, array( 'spacing' => $spacing ) ); 2196 } 2197 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_VARIABLE_UNSET ) 2198 { 2199 $variableName = $node[1]; 2200 $spacing = $currentParameters['spacing']; 2201 if ( isset( $node[2]['spacing'] ) ) 2202 $spacing += $node[2]['spacing']; 2203 2204 if ( is_array( $variableName ) ) 2205 { 2206 $namespace = $variableName[0]; 2207 $namespaceScope = $variableName[1]; 2208 $variableName = $variableName[2]; 2209 $namespaceText = eZTemplateCompiler::generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, array( 'spacing' => $spacing ), true ); 2210 if ( !is_string( $namespaceText ) ) 2211 $namespaceText = "\$namespace"; 2212 $variableNameText = $php->variableText( $variableName, 0, 0, false ); 2213 if ( isset( $node[2]['remember_set'] ) and $node[2]['remember_set'] ) 2214 { 2215 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( isset( \$setArray[$namespaceText][$variableNameText] ) )\n". 2216 "{\n" ); 2217 $spacing += 4; 2218 } 2219 if ( isset( $node[2]['local-variable'] ) ) 2220 { 2221 $php->addCodePiece( "\$tpl->unsetLocalVariable( $variableNameText, $namespaceText );\n", 2222 array( 'spacing' => $spacing ) ); 2223 } 2224 else 2225 { 2226 $php->addCodePiece( "unset( \$vars[$namespaceText][$variableNameText] );", 2227 array( 'spacing' => $spacing ) ); 2228 } 2229 2230 if ( isset( $node[2]['remember_set'] ) and $node[2]['remember_set'] ) 2231 { 2232 $php->addCodePiece( "\n}\n" ); 2233 $spacing -= 4; 2234 } 2235 } 2236 else 2237 { 2238 $php->addVariableUnset( $variableName, array( 'spacing' => $spacing ) ); 2239 } 2240 } 2241 else if ( ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_RESOURCE_ACQUISITION ) || 2242 ( $nodeType == EZ_TEMPLATE_NODE_OPTIMIZED_RESOURCE_ACQUISITION ) ) 2243 { 2244 $resource = $node[1]; 2245 $resourceObject =& $tpl->resourceHandler( $resource ); 2246 if ( !$resourceObject ) 2247 continue; 2248 2249 $spacing = $currentParameters['spacing']; 2250 if ( isset( $node[7]['spacing'] ) ) 2251 $spacing += $node[7]['spacing']; 2252 $newRootNamespace = $node[8]; 2253 $resourceVariableName = $node[9]; 2254 $resourceFilename = isset( $node[10] ) ? $node[10] : false; 2255 2256 /* We can only use fallback code if we know upfront which 2257 * template is included; it does not work if we are using 2258 * something from the ezobjectforwarder which makes the 2259 * uriMap an array */ 2260 $useFallbackCode = true; 2261 $uriMap = $node[2]; 2262 if ( is_string( $uriMap ) ) 2263 { 2264 $uriMap = array( $uriMap ); 2265 } 2266 else 2267 { 2268 $useFallbackCode = false; 2269 } 2270 2271 $resourceMap = array(); 2272 $hasCompiledCode = false; 2273 foreach ( $uriMap as $uriKey => $originalURI ) 2274 { 2275 $uri = $originalURI; 2276 if ( $resource ) 2277 $uri = $resource . ':' . $uri; 2278 unset( $tmpResourceData ); 2279 $tmpResourceData = $tpl->resourceData( $resourceObject, $uri, $node[1], $originalURI ); 2280 $uriText = $php->variableText( $uri, 0, 0, false ); 2281 2282 $resourceCanCache = true; 2283 if ( !$resourceObject->servesStaticData() ) 2284 $resourceCanCache = false; 2285 if ( !$tpl->isCachingAllowed() ) 2286 $resourceCanCache = false; 2287 2288 $tmpResourceData['text'] = null; 2289 $tmpResourceData['root-node'] = null; 2290 $tmpResourceData['compiled-template'] = false; 2291 $tmpResourceData['time-stamp'] = null; 2292 $tmpResourceData['key-data'] = null; 2293 $tmpResourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled(); 2294 $subSpacing = 0; 2295 $hasResourceData = false; 2296 2297 $savedLocale = setlocale( LC_CTYPE, null ); 2298 if ( isset( $GLOBALS['eZTemplateCompilerResourceCache'][$tmpResourceData['template-filename']] ) ) 2299 { 2300 $tmpFileName = $tmpResourceData['template-filename']; 2301 unset( $tmpResourceData ); 2302 $tmpResourceData = $GLOBALS['eZTemplateCompilerResourceCache'][$tmpFileName]; 2303 $tmpResourceData['compiled-template'] = true; 2304 $tmpResourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled(); 2305 $hasResourceData = true; 2306 $hasCompiledCode = true; 2307 } 2308 else if ( $useFallbackCode ) 2309 { 2310 // If we can use fallback code we don't need to compile the templates in advance 2311 // Simply fake that it has been compiled by setting some variables 2312 // Note: Yes this is a hack, but rewriting this code is not an easy task 2313 if ( $resourceObject->handleResource( $tpl, $tmpResourceData, $node[4], $node[5] ) ) 2314 { 2315 $tmpResourceData['compiled-template'] = true; 2316 $hasResourceData = true; 2317 $hasCompiledCode = true; 2318 } 2319 } 2320 else 2321 { 2322 if ( $resourceObject->handleResource( $tpl, $tmpResourceData, $node[4], $node[5] ) ) 2323 { 2324 if ( !$tmpResourceData['compiled-template'] and 2325 $tmpResourceData['root-node'] === null ) 2326 { 2327 $root =& $tmpResourceData['root-node']; 2328 $root = array( EZ_TEMPLATE_NODE_ROOT, false ); 2329 $templateText =& $tmpResourceData["text"]; 2330 $keyData = $tmpResourceData['key-data']; 2331 $rootNamespace = ''; 2332 $tpl->parse( $templateText, $root, $rootNamespace, $tmpResourceData ); 2333 $hasResourceData = false; 2334 } 2335 2336 /* We always DO need to execute this part if we 2337 * don't have any fallback code. If we can 2338 * generate the fallback code we make the 2339 * included template compile on demand */ 2340 if ( !$tmpResourceData['compiled-template'] and 2341 $resourceCanCache and 2342 $tpl->canCompileTemplate( $tmpResourceData, $node[5] ) and 2343 !$useFallbackCode ) 2344 { 2345 $generateStatus = $tpl->compileTemplate( $tmpResourceData, $node[5] ); 2346 2347 // Time limit #2: 2348 /* We reset the time limit to 60 seconds to 2349 * ensure that remaining template has 2350 * enough time to compile. However if time 2351 * limit is unlimited (0) we leave it be */ 2352 $maxExecutionTime = ini_get( 'max_execution_time' ); 2353 if ( $maxExecutionTime != 0 && $maxExecutionTime < 60 ) 2354 { 2355 @set_time_limit( 60 ); 2356 } 2357 2358 if ( $generateStatus ) 2359 $tmpResourceData['compiled-template'] = true; 2360 } 2361 } 2362 $GLOBALS['eZTemplateCompilerResourceCache'][$tmpResourceData['template-filename']] =& $tmpResourceData; 2363 } 2364 setlocale( LC_CTYPE, $savedLocale ); 2365 $textName = eZTemplateCompiler::currentTextName( $parameters ); 2366 if ( $tmpResourceData['compiled-template'] ) 2367 { 2368 $hasCompiledCode = true; 2369 // if ( !eZTemplateCompiler::isFallbackResourceCodeEnabled() ) 2370 // $useFallbackCode = false; 2371 $keyData = $tmpResourceData['key-data']; 2372 $templatePath = $tmpResourceData['template-name']; 2373 $key = $resourceObject->cacheKey( $keyData, $tmpResourceData, $templatePath, $node[5] ); 2374 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $tmpResourceData ); 2375 2376 $directory = eZTemplateCompiler::compilationDirectory(); 2377 $phpScript = eZDir::path( array( $directory, $cacheFileName ) ); 2378 $phpScriptText = $php->variableText( $phpScript, 0, 0, false ); 2379 $resourceMap[$uriKey] = array( 'key' => $uriKey, 2380 'uri' => $uri, 2381 'phpscript' => $phpScript ); 2382 } 2383 } 2384 2385 if ( $useComments ) 2386 { 2387 $variablePlacement = $node[6]; 2388 if ( $variablePlacement ) 2389 { 2390 $originalText = eZTemplateCompiler::fetchTemplatePiece( $variablePlacement ); 2391 $php->addComment( "Resource Acquisition:", true, true, array( 'spacing' => $spacing ) ); 2392 $php->addComment( $originalText, true, true, array( 'spacing' => $spacing ) ); 2393 } 2394 } 2395 2396 if ( $hasCompiledCode ) 2397 { 2398 if ( $resourceVariableName ) 2399 { 2400 $phpScriptText = '$phpScript'; 2401 $phpScriptArray = array(); 2402 2403 foreach ( $resourceMap as $resourceMapItem ) 2404 { 2405 $phpScriptArray[$resourceMapItem['key']] = $resourceMapItem['phpscript']; 2406 } 2407 2408 if ( !$resourceFilename ) /* Not optimized version */ 2409 { 2410 $php->addVariable( "phpScriptArray", $phpScriptArray, EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, array( 'spacing' => $spacing ) ); 2411 $resourceVariableNameText = "\$$resourceVariableName"; 2412 $php->addCodePiece( "\$phpScript = isset( \$phpScriptArray[$resourceVariableNameText] ) ? \$phpScriptArray[$resourceVariableNameText] : false;\n", array( 'spacing' => $spacing ) ); 2413 } 2414 else /* Optimised version */ 2415 { 2416 $php->addVariable( "phpScript", $phpScriptArray[$node[10]], EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, array('spacing' => $spacing ) ); 2417 } 2418 2419 // The default is to only check if it exists 2420 $modificationCheckText = "file_exists( $phpScriptText )"; 2421 if ( eZTemplateCompiler::isDevelopmentModeEnabled() ) 2422 { 2423 $modificationCheckText = "@filemtime( $phpScriptText ) > filemtime( $uriText )"; 2424 } 2425 $php->addCodePiece( "\$resourceFound = false;\nif " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( $phpScriptText !== false and $modificationCheckText )\n{\n", array( 'spacing' => $spacing ) ); 2426 } 2427 else 2428 { 2429 $php->addCodePiece( "\$resourceFound = false;\n", array( 'spacing' => $spacing ) ); 2430 $phpScript = $resourceMap[0]['phpscript']; 2431 $phpScriptText = $php->variableText( $phpScript, 0, 0, false ); 2432 // Not sure where this should come from 2433 // if ( $resourceIndex > 0 ) 2434 // $php->addCodePiece( "else " ); 2435 // The default is to only check if it exists 2436 $modificationCheckText = "file_exists( $phpScriptText )"; 2437 if ( eZTemplateCompiler::isDevelopmentModeEnabled() ) 2438 { 2439 $modificationCheckText = "@filemtime( $phpScriptText ) > filemtime( $uriText )"; 2440 } 2441 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( $modificationCheckText )\n{\n", array( 'spacing' => $spacing ) ); 2442 2443 } 2444 2445 /* Generate code to do a namespace switch and includes the template */ 2446 $code = "\$resourceFound = true;\n\$namespaceStack[] = array( \$rootNamespace, \$currentNamespace );\n"; 2447 if ( $newRootNamespace ) 2448 { 2449 $newRootNamespaceText = $php->variableText( $newRootNamespace, 0, 0, false ); 2450 $code .= "\$currentNamespace = \$rootNamespace = !\$currentNamespace ? $newRootNamespaceText : ( \$currentNamespace . ':' . $newRootNamespaceText );\n"; 2451 } 2452 else 2453 { 2454 $code .= "\$rootNamespace = \$currentNamespace;\n"; 2455 } 2456 2457 $code .= 2458 "\$tpl->createLocalVariablesList();\n" . 2459 "\$tpl->appendTemplateFetch( $uriText );\n" . // Make sure the template file is recorded, like in loadURIRoot 2460 "include( '" . eZTemplateCompiler::TemplatePrefix() . "' . $phpScriptText );\n" . 2461 "\$tpl->unsetLocalVariables();\n" . 2462 "\$tpl->destroyLocalVariablesList();\n" . 2463 "list( \$rootNamespace, \$currentNamespace ) = array_pop( \$namespaceStack );\n"; 2464 2465 $php->addCodePiece( $code, array( 'spacing' => $spacing + 4 ) ); 2466 if ( $useFallbackCode ) 2467 $php->addCodePiece( "}\nelse\n{\n \$resourceFound = true;\n", array( 'spacing' => $spacing ) ); 2468 else 2469 $php->addCodePiece( "}\n", array( 'spacing' => $spacing ) ); 2470 $subSpacing = 4; 2471 } 2472 else 2473 { 2474 /* Yes, this is a hack, but it is required because 2475 * sometimes the generated nodes after this one emit an 2476 * else statement while there is no accompanied if */ 2477 $php->addCodePiece( "\nif " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "(false)\n{\n}\n" ); 2478 } 2479 2480 /* The fallback code will be added if we need to process an 2481 * URI, this will also compile a template then. We need to 2482 * do the namespace switch manually here otherwise the 2483 * processed template will be run on the node from which 2484 * the template was included from. */ 2485 if ( $useFallbackCode ) 2486 { 2487 $code = "\$resourceFound = true;\n\$namespaceStack[] = array( \$rootNamespace, \$currentNamespace );\n"; 2488 if ( $newRootNamespace ) 2489 { 2490 $newRootNamespaceText = $php->variableText( $newRootNamespace, 0, 0, false ); 2491 $code .= "\$currentNamespace = \$rootNamespace = !\$currentNamespace ? $newRootNamespaceText : ( \$currentNamespace . ':' . $newRootNamespaceText );\n"; 2492 } 2493 else 2494 { 2495 $code .= "\$rootNamespace = \$currentNamespace;\n"; 2496 } 2497 $php->addCodePiece( $code ); 2498 2499 $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 ) ); 2500 $php->addCodePiece( "list( \$rootNamespace, \$currentNamespace ) = array_pop( \$namespaceStack );\n" ); 2501 } 2502 2503 if ( $hasCompiledCode and $useFallbackCode ) 2504 { 2505 $php->addCodePiece( "}\n", array( 'spacing' => $spacing ) ); 2506 } 2507 } 2508 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_NAMESPACE_CHANGE ) 2509 { 2510 $variableData = $node[1]; 2511 $spacing = $currentParameters['spacing']; 2512 if ( isset( $node[2]['spacing'] ) ) 2513 $spacing += $node[2]['spacing']; 2514 $php->addCodePiece( "\$namespaceStack[] = \$currentNamespace;\n", array( 'spacing' => $spacing ) ); 2515 $php->addCodePiece( '$currentNamespace .= ( $currentNamespace ? ":" : "" ) . \''. $variableData[0][1] . '\';' . "\n", array( 'spacing' => $spacing ) ); 2516 } 2517 else if ( $nodeType == EZ_TEMPLATE_NODE_INTERNAL_NAMESPACE_RESTORE ) 2518 { 2519 $spacing = $currentParameters['spacing']; 2520 if ( isset( $node[1]['spacing'] ) ) 2521 $spacing += $node[1]['spacing']; 2522 $php->addCodePiece( "\$currentNamespace = array_pop( \$namespaceStack );\n", array( 'spacing' => $spacing ) ); 2523 } 2524 else if ( $nodeType == EZ_TEMPLATE_NODE_OPTIMIZED_INIT ) 2525 { 2526 $code = <<<END 2527 \$node = ( array_key_exists( \$rootNamespace, \$vars ) and array_key_exists( "node", \$vars[\$rootNamespace] ) ) ? \$vars[\$rootNamespace]["node"] : null; 2528 if ( is_object( \$node ) ) 2529 \$object = \$node->attribute( 'object' ); 2530 if ( isset( \$object ) && is_object( \$object ) ) 2531 \$nod_{$resourceData['uniqid']} = \$object->attribute( 'data_map' ); 2532 else 2533 \$nod_{$resourceData['uniqid']} = false; 2534 unset( \$node, \$object ); 2535 2536 END; 2537 $php->addCodePiece($code); 2538 // Tell the rest of the system that we have create the nod_* variable 2539 $resourceData['node-object-cached'] = true; 2540 } 2541 else 2542 eZDebug::writeWarning( "Unknown internal template node type $nodeType, ignoring node for code generation", 2543 'eZTemplateCompiler:generatePHPCodeChildren' ); 2544 } 2545 else if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 2546 { 2547 $children = $node[1]; 2548 if ( $children ) 2549 { 2550 $newCurrentParameters = $currentParameters; 2551 $newCurrentParameters['spacing'] += 4; 2552 eZTemplateCompiler::generatePHPCodeChildren( $useComments, $php, $tpl, $children, $resourceData, $parameters, $newCurrentParameters ); 2553 } 2554 continue; 2555 } 2556 else if ( $nodeType == EZ_TEMPLATE_NODE_TEXT ) 2557 { 2558 $text = $node[2]; 2559 if ( $text != '' ) 2560 { 2561 $variablePlacement = $node[3]; 2562 $originalText = eZTemplateCompiler::fetchTemplatePiece( $variablePlacement ); 2563 if ( $useComments ) 2564 { 2565 $php->addComment( "Text start:", true, true, array( 'spacing' => $currentParameters['spacing'] ) ); 2566 $php->addComment( $originalText, true, true, array( 'spacing' => $currentParameters['spacing'] ) ); 2567 $php->addComment( "Text end:", true, true, array( 'spacing' => $currentParameters['spacing'] ) ); 2568 } 2569 $php->addVariable( eZTemplateCompiler::currentTextName( $parameters ), 2570 $text, EZ_PHPCREATOR_VARIABLE_APPEND_TEXT, 2571 array( 'spacing' => $currentParameters['spacing'] ) ); 2572 } 2573 continue; 2574 } 2575 else if ( $nodeType == EZ_TEMPLATE_NODE_VARIABLE ) 2576 { 2577 $variableAssignmentName = $node[1]; 2578 $variableData = $node[2]; 2579 $variablePlacement = $node[3]; 2580 2581 $variableParameters = array(); 2582 if ( isset( $node[4] ) and 2583 $node[4] ) 2584 $variableParameters = $node[4]; 2585 $variableOnlyExisting = isset( $node[5] ) ? $node[5] : false; 2586 $variableOverWrite = isset( $node[6] ) ? $node[6] : false; 2587 $rememberSet = isset( $node[7] ) ? $node[7] : false; 2588 2589 $spacing = $currentParameters['spacing']; 2590 if ( isset( $variableParameters['spacing'] ) ) 2591 $spacing += $variableParameters['spacing']; 2592 $variableParameters = array_merge( array( 'variable-name' => 'var', 2593 'text-result' => true ), 2594 $variableParameters ); 2595 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl, 2596 $variableData, $variablePlacement, 2597 $resourceData ); 2598 $newNode = $node; 2599 $newNode[1] = false; 2600 2601 $treatVariableDataAsNonObject = isset( $variableParameters['treat-value-as-non-object'] ) && $variableParameters['treat-value-as-non-object']; 2602 2603 if ( $useComments ) 2604 { 2605 $php->addComment( "Variable data: " . 2606 "Is constant: " . ( $dataInspection['is-constant'] ? 'Yes' : 'No' ) . 2607 " Is variable: " . ( $dataInspection['is-variable'] ? 'Yes' : 'No' ) . 2608 " Has attributes: " . ( $dataInspection['has-attributes'] ? 'Yes' : 'No' ) . 2609 " Has operators: " . ( $dataInspection['has-operators'] ? 'Yes' : 'No' ), 2610 true, true, array( 'spacing' => $spacing ) 2611 ); 2612 $originalText = eZTemplateCompiler::fetchTemplatePiece( $variablePlacement ); 2613 $php->addComment( '{' . $originalText . '}', true, true, array( 'spacing' => $spacing ) ); 2614 } 2615 $generatedVariableName = $variableParameters['variable-name']; 2616 $assignVariable = false; 2617 if ( $variableAssignmentName !== false ) 2618 { 2619 if ( is_array( $variableAssignmentName ) ) 2620 { 2621 $variableParameters['text-result'] = false; 2622 $assignVariable = true; 2623 } 2624 else 2625 { 2626 $generatedVariableName = $variableAssignmentName; 2627 $variableParameters['text-result'] = false; 2628 } 2629 } 2630 2631 $isStaticElement = false; 2632 $nodeElements = $node[2]; 2633 $knownTypes = array(); 2634 if ( eZTemplateNodeTool::isStaticElement( $nodeElements ) and 2635 !$variableParameters['text-result'] ) 2636 { 2637 $variableText = $php->variableText( eZTemplateNodeTool::elementStaticValue( $nodeElements ), 0, 0, false ); 2638 $isStaticElement = true; 2639 } 2640 else if ( eZTemplateNodeTool::isPHPVariableElement( $nodeElements ) and 2641 !$variableParameters['text-result'] ) 2642 { 2643 $variableText = '$' . eZTemplateNodeTool::elementStaticValue( $nodeElements ); 2644 $isStaticElement = true; 2645 } 2646 else 2647 { 2648 $variableText = "\$$generatedVariableName"; 2649 eZTemplateCompiler::generateVariableCode( $php, $tpl, $node, $knownTypes, $dataInspection, 2650 array( 'spacing' => $spacing, 2651 'variable' => $generatedVariableName, 2652 'treat-value-as-non-object' => $treatVariableDataAsNonObject, 2653 'counter' => 0 ), 2654 $resourceData ); 2655 } 2656 2657 if ( $variableParameters['text-result'] ) 2658 { 2659 $textName = eZTemplateCompiler::currentTextName( $parameters ); 2660 if ( count( $knownTypes ) == 0 or in_array( 'objectproxy', $knownTypes ) ) 2661 { 2662 $php->addCodePiece( "\$$textName .= ( is_object( \$$generatedVariableName ) ? compiledFetchText( \$tpl, \$rootNamespace, \$currentNamespace, false, \$$generatedVariableName ) : \$$generatedVariableName );" . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "\n" . 2663 "unset( \$$generatedVariableName );\n", array( 'spacing' => $spacing ) ); 2664 } 2665 else 2666 { 2667 $php->addCodePiece( "\$$textName .= \$$generatedVariableName;\n" . 2668 "unset( \$$generatedVariableName );\n", array( 'spacing' => $spacing ) ); 2669 } 2670 } 2671 else if ( $assignVariable ) 2672 { 2673 $namespace = $variableAssignmentName[0]; 2674 $namespaceScope = $variableAssignmentName[1]; 2675 $variableName = $variableAssignmentName[2]; 2676 $namespaceText = eZTemplateCompiler::generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, array( 'spacing' => $spacing ), true ); 2677 if ( !is_string( $namespaceText ) ) 2678 $namespaceText = "\$namespace"; 2679 $variableNameText = $php->variableText( $variableName, 0, 0, false ); 2680 $unsetVariableText = false; 2681 if ( $variableOnlyExisting ) 2682 { 2683 if ( !$isStaticElement ) 2684 $unsetVariableText = "\n unset( $variableText );"; 2685 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( array_key_exists( $namespaceText, \$vars ) && array_key_exists( $variableNameText, \$vars[$namespaceText] ) )\n". 2686 "{\n". 2687 " \$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText\n". 2688 "}", 2689 array( 'spacing' => $spacing ) ); 2690 } 2691 else if ( $variableOverWrite ) 2692 { 2693 if ( !$isStaticElement ) 2694 $unsetVariableText = "\nunset( $variableText );"; 2695 if ( isset( $variableParameters['local-variable'] ) ) 2696 { 2697 $php->addCodePiece( "\$tpl->setLocalVariable( $variableNameText, $variableText, $namespaceText );\n" , 2698 array( 'spacing' => $spacing ) ); 2699 } 2700 else 2701 { 2702 $php->addCodePiece( "\$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText", 2703 array( 'spacing' => $spacing ) ); 2704 } 2705 2706 } 2707 else if ( $rememberSet ) 2708 { 2709 if ( !$isStaticElement ) 2710 $unsetVariableText = "\n unset( $variableText );"; 2711 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( !isset( \$vars[$namespaceText][$variableNameText] ) )\n". 2712 "{\n". 2713 " \$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText\n". 2714 " \$setArray[$namespaceText][$variableNameText] = true;\n". 2715 "}\n", 2716 array( 'spacing' => $spacing ) ); 2717 } 2718 else 2719 { 2720 if ( !$isStaticElement ) 2721 $unsetVariableText = "\n unset( $variableText );"; 2722 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( !isset( \$vars[$namespaceText][$variableNameText] ) )\n{\n \$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText\n}", 2723 array( 'spacing' => $spacing ) ); 2724 } 2725 } 2726 else if ( $variableAssignmentName !== false and $isStaticElement ) 2727 { 2728 $php->addCodePiece( "\$$generatedVariableName = $variableText;", array( 'spacing' => $spacing ) ); 2729 } 2730 else if ( $variableAssignmentName !== false and !$isStaticElement and !$treatVariableDataAsNonObject ) 2731 { 2732 // Normal assignment from an expression, no need to anything extra 2733 } 2734 unset( $dataInspection ); 2735 } 2736 else if ( $nodeType == EZ_TEMPLATE_NODE_FUNCTION ) 2737 { 2738 $functionChildren = $node[1]; 2739 $functionName = $node[2]; 2740 $functionParameters = $node[3]; 2741 $functionPlacement = $node[4]; 2742 2743 $newNode = array( $nodeType, 2744 false, 2745 $functionName, 2746 $functionParameters, 2747 $functionPlacement ); 2748 2749 $parameterText = 'No parameters'; 2750 if ( $functionParameters ) 2751 { 2752 $parameterText = "Parameters: ". implode( ', ', array_keys( $functionParameters ) ); 2753 } 2754 if ( $useComments ) 2755 { 2756 $php->addComment( "Function: $functionName, $parameterText", true, true, array( 'spacing' => $currentParameters['spacing'] ) ); 2757 $originalText = eZTemplateCompiler::fetchTemplatePiece( $functionPlacement ); 2758 $php->addComment( '{' . $originalText . '}', true, true, array( 'spacing' => $currentParameters['spacing'] ) ); 2759 } 2760 if ( isset( $node[5] ) ) 2761 { 2762 $functionHook = $node[5]; 2763 $functionHookCustomFunction = $functionHook['function']; 2764 if ( $functionHookCustomFunction ) 2765 { 2766 $functionHookCustomFunction = array_merge( array( 'add-function-name' => false, 2767 'add-hook-name' => false, 2768 'add-template-handler' => true, 2769 'add-function-hook-data' => false, 2770 'add-function-parameters' => true, 2771 'add-function-placement' => false, 2772 'add-calculated-namespace' => false, 2773 'add-namespace' => true, 2774 'add-input' => false, 2775 'return-value' => false ), 2776 $functionHookCustomFunction ); 2777 if ( !isset( $parameters['hook-result-variable-counter'][$functionName] ) ) 2778 $parameters['hook-result-variable-counter'][$functionName] = 0; 2779 if ( $functionHookCustomFunction['return-value'] ) 2780 $parameters['hook-result-variable-counter'][$functionName]++; 2781 $hookResultName = $functionName . 'Result' . $parameters['hook-result-variable-counter'][$functionName]; 2782 if ( $functionHookCustomFunction['add-input'] ) 2783 $parameters['hook-result-variable-counter'][$functionName]--; 2784 $functionHookCustomFunctionName = $functionHookCustomFunction['name']; 2785 $codeText = ''; 2786 if ( $functionHookCustomFunction['return-value'] ) 2787 $codeText = "\$$hookResultName = "; 2788 if ( $functionHookCustomFunction['static'] ) 2789 { 2790 $hookClassName = $functionHookCustomFunction['class-name']; 2791 $codeText .= "$hookClassName::$functionHookCustomFunctionName( "; 2792 } 2793 else 2794 $codeText .= "\$functionObject->$functionHookCustomFunctionName( "; 2795 $codeTextLength = strlen( $codeText ); 2796 2797 $functionNameText = $php->variableText( $functionName, 0, 0, false ); 2798 $functionChildrenText = $php->variableText( $functionChildren, $codeTextLength, 0, false ); 2799 2800 $inputFunctionParameters = $functionParameters; 2801 if ( $functionHookCustomFunction['add-calculated-namespace'] ) 2802 unset( $inputFunctionParameters['name'] ); 2803 $functionParametersText = $php->variableText( $inputFunctionParameters, $codeTextLength, 0, false ); 2804 2805 $functionPlacementText = $php->variableText( $functionPlacement, $codeTextLength, 0, false ); 2806 $functionHookText = $php->variableText( $functionHook, $codeTextLength, 0, false ); 2807 2808 $functionHookName = $functionHook['name']; 2809 $functionHookNameText = $php->variableText( $functionHookName, 0, 0, false ); 2810 2811 $codeParameters = array(); 2812 if ( $functionHookCustomFunction['add-function-name'] ) 2813 $codeParameters[] = $functionNameText; 2814 if ( $functionHookCustomFunction['add-hook-name'] ) 2815 $codeParameters[] = $functionHookNameText; 2816 if ( $functionHookCustomFunction['add-function-hook-data'] ) 2817 $codeParameters[] = $functionHookText; 2818 if ( $functionHookCustomFunction['add-template-handler'] ) 2819 $codeParameters[] = "\$tpl"; 2820 if ( $functionHookCustomFunction['add-function-parameters'] ) 2821 $codeParameters[] = $functionParametersText; 2822 if ( $functionHookCustomFunction['add-function-placement'] ) 2823 $codeParameters[] = $functionPlacementText; 2824 if ( $functionHookCustomFunction['add-calculated-namespace'] ) 2825 { 2826 $name = ''; 2827 if ( isset( $functionParameters['name'] ) ) 2828 { 2829 $nameParameter = $functionParameters['name']; 2830 $nameInspection = eZTemplateCompiler::inspectVariableData( $tpl, 2831 $nameParameter, $functionPlacement, 2832 $resourceData ); 2833 if ( $nameInspection['is-constant'] and 2834 !$nameInspection['is-variable'] and 2835 !$nameInspection['has-attributes'] and 2836 !$nameInspection['has-operators'] ) 2837 { 2838 $nameData = $nameParameter[0][1]; 2839 $nameText = $php->variableText( $nameData, 0, 0, false ); 2840 $php->addCodePiece( "if ( \$currentNamespace != '' ) 2841 \$name = \$currentNamespace . ':' . $nameText; 2842 else 2843 \$name = $nameText;\n", array( 'spacing' => $currentParameters['spacing'] ) ); 2844 $codeParameters[] = "\$name"; 2845 } 2846 else 2847 { 2848 $persistence = array(); 2849 $knownTypes = array(); 2850 eZTemplateCompiler::generateVariableCode( $php, $tpl, $nameParameter, $knownTypes, $nameInspection, 2851 $persistence, 2852 array( 'variable' => 'name', 2853 'counter' => 0 ), 2854 $resourceData ); 2855 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( \$currentNamespace != '' ) 2856 { 2857 if ( \$name != '' ) 2858 \$name = \"\$currentNamespace:\$name\"; 2859 else 2860 \$name = \$currentNamespace; 2861 }\n", array( 'spacing' => $currentParameters['spacing'] ) ); 2862 $codeParameters[] = "\$name"; 2863 } 2864 } 2865 else 2866 { 2867 $codeParameters[] = "\$currentNamespace"; 2868 } 2869 } 2870 if ( $functionHookCustomFunction['add-namespace'] ) 2871 $codeParameters[] = "\$rootNamespace, \$currentNamespace"; 2872 if ( $functionHookCustomFunction['add-input'] ) 2873 $codeParameters[] = "\$$hookResultName"; 2874 $codeText .= implode( ",\n" . str_repeat( ' ', $codeTextLength ), 2875 $codeParameters ); 2876 $codeText .= " );\n"; 2877 if ( $functionHookCustomFunction['static'] ) 2878 { 2879 $hookFile = $functionHookCustomFunction['php-file']; 2880 $hookFileText = $php->variableText( $hookFile, 0, 0, false ); 2881 $php->addCodePiece( "include_once( $hookFileText );\n", array( 'spacing' => $currentParameters['spacing'] ) ); 2882 } 2883 else 2884 $php->addCodePiece( "\$functionObject = \$tpl->fetchFunctionObject( $functionNameText );\n", array( 'spacing' => $currentParameters['spacing'] ) ); 2885 $php->addCodePiece( $codeText, array( 'spacing' => $currentParameters['spacing'] ) ); 2886 } 2887 else 2888 { 2889 $functionNameText = $php->variableText( $functionName, 0, 0, false ); 2890 $functionChildrenText = $php->variableText( $functionChildren, 52, 0, false ); 2891 $functionParametersText = $php->variableText( $functionParameters, 52, 0, false ); 2892 $functionPlacementText = $php->variableText( $functionPlacement, 52, 0, false ); 2893 2894 $functionHookText = $php->variableText( $functionHook, 52, 0, false ); 2895 $functionHookName = $functionHook['name']; 2896 $functionHookNameText = $php->variableText( $functionHookName, 0, 0, false ); 2897 $functionHookParameters = $functionHook['parameters']; 2898 $php->addCodePiece( "\$functionObject = \$tpl->fetchFunctionObject( $functionNameText ); 2899 \$hookResult = \$functionObject->templateHookProcess( $functionNameText, $functionHookNameText, 2900 $functionHookText, 2901 \$tpl, 2902 $functionParametersText, 2903 $functionPlacementText, 2904 \$rootNamespace, \$currentNamespace ); 2905 ", array( 'spacing' => $currentParameters['spacing'] ) ); 2906 } 2907 } 2908 else 2909 { 2910 $textName = eZTemplateCompiler::currentTextName( $parameters ); 2911 $functionNameText = $php->variableText( $functionName, 0, 0, false ); 2912 $functionChildrenText = $php->variableText( $functionChildren, 22, 0, false ); 2913 $functionParametersText = $php->variableText( $functionParameters, 22, 0, false ); 2914 $functionPlacementText = $php->variableText( $functionPlacement, 22, 0, false ); 2915 $php->addCodePiece( "\$textElements = array(); 2916 \$tpl->processFunction( $functionNameText, \$textElements, 2917 $functionChildrenText, 2918 $functionParametersText, 2919 $functionPlacementText, 2920 \$rootNamespace, \$currentNamespace ); 2921 \$$textName .= implode( '', \$textElements );\n", array( 'spacing' => $currentParameters['spacing'] ) ); 2922 } 2923 } 2924 $php->addSpace(); 2925 } 2926 } 2927 2928 /*! 2929 Generates PHP code which will do namespace merging. 2930 The namespace to merge with is specified in \a $namespace and 2931 the scope of the merging is defined by \a $namespaceScope. 2932 */ 2933 function generateMergeNamespaceCode( &$php, &$tpl, $namespace, $namespaceScope, $parameters = array(), $skipSimpleAssignment = false ) 2934 { 2935 if ( $namespace != '' ) 2936 { 2937 if ( $namespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_GLOBAL ) 2938 { 2939 $php->addVariable( 'namespace', $namespace, EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, $parameters ); 2940 } 2941 else if ( $namespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_LOCAL ) 2942 { 2943 $php->addCodePiece( "\$namespace = \$rootNamespace; 2944 if ( \$namespace == '' ) 2945 \$namespace = \"$namespace\"; 2946 else 2947 \$namespace .= ':$namespace'; 2948 ", $parameters ); 2949 } 2950 else if ( $namespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_RELATIVE ) 2951 { 2952 $php->addCodePiece( "\$namespace = \$currentNamespace; 2953 if ( \$namespace == '' ) 2954 \$namespace = \"$namespace\"; 2955 else 2956 \$namespace .= ':$namespace'; 2957 ", $parameters ); 2958 } 2959 } 2960 else 2961 { 2962 if ( $namespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_GLOBAL ) 2963 { 2964 if ( $skipSimpleAssignment ) 2965 return "''"; 2966 $php->addVariable( 'namespace', '', EZ_PHPCREATOR_VARIABLE_ASSIGNMENT, $parameters ); 2967 } 2968 else if ( $namespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_LOCAL ) 2969 { 2970 if ( $skipSimpleAssignment ) 2971 return "\$rootNamespace"; 2972 $php->addCodePiece( "\$namespace = \$rootNamespace;\n", $parameters ); 2973 } 2974 else if ( $namespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_RELATIVE ) 2975 { 2976 if ( $skipSimpleAssignment ) 2977 return "\$currentNamespace"; 2978 $php->addCodePiece( "\$namespace = \$currentNamespace;\n", $parameters ); 2979 } 2980 } 2981 return true; 2982 } 2983 2984 /*! 2985 Generates PHP code for the variable node \a $node. 2986 Use generateVariableDataCode if you want to create code for arbitrary variable data structures. 2987 */ 2988 function generateVariableCode( &$php, &$tpl, $node, &$knownTypes, $dataInspection, $parameters, &$resourceData ) 2989 { 2990 $variableData = $node[2]; 2991 $persistence = array(); 2992 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $variableData, $knownTypes, $dataInspection, $persistence, $parameters, $resourceData ); 2993 } 2994 2995 /*! 2996 Generates PHP code for the variable tree structure in \a $variableData. 2997 The code will contain string, numeric and identifier assignment, 2998 variable lookup, attribute lookup and operator execution. 2999 Use generateVariableCode if you want to create code for a variable tree node. 3000 */ 3001 function generateVariableDataCode( &$php, &$tpl, $variableData, &$knownTypes, $dataInspection, &$persistence, $parameters, &$resourceData ) 3002 { 3003 $staticTypeMap = array( EZ_TEMPLATE_TYPE_STRING => 'string', 3004 EZ_TEMPLATE_TYPE_NUMERIC => 'numeric', 3005 EZ_TEMPLATE_TYPE_IDENTIFIER => 'string', 3006 EZ_TEMPLATE_TYPE_ARRAY => 'array', 3007 EZ_TEMPLATE_TYPE_BOOLEAN => 'boolean' ); 3008 3009 $variableAssignmentName = $parameters['variable']; 3010 $variableAssignmentCounter = $parameters['counter']; 3011 $spacing = 0; 3012 $optimizeNode = false; 3013 if ( isset( $parameters['spacing'] ) ) 3014 $spacing = $parameters['spacing']; 3015 if ( $variableAssignmentCounter > 0 ) 3016 $variableAssignmentName .= $variableAssignmentCounter; 3017 3018 // We need to unset the assignment variable before any elements are processed 3019 // This ensures that we don't work on existing variables 3020 $php->addCodePiece( "unset( \$$variableAssignmentName );\n", array( 'spacing' => $spacing ) ); 3021 3022 if ( is_array( $variableData ) ) 3023 { 3024 foreach ( $variableData as $index => $variableDataItem ) 3025 { 3026 $variableDataType = $variableDataItem[0]; 3027 if ( $variableDataType == EZ_TEMPLATE_TYPE_STRING or 3028 $variableDataType == EZ_TEMPLATE_TYPE_NUMERIC or 3029 $variableDataType == EZ_TEMPLATE_TYPE_IDENTIFIER or 3030 $variableDataType == EZ_TEMPLATE_TYPE_ARRAY or 3031 $variableDataType == EZ_TEMPLATE_TYPE_BOOLEAN ) 3032 { 3033 $knownTypes = array_unique( array_merge( $knownTypes, array( $staticTypeMap[$variableDataType] ) ) ); 3034 $dataValue = $variableDataItem[1]; 3035 $dataText = $php->variableText( $dataValue, 0, 0, false ); 3036 $php->addCodePiece( "\$$variableAssignmentName = $dataText;\n", array( 'spacing' => $spacing ) ); 3037 } 3038 else if ( $variableDataType == EZ_TEMPLATE_TYPE_OPTIMIZED_NODE ) 3039 { 3040 $optimizeNode = true; 3041 if ( !isset( $resourceData['node-object-cached'] ) ) 3042 $tpl->error( "Attribute node-object-cached of variable \$resourceData was not found but variable node EZ_TEMPLATE_TYPE_OPTIMIZED_NODE is still present. This should not happen" ); 3043 $php->addCodePiece("\$$variableAssignmentName = \$nod_{$resourceData['uniqid']};\n"); 3044 3045 // If optimized node is not set, use unoptimized code. 3046 $php->addCodePiece( "if ( !\$$variableAssignmentName )\n{\n" ); 3047 } 3048 else if ( $variableDataType == EZ_TEMPLATE_TYPE_OPTIMIZED_ARRAY_LOOKUP ) 3049 { 3050 $code = ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/\n" ) : "" ); 3051 3052 // This code is used a lot so we create a variable for it 3053 $phpVar = "\$$variableAssignmentName"; 3054 $indexName = "'{$variableDataItem[1][0][1]}'"; 3055 3056 // Add sanity checking 3057 $code .= ( "if ( !isset( {$phpVar}[{$indexName}] ) )\n" . 3058 "{\n" . 3059 " \$tpl->error( 'eZTemplateCompiler" . ( $resourceData['use-comments'] ? ( ":" . __LINE__ ) : "" ) . "', \"PHP variable \\$phpVar"."[{$indexName}] does not exist, cannot fetch the value.\" );\n" . 3060 " $phpVar = null;\n" . 3061 "}\n" . 3062 "else\n " ); 3063 3064 // Add the actual code 3065 $code .= "$phpVar = {$phpVar}[{$indexName}];\n"; 3066 3067 $php->addCodePiece( $code ); 3068 } 3069 else if ( $variableDataType == EZ_TEMPLATE_TYPE_OPTIMIZED_ATTRIBUTE_LOOKUP ) 3070 { 3071 $code = ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/\n" ) : "" ); 3072 $code .= <<<END 3073 if ( !is_object( \${$variableAssignmentName} ) ) 3074 { 3075 \${$variableAssignmentName} = null; 3076 } 3077 else if ( \${$variableAssignmentName}->hasAttribute( "{$variableDataItem[1][0][1]}" ) ) 3078 { 3079 \${$variableAssignmentName} = \${$variableAssignmentName}->attribute( "{$variableDataItem[1][0][1]}" ); 3080 } 3081 3082 END; 3083 $php->addCodePiece($code); 3084 } 3085 else if ( $variableDataType == EZ_TEMPLATE_TYPE_OPTIMIZED_CONTENT_CALL ) 3086 { 3087 // Line number comment 3088 $code = ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/\n" ) : "" ); 3089 3090 // This code is used a lot so we create a variable for it 3091 $phpVar = "\$$variableAssignmentName"; 3092 3093 // Add sanity checking 3094 $code .= ( "if ( !is_object( $phpVar ) )\n" . 3095 "{\n" . 3096 " \$tpl->error( 'eZTemplateCompiler" . ( $resourceData['use-comments'] ? ( ":" . __LINE__ ) : "" ) . "', \"PHP variable \\$phpVar is not an object, cannot fetch content()\" );\n" . 3097 " $phpVar = null;\n" . 3098 "}\n" . 3099 "else\n" . 3100 "{\n" ); 3101 3102 // Add the actual code 3103 $code .= " {$phpVar}Tmp = {$phpVar}->content();\n" . 3104 " unset( $phpVar );\n" . 3105 " $phpVar = {$phpVar}Tmp;\n" . 3106 " unset( {$phpVar}Tmp );\n}\n"; 3107 3108 $php->addCodePiece( $code ); 3109 } 3110 else if ( $variableDataType == EZ_TEMPLATE_TYPE_PHP_VARIABLE ) 3111 { 3112 $knownTypes = array(); 3113 $phpVariableName = $variableDataItem[1]; 3114 $php->addCodePiece( "\$$variableAssignmentName = \$$phpVariableName;\n", array( 'spacing' => $spacing ) ); 3115 } 3116 else if ( $variableDataType == EZ_TEMPLATE_TYPE_VARIABLE ) 3117 { 3118 $knownTypes = array(); 3119 $namespace = $variableDataItem[1][0]; 3120 $namespaceScope = $variableDataItem[1][1]; 3121 $variableName = $variableDataItem[1][2]; 3122 $namespaceText = eZTemplateCompiler::generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, array( 'spacing' => $spacing ), true ); 3123 if ( !is_string( $namespaceText ) ) 3124 $namespaceText = "\$namespace"; 3125 $variableNameText = $php->variableText( $variableName, 0, 0, false ); 3126 $code = "unset( \$$variableAssignmentName );\n"; 3127 $code .= "\$$variableAssignmentName = ( array_key_exists( $namespaceText, \$vars ) and array_key_exists( $variableNameText, \$vars[$namespaceText] ) ) ? \$vars[$namespaceText][$variableNameText] : null;\n"; 3128 $php->addCodePiece( $code, 3129 array( 'spacing' => $spacing ) ); 3130 } 3131 else if ( $variableDataType == EZ_TEMPLATE_TYPE_ATTRIBUTE ) 3132 { 3133 $knownTypes = array(); 3134 $newParameters = $parameters; 3135 $newParameters['counter'] += 1; 3136 $tmpVariableAssignmentName = $newParameters['variable']; 3137 $tmpVariableAssignmentCounter = $newParameters['counter']; 3138 if ( $tmpVariableAssignmentCounter > 0 ) 3139 $tmpVariableAssignmentName .= $tmpVariableAssignmentCounter; 3140 if ( eZTemplateNodeTool::isStaticElement( $variableDataItem[1] ) ) 3141 { 3142 $attributeStaticValue = eZTemplateNodeTool::elementStaticValue( $variableDataItem[1] ); 3143 $attributeText = $php->variableText( $attributeStaticValue, 0, 0, false ); 3144 } 3145 else 3146 { 3147 $newParameters['counter'] += 1; 3148 $tmpKnownTypes = array(); 3149 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $variableDataItem[1], $tmpKnownTypes, $dataInspection, 3150 $persistence, $newParameters, $resourceData ); 3151 $newVariableAssignmentName = $newParameters['variable']; 3152 $newVariableAssignmentCounter = $newParameters['counter']; 3153 if ( $newVariableAssignmentCounter > 0 ) 3154 $newVariableAssignmentName .= $newVariableAssignmentCounter; 3155 $attributeText = "\$$newVariableAssignmentName"; 3156 } 3157 $php->addCodePiece( "\$$tmpVariableAssignmentName = compiledFetchAttribute( \$$variableAssignmentName, $attributeText );\n" . 3158 "unset( \$$variableAssignmentName );\n" . 3159 "\$$variableAssignmentName = \$$tmpVariableAssignmentName;\n", 3160 array( 'spacing' => $spacing ) ); 3161 3162 // End if optimized node object is null/false. See also eZTemplateOptimizer::optimizeVariable() 3163 if ( $optimizeNode && 3164 $index == 3 ) 3165 { 3166 $php->addCodePiece( "}\n" ); 3167 } 3168 } 3169 else if ( $variableDataType == EZ_TEMPLATE_TYPE_OPERATOR ) 3170 { 3171 $knownTypes = array(); 3172 $operatorParameters = $variableDataItem[1]; 3173 $operatorName = $operatorParameters[0]; 3174 $operatorParameters = array_splice( $operatorParameters, 1 ); 3175 $operatorNameText = $php->variableText( $operatorName, 0, 0, false ); 3176 $operatorParametersText = $php->variableText( $operatorParameters, 23, 0, false ); 3177 3178 $operatorHint = eZTemplateCompiler::operatorHint( $tpl, $operatorName ); 3179 if ( isset( $operatorHint['output'] ) and $operatorHint['output'] ) 3180 { 3181 if ( isset( $operatorHint['output-type'] ) ) 3182 { 3183 $knownType = $operatorHint['output-type']; 3184 if ( is_array( $knownType ) ) 3185 $knownTypes = array_merge( $knownTypes, $knownType ); 3186 else 3187 $knownTypes[] = $knownType; 3188 $knownTypes = array_unique( $knownTypes ); 3189 } 3190 else 3191 $knownTypes[] = 'static'; 3192 } 3193 3194 $php->addCodePiece( "if (! isset( \$$variableAssignmentName ) ) \$$variableAssignmentName = NULL;\n", array ( 'spacing' => $spacing ) ); 3195 $php->addCodePiece( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$variableAssignmentName ) and method_exists( \$$variableAssignmentName, 'templateValue' ) )\n" . 3196 " \$$variableAssignmentName = \$$variableAssignmentName" . "->templateValue();\n" ); 3197 $php->addCodePiece( "\$" . $variableAssignmentName . "Data = array( 'value' => \$$variableAssignmentName ); 3198 \$tpl->processOperator( $operatorNameText, 3199 $operatorParametersText, 3200 \$rootNamespace, \$currentNamespace, \$" . $variableAssignmentName . "Data, false, false ); 3201 \$$variableAssignmentName = \$" . $variableAssignmentName . "Data['value']; 3202 unset( \$" . $variableAssignmentName . "Data );\n", 3203 array( 'spacing' => $spacing ) ); 3204 } 3205 else if ( $variableDataType == EZ_TEMPLATE_TYPE_VOID ) 3206 { 3207 } 3208 else if ( $variableDataType == EZ_TEMPLATE_TYPE_DYNAMIC_ARRAY ) 3209 { 3210 $knownTypes = array_unique( array_merge( $knownTypes, array( 'array' ) ) ); 3211 $code = '%output% = array( '; 3212 3213 $matchMap = array( '%input%', '%output%' ); 3214 $replaceMap = array( '$' . $variableAssignmentName, '$' . $variableAssignmentName ); 3215 $unsetList = array(); 3216 $counter = 1; 3217 $paramCount = 0; 3218 3219 $values = $variableDataItem[2]; 3220 $newParameters = $parameters; 3221 foreach ( $values as $key => $value ) 3222 { 3223 if ( $paramCount != 0 ) 3224 { 3225 $code .= ', '; 3226 } 3227 ++$paramCount; 3228 $code .= '\'' . $key . '\' => '; 3229 if( eZTemplateNodeTool::isStaticElement( $value ) ) 3230 { 3231 $code .= eZPHPCreator::variableText( eZTemplateNodeTool::elementStaticValue( $value ), 0, 0, false ); 3232 continue; 3233 } 3234 $code .= '%' . $counter . '%'; 3235 $newParameters['counter'] += 1; 3236 $newVariableAssignmentName = $newParameters['variable']; 3237 $newVariableAssignmentCounter = $newParameters['counter']; 3238 if ( $newVariableAssignmentCounter > 0 ) 3239 $newVariableAssignmentName .= $newVariableAssignmentCounter; 3240 $matchMap[] = '%' . $counter . '%'; 3241 $replaceMap[] = '$' . $newVariableAssignmentName; 3242 $unsetList[] = $newVariableAssignmentName; 3243 $tmpKnownTypes = array(); 3244 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $value, $tmpKnownTypes, $dataInspection, 3245 $persistence, $newParameters, $resourceData ); 3246 ++$counter; 3247 } 3248 3249 $code .= ' );'; 3250 $code = str_replace( $matchMap, $replaceMap, $code ); 3251 $php->addCodePiece( $code, array( 'spacing' => $spacing ) ); 3252 $php->addVariableUnsetList( $unsetList, array( 'spacing' => $spacing ) ); 3253 } 3254 else if ( $variableDataType == EZ_TEMPLATE_TYPE_INTERNAL_CODE_PIECE ) 3255 { 3256 $code = $variableDataItem[1]; 3257 $values = false; 3258 $matchMap = array( '%input%', '%output%' ); 3259 $replaceMap = array( '$' . $variableAssignmentName, '$' . $variableAssignmentName ); 3260 $unsetList = array(); 3261 $counter = 1; 3262 if ( isset( $variableDataItem[3] ) && is_array( $variableDataItem[3] ) ) 3263 { 3264 $newParameters = $parameters; 3265 $values = $variableDataItem[3]; 3266 foreach ( $values as $value ) 3267 { 3268 $newParameters['counter'] += 1; 3269 $newVariableAssignmentName = $newParameters['variable']; 3270 $newVariableAssignmentCounter = $newParameters['counter']; 3271 if ( $newVariableAssignmentCounter > 0 ) 3272 $newVariableAssignmentName .= $newVariableAssignmentCounter; 3273 if ( eZTemplateNodeTool::isStaticElement( $value ) ) 3274 { 3275 $staticValue = eZTemplateNodeTool::elementStaticValue( $value ); 3276 $staticValueText = $php->variableText( $staticValue, 0, 0, false ); 3277 if ( preg_match( "/%code$counter%/", $code ) ) 3278 { 3279 $matchMap[] = '%code' . $counter . '%'; 3280 $replaceMap[] = ''; 3281 } 3282 $matchMap[] = '%' . $counter . '%'; 3283 $replaceMap[] = $staticValueText; 3284 } 3285 else 3286 { 3287 $matchMap[] = '%' . $counter . '%'; 3288 $replaceMap[] = '$' . $newVariableAssignmentName; 3289 $unsetList[] = $newVariableAssignmentName; 3290 if ( preg_match( "/%code$counter%/", $code ) ) 3291 { 3292 $tmpPHP = new eZPHPCreator( '', '', eZTemplateCompiler::TemplatePrefix() ); 3293 $tmpKnownTypes = array(); 3294 eZTemplateCompiler::generateVariableDataCode( $tmpPHP, $tpl, $value, $tmpKnownTypes, $dataInspection, 3295 $persistence, $newParameters, $resourceData ); 3296 $newCode = $tmpPHP->fetch( false ); 3297 if ( count( $tmpKnownTypes ) == 0 or in_array( 'objectproxy', $tmpKnownTypes ) ) 3298 { 3299 $newCode .= ( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$newVariableAssignmentName ) and method_exists( \$$newVariableAssignmentName, 'templateValue' ) )\n" . 3300 " \$$newVariableAssignmentName = \$$newVariableAssignmentName" . "->templateValue();\n" ); 3301 } 3302 $matchMap[] = '%code' . $counter . '%'; 3303 $replaceMap[] = $newCode; 3304 } 3305 else 3306 { 3307 $tmpKnownTypes = array(); 3308 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $value, $tmpKnownTypes, $dataInspection, 3309 $persistence, $newParameters, $resourceData ); 3310 if ( !$parameters['treat-value-as-non-object'] and ( count( $tmpKnownTypes ) == 0 or in_array( 'objectproxy', $tmpKnownTypes ) ) ) 3311 { 3312 $php->addCodePiece( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$newVariableAssignmentName ) and method_exists( \$$newVariableAssignmentName, 'templateValue' ) )\n" . 3313 " \$$newVariableAssignmentName = \$$newVariableAssignmentName" . "->templateValue();\n", 3314 array( 'spacing' => $spacing ) ); 3315 } 3316 } 3317 } 3318 ++$counter; 3319 } 3320 } 3321 if ( isset( $variableDataItem[4] ) && ( $variableDataItem[4] !== false ) ) 3322 { 3323 $values = $variableDataItem[4]; 3324 3325 for ( $i = 0; $i < $values; $i++ ) 3326 { 3327 $newParameters['counter'] += 1; 3328 $newVariableAssignmentName = $newParameters['variable']; 3329 $newVariableAssignmentCounter = $newParameters['counter']; 3330 if ( $newVariableAssignmentCounter > 0 ) 3331 $newVariableAssignmentName .= $newVariableAssignmentCounter; 3332 $matchMap[] = '%tmp' . ( $i + 1 ) . '%'; 3333 $replaceMap[] = '$' . $newVariableAssignmentName; 3334 $unsetList[] = $newVariableAssignmentName; 3335 } 3336 } 3337 if ( isset( $variableDataItem[5] ) and $variableDataItem[5] ) 3338 { 3339 if ( is_array( $variableDataItem[5] ) ) 3340 $knownTypes = array_unique( array_merge( $knownTypes, $variableDataItem[5] ) ); 3341 else if ( is_string( $variableDataItem[5] ) ) 3342 $knownTypes = array_unique( array_merge( $knownTypes, array( $variableDataItem[5] ) ) ); 3343 else 3344 $knownTypes = array_unique( array_merge( $knownTypes, array( 'static' ) ) ); 3345 } 3346 $code = str_replace( $matchMap, $replaceMap, $code ); 3347 $php->addCodePiece( $code, array( 'spacing' => $spacing ) ); 3348 $php->addVariableUnsetList( $unsetList, array( 'spacing' => $spacing ) ); 3349 } 3350 } 3351 } 3352 // After the entire expression line is done we try to extract the actual value if proxies are used 3353 $php->addCodePiece( "if (! isset( \$$variableAssignmentName ) ) \$$variableAssignmentName = NULL;\n" ); 3354 $php->addCodePiece( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$variableAssignmentName ) and method_exists( \$$variableAssignmentName, 'templateValue' ) )\n" . 3355 " \$$variableAssignmentName = \$$variableAssignmentName" . "->templateValue();\n" ); 3356 } 3357 } 3358 3359 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sat Feb 24 10:30:04 2007 | par Balluche grâce à PHPXref 0.7 |