[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Oct 2 15:03:47 2013 | Cross-referenced by PHPXref 0.7.1 |