[ Index ] |
|
Code source de eZ Publish 3.9.0 |
1 <?php 2 // 3 // Definition of eZTemplate class 4 // 5 // Created on: <01-Mar-2002 13:49:57 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 eztemplate.php 30 Template system manager. 31 */ 32 33 /*! \defgroup eZTemplate Template system */ 34 35 /*! 36 \class eZTemplate eztemplate.php 37 \ingroup eZTemplate 38 \brief The main manager for templates 39 40 The template systems allows for separation of code and 41 layout by moving the layout part into template files. These 42 template files are parsed and processed with template variables set 43 by the PHP code. 44 45 The template system in itself is does not do much, it parses template files 46 according to a rule set sets up a tree hierarchy and process the data 47 using functions and operators. The standard template system comes with only 48 a few functions and no operators, it is meant for these functions and operators 49 to be specified by the users of the template system. But for simplicity a few 50 help classes is available which can be easily enabled. 51 52 The classes are: 53 - eZTemplateDelimitFunction - Inserts the left and right delimiter which are normally parsed. 54 - eZTemplateSectionFunction - Allows for conditional blocks and loops. 55 - eZTemplateIncludeFunction - Includes external templates 56 - eZTemplateSequenceFunction - Creates sequences arrays 57 - eZTemplateSwitchFunction - Conditional output of template 58 59 - eZTemplatePHPOperator - Allows for easy redirection of operator names to PHP functions. 60 - eZTemplateLocaleOperator - Allows for locale conversions. 61 - eZTemplateArrayOperator - Creates arrays 62 - eZTemplateAttributeOperator - Displays contents of template variables, useful for debugging 63 - eZTemplateImageOperator - Converts text to image 64 - eZTemplateLogicOperator - Various logical operators for boolean handling 65 - eZTemplateUnitOperator - Unit conversion and display 66 67 To enable these functions and operator use registerFunction and registerOperator. 68 69 In keeping with the spirit of being simple the template system does not know how 70 to get the template files itself. Instead it relies on resource handlers, these 71 handlers fetches the template files using different kind of transport mechanism. 72 For simplicity a default resource class is available, eZTemplateFileResource fetches 73 templates from the filesystem. 74 75 The parser process consists of three passes, each pass adds a new level of complexity. 76 The first pass strips text from template blocks which starts with a left delimiter and 77 ends with a right delimiter (default is { and } ), and places them in an array. 78 The second pass iterates the text and block elements and removes newlines from 79 text before function blocks and text after function blocks. 80 The third pass builds the tree according the function rules. 81 82 Processing is done by iterating over the root of the tree, if a text block is found 83 the text is appended to the result text. If a variable or contant is it's data is extracted 84 and any operators found are run on it before fetching the result and appending it to 85 the result text. If a function is found the function is called with the parameters 86 and it's up to the function handle children if any. 87 88 Constants and template variables will usually be called variables since there's little 89 difference. A template variable expression will start with a $ and consists of a 90 namespace (optional) a name and attribues(optional). The variable expression 91 \verbatim $root:var.attr1 \endverbatim exists in the "root" namespace, has the name "var" and uses the 92 attribute "attr1". Some functions will create variables on demand, to avoid name conflicts 93 namespaces were introduced, each function will place the new variables in a namespace 94 specified in the template file. Attribues are used for fetching parts of the variable, 95 for instance an element in an array or data in an object. Since the syntax is the 96 same for arrays and objects the PHP code can use simple arrays when speed is required, 97 the template code will not care. 98 A different syntax is also available when you want to access an attribute using a variable. 99 For instance \verbatim $root:var[$attr_var] \endverbatim, if the variable $attr_var contains "attr1" it would 100 access the same attribute as in the first example. 101 102 The syntax for operators is a | and a name, optionally parameters can be specified with 103 ( and ) delimited with ,. Valid operators are \verbatim |upcase, |l10n(date) \endverbatim. 104 105 Functions look a lot like HTML/XML tags. The function consists of a name and parameters 106 which are assigned using the param=value syntax. Some parameters may be required while 107 others may be optionally, the exact behaviour is specified by each function. 108 Valid functions are \verbatim "section name=abc loop=4" \endverbatim 109 110 Example of usage: 111 \code 112 // Init template 113 $tpl =& eZTemplate::instance(); 114 115 $tpl->registerOperators( new eZTemplatePHPOperator( array( "upcase" => "strtoupper", 116 "reverse" => "strrev" ) ) ); 117 $tpl->registerOperators( new eZTemplateLocaleOperator() ); 118 $tpl->registerFunction( "section", new eZTemplateSectionFunction( "section" ) ); 119 $tpl->registerFunctions( new eZTemplateDelimitFunction() ); 120 121 $tpl->setVariable( "my_var", "{this value set by variable}", "test" ); 122 $tpl->setVariable( "my_arr", array( "1st", "2nd", "third", "fjerde" ) ); 123 $tpl->setVariable( "multidim", array( array( "a", "b" ), 124 array( "c", "d" ), 125 array( "e", "f" ), 126 array( "g", "h" ) ) ); 127 128 class mytest 129 { 130 function mytest( $n, $s ) 131 { 132 $this->n = $n; 133 $this->s = $s; 134 } 135 136 function hasAttribute( $attr ) 137 { 138 return ( $attr == "name" || $attr == "size" ); 139 } 140 141 function &attribute( $attr ) 142 { 143 switch ( $attr ) 144 { 145 case "name"; 146 return $this->n; 147 case "size"; 148 return $this->s; 149 default: 150 $retAttr = null; 151 return $retAttr; 152 } 153 } 154 155 }; 156 157 $tpl->setVariable( "multidim_obj", array( new mytest( "jan", 200 ), 158 new mytest( "feb", 200 ), 159 new mytest( "john", 200 ), 160 new mytest( "doe", 50 ) ) ); 161 $tpl->setVariable( "curdate", mktime() ); 162 163 $tpl->display( "lib/eztemplate/example/test.tpl" ); 164 165 // test.tpl 166 167 {section name=outer loop=4} 168 123 169 {delimit}::{/delimit} 170 {/section} 171 172 {literal test=1} This is some {blah arg1="" arg2="abc" /} {/literal} 173 174 <title>This is a test</title> 175 <table border="1"> 176 <tr><th>{$test:my_var} 177 {"some text!!!"|upcase|reverse}</th></tr> 178 {section name=abc loop=$my_arr} 179 <tr><td>{$abc:item}</td></tr> 180 {/section} 181 </table> 182 183 <table border="1"> 184 {section name=outer loop=$multidim} 185 <tr> 186 {section name=inner loop=$outer:item} 187 <td>{$inner:item}</td> 188 {/section} 189 </tr> 190 {/section} 191 </table> 192 193 <table border="1"> 194 {section name=outer loop=$multidim_obj} 195 <tr> 196 <td>{$outer:item.name}</td> 197 <td>{$outer:item.size}</td> 198 </tr> 199 {/section} 200 </table> 201 202 {section name=outer loop=$nonexistingvar} 203 <b><i>Dette skal ikke vises</b></i> 204 {section-else} 205 <b><i>This is shown when the {ldelim}$loop{rdelim} variable is non-existant</b></i> 206 {/section} 207 208 209 Denne koster {1.4|l10n(currency)}<br> 210 {-123456789|l10n(number)}<br> 211 {$curdate|l10n(date)}<br> 212 {$curdate|l10n(shortdate)}<br> 213 {$curdate|l10n(time)}<br> 214 {$curdate|l10n(shorttime)}<br> 215 {include file="test2.tpl"/} 216 217 \endcode 218 */ 219 220 include_once ( "lib/ezutils/classes/ezdebug.php" ); 221 222 include_once ( "lib/eztemplate/classes/eztemplatefileresource.php" ); 223 224 include_once ( "lib/eztemplate/classes/eztemplateroot.php" ); 225 include_once ( "lib/eztemplate/classes/eztemplatetextelement.php" ); 226 include_once ( "lib/eztemplate/classes/eztemplatevariableelement.php" ); 227 include_once ( "lib/eztemplate/classes/eztemplateoperatorelement.php" ); 228 include_once ( "lib/eztemplate/classes/eztemplatefunctionelement.php" ); 229 230 define( "EZ_RESOURCE_FETCH", 1 ); 231 define( "EZ_RESOURCE_QUERY", 2 ); 232 233 define( "EZ_ELEMENT_TEXT", 1 ); 234 define( "EZ_ELEMENT_SINGLE_TAG", 2 ); 235 define( "EZ_ELEMENT_NORMAL_TAG", 3 ); 236 define( "EZ_ELEMENT_END_TAG", 4 ); 237 define( "EZ_ELEMENT_VARIABLE", 5 ); 238 define( "EZ_ELEMENT_COMMENT", 6 ); 239 240 define( "EZ_TEMPLATE_NODE_ROOT", 1 ); 241 define( "EZ_TEMPLATE_NODE_TEXT", 2 ); 242 define( "EZ_TEMPLATE_NODE_VARIABLE", 3 ); 243 define( "EZ_TEMPLATE_NODE_FUNCTION", 4 ); 244 define( "EZ_TEMPLATE_NODE_OPERATOR", 5 ); 245 246 247 define( "EZ_TEMPLATE_NODE_INTERNAL", 100 ); 248 define( "EZ_TEMPLATE_NODE_INTERNAL_CODE_PIECE", 101 ); 249 250 define( "EZ_TEMPLATE_NODE_INTERNAL_VARIABLE_SET", 105 ); 251 define( "EZ_TEMPLATE_NODE_INTERNAL_VARIABLE_UNSET", 102 ); 252 253 define( "EZ_TEMPLATE_NODE_INTERNAL_NAMESPACE_CHANGE", 103 ); 254 define( "EZ_TEMPLATE_NODE_INTERNAL_NAMESPACE_RESTORE", 104 ); 255 256 define( "EZ_TEMPLATE_NODE_INTERNAL_WARNING", 120 ); 257 define( "EZ_TEMPLATE_NODE_INTERNAL_ERROR", 121 ); 258 259 define( "EZ_TEMPLATE_NODE_INTERNAL_RESOURCE_ACQUISITION", 140 ); 260 define( "EZ_TEMPLATE_NODE_OPTIMIZED_RESOURCE_ACQUISITION", 141 ); 261 262 define( "EZ_TEMPLATE_NODE_INTERNAL_OUTPUT_ASSIGN", 150 ); 263 define( "EZ_TEMPLATE_NODE_INTERNAL_OUTPUT_READ", 151 ); 264 define( "EZ_TEMPLATE_NODE_INTERNAL_OUTPUT_INCREASE", 152 ); 265 define( "EZ_TEMPLATE_NODE_INTERNAL_OUTPUT_DECREASE", 153 ); 266 267 define( "EZ_TEMPLATE_NODE_INTERNAL_SPACING_INCREASE", 160 ); 268 define( "EZ_TEMPLATE_NODE_INTERNAL_SPACING_DECREASE", 161 ); 269 270 define( "EZ_TEMPLATE_NODE_OPTIMIZED_INIT", 201 ); 271 272 273 define( "EZ_TEMPLATE_NODE_USER_CUSTOM", 1000 ); 274 275 276 define( "EZ_TEMPLATE_TYPE_VOID", 0 ); 277 define( "EZ_TEMPLATE_TYPE_STRING", 1 ); 278 define( "EZ_TEMPLATE_TYPE_NUMERIC", 2 ); 279 define( "EZ_TEMPLATE_TYPE_IDENTIFIER", 3 ); 280 define( "EZ_TEMPLATE_TYPE_VARIABLE", 4 ); 281 define( "EZ_TEMPLATE_TYPE_ATTRIBUTE", 5 ); 282 define( "EZ_TEMPLATE_TYPE_OPERATOR", 6 ); 283 define( "EZ_TEMPLATE_TYPE_BOOLEAN", 7 ); 284 define( "EZ_TEMPLATE_TYPE_ARRAY", 8 ); 285 define( "EZ_TEMPLATE_TYPE_DYNAMIC_ARRAY", 9 ); 286 287 define( "EZ_TEMPLATE_TYPE_INTERNAL", 100 ); 288 define( "EZ_TEMPLATE_TYPE_INTERNAL_CODE_PIECE", 101 ); 289 define( "EZ_TEMPLATE_TYPE_PHP_VARIABLE", 102 ); 290 291 define( "EZ_TEMPLATE_TYPE_OPTIMIZED_NODE", 201 ); 292 define( "EZ_TEMPLATE_TYPE_OPTIMIZED_ARRAY_LOOKUP", 202 ); 293 define( "EZ_TEMPLATE_TYPE_OPTIMIZED_CONTENT_CALL", 203 ); 294 define( "EZ_TEMPLATE_TYPE_OPTIMIZED_ATTRIBUTE_LOOKUP", 204 ); 295 296 define( "EZ_TEMPLATE_TYPE_INTERNAL_STOP", 999 ); 297 298 299 define( "EZ_TEMPLATE_TYPE_STRING_BIT", (1 << (EZ_TEMPLATE_TYPE_STRING - 1)) ); 300 define( "EZ_TEMPLATE_TYPE_NUMERIC_BIT", (1 << (EZ_TEMPLATE_TYPE_NUMERIC - 1)) ); 301 define( "EZ_TEMPLATE_TYPE_IDENTIFIER_BIT", (1 << (EZ_TEMPLATE_TYPE_IDENTIFIER - 1)) ); 302 define( "EZ_TEMPLATE_TYPE_VARIABLE_BIT", (1 << (EZ_TEMPLATE_TYPE_VARIABLE - 1)) ); 303 define( "EZ_TEMPLATE_TYPE_ATTRIBUTE_BIT", (1 << (EZ_TEMPLATE_TYPE_ATTRIBUTE - 1)) ); 304 define( "EZ_TEMPLATE_TYPE_OPERATOR_BIT", (1 << (EZ_TEMPLATE_TYPE_OPERATOR - 1)) ); 305 306 define( "EZ_TEMPLATE_TYPE_NONE", 0 ); 307 308 define( "EZ_TEMPLATE_TYPE_ALL", (EZ_TEMPLATE_TYPE_STRING_BIT | 309 EZ_TEMPLATE_TYPE_NUMERIC_BIT | 310 EZ_TEMPLATE_TYPE_IDENTIFIER_BIT | 311 EZ_TEMPLATE_TYPE_VARIABLE_BIT | 312 EZ_TEMPLATE_TYPE_ATTRIBUTE_BIT | 313 EZ_TEMPLATE_TYPE_OPERATOR_BIT ) ); 314 315 define( "EZ_TEMPLATE_TYPE_BASIC", (EZ_TEMPLATE_TYPE_STRING_BIT | 316 EZ_TEMPLATE_TYPE_NUMERIC_BIT | 317 EZ_TEMPLATE_TYPE_IDENTIFIER_BIT | 318 EZ_TEMPLATE_TYPE_VARIABLE_BIT | 319 EZ_TEMPLATE_TYPE_OPERATOR_BIT ) ); 320 321 define( "EZ_TEMPLATE_TYPE_MODIFIER_MASK", (EZ_TEMPLATE_TYPE_ATTRIBUTE_BIT | 322 EZ_TEMPLATE_TYPE_OPERATOR_BIT) ); 323 324 define( "EZ_TEMPLATE_NAMESPACE_SCOPE_GLOBAL", 1 ); 325 define( "EZ_TEMPLATE_NAMESPACE_SCOPE_LOCAL", 2 ); 326 define( "EZ_TEMPLATE_NAMESPACE_SCOPE_RELATIVE", 3 ); 327 328 define( "EZ_TEMPLATE_DEBUG_INTERNALS", false ); 329 330 define( 'EZ_ERROR_TEMPLATE_FILE_ERRORS', 1 ); 331 332 class eZTemplate 333 { 334 /*! 335 Intializes the template with left and right delimiters being { and }, 336 and a file resource. The literal tag "literal" is also registered. 337 */ 338 function eZTemplate() 339 { 340 $this->Tree = array( EZ_TEMPLATE_NODE_ROOT, false ); 341 $this->LDelim = "{"; 342 $this->RDelim = "}"; 343 344 $this->IncludeText = array(); 345 $this->IncludeOutput = array(); 346 347 $this->registerLiteral( "literal" ); 348 349 $res = new eZTemplateFileResource(); 350 $this->DefaultResource =& $res; 351 $this->registerResource( $res ); 352 353 $this->Resources = array(); 354 $this->Text = null; 355 356 $this->IsCachingAllowed = true; 357 358 $this->resetErrorLog(); 359 360 $this->AutoloadPathList = array( 'lib/eztemplate/classes/' ); 361 $this->Variables = array(); 362 $this->LocalVariablesNamesStack = array(); 363 $this->CurrentLocalVariablesNames = null; 364 $this->Functions = array(); 365 $this->FunctionAttributes = array(); 366 367 $this->TestCompile = false; 368 369 $ini = eZINI::instance( 'template.ini' ); 370 if ( $ini->hasVariable( 'ControlSettings', 'MaxLevel' ) ) 371 $this->MaxLevel = $ini->variable( 'ControlSettings', 'MaxLevel' ); 372 include_once ('kernel/common/i18n.php'); 373 $this->MaxLevelWarning = ezi18n( 'lib/template', 374 'The maximum nesting level of 40 has been reached. The execution is stopped to avoid infinite recursion.' ); 375 eZDebug::createAccumulatorGroup( 'template_total', 'Template Total' ); 376 377 $this->TemplatesUsageStatistics = array(); 378 // Array of templates which are used in a single fetch() 379 $this->TemplateFetchList = array(); 380 381 $this->ForeachCounter = 0; 382 $this->ForCounter = 0; 383 $this->WhileCounter = 0; 384 $this->DoCounter = 0; 385 $this->ElseifCounter = 0; 386 } 387 388 /*! 389 Returns the left delimiter being used. 390 */ 391 function leftDelimiter() 392 { 393 return $this->LDelim; 394 } 395 396 /*! 397 Returns the right delimiter being used. 398 */ 399 function rightDelimiter() 400 { 401 return $this->RDelim; 402 } 403 404 /*! 405 Sets the left delimiter. 406 */ 407 function setLeftDelimiter( $delim ) 408 { 409 $this->LDelim = $delim; 410 } 411 412 /*! 413 Sets the right delimiter. 414 */ 415 function setRightDelimiter( $delim ) 416 { 417 $this->RDelim = $delim; 418 } 419 420 /*! 421 Fetches the result of the template file and displays it. 422 If $template is supplied it will load this template file first. 423 */ 424 function display( $template = false, $extraParameters = false ) 425 { 426 $output =& $this->fetch( $template, $extraParameters ); 427 if ( $this->ShowDetails ) 428 { 429 echo '<h1>Result:</h1>' . "\n"; 430 echo '<hr/>' . "\n"; 431 } 432 echo "$output"; 433 if ( $this->ShowDetails ) 434 { 435 echo '<hr/>' . "\n"; 436 } 437 if ( $this->ShowDetails ) 438 { 439 echo "<h1>Template data:</h1>"; 440 echo "<p class=\"filename\">" . $template . "</p>"; 441 echo "<pre class=\"example\">" . htmlspecialchars( $this->Text ) . "</pre>"; 442 reset( $this->IncludeText ); 443 while ( ( $key = key( $this->IncludeText ) ) !== null ) 444 { 445 $item =& $this->IncludeText[$key]; 446 echo "<p class=\"filename\">" . $key . "</p>"; 447 echo "<pre class=\"example\">" . htmlspecialchars( $item ) . "</pre>"; 448 next( $this->IncludeText ); 449 } 450 echo "<h1>Result text:</h1>"; 451 echo "<p class=\"filename\">" . $template . "</p>"; 452 echo "<pre class=\"example\">" . htmlspecialchars( $output ) . "</pre>"; 453 reset( $this->IncludeOutput ); 454 while ( ( $key = key( $this->IncludeOutput ) ) !== null ) 455 { 456 $item =& $this->IncludeOutput[$key]; 457 echo "<p class=\"filename\">" . $key . "</p>"; 458 echo "<pre class=\"example\">" . htmlspecialchars( $item ) . "</pre>"; 459 next( $this->IncludeOutput ); 460 } 461 } 462 } 463 464 /*! 465 * Initialize list of local variables for the current template. 466 * The list contains only names of variables. 467 */ 468 function createLocalVariablesList() 469 { 470 $this->LocalVariablesNamesStack[] = array(); 471 $this->CurrentLocalVariablesNames =& $this->LocalVariablesNamesStack[ count( $this->LocalVariablesNamesStack ) - 1]; 472 } 473 474 /*! 475 * Check if the given local variable exists. 476 */ 477 function hasLocalVariable( $varName, $rootNamespace ) 478 { 479 return ( array_key_exists( $rootNamespace, $this->CurrentLocalVariablesNames ) && 480 array_key_exists( $varName, $this->CurrentLocalVariablesNames[$rootNamespace] ) ); 481 } 482 483 /*! 484 * Create a local variable. 485 */ 486 function setLocalVariable( $varName, $varValue, $rootNamespace ) 487 { 488 $this->CurrentLocalVariablesNames[$rootNamespace][$varName] = 1; 489 $this->setVariable( $varName, $varValue, $rootNamespace ); 490 } 491 492 /*! 493 * Destroy a local variable. 494 */ 495 function unsetLocalVariable( $varName, $rootNamespace ) 496 { 497 if ( !$this->hasLocalVariable( $varName, $rootNamespace ) ) 498 return; 499 500 $this->unsetVariable( $varName, $rootNamespace ); 501 unset( $this->CurrentLocalVariablesNames[$rootNamespace][$varName] ); 502 } 503 504 /*! 505 * Destroy all local variables defined in the current template. 506 */ 507 function unsetLocalVariables() 508 { 509 foreach ( $this->CurrentLocalVariablesNames as $ns => $vars ) 510 { 511 foreach ( $vars as $var => $val ) 512 $this->unsetLocalVariable( $var, $ns ); 513 } 514 } 515 516 /*! 517 * Destroy list of local variables defined in the current (innermost) template. 518 */ 519 function destroyLocalVariablesList() 520 { 521 array_pop( $this->LocalVariablesNamesStack ); 522 523 if ( $this->LocalVariablesNamesStack ) 524 $this->CurrentLocalVariablesNames =& $this->LocalVariablesNamesStack[ count( $this->LocalVariablesNamesStack ) - 1]; 525 else 526 unset( $this->CurrentLocalVariablesNames ); 527 } 528 529 /*! 530 Tries to fetch the result of the template file and returns it. 531 If $template is supplied it will load this template file first. 532 */ 533 function &fetch( $template = false, $extraParameters = false, $returnResourceData = false ) 534 { 535 $this->resetErrorLog(); 536 // Reset fetch list when a new fetch is started 537 $this->TemplateFetchList = array(); 538 539 eZDebug::accumulatorStart( 'template_total' ); 540 eZDebug::accumulatorStart( 'template_load', 'template_total', 'Template load' ); 541 $root = null; 542 if ( is_string( $template ) ) 543 { 544 $resourceData =& $this->loadURIRoot( $template, true, $extraParameters ); 545 if ( $resourceData and 546 $resourceData['root-node'] !== null ) 547 $root =& $resourceData['root-node']; 548 } 549 eZDebug::accumulatorStop( 'template_load' ); 550 if ( $resourceData['locales'] && count( $resourceData['locales'] ) ) 551 { 552 $savedLocale = setlocale( LC_CTYPE, null ); 553 setlocale( LC_CTYPE, $resourceData['locales'] ); 554 } 555 556 $text = ""; 557 558 if ( $root !== null or 559 $resourceData['compiled-template'] ) 560 { 561 if ( $this->ShowDetails ) 562 eZDebug::addTimingPoint( "Process" ); 563 eZDebug::accumulatorStart( 'template_processing', 'template_total', 'Template processing' ); 564 565 $templateCompilationUsed = false; 566 if ( $resourceData['compiled-template'] ) 567 { 568 $textElements = array(); 569 if ( $this->executeCompiledTemplate( $resourceData, $textElements, "", "", $extraParameters ) ) 570 { 571 $text = implode( '', $textElements ); 572 $templateCompilationUsed = true; 573 } 574 } 575 if ( !$templateCompilationUsed ) 576 { 577 if ( eZTemplate::isDebugEnabled() ) 578 { 579 $fname = $resourceData['template-filename']; 580 eZDebug::writeDebug( "FETCH START URI: $template, $fname" ); 581 } 582 $this->process( $root, $text, "", "" ); 583 if ( eZTemplate::isDebugEnabled() ) 584 eZDebug::writeDebug( "FETCH END URI: $template, $fname" ); 585 } 586 587 eZDebug::accumulatorStop( 'template_processing' ); 588 if ( $this->ShowDetails ) 589 eZDebug::addTimingPoint( "Process done" ); 590 } 591 592 eZDebug::accumulatorStop( 'template_total' ); 593 594 if ( $resourceData['locales'] && count( $resourceData['locales'] ) ) 595 { 596 setlocale( LC_CTYPE, $savedLocale ); 597 } 598 599 if ( $returnResourceData ) 600 { 601 $resourceData['result_text'] = $text; 602 return $resourceData; 603 } 604 return $text; 605 } 606 607 function process( &$root, &$text, $rootNamespace, $currentNamespace ) 608 { 609 $this->createLocalVariablesList(); 610 611 $textElements = array(); 612 $this->processNode( $root, $textElements, $rootNamespace, $currentNamespace ); 613 if ( is_array( $textElements ) ) 614 $text = implode( '', $textElements ); 615 else 616 $text = $textElements; 617 618 $this->unsetLocalVariables(); 619 $this->destroyLocalVariablesList(); 620 } 621 622 function processNode( &$node, &$textElements, $rootNamespace, $currentNamespace ) 623 { 624 $rslt = null; 625 $nodeType = $node[0]; 626 if ( $nodeType == EZ_TEMPLATE_NODE_ROOT ) 627 { 628 $children = $node[1]; 629 if ( $children ) 630 { 631 foreach ( $children as $child ) 632 { 633 $this->processNode( $child, $textElements, $rootNamespace, $currentNamespace ); 634 if ( !is_array( $textElements ) ) 635 eZDebug::writeError( "Textelements is no longer array: '$textElements'", 636 'eztemplate::processNode::root' ); 637 } 638 } 639 } 640 else if ( $nodeType == EZ_TEMPLATE_NODE_TEXT ) 641 { 642 $textElements[] = $node[2]; 643 } 644 else if ( $nodeType == EZ_TEMPLATE_NODE_VARIABLE ) 645 { 646 $variableData = $node[2]; 647 $variablePlacement = $node[3]; 648 $rslt = $this->processVariable( $textElements, $variableData, $variablePlacement, $rootNamespace, $currentNamespace ); 649 if ( !is_array( $textElements ) ) 650 eZDebug::writeError( "Textelements is no longer array: '$textElements'", 651 'eztemplate::processNode::variable' ); 652 } 653 else if ( $nodeType == EZ_TEMPLATE_NODE_FUNCTION ) 654 { 655 $functionChildren = $node[1]; 656 $functionName = $node[2]; 657 $functionParameters = $node[3]; 658 $functionPlacement = $node[4]; 659 $rslt = $this->processFunction( $functionName, $textElements, $functionChildren, $functionParameters, $functionPlacement, $rootNamespace, $currentNamespace ); 660 if ( !is_array( $textElements ) ) 661 eZDebug::writeError( "Textelements is no longer array: '$textElements'", 662 "eztemplate::processNode::function( '$functionName' )" ); 663 } 664 665 return $rslt; 666 } 667 668 function processVariable( &$textElements, $variableData, $variablePlacement, $rootNamespace, $currentNamespace ) 669 { 670 $value = $this->elementValue( $variableData, $rootNamespace, $currentNamespace, $variablePlacement ); 671 $this->appendElementText( $textElements, $value, $rootNamespace, $currentNamespace ); 672 } 673 674 function processFunction( $functionName, &$textElements, $functionChildren, $functionParameters, $functionPlacement, $rootNamespace, $currentNamespace ) 675 { 676 // Note: This code piece is replicated in the eZTemplateCompiler, 677 // if this code is changed the replicated code must be updated as well. 678 $func =& $this->Functions[$functionName]; 679 if ( is_array( $func ) ) 680 { 681 $this->loadAndRegisterFunctions( $this->Functions[$functionName] ); 682 $func =& $this->Functions[$functionName]; 683 } 684 if ( isset( $func ) and 685 is_object( $func ) ) 686 { 687 if ( eZTemplate::isMethodDebugEnabled() ) 688 eZDebug::writeDebug( "START FUNCTION: $functionName" ); 689 $value = $func->process( $this, $textElements, $functionName, $functionChildren, $functionParameters, $functionPlacement, $rootNamespace, $currentNamespace ); 690 if ( eZTemplate::isMethodDebugEnabled() ) 691 eZDebug::writeDebug( "END FUNCTION: $functionName" ); 692 return $value; 693 } 694 else 695 { 696 $this->warning( "", "Function \"$functionName\" is not registered" ); 697 } 698 } 699 700 function fetchFunctionObject( $functionName ) 701 { 702 $func =& $this->Functions[$functionName]; 703 if ( is_array( $func ) ) 704 { 705 $this->loadAndRegisterFunctions( $this->Functions[$functionName] ); 706 $func =& $this->Functions[$functionName]; 707 } 708 return $func; 709 } 710 711 /*! 712 Loads the template using the URI $uri and parses it. 713 \return The root node of the tree if \a $returnResourceData is false, 714 if \c true the entire resource data structure. 715 */ 716 function &load( $uri, $extraParameters = false, $returnResourceData = false ) 717 { 718 $resourceData =& $this->loadURIRoot( $uri, true, $extraParameters ); 719 if ( !$resourceData or 720 $resourceData['root-node'] === null ) 721 { 722 $retValue = null; 723 return $retValue; 724 } 725 else 726 return $resourceData['root-node']; 727 } 728 729 function parse( &$sourceText, &$rootElement, $rootNamespace, &$resourceData ) 730 { 731 include_once ( 'lib/eztemplate/classes/eztemplatemultipassparser.php' ); 732 $parser =& eZTemplateMultiPassParser::instance(); 733 $parser->parse( $this, $sourceText, $rootElement, $rootNamespace, $resourceData ); 734 } 735 736 function &loadURIData( &$resourceObject, $uri, $resourceName, $template, &$extraParameters, $displayErrors = true ) 737 { 738 $resourceData = $this->resourceData( $resourceObject, $uri, $resourceName, $template ); 739 740 $resourceData['text'] = null; 741 $resourceData['root-node'] = null; 742 $resourceData['compiled-template'] = false; 743 $resourceData['time-stamp'] = null; 744 $resourceData['key-data'] = null; 745 $resourceData['locales'] = null; 746 747 if ( !$resourceObject->handleResource( $this, $resourceData, EZ_RESOURCE_FETCH, $extraParameters ) ) 748 { 749 $resourceData = null; 750 if ( $displayErrors ) 751 $this->warning( "", "No template could be loaded for \"$template\" using resource \"$resourceName\"" ); 752 } 753 return $resourceData; 754 } 755 756 /*! 757 \static 758 Creates a resource data structure of the parameters and returns it. 759 This structure is passed to various parts of the template system. 760 761 \note If you only have the URI you should call resourceFor() first to 762 figure out the resource handler. 763 */ 764 function resourceData( &$resourceObject, $uri, $resourceName, $templateName ) 765 { 766 $resourceData = array(); 767 $resourceData['uri'] = $uri; 768 $resourceData['resource'] = $resourceName; 769 $resourceData['template-name'] = $templateName; 770 $resourceData['template-filename'] = $templateName; 771 $resourceData['handler'] =& $resourceObject; 772 $resourceData['test-compile'] = $this->TestCompile; 773 return $resourceData; 774 } 775 776 /*! 777 Loads the template using the URI $uri and returns a structure with the text and timestamp, 778 false otherwise. 779 The structure keys are: 780 - "text", the text. 781 - "time-stamp", the timestamp. 782 */ 783 function &loadURIRoot( $uri, $displayErrors = true, &$extraParameters ) 784 { 785 $res = ""; 786 $template = ""; 787 $resobj =& $this->resourceFor( $uri, $res, $template ); 788 789 if ( !is_object( $resobj ) ) 790 { 791 if ( $displayErrors ) 792 $this->warning( "", "No resource handler for \"$res\" and no default resource handler, aborting." ); 793 return null; 794 } 795 796 $canCache = true; 797 if ( !$resobj->servesStaticData() ) 798 $canCache = false; 799 if ( !$this->isCachingAllowed() ) 800 $canCache = false; 801 802 $resourceData =& $this->loadURIData( $resobj, $uri, $res, $template, $extraParameters, $displayErrors ); 803 804 if ( $resourceData ) 805 { 806 $root = null; 807 eZTemplate::appendTemplateToStatisticsIfNeeded( $resourceData['template-name'], $resourceData['template-filename'] ); 808 $this->appendTemplateFetch( $resourceData['template-filename'] ); 809 810 if ( !$resourceData['compiled-template'] and 811 $resourceData['root-node'] === null ) 812 { 813 $root =& $resourceData['root-node']; 814 $root = array( EZ_TEMPLATE_NODE_ROOT, false ); 815 $templateText =& $resourceData["text"]; 816 $keyData = $resourceData['key-data']; 817 $this->setIncludeText( $uri, $templateText ); 818 $rootNamespace = ''; 819 $this->parse( $templateText, $root, $rootNamespace, $resourceData ); 820 821 if ( eZTemplate::isDebugEnabled() ) 822 { 823 $this->appendDebugNodes( $root, $resourceData ); 824 } 825 826 if ( $canCache ) 827 $resobj->setCachedTemplateTree( $keyData, $uri, $res, $template, $extraParameters, $root ); 828 } 829 if ( !$resourceData['compiled-template'] and 830 $canCache and 831 $this->canCompileTemplate( $resourceData, $extraParameters ) ) 832 { 833 $generateStatus = $this->compileTemplate( $resourceData, $extraParameters ); 834 if ( $generateStatus ) 835 $resourceData['compiled-template'] = true; 836 } 837 } 838 839 return $resourceData; 840 } 841 842 function processURI( $uri, $displayErrors = true, &$extraParameters, 843 &$textElements, $rootNamespace, $currentNamespace ) 844 { 845 $this->Level++; 846 if ( $this->Level > $this->MaxLevel ) 847 { 848 eZDebug::writeError( $this->MaxLevelWarning, "eZTemplate:processURI Level: $this->Level @ $uri" ); 849 $textElements[] = $this->MaxLevelWarning; 850 $this->Level--; 851 return; 852 } 853 $resourceData =& $this->loadURIRoot( $uri, $displayErrors, $extraParameters ); 854 if ( !$resourceData or 855 ( !$resourceData['compiled-template'] and 856 $resourceData['root-node'] === null ) ) 857 { 858 $this->Level--; 859 return; 860 } 861 862 $templateCompilationUsed = false; 863 864 if ( $resourceData['locales'] && count( $resourceData['locales'] ) ) 865 { 866 $savedLocale = setlocale( LC_CTYPE, null ); 867 setlocale( LC_CTYPE, $resourceData['locales'] ); 868 } 869 870 if ( $resourceData['compiled-template'] ) 871 { 872 if ( $this->executeCompiledTemplate( $resourceData, $textElements, $rootNamespace, $currentNamespace, $extraParameters ) ) 873 $templateCompilationUsed = true; 874 } 875 if ( !$templateCompilationUsed ) 876 { 877 $root =& $resourceData['root-node']; 878 $text = null; 879 if ( eZTemplate::isDebugEnabled() ) 880 { 881 $fname = $resourceData['template-filename']; 882 eZDebug::writeDebug( "START URI: $uri, $fname" ); 883 } 884 $this->process( $root, $text, $rootNamespace, $currentNamespace ); 885 if ( eZTemplate::isDebugEnabled() ) 886 eZDebug::writeDebug( "END URI: $uri, $fname" ); 887 $this->setIncludeOutput( $uri, $text ); 888 $textElements[] = $text; 889 } 890 891 if ( $resourceData['locales'] && count( $resourceData['locales'] ) ) 892 { 893 setlocale( LC_CTYPE, $savedLocale ); 894 } 895 $this->Level--; 896 897 } 898 899 function canCompileTemplate( &$resourceData, &$extraParameters ) 900 { 901 $resourceObject =& $resourceData['handler']; 902 if ( !$resourceObject ) 903 return false; 904 $canGenerate = $resourceObject->canCompileTemplate( $this, $resourceData, $extraParameters ); 905 return $canGenerate; 906 } 907 908 /*! 909 Validates the template file \a $file and returns \c true if the file has correct syntax. 910 \param $returnResourceData If \c true then the returned value will be the resourcedata structure 911 \sa compileTemplateFile(), fetch() 912 */ 913 function validateTemplateFile( $file, $returnResourceData = false ) 914 { 915 $this->resetErrorLog(); 916 917 if ( !file_exists( $file ) ) 918 return false; 919 $resourceHandler =& $this->resourceFor( $file, $resourceName, $templateName ); 920 if ( !$resourceHandler ) 921 return false; 922 $resourceData = $this->resourceData( $resourceHandler, $file, $resourceName, $templateName ); 923 $keyData =& $resourceData['key-data']; 924 $keyData = "file:" . $file; 925 $key = md5( $keyData ); 926 $extraParameters = array(); 927 928 // Disable caching/compiling while fetchin the resource 929 // It will be restored afterwards 930 $isCachingAllowed = $this->IsCachingAllowed; 931 $this->IsCachingAllowed = false; 932 933 $resourceHandler->handleResource( $this, $resourceData, EZ_RESOURCE_FETCH, $extraParameters ); 934 935 // Restore previous caching flag 936 $this->IsCachingAllowed = $isCachingAllowed; 937 938 $root =& $resourceData['root-node']; 939 $root = array( EZ_TEMPLATE_NODE_ROOT, false ); 940 $templateText =& $resourceData["text"]; 941 $rootNamespace = ''; 942 $this->parse( $templateText, $root, $rootNamespace, $resourceData ); 943 if ( eZTemplate::isDebugEnabled() ) 944 { 945 $this->appendDebugNodes( $root, $resourceData ); 946 } 947 948 $result = !$this->hasErrors() and !$this->hasWarnings(); 949 if ( $returnResourceData ) 950 { 951 $resourceData['result'] = $result; 952 return $resourceData; 953 } 954 return $result; 955 } 956 957 /*! 958 Compiles the template file \a $file and returns \c true if the compilation was OK. 959 \param $returnResourceData If \c true then the returned value will be the resourcedata structure 960 \sa validateTemplateFile(), fetch() 961 */ 962 function compileTemplateFile( $file, $returnResourceData = false ) 963 { 964 $this->resetErrorLog(); 965 966 if ( !file_exists( $file ) ) 967 return false; 968 $resourceHandler =& $this->resourceFor( $file, $resourceName, $templateName ); 969 if ( !$resourceHandler ) 970 return false; 971 $resourceData = $this->resourceData( $resourceHandler, $file, $resourceName, $templateName ); 972 $keyData =& $resourceData['key-data']; 973 $keyData = "file:" . $file; 974 $key = md5( $keyData ); 975 $extraParameters = array(); 976 $resourceHandler->handleResource( $this, $resourceData, EZ_RESOURCE_FETCH, $extraParameters ); 977 978 $isCompiled = false; 979 if ( isset( $resourceData['compiled-template'] ) ) 980 $isCompiled = $resourceData['compiled-template']; 981 982 if ( !$isCompiled ) 983 { 984 $root =& $resourceData['root-node']; 985 $root = array( EZ_TEMPLATE_NODE_ROOT, false ); 986 $templateText =& $resourceData["text"]; 987 $rootNamespace = ''; 988 $this->parse( $templateText, $root, $rootNamespace, $resourceData ); 989 if ( eZTemplate::isDebugEnabled() ) 990 { 991 $this->appendDebugNodes( $root, $resourceData ); 992 } 993 994 $result = eZTemplateCompiler::compileTemplate( $this, $key, $resourceData ); 995 } 996 else 997 { 998 $result = true; 999 } 1000 1001 if ( $returnResourceData ) 1002 { 1003 $resourceData['result'] = $result; 1004 return $resourceData; 1005 } 1006 return $result; 1007 } 1008 1009 function compileTemplate( &$resourceData, &$extraParameters ) 1010 { 1011 $resourceObject =& $resourceData['handler']; 1012 if ( !$resourceObject ) 1013 return false; 1014 $keyData = $resourceData['key-data']; 1015 $uri = $resourceData['uri']; 1016 $resourceName = $resourceData['resource']; 1017 $templatePath = $resourceData['template-name']; 1018 return $resourceObject->compileTemplate( $this, $keyData, $uri, $resourceName, $templatePath, $extraParameters, $resourceData ); 1019 } 1020 1021 function executeCompiledTemplate( &$resourceData, &$textElements, $rootNamespace, $currentNamespace, &$extraParameters ) 1022 { 1023 $resourceObject =& $resourceData['handler']; 1024 if ( !$resourceObject ) 1025 return false; 1026 $keyData = $resourceData['key-data']; 1027 $uri = $resourceData['uri']; 1028 $resourceName = $resourceData['resource']; 1029 $templatePath = $resourceData['template-name']; 1030 $timestamp = $resourceData['time-stamp']; 1031 return $resourceObject->executeCompiledTemplate( $this, $textElements, 1032 $keyData, $uri, $resourceData, $templatePath, 1033 $extraParameters, $timestamp, 1034 $rootNamespace, $currentNamespace ); 1035 } 1036 1037 /*! 1038 Returns the resource object for URI $uri. If a resource type is specified 1039 in the URI it is extracted and set in $res. The template name is set in $template 1040 without any resource specifier. To specify a resource the name and a ":" is 1041 prepended to the URI, for instance file:my.tpl. 1042 If no resource type is found the URI the default resource handler is used. 1043 */ 1044 function &resourceFor( &$uri, &$res, &$template ) 1045 { 1046 $args = explode( ":", $uri ); 1047 if ( count( $args ) > 1 ) 1048 { 1049 $res = $args[0]; 1050 $template = $args[1]; 1051 } 1052 else 1053 $template = $uri; 1054 if ( eZTemplate::isDebugEnabled() ) 1055 eZDebug::writeNotice( "eZTemplate: Loading template \"$template\" with resource \"$res\"" ); 1056 $resobj =& $this->DefaultResource; 1057 if ( isset( $this->Resources[$res] ) and is_object( $this->Resources[$res] ) ) 1058 { 1059 $resobj =& $this->Resources[$res]; 1060 } 1061 return $resobj; 1062 } 1063 1064 /*! 1065 \return The resource handler object for resource name \a $resourceName. 1066 \sa resourceFor 1067 */ 1068 function &resourceHandler( $resourceName ) 1069 { 1070 $resource =& $this->DefaultResource; 1071 if ( isset( $this->Resources[$resourceName] ) and 1072 is_object( $this->Resources[$resourceName] ) ) 1073 { 1074 $resource =& $this->Resources[$resourceName]; 1075 } 1076 return $resource; 1077 } 1078 1079 function hasChildren( &$function, $functionName ) 1080 { 1081 $hasChildren = $function->hasChildren(); 1082 if ( is_array( $hasChildren ) ) 1083 return $hasChildren[$functionName]; 1084 else 1085 return $hasChildren; 1086 } 1087 1088 /*! 1089 Returns the empty variable type. 1090 */ 1091 function emptyVariable() 1092 { 1093 return array( "type" => "null" ); 1094 } 1095 1096 /*! 1097 \static 1098 */ 1099 function mergeNamespace( $rootNamespace, $additionalNamespace ) 1100 { 1101 $namespace = $rootNamespace; 1102 if ( $namespace == '' ) 1103 $namespace = $additionalNamespace; 1104 else if ( $additionalNamespace != '' ) 1105 $namespace = "$namespace:$additionalNamespace"; 1106 return $namespace; 1107 } 1108 1109 /*! 1110 Returns the actual value of a template type or null if an unknown type. 1111 */ 1112 function &elementValue( &$dataElements, $rootNamespace, $currentNamespace, $placement = false, 1113 $checkExistance = false, $checkForProxy = false ) 1114 { 1115 /* 1116 * We use a small dirty hack in this function... 1117 * To help the caller to determine if the value was a proxy object, 1118 * we store boolean true to $dataElements['proxy-object-found'] in this case. 1119 * (it's up to caller to remove this garbage from $dataElements...) 1120 * This behaviour is enabled by $checkForProxy parameter. 1121 */ 1122 1123 $value = null; 1124 if ( !is_array( $dataElements ) ) 1125 { 1126 $this->error( "elementValue", 1127 "Missing array data structure, got " . gettype( $dataElements ) ); 1128 $retVal = null; 1129 return $retVal; 1130 } 1131 foreach ( $dataElements as $dataElement ) 1132 { 1133 if ( is_null( $dataElement ) ) 1134 { 1135 $retVal = null; 1136 return $retVal; 1137 } 1138 $dataType = $dataElement[0]; 1139 switch ( $dataType ) 1140 { 1141 case EZ_TEMPLATE_TYPE_VOID: 1142 { 1143 if ( !$checkExistance ) 1144 $this->warning( 'elementValue', 1145 'Found void datatype, should not be used' ); 1146 else 1147 { 1148 $retVal = null; 1149 return $retVal; 1150 } 1151 } break; 1152 case EZ_TEMPLATE_TYPE_STRING: 1153 case EZ_TEMPLATE_TYPE_NUMERIC: 1154 case EZ_TEMPLATE_TYPE_IDENTIFIER: 1155 case EZ_TEMPLATE_TYPE_BOOLEAN: 1156 case EZ_TEMPLATE_TYPE_ARRAY: 1157 { 1158 $value = $dataElement[1]; 1159 } break; 1160 case EZ_TEMPLATE_TYPE_VARIABLE: 1161 { 1162 $variableData = $dataElement[1]; 1163 $variableNamespace = $variableData[0]; 1164 $variableNamespaceScope = $variableData[1]; 1165 $variableName = $variableData[2]; 1166 if ( $variableNamespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_GLOBAL ) 1167 $namespace = $variableNamespace; 1168 else if ( $variableNamespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_LOCAL ) 1169 $namespace = $this->mergeNamespace( $rootNamespace, $variableNamespace ); 1170 else if ( $variableNamespaceScope == EZ_TEMPLATE_NAMESPACE_SCOPE_RELATIVE ) 1171 $namespace = $this->mergeNamespace( $currentNamespace, $variableNamespace ); 1172 else 1173 $namespace = false; 1174 if ( $this->hasVariable( $variableName, $namespace ) ) 1175 { 1176 $value = $this->variable( $variableName, $namespace ); 1177 } 1178 else 1179 { 1180 if ( !$checkExistance ) 1181 $this->error( '', "Unknown template variable '$variableName' in namespace '$namespace'", $placement ); 1182 { 1183 $retVal = null; 1184 return $retVal; 1185 } 1186 } 1187 } break; 1188 case EZ_TEMPLATE_TYPE_ATTRIBUTE: 1189 { 1190 $attributeData = $dataElement[1]; 1191 $attributeValue = $this->elementValue( $attributeData, $rootNamespace, $currentNamespace, false, $checkExistance ); 1192 1193 if ( !is_null( $attributeValue ) ) 1194 { 1195 if ( !is_numeric( $attributeValue ) and 1196 !is_string( $attributeValue ) and 1197 !is_bool( $attributeValue ) ) 1198 { 1199 if ( !$checkExistance ) 1200 $this->error( "", 1201 "Cannot use type " . gettype( $attributeValue ) . " for attribute lookup", $placement ); 1202 { 1203 $retVal = null; 1204 return $retVal; 1205 } 1206 } 1207 if ( is_array( $value ) ) 1208 { 1209 if ( array_key_exists( $attributeValue, $value ) ) 1210 { 1211 unset( $tempValue ); 1212 $tempValue =& $value[$attributeValue]; 1213 unset( $value ); 1214 $value =& $tempValue; 1215 } 1216 else 1217 { 1218 if ( !$checkExistance ) 1219 { 1220 $arrayAttributeList = array_keys( $value ); 1221 $arrayCount = count( $arrayAttributeList ); 1222 $errorMessage = "No such attribute for array($arrayCount): $attributeValue"; 1223 $chooseText = "Choose one of following: "; 1224 $errorMessage .= "\n$chooseText"; 1225 $errorMessage .= $this->expandAttributes( $arrayAttributeList, $chooseText, 25 ); 1226 $this->error( "", 1227 $errorMessage, $placement ); 1228 } 1229 $retVal = null; 1230 return $retVal; 1231 } 1232 } 1233 else if ( is_object( $value ) ) 1234 { 1235 if ( method_exists( $value, "attribute" ) and 1236 method_exists( $value, "hasattribute" ) ) 1237 { 1238 if ( $value->hasAttribute( $attributeValue ) ) 1239 { 1240 unset( $tempValue ); 1241 $tempValue =& $value->attribute( $attributeValue ); 1242 unset( $value ); 1243 $value =& $tempValue; 1244 } 1245 else 1246 { 1247 if ( !$checkExistance ) 1248 { 1249 $objectAttributeList = array(); 1250 if ( method_exists( $value, 'attributes' ) ) 1251 $objectAttributeList = $value->attributes(); 1252 $objectClass= get_class( $value ); 1253 $errorMessage = "No such attribute for object($objectClass): $attributeValue"; 1254 $chooseText = "Choose one of following: "; 1255 $errorMessage .= "\n$chooseText"; 1256 $errorMessage .= $this->expandAttributes( $objectAttributeList, $chooseText, 25 ); 1257 $this->error( "", 1258 $errorMessage, $placement ); 1259 } 1260 $retVal = null; 1261 return $retVal; 1262 } 1263 } 1264 else 1265 { 1266 if ( !$checkExistance ) 1267 $this->error( "", 1268 "Cannot retrieve attribute of object(" . get_class( $value ) . 1269 "), no attribute functions available", 1270 $placement ); 1271 $retVal = null; 1272 return $retVal; 1273 } 1274 } 1275 else 1276 { 1277 if ( !$checkExistance ) 1278 $this->error( "", 1279 "Cannot retrieve attribute of a " . gettype( $value ), 1280 $placement ); 1281 $retVal = null; 1282 return $retVal; 1283 } 1284 } 1285 else 1286 { 1287 if ( !$checkExistance ) 1288 $this->error( '', 1289 'Attribute value was null, cannot get attribute', 1290 $placement ); 1291 $retVal = null; 1292 return $retVal; 1293 } 1294 } break; 1295 case EZ_TEMPLATE_TYPE_OPERATOR: 1296 { 1297 $operatorParameters = $dataElement[1]; 1298 $operatorName = $operatorParameters[0]; 1299 $operatorParameters = array_splice( $operatorParameters, 1 ); 1300 if ( is_object( $value ) and 1301 method_exists( $value, 'templateValue' ) ) 1302 { 1303 if ( $checkForProxy ) 1304 $dataElements['proxy-object-found'] = true; 1305 $value = $value->templateValue(); 1306 } 1307 $valueData = array( 'value' => $value ); 1308 $this->processOperator( $operatorName, $operatorParameters, $rootNamespace, $currentNamespace, 1309 $valueData, $placement, $checkExistance ); 1310 unset( $value ); 1311 $value = $valueData['value']; 1312 } break; 1313 default: 1314 { 1315 if ( !$checkExistance ) 1316 $this->error( "elementValue", 1317 "Unknown data type: '$dataType'" ); 1318 $retVal = null; 1319 return $retVal; 1320 } 1321 } 1322 } 1323 if ( is_object( $value ) and 1324 method_exists( $value, 'templateValue' ) ) 1325 { 1326 if ( $checkForProxy ) 1327 $dataElements['proxy-object-found'] = true; 1328 $retVal = $value->templateValue(); 1329 return $retVal; 1330 } 1331 return $value; 1332 } 1333 1334 function expandAttributes( $attributeList, $chooseText, $maxThreshold, $minThreshold = 1 ) 1335 { 1336 $errorMessage = ''; 1337 $attributeCount = count( $attributeList ); 1338 if ( $attributeCount < $minThreshold ) 1339 return $errorMessage; 1340 if ( $attributeCount < $maxThreshold ) 1341 { 1342 $chooseLength = strlen( $chooseText ); 1343 $attributeText = ''; 1344 $i = 0; 1345 foreach ( $attributeList as $attributeName ) 1346 { 1347 if ( $i > 0 ) 1348 $attributeText .= ","; 1349 if ( strlen( $attributeText ) > 40 ) 1350 { 1351 $attributeText .= "\n"; 1352 $errorMessage .= $attributeText; 1353 $errorMessage .= str_repeat( ' ', $chooseLength ); 1354 $attributeText = ''; 1355 } 1356 else if ( $i > 0 ) 1357 $attributeText .= " "; 1358 $attributeText .= $attributeName; 1359 ++$i; 1360 } 1361 $errorMessage .= $attributeText; 1362 } 1363 return $errorMessage; 1364 } 1365 1366 function processOperator( $operatorName, $operatorParameters, $rootNamespace, $currentNamespace, 1367 &$valueData, $placement = false, $checkExistance = false ) 1368 { 1369 $namedParameters = array(); 1370 $operatorParameterDefinition = $this->operatorParameterList( $operatorName ); 1371 $i = 0; 1372 foreach ( $operatorParameterDefinition as $parameterName => $parameterType ) 1373 { 1374 if ( !isset( $operatorParameters[$i] ) or 1375 !isset( $operatorParameters[$i][0] ) or 1376 $operatorParameters[$i][0] == EZ_TEMPLATE_TYPE_VOID ) 1377 { 1378 if ( $parameterType["required"] ) 1379 { 1380 if ( !$checkExistance ) 1381 $this->warning( "eZTemplateOperatorElement", "Parameter '$parameterName' ($i) missing", 1382 $placement ); 1383 $namedParameters[$parameterName] = $parameterType["default"]; 1384 } 1385 else 1386 { 1387 $namedParameters[$parameterName] = $parameterType["default"]; 1388 } 1389 } 1390 else 1391 { 1392 $parameterData = $operatorParameters[$i]; 1393 $namedParameters[$parameterName] = $this->elementValue( $parameterData, $rootNamespace, $currentNamespace, false, $checkExistance ); 1394 } 1395 ++$i; 1396 } 1397 1398 if ( is_array( $this->Operators[$operatorName] ) ) 1399 { 1400 $this->loadAndRegisterOperators( $this->Operators[$operatorName] ); 1401 } 1402 $op =& $this->Operators[$operatorName]; 1403 if ( isset( $op ) ) 1404 { 1405 if ( is_object( $op ) and method_exists( $op, 'modify' ) ) 1406 { 1407 $value = $valueData['value']; 1408 if ( eZTemplate::isMethodDebugEnabled() ) 1409 eZDebug::writeDebug( "START OPERATOR: $operatorName" ); 1410 $op->modify( $this, $operatorName, $operatorParameters, $rootNamespace, $currentNamespace, $value, $namedParameters, 1411 $placement ); 1412 if ( eZTemplate::isMethodDebugEnabled() ) 1413 eZDebug::writeDebug( "END OPERATOR: $operatorName" ); 1414 $valueData['value'] = $value; 1415 } 1416 else 1417 $this->error( '', "Object problem with operator '$operatorName' ", 1418 $placement ); 1419 } 1420 else if ( !$checkExistance ) 1421 $this->warning( "", "Operator '$operatorName' is not registered", 1422 $placement ); 1423 } 1424 1425 /*! 1426 Returns the value of the template variable $data, or null if no defined variable for that name. 1427 */ 1428 function &variableElementValue( &$data, $def_nspace ) 1429 { 1430 if ( $data["type"] != "variable" ) 1431 { 1432 $retValue = null; 1433 return $retValue; 1434 } 1435 1436 $nspace = $data["namespace"]; 1437 if ( $nspace === false ) 1438 $nspace = $def_nspace; 1439 else 1440 { 1441 if ( $def_nspace != "" ) 1442 $nspace = $def_nspace . ':' . $nspace; 1443 } 1444 $name = $data["name"]; 1445 if ( !$this->hasVariable( $name, $nspace ) ) 1446 { 1447 $var_name = $name; 1448 $this->warning( "", "Undefined variable: \"$var_name\"" . ( $nspace != "" ? " in namespace \"$nspace\"" : "" ) ); 1449 $retValue = null; 1450 return $retValue; 1451 } 1452 $value =& $this->variable( $name, $nspace ); 1453 $return_value =& $value; 1454 $attrs = $data["attributes"]; 1455 if ( count( $attrs ) > 0 ) 1456 { 1457 foreach( $attrs as $key => $attr ) 1458 { 1459 $attr_value = $this->attributeValue( $attr, $def_nspace ); 1460 if ( !is_null( $attr_value ) ) 1461 { 1462 if ( !is_numeric( $attr_value ) and 1463 !is_string( $attr_value ) ) 1464 { 1465 $this->error( "", 1466 "Cannot use type " . gettype( $attr_value ) . " for attribute lookup" ); 1467 $retValue = null; 1468 return $retValue; 1469 } 1470 if ( is_array( $return_value ) ) 1471 { 1472 if ( isset( $return_value[$attr_value] ) ) 1473 $return_value =& $return_value[$attr_value]; 1474 else 1475 { 1476 $this->error( "", 1477 "No such attribute for array: $attr_value" ); 1478 $retValue = null; 1479 return $retValue; 1480 } 1481 } 1482 else if ( is_object( $return_value ) ) 1483 { 1484 if ( method_exists( $return_value, "attribute" ) and 1485 method_exists( $return_value, "hasattribute" ) ) 1486 { 1487 if ( $return_value->hasAttribute( $attr_value ) ) 1488 { 1489 unset( $return_attribute_value ); 1490 $return_attribute_value =& $return_value->attribute( $attr_value ); 1491 unset( $return_value ); 1492 $return_value =& $return_attribute_value; 1493 } 1494 else 1495 { 1496 $this->error( "", 1497 "No such attribute for object: $attr_value" ); 1498 $retValue = null; 1499 return $retValue; 1500 } 1501 } 1502 else 1503 { 1504 $this->error( "", 1505 "Cannot retrieve attribute of object(" . get_class( $return_value ) . 1506 "), no attribute functions available." ); 1507 $retValue = null; 1508 return $retValue; 1509 } 1510 } 1511 else 1512 { 1513 $this->error( "", 1514 "Cannot retrieve attribute of a " . gettype( $return_value ) ); 1515 $retValue = null; 1516 return $retValue; 1517 } 1518 } 1519 else 1520 { 1521 $retValue = null; 1522 return $retValue; 1523 } 1524 } 1525 } 1526 return $return_value; 1527 } 1528 1529 /*! 1530 Return the identifier used for attribute lookup. 1531 */ 1532 function attributeValue( &$data, $nspace ) 1533 { 1534 switch ( $data["type"] ) 1535 { 1536 case "map": 1537 { 1538 return $data["content"]; 1539 } break; 1540 case "index": 1541 { 1542 return $data["content"]; 1543 } break; 1544 case "variable": 1545 { 1546 return $this->elementValue( $data["content"], $nspace ); 1547 } break; 1548 default: 1549 { 1550 $this->error( "attributeValue()", "Unknown attribute type: " . $data["type"] ); 1551 return null; 1552 } 1553 } 1554 } 1555 1556 /*! 1557 Helper function for creating a displayable text for a variable. 1558 */ 1559 function variableText( $var, $namespace = "", $attrs = array() ) 1560 { 1561 $txt = "$"; 1562 if ( $namespace != "" ) 1563 $txt .= "$namespace:"; 1564 $txt .= $var; 1565 if ( count( $attrs ) > 0 ) 1566 $txt .= "." . implode( ".", $attrs ); 1567 return $txt; 1568 } 1569 1570 /*! 1571 Returns the named parameter list for the operator $name. 1572 */ 1573 function operatorParameterList( $name ) 1574 { 1575 $param_list = array(); 1576 if ( isset( $this->Operators[$name] ) and 1577 is_array( $this->Operators[$name] ) ) 1578 { 1579 $this->loadAndRegisterOperators( $this->Operators[$name] ); 1580 } 1581 $op =& $this->Operators[$name]; 1582 if ( isset( $op ) and 1583 method_exists( $op, "namedparameterlist" ) ) 1584 { 1585 $param_list = $op->namedParameterList(); 1586 if ( method_exists( $op, "namedparameterperoperator" ) and 1587 $op->namedParameterPerOperator() ) 1588 { 1589 if ( !isset( $param_list[$name] ) ) 1590 return array(); 1591 $param_list = $param_list[$name]; 1592 } 1593 } 1594 return $param_list; 1595 } 1596 1597 /*! 1598 Tries to run the operator $operatorName with parameters $operatorParameters 1599 on the value $value. 1600 */ 1601 function doOperator( &$element, &$namespace, &$current_nspace, &$value, &$operatorName, &$operatorParameters, &$named_params ) 1602 { 1603 if ( is_array( $this->Operators[$operatorName] ) ) 1604 { 1605 $this->loadAndRegisterOperators( $this->Operators[$operatorName] ); 1606 } 1607 $op =& $this->Operators[$operatorName]; 1608 if ( isset( $op ) ) 1609 { 1610 $op->modify( $element, $this, $operatorName, $operatorParameters, $namespace, $current_nspace, $value, $named_params ); 1611 } 1612 else 1613 $this->warning( "", "Operator \"$operatorName\" is not registered" ); 1614 } 1615 1616 /*! 1617 Tries to run the function object $func_obj 1618 */ 1619 function doFunction( &$name, &$func_obj, $nspace, $current_nspace ) 1620 { 1621 $func =& $this->Functions[$name]; 1622 if ( is_array( $func ) ) 1623 { 1624 $this->loadAndRegisterFunctions( $this->Functions[$name] ); 1625 $func =& $this->Functions[$name]; 1626 } 1627 if ( isset( $func ) and 1628 is_object( $func ) ) 1629 { 1630 return $func->process( $this, $name, $func_obj, $nspace, $current_nspace ); 1631 } 1632 else 1633 { 1634 $this->warning( "", "Function \"$name\" is not registered" ); 1635 return false; 1636 } 1637 } 1638 1639 /*! 1640 Sets the template variable $var to the value $val. 1641 \sa setVariableRef 1642 */ 1643 function setVariable( $var, $val, $namespace = "" ) 1644 { 1645 if ( array_key_exists( $namespace, $this->Variables ) and 1646 array_key_exists( $var, $this->Variables[$namespace] ) ) 1647 unset( $this->Variables[$namespace][$var] ); 1648 $this->Variables[$namespace][$var] = $val; 1649 } 1650 1651 /*! 1652 Sets the template variable $var to the value $val. 1653 \note This sets the variable using reference 1654 \sa setVariable 1655 */ 1656 function setVariableRef( $var, &$val, $namespace = "" ) 1657 { 1658 if ( array_key_exists( $namespace, $this->Variables ) and 1659 array_key_exists( $var, $this->Variables[$namespace] ) ) 1660 unset( $this->Variables[$namespace][$var] ); 1661 $this->Variables[$namespace][$var] =& $val; 1662 } 1663 1664 /*! 1665 Removes the template variable $var. If the variable does not exists an error is output. 1666 */ 1667 function unsetVariable( $var, $namespace = "" ) 1668 { 1669 if ( array_key_exists( $namespace, $this->Variables ) and 1670 array_key_exists( $var, $this->Variables[$namespace] ) ) 1671 unset( $this->Variables[$namespace][$var] ); 1672 else 1673 $this->warning( "unsetVariable()", "Undefined Variable: \$$namespace:$var, cannot unset" ); 1674 } 1675 1676 /*! 1677 Returns true if the variable $var is set in namespace $namespace, 1678 if $attrs is supplied alle attributes must exist for the function to return true. 1679 */ 1680 function hasVariable( $var, $namespace = "", $attrs = array() ) 1681 { 1682 $exists = ( array_key_exists( $namespace, $this->Variables ) and 1683 array_key_exists( $var, $this->Variables[$namespace] ) ); 1684 if ( $exists and count( $attrs ) > 0 ) 1685 { 1686 $ptr =& $this->Variables[$namespace][$var]; 1687 foreach( $attrs as $attr ) 1688 { 1689 unset( $tmp ); 1690 if ( is_object( $ptr ) ) 1691 { 1692 if ( $ptr->hasAttribute( $attr ) ) 1693 $tmp =& $ptr->attribute( $attr ); 1694 else 1695 return false; 1696 } 1697 else if ( is_array( $ptr ) ) 1698 { 1699 if ( array_key_exists( $attr, $ptr ) ) 1700 $tmp =& $ptr[$attr]; 1701 else 1702 return false; 1703 } 1704 else 1705 { 1706 return false; 1707 } 1708 unset( $ptr ); 1709 $ptr =& $tmp; 1710 } 1711 } 1712 return $exists; 1713 } 1714 1715 /*! 1716 Returns the content of the variable $var using namespace $namespace, 1717 if $attrs is supplied the result of the attributes is returned. 1718 */ 1719 function &variable( $var, $namespace = "", $attrs = array() ) 1720 { 1721 $val = null; 1722 $exists = ( array_key_exists( $namespace, $this->Variables ) and 1723 array_key_exists( $var, $this->Variables[$namespace] ) ); 1724 if ( $exists ) 1725 { 1726 if ( count( $attrs ) > 0 ) 1727 { 1728 $ptr =& $this->Variables[$namespace][$var]; 1729 foreach( $attrs as $attr ) 1730 { 1731 unset( $tmp ); 1732 if ( is_object( $ptr ) ) 1733 { 1734 if ( $ptr->hasAttribute( $attr ) ) 1735 $tmp =& $ptr->attribute( $attr ); 1736 else 1737 return $val; 1738 } 1739 else if ( is_array( $ptr ) ) 1740 { 1741 if ( array_key_exists( $attr, $ptr ) ) 1742 $tmp =& $ptr[$attr]; 1743 else 1744 return $val; 1745 } 1746 else 1747 return $val; 1748 unset( $ptr ); 1749 $ptr =& $tmp; 1750 } 1751 if ( isset( $ptr ) ) 1752 return $ptr; 1753 } 1754 else 1755 { 1756 $val =& $this->Variables[$namespace][$var]; 1757 } 1758 } 1759 return $val; 1760 } 1761 1762 /*! 1763 Returns the attribute(s) of the template variable $var, 1764 $attrs is an array of attribute names to use iteratively for each new variable returned. 1765 */ 1766 function &variableAttribute( &$var, $attrs ) 1767 { 1768 $val = null; 1769 if ( count( $attrs ) > 0 ) 1770 { 1771 $ptr =& $var; 1772 foreach( $attrs as $attr ) 1773 { 1774 unset( $tmp ); 1775 if ( is_object( $ptr ) ) 1776 { 1777 if ( $ptr->hasAttribute( $attr ) ) 1778 $tmp =& $ptr->attribute( $attr ); 1779 else 1780 return $val; 1781 } 1782 else if ( is_array( $ptr ) ) 1783 { 1784 if ( isset( $ptr[$attr] ) ) 1785 $tmp =& $ptr[$attr]; 1786 else 1787 return $val; 1788 } 1789 else 1790 return $val; 1791 unset( $ptr ); 1792 $ptr =& $tmp; 1793 } 1794 if ( isset( $ptr ) ) 1795 return $ptr; 1796 } 1797 return $val; 1798 } 1799 1800 /*! 1801 */ 1802 function appendElement( &$text, &$item, $nspace, $name ) 1803 { 1804 $this->appendElementText( $textElements, $item, $nspace, $name ); 1805 $text .= implode( '', $textElements ); 1806 } 1807 1808 /*! 1809 */ 1810 function appendElementText( &$textElements, &$item, $nspace, $name ) 1811 { 1812 if ( !is_array( $textElements ) ) 1813 $textElements = array(); 1814 if ( is_object( $item ) and 1815 method_exists( $item, 'templateValue' ) ) 1816 { 1817 $item = $item->templateValue(); 1818 $textElements[] = "$item"; 1819 } 1820 else if ( is_object( $item ) ) 1821 { 1822 $hasTemplateData = false; 1823 if ( method_exists( $item, 'templateData' ) ) 1824 { 1825 $templateData = $item->templateData(); 1826 if ( is_array( $templateData ) and 1827 isset( $templateData['type'] ) ) 1828 { 1829 $templateType =& $templateData['type']; 1830 if ( $templateType == 'template' and 1831 isset( $templateData['uri'] ) and 1832 isset( $templateData['template_variable_name'] ) ) 1833 { 1834 $templateURI =& $templateData['uri']; 1835 $templateVariableName =& $templateData['template_variable_name']; 1836 $templateText = ''; 1837 include_once ( 'lib/eztemplate/classes/eztemplateincludefunction.php' ); 1838 $this->setVariableRef( $templateVariableName, $item, $name ); 1839 eZTemplateIncludeFunction::handleInclude( $textElements, $templateURI, $this, $nspace, $name ); 1840 $hasTemplateData = true; 1841 } 1842 } 1843 } 1844 if ( !$hasTemplateData ) 1845 $textElements[] = 'Object(' . get_class( $item ) . ')'; 1846 } 1847 else 1848 $textElements[] = "$item"; 1849 return $textElements; 1850 } 1851 1852 /*! 1853 Creates some text nodes before and after the children of \a $root. 1854 It will extract the current filename and uri and create some XHTML 1855 comments and inline text. 1856 \sa isXHTMLCodeIncluded 1857 */ 1858 function appendDebugNodes( &$root, &$resourceData ) 1859 { 1860 $path = $resourceData['template-filename']; 1861 $uri = $resourceData['uri']; 1862 $preText = "\n<!-- START: including template: $path ($uri) -->\n"; 1863 if ( eZTemplate::isXHTMLCodeIncluded() ) 1864 $preText .= "<p class=\"small\">$path</p><br/>\n"; 1865 $postText = "\n<!-- STOP: including template: $path ($uri) -->\n"; 1866 include_once ( 'lib/eztemplate/classes/eztemplatenodetool.php' ); 1867 $root[1] = array_merge( array( eZTemplateNodeTool::createTextNode( $preText ) ), $root[1] ); 1868 $root[1][] = eZTemplateNodeTool::createTextNode( $postText ); 1869 } 1870 1871 /*! 1872 Registers the functions supplied by the object $functionObject. 1873 The object must have a function called functionList() 1874 which returns an array of functions this object handles. 1875 If the object has a function called attributeList() 1876 it is used for registering function attributes. 1877 The function returns an associative array with each key being 1878 the name of the function and the value being a boolean. 1879 If the boolean is true the function will have children. 1880 */ 1881 function registerFunctions( &$functionObject ) 1882 { 1883 $this->registerFunctionsInternal( $functionObject ); 1884 } 1885 1886 /*! 1887 */ 1888 function registerAutoloadFunctions( $functionDefinition ) 1889 { 1890 if ( ( ( isset( $functionDefinition['function'] ) or 1891 ( isset( $functionDefinition['script'] ) and 1892 isset( $functionDefinition['class'] ) ) ) and 1893 ( isset( $functionDefinition['function_names_function'] ) or 1894 isset( $functionDefinition['function_names'] ) ) ) ) 1895 { 1896 if ( isset( $functionDefinition['function_names_function'] ) ) 1897 { 1898 $functionNamesFunction = $functionDefinition['function_names_function']; 1899 if ( !function_exists( $functionNamesFunction ) ) 1900 { 1901 $this->error( 'registerFunctions', "Cannot register function definition, missing function names function '$functionNamesFunction'" ); 1902 return; 1903 } 1904 $functionNames = $operatorNamesFunction(); 1905 } 1906 else 1907 $functionNames = $functionDefinition['function_names']; 1908 foreach ( $functionNames as $functionName ) 1909 { 1910 $this->Functions[$functionName] =& $functionDefinition; 1911 } 1912 if ( isset( $functionDefinition['function_attributes'] ) ) 1913 { 1914 foreach ( $functionDefinition['function_attributes'] as $functionAttributeName ) 1915 { 1916 unset( $this->FunctionAttributes[$functionAttributeName] ); 1917 $this->FunctionAttributes[$functionAttributeName] =& $functionDefinition; 1918 } 1919 } 1920 } 1921 else 1922 $this->error( 'registerFunctions', 'Cannot register function definition, missing data' ); 1923 } 1924 1925 function loadAndRegisterFunctions( $functionDefinition ) 1926 { 1927 eZDebug::accumulatorStart( 'template_register_function', 'template_total', 'Template load and register function' ); 1928 $functionObject = null; 1929 if ( isset( $functionDefinition['function'] ) ) 1930 { 1931 $function = $functionDefinition['function']; 1932 // print( "loadAndRegisterFunction: $function<br/>" ); 1933 if ( function_exists( $function ) ) 1934 $functionObject = $function(); 1935 } 1936 else if ( isset( $functionDefinition['script'] ) ) 1937 { 1938 $script = $functionDefinition['script']; 1939 $class = $functionDefinition['class']; 1940 // print( "loadAndRegisterFunction: $script<br/>" ); 1941 include_once( $script ); 1942 if ( class_exists( $class ) ) 1943 $functionObject = new $class(); 1944 } 1945 eZDebug::accumulatorStop( 'template_register_function' ); 1946 if ( is_object( $functionObject ) ) 1947 { 1948 $this->registerFunctionsInternal( $functionObject, true ); 1949 return true; 1950 } 1951 return false; 1952 } 1953 1954 /*! 1955 \private 1956 */ 1957 function registerFunctionsInternal( &$functionObject, $debug = false ) 1958 { 1959 if ( !is_object( $functionObject ) or 1960 !method_exists( $functionObject, 'functionList' ) ) 1961 return false; 1962 foreach ( $functionObject->functionList() as $functionName ) 1963 { 1964 $this->Functions[$functionName] =& $functionObject; 1965 } 1966 if ( method_exists( $functionObject, "attributeList" ) ) 1967 { 1968 $functionAttributes = $functionObject->attributeList(); 1969 foreach ( $functionAttributes as $attributeName => $hasChildren ) 1970 { 1971 unset( $this->FunctionAttributes[$attributeName] ); 1972 $this->FunctionAttributes[$attributeName] = $hasChildren; 1973 } 1974 } 1975 return true; 1976 } 1977 1978 /*! 1979 Registers the function $func_name to be bound to object $func_obj. 1980 If the object has a function called attributeList() 1981 it is used for registering function attributes. 1982 The function returns an associative array with each key being 1983 the name of the function and the value being a boolean. 1984 If the boolean is true the function will have children. 1985 */ 1986 function registerFunction( $func_name, &$func_obj ) 1987 { 1988 $this->Functions[$func_name] =& $func_obj; 1989 if ( method_exists( $func_obj, "attributeList" ) ) 1990 { 1991 $attrs = $func_obj->attributeList(); 1992 while ( list( $attr_name, $has_children ) = each( $attrs ) ) 1993 { 1994 $this->FunctionAttributes[$attr_name] = $has_children; 1995 } 1996 } 1997 } 1998 1999 /*! 2000 Registers a new literal tag in which the tag will be transformed into 2001 a text element. 2002 */ 2003 function registerLiteral( $func_name ) 2004 { 2005 $this->Literals[$func_name] = true; 2006 } 2007 2008 /*! 2009 Removes the literal tag $func_name. 2010 */ 2011 function unregisterLiteral( $func_name ) 2012 { 2013 unset( $this->Literals[$func_name] ); 2014 } 2015 2016 /*! 2017 */ 2018 function registerAutoloadOperators( $operatorDefinition ) 2019 { 2020 if ( ( ( isset( $operatorDefinition['function'] ) or 2021 ( isset( $operatorDefinition['script'] ) and 2022 isset( $operatorDefinition['class'] ) ) ) and 2023 ( isset( $operatorDefinition['operator_names_function'] ) or 2024 isset( $operatorDefinition['operator_names'] ) ) ) ) 2025 { 2026 if ( isset( $operatorDefinition['operator_names_function'] ) ) 2027 { 2028 $operatorNamesFunction = $operatorDefinition['operator_names_function']; 2029 if ( !function_exists( $operatorNamesFunction ) ) 2030 { 2031 $this->error( 'registerOperators', "Cannot register operator definition, missing operator names function '$operatorNamesFunction'" ); 2032 return; 2033 } 2034 $operatorNames = $operatorNamesFunction(); 2035 } 2036 else 2037 $operatorNames = $operatorDefinition['operator_names']; 2038 foreach ( $operatorNames as $operatorName ) 2039 { 2040 $this->Operators[$operatorName] =& $operatorDefinition; 2041 } 2042 } 2043 else 2044 $this->error( 'registerOperators', 'Cannot register operator definition, missing data' ); 2045 } 2046 2047 function loadAndRegisterOperators( $operatorDefinition ) 2048 { 2049 $operatorObject = null; 2050 if ( isset( $operatorDefinition['function'] ) ) 2051 { 2052 $function = $operatorDefinition['function']; 2053 // print( "loadAndRegisterOperator: $function<br/>" ); 2054 if ( function_exists( $function ) ) 2055 $operatorObject =& $function(); 2056 } 2057 else if ( isset( $operatorDefinition['script'] ) ) 2058 { 2059 $script = $operatorDefinition['script']; 2060 $class = $operatorDefinition['class']; 2061 // print( "loadAndRegisterOperator: $script<br/>" ); 2062 include_once( $script ); 2063 if ( class_exists( $class ) ) 2064 { 2065 if ( isset( $operatorDefinition['class_parameter'] ) ) 2066 $operatorObject = new $class( $operatorDefinition['class_parameter'] ); 2067 else 2068 $operatorObject = new $class(); 2069 } 2070 } 2071 if ( is_object( $operatorObject ) ) 2072 { 2073 $this->registerOperatorsInternal( $operatorObject, true ); 2074 return true; 2075 } 2076 return false; 2077 } 2078 2079 /*! 2080 Registers the operators supplied by the object $operatorObject. 2081 The function operatorList() must return an array of operator names. 2082 */ 2083 function registerOperators( &$operatorObject ) 2084 { 2085 $this->registerOperatorsInternal( $operatorObject ); 2086 } 2087 2088 /*! 2089 */ 2090 function registerOperatorsInternal( &$operatorObject, $debug = false ) 2091 { 2092 if ( !is_object( $operatorObject ) or 2093 !method_exists( $operatorObject, 'operatorList' ) ) 2094 return false; 2095 foreach( $operatorObject->operatorList() as $operatorName ) 2096 { 2097 $this->Operators[$operatorName] =& $operatorObject; 2098 } 2099 } 2100 2101 /*! 2102 Registers the operator $op_name to use the object $op_obj. 2103 */ 2104 function registerOperator( $op_name, &$op_obj ) 2105 { 2106 $this->Operators[$op_name] =& $op_obj; 2107 } 2108 2109 /*! 2110 Unregisters the operator $op_name. 2111 */ 2112 function unregisterOperator( $op_name ) 2113 { 2114 if ( is_array( $op_name ) ) 2115 { 2116 foreach ( $op_name as $op ) 2117 { 2118 $this->unregisterOperator( $op_name ); 2119 } 2120 } 2121 else if ( isset( $this->Operators ) ) 2122 unset( $this->Operators[$op_name] ); 2123 else 2124 $this->warning( "unregisterOpearator()", "Operator $op_name is not registered, cannot unregister" ); 2125 } 2126 2127 /*! 2128 Not implemented yet. 2129 */ 2130 function registerFilter() 2131 { 2132 } 2133 2134 /*! 2135 Registers a new resource object $res. 2136 The resource object take care of fetching templates using an URI. 2137 */ 2138 function registerResource( &$res ) 2139 { 2140 if ( is_object( $res ) ) 2141 $this->Resources[$res->resourceName()] =& $res; 2142 else 2143 $this->warning( "registerResource()", "Supplied argument is not a resource object" ); 2144 } 2145 2146 /*! 2147 Unregisters the resource $res_name. 2148 */ 2149 function unregisterResource( $res_name ) 2150 { 2151 if ( is_array( $res_name ) ) 2152 { 2153 foreach ( $res_name as $res ) 2154 { 2155 $this->unregisterResource( $res ); 2156 } 2157 } 2158 else if ( isset( $this->Resources[$res_name] ) ) 2159 unset( $this->Resources[$res_name] ); 2160 else 2161 $this->warning( "unregisterResource()", "Resource $res_name is not registered, cannot unregister" ); 2162 } 2163 2164 /*! 2165 Sets whether detail output is used or not. 2166 Detail output is useful for debug output where you want to examine the template 2167 and the output text. 2168 */ 2169 function setShowDetails( $show ) 2170 { 2171 $this->ShowDetails = $show; 2172 } 2173 2174 /*! 2175 Outputs a warning about the parameter $param missing for function/operator $name. 2176 */ 2177 function missingParameter( $name, $param ) 2178 { 2179 $this->warning( $name, "Missing parameter $param" ); 2180 } 2181 2182 /*! 2183 Outputs a warning about the parameter count being to high for function/operator $name. 2184 */ 2185 function extraParameters( $name, $count, $maxCount ) 2186 { 2187 $this->warning( $name, "Passed $count parameters but correct count is $maxCount" ); 2188 } 2189 2190 /*! 2191 Outputs a warning about the variable $var being undefined. 2192 */ 2193 function undefinedVariable( $name, $var ) 2194 { 2195 $this->warning( $name, "Undefined variable: $var" ); 2196 } 2197 2198 /*! 2199 Outputs an error about the template function $func_name being undefined. 2200 */ 2201 function undefinedFunction( $func_name ) 2202 { 2203 $this->error( "", "Undefined function: $func_name" ); 2204 } 2205 2206 /*! 2207 Creates a string for the placement information and returns it. 2208 \note The placement information can either be in indexed or associative 2209 */ 2210 function placementText( $placement = false ) 2211 { 2212 $placementText = false; 2213 if ( $placement !== false ) 2214 { 2215 if ( isset( $placement['start'] ) and 2216 isset( $placement['stop'] ) and 2217 isset( $placement['templatefile'] ) ) 2218 { 2219 $line = $placement['start']['line']; 2220 $column = $placement['start']['column']; 2221 $templateFile = $placement['templatefile']; 2222 } 2223 else 2224 { 2225 $line = $placement[0][0]; 2226 $column = $placement[0][1]; 2227 $templateFile = $placement[2]; 2228 } 2229 2230 $placementText = " @ $templateFile:$line" . "[$column]"; 2231 } 2232 return $placementText; 2233 } 2234 2235 /*! 2236 Displays a warning for the function/operator $name and text $txt. 2237 */ 2238 function warning( $name, $txt, $placement = false ) 2239 { 2240 $this->WarningLog[] = array( 'name' => $name, 2241 'text' => $txt, 2242 'placement' => $placement ); 2243 2244 if ( !is_string( $placement ) ) 2245 $placementText = $this->placementText( $placement ); 2246 else 2247 $placementText = $placement; 2248 $placementText = $this->placementText( $placement ); 2249 if ( $name != "" ) 2250 eZDebug::writeWarning( $txt, "eZTemplate:$name" . $placementText ); 2251 else 2252 eZDebug::writeWarning( $txt, "eZTemplate" . $placementText ); 2253 } 2254 2255 /*! 2256 Displays an error for the function/operator $name and text $txt. 2257 */ 2258 function error( $name, $txt, $placement = false ) 2259 { 2260 $this->ErrorLog[] = array( 'name' => $name, 2261 'text' => $txt, 2262 'placement' => $placement ); 2263 2264 if ( !is_string( $placement ) ) 2265 $placementText = $this->placementText( $placement ); 2266 else 2267 $placementText = $placement; 2268 if ( $name != "" ) 2269 $nameText = "eZTemplate:$name"; 2270 else 2271 $nameText = "eZTemplate"; 2272 eZDebug::writeError( $txt, $nameText . $placementText ); 2273 $hasAppendWarning =& $GLOBALS['eZTemplateHasAppendWarning']; 2274 $ini =& $this->ini(); 2275 if ( $ini->variable( 'ControlSettings', 'DisplayWarnings' ) == 'enabled' ) 2276 { 2277 if ( !isset( $hasAppendWarning ) or 2278 !$hasAppendWarning ) 2279 { 2280 if ( function_exists( 'eZAppendWarningItem' ) ) 2281 { 2282 eZAppendWarningItem( array( 'error' => array( 'type' => 'template', 2283 'number' => EZ_ERROR_TEMPLATE_FILE_ERRORS ), 2284 'text' => ezi18n( 'lib/eztemplate', 'Some template errors occured, see debug for more information.' ) ) ); 2285 $hasAppendWarning = true; 2286 } 2287 } 2288 } 2289 } 2290 2291 2292 function operatorInputSupported( $operatorName ) 2293 { 2294 } 2295 2296 /*! 2297 Sets the original text for uri $uri to $text. 2298 */ 2299 function setIncludeText( $uri, &$text ) 2300 { 2301 $this->IncludeText[$uri] =& $text; 2302 } 2303 2304 /*! 2305 Sets the output for uri $uri to $output. 2306 */ 2307 function setIncludeOutput( $uri, &$output ) 2308 { 2309 $this->IncludeOutput[$uri] =& $output; 2310 } 2311 2312 /*! 2313 \return the path list which is used for autoloading functions and operators. 2314 */ 2315 function autoloadPathList() 2316 { 2317 return $this->AutoloadPathList; 2318 } 2319 2320 /*! 2321 Sets the path list for autoloading. 2322 */ 2323 function setAutoloadPathList( $pathList ) 2324 { 2325 $this->AutoloadPathList = $pathList; 2326 } 2327 2328 /*! 2329 Looks trough the pathes specified in autoloadPathList() and fetches autoload 2330 definition files used for autoloading functions and operators. 2331 */ 2332 function autoload() 2333 { 2334 $pathList = $this->autoloadPathList(); 2335 foreach ( $pathList as $path ) 2336 { 2337 $autoloadFile = $path . '/eztemplateautoload.php'; 2338 if ( file_exists( $autoloadFile ) ) 2339 { 2340 unset( $eZTemplateOperatorArray ); 2341 unset( $eZTemplateFunctionArray ); 2342 include( $autoloadFile ); 2343 if ( isset( $eZTemplateOperatorArray ) and 2344 is_array( $eZTemplateOperatorArray ) ) 2345 { 2346 foreach ( $eZTemplateOperatorArray as $operatorDefinition ) 2347 { 2348 $this->registerAutoloadOperators( $operatorDefinition ); 2349 } 2350 } 2351 if ( isset( $eZTemplateFunctionArray ) and 2352 is_array( $eZTemplateFunctionArray ) ) 2353 { 2354 foreach ( $eZTemplateFunctionArray as $functionDefinition ) 2355 { 2356 $this->registerAutoloadFunctions( $functionDefinition ); 2357 } 2358 } 2359 } 2360 } 2361 } 2362 2363 /*! 2364 Resets all template variables. 2365 */ 2366 function resetVariables() 2367 { 2368 $this->Variables = array(); 2369 } 2370 2371 /*! 2372 Resets all template functions and operators by calling the resetFunction and resetOperator 2373 on all elements that supports it. 2374 */ 2375 function resetElements() 2376 { 2377 foreach ( array_keys( $this->Functions ) as $functionName ) 2378 { 2379 $functionObject =& $this->Functions[$functionName]; 2380 if ( is_object( $functionObject ) and 2381 method_exists( $functionObject, 'resetFunction' ) ) 2382 { 2383 $functionObject->resetFunction( $functionName ); 2384 } 2385 } 2386 2387 foreach ( array_keys( $this->Operators ) as $operatorName ) 2388 { 2389 $operatorObject =& $this->Operators[$operatorName]; 2390 if ( is_object( $operatorObject ) and 2391 method_exists( $operatorObject, 'resetOperator' ) ) 2392 { 2393 $operatorObject->resetOperator( $operatorName ); 2394 } 2395 } 2396 } 2397 2398 /*! 2399 Resets all template variables, functions, operators and error counts. 2400 */ 2401 function reset() 2402 { 2403 $this->resetVariables(); 2404 $this->resetElements(); 2405 $this->IsCachingAllowed = true; 2406 2407 $this->resetErrorLog(); 2408 2409 $this->TemplatesUsageStatistics = array(); 2410 $this->TemplateFetchList = array(); 2411 } 2412 2413 /*! 2414 \return The number of errors that occured with the last fetch 2415 \sa hasErrors() 2416 */ 2417 function errorCount() 2418 { 2419 return count( $this->ErrorLog ); 2420 } 2421 2422 /*! 2423 \return \ true if errors occured with the last fetch. 2424 \sa errorCount() 2425 */ 2426 function hasErrors() 2427 { 2428 return $this->errorCount() > 0; 2429 } 2430 2431 /*! 2432 \return error log. 2433 \sa errorCount() 2434 */ 2435 function errorLog() 2436 { 2437 return $this->ErrorLog; 2438 } 2439 2440 /*! 2441 \return The number of warnings that occured with the last fetch 2442 \sa hasWarnings() 2443 */ 2444 function warningCount() 2445 { 2446 return count( $this->WarningLog ); 2447 } 2448 2449 /*! 2450 \return \ true if warnings occured with the last fetch. 2451 \sa warningCount() 2452 */ 2453 function hasWarnings() 2454 { 2455 return $this->warningCount() > 0; 2456 } 2457 2458 /*! 2459 \return waring log. 2460 \sa warningCount() 2461 */ 2462 function warningLog() 2463 { 2464 return $this->WarningLog; 2465 } 2466 2467 /*! 2468 Returns the globale template instance, creating it if it does not exist. 2469 */ 2470 function &instance() 2471 { 2472 $tpl =& $GLOBALS["eZTemplateInstance"]; 2473 if ( get_class( $tpl ) != "eztemplate" ) 2474 { 2475 $tpl = new eZTemplate(); 2476 } 2477 2478 return $tpl; 2479 } 2480 2481 /*! 2482 Returns the INI object for the template.ini file. 2483 */ 2484 function &ini() 2485 { 2486 include_once ( "lib/ezutils/classes/ezini.php" ); 2487 $ini =& eZINI::instance( "template.ini" ); 2488 return $ini; 2489 } 2490 2491 /*! 2492 \static 2493 \return true if special XHTML code should be included before the included template file. 2494 This code will display the template filename in the browser but will eventually 2495 break the design. 2496 */ 2497 function isXHTMLCodeIncluded() 2498 { 2499 if ( !isset( $GLOBALS['eZTemplateDebugXHTMLCodeEnabled'] ) ) 2500 { 2501 $ini =& eZINI::instance(); 2502 $GLOBALS['eZTemplateDebugXHTMLCodeEnabled'] = $ini->variable( 'TemplateSettings', 'ShowXHTMLCode' ) == 'enabled'; 2503 } 2504 return $GLOBALS['eZTemplateDebugXHTMLCodeEnabled']; 2505 } 2506 2507 /*! 2508 \static 2509 \return \c true if debug output of template functions and operators should be enabled. 2510 */ 2511 function isMethodDebugEnabled() 2512 { 2513 if ( !isset( $GLOBALS['eZTemplateDebugMethodEnabled'] ) ) 2514 { 2515 $ini =& eZINI::instance(); 2516 $GLOBALS['eZTemplateDebugMethodEnabled'] = $ini->variable( 'TemplateSettings', 'ShowMethodDebug' ) == 'enabled'; 2517 } 2518 return $GLOBALS['eZTemplateDebugMethodEnabled']; 2519 } 2520 2521 /*! 2522 \static 2523 \return true if debugging of internals is enabled, this will display 2524 which files are loaded and when cache files are created. 2525 Set the option with setIsDebugEnabled(). 2526 */ 2527 function isDebugEnabled() 2528 { 2529 if ( !isset( $GLOBALS['eZTemplateDebugInternalsEnabled'] ) ) 2530 $GLOBALS['eZTemplateDebugInternalsEnabled'] = EZ_TEMPLATE_DEBUG_INTERNALS; 2531 return $GLOBALS['eZTemplateDebugInternalsEnabled']; 2532 } 2533 2534 /*! 2535 \static 2536 Sets whether internal debugging is enabled or not. 2537 */ 2538 function setIsDebugEnabled( $debug ) 2539 { 2540 $GLOBALS['eZTemplateDebugInternalsEnabled'] = $debug; 2541 } 2542 2543 /*! 2544 \return \c true if caching is allowed (default) or \c false otherwise. 2545 This also affects template compiling. 2546 \sa setIsCachingAllowed 2547 */ 2548 function isCachingAllowed() 2549 { 2550 return $this->IsCachingAllowed; 2551 } 2552 2553 /*! 2554 Sets whether caching/compiling is allowed or not. This is useful 2555 if you need to make sure templates are parsed and processed 2556 without any caching mechanisms. 2557 \note The default is to allow caching. 2558 \sa isCachingAllowed 2559 */ 2560 function setIsCachingAllowed( $allowed ) 2561 { 2562 $this->IsCachingAllowed = $allowed; 2563 } 2564 2565 /*! 2566 \static 2567 \return \c true if templates usage statistics should be enabled. 2568 */ 2569 function isTemplatesUsageStatisticsEnabled() 2570 { 2571 if ( !isset( $GLOBALS['eZTemplateDebugTemplatesUsageStatisticsEnabled'] ) ) 2572 { 2573 $ini =& eZINI::instance(); 2574 $GLOBALS['eZTemplateDebugTemplatesUsageStatisticsEnabled'] = $ini->variable( 'TemplateSettings', 'ShowUsedTemplates' ) == 'enabled'; 2575 } 2576 return ( $GLOBALS['eZTemplateDebugTemplatesUsageStatisticsEnabled'] ); 2577 } 2578 2579 /*! 2580 \static 2581 Sets whether templates usage statistics enabled or not. 2582 \return \c true if templates usage statistics was enabled, otherwise \c false. 2583 */ 2584 function setIsTemplatesUsageStatisticsEnabled( $enabled ) 2585 { 2586 $wasEnabled = false; 2587 if( isset( $GLOBALS['eZTemplateDebugTemplatesUsageStatisticsEnabled'] ) ) 2588 $wasEnabled = $GLOBALS['eZTemplateDebugTemplatesUsageStatisticsEnabled']; 2589 2590 $GLOBALS['eZTemplateDebugTemplatesUsageStatisticsEnabled'] = $enabled; 2591 return $wasEnabled; 2592 } 2593 2594 /*! 2595 \static 2596 Checks settings and if 'ShowUsedTemplates' is enabled appends template info to stats. 2597 */ 2598 function appendTemplateToStatisticsIfNeeded( &$templateName, &$templateFileName ) 2599 { 2600 if ( eZTemplate::isTemplatesUsageStatisticsEnabled() ) 2601 eZTemplate::appendTemplateToStatistics( $templateName, $templateFileName ); 2602 } 2603 2604 /*! 2605 \static 2606 Appends template info to stats. 2607 */ 2608 function appendTemplateToStatistics( &$templateName, &$templateFileName ) 2609 { 2610 $actualTemplateName = preg_replace( "#^[\w/]+templates/#", '', $templateFileName ); 2611 $requestedTemplateName = preg_replace( "#^[\w/]+templates/#", '', $templateName ); 2612 2613 $tpl =& eZTemplate::instance(); 2614 $needToAppend = true; 2615 2616 // don't add template info if it is a duplicate of previous. 2617 $statsSize = count( $tpl->TemplatesUsageStatistics ); 2618 if ( $statsSize > 0 ) 2619 { 2620 $lastTemplateInfo =& $tpl->TemplatesUsageStatistics[$statsSize-1]; 2621 if ( $lastTemplateInfo['actual-template-name'] === $actualTemplateName && 2622 $lastTemplateInfo['requested-template-name'] === $requestedTemplateName && 2623 $lastTemplateInfo['template-filename'] === $templateFileName ) 2624 { 2625 $needToAppend = false; 2626 } 2627 } 2628 2629 if ( $needToAppend ) 2630 { 2631 $templateInfo = array( 'actual-template-name' => $actualTemplateName, 2632 'requested-template-name' => $requestedTemplateName, 2633 'template-filename' => $templateFileName ); 2634 2635 $tpl->TemplatesUsageStatistics[] = $templateInfo; 2636 } 2637 } 2638 2639 /*! 2640 Appends template info for current fetch. 2641 */ 2642 function appendTemplateFetch( $actualTemplateName ) 2643 { 2644 $this->TemplateFetchList[] = $actualTemplateName; 2645 $this->TemplateFetchList = array_unique( $this->TemplateFetchList ); 2646 } 2647 2648 /*! 2649 Reset error and warning logs 2650 */ 2651 function resetErrorLog() 2652 { 2653 $this->ErrorLog = array(); 2654 $this->WarningLog = array(); 2655 } 2656 2657 /*! 2658 \static 2659 Returns template usage statistics 2660 */ 2661 function &templatesUsageStatistics() 2662 { 2663 $tpl =& eZTemplate::instance(); 2664 return $tpl->TemplatesUsageStatistics; 2665 } 2666 2667 /*! 2668 Returns template list for the last fetch. 2669 */ 2670 function templateFetchList() 2671 { 2672 return $this->TemplateFetchList; 2673 } 2674 2675 /*! 2676 Set template compilation test mode. 2677 2678 \param true, will set template compilation in test mode ( no disc writes ). 2679 false, will compile templates to disc 2680 */ 2681 function setCompileTest( $val ) 2682 { 2683 $this->TestCompile = $val; 2684 } 2685 2686 /*! 2687 Get if template session is test compile 2688 */ 2689 function testCompile() 2690 { 2691 return $this->TestCompile; 2692 } 2693 2694 /// \privatesection 2695 /// Associative array of resource objects 2696 var $Resources; 2697 /// Reference to the default resource object 2698 var $DefaultResource; 2699 /// The original template text 2700 var $Text; 2701 /// Included texts, usually performed by custom functions 2702 var $IncludeText; 2703 /// Included outputs, usually performed by custom functions 2704 var $IncludeOutput; 2705 /// The timestamp of the template when it was last modified 2706 var $TimeStamp; 2707 /// The left delimiter used for parsing 2708 var $LDelim; 2709 /// The right delimiter used for parsing 2710 var $RDelim; 2711 2712 /// The resulting object tree of the template 2713 var $Tree; 2714 /// An associative array of template variables 2715 var $Variables; 2716 /*! 2717 Last element of this stack contains names of 2718 all variables created in the innermost template, for them 2719 to be destroyed after the template execution finishes. 2720 */ 2721 var $LocalVariablesNamesStack; 2722 // Reference to the last element of $LocalVariablesNamesStack. 2723 var $CurrentLocalVariablesNames; 2724 /// An associative array of operators 2725 var $Operators; 2726 /// An associative array of functions 2727 var $Functions; 2728 /// An associative array of function attributes 2729 var $FunctionAttributes; 2730 /// An associative array of literal tags 2731 var $Literals; 2732 /// True if output details is to be shown 2733 var $ShowDetails = false; 2734 /// \c true if caching is allowed 2735 var $IsCachingAllowed; 2736 2737 /// Array containing all errors occured during a fetch 2738 var $ErrorLog; 2739 /// Array containing all warnings occured during a fetch 2740 var $WarningLog; 2741 2742 var $AutoloadPathList; 2743 /// include level 2744 var $Level = 0; 2745 var $MaxLevel = 40; 2746 2747 /// A list of templates used by a rendered page 2748 var $TemplatesUsageStatistics; 2749 2750 // counter to make unique names for {foreach} loop variables in com 2751 var $ForeachCounter; 2752 var $ForCounter; 2753 var $WhileCounter; 2754 var $DoCounter; 2755 var $ElseifCounter; 2756 2757 // Flag for setting compilation in test mode 2758 var $TestCompile; 2759 2760 // var $CurrentRelatedResource; 2761 // var $CurrentRelatedTemplateName; 2762 } 2763 2764 ?>
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 |