[ Index ]

PHP Cross Reference of phpBB 3.0 Beta 3

title

Body

[close]

/includes/ -> functions_template.php (source)

   1  <?php
   2  /** 
   3  *
   4  * @package phpBB3
   5  * @version $Id: functions_template.php,v 1.33 2006/11/10 13:48:48 acydburn Exp $
   6  * @copyright (c) 2005 phpBB Group, sections (c) 2001 ispi of Lincoln Inc
   7  * @license http://opensource.org/licenses/gpl-license.php GNU Public License 
   8  *
   9  */
  10  
  11  /**
  12  */
  13  if (!defined('IN_PHPBB'))
  14  {
  15      exit;
  16  }
  17  
  18  /**
  19  * Extension of template class - Functions needed for compiling templates only.
  20  *
  21  * psoTFX, phpBB Development Team - Completion of file caching, decompilation
  22  * routines and implementation of conditionals/keywords and associated changes
  23  *
  24  * The interface was inspired by PHPLib templates,  and the template file (formats are
  25  * quite similar)
  26  *
  27  * The keyword/conditional implementation is currently based on sections of code from
  28  * the Smarty templating engine (c) 2001 ispi of Lincoln, Inc. which is released
  29  * (on its own and in whole) under the LGPL. Section 3 of the LGPL states that any code
  30  * derived from an LGPL application may be relicenced under the GPL, this applies
  31  * to this source
  32  * 
  33  * DEFINE directive inspired by a request by Cyberalien
  34  *
  35  * @package phpBB3
  36  */
  37  class template_compile
  38  {
  39      var $template;
  40  
  41      // Various storage arrays
  42      var $block_names = array();
  43      var $block_else_level = array();
  44  
  45      /**
  46      * constuctor
  47      */
  48  	function template_compile(&$template)
  49      {
  50          $this->template = &$template;
  51      }
  52      
  53      /**
  54      * Load template source from file
  55      * @access private
  56      */
  57  	function _tpl_load_file($handle)
  58      {
  59          // Try and open template for read
  60          if (!file_exists($this->template->files[$handle]))
  61          {
  62              trigger_error("template->_tpl_load_file(): File {$this->template->files[$handle]} does not exist or is empty", E_USER_ERROR);
  63          }
  64  
  65          $this->template->compiled_code[$handle] = $this->compile(trim(@file_get_contents($this->template->files[$handle])));
  66  
  67          // Actually compile the code now.
  68          $this->compile_write($handle, $this->template->compiled_code[$handle]);
  69      }
  70  
  71      /**
  72      * Straight-forward strategy: use PHP's tokenizer to escape everything that
  73      * looks like a PHP tag.
  74      *
  75      * We open/close PHP tags at the beginning of the template to clearly indicate
  76      * that we are in HTML mode. If we find a PHP tag, we escape it then we reiterate
  77      * over the whole file. That can become quite slow if the file is stuffed with
  78      * <?php tags, but there's only so much we can do.
  79      *
  80      * Known issue: templates need to be rechecked everytime the value of the php.ini
  81      * settings asp_tags or short_tags are changed
  82      */
  83  	function remove_php_tags(&$code)
  84      {
  85          // This matches the information gathered from the internal PHP lexer
  86          $match = array(
  87              '#<([\?%])=?.*?\1>#s',
  88              '#<script\s+language\s*=\s*(["\']?)php\1\s*>.*?</script\s*>#s',
  89              '#<\?php(?:\r\n?|[ \n\t]).*?\?>#s'
  90          );
  91  
  92          $code = preg_replace($match, '', $code);
  93      }
  94  
  95      /**
  96      * The all seeing all doing compile method. Parts are inspired by or directly from Smarty
  97      * @access private
  98      */
  99  	function compile($code, $no_echo = false, $echo_var = '')
 100      {
 101          global $config;
 102  
 103          if ($echo_var)
 104          {
 105              global $$echo_var;
 106          }
 107  
 108          // Remove any "loose" php ... we want to give admins the ability
 109          // to switch on/off PHP for a given template. Allowing unchecked
 110          // php is a no-no. There is a potential issue here in that non-php
 111          // content may be removed ... however designers should use entities
 112          // if they wish to display < and >
 113          $this->remove_php_tags($code);
 114  
 115          // Pull out all block/statement level elements and seperate plain text
 116          preg_match_all('#<!-- PHP -->(.*?)<!-- ENDPHP -->#s', $code, $matches);
 117          $php_blocks = $matches[1];
 118          $code = preg_replace('#<!-- PHP -->(.*?)<!-- ENDPHP -->#s', '<!-- PHP -->', $code);
 119  
 120          preg_match_all('#<!-- INCLUDE ([a-zA-Z0-9\_\-\+\./]+?) -->#', $code, $matches);
 121          $include_blocks = $matches[1];
 122          $code = preg_replace('#<!-- INCLUDE ([a-zA-Z0-9\_\-\+\./]+?) -->#', '<!-- INCLUDE -->', $code);
 123  
 124          preg_match_all('#<!-- INCLUDEPHP ([a-zA-Z0-9\_\-\+\./]+?) -->#', $code, $matches);
 125          $includephp_blocks = $matches[1];
 126          $code = preg_replace('#<!-- INCLUDEPHP ([a-zA-Z0-9\_\-\+\./]+?) -->#', '<!-- INCLUDEPHP -->', $code);
 127  
 128          preg_match_all('#<!-- ([^<].*?) (.*?)?[ ]?-->#', $code, $blocks);
 129          $text_blocks = preg_split('#<!-- ([^<].*?) (.*?)?[ ]?-->#', $code);
 130  
 131          for ($i = 0, $j = sizeof($text_blocks); $i < $j; $i++)
 132          {
 133              $this->compile_var_tags($text_blocks[$i]);
 134          }
 135          $compile_blocks = array();
 136  
 137          for ($curr_tb = 0, $tb_size = sizeof($text_blocks); $curr_tb < $tb_size; $curr_tb++)
 138          {
 139              if (!isset($blocks[1][$curr_tb]))
 140              {
 141                  $blocks[1][$curr_tb] = '';
 142              }
 143  
 144              switch ($blocks[1][$curr_tb])
 145              {
 146                  case 'BEGIN':
 147                      $this->block_else_level[] = false;
 148                      $compile_blocks[] = '<?php ' . $this->compile_tag_block($blocks[2][$curr_tb]) . ' ?>';
 149                  break;
 150  
 151                  case 'BEGINELSE':
 152                      $this->block_else_level[sizeof($this->block_else_level) - 1] = true;
 153                      $compile_blocks[] = '<?php }} else { ?>';
 154                  break;
 155  
 156                  case 'END':
 157                      array_pop($this->block_names);
 158                      $compile_blocks[] = '<?php ' . ((array_pop($this->block_else_level)) ? '}' : '}}') . ' ?>';
 159                  break;
 160  
 161                  case 'IF':
 162                      $compile_blocks[] = '<?php ' . $this->compile_tag_if($blocks[2][$curr_tb], false) . ' ?>';
 163                  break;
 164  
 165                  case 'ELSE':
 166                      $compile_blocks[] = '<?php } else { ?>';
 167                  break;
 168  
 169                  case 'ELSEIF':
 170                      $compile_blocks[] = '<?php ' . $this->compile_tag_if($blocks[2][$curr_tb], true) . ' ?>';
 171                  break;
 172  
 173                  case 'ENDIF':
 174                      $compile_blocks[] = '<?php } ?>';
 175                  break;
 176  
 177                  case 'DEFINE':
 178                      $compile_blocks[] = '<?php ' . $this->compile_tag_define($blocks[2][$curr_tb], true) . ' ?>';
 179                  break;
 180  
 181                  case 'UNDEFINE':
 182                      $compile_blocks[] = '<?php ' . $this->compile_tag_define($blocks[2][$curr_tb], false) . ' ?>';
 183                  break;
 184  
 185                  case 'INCLUDE':
 186                      $temp = array_shift($include_blocks);
 187                      $compile_blocks[] = '<?php ' . $this->compile_tag_include($temp) . ' ?>';
 188                      $this->template->_tpl_include($temp, false);
 189                  break;
 190  
 191                  case 'INCLUDEPHP':
 192                      $compile_blocks[] = ($config['tpl_allow_php']) ? '<?php ' . $this->compile_tag_include_php(array_shift($includephp_blocks)) . ' ?>' : '';
 193                  break;
 194  
 195                  case 'PHP':
 196                      $compile_blocks[] = ($config['tpl_allow_php']) ? '<?php ' . array_shift($php_blocks) . ' ?>' : '';
 197                  break;
 198  
 199                  default:
 200                      $this->compile_var_tags($blocks[0][$curr_tb]);
 201                      $trim_check = trim($blocks[0][$curr_tb]);
 202                      $compile_blocks[] = (!$no_echo) ? ((!empty($trim_check)) ? $blocks[0][$curr_tb] : '') : ((!empty($trim_check)) ? $blocks[0][$curr_tb] : '');
 203                  break;
 204              }
 205          }
 206  
 207          $template_php = '';
 208          for ($i = 0, $size = sizeof($text_blocks); $i < $size; $i++)
 209          {
 210              $trim_check_text = trim($text_blocks[$i]);
 211              $template_php .= (!$no_echo) ? ((!empty($trim_check_text)) ? $text_blocks[$i] : '') . ((!empty($compile_blocks[$i])) ? $compile_blocks[$i] : '') : ((!empty($trim_check_text)) ? $text_blocks[$i] : '') . ((!empty($compile_blocks[$i])) ? $compile_blocks[$i] : '');
 212          }
 213  
 214          // There will be a number of occassions where we switch into and out of
 215          // PHP mode instantaneously. Rather than "burden" the parser with this
 216          // we'll strip out such occurences, minimising such switching
 217          $template_php = str_replace(' ?><?php ', ' ', $template_php);
 218  
 219          return  (!$no_echo) ? $template_php : "\$$echo_var .= '" . $template_php . "'";
 220      }
 221  
 222      /**
 223      * Compile variables
 224      * @access private
 225      */
 226  	function compile_var_tags(&$text_blocks)
 227      {
 228          // change template varrefs into PHP varrefs
 229          $varrefs = array();
 230  
 231          // This one will handle varrefs WITH namespaces
 232          preg_match_all('#\{((?:[a-z0-9\-_]+\.)+)(\$)?([A-Z0-9\-_]+)\}#', $text_blocks, $varrefs);
 233  
 234          for ($j = 0, $size = sizeof($varrefs[1]); $j < $size; $j++)
 235          {
 236              $namespace = $varrefs[1][$j];
 237              $varname = $varrefs[3][$j];
 238              $new = $this->generate_block_varref($namespace, $varname, true, $varrefs[2][$j]);
 239  
 240              $text_blocks = str_replace($varrefs[0][$j], $new, $text_blocks);
 241          }
 242  
 243          // This will handle the remaining root-level varrefs
 244          // transform vars prefixed by L_ into their language variable pendant if nothing is set within the tpldata array
 245          if (strpos($text_blocks, '{L_') !== false)
 246          {
 247              $text_blocks = preg_replace('#\{L_([a-z0-9\-_]*)\}#is', "<?php echo ((isset(\$this->_tpldata['.'][0]['L_\\1'])) ? \$this->_tpldata['.'][0]['L_\\1'] : ((isset(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '{ ' . ucfirst(strtolower(str_replace('_', ' ', '\\1'))) . ' }')); ?>", $text_blocks);
 248          }
 249  
 250          // Handle addslashed language variables prefixed with LA_
 251          // If a template variable already exist, it will be used in favor of it...
 252          if (strpos($text_blocks, '{LA_') !== false)
 253          {
 254              $text_blocks = preg_replace('#\{LA_([a-z0-9\-_]*)\}#is', "<?php echo ((isset(\$this->_tpldata['.'][0]['LA_\\1'])) ? \$this->_tpldata['.'][0]['LA_\\1'] : ((isset(\$this->_tpldata['.'][0]['L_\\1'])) ? addslashes(\$this->_tpldata['.'][0]['L_\\1']) : ((isset(\$user->lang['\\1'])) ? addslashes(\$user->lang['\\1']) : '{ ' . ucfirst(strtolower(str_replace('_', ' ', '\\1'))) . ' }'))); ?>", $text_blocks);
 255          }
 256  
 257          // Handle remaining varrefs
 258          $text_blocks = preg_replace('#\{([a-z0-9\-_]*)\}#is', "<?php echo (isset(\$this->_tpldata['.'][0]['\\1'])) ? \$this->_tpldata['.'][0]['\\1'] : ''; ?>", $text_blocks);
 259          $text_blocks = preg_replace('#\{\$([a-z0-9\-_]*)\}#is', "<?php echo (isset(\$this->_tpldata['DEFINE']['.']['\\1'])) ? \$this->_tpldata['DEFINE']['.']['\\1'] : ''; ?>", $text_blocks);
 260  
 261          return;
 262      }
 263  
 264      /**
 265      * Compile blocks
 266      * @access private
 267      */
 268  	function compile_tag_block($tag_args)
 269      {
 270          $no_nesting = false;
 271  
 272          // Is the designer wanting to call another loop in a loop?
 273          if (strpos($tag_args, '!') === 0)
 274          {
 275              // Count the number if ! occurrences (not allowed in vars)
 276              $no_nesting = substr_count($tag_args, '!');
 277              $tag_args = substr($tag_args, $no_nesting);
 278          }
 279  
 280          // Allow for control of looping (indexes start from zero):
 281          // foo(2)    : Will start the loop on the 3rd entry
 282          // foo(-2)   : Will start the loop two entries from the end
 283          // foo(3,4)  : Will start the loop on the fourth entry and end it on the fifth
 284          // foo(3,-4) : Will start the loop on the fourth entry and end it four from last
 285          if (preg_match('#^([^()]*)\(([\-\d]+)(?:,([\-\d]+))?\)$#', $tag_args, $match))
 286          {
 287              $tag_args = $match[1];
 288  
 289              if ($match[2] < 0)
 290              {
 291                  $loop_start = '($_' . $tag_args . '_count ' . $match[2] . ' < 0 ? 0 : $_' . $tag_args . '_count ' . $match[2] . ')';
 292              }
 293              else
 294              {
 295                  $loop_start = '($_' . $tag_args . '_count < ' . $match[2] . ' ? $_' . $tag_args . '_count : ' . $match[2] . ')';
 296              }
 297  
 298              if (strlen($match[3]) < 1 || $match[3] == -1)
 299              {
 300                  $loop_end = '$_' . $tag_args . '_count';
 301              }
 302              else if ($match[3] >= 0)
 303              {
 304                  $loop_end = '(' . ($match[3] + 1) . ' > $_' . $tag_args . '_count ? $_' . $tag_args . '_count : ' . ($match[3] + 1) . ')';
 305              }
 306              else //if ($match[3] < -1)
 307              {
 308                  $loop_end = '$_' . $tag_args . '_count' . ($match[3] + 1);
 309              }
 310          }
 311          else
 312          {
 313              $loop_start = 0;
 314              $loop_end = '$_' . $tag_args . '_count';
 315          }
 316  
 317          $tag_template_php = '';
 318          array_push($this->block_names, $tag_args);
 319  
 320          if (sizeof($this->block_names) < 2)
 321          {
 322              // Block is not nested.
 323              $tag_template_php = '$_' . $tag_args . "_count = (isset(\$this->_tpldata['$tag_args'])) ?  sizeof(\$this->_tpldata['$tag_args']) : 0;";
 324          }
 325          else
 326          {
 327              // This block is nested.
 328  
 329              // Generate a namespace string for this block.
 330              if ($no_nesting !== false)
 331              {
 332                  // We need to implode $no_nesting times from the end...
 333                  $namespace = implode('.', array_slice($this->block_names, -$no_nesting));
 334              }
 335              else
 336              {
 337                  $namespace = implode('.', $this->block_names);
 338              }
 339  
 340              // Get a reference to the data array for this block that depends on the
 341              // current indices of all parent blocks.
 342              $varref = $this->generate_block_data_ref($namespace, false);
 343  
 344              // Create the for loop code to iterate over this block.
 345              $tag_template_php = '$_' . $tag_args . '_count = (isset(' . $varref . ')) ? sizeof(' . $varref . ') : 0;';
 346          }
 347  
 348          $tag_template_php .= 'if ($_' . $tag_args . '_count) {';
 349          $tag_template_php .= 'for ($this->_' . $tag_args . '_i = ' . $loop_start . '; $this->_' . $tag_args . '_i < ' . $loop_end . '; $this->_' . $tag_args . '_i++){';
 350  
 351          return $tag_template_php;
 352      }
 353  
 354      /**
 355      * Compile IF tags - much of this is from Smarty with
 356      * some adaptions for our block level methods
 357      * @access private
 358      */
 359  	function compile_tag_if($tag_args, $elseif)
 360      {
 361          // Tokenize args for 'if' tag.
 362          preg_match_all('/(?:
 363              "[^"\\\\]*(?:\\\\.[^"\\\\]*)*"         |
 364              \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'     |
 365              [(),]                                  |
 366              [^\s(),]+)/x', $tag_args, $match);
 367  
 368          $tokens = $match[0];
 369          $is_arg_stack = array();
 370  
 371          for ($i = 0, $size = sizeof($tokens); $i < $size; $i++)
 372          {
 373              $token = &$tokens[$i];
 374  
 375              switch ($token)
 376              {
 377                  case '!==':
 378                  case '===':
 379                  case '<<':
 380                  case '>>':
 381                  case '|':
 382                  case '^':
 383                  case '&':
 384                  case '~':
 385                  case ')':
 386                  case ',':
 387                  case '+':
 388                  case '-':
 389                  case '*':
 390                  case '/':
 391                  case '@':
 392                  break;
 393  
 394                  case '==':
 395                  case 'eq':
 396                      $token = '==';
 397                  break;
 398  
 399                  case '!=':
 400                  case '<>':
 401                  case 'ne':
 402                  case 'neq':
 403                      $token = '!=';
 404                  break;
 405  
 406                  case '<':
 407                  case 'lt':
 408                      $token = '<';
 409                  break;
 410  
 411                  case '<=':
 412                  case 'le':
 413                  case 'lte':
 414                      $token = '<=';
 415                  break;
 416  
 417                  case '>':
 418                  case 'gt':
 419                      $token = '>';
 420                  break;
 421  
 422                  case '>=':
 423                  case 'ge':
 424                  case 'gte':
 425                      $token = '>=';
 426                  break;
 427  
 428                  case '&&':
 429                  case 'and':
 430                      $token = '&&';
 431                  break;
 432  
 433                  case '||':
 434                  case 'or':
 435                      $token = '||';
 436                  break;
 437  
 438                  case '!':
 439                  case 'not':
 440                      $token = '!';
 441                  break;
 442  
 443                  case '%':
 444                  case 'mod':
 445                      $token = '%';
 446                  break;
 447  
 448                  case '(':
 449                      array_push($is_arg_stack, $i);
 450                  break;
 451  
 452                  case 'is':
 453                      $is_arg_start = ($tokens[$i-1] == ')') ? array_pop($is_arg_stack) : $i-1;
 454                      $is_arg    = implode('    ', array_slice($tokens,    $is_arg_start, $i -    $is_arg_start));
 455  
 456                      $new_tokens    = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
 457  
 458                      array_splice($tokens, $is_arg_start, sizeof($tokens), $new_tokens);
 459  
 460                      $i = $is_arg_start;
 461  
 462                  // no break
 463  
 464                  default:
 465                      if (preg_match('#^((?:[a-z0-9\-_]+\.)+)?(\$)?(?=[A-Z])([A-Z0-9\-_]+)#s', $token, $varrefs))
 466                      {
 467                          $token = (!empty($varrefs[1])) ? $this->generate_block_data_ref(substr($varrefs[1], 0, -1), true, $varrefs[2]) . '[\'' . $varrefs[3] . '\']' : (($varrefs[2]) ? '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $varrefs[3] . '\']' : '$this->_tpldata[\'.\'][0][\'' . $varrefs[3] . '\']');
 468                      }
 469                      else if (preg_match('#^\.(([a-z0-9\-_]+\.?)+)$#s', $token, $varrefs))
 470                      {
 471                          // Allow checking if loops are set with .loopname
 472                          // It is also possible to check the loop count by doing <!-- IF .loopname > 1 --> for example
 473                          $_tok = $this->generate_block_data_ref($varrefs[1], false);
 474                          $token = "sizeof($_tok)";
 475                      }
 476  
 477                  break;
 478              }
 479          }
 480  
 481          return (($elseif) ? '} else if (' : 'if (') . (implode(' ', $tokens) . ') { ');
 482      }
 483  
 484      /**
 485      * Compile DEFINE tags
 486      * @access private
 487      */
 488  	function compile_tag_define($tag_args, $op)
 489      {
 490          preg_match('#^((?:[a-z0-9\-_]+\.)+)?\$(?=[A-Z])([A-Z0-9_\-]*)(?: = (\'?)([^\']*)(\'?))?$#', $tag_args, $match);
 491  
 492          if (empty($match[2]) || (!isset($match[4]) && $op))
 493          {
 494              return;
 495          }
 496  
 497          if (!$op)
 498          {
 499              return 'unset(' . (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ');';
 500          }
 501  
 502          // Are we a string?
 503          if ($match[3] && $match[5])
 504          {
 505              $match[4] = str_replace(array('\\\'', '\\\\', '\''), array('\'', '\\', '\\\''), $match[4]);
 506  
 507              // Compile reference, we allow template variables in defines...
 508              $match[4] = $this->compile($match[4]);
 509  
 510              // Now replace the php code
 511              $match[4] = "'" . str_replace(array('<?php echo ', '; ?>'), array("' . ", " . '"), $match[4]) . "'";
 512          }
 513          else
 514          {
 515              preg_match('#true|false|\.#i', $match[4], $type);
 516  
 517              switch (strtolower($type[0]))
 518              {
 519                  case 'true':
 520                  case 'false':
 521                      $match[4] = strtoupper($match[4]);
 522                  break;
 523  
 524                  case '.':
 525                      $match[4] = doubleval($match[4]);
 526                  break;
 527  
 528                  default:
 529                      $match[4] = intval($match[4]);
 530                  break;
 531              }
 532          }
 533  
 534          return (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ' = ' . $match[4] . ';';
 535      }
 536  
 537      /**
 538      * Compile INCLUDE tag
 539      * @access private
 540      */
 541  	function compile_tag_include($tag_args)
 542      {
 543          return "\$this->_tpl_include('$tag_args');";
 544      }
 545  
 546      /**
 547      * Compile INCLUDE_PHP tag
 548      * @access private
 549      */
 550  	function compile_tag_include_php($tag_args)
 551      {
 552          return "include('" . $tag_args . "');";
 553      }
 554  
 555      /**
 556      * parse expression
 557      * This is from Smarty
 558      * @access private
 559      */
 560  	function _parse_is_expr($is_arg, $tokens)
 561      {
 562          $expr_end = 0;
 563          $negate_expr = false;
 564  
 565          if (($first_token = array_shift($tokens)) == 'not')
 566          {
 567              $negate_expr = true;
 568              $expr_type = array_shift($tokens);
 569          }
 570          else
 571          {
 572              $expr_type = $first_token;
 573          }
 574  
 575          switch ($expr_type)
 576          {
 577              case 'even':
 578                  if (@$tokens[$expr_end] == 'by')
 579                  {
 580                      $expr_end++;
 581                      $expr_arg = $tokens[$expr_end++];
 582                      $expr = "!(($is_arg / $expr_arg) % $expr_arg)";
 583                  }
 584                  else
 585                  {
 586                      $expr = "!($is_arg % 2)";
 587                  }
 588              break;
 589  
 590              case 'odd':
 591                  if (@$tokens[$expr_end] == 'by')
 592                  {
 593                      $expr_end++;
 594                      $expr_arg = $tokens[$expr_end++];
 595                      $expr = "(($is_arg / $expr_arg) % $expr_arg)";
 596                  }
 597                  else
 598                  {
 599                      $expr = "($is_arg % 2)";
 600                  }
 601              break;
 602  
 603              case 'div':
 604                  if (@$tokens[$expr_end] == 'by')
 605                  {
 606                      $expr_end++;
 607                      $expr_arg = $tokens[$expr_end++];
 608                      $expr = "!($is_arg % $expr_arg)";
 609                  }
 610              break;
 611          }
 612  
 613          if ($negate_expr)
 614          {
 615              $expr = "!($expr)";
 616          }
 617  
 618          array_splice($tokens, 0, $expr_end, $expr);
 619  
 620          return $tokens;
 621      }
 622  
 623      /**
 624      * Generates a reference to the given variable inside the given (possibly nested)
 625      * block namespace. This is a string of the form:
 626      * ' . $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['varname'] . '
 627      * It's ready to be inserted into an "echo" line in one of the templates.
 628      * NOTE: expects a trailing "." on the namespace.
 629      * @access private
 630      */
 631  	function generate_block_varref($namespace, $varname, $echo = true, $defop = false)
 632      {
 633          // Strip the trailing period.
 634          $namespace = substr($namespace, 0, -1);
 635  
 636          // Get a reference to the data block for this namespace.
 637          $varref = $this->generate_block_data_ref($namespace, true, $defop);
 638          // Prepend the necessary code to stick this in an echo line.
 639  
 640          // Append the variable reference.
 641          $varref .= "['$varname']";
 642          $varref = ($echo) ? "<?php echo $varref; ?>" : ((isset($varref)) ? $varref : '');
 643  
 644          return $varref;
 645      }
 646  
 647      /**
 648      * Generates a reference to the array of data values for the given
 649      * (possibly nested) block namespace. This is a string of the form:
 650      * $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['$childN']
 651      *
 652      * If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above.
 653      * NOTE: does not expect a trailing "." on the blockname.
 654      * @access private
 655      */
 656  	function generate_block_data_ref($blockname, $include_last_iterator, $defop = false)
 657      {
 658          // Get an array of the blocks involved.
 659          $blocks = explode('.', $blockname);
 660          $blockcount = sizeof($blocks) - 1;
 661          $varref = '$this->_tpldata' . (($defop) ? '[\'DEFINE\']' : '');
 662  
 663          // Build up the string with everything but the last child.
 664          for ($i = 0; $i < $blockcount; $i++)
 665          {
 666              $varref .= "['" . $blocks[$i] . "'][\$this->_" . $blocks[$i] . '_i]';
 667          }
 668  
 669          // Add the block reference for the last child.
 670          $varref .= "['" . $blocks[$blockcount] . "']";
 671  
 672          // Add the iterator for the last child if requried.
 673          if ($include_last_iterator)
 674          {
 675              $varref .= '[$this->_' . $blocks[$blockcount] . '_i]';
 676          }
 677  
 678          return $varref;
 679      }
 680  
 681      /**
 682      * Write compiled file to cache directory
 683      * @access private
 684      */
 685  	function compile_write(&$handle, $data)
 686      {
 687          global $phpEx, $user;
 688  
 689          $filename = $this->template->cachepath . str_replace('/', '.', $this->template->filename[$handle]) . '.' . $phpEx;
 690  
 691          if ($fp = @fopen($filename, 'wb'))
 692          {
 693              @flock($fp, LOCK_EX);
 694              @fwrite ($fp, $data);
 695              @flock($fp, LOCK_UN);
 696              @fclose($fp);
 697  
 698              @umask(0);
 699              @chmod($filename, 0644);
 700          }
 701  
 702          return;
 703      }
 704  }
 705  
 706  ?>


Generated: Wed Nov 22 00:35:05 2006 Cross-referenced by PHPXref 0.6