[ Index ]
 

Code source de PHP NUKE 7.9

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/includes/ -> template.php (source)

   1  <?php
   2  /***************************************************************************
   3   *                              template.php
   4   *                            -------------------
   5   *   begin                : Saturday, Feb 13, 2001
   6   *   copyright            : (C) 2001 The phpBB Group
   7   *   email                : support@phpbb.com
   8   *
   9   *   $Id: template.php,v 1.10.2.4 2005/02/21 18:37:50 acydburn Exp $
  10   *
  11   *
  12   ***************************************************************************/
  13  
  14  /***************************************************************************
  15   *
  16   *   This program is free software; you can redistribute it and/or modify
  17   *   it under the terms of the GNU General Public License as published by
  18   *   the Free Software Foundation; either version 2 of the License, or
  19   *   (at your option) any later version.
  20   *
  21   ***************************************************************************/
  22  
  23  /**
  24   * Template class. By Nathan Codding of the phpBB group.
  25   * The interface was originally inspired by PHPLib templates,
  26   * and the template file formats are quite similar.
  27   *
  28   */
  29  
  30  if (!defined('IN_PHPBB')) {
  31      die();
  32  }
  33  class Template {
  34          var $classname = "Template";
  35  
  36          // variable that holds all the data we'll be substituting into
  37          // the compiled templates.
  38          // ...
  39          // This will end up being a multi-dimensional array like this:
  40          // $this->_tpldata[block.][iteration#][child.][iteration#][child2.][iteration#][variablename] == value
  41          // if it's a root-level variable, it'll be like this:
  42          // $this->_tpldata[.][0][varname] == value
  43          var $_tpldata = array();
  44  
  45          // Hash of filenames for each template handle.
  46          var $files = array();
  47  
  48          // Root template directory.
  49          var $root = "";
  50  
  51          // this will hash handle names to the compiled code for that handle.
  52          var $compiled_code = array();
  53  
  54          // This will hold the uncompiled code for that handle.
  55          var $uncompiled_code = array();
  56  
  57          /**
  58           * Constructor. Simply sets the root dir.
  59           *
  60           */
  61          function Template($root = ".")
  62          {
  63                  $this->set_rootdir($root);
  64          }
  65  
  66          /**
  67           * Destroys this template object. Should be called when you're done with it, in order
  68           * to clear out the template data so you can load/parse a new template set.
  69           */
  70          function destroy()
  71          {
  72                  $this->_tpldata = array();
  73          }
  74  
  75          /**
  76           * Sets the template root directory for this Template object.
  77           */
  78          function set_rootdir($dir)
  79          {
  80                  if (!is_dir($dir))
  81                  {
  82                          return false;
  83                  }
  84  
  85                  $this->root = $dir;
  86                  return true;
  87          }
  88  
  89          /**
  90           * Sets the template filenames for handles. $filename_array
  91           * should be a hash of handle => filename pairs.
  92           */
  93          function set_filenames($filename_array)
  94          {
  95                  if (!is_array($filename_array))
  96                  {
  97                          return false;
  98                  }
  99  
 100                  reset($filename_array);
 101                  while(list($handle, $filename) = each($filename_array))
 102                  {
 103                          $this->files[$handle] = $this->make_filename($filename);
 104                  }
 105  
 106                  return true;
 107          }
 108  
 109  
 110          /**
 111           * Load the file for the handle, compile the file,
 112           * and run the compiled code. This will print out
 113           * the results of executing the template.
 114           */
 115          function pparse($handle)
 116          {
 117                  if (!$this->loadfile($handle))
 118                  {
 119                          die("Template->pparse(): Couldn't load template file for handle $handle");
 120                  }
 121  
 122                  // actually compile the template now.
 123                  if (!isset($this->compiled_code[$handle]) || empty($this->compiled_code[$handle]))
 124                  {
 125                          // Actually compile the code now.
 126                          $this->compiled_code[$handle] = $this->compile($this->uncompiled_code[$handle]);
 127                  }
 128  
 129                  // Run the compiled code.
 130                  eval($this->compiled_code[$handle]);
 131                  return true;
 132          }
 133  
 134          /**
 135           * Inserts the uncompiled code for $handle as the
 136           * value of $varname in the root-level. This can be used
 137           * to effectively include a template in the middle of another
 138           * template.
 139           * Note that all desired assignments to the variables in $handle should be done
 140           * BEFORE calling this function.
 141           */
 142          function assign_var_from_handle($varname, $handle)
 143          {
 144                  if (!$this->loadfile($handle))
 145                  {
 146                          die("Template->assign_var_from_handle(): Couldn't load template file for handle $handle");
 147                  }
 148  
 149                  // Compile it, with the "no echo statements" option on.
 150                  $_str = "";
 151                  $code = $this->compile($this->uncompiled_code[$handle], true, '_str');
 152  
 153                  // evaluate the variable assignment.
 154                  eval($code);
 155                  // assign the value of the generated variable to the given varname.
 156                  $this->assign_var($varname, $_str);
 157  
 158                  return true;
 159          }
 160  
 161          /**
 162           * Block-level variable assignment. Adds a new block iteration with the given
 163           * variable assignments. Note that this should only be called once per block
 164           * iteration.
 165           */
 166          function assign_block_vars($blockname, $vararray)
 167          {
 168                  if (strstr($blockname, '.'))
 169                  {
 170                          // Nested block.
 171                          $blocks = explode('.', $blockname);
 172                          $blockcount = sizeof($blocks) - 1;
 173                          $str = '$this->_tpldata';
 174                          for ($i = 0; $i < $blockcount; $i++)
 175                          {
 176                                  $str .= '[\'' . $blocks[$i] . '.\']';
 177                                  eval('$lastiteration = sizeof(' . $str . ') - 1;');
 178                                  $str .= '[' . $lastiteration . ']';
 179                          }
 180                          // Now we add the block that we're actually assigning to.
 181                          // We're adding a new iteration to this block with the given
 182                          // variable assignments.
 183                          $str .= '[\'' . $blocks[$blockcount] . '.\'][] = $vararray;';
 184  
 185                          // Now we evaluate this assignment we've built up.
 186                          eval($str);
 187                  }
 188                  else
 189                  {
 190                          // Top-level block.
 191                          // Add a new iteration to this block with the variable assignments
 192                          // we were given.
 193                          $this->_tpldata[$blockname . '.'][] = $vararray;
 194                  }
 195  
 196                  return true;
 197          }
 198  
 199          /**
 200           * Root-level variable assignment. Adds to current assignments, overriding
 201           * any existing variable assignment with the same name.
 202           */
 203          function assign_vars($vararray)
 204          {
 205                  reset ($vararray);
 206                  while (list($key, $val) = each($vararray))
 207                  {
 208                          $this->_tpldata['.'][0][$key] = $val;
 209                  }
 210  
 211                  return true;
 212          }
 213  
 214          /**
 215           * Root-level variable assignment. Adds to current assignments, overriding
 216           * any existing variable assignment with the same name.
 217           */
 218          function assign_var($varname, $varval)
 219          {
 220                  $this->_tpldata['.'][0][$varname] = $varval;
 221  
 222                  return true;
 223          }
 224  
 225  
 226          /**
 227           * Generates a full path+filename for the given filename, which can either
 228           * be an absolute name, or a name relative to the rootdir for this Template
 229           * object.
 230           */
 231          function make_filename($filename)
 232          {
 233                  // Check if it's an absolute or relative path.
 234                  if (substr($filename, 0, 1) != '/')
 235                  {
 236                         $filename = ($rp_filename = phpbb_realpath($this->root . '/' . $filename)) ? $rp_filename : $filename;
 237                  }
 238  
 239                  if (!file_exists($filename))
 240                  {
 241                          die("Template->make_filename(): Error - file $filename does not exist");
 242                  }
 243  
 244                  return $filename;
 245          }
 246  
 247  
 248          /**
 249           * If not already done, load the file for the given handle and populate
 250           * the uncompiled_code[] hash with its code. Do not compile.
 251           */
 252          function loadfile($handle)
 253          {
 254                  // If the file for this handle is already loaded and compiled, do nothing.
 255                  if (isset($this->uncompiled_code[$handle]) && !empty($this->uncompiled_code[$handle]))
 256                  {
 257                          return true;
 258                  }
 259  
 260                  // If we don't have a file assigned to this handle, die.
 261                  if (!isset($this->files[$handle]))
 262                  {
 263                          die("Template->loadfile(): No file specified for handle $handle");
 264                  }
 265  
 266                  $filename = $this->files[$handle];
 267  
 268                  $str = implode("", @file($filename));
 269                  if (empty($str))
 270                  {
 271                          die("Template->loadfile(): File $filename for handle $handle is empty");
 272                  }
 273  
 274                  $this->uncompiled_code[$handle] = $str;
 275  
 276                  return true;
 277          }
 278  
 279  
 280  
 281          /**
 282           * Compiles the given string of code, and returns
 283           * the result in a string.
 284           * If "do_not_echo" is true, the returned code will not be directly
 285           * executable, but can be used as part of a variable assignment
 286           * for use in assign_code_from_handle().
 287           */
 288          function compile($code, $do_not_echo = false, $retvar = '')
 289          {
 290                  // replace \ with \\ and then ' with \'.
 291                  $code = str_replace('\\', '\\\\', $code);
 292                  $code = str_replace('\'', '\\\'', $code);
 293  
 294                  // change template varrefs into PHP varrefs
 295  
 296                  // This one will handle varrefs WITH namespaces
 297                  $varrefs = array();
 298                  preg_match_all('#\{(([a-z0-9\-_]+?\.)+?)([a-z0-9\-_]+?)\}#is', $code, $varrefs);
 299                  $varcount = sizeof($varrefs[1]);
 300                  for ($i = 0; $i < $varcount; $i++)
 301                  {
 302                          $namespace = $varrefs[1][$i];
 303                          $varname = $varrefs[3][$i];
 304                          $new = $this->generate_block_varref($namespace, $varname);
 305  
 306                          $code = str_replace($varrefs[0][$i], $new, $code);
 307                  }
 308  
 309                  // This will handle the remaining root-level varrefs
 310                  $code = preg_replace('#\{([a-z0-9\-_]*?)\}#is', '\' . ( ( isset($this->_tpldata[\'.\'][0][\'\1\']) ) ? $this->_tpldata[\'.\'][0][\'\1\'] : \'\' ) . \'', $code);
 311  
 312                  // Break it up into lines.
 313                  $code_lines = explode("\n", $code);
 314  
 315                  $block_nesting_level = 0;
 316                  $block_names = array();
 317                  $block_names[0] = ".";
 318  
 319                  // Second: prepend echo ', append ' . "\n"; to each line.
 320                  $line_count = sizeof($code_lines);
 321                  for ($i = 0; $i < $line_count; $i++)
 322                  {
 323                          $code_lines[$i] = chop($code_lines[$i]);
 324                          if (preg_match('#<!-- BEGIN (.*?) -->#', $code_lines[$i], $m))
 325                          {
 326                                  $n[0] = $m[0];
 327                                  $n[1] = $m[1];
 328  
 329                                  // Added: dougk_ff7-Keeps templates from bombing if begin is on the same line as end.. I think. :)
 330                                  if ( preg_match('#<!-- END (.*?) -->#', $code_lines[$i], $n) )
 331                                  {
 332                                          $block_nesting_level++;
 333                                          $block_names[$block_nesting_level] = $m[1];
 334                                          if ($block_nesting_level < 2)
 335                                          {
 336                                                  // Block is not nested.
 337                                                  $code_lines[$i] = '$_' . $n[1] . '_count = ( isset($this->_tpldata[\'' . $n[1] . '.\']) ) ?  sizeof($this->_tpldata[\'' . $n[1] . '.\']) : 0;';
 338                                                  $code_lines[$i] .= "\n" . 'for ($_' . $n[1] . '_i = 0; $_' . $n[1] . '_i < $_' . $n[1] . '_count; $_' . $n[1] . '_i++)';
 339                                                  $code_lines[$i] .= "\n" . '{';
 340                                          }
 341                                          else
 342                                          {
 343                                                  // This block is nested.
 344  
 345                                                  // Generate a namespace string for this block.
 346                                                  $namespace = implode('.', $block_names);
 347                                                  // strip leading period from root level..
 348                                                  $namespace = substr($namespace, 2);
 349                                                  // Get a reference to the data array for this block that depends on the
 350                                                  // current indices of all parent blocks.
 351                                                  $varref = $this->generate_block_data_ref($namespace, false);
 352                                                  // Create the for loop code to iterate over this block.
 353                                                  $code_lines[$i] = '$_' . $n[1] . '_count = ( isset(' . $varref . ') ) ? sizeof(' . $varref . ') : 0;';
 354                                                  $code_lines[$i] .= "\n" . 'for ($_' . $n[1] . '_i = 0; $_' . $n[1] . '_i < $_' . $n[1] . '_count; $_' . $n[1] . '_i++)';
 355                                                  $code_lines[$i] .= "\n" . '{';
 356                                          }
 357  
 358                                          // We have the end of a block.
 359                                          unset($block_names[$block_nesting_level]);
 360                                          $block_nesting_level--;
 361                                          $code_lines[$i] .= '} // END ' . $n[1];
 362                                          $m[0] = $n[0];
 363                                          $m[1] = $n[1];
 364                                  }
 365                                  else
 366                                  {
 367                                          // We have the start of a block.
 368                                          $block_nesting_level++;
 369                                          $block_names[$block_nesting_level] = $m[1];
 370                                          if ($block_nesting_level < 2)
 371                                          {
 372                                                  // Block is not nested.
 373                                                  $code_lines[$i] = '$_' . $m[1] . '_count = ( isset($this->_tpldata[\'' . $m[1] . '.\']) ) ? sizeof($this->_tpldata[\'' . $m[1] . '.\']) : 0;';
 374                                                  $code_lines[$i] .= "\n" . 'for ($_' . $m[1] . '_i = 0; $_' . $m[1] . '_i < $_' . $m[1] . '_count; $_' . $m[1] . '_i++)';
 375                                                  $code_lines[$i] .= "\n" . '{';
 376                                          }
 377                                          else
 378                                          {
 379                                                  // This block is nested.
 380  
 381                                                  // Generate a namespace string for this block.
 382                                                  $namespace = implode('.', $block_names);
 383                                                  // strip leading period from root level..
 384                                                  $namespace = substr($namespace, 2);
 385                                                  // Get a reference to the data array for this block that depends on the
 386                                                  // current indices of all parent blocks.
 387                                                  $varref = $this->generate_block_data_ref($namespace, false);
 388                                                  // Create the for loop code to iterate over this block.
 389                                                  $code_lines[$i] = '$_' . $m[1] . '_count = ( isset(' . $varref . ') ) ? sizeof(' . $varref . ') : 0;';
 390                                                  $code_lines[$i] .= "\n" . 'for ($_' . $m[1] . '_i = 0; $_' . $m[1] . '_i < $_' . $m[1] . '_count; $_' . $m[1] . '_i++)';
 391                                                  $code_lines[$i] .= "\n" . '{';
 392                                          }
 393                                  }
 394                          }
 395                          else if (preg_match('#<!-- END (.*?) -->#', $code_lines[$i], $m))
 396                          {
 397                                  // We have the end of a block.
 398                                  unset($block_names[$block_nesting_level]);
 399                                  $block_nesting_level--;
 400                                  $code_lines[$i] = '} // END ' . $m[1];
 401                          }
 402                          else
 403                          {
 404                                  // We have an ordinary line of code.
 405                                  if (!$do_not_echo)
 406                                  {
 407                                          $code_lines[$i] = 'echo \'' . $code_lines[$i] . '\' . "\\n";';
 408                                  }
 409                                  else
 410                                  {
 411                                          $code_lines[$i] = '$' . $retvar . '.= \'' . $code_lines[$i] . '\' . "\\n";';
 412                                  }
 413                          }
 414                  }
 415  
 416                  // Bring it back into a single string of lines of code.
 417                  $code = implode("\n", $code_lines);
 418                  return $code        ;
 419  
 420          }
 421  
 422  
 423          /**
 424           * Generates a reference to the given variable inside the given (possibly nested)
 425           * block namespace. This is a string of the form:
 426           * ' . $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['varname'] . '
 427           * It's ready to be inserted into an "echo" line in one of the templates.
 428           * NOTE: expects a trailing "." on the namespace.
 429           */
 430          function generate_block_varref($namespace, $varname)
 431          {
 432                  // Strip the trailing period.
 433                  $namespace = substr($namespace, 0, strlen($namespace) - 1);
 434  
 435                  // Get a reference to the data block for this namespace.
 436                  $varref = $this->generate_block_data_ref($namespace, true);
 437                  // Prepend the necessary code to stick this in an echo line.
 438  
 439                  // Append the variable reference.
 440                  $varref .= '[\'' . $varname . '\']';
 441  
 442                  $varref = '\' . ( ( isset(' . $varref . ') ) ? ' . $varref . ' : \'\' ) . \'';
 443  
 444                  return $varref;
 445  
 446          }
 447  
 448  
 449          /**
 450           * Generates a reference to the array of data values for the given
 451           * (possibly nested) block namespace. This is a string of the form:
 452           * $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['$childN']
 453           *
 454           * If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above.
 455           * NOTE: does not expect a trailing "." on the blockname.
 456           */
 457          function generate_block_data_ref($blockname, $include_last_iterator)
 458          {
 459                  // Get an array of the blocks involved.
 460                  $blocks = explode(".", $blockname);
 461                  $blockcount = sizeof($blocks) - 1;
 462                  $varref = '$this->_tpldata';
 463                  // Build up the string with everything but the last child.
 464                  for ($i = 0; $i < $blockcount; $i++)
 465                  {
 466                          $varref .= '[\'' . $blocks[$i] . '.\'][$_' . $blocks[$i] . '_i]';
 467                  }
 468                  // Add the block reference for the last child.
 469                  $varref .= '[\'' . $blocks[$blockcount] . '.\']';
 470                  // Add the iterator for the last child if requried.
 471                  if ($include_last_iterator)
 472                  {
 473                          $varref .= '[$_' . $blocks[$blockcount] . '_i]';
 474                  }
 475  
 476                  return $varref;
 477          }
 478  
 479  }
 480  
 481  ?>


Généré le : Sun Apr 1 11:11:59 2007 par Balluche grâce à PHPXref 0.7