[ Index ]

PHP Cross Reference of Joomla 1.5.26 DE

title

Body

[close]

/libraries/pattemplate/ -> patTemplate.php (source)

   1  <?PHP
   2  /**
   3   * patTemplate
   4   *
   5   * $Id: patTemplate.php 12694 2009-09-11 21:03:02Z ian $
   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          if(!isset($this->_vars[$template]['rows']))
 665              return null;
 666  
 667          $cnt = count( $this->_vars[$template]['rows'] );
 668          for( $i = 0; $i < $cnt; $i++ )
 669          {
 670              if( !isset( $this->_vars[$template]['rows'][$i][$varname] ) )
 671                  continue;
 672              array_push( $value, $this->_vars[$template]['rows'][$i][$varname] );
 673          }
 674          if( !empty( $value ) )
 675              return $value;
 676          return null;
 677      }
 678  
 679      /**
 680      * clear the value of a variable
 681      *
 682      * @access    public
 683      * @param    string    name of the template
 684      * @param    string    name of the variable
 685      * @return   boolean
 686      * @see      clearVars(), clearTemplate()
 687      */
 688  	function clearVar( $template, $varname )
 689      {
 690          $template    =    strtolower( $template );
 691          $varname    =    strtoupper( $varname );
 692  
 693          if (isset( $this->_vars[$template]['scalar'][$varname] )) {
 694              unset ($this->_vars[$template]['scalar'][$varname]);
 695              return true;
 696          }
 697  
 698          $result = false;
 699          $cnt = count( $this->_vars[$template]['rows'] );
 700          for ($i = 0; $i < $cnt; $i++) {
 701              if (!isset($this->_vars[$template]['rows'][$i][$varname])) {
 702                  continue;
 703              }
 704              unset($this->_vars[$template]['rows'][$i][$varname]);
 705              $result = true;
 706          }
 707          return $result;
 708      }
 709  
 710  
 711      /**
 712      * Adds several variables to a template
 713      *
 714      * Each Template can have an unlimited amount of its own variables
 715      * $variables has to be an assotiative array containing variable/value pairs
 716      *
 717      * @param    string    $template    name of the template
 718      * @param    array    $variables    assotiative array of the variables
 719      * @param    string    $prefix    prefix for all variable names
 720      * @access    public
 721      * @see        addVar(), addRows(), addGlobalVar(), addGlobalVars()
 722      */
 723  	function addVars( $template, $variables, $prefix = '' )
 724      {
 725          $template    =    strtolower( $template );
 726          $prefix        =    strtoupper( $prefix );
 727          $variables    =    array_change_key_case( $variables, CASE_UPPER );
 728  
 729          foreach ($variables as $varname => $value) {
 730              $varname = $prefix.$varname;
 731  
 732              if (!is_array($value)) {
 733                  if (!is_scalar($value)) {
 734                      continue;
 735                  }
 736                  $this->_vars[$template]['scalar'][$varname] = $value;
 737                  continue;
 738              }
 739  
 740              $cnt = count( $value );
 741              for( $i = 0; $i < $cnt; $i++ ) {
 742                  if( !isset( $this->_vars[$template]['rows'][$i] ) )
 743                      $this->_vars[$template]['rows'][$i]    =    array();
 744  
 745                  $this->_vars[$template]['rows'][$i][$varname]    =    $value[$i];
 746              }
 747          }
 748      }
 749  
 750      /**
 751      * Clear all variables in a template
 752      *
 753      * This clears only variables, but does
 754      *
 755      * @access    public
 756      * @param    string    $template    name of the template
 757      * @return   boolean
 758      * @see        clearVar(), clearTemplate()
 759      */
 760  	function clearVars( $template )
 761      {
 762          $template = strtolower($template);
 763          $this->_vars[$template] = array(
 764                                           'scalar' => array(),
 765                                           'rows'   => array()
 766                                          );
 767          return true;
 768      }
 769  
 770  
 771      /**
 772      * Adds several rows of variables to a template
 773      *
 774      * Each Template can have an unlimited amount of its own variables
 775      * Can be used to add a database result as variables to a template
 776      *
 777      * @param    string    $template    name of the template
 778      * @param    array    $rows    array containing assotiative arrays with variable/value pairs
 779      * @param    string    $prefix    prefix for all variable names
 780      * @access    public
 781      * @see        addVar(), addVars(), addGlobalVar(), addGlobalVars()
 782      */
 783  	function addRows( $template, $rows, $prefix = '' )
 784      {
 785          $template    =    strtolower( $template );
 786          $prefix        =    strtoupper( $prefix );
 787  
 788          $cnt        =    count( $rows );
 789          for( $i = 0; $i < $cnt; $i++ )
 790          {
 791              if( !isset( $this->_vars[$template]['rows'][$i] ) )
 792                  $this->_vars[$template]['rows'][$i]    =    array();
 793  
 794              $rows[$i]    =    array_change_key_case( $rows[$i], CASE_UPPER );
 795  
 796              foreach( $rows[$i] as $varname => $value )
 797              {
 798                  $this->_vars[$template]['rows'][$i][$prefix.$varname]    =    $value;
 799              }
 800          }
 801      }
 802  
 803      /**
 804      * Adds an object to a template
 805      *
 806      * All properties of the object will be available as template variables.
 807      *
 808      * @access    public
 809      * @param    string            name of the template
 810      * @param    object|array    object or array of objects
 811      * @param    string            prefix for all variable names
 812      * @param    boolean            ignore private properties (starting with _)
 813      * @see        addVar(), addRows(), addGlobalVar(), addGlobalVars()
 814      */
 815  	function addObject( $template, $object, $prefix = '', $ignorePrivate = false )
 816      {
 817          if( is_array( $object ) ) {
 818              $rows = array();
 819              foreach($object as $o) {
 820                  array_push( $rows, $this->getObjectVars($o, $ignorePrivate) );
 821              }
 822  
 823                 return $this->addRows( $template, $rows, $prefix );
 824          } elseif (is_object($object)) {
 825              return $this->addVars( $template, $this->getObjectVars($object, $ignorePrivate), $prefix );
 826          }
 827          return false;
 828      }
 829  
 830      /**
 831      * get the vars from an object
 832      *
 833      * @access   private
 834      * @param    object
 835      * @param    boolean     ignore private properties (starting with _)
 836      * @return   array
 837      */
 838  	function getObjectVars($obj, $ignorePrivate = false)
 839      {
 840          if (method_exists($obj, 'getVars')) {
 841              return $obj->getVars();
 842          }
 843          $vars = get_object_vars($obj);
 844          if ($ignorePrivate === false) {
 845              return $vars;
 846          }
 847          foreach ($vars as $var => $value) {
 848              if ($var{0} == '_') {
 849                  unset($vars[$var]);
 850              }
 851          }
 852          return $vars;
 853      }
 854  
 855      /**
 856      * Adds a global variable
 857      *
 858      * Global variables are valid in all templates of this object.
 859      * A global variable has to be scalar, it will be converted to a string.
 860      *
 861      * @access    public
 862      * @param    string    $varname    name of the global variable
 863      * @param    string    $value        value of the variable
 864      * @return    boolean    true on success
 865      * @see        addGlobalVars(), addVar(), addVars(), addRows()
 866      */
 867  	function addGlobalVar( $varname, $value )
 868      {
 869          $this->_globals[strtoupper( $varname )]    =    ( string )$value;
 870          return    true;
 871      }
 872  
 873      /**
 874      * Clears a global variable
 875      *
 876      * @access    public
 877      * @param    string    $varname    name of the global variable
 878      * @return    boolean    true on success
 879      * @see        clearVar(), clearVars(), clearGlobalVars()
 880      */
 881  	function clearGlobalVar( $varname )
 882      {
 883          $varname = strtoupper( $varname );
 884          if (!isset($this->_globals[$varname])) {
 885              return false;
 886          }
 887          unset($this->_globals[$varname]);
 888          return    true;
 889      }
 890  
 891      /**
 892      * Clears all global variables
 893      *
 894      * @access    public
 895      * @return    boolean    true on success
 896      * @see        clearVar(), clearVars(), clearGlobalVar()
 897      */
 898  	function clearGlobalVars()
 899      {
 900          $this->_globals = array();
 901          return    true;
 902      }
 903  
 904      /**
 905      * Adds several global variables
 906      *
 907      * Global variables are valid in all templates of this object.
 908      *
 909      * $variables is an associative array, containing name/value pairs of the variables.
 910      *
 911      * @access    public
 912      * @param    array    $variables    array containing the variables
 913      * @param    string    $prefix        prefix for variable names
 914      * @return    boolean    true on success
 915      * @see        addGlobalVar(), addVar(), addVars(), addRows()
 916      */
 917  	function addGlobalVars( $variables, $prefix = '' )
 918      {
 919          $variables    =    array_change_key_case( $variables, CASE_UPPER );
 920          $prefix        =    strtoupper( $prefix );
 921          foreach( $variables as $varname => $value )
 922          {
 923              $this->_globals[$prefix.$varname]    =    ( string )$value;
 924          }
 925  
 926          return    true;
 927      }
 928  
 929      /**
 930      * get all global variables
 931      *
 932      * @access    public
 933      * @return    array    global variables
 934      */
 935  	function getGlobalVars()
 936      {
 937          return    $this->_globals;
 938      }
 939  
 940      /**
 941      * checks wether a template exists
 942      *
 943      * @access    public
 944      * @param    string        name of the template
 945      * @return    boolean        true, if the template exists, false otherwise
 946      */
 947  	function exists( $name )
 948      {
 949          return    in_array( strtolower( $name ), $this->_templateList );
 950      }
 951  
 952      /**
 953      * enable a template cache
 954      *
 955      * A template cache will improve performace, as the templates
 956      * do not have to be read on each request.
 957      *
 958      * @access    public
 959      * @param    string        name of the template cache
 960      * @param    array        parameters for the template cache
 961      * @return    boolean        true on success, patError otherwise
 962      */
 963  	function useTemplateCache( $cache, $params = array() )
 964      {
 965          if( !is_object( $cache ) )
 966          {
 967              $cache = &$this->loadModule( 'TemplateCache', $cache, $params );
 968          }
 969          if( patErrorManager::isError( $cache ) )
 970              return $cache;
 971  
 972          $this->_tmplCache = &$cache;
 973          return true;
 974      }
 975  
 976      /**
 977      * enable an output filter
 978      *
 979      * Output filters are used to modify the template
 980      * result before it is sent to the browser.
 981      *
 982      * They are applied, when displayParsedTemplate() is called.
 983      *
 984      * @access    public
 985      * @param    string        name of the output filter
 986      * @param    array        parameters for the output filter
 987      * @return    boolean        true on success, patError otherwise
 988      */
 989  	function applyOutputFilter( $filter, $params = array(), $template = null )
 990      {
 991          if (!is_object($filter)) {
 992              $filter = &$this->loadModule( 'OutputFilter', $filter, $params );
 993          }
 994          if (patErrorManager::isError($filter)) {
 995              return $filter;
 996          }
 997  
 998          if ($template === null) {
 999              $this->_outputFilters[] = &$filter;
1000              return true;
1001          }
1002  
1003          $template = strtolower($template);
1004          if (!$this->exists($template)) {
1005              return patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'The selected template does not exist');
1006          }
1007          $this->_templates[$template]['attributes']['outputfilter'] = &$filter;
1008          return true;
1009      }
1010  
1011      /**
1012      * enable an input filter
1013      *
1014      * input filters are used to modify the template
1015      * stream before it is split into smaller templates-
1016      *
1017      * @access    public
1018      * @param    string        name of the input filter
1019      * @param    array        parameters for the input filter
1020      * @return    boolean        true on success, patError otherwise
1021      */
1022  	function applyInputFilter( $filter, $params = array() )
1023      {
1024          if( !is_object( $filter ) )
1025          {
1026              $filter = &$this->loadModule( 'InputFilter', $filter, $params );
1027          }
1028          if( patErrorManager::isError( $filter ) )
1029              return $filter;
1030  
1031          $this->_inputFilters[] = &$filter;
1032          return true;
1033      }
1034  
1035      /**
1036      * open a file and parse for patTemplate tags
1037      *
1038      * @access        public
1039      * @param        name of the file
1040      * @return        true, if the template could be parsed
1041      * @deprecated    Use patTemplate::readTemplatesFromInput() instead, as the method name is misleading
1042      * @see            readTemplatesFromInput()
1043      */
1044  	function readTemplatesFromFile( $filename )
1045      {
1046          return    $this->readTemplatesFromInput( $filename, 'File' );
1047      }
1048  
1049      /**
1050      * open any input and parse for patTemplate tags
1051      *
1052      * @access    public
1053      * @param    string    name of the input (filename, shm segment, etc.)
1054      * @param    string    driver that is used as reader, you may also pass a Reader object
1055      * @param    array    additional options that will only be used for this template
1056      * @param    string    name of the template that should be used as a container, should not be used by public
1057      *                    calls.
1058      * @return    boolean    true, if the template could be parsed, false otherwise
1059      */
1060  	function readTemplatesFromInput( $input, $reader = 'File', $options = null, $parseInto = null )
1061      {
1062          if ((string)$input === '') {
1063              return patErrorManager::raiseError(PATTEMPLATE_ERROR_NO_INPUT, 'No input to read has been passed.');
1064          }
1065  
1066          if (is_array($options)) {
1067              $options = array_merge( $this->_options, $options );
1068          } else {
1069              $options = $this->_options;
1070          }
1071  
1072          if (!is_null($parseInto)) {
1073              $parseInto    =    strtolower( $parseInto );
1074          }
1075  
1076          $templates = false;
1077          if ($this->_tmplCache !== null) {
1078              /**
1079               * get the unique cache key
1080               */
1081              $key = $this->_tmplCache->getKey($input, $options);
1082  
1083              $templates = $this->_loadTemplatesFromCache( $input, $reader, $options, $key );
1084  
1085              /**
1086               * check for error returned from cache
1087               */
1088              if (patErrorManager::isError($templates)) {
1089                  return $templates;
1090              }
1091          }
1092  
1093          /**
1094           * templates have not been loaded from cache
1095           */
1096          if ($templates === false) {
1097              if (!is_object( $reader)) {
1098                  $reader = &$this->loadModule('Reader', $reader);
1099                  if (patErrorManager::isError($reader)) {
1100                      return $reader;
1101                  }
1102              }
1103  
1104              if ($reader->isInUse()) {
1105                  $reader = &$this->loadModule( 'Reader', $reader->getName(), array(), true);
1106                  if( patErrorManager::isError( $reader ) ) {
1107                      return $reader;
1108                  }
1109              }
1110  
1111              $reader->setOptions($options);
1112  
1113              /**
1114               * set the root attributes
1115               */
1116              if( !is_null( $parseInto ) )
1117              {
1118                  $attributes = $this->getAttributes( $parseInto );
1119                  if( !patErrorManager::isError( $attributes ) )
1120                  {
1121                      $reader->setRootAttributes( $attributes );
1122                  }
1123              }
1124  
1125              $templates    =    $reader->readTemplates( $input );
1126  
1127              /**
1128               * check for error returned from reader
1129               */
1130              if( patErrorManager::isError( $templates ) )
1131                  return $templates;
1132  
1133              /**
1134               * store the
1135               */
1136              if( $this->_tmplCache !== null )
1137              {
1138                  $this->_tmplCache->write( $key, $templates );
1139              }
1140          }
1141  
1142          /**
1143           * traverse all templates
1144           */
1145          foreach( $templates as $name => $spec )
1146          {
1147  
1148              /**
1149               * root template
1150               */
1151              if( $name == '__ptroot' )
1152              {
1153                  if( $parseInto === false )
1154                  {
1155                      continue;
1156                  }
1157                  if( !in_array( $parseInto, $this->_templateList ) )
1158                      continue;
1159  
1160                  $spec['loaded']        = true;
1161                  $spec['attributes']    = $this->_templates[$parseInto]['attributes'];
1162                  $name    =    $parseInto;
1163              }
1164              else
1165              {
1166                  /**
1167                   * store the name
1168                   */
1169                  array_push( $this->_templateList, $name );
1170              }
1171  
1172              /**
1173               * if this is the first template that has been loaded
1174               * set it as the root template
1175               */
1176              if( $this->_root === null && is_null( $parseInto ) && isset( $spec['isRoot'] ) && $spec['isRoot'] == true )
1177              {
1178                  $this->_root = $name;
1179              }
1180  
1181              /**
1182               * set some default values
1183               */
1184              $spec['iteration']            =    0;
1185              $spec['lastMode']            =    'w';
1186              $spec['result']                =    '';
1187              $spec['modifyVars']            =    array();
1188              $spec['copyVars']            =    array();
1189              $spec['defaultVars']        =    array();
1190  
1191              /**
1192               * store the template
1193               */
1194              $this->_templates[$name]    =    $spec;
1195  
1196              $this->prepareTemplate( $name );
1197  
1198              /**
1199               * store the default values of the variables
1200               */
1201              foreach( $spec['varspecs'] as $varname => $varspec )
1202              {
1203                  if (isset($varspec['modifier'])) {
1204                      $this->_templates[$name]['modifyVars'][$varname] = $varspec['modifier'];
1205                  }
1206  
1207                  if( isset( $varspec['copyfrom'] ) )
1208                  {
1209                      $this->_templates[$name]['copyVars'][$varname] = $varspec['copyfrom'];
1210                  }
1211  
1212                  if( !isset( $varspec['default'] ) )
1213                      continue;
1214  
1215                  $this->_templates[$name]['defaultVars'][$varname] = $varspec['default'];
1216  
1217                  if( !is_null( $this->getVar( $name, $varname ) ) )
1218                      continue;
1219  
1220                  $this->addVar( $name, $varname, $varspec['default'] );
1221              }
1222  
1223              unset($this->_templates[$name]['varspecs']);
1224  
1225              /**
1226               * autoload the template
1227               *
1228               * Some error management is needed here...
1229               */
1230              if( isset( $this->_templates[$name]['attributes']['src'] ) && $this->_templates[$name]['attributes']['autoload'] == 'on' )
1231              {
1232                  if( $this->_templates[$name]['loaded'] !== true )
1233                  {
1234                      if( $this->_templates[$name]['attributes']['parse'] == 'on' )
1235                      {
1236                          $this->readTemplatesFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], $options, $name );
1237                      }
1238                      else
1239                      {
1240                          $this->loadTemplateFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], null, $name );
1241                      }
1242                      $this->_templates[$name]['loaded']    =    true;
1243                  }
1244              }
1245          }
1246  
1247          return true;
1248      }
1249  
1250      /**
1251      * load from template cache
1252      *
1253      * @access    private
1254      * @param    string    name of the input (filename, shm segment, etc.)
1255      * @param    string    driver that is used as reader, you may also pass a Reader object
1256      * @param    array    options for the reader
1257      * @param    string    cache key
1258      * @return    array|boolean    either an array containing the templates, or false
1259      */
1260  	function _loadTemplatesFromCache( $input, &$reader, $options, $key )
1261      {
1262          if( is_object( $reader ) )
1263              $statName   =   $reader->getName();
1264          else
1265              $statName    =    $reader;
1266  
1267          $stat    =    &$this->loadModule( 'Stat', $statName );
1268          $stat->setOptions( $options );
1269  
1270          /**
1271           * get modification time
1272           */
1273          $modTime   = $stat->getModificationTime( $input );
1274          $templates = $this->_tmplCache->load( $key, $modTime );
1275  
1276          return $templates;
1277      }
1278  
1279      /**
1280      * open any input and load content into template
1281      *
1282      * @access    public
1283      * @param    string    name of the input (filename, shm segment, etc.)
1284      * @param    string    driver that is used as reader
1285      * @param    string    name of the template that should be used as a container,
1286      * @return    boolean    true, if the template could be parsed, false otherwise
1287      */
1288  	function loadTemplateFromInput( $input, $reader = 'File', $options = null, $parseInto = false )
1289      {
1290          if( is_array( $options ) )
1291              $options = array_merge( $this->_options, $options );
1292          else
1293              $options = $this->_options;
1294  
1295          if( !is_null( $parseInto ) )
1296              $parseInto    =    strtolower( $parseInto );
1297  
1298          $reader    = &$this->loadModule( 'Reader', $reader );
1299          if( patErrorManager::isError( $reader ) )
1300          {
1301              return $reader;
1302          }
1303          $reader->setOptions($options);
1304  
1305          $result    = $reader->loadTemplate( $input );
1306  
1307          if( patErrorManager::isError( $result ) )
1308          {
1309              return $result;
1310          }
1311  
1312          $this->_templates[$parseInto]['content'] .= $result;
1313          $this->_templates[$parseInto]['loaded']   = true;
1314          return true;
1315      }
1316  
1317      /**
1318      * load a template that had autoload="off"
1319      *
1320      * This is needed, if you change the source of a template and want to
1321      * load it, after changing the attribute.
1322      *
1323      * @access    public
1324      * @param    string        template name
1325      * @return    boolean        true, if template could be loaded
1326      */
1327  	function  loadTemplate( $template )
1328      {
1329          $template = strtolower( $template );
1330          if( !isset( $this->_templates[$template] ) )
1331          {
1332              return    patErrorManager::raiseWarning(
1333                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
1334                                                      "Template '$template' does not exist."
1335                                                  );
1336          }
1337  
1338          if( $this->_templates[$template]['loaded'] === true )
1339              return true;
1340  
1341          if( $this->_templates[$template]['attributes']['parse'] == 'on' )
1342          {
1343              return $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
1344          }
1345          else
1346          {
1347              return $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
1348          }
1349      }
1350  
1351      /**
1352      * loads a patTemplate module
1353      *
1354      * Modules are located in the patTemplate folder and include:
1355      * - Readers
1356      * - Caches
1357      * - Variable Modifiers
1358      * - Filters
1359      * - Functions
1360      * - Stats
1361      *
1362      * @access    public
1363      * @param    string    moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter)
1364      * @param    string    moduleName
1365      * @param    array    parameters for the module
1366      * @return    object
1367      */
1368      function &loadModule( $moduleType, $moduleName, $params = array(), $new = false )
1369      {
1370          if( !isset( $this->_modules[$moduleType] ) )
1371              $this->_modules[$moduleType]    =    array();
1372  
1373          $sig = md5( $moduleName . serialize( $params ) );
1374  
1375          if( isset( $this->_modules[$moduleType][$sig] ) && $new === false ) {
1376              return    $this->_modules[$moduleType][$sig];
1377          }
1378  
1379          if( !class_exists( 'patTemplate_Module' ) )
1380          {
1381              $file    =    sprintf( "%s/Module.php", $this->getIncludePath() );
1382              if( !file_exists( $file ) or !include_once $file )
1383                  return    patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, 'Could not load module base class.' );
1384          }
1385  
1386          $baseClass    =    'patTemplate_' . $moduleType;
1387          if( !class_exists( $baseClass ) )
1388          {
1389              $baseFile    =    sprintf( "%s/%s.php", $this->getIncludePath(), $moduleType );
1390              if( !file_exists( $baseFile ) or !include_once $baseFile )
1391                  return    patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, "Could not load base class for $moduleType ($baseFile)." );
1392          }
1393  
1394          $moduleClass    =    'patTemplate_' . $moduleType . '_' .$moduleName;
1395          if( !class_exists( $moduleClass ) )
1396          {
1397              if( isset( $this->_moduleDirs[$moduleType] ) )
1398                  $dirs = $this->_moduleDirs[$moduleType];
1399              else
1400                  $dirs = array();
1401              array_push( $dirs, $this->getIncludePath() .'/'. $moduleType );
1402  
1403              $found = false;
1404              foreach( $dirs as $dir )
1405              {
1406                  $moduleFile    = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) );
1407  
1408                  if ( file_exists( $moduleFile ) and include_once $moduleFile) {
1409                      $found = true;
1410                      break;
1411                  }
1412              }
1413  
1414              if( !$found ) {
1415                  return    patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Could not load module $moduleClass ($moduleFile)." );
1416              }
1417          }
1418  
1419          if( !class_exists( $moduleClass ) )
1420          {
1421              return    patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Module file $moduleFile does not contain class $moduleClass." );
1422          }
1423  
1424          $this->_modules[$moduleType][$sig]    = new $moduleClass;
1425          if( method_exists( $this->_modules[$moduleType][$sig], 'setTemplateReference' ) )
1426          {
1427              $this->_modules[$moduleType][$sig]->setTemplateReference( $this );
1428          }
1429  
1430          $this->_modules[$moduleType][$sig]->setParams( $params );
1431  
1432          return $this->_modules[$moduleType][$sig];
1433      }
1434  
1435      /**
1436      * checks whether a module exists.
1437      *
1438      * Modules are located in the patTemplate folder and include:
1439      * - Readers
1440      * - Caches
1441      * - Variable Modifiers
1442      * - Filters
1443      * - Functions
1444      * - Stats
1445      *
1446      * @access    public
1447      * @param    string    moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter)
1448      * @param    string    moduleName
1449      * @return    boolean
1450      */
1451  	function moduleExists( $moduleType, $moduleName )
1452      {
1453          // !!!JOOMLA VARIATION!!!
1454          // cache checks on files
1455          static $paths;
1456  
1457          if (!$paths)
1458          {
1459              $paths = array();
1460          }
1461  
1462          if (isset($this->_moduleDirs[$moduleType])) {
1463              $dirs = $this->_moduleDirs[$moduleType];
1464          } else {
1465              $dirs = array();
1466          }
1467          array_push($dirs, $this->getIncludePath() .'/'. $moduleType);
1468  
1469          foreach ($dirs as $dir) {
1470              $moduleFile    = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) );
1471              if (!isset( $paths[$moduleFile] ))
1472              {
1473                  if (!file_exists($moduleFile)) {
1474                      $paths[$moduleFile] = false;
1475                  }
1476                  else if (!is_readable($moduleFile)) {
1477                      $paths[$moduleFile] = false;
1478                  }
1479                  else
1480                  {
1481                      $paths[$moduleFile] = true;
1482                  }
1483              }
1484  
1485              if (!$paths[$moduleFile]) {
1486                  continue;
1487              }
1488              return true;
1489          }
1490          return false;
1491      }
1492  
1493      /**
1494      * parses a template
1495      *
1496      * Parses a template and stores the parsed content.
1497      * mode can be "w" for write (delete already parsed content) or "a" for append (appends the
1498      * new parsed content to the already parsed content)
1499      *
1500      * @access    public
1501      * @param    string    name of the template
1502      * @param    string    mode for the parsing
1503      */
1504  	function parseTemplate( $template, $mode = 'w' )
1505      {
1506          $template = strtolower($template);
1507  
1508          if (!isset($this->_templates[$template])) {
1509              return    patErrorManager::raiseWarning(
1510                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
1511                                                      "Template '$template' does not exist."
1512                                                  );
1513          }
1514  
1515          /**
1516           * template is not visible
1517           */
1518          if ($this->_templates[$template]['attributes']['visibility'] == 'hidden') {
1519              $this->_templates[$template]['result']    =    '';
1520              $this->_templates[$template]['parsed']    =    true;
1521              return true;
1522          }
1523  
1524          /**
1525           * check, if the template has been loaded
1526           * and load it if necessary.
1527           */
1528          if ($this->_templates[$template]['loaded'] !== true) {
1529              if ($this->_templates[$template]['attributes']['parse'] == 'on') {
1530                  $result = $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
1531              } else {
1532                  $result = $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
1533              }
1534              if (patErrorManager::isError($result)) {
1535                  return $result;
1536              }
1537          }
1538  
1539          /**
1540           * check for autoclear
1541           */
1542          if(
1543              isset( $this->_templates[$template]['attributes']['autoclear'] ) &&
1544              $this->_templates[$template]['attributes']['autoclear'] == 'yes' &&
1545              $mode === 'w' &&
1546              $this->_templates[$template]['lastMode'] != 'a'
1547            ) {
1548              $this->_templates[$template]['parsed']    = false;
1549          }
1550  
1551          /**
1552           * template has been parsed and mode is not 'append'
1553           */
1554          if ($this->_templates[$template]['parsed'] === true && $mode === 'w') {
1555              return true;
1556          }
1557  
1558          $this->_templates[$template]['lastMode'] = $mode;
1559  
1560          $this->_initTemplate( $template );
1561  
1562          if (!isset($this->_vars[$template]['rows'])) {
1563              $this->_vars[$template]['rows']    =    array();
1564          }
1565          $loop = count( $this->_vars[$template]['rows'] );
1566  
1567          /**
1568           * loop at least one times
1569           */
1570          if ($loop < 1) {
1571              $loop = 1;
1572          }
1573  
1574          if (isset($this->_templates[$template]['attributes']['maxloop'])) {
1575              $loop = ceil( $loop / $this->_templates[$template]['attributes']['maxloop'] ) * $this->_templates[$template]['attributes']['maxloop'];
1576          }
1577  
1578          $this->_templates[$template]['loop'] = max( $this->_templates[$template]['attributes']['loop'], $loop );
1579  
1580          $start = 0;
1581          if (isset($this->_templates[$template]['attributes']['limit'])) {
1582              $p = strpos( $this->_templates[$template]['attributes']['limit'], ',' );
1583              if ($p === false) {
1584                  $this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $this->_templates[$template]['attributes']['limit'] );
1585                  $start = 0;
1586              } else {
1587                  $start = substr( $this->_templates[$template]['attributes']['limit'], 0, $p );
1588                  $end   = substr( $this->_templates[$template]['attributes']['limit'], $p+1 )+$start;
1589  
1590                  $this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $end );
1591              }
1592          }
1593  
1594          /**
1595           * template should be cleared before parsing
1596           */
1597          if ($mode == 'w') {
1598              $this->_templates[$template]['result']    = '';
1599              $this->_templates[$template]['iteration'] = $start;
1600          }
1601  
1602          $loopCount = 0;
1603          for ($i = $start; $i < $this->_templates[$template]['loop']; $i++) {
1604              $finished  = false;
1605  
1606              unset( $this->_templates[$template]['vars'] );
1607  
1608              /**
1609               * fetch the variables
1610               */
1611              $this->_fetchVariables( $template );
1612  
1613              /**
1614               * fetch the template
1615               */
1616              $result = $this->_fetchTemplate($template);
1617  
1618              if ($result === false) {
1619                  $this->_templates[$template]['iteration']++;
1620                  continue;
1621              }
1622  
1623              /**
1624               * parse
1625               */
1626              $this->_parseVariables( $template );
1627              $result = $this->_parseDependencies( $template );
1628              if (patErrorManager::isError($result)) {
1629                  return $result;
1630              }
1631  
1632              /**
1633               * store result
1634               */
1635              $this->_templates[$template]['result'] .= $this->_templates[$template]['work'];
1636  
1637              $this->_templates[$template]['iteration']++;
1638  
1639              ++$loopCount;
1640  
1641              /**
1642               * check for maximum loops
1643               */
1644              if (isset($this->_templates[$template]['attributes']['maxloop'])) {
1645                  if ($loopCount == $this->_templates[$template]['attributes']['maxloop'] && $i < ($loop-1)) {
1646                      $loopCount = 0;
1647                      $finished  = true;
1648                      $this->_templates[$template]['parsed'] = true;
1649                      $this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a' );
1650                      $this->_templates[$template]['parsed'] = false;
1651                      $this->_templates[$template]['result'] = '';
1652                  }
1653              }
1654          }
1655  
1656          if (!$finished && isset($this->_templates[$template]['attributes']['maxloop'])) {
1657              $this->_templates[$template]['parsed'] = true;
1658              $this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a', false );
1659              $this->_templates[$template]['parsed'] = false;
1660              $this->_templates[$template]['result'] = '';
1661              $this->_templates[$this->_templates[$template]['attributes']['parent']]['work'] = '';
1662          }
1663  
1664          $this->_parseGlobals($template);
1665  
1666          $this->_handleUnusedVars($template);
1667  
1668          $this->_templates[$template]['parsed']    = true;
1669  
1670          if (isset($this->_templates[$template]['attributes']['autoclear']) && $this->_templates[$template]['attributes']['autoclear'] == 'yes') {
1671              $this->_vars[$template] = array(
1672                                              'scalar' => array(),
1673                                              'rows'   => array()
1674                                              );
1675          }
1676  
1677          if (isset($this->_templates[$template]['attributes']['outputfilter'])) {
1678              if (is_object($this->_templates[$template]['attributes']['outputfilter'])) {
1679                  $filter = &$this->_templates[$template]['attributes']['outputfilter'];
1680              } else {
1681                  $filter = &$this->loadModule('OutputFilter', $this->_templates[$template]['attributes']['outputfilter']);
1682              }
1683  
1684              if (patErrorManager::isError($filter)) {
1685                  return $filter;
1686              }
1687  
1688              $this->_templates[$template]['result'] = $filter->apply($this->_templates[$template]['result']);
1689          }
1690          return true;
1691      }
1692  
1693      /**
1694      * Initialize a template
1695      *
1696      * This method checks the variable specifications and
1697      * copys variables from other templates.
1698      *
1699      * @access    private
1700      * @param    string    name of the template
1701      * @return    boolean    true on success
1702      */
1703  	function _initTemplate( $template )
1704      {
1705          foreach( $this->_templates[$template]['copyVars'] as $dest => $src )
1706          {
1707              /**
1708               * copy from the same template
1709               */
1710              if( !is_array( $src ) )
1711              {
1712                  $srcTemplate = $template;
1713                  $srcVar      = $src;
1714              }
1715              else
1716              {
1717                  $srcTemplate = $src[0];
1718                  $srcVar      = $src[1];
1719              }
1720  
1721              $copied = false;
1722  
1723              /**
1724               * copy from another template
1725               */
1726              if( isset( $this->_vars[$srcTemplate] ) )
1727              {
1728                  if( isset( $this->_vars[$srcTemplate]['scalar'][$srcVar] ) )
1729                  {
1730                      $this->_vars[$template]['scalar'][$dest] = $this->_vars[$srcTemplate]['scalar'][$srcVar];
1731                      continue;
1732                  }
1733  
1734                  $rows = count( $this->_vars[$srcTemplate]['rows'] );
1735  
1736                  for( $i = 0; $i < $rows; $i++ )
1737                  {
1738                      if( !isset( $this->_vars[$srcTemplate]['rows'][$i][$srcVar] ) )
1739                          continue;
1740                      if( !isset( $this->_vars[$template]['rows'][$i] ) )
1741                          $this->_vars[$template]['rows'][$i] = array();
1742                      $this->_vars[$template]['rows'][$i][$dest] = $this->_vars[$srcTemplate]['rows'][$i][$srcVar];
1743                      $copied = true;
1744                  }
1745              }
1746              if( !$copied && isset( $this->_globals[$srcVar] ))
1747              {
1748                  $this->_vars[$template]['scalar'][$dest] = $this->_globals[$srcVar];
1749              }
1750  
1751          }
1752          return true;
1753      }
1754  
1755      /**
1756      * parse all variables in a template
1757      *
1758      * @access    private
1759      * @param    string
1760      */
1761  	function _parseVariables( $template )
1762      {
1763          /**
1764           * modify variables before parsing
1765           */
1766          $this->_applyModifers($template, $this->_templates[$template]['vars']);
1767  
1768          foreach( $this->_templates[$template]['vars'] as $key => $value )
1769          {
1770              if( is_array( $value ) )
1771              {
1772                  if( count( $this->_templates[$template]['currentDependencies'] ) == 1 )
1773                  {
1774                      $child    =    $this->_templates[$template]['currentDependencies'][0];
1775                  }
1776                  else
1777                  {
1778                      if( isset( $this->_templates[$template]['attributes']['child'] ) )
1779                          $child = $this->_templates[$template]['attributes']['child'];
1780                      else
1781                          continue;
1782                  }
1783  
1784                  $this->setAttribute( $child, 'autoclear', 'yes' );
1785                  $this->addVar( $child, $key, $value );
1786                  continue;
1787              }
1788  
1789              $var  = $this->_startTag.$key.$this->_endTag;
1790              $this->_templates[$template]['work'] = str_replace( $var, $value, $this->_templates[$template]['work'] );
1791          }
1792          return true;
1793      }
1794  
1795      /**
1796      * parse global variables in the template
1797      *
1798      * @access   private
1799      * @param    string      name of the template
1800      * @return   boolean
1801      */
1802  	function _parseGlobals($template)
1803      {
1804          $globalVars = $this->_globals;
1805          $this->_applyModifers($template, $globalVars);
1806  
1807          foreach( $globalVars as $key => $value )
1808          {
1809              if( is_array( $value ) )
1810              {
1811                  continue;
1812              }
1813  
1814              $var  = $this->_startTag.$key.$this->_endTag;
1815              $this->_templates[$template]['result'] = str_replace( $var, $value, $this->_templates[$template]['result'] );
1816          }
1817          return true;
1818      }
1819  
1820      /**
1821      * apply variable modifiers
1822      *
1823      * The variables will be passed by reference.
1824      *
1825      * @access   private
1826      * @param    string      name of the template (use modifiers from this template)
1827      * @param    array       variables to which the modifiers should be applied
1828      * @return   boolean
1829      */
1830  	function _applyModifers($template, &$vars)
1831      {
1832          foreach ($this->_templates[$template]['modifyVars'] as $varname => $modifier) {
1833              if (!isset($vars[$varname])) {
1834                  continue;
1835              }
1836  
1837              if (($modifier['type'] === 'php' || $modifier['type'] === 'auto' ) && is_callable($modifier['mod'])) {
1838                  $vars[$varname] = call_user_func($modifier['mod'], $vars[$varname]);
1839                  continue;
1840              }
1841  
1842              if ($modifier['type'] === 'php') {
1843                  continue;
1844              }
1845  
1846              $mod = &$this->loadModule( 'Modifier', ucfirst( $modifier['mod'] ) );
1847              $vars[$varname] = $mod->modify( $vars[$varname], $modifier['params'] );
1848          }
1849  
1850          // apply the default modifier
1851          if (isset($this->_templates[$template]['attributes']['defaultmodifier'])) {
1852  
1853              $defaultModifier = $this->_templates[$template]['attributes']['defaultmodifier'];
1854              if (is_callable($defaultModifier)) {
1855                  $type = 'php';
1856              } else {
1857                  $type = 'custom';
1858                  $defaultModifier = &$this->loadModule('Modifier', ucfirst($defaultModifier));
1859              }
1860  
1861  
1862              foreach (array_keys($vars) as $varname) {
1863                  if (isset($this->_templates[$template]['modifyVars'][$varname])) {
1864                      continue;
1865                  }
1866                  if ($type === 'php') {
1867                      $vars[$varname] = call_user_func($defaultModifier, $vars[$varname]);
1868                  } else {
1869                      $vars[$varname] = $defaultModifier->modify($vars[$varname], array());
1870                  }
1871              }
1872          }
1873  
1874          return true;
1875      }
1876  
1877      /**
1878      * parse all dependencies in a template
1879      *
1880      * @access    private
1881      * @param    string
1882      */
1883  	function _parseDependencies($template)
1884      {
1885          $countDep    =    count( $this->_templates[$template]['currentDependencies'] );
1886          for ($i = 0; $i < $countDep; $i++) {
1887              $depTemplate = $this->_templates[$template]['currentDependencies'][$i];
1888              if ($depTemplate == $template) {
1889                  return patErrorManager::raiseError(PATTEMPLATE_ERROR_RECURSION, 'You have an error in your template "' . $template . '", which leads to recursion');
1890              }
1891              $this->parseTemplate($depTemplate);
1892              $var    = $this->_startTag.'TMPL:'.strtoupper( $depTemplate) .$this->_endTag;
1893              $this->_templates[$template]['work'] = str_replace( $var, $this->_templates[$depTemplate]['result'], $this->_templates[$template]['work'] );
1894          }
1895          return true;
1896      }
1897  
1898      /**
1899      * fetch plain template
1900      *
1901      * The template content will be stored in the template
1902      * configuration so it can be used by other
1903      * methods.
1904      *
1905      * @access    private
1906      * @param    string    template name
1907      * @return    boolean
1908      */
1909  	function _fetchTemplate( $template )
1910      {
1911          switch( $this->_templates[$template]['attributes']['type'] )
1912          {
1913              /**
1914               * condition template
1915               */
1916              case 'condition':
1917                  $value = $this->_getConditionValue($template, $this->_templates[$template]['attributes']['conditionvar']);
1918                  if ($value === false) {
1919                      $this->_templates[$template]['work']                = '';
1920                      $this->_templates[$template]['currentDependencies']    = array();
1921                  } else {
1922                      $this->_templates[$template]['work']                = $this->_templates[$template]['subtemplates'][$value]['data'];
1923                      $this->_templates[$template]['currentDependencies']    = $this->_templates[$template]['subtemplates'][$value]['dependencies'];
1924                  }
1925                  break;
1926  
1927              /**
1928               * condition template
1929               */
1930              case 'simplecondition':
1931                  foreach( $this->_templates[$template]['attributes']['requiredvars'] as $var )
1932                  {
1933                      // different template scope
1934                      if( $var[0] !== $template ) {
1935                          $this->_fetchVariables($var[0]);
1936                      }
1937                      $value = null;
1938                      // fetch the local variable
1939                      if( isset( $this->_templates[$var[0]]['vars'][$var[1]] )
1940                        && strlen( $this->_templates[$var[0]]['vars'][$var[1]] ) > 0 ) {
1941                         $value = $this->_templates[$var[0]]['vars'][$var[1]];
1942                      }
1943                      if (isset($this->_templates[$template]['attributes']['useglobals'])) {
1944                          if(isset($this->_globals[$var[1]]) && strlen($this->_globals[$var[1]]) > 1) {
1945                              $value = $this->_globals[$var[1]];
1946                          }
1947                      }
1948                      if ($value !== null) {
1949                          if ($var[2] === null) {
1950                              continue;
1951                          } else {
1952                              // Joomla! addition 23-June-2005
1953                              // value wrapped in ## uses regex for comparison
1954                              $condition = $var[2];
1955                              if (substr( $condition, 0, 1 ) == '#' && substr( $condition, -1, 1 ) == '#' ) {
1956                                  if (preg_match( $condition, $value )) {
1957                                      continue;
1958                                  }
1959                              } else if ($condition == $value) {
1960                                  continue;
1961                              }
1962                              /* Pat Original
1963                              if ($var[2] == $value) {
1964                                     continue;
1965                              }
1966                              */
1967                          }
1968                      }
1969  
1970                      $this->_templates[$template]['work']                = '';
1971                      $this->_templates[$template]['currentDependencies']    = array();
1972                      break 2;
1973                  }
1974                  $this->_templates[$template]['work']                 = $this->_templates[$template]['content'];
1975                  $this->_templates[$template]['currentDependencies']    = $this->_templates[$template]['dependencies'];
1976                  break;
1977  
1978              /**
1979               * modulo template
1980               */
1981              case 'modulo':
1982                  // check for empty template
1983  
1984                  if ($this->_hasVariables($template)) {
1985                      $value = (string)($this->_templates[$template]['iteration'] + 1 ) % $this->_templates[$template]['attributes']['modulo'];
1986                  } else {
1987                      $value = '__empty';
1988                  }
1989  
1990                  $value = $this->_getConditionValue($template, $value, false);
1991                  if ($value === false) {
1992                      $this->_templates[$template]['work']                = '';
1993                      $this->_templates[$template]['currentDependencies']    = array();
1994                  } else {
1995                      $this->_templates[$template]['work']                = $this->_templates[$template]['subtemplates'][$value]['data'];
1996                      $this->_templates[$template]['currentDependencies']    = $this->_templates[$template]['subtemplates'][$value]['dependencies'];
1997                  }
1998                  break;
1999  
2000              /**
2001               * standard template
2002               */
2003              default:
2004                  $this->_templates[$template]['work']                 =    $this->_templates[$template]['content'];
2005                  $this->_templates[$template]['currentDependencies']    =    $this->_templates[$template]['dependencies'];
2006                  break;
2007          }
2008          return true;
2009      }
2010  
2011      /**
2012      * check, whether a template contains variables
2013      *
2014      * @access   private
2015      * @param    string  template name
2016      * @return   boolean
2017      */
2018  	function _hasVariables($template)
2019      {
2020          if (!empty($this->_vars[$template]['scalar'])) {
2021              return true;
2022          }
2023          if (isset($this->_vars[$template]['rows'][$this->_templates[$template]['iteration']])) {
2024              return true;
2025          }
2026          return false;
2027      }
2028  
2029      /**
2030      * fetch the value of a condition variable
2031      *
2032      * _fetchVariables() has to be called before this
2033      * method is being called.
2034      *
2035      * @access    private
2036      * @param    string    template name
2037      * @param    string    condition value
2038      * @param    boolean    flag that indicates whether value is the name of the variable that should be resolved
2039      *
2040      * @todo        split this method into smaller check methods that will be called according to
2041      *            a priority list
2042      */
2043  	function _getConditionValue( $template, $value, $isVar = true )
2044      {
2045          if ($isVar === true) {
2046              if (isset($this->_templates[$template]['attributes']['conditiontmpl'])) {
2047                  $_template = $this->_templates[$template]['attributes']['conditiontmpl'];
2048                  $this->_fetchVariables($_template);
2049              } else {
2050                  $_template = $template;
2051              }
2052  
2053              /**
2054               * get the value from the template variables
2055               */
2056              if (!isset($this->_templates[$_template]['vars'][$value]) || strlen($this->_templates[$_template]['vars'][$value]) === 0) {
2057                  if ($this->_templates[$template]['attributes']['useglobals'] == 'yes' || $this->_templates[$template]['attributes']['useglobals'] == 'useglobals') {
2058                      if (isset( $this->_globals[$value] ) && strlen( $this->_globals[$value] ) > 0) {
2059                          $value = $this->_globals[$value];
2060                      } else {
2061                          $value = '__empty';
2062                      }
2063                  } else {
2064                      $value = '__empty';
2065                  }
2066              } else {
2067                  $value = $this->_templates[$_template]['vars'][$value];
2068              }
2069          } else {
2070              $_template = $template;
2071          }
2072  
2073          // if value is empty and a template for empty has been defined, this
2074          // has priority
2075          if ($value === '__empty' && isset($this->_templates[$template]['subtemplates']['__empty'])) {
2076              return $value;
2077          }
2078  
2079          // only one iteration (but not empty), use the __single condition
2080          if ($value !== '__empty' && $this->_templates[$_template]['loop'] === 1) {
2081              if( isset($this->_templates[$template]['subtemplates']['__single'])) {
2082                  return '__single';
2083              }
2084          } else {
2085  
2086              // is __first?
2087              if( $this->_templates[$_template]['iteration'] == 0 ) {
2088                  if( isset( $this->_templates[$template]['subtemplates']['__first'] ) ) {
2089                      return '__first';
2090                  }
2091              }
2092  
2093              /**
2094               * is __last?
2095               */
2096              if (isset($this->_templates[$_template]['loop'])) {
2097                  $max = $this->_templates[$_template]['loop'] - 1;
2098                  if( $this->_templates[$_template]['iteration'] == $max ) {
2099                      if( isset( $this->_templates[$template]['subtemplates']['__last'] ) ) {
2100                          return '__last';
2101                      }
2102                  }
2103              }
2104          }
2105  
2106          // search for exact match
2107          foreach (array_keys($this->_templates[$template]['subtemplates']) as $key) {
2108              if (isset($this->_templates[$template]['subtemplates'][$key]['attributes']['var'])) {
2109                  $var = $this->_templates[$template]['subtemplates'][$key]['attributes']['var'];
2110                  if (isset($this->_templates[$template]['vars'][$var])) {
2111                      $current = $this->_templates[$template]['vars'][$var];
2112                  } else {
2113                      $current = null;
2114                  }
2115              } else {
2116                  $current = $key;
2117              }
2118  
2119              if ((string)$value === (string)$current) {
2120                  return $key;
2121              }
2122          }
2123  
2124          /**
2125           * is __default?
2126           */
2127          if( isset( $this->_templates[$template]['subtemplates']['__default'] ) ) {
2128              return '__default';
2129          }
2130  
2131          return false;
2132      }
2133  
2134      /**
2135      * fetch variables for a template
2136      *
2137      * The variables will be stored in the template
2138      * configuration so they can be used by other
2139      * methods.
2140      *
2141      * @access    private
2142      * @param    string    template name
2143      * @return    boolean
2144      */
2145  	function _fetchVariables( $template )
2146      {
2147          /**
2148           * variables already have been fetched
2149           */
2150          if (isset($this->_templates[$template]['vars'])) {
2151              return true;
2152          }
2153  
2154          $iteration = $this->_templates[$template]['iteration'];
2155  
2156          $vars = array();
2157          if( isset( $this->_templates[$template]['attributes']['varscope'] ) )
2158          {
2159              if (!is_array($this->_templates[$template]['attributes']['varscope'])) {
2160                  $this->_templates[$template]['attributes']['varscope'] = array($this->_templates[$template]['attributes']['varscope']);
2161              }
2162              foreach ($this->_templates[$template]['attributes']['varscope'] as $scopeTemplate) {
2163                  if ($this->exists($scopeTemplate)) {
2164                      $this->_fetchVariables( $scopeTemplate );
2165                      $vars = array_merge($this->_templates[$scopeTemplate]['vars'], $vars);
2166                  } else {
2167                      patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'Template \''.$scopeTemplate.'\' does not exist, referenced in varscope attribute of template \''.$template.'\'');
2168                  }
2169              }
2170          } else {
2171              $vars    =    array();
2172          }
2173  
2174          /**
2175           * get the scalar variables
2176           */
2177          if( isset( $this->_vars[$template] ) && isset( $this->_vars[$template]['scalar'] ) )
2178          {
2179              $vars = array_merge( $vars, $this->_vars[$template]['scalar'] );
2180          }
2181  
2182          /**
2183           * get the row variables
2184           */
2185          if( isset( $this->_vars[$template]['rows'][$iteration] ) )
2186          {
2187              $vars = array_merge( $vars, $this->_vars[$template]['rows'][$iteration] );
2188          }
2189  
2190          /**
2191           * add some system variables
2192           */
2193          $currentRow                =    $iteration + $this->_templates[$template]['attributes']['rowoffset'];
2194          $vars['PAT_ROW_VAR']    =    $currentRow;
2195  
2196          if( $this->_templates[$template]['attributes']['type'] == 'modulo' )
2197          {
2198              $vars['PAT_MODULO_REP']    =    ceil( $currentRow / $this->_templates[$template]['attributes']['modulo'] );
2199              $vars['PAT_MODULO']        =    ( $this->_templates[$template]['iteration'] + 1 ) % $this->_templates[$template]['attributes']['modulo'];
2200          }
2201  
2202          if( $this->_templates[$template]['attributes']['addsystemvars'] !== false )
2203          {
2204              $vars['PATTEMPLATE_VERSION'] = $this->_systemVars['appVersion'];
2205              $vars['PAT_LOOPS']        =    $this->_templates[$template]['loop'];
2206  
2207              switch ($this->_templates[$template]['attributes']['addsystemvars'])
2208              {
2209                  case 'boolean':
2210                      $trueValue  = 'true';
2211                      $falseValue = 'false';
2212                      break;
2213                  case 'integer':
2214                      $trueValue  = '1';
2215                      $falseValue = '0';
2216                      break;
2217                  default:
2218                      $trueValue  = $this->_templates[$template]['attributes']['addsystemvars'];
2219                      $falseValue = '';
2220                      break;
2221              }
2222  
2223              $vars['PAT_IS_ODD']        = ( $currentRow % 2 == 1 ) ? $trueValue : $falseValue;
2224              $vars['PAT_IS_EVEN']    = ( $currentRow % 2 == 0 ) ? $trueValue : $falseValue;
2225              $vars['PAT_IS_FIRST']    = ( $currentRow == 1 ) ? $trueValue : $falseValue;
2226              $vars['PAT_IS_LAST']    = ( $currentRow == $this->_templates[$template]['loop'] ) ? $trueValue : $falseValue;
2227              $vars['PAT_ROW_TYPE']    = ( $currentRow % 2 == 1 ) ? 'odd' : 'even';
2228          }
2229  
2230          $this->_templates[$template]['vars'] = $vars;
2231          return true;
2232      }
2233  
2234      /**
2235      * handle all unused variables in a template
2236      *
2237      * This is influenced by the 'unusedvars' attribute of the
2238      * template
2239      *
2240      * @access    private
2241      * @param    string
2242      */
2243  	function _handleUnusedVars( $template )
2244      {
2245          $regexp = '/([^\\\])('.$this->_startTag.'[^a-z]+[^\\\]'.$this->_endTag.')/U';
2246  
2247          switch( $this->_templates[$template]['attributes']['unusedvars'] )
2248          {
2249              case 'comment':
2250                  $this->_templates[$template]['result'] = preg_replace( $regexp, '<!-- \\1\\2 -->', $this->_templates[$template]['result'] );
2251                  break;
2252              case 'strip':
2253                  $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1', $this->_templates[$template]['result'] );
2254                  break;
2255              case 'nbsp':
2256                  $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1&nbsp;', $this->_templates[$template]['result'] );
2257                  break;
2258              case 'ignore':
2259                  break;
2260              default:
2261                  $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1'.$this->_templates[$template]['attributes']['unusedvars'], $this->_templates[$template]['result'] );
2262                  break;
2263          }
2264  
2265          // replace quoted variables
2266          $regexp = '/[\\\]'.$this->_startTag.'([^a-z]+)[\\\]'.$this->_endTag.'/U';
2267          $this->_templates[$template]['result'] = preg_replace( $regexp, $this->_startTag.'\\1'.$this->_endTag, $this->_templates[$template]['result'] );
2268  
2269          return true;
2270      }
2271  
2272      /**
2273      * returns a parsed Template
2274      *
2275      * If the template already has been parsed, it just returns the parsed template.
2276      * If the template has not been loaded, it will be loaded.
2277      *
2278      * @access    public
2279      * @param    string     name of the template
2280      * @param    boolean  whether to apply output filters
2281      * @return    string     Content of the parsed template
2282      * @see        displayParsedTemplate()
2283      */
2284  	function getParsedTemplate( $name = null, $applyFilters = false )
2285      {
2286          if (is_null($name)) {
2287              $name = $this->_root;
2288          }
2289  
2290          $name = strtolower( $name );
2291          $result = $this->parseTemplate( $name );
2292  
2293          if (patErrorManager::isError( $result )) {
2294              return $result;
2295          }
2296  
2297          if ($applyFilters === false) {
2298              return $this->_templates[$name]['result'];
2299          }
2300  
2301          $result = $this->_templates[$name]['result'];
2302  
2303          $cnt = count ($this->_outputFilters);
2304          for ($i = 0; $i < $cnt; $i++) {
2305              $result = $this->_outputFilters[$i]->apply( $result );
2306          }
2307  
2308          return $result;
2309      }
2310  
2311      /**
2312      * displays a parsed Template
2313      *
2314      * If the template has not been loaded, it will be loaded.
2315      *
2316      * @see        getParsedTemplate()
2317      * @param    string    name of the template
2318      * @param    boolean  whether to apply output filters
2319      * @return    boolean    true on success
2320      * @access    public
2321      */
2322  	function displayParsedTemplate($name = null, $applyFilters = true)
2323      {
2324          $result = $this->getParsedTemplate($name, $applyFilters);
2325  
2326          /**
2327           * error happened
2328           */
2329          if (patErrorManager::isError($result)) {
2330              return $result;
2331          }
2332  
2333          echo $result;
2334          return true;
2335      }
2336  
2337      /**
2338      * parse a template and push the result into a variable of any other
2339      * template
2340      *
2341      * If the template already has been parsed, it will just be pushed into the variable.
2342      * If the template has not been loaded, it will be loaded.
2343      *
2344      * @access    public
2345      * @param    string    name of the template
2346      * @return    string    Content of the parsed template
2347      * @param    boolean    if set to true, the value will be appended to the value already stored.
2348      * @see        getParsedTemplate()
2349      * @see        addVar()
2350      */
2351  	function parseIntoVar( $srcTmpl, $destTmpl, $var, $append = false )
2352      {
2353          $srcTmpl  =    strtolower( $srcTmpl );
2354          $destTmpl =    strtolower( $destTmpl );
2355          $var      = strtoupper($var);
2356  
2357          $result    =    $this->parseTemplate( $srcTmpl );
2358  
2359          if( patErrorManager::isError( $result ) )
2360              return $result;
2361  
2362          if( $append !== true || !isset( $this->_vars[$destTmpl]['scalar'][$var] ) )
2363              $this->_vars[$destTmpl]['scalar'][$var] = '';
2364  
2365          $this->_vars[$destTmpl]['scalar'][$var] .= $this->_templates[$srcTmpl]['result'];
2366  
2367          return true;
2368      }
2369  
2370      /**
2371      * clears a parsed Template
2372      *
2373      * Parsed Content, variables and the loop attribute are cleared
2374      *
2375      * If you will not be using this template anymore, then you should
2376      * call freeTemplate()
2377      *
2378      * @access    public
2379      * @param    string    name of the template
2380      * @param    boolean        set this to true to clear all child templates, too
2381      * @see        clearAllTemplates()
2382      * @see        freeTemplate()
2383      */
2384  	function clearTemplate( $name, $recursive = false )
2385      {
2386          $name    =    strtolower( $name );
2387          $this->_templates[$name]['parsed']        =    false;
2388          $this->_templates[$name]['work']        =    '';
2389          $this->_templates[$name]['iteration']    =    0;
2390          $this->_templates[$name]['result']        =    '';
2391          $this->_vars[$name]                        =    array(
2392                                                          'scalar'    =>    array(),
2393                                                          'rows'        =>    array()
2394                                                      );
2395  
2396          if (!empty($this->_templates[$name]['defaultVars'])) {
2397              foreach ($this->_templates[$name]['defaultVars'] as $varname => $value) {
2398                  $this->addVar($name, $varname, $value);
2399              }
2400          }
2401  
2402          /**
2403           * clear child templates as well
2404           */
2405          if( $recursive === true )
2406          {
2407              $deps = $this->_getDependencies( $name );
2408              foreach( $deps as $dep )
2409              {
2410                  $this->clearTemplate( $dep, true );
2411              }
2412          }
2413          return true;
2414      }
2415  
2416      /**
2417      * clears all templates
2418      *
2419      * @access    public
2420      * @uses        clearTemplate()
2421      */
2422  	function clearAllTemplates()
2423      {
2424          $templates    =    array_keys( $this->_templates );
2425          $cnt        =    count( $templates );
2426          for( $i = 0; $i < $cnt; $i++ )
2427          {
2428              $this->clearTemplate( $templates[$i] );
2429          }
2430          return true;
2431      }
2432  
2433      /**
2434      * frees a template
2435      *
2436      * All memory consumed by the template
2437      * will be freed.
2438      *
2439      * @access    public
2440      * @param    string    name of the template
2441      * @param    boolean    clear dependencies of the template
2442      * @see        freeAllTemplates()
2443      */
2444  	function freeTemplate( $name, $recursive = false )
2445      {
2446          $name    =    strtolower( $name );
2447          $key = array_search( $name, $this->_templateList );
2448          if( $key === false )
2449          {
2450              return    patErrorManager::raiseWarning(
2451                                                      PATTEMPLATE_WARNING_NO_TEMPLATE,
2452                                                      "Template '$name' does not exist."
2453                                                  );
2454          }
2455  
2456          unset( $this->_templateList[$key] );
2457          $this->_templateList = array_values( $this->_templateList );
2458  
2459          /**
2460           * free child templates as well
2461           */
2462          if( $recursive === true )
2463          {
2464              $deps = $this->_getDependencies( $name );
2465              foreach( $deps as $dep )
2466              {
2467                  $this->freeTemplate( $dep, true );
2468              }
2469          }
2470  
2471          unset( $this->_templates[$name] );
2472          unset( $this->_vars[$name] );
2473          if (isset($this->_discoveredPlaceholders[$name])) {
2474              unset($this->_discoveredPlaceholders[$name]);
2475          }
2476  
2477          return true;
2478      }
2479  
2480      /**
2481      * frees all templates
2482      *
2483      * All memory consumed by the templates
2484      * will be freed.
2485      *
2486      * @access    public
2487      * @see        freeTemplate()
2488      */
2489  	function freeAllTemplates()
2490      {
2491          $this->_templates     = array();
2492          $this->_vars         = array();
2493          $this->_templateList = array();
2494      }
2495  
2496      /**
2497      * get _all_ dependencies of a template,
2498      * regardless of the subtemplates
2499      *
2500      * @access    private
2501      * @param    string    template name
2502      * @return    array    list of all subtemplates
2503      */
2504  	function _getDependencies( $template )
2505      {
2506          $deps = array();
2507          if( isset( $this->_templates[$template]['dependencies'] ) )
2508              $deps = $this->_templates[$template]['dependencies'];
2509  
2510          if( isset( $this->_templates[$template]['subtemplates'] ) )
2511          {
2512              foreach( $this->_templates[$template]['subtemplates'] as $sub )
2513              {
2514                  if( isset( $sub['dependencies'] ) )
2515                      $deps = array_merge( $deps, $sub['dependencies'] );
2516              }
2517          }
2518          $deps = array_unique( $deps );
2519          return $deps;
2520      }
2521  
2522      /**
2523      * Displays useful information about all or named templates
2524      *
2525      * This method breaks BC, as it now awaits an array instead of
2526      * unlimited parameters.
2527      *
2528      * @param    mixed    array of templates that should be dumped, or null if you
2529      *                    want all templates to be dumped
2530      * @param    string    dumper
2531      * @access    public
2532      */
2533  	function dump( $restrict = null, $dumper = 'Html' )
2534      {
2535          if( is_string( $restrict ) )
2536              $restrict = array( $restrict );
2537  
2538          $dumper    =    &$this->loadModule( 'Dump', $dumper );
2539  
2540          if( patErrorManager::isError( $dumper ) )
2541          {
2542              return    $dumper;
2543          }
2544  
2545          if( is_null( $restrict ) )
2546          {
2547              $templates = $this->_templates;
2548              $vars      = $this->_vars;
2549          }
2550          else
2551          {
2552              $restrict = array_map( 'strtolower', $restrict );
2553  
2554              $templates = array();
2555              $vars      = array();
2556  
2557              foreach( $this->_templates as $name => $spec )
2558              {
2559                  if( !in_array( $name, $restrict ) )
2560                      continue;
2561                  $templates[$name] = $spec;
2562                  $vars[$name]      = $this->_vars[$name];
2563              }
2564          }
2565  
2566          $dumper->displayHeader();
2567          $dumper->dumpGlobals( $this->_globals );
2568          $dumper->dumpTemplates( $templates, $vars );
2569          $dumper->displayFooter();
2570  
2571          return    true;
2572      }
2573  
2574      /**
2575      * get the include path
2576      *
2577      * @access    public
2578      * @return   string
2579      */
2580  	function getIncludePath()
2581      {
2582          return    PATTEMPLATE_INCLUDE_PATH;
2583      }
2584  
2585      /**
2586      * apply input filters that have been set
2587      *
2588      * This is being called by the readers.
2589      *
2590      * @access    public
2591      * @param    string        template
2592      * @return    string        filtered templeta
2593      */
2594  	function applyInputFilters( $template )
2595      {
2596          $cnt = count( $this->_inputFilters );
2597          for( $i = 0; $i < $cnt; $i++ )
2598          {
2599              $template = $this->_inputFilters[$i]->apply( $template );
2600          }
2601          return $template;
2602      }
2603  
2604      /**
2605      * checks, whether a placeholder exists in a template
2606      *
2607      * @access   public
2608      * @param    string      name of the placeholder
2609      * @param    string      name of the template
2610      * @param    boolean     whether to use the cached result of a previous call
2611      */
2612  	function placeholderExists($placeholder, $tmpl, $cached = true)
2613      {
2614          $tmpl = strtolower($tmpl);
2615          $placeholder = strtoupper($placeholder);
2616  
2617          if (!$this->exists($tmpl)) {
2618              return false;
2619          }
2620  
2621          if ($cached === true) {
2622              if (isset($this->_discoveredPlaceholders[$tmpl]) && isset($this->_discoveredPlaceholders[$tmpl][$placeholder])) {
2623                  return $this->_discoveredPlaceholders[$tmpl][$placeholder];
2624              }
2625          }
2626  
2627          if (isset($this->_templates[$tmpl]['subtemplates'])) {
2628              $content = '';
2629              foreach ($this->_templates[$tmpl]['subtemplates'] as $temp) {
2630                  if (!isset($temp['data'])) {
2631                      continue;
2632                  }
2633                  $content .= $temp['data'];
2634              }
2635          } else {
2636              $content = $this->_templates[$tmpl]['content'];
2637          }
2638  
2639          $search = $this->_startTag . $placeholder . $this->_endTag;
2640          if (strstr($content, $search) !== false) {
2641              $this->_discoveredPlaceholders[$tmpl][$placeholder] = true;
2642              return true;
2643          }
2644          $this->_discoveredPlaceholders[$tmpl][$placeholder] = false;
2645          return false;
2646      }
2647  
2648      /**
2649      * Convert the template to its string representation.
2650      *
2651      * This method allows you to just echo the patTemplate
2652      * object in order to display the template.
2653      *
2654      * Requires PHP5
2655      *
2656      * <code>
2657      * $tmpl = new patTemplate();
2658      * $tmpl->readTemplatesFromFile( 'myfile.tmpl' );
2659      * echo $tmpl;
2660      * </code>
2661      *
2662      * @access    private
2663      * @return    string
2664      */
2665  	function __toString()
2666      {
2667          return $this->getParsedTemplate();
2668      }
2669  }
2670  ?>


Generated: Wed Mar 28 15:54:07 2012 Cross-referenced by PHPXref 0.7.1