[ Index ]
 

Code source de Joomla 1.0.13

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/includes/patTemplate/ -> patTemplate.php (source)

   1  <?PHP
   2  /**
   3   * patTemplate
   4   *
   5   * $Id: patTemplate.php 1546 2005-12-23 07:01:01Z eddieajau $
   6   *
   7   * powerful templating engine
   8   *
   9   * @version        3.1.0
  10   * @package        patTemplate
  11   * @author        Stephan Schmidt <schst@php.net>
  12   * @license        LGPL
  13   * @link        http://www.php-tools.net
  14   */
  15  
  16  // ** Following line Joomla! specific **
  17  require_once( dirname( __FILE__ ) . '/patErrorManager.php' );
  18  
  19  /**
  20   * template already exists
  21   */
  22  define( 'PATTEMPLATE_ERROR_TEMPLATE_EXISTS', 5010 );
  23  
  24  /**
  25   * template does not exist
  26   */
  27  define ( 'PATTEMPLATE_WARNING_NO_TEMPLATE', 5011 );
  28  
  29  /**
  30   * unknown type
  31   */
  32  define ( 'PATTEMPLATE_WARNING_UNKNOWN_TYPE', 5012 );
  33  
  34  /**
  35   * base class for module could not be found
  36   */
  37  define( 'PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND', 5050 );
  38  
  39  /**
  40   * module could not be found
  41   */
  42  define( 'PATTEMPLATE_ERROR_MODULE_NOT_FOUND', 5051 );
  43  
  44  /**
  45   * array expected
  46   */
  47  define( 'PATTEMPLATE_ERROR_EXPECTED_ARRAY', 5052 );
  48  
  49  /**
  50   * No input
  51   */
  52  define( 'PATTEMPLATE_ERROR_NO_INPUT', 6000 );
  53  /**
  54   * Recursion
  55   */
  56  define( 'PATTEMPLATE_ERROR_RECURSION', 6010 );
  57  
  58  /**
  59   * patTemplate
  60   *
  61   * powerful templating engine
  62   *
  63   * @version        3.1.0
  64   * @package        patTemplate
  65   * @author        Stephan Schmidt <schst@php.net>
  66   * @license        LGPL
  67   * @link        http://www.php-tools.net
  68   */
  69  class patTemplate
  70  {
  71     /**
  72      * standard system vars that identify pat tools
  73      * @var    array
  74      */
  75      var    $_systemVars            =    array(
  76                                          'appName'        =>    'patTemplate',
  77                                          'appVersion'    =>    '3.1.0',
  78                                          'author'        =>    array(
  79                                                                      'Stephan Schmidt <schst@php.net>'
  80                                                                   )
  81                                      );
  82  
  83     /**
  84      * default attributes for new templates
  85      * @access    private
  86      * @var        array
  87      */
  88      var    $_defaultAttributes    =    array(
  89                                          'type'            =>    'standard',
  90                                          'visibility'    =>    'visible',
  91                                          'loop'            =>    1,
  92                                          'unusedvars'    =>    'strip',
  93                                          'whitespace'    =>    'keep',
  94                                          'autoclear'        =>    'off',
  95                                          'autoload'        =>    'on'
  96                                      );
  97  
  98     /**
  99      * options for patTemplate
 100      *
 101      * Currently the following options are implemented:
 102      * - maintainBc defines, whether patTemplate should be backwards compatible.
 103      *   This means, that you may use 'default' and 'empty' for subtemplates.
 104      *
 105      * @access    private
 106      * @var        array
 107      */
 108      var    $_options    =    array(
 109                                  'startTag'            => '{',
 110                                  'endTag'            => '}',
 111                                  'root'                => array('__default' => '.'),
 112                                  'namespace'            => 'patTemplate',
 113                                  'maintainBc'        => true,
 114                                  'defaultFunction'    => false
 115                               );
 116  
 117     /**
 118      * start tag
 119      *
 120      * @access    private
 121      * @var        string
 122      */
 123      var $_startTag = '{';
 124  
 125     /**
 126      * end tag
 127      *
 128      * @access    private
 129      * @var        string
 130      */
 131      var $_endTag = '}';
 132  
 133     /**
 134      * loaded modules
 135      *
 136      * Modules are:
 137      * - Readers
 138      * - Caches
 139      * - Variable modifiers
 140      * - Filters
 141      *
 142      * @access    private
 143      * @var        array
 144      */
 145      var    $_modules        =    array();
 146  
 147     /**
 148      * directories, where modules can be stored
 149      * @access    private
 150      * @var        array
 151      */
 152      var    $_moduleDirs    =    array();
 153  
 154     /**
 155      * stores all template names
 156      * @access    private
 157      * @var        array
 158      */
 159      var    $_templateList    =    array();
 160  
 161     /**
 162      * stores all template data
 163      * @access    private
 164      * @var        array
 165      */
 166      var    $_templates        =    array();
 167  
 168     /**
 169      * stores all global variables
 170      * @access    private
 171      * @var        array
 172      */
 173      var    $_globals    =    array();
 174  
 175     /**
 176      * stores all local variables
 177      * @access    private
 178      * @var        array
 179      */
 180      var    $_vars    =    array();
 181  
 182     /**
 183      * stores the name of the first template that has been
 184      * found
 185      *
 186      * @access    private
 187      * @var        string
 188      */
 189      var    $_root;
 190  
 191     /**
 192      * output filters that should be used
 193      *
 194      * @access    private
 195      * @var        array
 196      */
 197      var    $_outputFilters = array();
 198  
 199     /**
 200      * input filters that should be used
 201      *
 202      * @access    private
 203      * @var        array
 204      */
 205      var    $_inputFilters = array();
 206  
 207     /**
 208      * template cache, that should be used
 209      *
 210      * @access    private
 211      * @var        array
 212      */
 213      var    $_tmplCache = null;
 214  
 215     /**
 216      * placeholders, that have been discovered
 217      *
 218      * @access    private
 219      * @var        array
 220      */
 221      var    $_discoveredPlaceholders = array();
 222  
 223     /**
 224      * Create a new patTemplate instance.
 225      *
 226      * The constructor accepts the type of the templates as sole parameter.
 227      * You may choose one of:
 228      * - html (default)
 229      * - tex
 230      *
 231      * The type influences the tags you are using in your templates.
 232      *
 233      * @access    public
 234      * @param    string    type (either html or tex)
 235      */
 236  	function patTemplate( $type = 'html' )
 237      {
 238          if( !defined( 'PATTEMPLATE_INCLUDE_PATH' ) ) {
 239              define( 'PATTEMPLATE_INCLUDE_PATH', dirname( __FILE__ ) . '/patTemplate' );
 240          }
 241  
 242          $this->setType( $type );
 243      }
 244  
 245     /**
 246      * sets an option
 247      *
 248      * Currently, the following options are supported
 249      * - maintainBc (true|false)
 250      * - namespace (string)
 251      *
 252      * @access    public
 253      * @param    string    option to set
 254      * @param    string    value of the option
 255      */
 256  	function setOption($option, $value)
 257      {
 258          $this->_options[$option] = $value;
 259      }
 260  
 261     /**
 262      * gets an option
 263      *
 264      * @access    public
 265      * @param    string    option to get
 266      * @return    mixed    value of the option
 267      */
 268  	function getOption( $option )
 269      {
 270          if (!isset($this->_options[$option])) {
 271              return null;
 272          }
 273          return $this->_options[$option];
 274      }
 275  
 276     /**
 277      * sets name of directory where templates are stored
 278      *
 279      * @access    public
 280      * @param    string    dir where templates are stored
 281      * @deprecated        please use patTemplate::setRoot() instead
 282      */
 283  	function setBasedir($basedir)
 284      {
 285          $this->setRoot($basedir);
 286      }
 287  
 288     /**
 289      * sets root base for the template
 290      *
 291      * The parameter depends on the reader you are using.
 292      *
 293      * @access    public
 294      * @param    string    root base of the templates
 295      */
 296  	function setRoot($root, $reader = '__default')
 297      {
 298          $this->_options['root'][$reader] = $root;
 299      }
 300  
 301     /**
 302      * gets name of root base for the templates
 303      *
 304      * @access    public
 305      * @return    mixed         root base
 306      */
 307  	function getRoot($reader = '__default')
 308      {
 309          return    $this->_options['root'][$reader];
 310      }
 311  
 312     /**
 313      * sets namespace of patTemplate tags
 314      *
 315      * If you want to use more than one namespace, you may set this to
 316      * an array. All tags in these namespaces will be treated as patTemplate
 317      * tags.
 318      *
 319      * @access    public
 320      * @param    string|array    namespace(s)
 321      */
 322  	function setNamespace($ns)
 323      {
 324          $this->_options['namespace'] = $ns;
 325      }
 326  
 327     /**
 328      * gets namespace of patTemplate tags
 329      *
 330      * @access    public
 331      * @return    string|array    namespace(s)
 332      */
 333  	function getNamespace()
 334      {
 335          return $this->_options['namespace'];
 336      }
 337  
 338     /**
 339      * set default attribute
 340      *
 341      * @access    public
 342      * @param    string    attribute name
 343      * @param    mixed    attribute value
 344      */
 345  	function setDefaultAttribute( $name, $value )
 346      {
 347          $this->_defaultAttributes[$name]    =    $value;
 348      }
 349  
 350     /**
 351      * set default attributes
 352      *
 353      * @access    public
 354      * @param    array    attributes
 355      */
 356  	function setDefaultAttributes( $attributes )
 357      {
 358          $this->_defaultAttributes    =    array_merge( $this->_defaultAttributes, $attributes );
 359      }
 360  
 361     /**
 362      * get default attributes
 363      *
 364      * @access    public
 365      * @return    return default attributes
 366      */
 367  	function getDefaultAttributes()
 368      {
 369          return    $this->_defaultAttributes;
 370      }
 371  
 372     /**
 373      * set the type for the templates
 374      *
 375      * @access    public
 376      * @param    string    type (html or tex)
 377      * @return    boolean    true on success
 378      */
 379  	function setType( $type )
 380      {
 381          switch( strtolower( $type ) )
 382          {
 383              case "tex":
 384                  $this->setTags( '<{', '}>' );
 385                  break;
 386              case "html":
 387                  $this->setTags( '{', '}' );
 388                  break;
 389              default:
 390                  return    patErrorManager::raiseWarning(
 391                                                          PATTEMPLATE_WARNING_UNKNOWN_TYPE,
 392                                                          "Unknown type '$type'. Please use 'html' or 'tex'."
 393                                                      );
 394          }
 395          return true;
 396      }
 397  
 398     /**
 399      * set the start and end tag for variables
 400      *
 401      * @access    public
 402      * @param    string    start tag
 403      * @param    string    end tag
 404      * @return    boolean    true on success
 405      */
 406  	function setTags( $startTag, $endTag )
 407      {
 408          $this->_options['startTag']    =    $startTag;
 409          $this->_options['endTag']    =    $endTag;
 410  
 411          $this->_startTag    =    $startTag;
 412          $this->_endTag        =    $endTag;
 413          return true;
 414      }
 415  
 416     /**
 417      * get start tag for variables
 418      *
 419      * @access    public
 420      * @return    string    start tag
 421      */
 422  	function getStartTag()
 423      {
 424          return $this->_options['startTag'];
 425      }
 426  
 427     /**
 428      * get end tag for variables
 429      *
 430      * @access    public
 431      * @return    string    end tag
 432      */
 433  	function getEndTag()
 434      {
 435          return $this->_options['endTag'];
 436      }
 437  
 438     /**
 439      * add a directory where patTemplate should search for
 440      * modules.
 441      *
 442      * You may either pass a string or an array of directories.
 443      *
 444      * patTemplate will be searching for a module in the same
 445      * order you added them. If the module cannot be found in
 446      * the custom folders, it will look in
 447      * patTemplate/$moduleType.
 448      *
 449      * @access    public
 450      * @param    string            module type
 451      * @param    string|array    directory or directories to search.
 452      */
 453  	function addModuleDir( $moduleType, $dir )
 454      {
 455          if( !isset( $this->_moduleDirs[$moduleType] ) )
 456              $this->_moduleDirs[$moduleType]    =    array();
 457          if( is_array( $dir ) )
 458              $this->_moduleDirs[$moduleType] = array_merge( $this->_moduleDirs[$moduleType], $dir );
 459          else
 460              array_push( $this->_moduleDirs[$moduleType], $dir );
 461      }
 462  
 463     /**
 464      * Sets an attribute of a template
 465      *
 466      * supported attributes: visibilty, loop, parse, unusedvars
 467      *
 468      * @param    string    $template    name of the template
 469      * @param    string    $attribute    name of the attribute
 470      * @param    mixed    $value    value of the attribute
 471      * @access    public
 472      * @see        setAttributes(),getAttribute(), clearAttribute()
 473      */
 474  	function setAttribute( $template, $attribute, $value )
 475      {
 476          $template    =    strtolower( $template );
 477          if( !isset( $this->_templates[$template] ) )
 478          {
 479              return    patErrorManager::raiseWarning(
 480                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
 481                                                      "Template '$template' does not exist."
 482                                                  );
 483          }
 484  
 485          $attribute    =    strtolower( $attribute );
 486          $this->_templates[$template]['attributes'][$attribute]    =    $value;
 487          return true;
 488      }
 489  
 490     /**
 491      * Sets several attribute of a template
 492      *
 493      * $attributes has to be a assotiative arrays containing attribute/value pairs
 494      * supported attributes: visibilty, loop, parse, unusedvars
 495      *
 496      * @param    string    $template    name of the template
 497      * @param    array    $attributes    attribute/value pairs
 498      * @access    public
 499      * @see        setAttribute(), getAttribute(), clearAttribute()
 500      */
 501  	function setAttributes( $template, $attributes )
 502      {
 503          if( !is_array( $attributes ) )
 504          {
 505              return patErrorManager::raiseError( PATTEMPLATE_ERROR_EXPECTED_ARRAY, 'patTemplate::setAttributes: Expected array as second parameter, '.gettype( $attributes ).' given' );
 506          }
 507  
 508          $template    =    strtolower( $template );
 509          $attributes    =    array_change_key_case( $attributes );
 510          if( !isset( $this->_templates[$template] ) )
 511          {
 512              return    patErrorManager::raiseWarning(
 513                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
 514                                                      "Template '$template' does not exist."
 515                                                  );
 516          }
 517  
 518          $this->_templates[$template]['attributes']    =    array_merge( $this->_templates[$template]['attributes'], $attributes );
 519          return true;
 520      }
 521  
 522     /**
 523      * Get all attributes of a template
 524      *
 525      * @param    string    name of the template
 526      * @return    array    attributes
 527      * @access    public
 528      */
 529  	function getAttributes( $template )
 530      {
 531          $template    =    strtolower( $template );
 532          if( !isset( $this->_templates[$template] ) )
 533          {
 534              return    patErrorManager::raiseWarning(
 535                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
 536                                                      "Template '$template' does not exist."
 537                                                  );
 538          }
 539          return    $this->_templates[$template]['attributes'];
 540      }
 541  
 542     /**
 543      * Gets an attribute of a template
 544      *
 545      * supported attributes: visibilty, loop, parse, unusedvars
 546      *
 547      * @param    string    $template    name of the template
 548      * @param    string    $attribute    name of the attribute
 549      * @return    mixed    value of the attribute
 550      * @access    public
 551      * @see        setAttribute(), setAttributes(), clearAttribute()
 552      */
 553  	function getAttribute( $template, $attribute )
 554      {
 555          $template    =    strtolower( $template );
 556          $attribute    =    strtolower( $attribute );
 557          if( !isset( $this->_templates[$template] ) )
 558          {
 559              return    patErrorManager::raiseWarning(
 560                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
 561                                                      "Template '$template' does not exist."
 562                                                  );
 563          }
 564          return    $this->_templates[$template]['attributes'][$attribute];
 565      }
 566  
 567     /**
 568      * Clears an attribute of a template
 569      *
 570      * supported attributes: visibilty, loop, parse, unusedvars
 571      *
 572      * @param    string    $template    name of the template
 573      * @param    string    $attribute    name of the attribute
 574      * @access    public
 575      * @see        setAttribute(), setAttributes(), getAttribute()
 576      */
 577  	function clearAttribute( $template, $attribute )
 578      {
 579          $template    =    strtolower( $template );
 580          $attribute    =    strtolower( $attribute );
 581  
 582          if( !isset( $this->_templates[$template] ) )
 583          {
 584              return    patErrorManager::raiseWarning(
 585                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
 586                                                      "Template '$template' does not exist."
 587                                                  );
 588          }
 589          $this->_templates[$template]['attributes'][$attribute]    =    '';;
 590          return true;
 591      }
 592  
 593     /**
 594      * Prepare a template
 595      *
 596      * This can be used if you want to add variables to
 597      * a template, that has not been loaded yet.
 598      *
 599      * @access    public
 600      * @param    string    template name
 601      */
 602  	function prepareTemplate( $name )
 603      {
 604          $name    =    strtolower( $name );
 605          if( !isset( $this->_vars[$name] ) )
 606          {
 607              $this->_vars[$name]    =    array(
 608                                                  'scalar'    =>    array(),
 609                                                  'rows'        =>    array()
 610                                              );
 611          }
 612      }
 613  
 614     /**
 615      * add a variable to a template
 616      *
 617      * A variable may also be an indexed array, but _not_
 618      * an associative array!
 619      *
 620      * @access    public
 621      * @param    string    $template    name of the template
 622      * @param    string    $varname    name of the variable
 623      * @param    mixed    $value        value of the variable
 624      */
 625  	function addVar( $template, $varname, $value )
 626      {
 627          $template = strtolower( $template );
 628          $varname  = strtoupper( $varname );
 629  
 630          if( !is_array( $value ) ) {
 631              $this->_vars[$template]['scalar'][$varname] = $value;
 632              return true;
 633          }
 634  
 635          $cnt = count( $value );
 636          for ($i = 0; $i < $cnt; $i++) {
 637              if (!isset( $this->_vars[$template]['rows'][$i] )) {
 638                  $this->_vars[$template]['rows'][$i] = array();
 639              }
 640              $this->_vars[$template]['rows'][$i][$varname] = $value[$i];
 641          }
 642  
 643          return true;
 644      }
 645  
 646     /**
 647      * get the value of a variable
 648      *
 649      * @access    public
 650      * @param    string    name of the template
 651      * @param    string    name of the variable
 652      * @return    string    value of the variable, null if the variable is not set
 653      */
 654  	function getVar( $template, $varname )
 655      {
 656          $template    =    strtolower( $template );
 657          $varname    =    strtoupper( $varname );
 658  
 659          if( isset( $this->_vars[$template]['scalar'][$varname] ) )
 660              return $this->_vars[$template]['scalar'][$varname];
 661  
 662          $value = array();
 663  
 664          $cnt = count( $this->_vars[$template]['rows'] );
 665          for( $i = 0; $i < $cnt; $i++ )
 666          {
 667              if( !isset( $this->_vars[$template]['rows'][$i][$varname] ) )
 668                  continue;
 669              array_push( $value, $this->_vars[$template]['rows'][$i][$varname] );
 670          }
 671          if( !empty( $value ) )
 672              return $value;
 673          return null;
 674      }
 675  
 676     /**
 677      * clear the value of a variable
 678      *
 679      * @access    public
 680      * @param    string    name of the template
 681      * @param    string    name of the variable
 682      * @return   boolean
 683      * @see      clearVars(), clearTemplate()
 684      */
 685  	function clearVar( $template, $varname )
 686      {
 687          $template    =    strtolower( $template );
 688          $varname    =    strtoupper( $varname );
 689  
 690          if (isset( $this->_vars[$template]['scalar'][$varname] )) {
 691              unset ($this->_vars[$template]['scalar'][$varname]);
 692              return true;
 693          }
 694  
 695          $result = false;
 696          $cnt = count( $this->_vars[$template]['rows'] );
 697          for ($i = 0; $i < $cnt; $i++) {
 698              if (!isset($this->_vars[$template]['rows'][$i][$varname])) {
 699                  continue;
 700              }
 701              unset($this->_vars[$template]['rows'][$i][$varname]);
 702              $result = true;
 703          }
 704          return $result;
 705      }
 706  
 707  
 708     /**
 709      * Adds several variables to a template
 710      *
 711      * Each Template can have an unlimited amount of its own variables
 712      * $variables has to be an assotiative array containing variable/value pairs
 713      *
 714      * @param    string    $template    name of the template
 715      * @param    array    $variables    assotiative array of the variables
 716      * @param    string    $prefix    prefix for all variable names
 717      * @access    public
 718      * @see        addVar(), addRows(), addGlobalVar(), addGlobalVars()
 719      */
 720  	function addVars( $template, $variables, $prefix = '' )
 721      {
 722          $template    =    strtolower( $template );
 723          $prefix        =    strtoupper( $prefix );
 724          $variables    =    array_change_key_case( $variables, CASE_UPPER );
 725  
 726          foreach ($variables as $varname => $value) {
 727              $varname = $prefix.$varname;
 728  
 729              if (!is_array($value)) {
 730                  if (!is_scalar($value)) {
 731                      continue;
 732                  }
 733                  $this->_vars[$template]['scalar'][$varname] = $value;
 734                  continue;
 735              }
 736  
 737              $cnt = count( $value );
 738              for( $i = 0; $i < $cnt; $i++ ) {
 739                  if( !isset( $this->_vars[$template]['rows'][$i] ) )
 740                      $this->_vars[$template]['rows'][$i]    =    array();
 741  
 742                  $this->_vars[$template]['rows'][$i][$varname]    =    $value[$i];
 743              }
 744          }
 745      }
 746  
 747     /**
 748      * Clear all variables in a template
 749      *
 750      * This clears only variables, but does
 751      *
 752      * @access    public
 753      * @param    string    $template    name of the template
 754      * @return   boolean
 755      * @see        clearVar(), clearTemplate()
 756      */
 757  	function clearVars( $template )
 758      {
 759          $template = strtolower($template);
 760          $this->_vars[$template] = array(
 761                                           'scalar' => array(),
 762                                           'rows'   => array()
 763                                          );
 764          return true;
 765      }
 766  
 767  
 768     /**
 769      * Adds several rows of variables to a template
 770      *
 771      * Each Template can have an unlimited amount of its own variables
 772      * Can be used to add a database result as variables to a template
 773      *
 774      * @param    string    $template    name of the template
 775      * @param    array    $rows    array containing assotiative arrays with variable/value pairs
 776      * @param    string    $prefix    prefix for all variable names
 777      * @access    public
 778      * @see        addVar(), addVars(), addGlobalVar(), addGlobalVars()
 779      */
 780  	function addRows( $template, $rows, $prefix = '' )
 781      {
 782          $template    =    strtolower( $template );
 783          $prefix        =    strtoupper( $prefix );
 784  
 785          $cnt        =    count( $rows );
 786          for( $i = 0; $i < $cnt; $i++ )
 787          {
 788              if( !isset( $this->_vars[$template]['rows'][$i] ) )
 789                  $this->_vars[$template]['rows'][$i]    =    array();
 790  
 791              $rows[$i]    =    array_change_key_case( $rows[$i], CASE_UPPER );
 792  
 793              foreach( $rows[$i] as $varname => $value )
 794              {
 795                  $this->_vars[$template]['rows'][$i][$prefix.$varname]    =    $value;
 796              }
 797          }
 798      }
 799  
 800     /**
 801      * Adds an object to a template
 802      *
 803      * All properties of the object will be available as template variables.
 804      *
 805      * @access    public
 806      * @param    string            name of the template
 807      * @param    object|array    object or array of objects
 808      * @param    string            prefix for all variable names
 809      * @param    boolean            ignore private properties (starting with _)
 810      * @see        addVar(), addRows(), addGlobalVar(), addGlobalVars()
 811      */
 812  	function addObject( $template, $object, $prefix = '', $ignorePrivate = false )
 813      {
 814          if( is_array( $object ) ) {
 815              $rows = array();
 816              foreach($object as $o) {
 817                  array_push( $rows, $this->getObjectVars($o, $ignorePrivate) );
 818              }
 819  
 820                 return $this->addRows( $template, $rows, $prefix );
 821          } elseif (is_object($object)) {
 822              return $this->addVars( $template, $this->getObjectVars($object, $ignorePrivate), $prefix );
 823          }
 824          return false;
 825      }
 826  
 827     /**
 828      * get the vars from an object
 829      *
 830      * @access   private
 831      * @param    object
 832      * @param    boolean     ignore private properties (starting with _)
 833      * @return   array
 834      */
 835  	function getObjectVars($obj, $ignorePrivate = false)
 836      {
 837          if (method_exists($obj, 'getVars')) {
 838              return $obj->getVars();
 839          }
 840          $vars = get_object_vars($obj);
 841          if ($ignorePrivate === false) {
 842              return $vars;
 843          }
 844          foreach ($vars as $var => $value) {
 845              if ($var{0} == '_') {
 846                  unset($vars[$var]);
 847              }
 848          }
 849          return $vars;
 850      }
 851  
 852     /**
 853      * Adds a global variable
 854      *
 855      * Global variables are valid in all templates of this object.
 856      * A global variable has to be scalar, it will be converted to a string.
 857      *
 858      * @access    public
 859      * @param    string    $varname    name of the global variable
 860      * @param    string    $value        value of the variable
 861      * @return    boolean    true on success
 862      * @see        addGlobalVars(), addVar(), addVars(), addRows()
 863      */
 864  	function addGlobalVar( $varname, $value )
 865      {
 866          $this->_globals[strtoupper( $varname )]    =    ( string )$value;
 867          return    true;
 868      }
 869  
 870     /**
 871      * Clears a global variable
 872      *
 873      * @access    public
 874      * @param    string    $varname    name of the global variable
 875      * @return    boolean    true on success
 876      * @see        clearVar(), clearVars(), clearGlobalVars()
 877      */
 878  	function clearGlobalVar( $varname )
 879      {
 880          $varname = strtoupper( $varname );
 881          if (!isset($this->_globals[$varname])) {
 882              return false;
 883          }
 884          unset($this->_globals[$varname]);
 885          return    true;
 886      }
 887  
 888     /**
 889      * Clears all global variables
 890      *
 891      * @access    public
 892      * @return    boolean    true on success
 893      * @see        clearVar(), clearVars(), clearGlobalVar()
 894      */
 895  	function clearGlobalVars()
 896      {
 897          $this->_globals = array();
 898          return    true;
 899      }
 900  
 901     /**
 902      * Adds several global variables
 903      *
 904      * Global variables are valid in all templates of this object.
 905      *
 906      * $variables is an associative array, containing name/value pairs of the variables.
 907      *
 908      * @access    public
 909      * @param    array    $variables    array containing the variables
 910      * @param    string    $prefix        prefix for variable names
 911      * @return    boolean    true on success
 912      * @see        addGlobalVar(), addVar(), addVars(), addRows()
 913      */
 914  	function addGlobalVars( $variables, $prefix = '' )
 915      {
 916          $variables    =    array_change_key_case( $variables, CASE_UPPER );
 917          $prefix        =    strtoupper( $prefix );
 918          foreach( $variables as $varname => $value )
 919          {
 920              $this->_globals[$prefix.$varname]    =    ( string )$value;
 921          }
 922  
 923          return    true;
 924      }
 925  
 926     /**
 927      * get all global variables
 928      *
 929      * @access    public
 930      * @return    array    global variables
 931      */
 932  	function getGlobalVars()
 933      {
 934          return    $this->_globals;
 935      }
 936  
 937      /**
 938      * checks wether a template exists
 939      *
 940      * @access    public
 941      * @param    string        name of the template
 942      * @return    boolean        true, if the template exists, false otherwise
 943      */
 944  	function exists( $name )
 945      {
 946          return    in_array( strtolower( $name ), $this->_templateList );
 947      }
 948  
 949     /**
 950      * enable a template cache
 951      *
 952      * A template cache will improve performace, as the templates
 953      * do not have to be read on each request.
 954      *
 955      * @access    public
 956      * @param    string        name of the template cache
 957      * @param    array        parameters for the template cache
 958      * @return    boolean        true on success, patError otherwise
 959      */
 960  	function useTemplateCache( $cache, $params = array() )
 961      {
 962          if( !is_object( $cache ) )
 963          {
 964              $cache = &$this->loadModule( 'TemplateCache', $cache, $params );
 965          }
 966          if( patErrorManager::isError( $cache ) )
 967              return $cache;
 968  
 969          $this->_tmplCache = &$cache;
 970          return true;
 971      }
 972  
 973     /**
 974      * enable an output filter
 975      *
 976      * Output filters are used to modify the template
 977      * result before it is sent to the browser.
 978      *
 979      * They are applied, when displayParsedTemplate() is called.
 980      *
 981      * @access    public
 982      * @param    string        name of the output filter
 983      * @param    array        parameters for the output filter
 984      * @return    boolean        true on success, patError otherwise
 985      */
 986  	function applyOutputFilter( $filter, $params = array(), $template = null )
 987      {
 988          if (!is_object($filter)) {
 989              $filter = &$this->loadModule( 'OutputFilter', $filter, $params );
 990          }
 991          if (patErrorManager::isError($filter)) {
 992              return $filter;
 993          }
 994  
 995          if ($template === null) {
 996              $this->_outputFilters[] = &$filter;
 997              return true;
 998          }
 999  
1000          $template = strtolower($template);
1001          if (!$this->exists($template)) {
1002              return patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'The selected template does not exist');
1003          }
1004          $this->_templates[$template]['attributes']['outputfilter'] = &$filter;
1005          return true;
1006      }
1007  
1008     /**
1009      * enable an input filter
1010      *
1011      * input filters are used to modify the template
1012      * stream before it is split into smaller templates-
1013      *
1014      * @access    public
1015      * @param    string        name of the input filter
1016      * @param    array        parameters for the input filter
1017      * @return    boolean        true on success, patError otherwise
1018      */
1019  	function applyInputFilter( $filter, $params = array() )
1020      {
1021          if( !is_object( $filter ) )
1022          {
1023              $filter = &$this->loadModule( 'InputFilter', $filter, $params );
1024          }
1025          if( patErrorManager::isError( $filter ) )
1026              return $filter;
1027  
1028          $this->_inputFilters[] = &$filter;
1029          return true;
1030      }
1031  
1032     /**
1033      * open a file and parse for patTemplate tags
1034      *
1035      * @access        public
1036      * @param        name of the file
1037      * @return        true, if the template could be parsed
1038      * @deprecated    Use patTemplate::readTemplatesFromInput() instead, as the method name is misleading
1039      * @see            readTemplatesFromInput()
1040      */
1041  	function readTemplatesFromFile( $filename )
1042      {
1043          return    $this->readTemplatesFromInput( $filename, 'File' );
1044      }
1045  
1046     /**
1047      * open any input and parse for patTemplate tags
1048      *
1049      * @access    public
1050      * @param    string    name of the input (filename, shm segment, etc.)
1051      * @param    string    driver that is used as reader, you may also pass a Reader object
1052      * @param    array    additional options that will only be used for this template
1053      * @param    string    name of the template that should be used as a container, should not be used by public
1054      *                    calls.
1055      * @return    boolean    true, if the template could be parsed, false otherwise
1056      */
1057  	function readTemplatesFromInput( $input, $reader = 'File', $options = null, $parseInto = null )
1058      {
1059          if ((string)$input === '') {
1060              return patErrorManager::raiseError(PATTEMPLATE_ERROR_NO_INPUT, 'No input to read has been passed.');
1061          }
1062  
1063          if (is_array($options)) {
1064              $options = array_merge( $this->_options, $options );
1065          } else {
1066              $options = $this->_options;
1067          }
1068  
1069          if (!is_null($parseInto)) {
1070              $parseInto    =    strtolower( $parseInto );
1071          }
1072  
1073          $templates = false;
1074          if ($this->_tmplCache !== null) {
1075              /**
1076               * get the unique cache key
1077               */
1078              $key = $this->_tmplCache->getKey($input, $options);
1079  
1080              $templates = $this->_loadTemplatesFromCache( $input, $reader, $options, $key );
1081  
1082              /**
1083               * check for error returned from cache
1084               */
1085              if (patErrorManager::isError($templates)) {
1086                  return $templates;
1087              }
1088          }
1089  
1090          /**
1091           * templates have not been loaded from cache
1092           */
1093          if ($templates === false) {
1094              if (!is_object( $reader)) {
1095                  $reader = &$this->loadModule('Reader', $reader);
1096                  if (patErrorManager::isError($reader)) {
1097                      return $reader;
1098                  }
1099              }
1100  
1101              if ($reader->isInUse()) {
1102                  $reader = &$this->loadModule( 'Reader', $reader->getName(), array(), true);
1103                  if( patErrorManager::isError( $reader ) ) {
1104                      return $reader;
1105                  }
1106              }
1107  
1108              $reader->setOptions($options);
1109  
1110              /**
1111               * set the root attributes
1112               */
1113              if( !is_null( $parseInto ) )
1114              {
1115                  $attributes = $this->getAttributes( $parseInto );
1116                  if( !patErrorManager::isError( $attributes ) )
1117                  {
1118                      $reader->setRootAttributes( $attributes );
1119                  }
1120              }
1121  
1122              $templates    =    $reader->readTemplates( $input );
1123  
1124              /**
1125               * check for error returned from reader
1126               */
1127              if( patErrorManager::isError( $templates ) )
1128                  return $templates;
1129  
1130              /**
1131               * store the
1132               */
1133              if( $this->_tmplCache !== null )
1134              {
1135                  $this->_tmplCache->write( $key, $templates );
1136              }
1137          }
1138  
1139          /**
1140           * traverse all templates
1141           */
1142          foreach( $templates as $name => $spec )
1143          {
1144  
1145              /**
1146               * root template
1147               */
1148              if( $name == '__ptroot' )
1149              {
1150                  if( $parseInto === false )
1151                  {
1152                      continue;
1153                  }
1154                  if( !in_array( $parseInto, $this->_templateList ) )
1155                      continue;
1156  
1157                  $spec['loaded']        = true;
1158                  $spec['attributes']    = $this->_templates[$parseInto]['attributes'];
1159                  $name    =    $parseInto;
1160              }
1161              else
1162              {
1163                  /**
1164                   * store the name
1165                   */
1166                  array_push( $this->_templateList, $name );
1167              }
1168  
1169              /**
1170               * if this is the first template that has been loaded
1171               * set it as the root template
1172               */
1173              if( $this->_root === null && is_null( $parseInto ) && isset( $spec['isRoot'] ) && $spec['isRoot'] == true )
1174              {
1175                  $this->_root = $name;
1176              }
1177  
1178              /**
1179               * set some default values
1180               */
1181              $spec['iteration']            =    0;
1182              $spec['lastMode']            =    'w';
1183              $spec['result']                =    '';
1184              $spec['modifyVars']            =    array();
1185              $spec['copyVars']            =    array();
1186              $spec['defaultVars']        =    array();
1187  
1188              /**
1189               * store the template
1190               */
1191              $this->_templates[$name]    =    $spec;
1192  
1193              $this->prepareTemplate( $name );
1194  
1195              /**
1196               * store the default values of the variables
1197               */
1198              foreach( $spec['varspecs'] as $varname => $varspec )
1199              {
1200                  if (isset($varspec['modifier'])) {
1201                      $this->_templates[$name]['modifyVars'][$varname] = $varspec['modifier'];
1202                  }
1203  
1204                  if( isset( $varspec['copyfrom'] ) )
1205                  {
1206                      $this->_templates[$name]['copyVars'][$varname] = $varspec['copyfrom'];
1207                  }
1208  
1209                  if( !isset( $varspec['default'] ) )
1210                      continue;
1211  
1212                  $this->_templates[$name]['defaultVars'][$varname] = $varspec['default'];
1213  
1214                  if( !is_null( $this->getVar( $name, $varname ) ) )
1215                      continue;
1216  
1217                  $this->addVar( $name, $varname, $varspec['default'] );
1218              }
1219  
1220              unset($this->_templates[$name]['varspecs']);
1221  
1222              /**
1223               * autoload the template
1224               *
1225               * Some error management is needed here...
1226               */
1227              if( isset( $this->_templates[$name]['attributes']['src'] ) && $this->_templates[$name]['attributes']['autoload'] == 'on' )
1228              {
1229                  if( $this->_templates[$name]['loaded'] !== true )
1230                  {
1231                      if( $this->_templates[$name]['attributes']['parse'] == 'on' )
1232                      {
1233                          $this->readTemplatesFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], $options, $name );
1234                      }
1235                      else
1236                      {
1237                          $this->loadTemplateFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], null, $name );
1238                      }
1239                      $this->_templates[$name]['loaded']    =    true;
1240                  }
1241              }
1242          }
1243  
1244          return true;
1245      }
1246  
1247     /**
1248      * load from template cache
1249      *
1250      * @access    private
1251      * @param    string    name of the input (filename, shm segment, etc.)
1252      * @param    string    driver that is used as reader, you may also pass a Reader object
1253      * @param    array    options for the reader
1254      * @param    string    cache key
1255      * @return    array|boolean    either an array containing the templates, or false
1256      */
1257  	function _loadTemplatesFromCache( $input, &$reader, $options, $key )
1258      {
1259          if( is_object( $reader ) )
1260              $statName   =   $reader->getName();
1261          else
1262              $statName    =    $reader;
1263  
1264          $stat    =    &$this->loadModule( 'Stat', $statName );
1265          $stat->setOptions( $options );
1266  
1267          /**
1268           * get modification time
1269           */
1270          $modTime   = $stat->getModificationTime( $input );
1271          $templates = $this->_tmplCache->load( $key, $modTime );
1272  
1273          return $templates;
1274      }
1275  
1276     /**
1277      * open any input and load content into template
1278      *
1279      * @access    public
1280      * @param    string    name of the input (filename, shm segment, etc.)
1281      * @param    string    driver that is used as reader
1282      * @param    string    name of the template that should be used as a container,
1283      * @return    boolean    true, if the template could be parsed, false otherwise
1284      */
1285  	function loadTemplateFromInput( $input, $reader = 'File', $options = null, $parseInto = false )
1286      {
1287          if( is_array( $options ) )
1288              $options = array_merge( $this->_options, $options );
1289          else
1290              $options = $this->_options;
1291  
1292          if( !is_null( $parseInto ) )
1293              $parseInto    =    strtolower( $parseInto );
1294  
1295          $reader    = &$this->loadModule( 'Reader', $reader );
1296          if( patErrorManager::isError( $reader ) )
1297          {
1298              return $reader;
1299          }
1300          $reader->setOptions($options);
1301  
1302          $result    = $reader->loadTemplate( $input );
1303  
1304          if( patErrorManager::isError( $result ) )
1305          {
1306              return $result;
1307          }
1308  
1309          $this->_templates[$parseInto]['content'] .= $result;
1310          $this->_templates[$parseInto]['loaded']   = true;
1311          return true;
1312      }
1313  
1314     /**
1315      * load a template that had autoload="off"
1316      *
1317      * This is needed, if you change the source of a template and want to
1318      * load it, after changing the attribute.
1319      *
1320      * @access    public
1321      * @param    string        template name
1322      * @return    boolean        true, if template could be loaded
1323      */
1324  	function  loadTemplate( $template )
1325      {
1326          $template = strtolower( $template );
1327          if( !isset( $this->_templates[$template] ) )
1328          {
1329              return    patErrorManager::raiseWarning(
1330                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
1331                                                      "Template '$template' does not exist."
1332                                                  );
1333          }
1334  
1335          if( $this->_templates[$template]['loaded'] === true )
1336              return true;
1337  
1338          if( $this->_templates[$template]['attributes']['parse'] == 'on' )
1339          {
1340              return $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
1341          }
1342          else
1343          {
1344              return $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
1345          }
1346      }
1347  
1348     /**
1349      * loads a patTemplate module
1350      *
1351      * Modules are located in the patTemplate folder and include:
1352      * - Readers
1353      * - Caches
1354      * - Variable Modifiers
1355      * - Filters
1356      * - Functions
1357      * - Stats
1358      *
1359      * @access    public
1360      * @param    string    moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter)
1361      * @param    string    moduleName
1362      * @param    array    parameters for the module
1363      * @return    object
1364      */
1365      function &loadModule( $moduleType, $moduleName, $params = array(), $new = false )
1366      {
1367          if( !isset( $this->_modules[$moduleType] ) )
1368              $this->_modules[$moduleType]    =    array();
1369  
1370          $sig = md5( $moduleName . serialize( $params ) );
1371  
1372          if( isset( $this->_modules[$moduleType][$sig] ) && $new === false ) {
1373              return    $this->_modules[$moduleType][$sig];
1374          }
1375  
1376          if( !class_exists( 'patTemplate_Module' ) )
1377          {
1378              $file    =    sprintf( "%s/Module.php", $this->getIncludePath() );
1379              if( !@include_once $file )
1380                  return    patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, 'Could not load module base class.' );
1381          }
1382  
1383          $baseClass    =    'patTemplate_' . $moduleType;
1384          if( !class_exists( $baseClass ) )
1385          {
1386              $baseFile    =    sprintf( "%s/%s.php", $this->getIncludePath(), $moduleType );
1387              if( !@include_once $baseFile )
1388                  return    patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, "Could not load base class for $moduleType ($baseFile)." );
1389          }
1390  
1391          $moduleClass    =    'patTemplate_' . $moduleType . '_' .$moduleName;
1392          if( !class_exists( $moduleClass ) )
1393          {
1394              if( isset( $this->_moduleDirs[$moduleType] ) )
1395                  $dirs = $this->_moduleDirs[$moduleType];
1396              else
1397                  $dirs = array();
1398              array_push( $dirs, $this->getIncludePath() .'/'. $moduleType );
1399  
1400              $found = false;
1401              foreach( $dirs as $dir )
1402              {
1403                  $moduleFile    = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) );
1404                  if (@include_once $moduleFile) {
1405                      $found = true;
1406                      break;
1407                  }
1408              }
1409  
1410              if( !$found ) {
1411                  return    patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Could not load module $moduleClass ($moduleFile)." );
1412              }
1413          }
1414  
1415          if( !class_exists( $moduleClass ) )
1416          {
1417              return    patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Module file $moduleFile does not contain class $moduleClass." );
1418          }
1419  
1420          $this->_modules[$moduleType][$sig]    =    &new $moduleClass;
1421          if( method_exists( $this->_modules[$moduleType][$sig], 'setTemplateReference' ) )
1422          {
1423              $this->_modules[$moduleType][$sig]->setTemplateReference( $this );
1424          }
1425  
1426          $this->_modules[$moduleType][$sig]->setParams( $params );
1427  
1428          return $this->_modules[$moduleType][$sig];
1429      }
1430  
1431     /**
1432      * checks whether a module exists.
1433      *
1434      * Modules are located in the patTemplate folder and include:
1435      * - Readers
1436      * - Caches
1437      * - Variable Modifiers
1438      * - Filters
1439      * - Functions
1440      * - Stats
1441      *
1442      * @access    public
1443      * @param    string    moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter)
1444      * @param    string    moduleName
1445      * @return    boolean
1446      */
1447  	function moduleExists( $moduleType, $moduleName )
1448      {
1449          if (isset($this->_moduleDirs[$moduleType])) {
1450              $dirs = $this->_moduleDirs[$moduleType];
1451          } else {
1452              $dirs = array();
1453          }
1454          array_push($dirs, $this->getIncludePath() .'/'. $moduleType);
1455  
1456          foreach ($dirs as $dir) {
1457              $moduleFile    = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) );
1458              if (!file_exists($moduleFile)) {
1459                  continue;
1460              }
1461              if (!is_readable($moduleFile)) {
1462                  continue;
1463              }
1464              return true;
1465          }
1466          return false;
1467      }
1468  
1469     /**
1470      * parses a template
1471      *
1472      * Parses a template and stores the parsed content.
1473      * mode can be "w" for write (delete already parsed content) or "a" for append (appends the
1474      * new parsed content to the already parsed content)
1475      *
1476      * @access    public
1477      * @param    string    name of the template
1478      * @param    string    mode for the parsing
1479      */
1480  	function parseTemplate( $template, $mode = 'w' )
1481      {
1482          $template = strtolower($template);
1483  
1484          if (!isset($this->_templates[$template])) {
1485              return    patErrorManager::raiseWarning(
1486                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
1487                                                      "Template '$template' does not exist."
1488                                                  );
1489          }
1490  
1491          /**
1492           * template is not visible
1493           */
1494          if ($this->_templates[$template]['attributes']['visibility'] == 'hidden') {
1495              $this->_templates[$template]['result']    =    '';
1496              $this->_templates[$template]['parsed']    =    true;
1497              return true;
1498          }
1499  
1500          /**
1501           * check, if the template has been loaded
1502           * and load it if necessary.
1503           */
1504          if ($this->_templates[$template]['loaded'] !== true) {
1505              if ($this->_templates[$template]['attributes']['parse'] == 'on') {
1506                  $result = $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
1507              } else {
1508                  $result = $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
1509              }
1510              if (patErrorManager::isError($result)) {
1511                  return $result;
1512              }
1513          }
1514  
1515          /**
1516           * check for autoclear
1517           */
1518          if(
1519              isset( $this->_templates[$template]['attributes']['autoclear'] ) &&
1520              $this->_templates[$template]['attributes']['autoclear'] == 'yes' &&
1521              $mode === 'w' &&
1522              $this->_templates[$template]['lastMode'] != 'a'
1523            ) {
1524              $this->_templates[$template]['parsed']    = false;
1525          }
1526  
1527          /**
1528           * template has been parsed and mode is not 'append'
1529           */
1530          if ($this->_templates[$template]['parsed'] === true && $mode === 'w') {
1531              return true;
1532          }
1533  
1534          $this->_templates[$template]['lastMode'] = $mode;
1535  
1536          $this->_initTemplate( $template );
1537  
1538          if (!isset($this->_vars[$template]['rows'])) {
1539              $this->_vars[$template]['rows']    =    array();
1540          }
1541          $loop = count( $this->_vars[$template]['rows'] );
1542  
1543          /**
1544           * loop at least one times
1545           */
1546          if ($loop < 1) {
1547              $loop = 1;
1548          }
1549  
1550          if (isset($this->_templates[$template]['attributes']['maxloop'])) {
1551              $loop = ceil( $loop / $this->_templates[$template]['attributes']['maxloop'] ) * $this->_templates[$template]['attributes']['maxloop'];
1552          }
1553  
1554          $this->_templates[$template]['loop'] = max( $this->_templates[$template]['attributes']['loop'], $loop );
1555  
1556          $start = 0;
1557          if (isset($this->_templates[$template]['attributes']['limit'])) {
1558              $p = strpos( $this->_templates[$template]['attributes']['limit'], ',' );
1559              if ($p === false) {
1560                  $this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $this->_templates[$template]['attributes']['limit'] );
1561                  $start = 0;
1562              } else {
1563                  $start = substr( $this->_templates[$template]['attributes']['limit'], 0, $p );
1564                  $end   = substr( $this->_templates[$template]['attributes']['limit'], $p+1 )+$start;
1565  
1566                  $this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $end );
1567              }
1568          }
1569  
1570          /**
1571           * template should be cleared before parsing
1572           */
1573          if ($mode == 'w') {
1574              $this->_templates[$template]['result']    = '';
1575              $this->_templates[$template]['iteration'] = $start;
1576          }
1577  
1578          $loopCount = 0;
1579          for ($i = $start; $i < $this->_templates[$template]['loop']; $i++) {
1580              $finished  = false;
1581  
1582              unset( $this->_templates[$template]['vars'] );
1583  
1584              /**
1585               * fetch the variables
1586               */
1587              $this->_fetchVariables( $template );
1588  
1589              /**
1590               * fetch the template
1591               */
1592              $result = $this->_fetchTemplate($template);
1593  
1594              if ($result === false) {
1595                  $this->_templates[$template]['iteration']++;
1596                  continue;
1597              }
1598  
1599              /**
1600               * parse
1601               */
1602              $this->_parseVariables( $template );
1603              $result = $this->_parseDependencies( $template );
1604              if (patErrorManager::isError($result)) {
1605                  return $result;
1606              }
1607  
1608              /**
1609               * store result
1610               */
1611              $this->_templates[$template]['result'] .= $this->_templates[$template]['work'];
1612  
1613              $this->_templates[$template]['iteration']++;
1614  
1615              ++$loopCount;
1616  
1617              /**
1618               * check for maximum loops
1619               */
1620              if (isset($this->_templates[$template]['attributes']['maxloop'])) {
1621                  if ($loopCount == $this->_templates[$template]['attributes']['maxloop'] && $i < ($loop-1)) {
1622                      $loopCount = 0;
1623                      $finished  = true;
1624                      $this->_templates[$template]['parsed'] = true;
1625                      $this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a' );
1626                      $this->_templates[$template]['parsed'] = false;
1627                      $this->_templates[$template]['result'] = '';
1628                  }
1629              }
1630          }
1631  
1632          if (!$finished && isset($this->_templates[$template]['attributes']['maxloop'])) {
1633              $this->_templates[$template]['parsed'] = true;
1634              $this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a', false );
1635              $this->_templates[$template]['parsed'] = false;
1636              $this->_templates[$template]['result'] = '';
1637              $this->_templates[$this->_templates[$template]['attributes']['parent']]['work'] = '';
1638          }
1639  
1640          $this->_parseGlobals($template);
1641  
1642          $this->_handleUnusedVars($template);
1643  
1644          $this->_templates[$template]['parsed']    = true;
1645  
1646          if (isset($this->_templates[$template]['attributes']['autoclear']) && $this->_templates[$template]['attributes']['autoclear'] == 'yes') {
1647              $this->_vars[$template] = array(
1648                                              'scalar' => array(),
1649                                              'rows'   => array()
1650                                              );
1651          }
1652  
1653          if (isset($this->_templates[$template]['attributes']['outputfilter'])) {
1654              if (is_object($this->_templates[$template]['attributes']['outputfilter'])) {
1655                  $filter = &$this->_templates[$template]['attributes']['outputfilter'];
1656              } else {
1657                  $filter = &$this->loadModule('OutputFilter', $this->_templates[$template]['attributes']['outputfilter']);
1658              }
1659  
1660              if (patErrorManager::isError($filter)) {
1661                  return $filter;
1662              }
1663  
1664              $this->_templates[$template]['result'] = $filter->apply($this->_templates[$template]['result']);
1665          }
1666          return true;
1667      }
1668  
1669     /**
1670      * Initialize a template
1671      *
1672      * This method checks the variable specifications and
1673      * copys variables from other templates.
1674      *
1675      * @access    private
1676      * @param    string    name of the template
1677      * @return    boolean    true on success
1678      */
1679  	function _initTemplate( $template )
1680      {
1681          foreach( $this->_templates[$template]['copyVars'] as $dest => $src )
1682          {
1683              /**
1684               * copy from the same template
1685               */
1686              if( !is_array( $src ) )
1687              {
1688                  $srcTemplate = $template;
1689                  $srcVar      = $src;
1690              }
1691              else
1692              {
1693                  $srcTemplate = $src[0];
1694                  $srcVar      = $src[1];
1695              }
1696  
1697              $copied = false;
1698  
1699              /**
1700               * copy from another template
1701               */
1702              if( isset( $this->_vars[$srcTemplate] ) )
1703              {
1704                  if( isset( $this->_vars[$srcTemplate]['scalar'][$srcVar] ) )
1705                  {
1706                      $this->_vars[$template]['scalar'][$dest] = $this->_vars[$srcTemplate]['scalar'][$srcVar];
1707                      continue;
1708                  }
1709  
1710                  $rows = count( $this->_vars[$srcTemplate]['rows'] );
1711  
1712                  for( $i = 0; $i < $rows; $i++ )
1713                  {
1714                      if( !isset( $this->_vars[$srcTemplate]['rows'][$i][$srcVar] ) )
1715                          continue;
1716                      if( !isset( $this->_vars[$template]['rows'][$i] ) )
1717                          $this->_vars[$template]['rows'][$i] = array();
1718                      $this->_vars[$template]['rows'][$i][$dest] = $this->_vars[$srcTemplate]['rows'][$i][$srcVar];
1719                      $copied = true;
1720                  }
1721              }
1722              if( !$copied && isset( $this->_globals[$srcVar] ))
1723              {
1724                  $this->_vars[$template]['scalar'][$dest] = $this->_globals[$srcVar];
1725              }
1726  
1727          }
1728          return true;
1729      }
1730  
1731     /**
1732      * parse all variables in a template
1733      *
1734      * @access    private
1735      * @param    string
1736      */
1737  	function _parseVariables( $template )
1738      {
1739          /**
1740           * modify variables before parsing
1741           */
1742          $this->_applyModifers($template, $this->_templates[$template]['vars']);
1743  
1744          foreach( $this->_templates[$template]['vars'] as $key => $value )
1745          {
1746              if( is_array( $value ) )
1747              {
1748                  if( count( $this->_templates[$template]['currentDependencies'] ) == 1 )
1749                  {
1750                      $child    =    $this->_templates[$template]['currentDependencies'][0];
1751                  }
1752                  else
1753                  {
1754                      if( isset( $this->_templates[$template]['attributes']['child'] ) )
1755                          $child = $this->_templates[$template]['attributes']['child'];
1756                      else
1757                          continue;
1758                  }
1759  
1760                  $this->setAttribute( $child, 'autoclear', 'yes' );
1761                  $this->addVar( $child, $key, $value );
1762                  continue;
1763              }
1764  
1765              $var  = $this->_startTag.$key.$this->_endTag;
1766              $this->_templates[$template]['work'] = str_replace( $var, $value, $this->_templates[$template]['work'] );
1767          }
1768          return true;
1769      }
1770  
1771     /**
1772      * parse global variables in the template
1773      *
1774      * @access   private
1775      * @param    string      name of the template
1776      * @return   boolean
1777      */
1778  	function _parseGlobals($template)
1779      {
1780          $globalVars = $this->_globals;
1781          $this->_applyModifers($template, $globalVars);
1782  
1783          foreach( $globalVars as $key => $value )
1784          {
1785              if( is_array( $value ) )
1786              {
1787                  continue;
1788              }
1789  
1790              $var  = $this->_startTag.$key.$this->_endTag;
1791              $this->_templates[$template]['result'] = str_replace( $var, $value, $this->_templates[$template]['result'] );
1792          }
1793          return true;
1794      }
1795  
1796     /**
1797      * apply variable modifiers
1798      *
1799      * The variables will be passed by reference.
1800      *
1801      * @access   private
1802      * @param    string      name of the template (use modifiers from this template)
1803      * @param    array       variables to which the modifiers should be applied
1804      * @return   boolean
1805      */
1806  	function _applyModifers($template, &$vars)
1807      {
1808          foreach ($this->_templates[$template]['modifyVars'] as $varname => $modifier) {
1809              if (!isset($vars[$varname])) {
1810                  continue;
1811              }
1812  
1813              if (($modifier['type'] === 'php' || $modifier['type'] === 'auto' ) && is_callable($modifier['mod'])) {
1814                  $vars[$varname] = call_user_func($modifier['mod'], $vars[$varname]);
1815                  continue;
1816              }
1817  
1818              if ($modifier['type'] === 'php') {
1819                  continue;
1820              }
1821  
1822              $mod = &$this->loadModule( 'Modifier', ucfirst( $modifier['mod'] ) );
1823              $vars[$varname] = $mod->modify( $vars[$varname], $modifier['params'] );
1824          }
1825  
1826          // apply the default modifier
1827          if (isset($this->_templates[$template]['attributes']['defaultmodifier'])) {
1828  
1829              $defaultModifier = $this->_templates[$template]['attributes']['defaultmodifier'];
1830              if (is_callable($defaultModifier)) {
1831                  $type = 'php';
1832              } else {
1833                  $type = 'custom';
1834                  $defaultModifier = &$this->loadModule('Modifier', ucfirst($defaultModifier));
1835              }
1836  
1837  
1838              foreach (array_keys($vars) as $varname) {
1839                  if (isset($this->_templates[$template]['modifyVars'][$varname])) {
1840                      continue;
1841                  }
1842                  if ($type === 'php') {
1843                      $vars[$varname] = call_user_func($defaultModifier, $vars[$varname]);
1844                  } else {
1845                      $vars[$varname] = $defaultModifier->modify($vars[$varname], array());
1846                  }
1847              }
1848          }
1849  
1850          return true;
1851      }
1852  
1853     /**
1854      * parse all dependencies in a template
1855      *
1856      * @access    private
1857      * @param    string
1858      */
1859  	function _parseDependencies($template)
1860      {
1861          $countDep    =    count( $this->_templates[$template]['currentDependencies'] );
1862          for ($i = 0; $i < $countDep; $i++) {
1863              $depTemplate = $this->_templates[$template]['currentDependencies'][$i];
1864              if ($depTemplate == $template) {
1865                  return patErrorManager::raiseError(PATTEMPLATE_ERROR_RECURSION, 'You have an error in your template "' . $template . '", which leads to recursion');
1866              }
1867              $this->parseTemplate($depTemplate);
1868              $var    = $this->_startTag.'TMPL:'.strtoupper( $depTemplate) .$this->_endTag;
1869              $this->_templates[$template]['work'] = str_replace( $var, $this->_templates[$depTemplate]['result'], $this->_templates[$template]['work'] );
1870          }
1871          return true;
1872      }
1873  
1874     /**
1875      * fetch plain template
1876      *
1877      * The template content will be stored in the template
1878      * configuration so it can be used by other
1879      * methods.
1880      *
1881      * @access    private
1882      * @param    string    template name
1883      * @return    boolean
1884      */
1885  	function _fetchTemplate( $template )
1886      {
1887          switch( $this->_templates[$template]['attributes']['type'] )
1888          {
1889              /**
1890               * condition template
1891               */
1892              case 'condition':
1893                  $value = $this->_getConditionValue($template, $this->_templates[$template]['attributes']['conditionvar']);
1894                  if ($value === false) {
1895                      $this->_templates[$template]['work']                = '';
1896                      $this->_templates[$template]['currentDependencies']    = array();
1897                  } else {
1898                      $this->_templates[$template]['work']                = $this->_templates[$template]['subtemplates'][$value]['data'];
1899                      $this->_templates[$template]['currentDependencies']    = $this->_templates[$template]['subtemplates'][$value]['dependencies'];
1900                  }
1901                  break;
1902  
1903              /**
1904               * condition template
1905               */
1906              case 'simplecondition':
1907                  foreach( $this->_templates[$template]['attributes']['requiredvars'] as $var )
1908                  {
1909                      // different template scope
1910                      if( $var[0] !== $template ) {
1911                          $this->_fetchVariables($var[0]);
1912                      }
1913                      $value = null;
1914                      // fetch the local variable
1915                      if( isset( $this->_templates[$var[0]]['vars'][$var[1]] )
1916                        && strlen( $this->_templates[$var[0]]['vars'][$var[1]] ) > 0 ) {
1917                         $value = $this->_templates[$var[0]]['vars'][$var[1]];
1918                      }
1919                      if (isset($this->_templates[$template]['attributes']['useglobals'])) {
1920                          if(isset($this->_globals[$var[1]]) && strlen($this->_globals[$var[1]]) > 1) {
1921                              $value = $this->_globals[$var[1]];
1922                          }
1923                      }
1924                      if ($value !== null) {
1925                          if ($var[2] === null) {
1926                              continue;
1927                          } else {
1928                              // Joomla! addition 23-June-2005
1929                              // value wrapped in ## uses regex for comparison
1930                              $condition = $var[2];
1931                              if (substr( $condition, 0, 1 ) == '#' && substr( $condition, -1, 1 ) == '#' ) {
1932                                  if (preg_match( $condition, $value )) {
1933                                      continue;
1934                                  }
1935                              } else if ($condition == $value) {
1936                                  continue;
1937                              }
1938                              /* Pat Original
1939                              if ($var[2] == $value) {
1940                                     continue;
1941                              }
1942                              */
1943                          }
1944                      }
1945  
1946                      $this->_templates[$template]['work']                = '';
1947                      $this->_templates[$template]['currentDependencies']    = array();
1948                      break 2;
1949                  }
1950                  $this->_templates[$template]['work']                 = $this->_templates[$template]['content'];
1951                  $this->_templates[$template]['currentDependencies']    = $this->_templates[$template]['dependencies'];
1952                  break;
1953  
1954              /**
1955               * modulo template
1956               */
1957              case 'modulo':
1958                  // check for empty template
1959  
1960                  if ($this->_hasVariables($template)) {
1961                      $value = (string)($this->_templates[$template]['iteration'] + 1 ) % $this->_templates[$template]['attributes']['modulo'];
1962                  } else {
1963                      $value = '__empty';
1964                  }
1965  
1966                  $value = $this->_getConditionValue($template, $value, false);
1967                  if ($value === false) {
1968                      $this->_templates[$template]['work']                = '';
1969                      $this->_templates[$template]['currentDependencies']    = array();
1970                  } else {
1971                      $this->_templates[$template]['work']                = $this->_templates[$template]['subtemplates'][$value]['data'];
1972                      $this->_templates[$template]['currentDependencies']    = $this->_templates[$template]['subtemplates'][$value]['dependencies'];
1973                  }
1974                  break;
1975  
1976              /**
1977               * standard template
1978               */
1979              default:
1980                  $this->_templates[$template]['work']                 =    $this->_templates[$template]['content'];
1981                  $this->_templates[$template]['currentDependencies']    =    $this->_templates[$template]['dependencies'];
1982                  break;
1983          }
1984          return true;
1985      }
1986  
1987     /**
1988      * check, whether a template contains variables
1989      *
1990      * @access   private
1991      * @param    string  template name
1992      * @return   boolean
1993      */
1994  	function _hasVariables($template)
1995      {
1996          if (!empty($this->_vars[$template]['scalar'])) {
1997              return true;
1998          }
1999          if (isset($this->_vars[$template]['rows'][$this->_templates[$template]['iteration']])) {
2000              return true;
2001          }
2002          return false;
2003      }
2004  
2005     /**
2006      * fetch the value of a condition variable
2007      *
2008      * _fetchVariables() has to be called before this
2009      * method is being called.
2010      *
2011      * @access    private
2012      * @param    string    template name
2013      * @param    string    condition value
2014      * @param    boolean    flag that indicates whether value is the name of the variable that should be resolved
2015      *
2016      * @todo        split this method into smaller check methods that will be called according to
2017      *            a priority list
2018      */
2019  	function _getConditionValue( $template, $value, $isVar = true )
2020      {
2021          if ($isVar === true) {
2022              if (isset($this->_templates[$template]['attributes']['conditiontmpl'])) {
2023                  $_template = $this->_templates[$template]['attributes']['conditiontmpl'];
2024                  $this->_fetchVariables($_template);
2025              } else {
2026                  $_template = $template;
2027              }
2028  
2029              /**
2030               * get the value from the template variables
2031               */
2032              if (!isset($this->_templates[$_template]['vars'][$value]) || strlen($this->_templates[$_template]['vars'][$value]) === 0) {
2033                  if ($this->_templates[$template]['attributes']['useglobals'] == 'yes' || $this->_templates[$template]['attributes']['useglobals'] == 'useglobals') {
2034                      if (isset( $this->_globals[$value] ) && strlen( $this->_globals[$value] ) > 0) {
2035                          $value = $this->_globals[$value];
2036                      } else {
2037                          $value = '__empty';
2038                      }
2039                  } else {
2040                      $value = '__empty';
2041                  }
2042              } else {
2043                  $value = $this->_templates[$_template]['vars'][$value];
2044              }
2045          } else {
2046              $_template = $template;
2047          }
2048  
2049          // if value is empty and a template for empty has been defined, this
2050          // has priority
2051          if ($value === '__empty' && isset($this->_templates[$template]['subtemplates']['__empty'])) {
2052              return $value;
2053          }
2054  
2055          // only one iteration (but not empty), use the __single condition
2056          if ($value !== '__empty' && $this->_templates[$_template]['loop'] === 1) {
2057              if( isset($this->_templates[$template]['subtemplates']['__single'])) {
2058                  return '__single';
2059              }
2060          } else {
2061  
2062              // is __first?
2063              if( $this->_templates[$_template]['iteration'] == 0 ) {
2064                  if( isset( $this->_templates[$template]['subtemplates']['__first'] ) ) {
2065                      return '__first';
2066                  }
2067              }
2068  
2069              /**
2070               * is __last?
2071               */
2072              if (isset($this->_templates[$_template]['loop'])) {
2073                  $max = $this->_templates[$_template]['loop'] - 1;
2074                  if( $this->_templates[$_template]['iteration'] == $max ) {
2075                      if( isset( $this->_templates[$template]['subtemplates']['__last'] ) ) {
2076                          return '__last';
2077                      }
2078                  }
2079              }
2080          }
2081  
2082          // search for exact match
2083          foreach (array_keys($this->_templates[$template]['subtemplates']) as $key) {
2084              if (isset($this->_templates[$template]['subtemplates'][$key]['attributes']['var'])) {
2085                  $var = $this->_templates[$template]['subtemplates'][$key]['attributes']['var'];
2086                  if (isset($this->_templates[$template]['vars'][$var])) {
2087                      $current = $this->_templates[$template]['vars'][$var];
2088                  } else {
2089                      $current = null;
2090                  }
2091              } else {
2092                  $current = $key;
2093              }
2094  
2095              if ((string)$value === (string)$current) {
2096                  return $key;
2097              }
2098          }
2099  
2100          /**
2101           * is __default?
2102           */
2103          if( isset( $this->_templates[$template]['subtemplates']['__default'] ) ) {
2104              return '__default';
2105          }
2106  
2107          return false;
2108      }
2109  
2110     /**
2111      * fetch variables for a template
2112      *
2113      * The variables will be stored in the template
2114      * configuration so they can be used by other
2115      * methods.
2116      *
2117      * @access    private
2118      * @param    string    template name
2119      * @return    boolean
2120      */
2121  	function _fetchVariables( $template )
2122      {
2123          /**
2124           * variables already have been fetched
2125           */
2126          if (isset($this->_templates[$template]['vars'])) {
2127              return true;
2128          }
2129  
2130          $iteration = $this->_templates[$template]['iteration'];
2131  
2132          $vars = array();
2133          if( isset( $this->_templates[$template]['attributes']['varscope'] ) )
2134          {
2135              if (!is_array($this->_templates[$template]['attributes']['varscope'])) {
2136                  $this->_templates[$template]['attributes']['varscope'] = array($this->_templates[$template]['attributes']['varscope']);
2137              }
2138              foreach ($this->_templates[$template]['attributes']['varscope'] as $scopeTemplate) {
2139                  if ($this->exists($scopeTemplate)) {
2140                      $this->_fetchVariables( $scopeTemplate );
2141                      $vars = array_merge($this->_templates[$scopeTemplate]['vars'], $vars);
2142                  } else {
2143                      patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'Template \''.$scopeTemplate.'\' does not exist, referenced in varscope attribute of template \''.$template.'\'');
2144                  }
2145              }
2146          } else {
2147              $vars    =    array();
2148          }
2149  
2150          /**
2151           * get the scalar variables
2152           */
2153          if( isset( $this->_vars[$template] ) && isset( $this->_vars[$template]['scalar'] ) )
2154          {
2155              $vars = array_merge( $vars, $this->_vars[$template]['scalar'] );
2156          }
2157  
2158          /**
2159           * get the row variables
2160           */
2161          if( isset( $this->_vars[$template]['rows'][$iteration] ) )
2162          {
2163              $vars = array_merge( $vars, $this->_vars[$template]['rows'][$iteration] );
2164          }
2165  
2166          /**
2167           * add some system variables
2168           */
2169          $currentRow                =    $iteration + $this->_templates[$template]['attributes']['rowoffset'];
2170          $vars['PAT_ROW_VAR']    =    $currentRow;
2171  
2172          if( $this->_templates[$template]['attributes']['type'] == 'modulo' )
2173          {
2174              $vars['PAT_MODULO_REP']    =    ceil( $currentRow / $this->_templates[$template]['attributes']['modulo'] );
2175              $vars['PAT_MODULO']        =    ( $this->_templates[$template]['iteration'] + 1 ) % $this->_templates[$template]['attributes']['modulo'];
2176          }
2177  
2178          if( $this->_templates[$template]['attributes']['addsystemvars'] !== false )
2179          {
2180              $vars['PATTEMPLATE_VERSION'] = $this->_systemVars['appVersion'];
2181              $vars['PAT_LOOPS']        =    $this->_templates[$template]['loop'];
2182  
2183              switch ($this->_templates[$template]['attributes']['addsystemvars'])
2184              {
2185                  case 'boolean':
2186                      $trueValue  = 'true';
2187                      $falseValue = 'false';
2188                      break;
2189                  case 'integer':
2190                      $trueValue  = '1';
2191                      $falseValue = '0';
2192                      break;
2193                  default:
2194                      $trueValue  = $this->_templates[$template]['attributes']['addsystemvars'];
2195                      $falseValue = '';
2196                      break;
2197              }
2198  
2199              $vars['PAT_IS_ODD']        = ( $currentRow % 2 == 1 ) ? $trueValue : $falseValue;
2200              $vars['PAT_IS_EVEN']    = ( $currentRow % 2 == 0 ) ? $trueValue : $falseValue;
2201              $vars['PAT_IS_FIRST']    = ( $currentRow == 1 ) ? $trueValue : $falseValue;
2202              $vars['PAT_IS_LAST']    = ( $currentRow == $this->_templates[$template]['loop'] ) ? $trueValue : $falseValue;
2203              $vars['PAT_ROW_TYPE']    = ( $currentRow % 2 == 1 ) ? 'odd' : 'even';
2204          }
2205  
2206          $this->_templates[$template]['vars'] = $vars;
2207          return true;
2208      }
2209  
2210     /**
2211      * handle all unused variables in a template
2212      *
2213      * This is influenced by the 'unusedvars' attribute of the
2214      * template
2215      *
2216      * @access    private
2217      * @param    string
2218      */
2219  	function _handleUnusedVars( $template )
2220      {
2221          $regexp = '/([^\\\])('.$this->_startTag.'[^a-z]+[^\\\]'.$this->_endTag.')/U';
2222  
2223          switch( $this->_templates[$template]['attributes']['unusedvars'] )
2224          {
2225              case 'comment':
2226                  $this->_templates[$template]['result'] = preg_replace( $regexp, '<!-- \\1\\2 -->', $this->_templates[$template]['result'] );
2227                  break;
2228              case 'strip':
2229                  $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1', $this->_templates[$template]['result'] );
2230                  break;
2231              case 'nbsp':
2232                  $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1&nbsp;', $this->_templates[$template]['result'] );
2233                  break;
2234              case 'ignore':
2235                  break;
2236              default:
2237                  $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1'.$this->_templates[$template]['attributes']['unusedvars'], $this->_templates[$template]['result'] );
2238                  break;
2239          }
2240  
2241          // replace quoted variables
2242          $regexp = '/[\\\]'.$this->_startTag.'([^a-z]+)[\\\]'.$this->_endTag.'/U';
2243          $this->_templates[$template]['result'] = preg_replace( $regexp, $this->_startTag.'\\1'.$this->_endTag, $this->_templates[$template]['result'] );
2244  
2245          return true;
2246      }
2247  
2248     /**
2249      * returns a parsed Template
2250      *
2251      * If the template already has been parsed, it just returns the parsed template.
2252      * If the template has not been loaded, it will be loaded.
2253      *
2254      * @access    public
2255      * @param    string     name of the template
2256      * @param    boolean  whether to apply output filters
2257      * @return    string     Content of the parsed template
2258      * @see        displayParsedTemplate()
2259      */
2260  	function getParsedTemplate( $name = null, $applyFilters = false )
2261      {
2262          if (is_null($name)) {
2263              $name = $this->_root;
2264          }
2265  
2266          $name = strtolower( $name );
2267          $result = $this->parseTemplate( $name );
2268  
2269          if (patErrorManager::isError( $result )) {
2270              return $result;
2271          }
2272  
2273          if ($applyFilters === false) {
2274              return $this->_templates[$name]['result'];
2275          }
2276  
2277          $result = $this->_templates[$name]['result'];
2278  
2279          $cnt = count ($this->_outputFilters);
2280          for ($i = 0; $i < $cnt; $i++) {
2281              $result = $this->_outputFilters[$i]->apply( $result );
2282          }
2283  
2284          return $result;
2285      }
2286  
2287     /**
2288      * displays a parsed Template
2289      *
2290      * If the template has not been loaded, it will be loaded.
2291      *
2292      * @see        getParsedTemplate()
2293      * @param    string    name of the template
2294      * @param    boolean  whether to apply output filters
2295      * @return    boolean    true on success
2296      * @access    public
2297      */
2298  	function displayParsedTemplate($name = null, $applyFilters = true)
2299      {
2300          $result = $this->getParsedTemplate($name, $applyFilters);
2301  
2302          /**
2303           * error happened
2304           */
2305          if (patErrorManager::isError($result)) {
2306              return $result;
2307          }
2308  
2309          echo $result;
2310          return true;
2311      }
2312  
2313     /**
2314      * parse a template and push the result into a variable of any other
2315      * template
2316      *
2317      * If the template already has been parsed, it will just be pushed into the variable.
2318      * If the template has not been loaded, it will be loaded.
2319      *
2320      * @access    public
2321      * @param    string    name of the template
2322      * @return    string    Content of the parsed template
2323      * @param    boolean    if set to true, the value will be appended to the value already stored.
2324      * @see        getParsedTemplate()
2325      * @see        addVar()
2326      */
2327  	function parseIntoVar( $srcTmpl, $destTmpl, $var, $append = false )
2328      {
2329          $srcTmpl  =    strtolower( $srcTmpl );
2330          $destTmpl =    strtolower( $destTmpl );
2331          $var      = strtoupper($var);
2332  
2333          $result    =    $this->parseTemplate( $srcTmpl );
2334  
2335          if( patErrorManager::isError( $result ) )
2336              return $result;
2337  
2338          if( $append !== true || !isset( $this->_vars[$destTmpl]['scalar'][$var] ) )
2339              $this->_vars[$destTmpl]['scalar'][$var] = '';
2340  
2341          $this->_vars[$destTmpl]['scalar'][$var] .= $this->_templates[$srcTmpl]['result'];
2342  
2343          return true;
2344      }
2345  
2346     /**
2347      * clears a parsed Template
2348      *
2349      * Parsed Content, variables and the loop attribute are cleared
2350      *
2351      * If you will not be using this template anymore, then you should
2352      * call freeTemplate()
2353      *
2354      * @access    public
2355      * @param    string    name of the template
2356      * @param    boolean        set this to true to clear all child templates, too
2357      * @see        clearAllTemplates()
2358      * @see        freeTemplate()
2359      */
2360  	function clearTemplate( $name, $recursive = false )
2361      {
2362          $name    =    strtolower( $name );
2363          $this->_templates[$name]['parsed']        =    false;
2364          $this->_templates[$name]['work']        =    '';
2365          $this->_templates[$name]['iteration']    =    0;
2366          $this->_templates[$name]['result']        =    '';
2367          $this->_vars[$name]                        =    array(
2368                                                          'scalar'    =>    array(),
2369                                                          'rows'        =>    array()
2370                                                      );
2371  
2372          if (!empty($this->_templates[$name]['defaultVars'])) {
2373              foreach ($this->_templates[$name]['defaultVars'] as $varname => $value) {
2374                  $this->addVar($name, $varname, $value);
2375              }
2376          }
2377  
2378          /**
2379           * clear child templates as well
2380           */
2381          if( $recursive === true )
2382          {
2383              $deps = $this->_getDependencies( $name );
2384              foreach( $deps as $dep )
2385              {
2386                  $this->clearTemplate( $dep, true );
2387              }
2388          }
2389          return true;
2390      }
2391  
2392     /**
2393      * clears all templates
2394      *
2395      * @access    public
2396      * @uses        clearTemplate()
2397      */
2398  	function clearAllTemplates()
2399      {
2400          $templates    =    array_keys( $this->_templates );
2401          $cnt        =    count( $templates );
2402          for( $i = 0; $i < $cnt; $i++ )
2403          {
2404              $this->clearTemplate( $templates[$i] );
2405          }
2406          return true;
2407      }
2408  
2409     /**
2410      * frees a template
2411      *
2412      * All memory consumed by the template
2413      * will be freed.
2414      *
2415      * @access    public
2416      * @param    string    name of the template
2417      * @param    boolean    clear dependencies of the template
2418      * @see        freeAllTemplates()
2419      */
2420  	function freeTemplate( $name, $recursive = false )
2421      {
2422          $name    =    strtolower( $name );
2423          $key = array_search( $name, $this->_templateList );
2424          if( $key === false )
2425          {
2426              return    patErrorManager::raiseWarning(
2427                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
2428                                                      "Template '$name' does not exist."
2429                                                  );
2430          }
2431  
2432          unset( $this->_templateList[$key] );
2433          $this->_templateList = array_values( $this->_templateList );
2434  
2435          /**
2436           * free child templates as well
2437           */
2438          if( $recursive === true )
2439          {
2440              $deps = $this->_getDependencies( $name );
2441              foreach( $deps as $dep )
2442              {
2443                  $this->freeTemplate( $dep, true );
2444              }
2445          }
2446  
2447          unset( $this->_templates[$name] );
2448          unset( $this->_vars[$name] );
2449          if (isset($this->_discoveredPlaceholders[$name])) {
2450              unset($this->_discoveredPlaceholders[$name]);
2451          }
2452  
2453          return true;
2454      }
2455  
2456     /**
2457      * frees all templates
2458      *
2459      * All memory consumed by the templates
2460      * will be freed.
2461      *
2462      * @access    public
2463      * @see        freeTemplate()
2464      */
2465  	function freeAllTemplates()
2466      {
2467          $this->_templates     = array();
2468          $this->_vars         = array();
2469          $this->_templateList = array();
2470      }
2471  
2472     /**
2473      * get _all_ dependencies of a template,
2474      * regardless of the subtemplates
2475      *
2476      * @access    private
2477      * @param    string    template name
2478      * @return    array    list of all subtemplates
2479      */
2480  	function _getDependencies( $template )
2481      {
2482          $deps = array();
2483          if( isset( $this->_templates[$template]['dependencies'] ) )
2484              $deps = $this->_templates[$template]['dependencies'];
2485  
2486          if( isset( $this->_templates[$template]['subtemplates'] ) )
2487          {
2488              foreach( $this->_templates[$template]['subtemplates'] as $sub )
2489              {
2490                  if( isset( $sub['dependencies'] ) )
2491                      $deps = array_merge( $deps, $sub['dependencies'] );
2492              }
2493          }
2494          $deps = array_unique( $deps );
2495          return $deps;
2496      }
2497  
2498     /**
2499      * Displays useful information about all or named templates
2500      *
2501      * This method breaks BC, as it now awaits an array instead of
2502      * unlimited parameters.
2503      *
2504      * @param    mixed    array of templates that should be dumped, or null if you
2505      *                    want all templates to be dumped
2506      * @param    string    dumper
2507      * @access    public
2508      */
2509  	function dump( $restrict = null, $dumper = 'Html' )
2510      {
2511          if( is_string( $restrict ) )
2512              $restrict = array( $restrict );
2513  
2514          $dumper    =    &$this->loadModule( 'Dump', $dumper );
2515  
2516          if( patErrorManager::isError( $dumper ) )
2517          {
2518              return    $dumper;
2519          }
2520  
2521          if( is_null( $restrict ) )
2522          {
2523              $templates = $this->_templates;
2524              $vars      = $this->_vars;
2525          }
2526          else
2527          {
2528              $restrict = array_map( 'strtolower', $restrict );
2529  
2530              $templates = array();
2531              $vars      = array();
2532  
2533              foreach( $this->_templates as $name => $spec )
2534              {
2535                  if( !in_array( $name, $restrict ) )
2536                      continue;
2537                  $templates[$name] = $spec;
2538                  $vars[$name]      = $this->_vars[$name];
2539              }
2540          }
2541  
2542          $dumper->displayHeader();
2543          $dumper->dumpGlobals( $this->_globals );
2544          $dumper->dumpTemplates( $templates, $vars );
2545          $dumper->displayFooter();
2546  
2547          return    true;
2548      }
2549  
2550     /**
2551      * get the include path
2552      *
2553      * @access    public
2554      * @return   string
2555      */
2556  	function getIncludePath()
2557      {
2558          return    PATTEMPLATE_INCLUDE_PATH;
2559      }
2560  
2561     /**
2562      * apply input filters that have been set
2563      *
2564      * This is being called by the readers.
2565      *
2566      * @access    public
2567      * @param    string        template
2568      * @return    string        filtered templeta
2569      */
2570  	function applyInputFilters( $template )
2571      {
2572          $cnt = count( $this->_inputFilters );
2573          for( $i = 0; $i < $cnt; $i++ )
2574          {
2575              $template = $this->_inputFilters[$i]->apply( $template );
2576          }
2577          return $template;
2578      }
2579  
2580     /**
2581      * checks, whether a placeholder exists in a template
2582      *
2583      * @access   public
2584      * @param    string      name of the placeholder
2585      * @param    string      name of the template
2586      * @param    boolean     whether to use the cached result of a previous call
2587      */
2588  	function placeholderExists($placeholder, $tmpl, $cached = true)
2589      {
2590          $tmpl = strtolower($tmpl);
2591          $placeholder = strtoupper($placeholder);
2592  
2593          if (!$this->exists($tmpl)) {
2594              return false;
2595          }
2596  
2597          if ($cached === true) {
2598              if (isset($this->_discoveredPlaceholders[$tmpl]) && isset($this->_discoveredPlaceholders[$tmpl][$placeholder])) {
2599                  return $this->_discoveredPlaceholders[$tmpl][$placeholder];
2600              }
2601          }
2602  
2603          if (isset($this->_templates[$tmpl]['subtemplates'])) {
2604              $content = '';
2605              foreach ($this->_templates[$tmpl]['subtemplates'] as $temp) {
2606                  if (!isset($temp['data'])) {
2607                      continue;
2608                  }
2609                  $content .= $temp['data'];
2610              }
2611          } else {
2612              $content = $this->_templates[$tmpl]['content'];
2613          }
2614  
2615          $search = $this->_startTag . $placeholder . $this->_endTag;
2616          if (strstr($content, $search) !== false) {
2617              $this->_discoveredPlaceholders[$tmpl][$placeholder] = true;
2618              return true;
2619          }
2620          $this->_discoveredPlaceholders[$tmpl][$placeholder] = false;
2621          return false;
2622      }
2623  
2624     /**
2625      * Convert the template to its string representation.
2626      *
2627      * This method allows you to just echo the patTemplate
2628      * object in order to display the template.
2629      *
2630      * Requires PHP5
2631      *
2632      * <code>
2633      * $tmpl = new patTemplate();
2634      * $tmpl->readTemplatesFromFile( 'myfile.tmpl' );
2635      * echo $tmpl;
2636      * </code>
2637      *
2638      * @access    private
2639      * @return    string
2640      */
2641  	function __toString()
2642      {
2643          return $this->getParsedTemplate();
2644      }
2645  }
2646  
2647  /**
2648   * @package Joomla
2649   */
2650  class patFactory {
2651      /**
2652       * @param array An array of additional files to include from the root folder
2653       * @return object
2654       */
2655      function &createTemplate( $files=null ) {
2656          global $mainframe;
2657          $tmpl = new patTemplate;
2658  
2659          // patTemplate
2660          if ($GLOBALS['mosConfig_caching']) {
2661                 $tmpl->useTemplateCache( 'File', array(
2662                  'cacheFolder' => $GLOBALS['mosConfig_cachepath'], 'lifetime' => 20 ));
2663          }
2664  
2665          $tmpl->setNamespace( 'mos' );
2666  
2667          // load the wrapper and common templates
2668          $tmpl->setRoot( dirname( __FILE__ ) . '/tmpl' );
2669          $tmpl->readTemplatesFromFile( 'page.html' );
2670          $tmpl->applyInputFilter('ShortModifiers');
2671  
2672          if (is_array( $files )) {
2673              foreach ($files as $file) {
2674                  $tmpl->readTemplatesFromInput( $file );
2675              }
2676          }
2677          //echo $this->basePath() . '/components/' . $option . '/tmpl';
2678  
2679          $tmpl->addGlobalVar( 'option',             $GLOBALS['option'] );
2680          $tmpl->addGlobalVar( 'self',             $_SERVER['PHP_SELF'] );
2681          $tmpl->addGlobalVar( 'itemid',             $GLOBALS['Itemid'] );
2682          $tmpl->addGlobalVar( 'siteurl', $GLOBALS['mosConfig_live_site'] );
2683          $tmpl->addGlobalVar( 'adminurl', $GLOBALS['mosConfig_live_site'] . '/administrator' );
2684          $tmpl->addGlobalVar( 'templateurl', $GLOBALS['mosConfig_live_site'] . '/templates/' . $mainframe->getTemplate() );
2685          $tmpl->addGlobalVar( 'admintemplateurl', $GLOBALS['mosConfig_live_site'] . '/administrator/templates/' . $mainframe->getTemplate() );
2686          $tmpl->addGlobalVar( 'sitename', $GLOBALS['mosConfig_sitename'] );
2687          $tmpl->addGlobalVar('treecss', 'dtree.css');
2688          $tmpl->addGlobalVar('treeimgfolder', 'img');
2689  
2690          $iso = split( '=', _ISO );
2691          $tmpl->addGlobalVar( 'page_encoding', $iso[1] );
2692          $tmpl->addGlobalVar( 'version_copyright', $GLOBALS['_VERSION']->COPYRIGHT );
2693          $tmpl->addGlobalVar( 'version_url', $GLOBALS['_VERSION']->URL );
2694  
2695          $tmpl->addVar( 'form', 'formAction', $_SERVER['PHP_SELF'] );
2696          $tmpl->addVar( 'form', 'formName', 'adminForm' );
2697  
2698          // tabs
2699          $turl = $GLOBALS['mosConfig_live_site'] .'/includes/js/tabs/';
2700          $tmpl->addVar( 'includeTabs', 'taburl', $turl );
2701  
2702          return $tmpl;
2703      }
2704  }
2705  ?>


Généré le : Wed Nov 21 14:43:32 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics