Support Joomla!

Joomla! 1.5 Documentation

Packages

Package: patTemplate

Developer Network License

The Joomla! Developer Network content is © copyright 2006 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution- NonCommercial- ShareAlike 2.5
Source code for file /pattemplate/patTemplate.php

Documentation is available at patTemplate.php

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

Documentation generated on Mon, 05 Mar 2007 21:16:22 +0000 by phpDocumentor 1.3.1