Support Joomla!

Packages

Package: patTemplate

License

Content on this site is copyright © 2005 - 2008 Open Source Matters Inc and can be used in accordance with the Joomla! Electronic Documentation License. Some parts of this website may be subject to other licenses.
Source code for file /pattemplate/patTemplate/Compiler.php

Documentation is available at Compiler.php

  1. <?PHP
  2. /**
  3.  * Compiler for patTemplate
  4.  *
  5.  * $Id: Compiler.php 10381 2008-06-01 03:35:53Z pasamio $
  6.  *
  7.  * WARNING: This is still experimental!
  8.  *
  9.  * @package        patTemplate
  10.  * @subpackage    Compiler
  11.  * @author        Stephan Schmidt <schst@php.net>
  12.  */
  13.  
  14. // Check to ensure this file is within the rest of the framework
  15. defined('JPATH_BASE'or die();
  16.  
  17. /**
  18.  * Compiler for patTemplate
  19.  *
  20.  * $Id: Compiler.php 10381 2008-06-01 03:35:53Z pasamio $
  21.  *
  22.  * WARNING: This is still experimental!
  23.  *
  24.  * @package        patTemplate
  25.  * @subpackage    Compiler
  26.  * @author        Stephan Schmidt <schst@php.net>
  27.  *
  28.  * @todo        implement all template types
  29.  * @todo        implement variable modifiers
  30.  * @todo        implement getParsedTemplate
  31.  * @todo        check for existing compiled template
  32.  */
  33. {
  34.     /**
  35.     * list of all templates that already have been compiled
  36.     *
  37.     * @access    private
  38.     * @var        array() 
  39.     */
  40.     var $_compiledTemplates array();
  41.  
  42.     /**
  43.     * file pointer to the compiled template
  44.     *
  45.     * @access    private
  46.     * @var        resource 
  47.     */
  48.     var $_fp;
  49.  
  50.     /**
  51.     * constructor
  52.     *
  53.     * Creates a new patTemplate Compiler
  54.     *
  55.     * @access    public
  56.     * @param    string        type of the templates, either 'html' or 'tex'
  57.     */
  58.     function patTemplate_Compiler$type 'html' )
  59.     {
  60.         $GLOBALS['patTemplate_Compiler']    =    &$this;
  61.         patTemplate::patTemplate$type );
  62.     }
  63.  
  64.     /**
  65.     * compile the currently loaded templates
  66.     *
  67.     * @access    public
  68.     * @param    string    name of the input (filename, shm segment, etc.)
  69.     */
  70.     function compile$compileName null )
  71.     {
  72.         $this->_varRegexp '/'.$this->_startTag.'([^a-z:]+)'.$this->_endTag.'/U';
  73.         $this->_depRegexp '/'.$this->_startTag.'TMPL:([^a-z:]+)'.$this->_endTag.'/U';
  74.  
  75.         $compileFolder    =    $this->getOption'compileFolder' );
  76.         $compileFile    =    sprintf'%s/%s'$compileFolder$compileName );
  77.  
  78.            $this->_fp    =    fopen$compileFile'w' );
  79.         $this->_addToCode'<?PHP' );
  80.         $this->_addToCode'/**' );
  81.         $this->_addToCode' * compiled patTemplate file' );
  82.         $this->_addToCode' *' );
  83.         $this->_addToCode' * compiled on 'date'Y-m-d H:i:s' ) );
  84.         $this->_addToCode' */' );
  85.         $this->_addToCode'class compiledTemplate {' );
  86.  
  87.         foreach$this->_templates as $template => $spec )
  88.         {
  89.             $this->compileTemplate$template );
  90.         }
  91.  
  92.         $this->_addToCode'}' );
  93.         $this->_addToCode'?>' );
  94.         fclose$this->_fp );
  95.  
  96.         include_once $compileFile;
  97.         return true;
  98.     }
  99.  
  100.     /**
  101.     * compile a template
  102.     *
  103.     * @access    public
  104.     * @param    string    name of the template
  105.     */
  106.     function compileTemplate$template )
  107.     {
  108.         $name    =    strtolower$template );
  109.  
  110.         if!isset$this->_templates[$template) )
  111.         {
  112.             return    patErrorManager::raiseWarning(
  113.                                                     PATTEMPLATE_WARNING_NO_TEMPLATE,
  114.                                                     "Template '$name' does not exist."
  115.                                                 );
  116.         }
  117.  
  118.  
  119.         /**
  120.          * check, if the template has been loaded
  121.          * and load it if necessary.
  122.          */
  123.         if$this->_templates[$template]['loaded'!== true )
  124.         {
  125.             if$this->_templates[$template]['attributes']['parse'== 'on' )
  126.             {
  127.                 $result $this->readTemplatesFromInput$this->_templates[$template]['attributes']['src']$this->_templates[$template]['attributes']['reader']null$template );
  128.             }
  129.             else
  130.             {
  131.                 $result $this->loadTemplateFromInput$this->_templates[$template]['attributes']['src']$this->_templates[$template]['attributes']['reader']$template );
  132.             }
  133.             ifpatErrorManager::isError$result ) )
  134.             {
  135.                 return $result;
  136.             }
  137.         }
  138.  
  139.         $this->_addToCode'' );
  140.         $this->_addToCode'/**' );
  141.         $this->_addToCode' * Compiled version of '.$template );
  142.         $this->_addToCode' *' );
  143.         $this->_addToCode' * Template type is '.$this->_templates[$template]['attributes']['type');
  144.         $this->_addToCode' */' );
  145.  
  146.  
  147.         /**
  148.          * start the output
  149.          */
  150.         $this->_addToCode'function '.$template.'()' );
  151.         $this->_addToCode'{' );
  152.         $this->_addToCode'$this->_prepareCompiledTemplate( "'.$template.'" );');
  153.         $this->_addToCode'$this->prepareTemplate( "'.$template.'" );');
  154.  
  155.         /**
  156.          * attributes
  157.          */
  158.         $this->_addToCode'$this->_templates["'.$template.'"]["attributes"] = unserialize( \''.serialize($this->_templates[$template]['attributes']).'\' );'1'Read the attributes' );
  159.  
  160.         /**
  161.          * copyVars
  162.          */
  163.         $this->_addToCode'$this->_templates["'.$template.'"]["copyVars"] = unserialize( \''.serialize($this->_templates[$template]['copyVars']).'\' );'1'Read the copyVars' );
  164.  
  165.         /**
  166.          * check visibility
  167.          */
  168.         $this->_addToCode'if( $this->_templates["'.$template.'"]["attributes"]["visibility"] != "hidden" ) {'1'Check, whether template is hidden' );
  169.  
  170.             /**
  171.              * autoloop the template
  172.              */
  173.                $this->_addToCode'$this->_templates["'.$template.'"]["iteration"] = 0;'2'Reset the iteration' );
  174.  
  175.             $this->_addToCode'$loop = count( $this->_vars["'.$template.'"]["rows"] );'2'Get the amount of loops' );
  176.             $this->_addToCode'$loop = max( $loop, 1 );');
  177.             $this->_addToCode'$this->_templates["'.$template.'"]["loop"] = $loop;');
  178.  
  179.             $this->_addToCode'for( $i = 0; $i < $loop; $i++ ) {'2'Traverse all variables.' );
  180.  
  181.                 /**
  182.                  * fetch the variables
  183.                  */
  184.                 $this->_addToCode'unset( $this->_templates["'.$template.'"]["vars"] );');
  185.                 $this->_addToCode'$this->_fetchVariables("'.$template.'");');
  186.  
  187.                 /**
  188.                  * different templates have to be compiled differently
  189.                  */
  190.                 switch$this->_templates[$template]['attributes']['type')
  191.                 {
  192.                     /**
  193.                      * modulo template
  194.                      */
  195.                     case 'modulo':
  196.                         $this->_compileModuloTemplate$template );
  197.                         break;
  198.  
  199.                     /**
  200.                      * simple condition template
  201.                      */
  202.                     case 'simplecondition':
  203.                         $this->_compileSimpleConditionTemplate$template );
  204.                         break;
  205.  
  206.                     /**
  207.                      * condition template
  208.                      */
  209.                     case 'condition':
  210.                         $this->_compileConditionTemplate$template );
  211.                         break;
  212.  
  213.                     /**
  214.                      * standard template
  215.                      */
  216.                     default:
  217.                         $this->_compileStandardTemplate$template );
  218.                         break;
  219.                 }
  220.                 $this->_addToCode'$this->_templates["'.$template.'"]["iteration"]++;');
  221.  
  222.             $this->_addToCode'}');
  223.  
  224.         $this->_addToCode'}');
  225.         $this->_addToCode'}' );
  226.  
  227.         /**
  228.          * remember this template
  229.          */
  230.         array_push$this->_compiledTemplates$template );
  231.     }
  232.  
  233.     /**
  234.     * compile a standard template
  235.     *
  236.     * @access    private
  237.     * @param    string        name of the template
  238.     */
  239.     function _compileStandardTemplate$template )
  240.     {
  241.         $content $this->_templateToPHP$this->_templates[$template]['content']$template );
  242.         $this->_addToCode$content );
  243.         return true;
  244.     }
  245.  
  246.     /**
  247.     * compile a modulo template
  248.     *
  249.     * A modulo template will be compiled into a switch/case
  250.     * statement.
  251.     *
  252.     * @access    private
  253.     * @param    string        name of the template
  254.     * @todo        check special conditions (__first, __last, __default)
  255.     */
  256.     function _compileModuloTemplate$template )
  257.     {
  258.         $this->_compileBuiltinConditions$template );
  259.  
  260.  
  261.         $this->_addToCode'if( !$_displayed ) {'3'Builtin condition has been displayed?' );
  262.  
  263.         /**
  264.          * build switch statement
  265.          */
  266.         $this->_addToCode'switch( ( $this->_templates["'.$template.'"]["iteration"] + 1 ) % '.$this->_templates[$template]['attributes']['modulo'].' ) {');
  267.  
  268.         foreach$this->_templates[$template]['subtemplates'as $condition => $spec )
  269.         {
  270.             $this->_addToCode'case "'.$condition.'":');
  271.             $content $this->_templateToPHP$spec['data']$template );
  272.             $this->_addToCode$content );
  273.             $this->_addToCode'break;');
  274.         }
  275.         $this->_addToCode'}');
  276.         $this->_addToCode'}');
  277.         return true;
  278.     }
  279.  
  280.     /**
  281.     * compile a simpleCondition template
  282.     *
  283.     * A simpleCondition template will be compiled into an 'if'
  284.     * statement.
  285.     *
  286.     * @access    private
  287.     * @param    string        name of the template
  288.     */
  289.     function _compileSimpleConditionTemplate$template )
  290.     {
  291.         $conditions    =    array();
  292.         foreach$this->_templates[$template]['attributes']['requiredvars'as $var )
  293.         {
  294.             array_push$conditions'isset( $this->_templates["'.$template.'"]["vars"]["'.$var.'"] )' );
  295.         }
  296.  
  297.         /**
  298.          * build switch statement
  299.          */
  300.         $this->_addToCode'if( '.implode' && '$conditions ).' ) {'3'Check for required variables' );
  301.  
  302.         $content $this->_templateToPHP$this->_templates[$template]['content']$template );
  303.         $this->_addToCode$content );
  304.         $this->_addToCode'}');
  305.         return true;
  306.     }
  307.  
  308.     /**
  309.     * compile a condition template
  310.     *
  311.     * A condition template will be compiled into an 'switch/case'
  312.     * statement.
  313.     *
  314.     * @access    private
  315.     * @param    string        name of the template
  316.     */
  317.     function _compileConditionTemplate$template )
  318.     {
  319.         /**
  320.          * __first, __last
  321.          */
  322.         $this->_compileBuiltinConditions$template );
  323.  
  324.         $this->_addToCode'if( !$_displayed ) {'3'Builtin condition has been displayed?' );
  325.  
  326.         /**
  327.          * build switch statement
  328.          */
  329.         $this->_addToCode'switch( $this->_templates["'.$template.'"]["vars"]["'.$this->_templates[$template]["attributes"]["conditionvar"].'"] ) {');
  330.  
  331.         foreach$this->_templates[$template]['subtemplates'as $condition => $spec )
  332.         {
  333.             if$condition == '__default' )
  334.             {
  335.                 $this->_addToCode'default:');
  336.             }
  337.             else
  338.             {
  339.                 $this->_addToCode'case "'.$condition.'":');
  340.             }
  341.             $content $this->_templateToPHP$spec['data']$template );
  342.             $this->_addToCode$content );
  343.             $this->_addToCode'break;');
  344.         }
  345.         $this->_addToCode'}');
  346.         $this->_addToCode'}');
  347.         return true;
  348.     }
  349.  
  350.     /**
  351.     * compile built-in conditions
  352.     *
  353.     * This will create the neccessary PHP code for:
  354.     * - __first
  355.     * - __last
  356.     *
  357.     * @access    private
  358.     * @param    string    template name
  359.     */
  360.     function _compileBuiltinConditions$template )
  361.     {
  362.         $this->_addToCode'$_displayed = false;');
  363.  
  364.         ifisset$this->_templates[$template]['subtemplates']['__first') )
  365.         {
  366.             $this->_addToCode'if( $this->_templates["'.$template.'"]["iteration"] == 0 ) {'3'Check for first entry' );
  367.             $content $this->_templateToPHP$this->_templates[$template]['subtemplates']['__first']['data']$template );
  368.             $this->_addToCode$content );
  369.             $this->_addToCode'$_displayed = true;');
  370.             $this->_addToCode'}');
  371.         }
  372.  
  373.         ifisset$this->_templates[$template]['subtemplates']['__last') )
  374.         {
  375.             $this->_addToCode'if( $this->_templates["'.$template.'"]["iteration"] == ($this->_templates["'.$template.'"]["loop"]-1) ) {'3'Check for last entry' );
  376.             $content $this->_templateToPHP$this->_templates[$template]['subtemplates']['__last']['data']$template );
  377.             $this->_addToCode$content );
  378.             $this->_addToCode'$_displayed = true;');
  379.             $this->_addToCode'}');
  380.         }
  381.     }
  382.  
  383.     /**
  384.     * build PHP code from a template
  385.     *
  386.     * This will replace the variables in a template with
  387.     * PHP Code.
  388.     *
  389.     * @access    private
  390.     * @param    string        template content
  391.     * @param    string        name of the template
  392.     * @return    string        PHP code
  393.     */
  394.     function _templateToPHP$content$template )
  395.     {
  396.         $content preg_replace$this->_varRegexp'<?PHP echo $this->_getVar( "'.$template.'", "$1"); ?>'$content  );
  397.         $content preg_replace$this->_depRegexp'<?PHP compiledTemplate::$1(); ?>'$content  );
  398.         $content '?>'.$content.'<?PHP';
  399.         return $content;
  400.     }
  401.  
  402.  
  403.     /**
  404.     * display the compiled template
  405.     *
  406.     * This is a replacement for patTemplate::displayParsedTemplate.
  407.     *
  408.     * @access    public
  409.     * @param    string        name of the template to display
  410.     */
  411.     function displayParsedTemplate$name null )
  412.     {
  413.         ifis_null$name ) )
  414.             $name $this->_root;
  415.  
  416.         $name    =    strtolower$name );
  417.  
  418.         if!is_callable'compiledTemplate'$name ) )
  419.         {
  420.             jexit'Unknown template' );
  421.         }
  422.  
  423.         compiledTemplate::$name();
  424.     }
  425.  
  426.     /**
  427.     * add a line to the compiled code
  428.     *
  429.     * @access    public
  430.     * @param    string        line to add
  431.     * @param    integer        indentation
  432.     * @return    void 
  433.     */
  434.     function _addToCode$line$indent 0$comment null )
  435.     {
  436.         if!is_null$comment ) )
  437.         {
  438.             fputs$this->_fp"\n" );
  439.             if$indent )