[ Index ]

PHP Cross Reference of Joomla 1.5.26 DE

title

Body

[close]

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

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


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