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/Reader.php

Documentation is available at Reader.php

  1. <?PHP
  2. /**
  3.  * Base class for patTemplate readers
  4.  *
  5.  * $Id: Reader.php 47 2005-09-15 02:55:27Z rhuk $
  6.  *
  7.  * This class is able to parse patTemplate tags from any string you hand it over
  8.  * It will emulate some kind of SAX parsing by calling start-, end- and CData-handlers.
  9.  *
  10.  * @package        patTemplate
  11.  * @subpackage    Readers
  12.  * @author        Stephan Schmidt <[email protected]>
  13.  */
  14.  
  15. // Check to ensure this file is within the rest of the framework
  16. defined('JPATH_BASE'or die();
  17.  
  18. /**
  19.  * No input
  20.  */
  21. define'PATTEMPLATE_READER_ERROR_NO_INPUT'6000 );
  22.  
  23. /**
  24.  * Unknown tag
  25.  */
  26. define'PATTEMPLATE_READER_ERROR_UNKNOWN_TAG'6001 );
  27.  
  28. /**
  29.  * Invalid tag (missing attribute)
  30.  */
  31. define'PATTEMPLATE_READER_ERROR_INVALID_TAG'6002 );
  32.  
  33. /**
  34.  * Closing tag is missing
  35.  */
  36. define'PATTEMPLATE_READER_ERROR_NO_CLOSING_TAG'6003 );
  37.  
  38. /**
  39.  * Invalid closing tag
  40.  */
  41. define'PATTEMPLATE_READER_ERROR_INVALID_CLOSING_TAG'6004 );
  42.  
  43. /**
  44.  * Invalid condition specified
  45.  */
  46. define'PATTEMPLATE_READER_ERROR_INVALID_CONDITION'6005 );
  47.  
  48. /**
  49.  * No name has been specified
  50.  */
  51. define'PATTEMPLATE_READER_ERROR_NO_NAME_SPECIFIED'6010 );
  52.  
  53. /**
  54.  * CData in a conditional template
  55.  */
  56. define'PATTEMPLATE_READER_NOTICE_INVALID_CDATA_SECTION'6050 );
  57.  
  58. /**
  59.  * template already exists
  60.  */
  61. define'PATTEMPLATE_READER_NOTICE_TEMPLATE_EXISTS'6051 );
  62.  
  63. /**
  64.  * Base class for patTemplate readers
  65.  *
  66.  * This class is able to parse patTemplate tags from any string you hand it over
  67.  * It will emulate some kind of SAX parsing by calling start-, end- and CData-handlers.
  68.  *
  69.  * @abstract
  70.  * @package        patTemplate
  71.  * @subpackage    Readers
  72.  * @author        Stephan Schmidt <[email protected]>
  73.  */
  74. {
  75.    /**
  76.     * reference to the patTemplate object that instantiated the module
  77.     *
  78.     * @access    protected
  79.     * @var    object 
  80.     */
  81.     var    $_tmpl;
  82.  
  83.    /**
  84.     * stack for all open elements
  85.     * @access    private
  86.     * @var    array 
  87.     */
  88.     var    $_elStack;
  89.  
  90.    /**
  91.     * stack for all open templates
  92.     * @access    private
  93.     * @var    array 
  94.     */
  95.     var    $_tmplStack;
  96.  
  97.    /**
  98.     * character data
  99.     * @access    private
  100.     * @var    array 
  101.     */
  102.     var    $_data;
  103.  
  104.    /**
  105.     * tag depth
  106.     * @access    private
  107.     * @var    integer 
  108.     */
  109.     var    $_depth;
  110.  
  111.    /**
  112.        * templates that have been found
  113.     * @access    protected
  114.     * @var        array 
  115.     */
  116.     var $_templates    =    array();
  117.  
  118.    /**
  119.        * path to the template
  120.     * @access    protected
  121.     * @var        array 
  122.     */
  123.     var $_path    =    array();
  124.  
  125.    /**
  126.     * start tag for variables
  127.     * @access    private
  128.     * @var        string 
  129.     */
  130.     var    $_startTag;
  131.  
  132.    /**
  133.     * end tag for variables
  134.     * @access    private
  135.     * @var        string 
  136.     */
  137.     var    $_endTag;
  138.  
  139.    /**
  140.     * default attributes
  141.     *
  142.     * @access    private
  143.     * @var        array 
  144.     */
  145.     var    $_defaultAtts    =    array();
  146.  
  147.    /**
  148.     * root attributes
  149.     *
  150.     * This is used when reading the template content
  151.     * from an external file.
  152.     *
  153.     * @access    private
  154.     * @var        array 
  155.     */
  156.     var    $_rootAtts    =    array();
  157.  
  158.    /**
  159.     * inherit attributes
  160.     *
  161.     * @access    private
  162.     * @var        array 
  163.     */
  164.     var    $_inheritAtts    =    array();
  165.  
  166.    /**
  167.     * name of the first template that has been found
  168.     *
  169.     * @access    private
  170.     * @var        string 
  171.     */
  172.     var    $_root null;
  173.  
  174.    /**
  175.     * all data that has been processed
  176.     *
  177.     * @access    private
  178.     * @var        string 
  179.     */
  180.     var    $_processedData null;
  181.  
  182.    /**
  183.     * current input
  184.     *
  185.     * @access    private
  186.     * @var        string 
  187.     */
  188.     var    $_currentInput null;
  189.  
  190.    /**
  191.     * all loaded functions
  192.     *
  193.     * @access    private
  194.     * @var        array 
  195.     */
  196.     var    $_functions    =    array();
  197.  
  198.    /**
  199.     * function aliases
  200.     *
  201.     * @access   private
  202.     * @var      array 
  203.     */
  204.     var $_funcAliases array();
  205.  
  206.    /**
  207.     * options
  208.     *
  209.     * @access   private
  210.     * @var      array 
  211.     */
  212.     var $_options array();
  213.  
  214.    /**
  215.     * reader is in use
  216.     *
  217.     * @access   private
  218.     * @var      boolean 
  219.     */
  220.     var $_inUse false;
  221.  
  222.    /**
  223.     * set a reference to the patTemplate object that instantiated the reader
  224.     *
  225.     * @access    public
  226.     * @param    object        patTemplate object
  227.     */
  228.     function setTemplateReference&$tmpl )
  229.     {
  230.         $this->_tmpl = &$tmpl;
  231.     }
  232.  
  233.    /**
  234.     * read templates from any input
  235.     *
  236.     * @abstract    must be implemented in the template readers
  237.     * @param    mixed    input to read from.
  238.     *                     This can be a string, a filename, a resource or whatever the derived class needs to read from
  239.     * @param    array    options, not implemented in current versions, but future versions will allow passing of options
  240.     * @return    array    template structure
  241.     */
  242.     function readTemplates$input$options array() )
  243.     {
  244.         return array();
  245.     }
  246.  
  247.    /**
  248.     * load template from any input
  249.     *
  250.     * If the a template is loaded, the content will not get
  251.     * analyzed but the whole content is returned as a string.
  252.     *
  253.     * @abstract    must be implemented in the template readers
  254.     * @param    mixed    input to load from.
  255.     *                     This can be a string, a filename, a resource or whatever the derived class needs to read from
  256.     * @param    array    options, not implemented in current versions, but future versions will allow passing of options
  257.     * @return    string  template content
  258.     */
  259.     function loadTemplate$input$options array() )
  260.     {
  261.         return $input;
  262.     }
  263.  
  264.    /**
  265.     * set options
  266.     *
  267.     * @access    public
  268.     * @param    array    array containing options
  269.     */
  270.     function setOptions$options )
  271.     {
  272.         $this->_startTag $options['startTag'];
  273.         $this->_endTag   $options['endTag'];
  274.  
  275.         $this->_options  $options;
  276.  
  277.         if (isset($options['functionAliases'])) {
  278.             $this->_funcAliases $options['functionAliases'];
  279.         }
  280.         array_map('strtolower'$this->_funcAliases);
  281.     }
  282.  
  283.    /**
  284.     * add an alias for a function
  285.     *
  286.     * @access   public
  287.     * @param    string  alias
  288.     * @param    string  function name
  289.     */
  290.     function addFunctionAlias($alias$function)
  291.     {
  292.         $this->_funcAliases[strtolower($alias)$function;
  293.     }
  294.  
  295.    /**
  296.     * set the root attributes
  297.     *
  298.     * @access    public
  299.     * @param    array    array containing options
  300.     */
  301.     function setRootAttributes$attributes )
  302.     {
  303.         $this->_rootAtts $attributes;
  304.     }
  305.  
  306.    /**
  307.     * parse templates from string
  308.     *
  309.     * @access    private
  310.     * @param    string        string to parse
  311.     * @return    array        templates
  312.     */
  313.     function parseString$string )
  314.     {
  315.         $this->_inUse true;
  316.  
  317.         /**
  318.          * apply input filter before parsing
  319.          */
  320.         $string $this->_tmpl->applyInputFilters$string );
  321.  
  322.         $this->_inheritAtts      =    array();
  323.         $this->_elStack          =    array();
  324.         $this->_data          =    array'' );
  325.         $this->_tmplStack      =    array();
  326.         $this->_depth          =    0;
  327.         $this->_templates      =    array();
  328.         $this->_path          =    array();
  329.         $this->_processedData =    '';
  330.  
  331.         $this->_defaultAtts    $this->_tmpl->getDefaultAttributes();
  332.  
  333.         if!isset$this->_defaultAtts['autoload') ) {
  334.             $this->_defaultAtts['autoload']    'on';
  335.         }
  336.  
  337.         /**
  338.          * create a special root template
  339.          */
  340.         $attributes            $this->_rootAtts;
  341.         $attributes['name']    '__ptroot';
  342.  
  343.         $rootTemplate $this->_initTemplate$attributes );
  344.         $this->_root  null;
  345.         unset$rootTemplate['isRoot');
  346.  
  347.         array_push$this->_tmplStack$rootTemplate );
  348.  
  349.         $patNamespace $this->_tmpl->getNamespace();
  350.         if (is_array($patNamespace)) {
  351.             $patNamespace array_map('strtolower'$patNamespace);
  352.         else {
  353.             $patNamespace array(strtolower$patNamespace ));
  354.         }
  355.  
  356.         /**
  357.          *start parsing
  358.          */
  359.         $regexp    =    '/(<(\/?)([[:alnum:]]+):([[:alnum:]]+)[[:space:]]*([^>]*)>)/im';
  360.  
  361.         $tokens    =    preg_split$regexp$string-1PREG_SPLIT_DELIM_CAPTURE );
  362.  
  363.         /**
  364.          * the first token is always character data
  365.          * Though it could just be empty
  366.          */
  367.         if$tokens[0!= '' {
  368.             $this->_characterData$tokens[0);
  369.         }
  370.  
  371.         $cnt    =    count$tokens );
  372.         $i        =    1;
  373.         // process all tokens
  374.         while$i $cnt {
  375.             $fullTag    $tokens[$i++];
  376.             $closing    $tokens[$i++];
  377.             $namespace    strtolower$tokens[$i++);
  378.             $tagname    strtolower$tokens[$i++);
  379.             $attString    $tokens[$i++];
  380.             $empty        substr$attString-);
  381.             $data        $tokens[$i++];
  382.  
  383.             /**
  384.              * check, whether it's a known namespace
  385.              * currently only the template namespace is possible
  386.              */
  387.              if!in_array($namespace$patNamespace) ) {
  388.                  $this->_characterData$fullTag );
  389.                  $this->_characterData$data );
  390.                 continue;
  391.              }
  392.  
  393.             /**
  394.              * is it a closing tag?
  395.              */
  396.             if$closing === '/' {
  397.                 $result    =    $this->_endElement$namespace$tagname );
  398.                 ifpatErrorManager::isError$result ) ) {
  399.                     return    $result;
  400.                 }
  401.                 $this->_characterData$data );
  402.                 continue;
  403.             }
  404.  
  405.             /**
  406.              * Is empty or opening tag!
  407.              */
  408.             if$empty === '/' {
  409.                 $attString    =    substr$attString0-);
  410.             }
  411.  
  412.             $attributes    =    $this->_parseAttributes$attString );
  413.             $result     =    $this->_startElement$namespace$tagname$attributes );
  414.             ifpatErrorManager::isError$result ) ) {
  415.                 return    $result;
  416.             }
  417.  
  418.             /**
  419.              * check, if the tag is empty
  420.              */
  421.             if$empty === '/' {
  422.                 $result    =    $this->_endElement$namespace$tagname );
  423.                 ifpatErrorManager::isError$result ) ) {
  424.                     return    $result;
  425.                 }
  426.             }
  427.  
  428.             $this->_characterData$data );
  429.         }
  430.  
  431.         $rootTemplate array_pop$this->_tmplStack );
  432.  
  433.         $this->_closeTemplate$rootTemplate$this->_data[0);
  434.  
  435.         /**
  436.          * check for tags that are still open
  437.          */
  438.         if$this->_depth {
  439.             $el    =    array_pop$this->_elStack );
  440.             return patErrorManager::raiseError(
  441.                 PATTEMPLATE_READER_ERROR_NO_CLOSING_TAG,
  442.                 $this->_createErrorMessage"No closing tag for {$el['ns']}:{$el['name']} found)
  443.             );
  444.         }
  445.  
  446.         $this->_inUse false;
  447.  
  448.         return    $this->_templates;
  449.     }
  450.  
  451.    /**
  452.     * parse an attribute string and build an array
  453.     *
  454.     * @access    private
  455.     * @param    string    attribute string
  456.     * @param    array    attribute array
  457.     */
  458.     function _parseAttributes$string )
  459.     {
  460.          static $entities array(
  461.                                     '&lt;' => '<',
  462.                                     '&gt;' => '>',
  463.                                     '&amp;' => '&',
  464.                                     '&quot;' => '"',
  465.                                     '&apos;' => '\''
  466.                                 );
  467.  
  468.         $attributes    =    array();
  469.         $match array();
  470.         preg_match_all('/([a-zA-Z_0-9]+)="((?:\\\.|[^"\\\])*)"/U'$string$match);
  471.         for ($i 0$i count($match[1])$i++{
  472.             $attributes[strtolower$match[1][$i)strtr(string)$match[2][$i]$entities );
  473.         }
  474.         return    $attributes;
  475.     }
  476.  
  477.    /**
  478.     * handle start element
  479.     *
  480.     * @access    private
  481.     * @param    string        element name
  482.     * @param    array        attributes
  483.     */
  484.     function _startElement$ns$name$attributes )
  485.     {
  486.         array_push$this->_elStackarray(
  487.                                             'ns'            =>  $ns,
  488.                                             'name'            =>    $name,
  489.                                             'attributes'    =>    $attributes,
  490.                                         )
  491.                  );
  492.  
  493.         $this->_depth++;
  494.  
  495.         $this->_data[$this->_depth]    =    '';
  496.  
  497.         /**
  498.          * handle tag
  499.          */
  500.         switch$name )
  501.         {
  502.             /**
  503.              * template
  504.              */
  505.             case 'tmpl':
  506.                 $result    =    $this->_initTemplate$attributes );
  507.                 break;
  508.  
  509.             /**
  510.              * sub-template
  511.              */
  512.             case 'sub':
  513.                 $result    =    $this->_initSubTemplate$attributes );
  514.                 break;
  515.  
  516.             /**
  517.              * link
  518.              */
  519.             case 'link':
  520.                 $result    =    $this->_initLink$attributes );
  521.                 break;
  522.  
  523.             /**
  524.              * variable
  525.              */
  526.             case 'var':
  527.                 $result    =    false;
  528.                 break;
  529.  
  530.             /**
  531.              * instance
  532.              */
  533.             case 'instance':
  534.             case 'comment':
  535.                 $result    =    false;
  536.                 break;
  537.  
  538.             /**
  539.              * any other tag
  540.              */
  541.             default:
  542.                 if (isset($this->_funcAliases[strtolower($name)])) {
  543.                     $name $this->_funcAliases[strtolower($name)];
  544.                 }
  545.                 $name ucfirst$name );
  546.  
  547.                 if!$this->_tmpl->moduleExists'Function'$name ) ) {
  548.  
  549.                     if (isset($this->_options['defaultFunction']&& !empty($this->_options['defaultFunction'])) {
  550.                         $attributes['_originalTag'$name;
  551.                         $name ucfirst($this->_options['defaultFunction']);
  552.                     else {
  553.                         return patErrorManager::raiseError(
  554.                                                             PATTEMPLATE_READER_ERROR_UNKNOWN_TAG,
  555.                                                             $this->_createErrorMessage"Unknown tag {$ns}:{$name}.)
  556.                                                         );
  557.                     }
  558.                 }
  559.                 $result array(
  560.                                 'type'       => 'custom',
  561.                                 'function'   => $name,
  562.                                 'attributes' => $attributes
  563.                                 );
  564.                 break;
  565.         }
  566.  
  567.         ifpatErrorManager::isError$result ) ) {
  568.             return    $result;
  569.         }
  570.  
  571.         array_push$this->_tmplStack$result );
  572.         return true;
  573.     }
  574.  
  575.    /**
  576.     * handle end element
  577.     *
  578.     * @access    private
  579.     * @param    string        element name
  580.     */
  581.     function _endElement$ns$name )
  582.     {
  583.         $el            =    array_pop$this->_elStack );
  584.         $data        =    $this->_getCData();
  585.         $this->_depth--;
  586.  
  587.         if$el['name'!= $name || $el['ns'!= $ns {
  588.             return patErrorManager::raiseError(
  589.                 PATTEMPLATE_READER_ERROR_INVALID_CLOSING_TAG,
  590.                 $this->_createErrorMessage"Invalid closing tag {$ns}:{$name}, {$el['ns']}:{$el['name']} expected)
  591.             );
  592.         }
  593.  
  594.         $tmpl    =    array_pop$this->_tmplStack );
  595.  
  596.         /**
  597.          * handle tag
  598.          */
  599.         switch$name )
  600.         {
  601.             /**
  602.              * template
  603.              */
  604.             case 'tmpl':
  605.                 $this->_closeTemplate$tmpl$data );
  606.                 break;
  607.  
  608.             /**
  609.              * sub-template
  610.              */
  611.             case 'sub':
  612.                 $this->_closeSubTemplate$tmpl$data );
  613.                 break;
  614.  
  615.             /**
  616.              * link
  617.              */
  618.             case 'link':
  619.                 $this->_closeLink$tmpl );
  620.                 break;
  621.  
  622.             /**
  623.              * variable
  624.              */
  625.             case 'var':
  626.                 $this->_handleVariable$el['attributes']$data );
  627.                 break;
  628.  
  629.             /**
  630.              * instance
  631.              */
  632.             case 'instance':
  633.                 break;
  634.  
  635.             /**
  636.              * comment
  637.              */
  638.             case 'comment':
  639.                 $this->_handleComment$el['attributes']$data );
  640.                 break;
  641.  
  642.             /**
  643.              * custom function
  644.              */
  645.             default:
  646.                 $name ucfirst$tmpl['function');
  647.  
  648.                 if!isset$this->_functions[$name) ) {
  649.                     $this->_functions[$name$this->_tmpl->loadModule'Function'$name );
  650.                     $this->_functions[$name]->setReader$this );
  651.                 }
  652.  
  653.                 $result $this->_functions[$name]->call$tmpl['attributes']$data );
  654.  
  655.                 ifpatErrorManager::isError$result ) ) {
  656.                     return $result;
  657.                 }
  658.  
  659.                 ifis_string$result ) ) {
  660.                     $this->_characterData$resultfalse );
  661.                 }
  662.                 break;
  663.         }
  664.         return true;
  665.     }
  666.  
  667.    /**
  668.     * handle character data
  669.     *
  670.     * @access    private
  671.     * @param    string        data
  672.     */
  673.     function _characterData$data$readFromTemplate true )
  674.     {
  675.         $this->_data[$this->_depth]    .=    $data;
  676.  
  677.         if ($readFromTemplate{
  678.             $this->_processedData .= $data;
  679.         }
  680.  
  681.         return    true;
  682.     }
  683.  
  684.    /**
  685.     * handle a Link
  686.     *
  687.     * @access    private
  688.     * @param    array        attributes
  689.     * @return    boolean        true on success
  690.     */
  691.     function _initLink$attributes )
  692.     {
  693.         /**
  694.          * needs a src attribute
  695.          */
  696.         if!isset$attributes['src') ) {
  697.             return patErrorManager::raiseError(
  698.                                                 PATTEMPLATE_READER_ERROR_INVALID_TAG,
  699.                                                 $this->_createErrorMessage"Attribute 'src' missing for link" )
  700.                                                 );
  701.         }
  702.  
  703.         /**
  704.          * create a new template
  705.          */
  706.         $tmpl    =    array(
  707.                             'type'            =>    'link',
  708.                             'src'            =>    $attributes['src'],
  709.                         );
  710.         return $tmpl;
  711.     }
  712.  
  713.    /**
  714.     * close a link template
  715.     *
  716.     * It will be added to the dependecies of the parent template.
  717.     *
  718.     * @access    private
  719.     * @param    array    template definition for the link
  720.     */
  721.     function _closeLink$tmpl )
  722.     {
  723.         /**
  724.          * add it to the dependencies
  725.          */
  726.         if!empty$this->_tmplStack ) )
  727.         {
  728.             $this->_addToParentTag'dependencies'strtolower$tmpl['src') );
  729.             $this->_characterDatasprintf"%sTMPL:%s%s"$this->_startTagstrtoupper$tmpl['src')$this->_endTag ) );
  730.         }
  731.  
  732.         return true;
  733.     }
  734.  
  735.    /**
  736.     * create a new template
  737.     *
  738.     * @access    private
  739.     * @param    array        attributes
  740.     * @return    boolean        true on success
  741.     */
  742.     function _initTemplate$attributes )
  743.     {
  744.         /**
  745.          * build name for the template
  746.          */
  747.         if (!isset$attributes['name')) {
  748.             $name    =    $this->_buildTemplateName();
  749.         else {
  750.             $name    =    strtolower$attributes['name');
  751.             unset$attributes['name');
  752.         }
  753.  
  754.         /**
  755.          * name must be unique
  756.          */
  757.         ifisset$this->_templates[$name|| $this->_tmpl->exists$name ) ) {
  758.             patErrorManager::raiseNotice(
  759.                                         PATTEMPLATE_READER_NOTICE_TEMPLATE_EXISTS,
  760.                                         $this->_createErrorMessage"Template $name already exists),
  761.                                         $name
  762.                                         );
  763.         }
  764.  
  765.         /**
  766.          * update the path
  767.          */
  768.         array_push$this->_path$name );
  769.  
  770.         ifisset$attributes['maxloop') ) {
  771.             if (!isset$attributes['parent')) {
  772.                 $attributes['parent'$this->_getFromParentTemplate'name' );
  773.             }
  774.         }
  775.  
  776.         $attributes    $this->_prepareTmplAttributes$attributes$name );
  777.  
  778.         array_push$this->_inheritAttsarray(
  779.                                                 'whitespace' => $attributes['whitespace'],
  780.                                                 'unusedvars' => $attributes['unusedvars'],
  781.                                                 'autoclear'  => $attributes['autoclear']
  782.                                             )
  783.                  );
  784.  
  785.         /**
  786.          * create a new template
  787.          */
  788.         $tmpl    =    array(
  789.                             'type'            =>    'tmpl',
  790.                             'name'            =>    $name,
  791.                             'attributes'    =>    $attributes,
  792.                             'content'        =>    '',
  793.                             'dependencies'    =>    array(),
  794.                             'varspecs'        =>    array(),
  795.                             'comments'        =>    array(),
  796.                             'loaded'        =>    false,
  797.                             'parsed'        =>    false,
  798.                             'input'            =>  $this->_name.'://'.$this->_currentInput
  799.                         );
  800.  
  801.         if$this->_root == null {
  802.             $this->_root $name;
  803.             $tmpl['isRoot'true;
  804.         }
  805.  
  806.  
  807.         /**
  808.          * prepare subtemplates
  809.          */
  810.         switch$attributes['type'{
  811.             case 'condition':
  812.             case 'modulo':
  813.                 $tmpl['subtemplates']    =    array();
  814.                 break;
  815.         }
  816.  
  817.         return $tmpl;
  818.     }
  819.  
  820.    /**
  821.     * prepare attributes
  822.     *
  823.     * @access    private
  824.     * @param    array    attributes
  825.     * @param    string    template name (only used for error messages)
  826.     * @return    array    attributes
  827.     */
  828.     function _prepareTmplAttributes$attributes$templatename )
  829.     {
  830.         /**
  831.          * do not prepare twice
  832.          */
  833.         ifisset$attributes['__prepared'&& $attributes['__prepared'=== true {
  834.             return $attributes;
  835.         }
  836.  
  837.         $attributes    $this->_inheritAttributes$attributes );
  838.  
  839.         /**
  840.          * get the attributes
  841.          */
  842.         $attributes    array_merge$this->_tmpl->getDefaultAttributes()$attributes );
  843.  
  844.         $attributes['type']    strtolower$attributes['type');
  845.  
  846.         if!isset$attributes['rowoffset') ) {
  847.             $attributes['rowoffset'1;
  848.         }
  849.  
  850.         if!isset$attributes['addsystemvars') ) {
  851.             $attributes['addsystemvars'false;
  852.         else {
  853.             switch ($attributes['addsystemvars']{
  854.                 case 'on':
  855.                 case 'boolean':
  856.                     $attributes['addsystemvars''boolean';
  857.                     break;
  858.                 case 'int':
  859.                 case 'integer':
  860.                     $attributes['addsystemvars''integer';
  861.                     break;
  862.                 case 'off':
  863.                     $attributes['addsystemvars'false;
  864.                     break;
  865.             }
  866.         }
  867.  
  868.         /**
  869.          * external template
  870.          */
  871.         ifisset$attributes['src') ) {
  872.              if!isset$attributes['parse') )
  873.                 $attributes['parse']    =    'on';
  874.              if!isset$attributes['reader') )
  875.                 $attributes['reader']    =    $this->getName();
  876.              if!isset$attributes['autoload') )
  877.                 $attributes['autoload']    =    $this->_defaultAtts['autoload'];
  878.  
  879.              if (isset($attributes['relative']&& strtolower($attributes['relative'=== 'yes')) {
  880.                 $attributes['relative']    $this->getCurrentInput();
  881.              else {
  882.                 $attributes['relative']    false;
  883.              }
  884.         }
  885.  
  886.         /**
  887.          * varscope is set
  888.          */
  889.         ifisset$attributes['varscope') ) {
  890.              /**
  891.              * varscope is parent
  892.              */
  893.              if$attributes['varscope'=== '__parent' {
  894.                 $attributes['varscope'$this->_getFromParentTemplate'name' );
  895.             }
  896.  
  897.             $attributes['varscope']    strtolower$attributes['varscope');
  898.             if (strstr($attributes['varscope']',')) {
  899.                 $attributes['varscope'array_map('trim'explode(','$attributes['varscope']));
  900.             }
  901.         }
  902.  
  903.         switch$attributes['type'{
  904.             /**
  905.              * validate condition template
  906.              */
  907.             case    'condition':
  908.                 if!isset$attributes['conditionvar') ) {
  909.                     return patErrorManager::raiseError(
  910.                                                         PATTEMPLATE_READER_ERROR_INVALID_TAG,
  911.                                                         $this->_createErrorMessage"Attribute 'conditionvarmissing for $templatename)
  912.                                                         );
  913.                 }
  914.                 $attributes['conditionvar']    =    strtoupper$attributes['conditionvar');
  915.  
  916.                 ifstrstr$attributes['conditionvar']'.' ) ) {
  917.                     list$attributes['conditiontmpl']$attributes['conditionvar'explode'.'$attributes['conditionvar');
  918.                     $attributes['conditiontmpl'strtolower$attributes['conditiontmpl');
  919.                 }
  920.  
  921.                 $attributes['autoclear']    =    'yes';
  922.  
  923.                 if (!isset$attributes['useglobals')) {
  924.                     $attributes['useglobals']    =    'no';
  925.                 }
  926.                 break;
  927.  
  928.             /**
  929.              * validate simplecondition template
  930.              */
  931.             case    'simplecondition':
  932.                 if!isset$attributes['requiredvars') ) {
  933.                     return patErrorManager::raiseError(
  934.                                                         PATTEMPLATE_READER_ERROR_INVALID_TAG,
  935.                                                         $this->_createErrorMessage"Attribute 'requiredvarsmissing for $templatename)
  936.                                                         );
  937.                 }
  938.                 $tmp array_map'trim'explode','$attributes['requiredvars') );
  939.                 $attributes['requiredvars']   array();
  940.                 foreach$tmp as $var {
  941.  
  942.                     $pos strpos$var'=' );
  943.                     if ($pos !== false{
  944.                         $val trim(substr$var$pos+));
  945.                         $var trim(substr$var0$pos ));
  946.                     else {
  947.                         $val null;
  948.                     }
  949.                     $var strtoupper($var);
  950.                     $pos strpos$var'.' );
  951.  
  952.                     if ($pos === false{
  953.                         array_push$attributes['requiredvars']array$templatename$var$val ) );
  954.                     else {
  955.                         array_push$attributes['requiredvars']array(
  956.                                                                         strtolowersubstr$var0$pos ) ),
  957.                                                                         substr$var$pos+),
  958.                                                                         $val
  959.                                                                     )
  960.                                 );
  961.                     }
  962.  
  963.                 }
  964.                 $attributes['autoclear''yes';
  965.                 break;
  966.  
  967.             /**
  968.              * oddeven => switch to new modulo syntax
  969.              */
  970.             case    'oddeven':
  971.                 $attributes['type']         'modulo';
  972.                 $attributes['modulo']     2;
  973.                 $attributes['autoclear''yes';
  974.                 break;
  975.  
  976.             /**
  977.              * modulo => requires a module attribute
  978.              */
  979.             case    'modulo':
  980.                 if!isset$attributes['modulo') ) {
  981.                     return patErrorManager::raiseError(
  982.                                                         PATTEMPLATE_READER_ERROR_INVALID_TAG,
  983.                                                         $this->_createErrorMessage"Attribute 'modulomissing for $templatename)
  984.                                                         );
  985.                 }
  986.                 $attributes['autoclear''yes';
  987.                 break;
  988.  
  989.             /**
  990.              * standard template => do nothing
  991.              */
  992.             case    'standard':
  993.                 break;
  994.  
  995.             /**
  996.              * unknown type
  997.              */
  998.             default:
  999.                 return patErrorManager::raiseError(
  1000.                                                     PATTEMPLATE_READER_ERROR_INVALID_TAG,
  1001.                                                     $this->_createErrorMessage"Unknown value for attribute type: {$attributes['type']})
  1002.                                                     );
  1003.                 break;
  1004.         }
  1005.  
  1006.         $attributes['__prepared'true;
  1007.  
  1008.         return $attributes;
  1009.     }
  1010.  
  1011.    /**
  1012.     * build a template name
  1013.     *
  1014.     * @access    private
  1015.     * @return    string    new template name
  1016.     */
  1017.     function _buildTemplateName()
  1018.     {
  1019.         return strtoloweruniqid'tmpl' ) );
  1020.     }
  1021.  
  1022.    /**
  1023.     * close the current template
  1024.     *
  1025.     * @access    private
  1026.     * @return    boolean    true on success
  1027.     */
  1028.     function _closeTemplate$tmpl$data )
  1029.     {
  1030.         $name array_pop$this->_path );
  1031.  
  1032.         $data $this->_adjustWhitespace$data$tmpl['attributes']['whitespace');
  1033.  
  1034.         array_pop$this->_inheritAtts );
  1035.  
  1036.         /**
  1037.          * check for special templates
  1038.          */
  1039.         switch$tmpl['attributes']['type')
  1040.         {
  1041.             /**
  1042.              * check for whitespace in conditional templates
  1043.              * and raise a notice
  1044.              */
  1045.             case    'condition':
  1046.             case    'modulo':
  1047.                 iftrim$data != '' {
  1048.                     patErrorManager::raiseNotice(
  1049.                                                     PATTEMPLATE_READER_NOTICE_INVALID_CDATA_SECTION,
  1050.                                                     $this->_createErrorMessagesprintf'No cdata is allowed inside a template of type %s (cdata was found in %s)'$tmpl['attributes']['type']$tmpl['name') )
  1051.                                                 );
  1052.                 }
  1053.                 $data    =    null;
  1054.                 break;
  1055.         }
  1056.  
  1057.         /**
  1058.          * store the content
  1059.          */
  1060.         $tmpl['content'$data;
  1061.  
  1062.         /**
  1063.          * No external template
  1064.          */
  1065.         if!isset$tmpl['attributes']['src') ) {
  1066.             $tmpl['loaded']    =    true;
  1067.         }
  1068.  
  1069.         /**
  1070.          * add it to the dependencies
  1071.          */
  1072.          if!empty$this->_tmplStack ) ) {
  1073.             $this->_addToParentTag'dependencies'$name );
  1074.  
  1075.             ifisset$tmpl['attributes']['placeholder') ) {
  1076.                 // maintain BC
  1077.                 if$this->shouldMaintainBc(&& $tmpl['attributes']['placeholder'=== 'none' {
  1078.                     $tmpl['attributes']['placeholder''__none';
  1079.                 }
  1080.  
  1081.                 if$tmpl['attributes']['placeholder'!== '__none' {
  1082.                     $this->_characterData$this->_startTag.(strtoupper$tmpl['attributes']['placeholder') ).$this->_endTag );
  1083.                 }
  1084.             else {
  1085.                 $this->_characterDatasprintf"%sTMPL:%s%s"$this->_startTagstrtoupper$name )$this->_endTag ) );
  1086.             }
  1087.          }
  1088.  
  1089.         unset$tmpl['name');
  1090.         unset$tmpl['tag');
  1091.  
  1092.         $this->_templates[$name$tmpl;
  1093.  
  1094.         return true;
  1095.     }
  1096.  
  1097.    /**
  1098.     * create a new sub-template
  1099.     *
  1100.     * @access    private
  1101.     * @param    array        attributes
  1102.     * @return    boolean        true on success
  1103.     */
  1104.     function _initSubTemplate$attributes )
  1105.     {
  1106.         /**
  1107.          * has to be embedded in a 'tmpl' tag
  1108.          */
  1109.         if (!$this->_parentTagIs('tmpl')) {
  1110.             return patErrorManager::raiseError(
  1111.                                                 PATTEMPLATE_READER_ERROR_INVALID_TAG,
  1112.                                                 $this->_createErrorMessage'A subtemplate is only allowed in a TMPL tag' )
  1113.                                                 );
  1114.         }
  1115.  
  1116.         /**
  1117.          * needs a condition attribute
  1118.          */
  1119.         if (!isset$attributes['condition')) {
  1120.             return patErrorManager::raiseError(
  1121.                                                 PATTEMPLATE_READER_ERROR_NO_CONDITION_SPECIFIED,
  1122.                                                 $this->_createErrorMessage'Missing \'condition\' attribute for subtemplate' )
  1123.                                                 );
  1124.         }
  1125.         $matches array();
  1126.         $regexp '/^'.$this->_startTag.'([^a-z]+[^\\\])'.$this->_endTag.'$/U';
  1127.         if (preg_match($regexp$attributes['condition']$matches)) {
  1128.             $attributes['var'$matches[1];
  1129.         }
  1130.  
  1131.         /**
  1132.          * maintain BC
  1133.          */
  1134.         if$this->shouldMaintainBc(&& in_array$attributes['condition']array'default''empty''odd''even' ) ) ) {
  1135.             $attributes['condition''__' $attributes['condition'];
  1136.         }
  1137.  
  1138.         if$attributes['condition'== '__odd' {
  1139.             $attributes['condition'1;
  1140.         elseif$attributes['condition'== '__even' {
  1141.             $attributes['condition'0;
  1142.         }
  1143.  
  1144.         $parent    array_pop$this->_tmplStack );
  1145.         array_push$this->_tmplStack$parent );
  1146.         if ($parent['attributes']['type'== 'modulo'{
  1147.  
  1148.             ifpreg_match'/^\d$/'$attributes['condition') ) {
  1149.                 if(integer)$attributes['condition'>= $parent['attributes']['modulo'{
  1150.                     return patErrorManager::raiseError(
  1151.                                                         PATTEMPLATE_READER_ERROR_INVALID_CONDITION,
  1152.                                                         $this->_createErrorMessage'Condition may only be between 0 and '.($parent['attributes']['modulo']-1) )
  1153.                                                     );
  1154.                 }
  1155.             }
  1156.         }
  1157.  
  1158.         $attributes $this->_inheritAttributes$attributes );
  1159.  
  1160.         $condition  $attributes['condition'];
  1161.         unset$attributes['condition');
  1162.  
  1163.         $subTmpl array(
  1164.                         'type'            =>    'sub',
  1165.                         'condition'        =>    $condition,
  1166.                         'data'            =>    '',
  1167.                         'attributes'    =>    $attributes,
  1168.                         'comments'        =>    array(),
  1169.                         'dependencies'    =>    array()
  1170.                         );
  1171.  
  1172.         return    $subTmpl;
  1173.     }
  1174.  
  1175.    /**
  1176.     * close subtemplate
  1177.     *
  1178.     * @access    private
  1179.     * @param    string        data
  1180.     * @return    boolean        true on success
  1181.     */
  1182.     function _closeSubTemplate$subTmpl$data )
  1183.     {
  1184.         $data                =    $this->_adjustWhitespace$data$subTmpl['attributes']['whitespace');
  1185.  
  1186.         $subTmpl['data']    =    $data;
  1187.         $condition            =    $subTmpl['condition'];
  1188.         unset$subTmpl['condition');
  1189.  
  1190.         $this->_addToParentTemplate'subtemplates',
  1191.                                       $subTmpl,
  1192.                                       $condition
  1193.                                     );
  1194.         return true;
  1195.     }
  1196.  
  1197.    /**
  1198.     * handle a variable
  1199.     *
  1200.     * @access    private
  1201.     * @param    array    attributes of the var tag
  1202.     * @param    string    cdata between the tags (will be used as default)
  1203.     * @return    boolean    true on success
  1204.     */
  1205.     function _handleVariable$attributes$data )
  1206.     {
  1207.         if!isset$attributes['name') ) {
  1208.             return patErrorManager::raiseError(
  1209.                                                 PATTEMPLATE_READER_ERROR_NO_NAME_SPECIFIED,
  1210.                                                 $this->_createErrorMessage'Variable needs a name attribute' )
  1211.                                                 );
  1212.         }
  1213.  
  1214.         $specs array();
  1215.  
  1216.         /**
  1217.          * get name
  1218.          */
  1219.         $name    =    strtoupper$attributes['name');
  1220.         unset$attributes['name');
  1221.         $specs['name']    =    $name;
  1222.  
  1223.         /**
  1224.          * use data as default value
  1225.          */
  1226.         ifisset$attributes['default') ) {
  1227.             $data                 =    $attributes['default'];
  1228.             $specs['default']    =    $data;
  1229.             unset$attributes['default');
  1230.         elseif (!empty$data )) {
  1231.             $specs['default']    =    $data;
  1232.         }
  1233.  
  1234.         /**
  1235.          * add it to template, if it's not hidden
  1236.          */
  1237.         if (!isset$attributes['hidden'|| $attributes['hidden'== 'no'{
  1238.             $this->_characterData$this->_startTag strtoupper$name $this->_endTag );
  1239.         }
  1240.  
  1241.         ifisset$attributes['hidden') ) {
  1242.             unset$attributes['hidden');
  1243.         }
  1244.  
  1245.         /**
  1246.          * copy value from any other variable
  1247.          */
  1248.         if (isset$attributes['copyfrom')) {
  1249.             $specs['copyfrom'strtoupper$attributes['copyfrom');
  1250.  
  1251.             if (strstr$specs['copyfrom']'.' )) {
  1252.                 $specs['copyfrom']    explode'.'$specs['copyfrom');
  1253.                 $specs['copyfrom'][0strtolower$specs['copyfrom'][0);
  1254.             }
  1255.  
  1256.             unset$attributes['copyfrom');
  1257.         }
  1258.  
  1259.         ifisset$attributes['modifier') ) {
  1260.             $modifier $attributes['modifier'];
  1261.             unset$attributes['modifier');
  1262.  
  1263.             $type = isset$attributes['modifiertype'$attributes['modifiertype''auto';
  1264.  
  1265.             ifisset$attributes['modifiertype') )
  1266.                 unset$attributes['modifiertype');
  1267.  
  1268.             $specs['modifier'array'mod' => $modifier'type' => $type'params' => $attributes );
  1269.         }
  1270.  
  1271.         if (!empty$specs )) {
  1272.             $this->_addToParentTemplate(
  1273.                                         'varspecs',
  1274.                                         $specs,
  1275.                                         $name
  1276.                                         );
  1277.         }
  1278.         return true;
  1279.     }
  1280.  
  1281.  
  1282.    /**
  1283.     * handle a comment
  1284.     *
  1285.     * @access    private
  1286.     * @param    array    attributes of the comment tag
  1287.     * @param    string    cdata between the tags (will be used as default)
  1288.     * @return    boolean    true on success
  1289.     */
  1290.     function _handleComment$attributes$data )
  1291.     {
  1292.         $this->_addToParentTag'comments'$data );
  1293.     }
  1294.  
  1295.    /**
  1296.     * get the character data of the element
  1297.     *
  1298.     * @access    private
  1299.     * @return    string 
  1300.     */
  1301.     function _getCData()
  1302.     {
  1303.         if$this->_depth == {
  1304.             return    '';
  1305.         }
  1306.         return $this->_data[$this->_depth];
  1307.     }
  1308.  
  1309.    /**
  1310.     * add to a property of the parent template
  1311.     *
  1312.     * @access    private
  1313.     * @param    string    property to add to
  1314.     * @param    mixed    value to add
  1315.     * @param    string    key
  1316.     */
  1317.     function _addToParentTemplate$property$value$key null )
  1318.     {
  1319.         $cnt count$this->_tmplStack );
  1320.  
  1321.         if ($cnt === 0{
  1322.             return false;
  1323.         }
  1324.  
  1325.         $pos $cnt 1;
  1326.         while ($pos >= 0{
  1327.             if ($this->_tmplStack[$pos]['type'!= 'tmpl'{
  1328.                 $pos--;
  1329.                 continue;
  1330.             }
  1331.  
  1332.             if ($key === null{
  1333.  
  1334.                 if (!in_array$value$this->_tmplStack[$pos][$property)) {
  1335.                     array_push$this->_tmplStack[$pos][$property]$value );
  1336.                 }
  1337.             else {
  1338.                 $this->_tmplStack[$pos][$property][$key$value;
  1339.             }
  1340.  
  1341.             return true;
  1342.         }
  1343.  
  1344.         return    false;
  1345.     }
  1346.  
  1347.    /**
  1348.     * get a property of the parent template
  1349.     *
  1350.     * @access    private
  1351.     * @param    string    property to add to
  1352.     * @return    mixed    value to add
  1353.     */
  1354.     function _getFromParentTemplate$property )
  1355.     {
  1356.         $cnt count$this->_tmplStack );
  1357.  
  1358.         if ($cnt === 0{
  1359.             return false;
  1360.         }
  1361.  
  1362.         $pos $cnt 1;
  1363.         while ($pos >= 0{
  1364.             if$this->_tmplStack[$pos]['type'!= 'tmpl' {
  1365.                 $pos--;
  1366.                 continue;
  1367.             }
  1368.  
  1369.             if (isset$this->_tmplStack[$pos][$property)) {
  1370.                 return $this->_tmplStack[$pos][$property];
  1371.             }
  1372.  
  1373.             return false;
  1374.         }
  1375.         return    false;
  1376.     }
  1377.  
  1378.  
  1379.    /**
  1380.     * add to a property of the parent tag
  1381.     *
  1382.     * @access    private
  1383.     * @param    string    property to add to
  1384.     * @param    mixed    value to add
  1385.     * @param    string    key
  1386.     */
  1387.     function _addToParentTag$property$value$key null )
  1388.     {
  1389.         $cnt count$this->_tmplStack );
  1390.  
  1391.         if ($cnt === 0{
  1392.             return false;
  1393.         }
  1394.  
  1395.         $pos $cnt 1;
  1396.  
  1397.         if ($key === null{
  1398.  
  1399.             if (!in_array$value$this->_tmplStack[$pos][$property)) {
  1400.                 array_push$this->_tmplStack[$pos][$property]$value );
  1401.             }
  1402.         else {
  1403.             $this->_tmplStack[$pos][$property][$key$value;
  1404.         }
  1405.  
  1406.         return true;
  1407.     }
  1408.  
  1409.    /**
  1410.     * adjust whitespace in a CData block
  1411.     *
  1412.     * @access    private
  1413.     * @param    string        data
  1414.     * @param    string        behaviour
  1415.     * @return    string        data
  1416.     */
  1417.     function _adjustWhitespace$data$behaviour )
  1418.     {
  1419.         switch$behaviour {
  1420.             case 'trim':
  1421.                 $data str_replace'\n'' '$data );
  1422.                 $data preg_replace'/\s\s+/'' '$data );
  1423.                 $data trim$data );
  1424.                 break;
  1425.         }
  1426.         return    $data;
  1427.     }
  1428.  
  1429.    /**
  1430.     * inherit attributes from the parent template
  1431.     *
  1432.     * The following attributes are inherited automatically:
  1433.     * - whitespace
  1434.     * - unusedvars
  1435.     *
  1436.     * @access    private
  1437.     * @param    array    attributes
  1438.     * @param    array    attributes with inherited attributes
  1439.     * @return    array    new attribute collection
  1440.     */
  1441.     function _inheritAttributes$attributes )
  1442.     {
  1443.         if (!empty$this->_inheritAtts )) {
  1444.             $parent end$this->_inheritAtts );
  1445.         else {
  1446.             $parent array(
  1447.                                 'whitespace' => $this->_defaultAtts['whitespace'],
  1448.                                 'unusedvars' => $this->_defaultAtts['unusedvars'],
  1449.                                 'autoclear'  => $this->_defaultAtts['autoclear']
  1450.                             );
  1451.         }
  1452.  
  1453.         $attributes array_merge$parent$attributes );
  1454.  
  1455.         return    $attributes;
  1456.     }
  1457.  
  1458.    /**
  1459.     * checks, whether the parent tag is of a certain type
  1460.     *
  1461.     * This is needed to ensure, that subtemplates are only
  1462.     * placed inside a template
  1463.     *
  1464.     * @access    private
  1465.     * @param    string    type (tmpl, sub, var, link)
  1466.     * @return    boolean 
  1467.     */
  1468.     function _parentTagIs$type )
  1469.     {
  1470.         $parent    =    array_pop$this->_tmplStack );
  1471.         if$parent === null {
  1472.             return false;
  1473.         }
  1474.         array_push$this->_tmplStack$parent );
  1475.  
  1476.         if$parent['type'== $type {
  1477.             return true;
  1478.         }
  1479.  
  1480.         return false;
  1481.     }
  1482.  
  1483.    /**
  1484.     * get the current line number
  1485.     *
  1486.     * @access    private
  1487.     * @return    integer        line number
  1488.     */
  1489.     function _getCurrentLine()
  1490.     {
  1491.         $line countexplode"\n"$this->_processedData ) );
  1492.         return $line;
  1493.     }
  1494.  
  1495.    /**
  1496.     * create an error message
  1497.     *
  1498.     * This method takes an error messages and appends the
  1499.     * current line number as well as a pointer to the input
  1500.     * (filename)
  1501.     *
  1502.     * @access    private
  1503.     * @param    string    base error message
  1504.     * @return    strin    error message
  1505.     */
  1506.     function _createErrorMessage$msg )
  1507.     {
  1508.         return sprintf'%s in %s on line %d'$msg$this->getCurrentInput()$this->_getCurrentLine() );
  1509.     }
  1510.  
  1511.    /**
  1512.     * get the current input
  1513.     *
  1514.     * @access   public
  1515.     * @return   string 
  1516.     */
  1517.     function getCurrentInput()
  1518.     {
  1519.         return $this->_currentInput;
  1520.     }
  1521.  
  1522.    /**
  1523.     * tests whether the reader should maintain backwards compatibility
  1524.     *
  1525.     * If enabled, you can still use 'default', 'empty', 'odd' and 'even'
  1526.     * instead of '__default', '__empty', etc.
  1527.     *
  1528.     * This will be disabled by default in future versions.
  1529.     *
  1530.     * @access    public
  1531.     * @return    boolean 
  1532.     */
  1533.     function shouldMaintainBc()
  1534.     {
  1535.         if (!isset$this->_options['maintainBc')) {
  1536.             return false;
  1537.         }
  1538.         return $this->_options['maintainBc'];
  1539.     }
  1540.  
  1541.    /**
  1542.     * returns, whether the reader currently is in use
  1543.     *
  1544.     * @access   public
  1545.     * @return   boolean 
  1546.     */
  1547.     function isInUse()
  1548.     {
  1549.         return $this->_inUse;
  1550.     }
  1551.  
  1552.    /**
  1553.     * get the template root for this reader
  1554.     *
  1555.     * @access  public
  1556.     * @return  string 
  1557.     */
  1558.     function getTemplateRoot()
  1559.     {
  1560.         if (!isset($this->_options['root'])) {
  1561.             return null;
  1562.         }
  1563.         if (isset($this->_options['root'][$this->_name])) {
  1564.             return $this->_options['root'][$this->_name];
  1565.         }
  1566.         if (isset($this->_options['root']['__default'])) {
  1567.             return $this->_options['root']['__default'];
  1568.         }
  1569.         return null;
  1570.     }
  1571. }
  1572. ?>

Documentation generated on Mon, 05 Mar 2007 21:19:57 +0000 by phpDocumentor 1.3.1