[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/includes/ -> template.php (source)

   1  <?php
   2  /**
   3  *
   4  * @package phpBB3
   5  * @version $Id$
   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  * @ignore
  13  */
  14  if (!defined('IN_PHPBB'))
  15  {
  16      exit;
  17  }
  18  
  19  /**
  20  * Base Template class.
  21  * @package phpBB3
  22  */
  23  class template
  24  {
  25      /** variable that holds all the data we'll be substituting into
  26      * the compiled templates. Takes form:
  27      * --> $this->_tpldata[block][iteration#][child][iteration#][child2][iteration#][variablename] == value
  28      * if it's a root-level variable, it'll be like this:
  29      * --> $this->_tpldata[.][0][varname] == value
  30      */
  31      var $_tpldata = array('.' => array(0 => array()));
  32      var $_rootref;
  33  
  34      // Root dir and hash of filenames for each template handle.
  35      var $root = '';
  36      var $cachepath = '';
  37      var $files = array();
  38      var $filename = array();
  39      var $files_inherit = array();
  40      var $files_template = array();
  41      var $inherit_root = '';
  42      var $orig_tpl_storedb;
  43      var $orig_tpl_inherits_id;
  44  
  45      // this will hash handle names to the compiled/uncompiled code for that handle.
  46      var $compiled_code = array();
  47  
  48      /**
  49      * Set template location
  50      * @access public
  51      */
  52  	function set_template()
  53      {
  54          global $phpbb_root_path, $user;
  55  
  56          if (file_exists($phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template'))
  57          {
  58              $this->root = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template';
  59              $this->cachepath = $phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $user->theme['template_path']) . '_';
  60  
  61              if ($this->orig_tpl_storedb === null)
  62              {
  63                  $this->orig_tpl_storedb = $user->theme['template_storedb'];
  64              }
  65  
  66              if ($this->orig_tpl_inherits_id === null)
  67              {
  68                  $this->orig_tpl_inherits_id = $user->theme['template_inherits_id'];
  69              }
  70  
  71              $user->theme['template_storedb'] = $this->orig_tpl_storedb;
  72              $user->theme['template_inherits_id'] = $this->orig_tpl_inherits_id;
  73  
  74              if ($user->theme['template_inherits_id'])
  75              {
  76                  $this->inherit_root = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template';
  77              }
  78          }
  79          else
  80          {
  81              trigger_error('Template path could not be found: styles/' . $user->theme['template_path'] . '/template', E_USER_ERROR);
  82          }
  83  
  84          $this->_rootref = &$this->_tpldata['.'][0];
  85  
  86          return true;
  87      }
  88  
  89      /**
  90      * Set custom template location (able to use directory outside of phpBB)
  91      * @access public
  92      */
  93  	function set_custom_template($template_path, $template_name, $fallback_template_path = false)
  94      {
  95          global $phpbb_root_path, $user;
  96  
  97          // Make sure $template_path has no ending slash
  98          if (substr($template_path, -1) == '/')
  99          {
 100              $template_path = substr($template_path, 0, -1);
 101          }
 102  
 103          $this->root = $template_path;
 104          $this->cachepath = $phpbb_root_path . 'cache/ctpl_' . str_replace('_', '-', $template_name) . '_';
 105  
 106          if ($fallback_template_path !== false)
 107          {
 108              if (substr($fallback_template_path, -1) == '/')
 109              {
 110                  $fallback_template_path = substr($fallback_template_path, 0, -1);
 111              }
 112  
 113              $this->inherit_root = $fallback_template_path;
 114              $this->orig_tpl_inherits_id = true;
 115          }
 116          else
 117          {
 118              $this->orig_tpl_inherits_id = false;
 119          }
 120  
 121          // the database does not store the path or name of a custom template
 122          // so there is no way we can properly store custom templates there
 123          $this->orig_tpl_storedb = false;
 124  
 125          $this->_rootref = &$this->_tpldata['.'][0];
 126  
 127          return true;
 128      }
 129  
 130      /**
 131      * Sets the template filenames for handles. $filename_array
 132      * should be a hash of handle => filename pairs.
 133      * @access public
 134      */
 135  	function set_filenames($filename_array)
 136      {
 137          if (!is_array($filename_array))
 138          {
 139              return false;
 140          }
 141          foreach ($filename_array as $handle => $filename)
 142          {
 143              if (empty($filename))
 144              {
 145                  trigger_error("template->set_filenames: Empty filename specified for $handle", E_USER_ERROR);
 146              }
 147  
 148              $this->filename[$handle] = $filename;
 149              $this->files[$handle] = $this->root . '/' . $filename;
 150  
 151              if ($this->inherit_root)
 152              {
 153                  $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename;
 154              }
 155          }
 156  
 157          return true;
 158      }
 159  
 160      /**
 161      * Destroy template data set
 162      * @access public
 163      */
 164  	function destroy()
 165      {
 166          $this->_tpldata = array('.' => array(0 => array()));
 167          $this->_rootref = &$this->_tpldata['.'][0];
 168      }
 169  
 170      /**
 171      * Reset/empty complete block
 172      * @access public
 173      */
 174  	function destroy_block_vars($blockname)
 175      {
 176          if (strpos($blockname, '.') !== false)
 177          {
 178              // Nested block.
 179              $blocks = explode('.', $blockname);
 180              $blockcount = sizeof($blocks) - 1;
 181  
 182              $str = &$this->_tpldata;
 183              for ($i = 0; $i < $blockcount; $i++)
 184              {
 185                  $str = &$str[$blocks[$i]];
 186                  $str = &$str[sizeof($str) - 1];
 187              }
 188  
 189              unset($str[$blocks[$blockcount]]);
 190          }
 191          else
 192          {
 193              // Top-level block.
 194              unset($this->_tpldata[$blockname]);
 195          }
 196  
 197          return true;
 198      }
 199  
 200      /**
 201      * Display handle
 202      * @access public
 203      */
 204  	function display($handle, $include_once = true)
 205      {
 206          global $user, $phpbb_hook;
 207  
 208          if (!empty($phpbb_hook) && $phpbb_hook->call_hook(array(__CLASS__, __FUNCTION__), $handle, $include_once, $this))
 209          {
 210              if ($phpbb_hook->hook_return(array(__CLASS__, __FUNCTION__)))
 211              {
 212                  return $phpbb_hook->hook_return_result(array(__CLASS__, __FUNCTION__));
 213              }
 214          }
 215  
 216          if (defined('IN_ERROR_HANDLER'))
 217          {
 218              if ((E_NOTICE & error_reporting()) == E_NOTICE)
 219              {
 220                  error_reporting(error_reporting() ^ E_NOTICE);
 221              }
 222          }
 223  
 224          if ($filename = $this->_tpl_load($handle))
 225          {
 226              ($include_once) ? include_once($filename) : include($filename);
 227          }
 228          else
 229          {
 230              eval(' ?>' . $this->compiled_code[$handle] . '<?php ');
 231          }
 232  
 233          return true;
 234      }
 235  
 236      /**
 237      * Display the handle and assign the output to a template variable or return the compiled result.
 238      * @access public
 239      */
 240  	function assign_display($handle, $template_var = '', $return_content = true, $include_once = false)
 241      {
 242          ob_start();
 243          $this->display($handle, $include_once);
 244          $contents = ob_get_clean();
 245  
 246          if ($return_content)
 247          {
 248              return $contents;
 249          }
 250  
 251          $this->assign_var($template_var, $contents);
 252  
 253          return true;
 254      }
 255  
 256      /**
 257      * Load a compiled template if possible, if not, recompile it
 258      * @access private
 259      */
 260  	function _tpl_load(&$handle)
 261      {
 262          global $user, $phpEx, $config;
 263  
 264          if (!isset($this->filename[$handle]))
 265          {
 266              trigger_error("template->_tpl_load(): No file specified for handle $handle", E_USER_ERROR);
 267          }
 268  
 269          // reload these settings to have the values they had when this object was initialised
 270          // using set_template or set_custom_template, they might otherwise have been overwritten
 271          // by other template class instances in between.
 272          $user->theme['template_storedb'] = $this->orig_tpl_storedb;
 273          $user->theme['template_inherits_id'] = $this->orig_tpl_inherits_id;
 274  
 275          $filename = $this->cachepath . str_replace('/', '.', $this->filename[$handle]) . '.' . $phpEx;
 276          $this->files_template[$handle] = (isset($user->theme['template_id'])) ? $user->theme['template_id'] : 0;
 277  
 278          $recompile = false;
 279          if (!file_exists($filename) || @filesize($filename) === 0 || defined('DEBUG_EXTRA'))
 280          {
 281              $recompile = true;
 282          }
 283          else if ($config['load_tplcompile'])
 284          {
 285              // No way around it: we need to check inheritance here
 286              if ($user->theme['template_inherits_id'] && !file_exists($this->files[$handle]))
 287              {
 288                  $this->files[$handle] = $this->files_inherit[$handle];
 289                  $this->files_template[$handle] = $user->theme['template_inherits_id'];
 290              }
 291              $recompile = (@filemtime($filename) < filemtime($this->files[$handle])) ? true : false;
 292          }
 293  
 294          // Recompile page if the original template is newer, otherwise load the compiled version
 295          if (!$recompile)
 296          {
 297              return $filename;
 298          }
 299  
 300          global $db, $phpbb_root_path;
 301  
 302          if (!class_exists('template_compile'))
 303          {
 304              include($phpbb_root_path . 'includes/functions_template.' . $phpEx);
 305          }
 306  
 307          // Inheritance - we point to another template file for this one. Equality is also used for store_db
 308          if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($this->files[$handle]))
 309          {
 310              $this->files[$handle] = $this->files_inherit[$handle];
 311              $this->files_template[$handle] = $user->theme['template_inherits_id'];
 312          }
 313  
 314          $compile = new template_compile($this);
 315  
 316          // If we don't have a file assigned to this handle, die.
 317          if (!isset($this->files[$handle]))
 318          {
 319              trigger_error("template->_tpl_load(): No file specified for handle $handle", E_USER_ERROR);
 320          }
 321  
 322          // Just compile if no user object is present (happens within the installer)
 323          if (!$user)
 324          {
 325              $compile->_tpl_load_file($handle);
 326              return false;
 327          }
 328  
 329          if (isset($user->theme['template_storedb']) && $user->theme['template_storedb'])
 330          {
 331              $rows = array();
 332              $ids = array();
 333              // Inheritance
 334              if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'])
 335              {
 336                  $ids[] = $user->theme['template_inherits_id'];
 337              }
 338              $ids[] = $user->theme['template_id'];
 339  
 340              foreach ($ids as $id)
 341              {
 342                  $sql = 'SELECT *
 343                  FROM ' . STYLES_TEMPLATE_DATA_TABLE . '
 344                  WHERE template_id = ' . $id . "
 345                      AND (template_filename = '" . $db->sql_escape($this->filename[$handle]) . "'
 346                          OR template_included " . $db->sql_like_expression($db->any_char . $this->filename[$handle] . ':' . $db->any_char) . ')';
 347  
 348                  $result = $db->sql_query($sql);
 349                  while ($row = $db->sql_fetchrow($result))
 350                  {
 351                      $rows[$row['template_filename']] = $row;
 352                  }
 353                  $db->sql_freeresult($result);
 354              }
 355  
 356              if (sizeof($rows))
 357              {
 358                  foreach ($rows as $row)
 359                  {
 360                      $file = $this->root . '/' . $row['template_filename'];
 361                      $force_reload = false;
 362                      if ($row['template_id'] != $user->theme['template_id'])
 363                      {
 364                          // make sure that we are not overlooking a file not in the db yet
 365                          if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($file))
 366                          {
 367                              $file = $this->inherit_root . '/' . $row['template_filename'];
 368                              $this->files[$row['template_filename']] = $file;
 369                              $this->files_inherit[$row['template_filename']] = $file;
 370                              $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id'];
 371                          }
 372                          else if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'])
 373                          {
 374                              // Ok, we have a situation. There is a file in the subtemplate, but nothing in the DB. We have to fix that.
 375                              $force_reload = true;
 376                              $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id'];
 377                          }
 378                      }
 379                      else
 380                      {
 381                          $this->files_template[$row['template_filename']] = $user->theme['template_id'];
 382                      }
 383  
 384                      if ($force_reload || $row['template_mtime'] < filemtime($file))
 385                      {
 386                          if ($row['template_filename'] == $this->filename[$handle])
 387                          {
 388                              $compile->_tpl_load_file($handle, true);
 389                          }
 390                          else
 391                          {
 392                              $this->files[$row['template_filename']] = $file;
 393                              $this->filename[$row['template_filename']] = $row['template_filename'];
 394                              $compile->_tpl_load_file($row['template_filename'], true);
 395                              unset($this->compiled_code[$row['template_filename']]);
 396                              unset($this->files[$row['template_filename']]);
 397                              unset($this->filename[$row['template_filename']]);
 398                          }
 399                      }
 400  
 401                      if ($row['template_filename'] == $this->filename[$handle])
 402                      {
 403                          $this->compiled_code[$handle] = $compile->compile(trim($row['template_data']));
 404                          $compile->compile_write($handle, $this->compiled_code[$handle]);
 405                      }
 406                      else
 407                      {
 408                          // Only bother compiling if it doesn't already exist
 409                          if (!file_exists($this->cachepath . str_replace('/', '.', $row['template_filename']) . '.' . $phpEx))
 410                          {
 411                              $this->filename[$row['template_filename']] = $row['template_filename'];
 412                              $compile->compile_write($row['template_filename'], $compile->compile(trim($row['template_data'])));
 413                              unset($this->filename[$row['template_filename']]);
 414                          }
 415                      }
 416                  }
 417              }
 418              else
 419              {
 420                  $file = $this->root . '/' . $row['template_filename'];
 421  
 422                  if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($file))
 423                  {
 424                      $file = $this->inherit_root . '/' . $row['template_filename'];
 425                      $this->files[$row['template_filename']] = $file;
 426                      $this->files_inherit[$row['template_filename']] = $file;
 427                      $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id'];
 428                  }
 429                  // Try to load from filesystem and instruct to insert into the styles table...
 430                  $compile->_tpl_load_file($handle, true);
 431                  return false;
 432              }
 433  
 434              return false;
 435          }
 436  
 437          $compile->_tpl_load_file($handle);
 438          return false;
 439      }
 440  
 441      /**
 442      * Assign key variable pairs from an array
 443      * @access public
 444      */
 445  	function assign_vars($vararray)
 446      {
 447          foreach ($vararray as $key => $val)
 448          {
 449              $this->_rootref[$key] = $val;
 450          }
 451  
 452          return true;
 453      }
 454  
 455      /**
 456      * Assign a single variable to a single key
 457      * @access public
 458      */
 459  	function assign_var($varname, $varval)
 460      {
 461          $this->_rootref[$varname] = $varval;
 462  
 463          return true;
 464      }
 465  
 466      /**
 467      * Assign key variable pairs from an array to a specified block
 468      * @access public
 469      */
 470  	function assign_block_vars($blockname, $vararray)
 471      {
 472          if (strpos($blockname, '.') !== false)
 473          {
 474              // Nested block.
 475              $blocks = explode('.', $blockname);
 476              $blockcount = sizeof($blocks) - 1;
 477  
 478              $str = &$this->_tpldata;
 479              for ($i = 0; $i < $blockcount; $i++)
 480              {
 481                  $str = &$str[$blocks[$i]];
 482                  $str = &$str[sizeof($str) - 1];
 483              }
 484  
 485              $s_row_count = isset($str[$blocks[$blockcount]]) ? sizeof($str[$blocks[$blockcount]]) : 0;
 486              $vararray['S_ROW_COUNT'] = $s_row_count;
 487  
 488              // Assign S_FIRST_ROW
 489              if (!$s_row_count)
 490              {
 491                  $vararray['S_FIRST_ROW'] = true;
 492              }
 493  
 494              // Now the tricky part, we always assign S_LAST_ROW and remove the entry before
 495              // This is much more clever than going through the complete template data on display (phew)
 496              $vararray['S_LAST_ROW'] = true;
 497              if ($s_row_count > 0)
 498              {
 499                  unset($str[$blocks[$blockcount]][($s_row_count - 1)]['S_LAST_ROW']);
 500              }
 501  
 502              // Now we add the block that we're actually assigning to.
 503              // We're adding a new iteration to this block with the given
 504              // variable assignments.
 505              $str[$blocks[$blockcount]][] = $vararray;
 506          }
 507          else
 508          {
 509              // Top-level block.
 510              $s_row_count = (isset($this->_tpldata[$blockname])) ? sizeof($this->_tpldata[$blockname]) : 0;
 511              $vararray['S_ROW_COUNT'] = $s_row_count;
 512  
 513              // Assign S_FIRST_ROW
 514              if (!$s_row_count)
 515              {
 516                  $vararray['S_FIRST_ROW'] = true;
 517              }
 518  
 519              // We always assign S_LAST_ROW and remove the entry before
 520              $vararray['S_LAST_ROW'] = true;
 521              if ($s_row_count > 0)
 522              {
 523                  unset($this->_tpldata[$blockname][($s_row_count - 1)]['S_LAST_ROW']);
 524              }
 525  
 526              // Add a new iteration to this block with the variable assignments we were given.
 527              $this->_tpldata[$blockname][] = $vararray;
 528          }
 529  
 530          return true;
 531      }
 532  
 533      /**
 534      * Change already assigned key variable pair (one-dimensional - single loop entry)
 535      *
 536      * An example of how to use this function:
 537      * {@example alter_block_array.php}
 538      *
 539      * @param    string    $blockname    the blockname, for example 'loop'
 540      * @param    array    $vararray    the var array to insert/add or merge
 541      * @param    mixed    $key        Key to search for
 542      *
 543      * array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position]
 544      *
 545      * int: Position [the position to change or insert at directly given]
 546      *
 547      * If key is false the position is set to 0
 548      * If key is true the position is set to the last entry
 549      *
 550      * @param    string    $mode        Mode to execute (valid modes are 'insert' and 'change')
 551      *
 552      *    If insert, the vararray is inserted at the given position (position counting from zero).
 553      *    If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value).
 554      *
 555      * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array)
 556      * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars)
 557      *
 558      * @return bool false on error, true on success
 559      * @access public
 560      */
 561  	function alter_block_array($blockname, $vararray, $key = false, $mode = 'insert')
 562      {
 563          if (strpos($blockname, '.') !== false)
 564          {
 565              // Nested blocks are not supported
 566              return false;
 567          }
 568  
 569          // Change key to zero (change first position) if false and to last position if true
 570          if ($key === false || $key === true)
 571          {
 572              $key = ($key === false) ? 0 : sizeof($this->_tpldata[$blockname]);
 573          }
 574  
 575          // Get correct position if array given
 576          if (is_array($key))
 577          {
 578              // Search array to get correct position
 579              list($search_key, $search_value) = @each($key);
 580  
 581              $key = NULL;
 582              foreach ($this->_tpldata[$blockname] as $i => $val_ary)
 583              {
 584                  if ($val_ary[$search_key] === $search_value)
 585                  {
 586                      $key = $i;
 587                      break;
 588                  }
 589              }
 590  
 591              // key/value pair not found
 592              if ($key === NULL)
 593              {
 594                  return false;
 595              }
 596          }
 597  
 598          // Insert Block
 599          if ($mode == 'insert')
 600          {
 601              // Make sure we are not exceeding the last iteration
 602              if ($key >= sizeof($this->_tpldata[$blockname]))
 603              {
 604                  $key = sizeof($this->_tpldata[$blockname]);
 605                  unset($this->_tpldata[$blockname][($key - 1)]['S_LAST_ROW']);
 606                  $vararray['S_LAST_ROW'] = true;
 607              }
 608              else if ($key === 0)
 609              {
 610                  unset($this->_tpldata[$blockname][0]['S_FIRST_ROW']);
 611                  $vararray['S_FIRST_ROW'] = true;
 612              }
 613  
 614              // Re-position template blocks
 615              for ($i = sizeof($this->_tpldata[$blockname]); $i > $key; $i--)
 616              {
 617                  $this->_tpldata[$blockname][$i] = $this->_tpldata[$blockname][$i-1];
 618                  $this->_tpldata[$blockname][$i]['S_ROW_COUNT'] = $i;
 619              }
 620  
 621              // Insert vararray at given position
 622              $vararray['S_ROW_COUNT'] = $key;
 623              $this->_tpldata[$blockname][$key] = $vararray;
 624  
 625              return true;
 626          }
 627  
 628          // Which block to change?
 629          if ($mode == 'change')
 630          {
 631              if ($key == sizeof($this->_tpldata[$blockname]))
 632              {
 633                  $key--;
 634              }
 635  
 636              $this->_tpldata[$blockname][$key] = array_merge($this->_tpldata[$blockname][$key], $vararray);
 637              return true;
 638          }
 639  
 640          return false;
 641      }
 642  
 643      /**
 644      * Include a separate template
 645      * @access private
 646      */
 647  	function _tpl_include($filename, $include = true)
 648      {
 649          $handle = $filename;
 650          $this->filename[$handle] = $filename;
 651          $this->files[$handle] = $this->root . '/' . $filename;
 652          if ($this->inherit_root)
 653          {
 654              $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename;
 655          }
 656  
 657          $filename = $this->_tpl_load($handle);
 658  
 659          if ($include)
 660          {
 661              global $user;
 662  
 663              if ($filename)
 664              {
 665                  include($filename);
 666                  return;
 667              }
 668              eval(' ?>' . $this->compiled_code[$handle] . '<?php ');
 669          }
 670      }
 671  
 672      /**
 673      * Include a php-file
 674      * @access private
 675      */
 676  	function _php_include($filename)
 677      {
 678          global $phpbb_root_path;
 679  
 680          $file = $phpbb_root_path . $filename;
 681  
 682          if (!file_exists($file))
 683          {
 684              // trigger_error cannot be used here, as the output already started
 685              echo 'template->_php_include(): File ' . htmlspecialchars($file) . ' does not exist or is empty';
 686              return;
 687          }
 688          include($file);
 689      }
 690  }
 691  
 692  ?>


Generated: Wed Oct 2 15:03:47 2013 Cross-referenced by PHPXref 0.7.1