[ Index ]
 

Code source de eZ Publish 3.9.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/eztemplate/classes/ -> eztemplate.php (source)

   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  ?>


Généré le : Sat Feb 24 10:30:04 2007 par Balluche grâce à PHPXref 0.7