| [ Index ] |
PHP Cross Reference of Joomla 1.5.26 DE |
[Summary view] [Print] [Text view]
1 <?PHP 2 /** 3 * patTemplate 4 * 5 * $Id: patTemplate.php 12694 2009-09-11 21:03:02Z ian $ 6 * 7 * powerful templating engine 8 * 9 * @version 3.1.0 10 * @package patTemplate 11 * @author Stephan Schmidt <schst@php.net> 12 * @license LGPL 13 * @link http://www.php-tools.net 14 */ 15 16 // ** Following line Joomla! specific ** 17 require_once( dirname( __FILE__ ) . '/patErrorManager.php' ); 18 19 /** 20 * template already exists 21 */ 22 define( 'PATTEMPLATE_ERROR_TEMPLATE_EXISTS', 5010 ); 23 24 /** 25 * template does not exist 26 */ 27 define ( 'PATTEMPLATE_WARNING_NO_TEMPLATE', 5011 ); 28 29 /** 30 * unknown type 31 */ 32 define ( 'PATTEMPLATE_WARNING_UNKNOWN_TYPE', 5012 ); 33 34 /** 35 * base class for module could not be found 36 */ 37 define( 'PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND', 5050 ); 38 39 /** 40 * module could not be found 41 */ 42 define( 'PATTEMPLATE_ERROR_MODULE_NOT_FOUND', 5051 ); 43 44 /** 45 * array expected 46 */ 47 define( 'PATTEMPLATE_ERROR_EXPECTED_ARRAY', 5052 ); 48 49 /** 50 * No input 51 */ 52 define( 'PATTEMPLATE_ERROR_NO_INPUT', 6000 ); 53 /** 54 * Recursion 55 */ 56 define( 'PATTEMPLATE_ERROR_RECURSION', 6010 ); 57 58 /** 59 * patTemplate 60 * 61 * powerful templating engine 62 * 63 * @version 3.1.0 64 * @package patTemplate 65 * @author Stephan Schmidt <schst@php.net> 66 * @license LGPL 67 * @link http://www.php-tools.net 68 */ 69 class patTemplate 70 { 71 /** 72 * standard system vars that identify pat tools 73 * @var array 74 */ 75 var $_systemVars = array( 76 'appName' => 'patTemplate', 77 'appVersion' => '3.1.0', 78 'author' => array( 79 'Stephan Schmidt <schst@php.net>' 80 ) 81 ); 82 83 /** 84 * default attributes for new templates 85 * @access private 86 * @var array 87 */ 88 var $_defaultAttributes = array( 89 'type' => 'standard', 90 'visibility' => 'visible', 91 'loop' => 1, 92 'unusedvars' => 'strip', 93 'whitespace' => 'keep', 94 'autoclear' => 'off', 95 'autoload' => 'on' 96 ); 97 98 /** 99 * options for patTemplate 100 * 101 * Currently the following options are implemented: 102 * - maintainBc defines, whether patTemplate should be backwards compatible. 103 * This means, that you may use 'default' and 'empty' for subtemplates. 104 * 105 * @access private 106 * @var array 107 */ 108 var $_options = array( 109 'startTag' => '{', 110 'endTag' => '}', 111 'root' => array('__default' => '.'), 112 'namespace' => 'patTemplate', 113 'maintainBc' => true, 114 'defaultFunction' => false 115 ); 116 117 /** 118 * start tag 119 * 120 * @access private 121 * @var string 122 */ 123 var $_startTag = '{'; 124 125 /** 126 * end tag 127 * 128 * @access private 129 * @var string 130 */ 131 var $_endTag = '}'; 132 133 /** 134 * loaded modules 135 * 136 * Modules are: 137 * - Readers 138 * - Caches 139 * - Variable modifiers 140 * - Filters 141 * 142 * @access private 143 * @var array 144 */ 145 var $_modules = array(); 146 147 /** 148 * directories, where modules can be stored 149 * @access private 150 * @var array 151 */ 152 var $_moduleDirs = array(); 153 154 /** 155 * stores all template names 156 * @access private 157 * @var array 158 */ 159 var $_templateList = array(); 160 161 /** 162 * stores all template data 163 * @access private 164 * @var array 165 */ 166 var $_templates = array(); 167 168 /** 169 * stores all global variables 170 * @access private 171 * @var array 172 */ 173 var $_globals = array(); 174 175 /** 176 * stores all local variables 177 * @access private 178 * @var array 179 */ 180 var $_vars = array(); 181 182 /** 183 * stores the name of the first template that has been 184 * found 185 * 186 * @access private 187 * @var string 188 */ 189 var $_root; 190 191 /** 192 * output filters that should be used 193 * 194 * @access private 195 * @var array 196 */ 197 var $_outputFilters = array(); 198 199 /** 200 * input filters that should be used 201 * 202 * @access private 203 * @var array 204 */ 205 var $_inputFilters = array(); 206 207 /** 208 * template cache, that should be used 209 * 210 * @access private 211 * @var array 212 */ 213 var $_tmplCache = null; 214 215 /** 216 * placeholders, that have been discovered 217 * 218 * @access private 219 * @var array 220 */ 221 var $_discoveredPlaceholders = array(); 222 223 /** 224 * Create a new patTemplate instance. 225 * 226 * The constructor accepts the type of the templates as sole parameter. 227 * You may choose one of: 228 * - html (default) 229 * - tex 230 * 231 * The type influences the tags you are using in your templates. 232 * 233 * @access public 234 * @param string type (either html or tex) 235 */ 236 function patTemplate( $type = 'html' ) 237 { 238 if( !defined( 'PATTEMPLATE_INCLUDE_PATH' ) ) { 239 define( 'PATTEMPLATE_INCLUDE_PATH', dirname( __FILE__ ) . '/patTemplate' ); 240 } 241 242 $this->setType( $type ); 243 } 244 245 /** 246 * sets an option 247 * 248 * Currently, the following options are supported 249 * - maintainBc (true|false) 250 * - namespace (string) 251 * 252 * @access public 253 * @param string option to set 254 * @param string value of the option 255 */ 256 function setOption($option, $value) 257 { 258 $this->_options[$option] = $value; 259 } 260 261 /** 262 * gets an option 263 * 264 * @access public 265 * @param string option to get 266 * @return mixed value of the option 267 */ 268 function getOption( $option ) 269 { 270 if (!isset($this->_options[$option])) { 271 return null; 272 } 273 return $this->_options[$option]; 274 } 275 276 /** 277 * sets name of directory where templates are stored 278 * 279 * @access public 280 * @param string dir where templates are stored 281 * @deprecated please use patTemplate::setRoot() instead 282 */ 283 function setBasedir($basedir) 284 { 285 $this->setRoot($basedir); 286 } 287 288 /** 289 * sets root base for the template 290 * 291 * The parameter depends on the reader you are using. 292 * 293 * @access public 294 * @param string root base of the templates 295 */ 296 function setRoot($root, $reader = '__default') 297 { 298 $this->_options['root'][$reader] = $root; 299 } 300 301 /** 302 * gets name of root base for the templates 303 * 304 * @access public 305 * @return mixed root base 306 */ 307 function getRoot($reader = '__default') 308 { 309 return $this->_options['root'][$reader]; 310 } 311 312 /** 313 * sets namespace of patTemplate tags 314 * 315 * If you want to use more than one namespace, you may set this to 316 * an array. All tags in these namespaces will be treated as patTemplate 317 * tags. 318 * 319 * @access public 320 * @param string|array namespace(s) 321 */ 322 function setNamespace($ns) 323 { 324 $this->_options['namespace'] = $ns; 325 } 326 327 /** 328 * gets namespace of patTemplate tags 329 * 330 * @access public 331 * @return string|array namespace(s) 332 */ 333 function getNamespace() 334 { 335 return $this->_options['namespace']; 336 } 337 338 /** 339 * set default attribute 340 * 341 * @access public 342 * @param string attribute name 343 * @param mixed attribute value 344 */ 345 function setDefaultAttribute( $name, $value ) 346 { 347 $this->_defaultAttributes[$name] = $value; 348 } 349 350 /** 351 * set default attributes 352 * 353 * @access public 354 * @param array attributes 355 */ 356 function setDefaultAttributes( $attributes ) 357 { 358 $this->_defaultAttributes = array_merge( $this->_defaultAttributes, $attributes ); 359 } 360 361 /** 362 * get default attributes 363 * 364 * @access public 365 * @return return default attributes 366 */ 367 function getDefaultAttributes() 368 { 369 return $this->_defaultAttributes; 370 } 371 372 /** 373 * set the type for the templates 374 * 375 * @access public 376 * @param string type (html or tex) 377 * @return boolean true on success 378 */ 379 function setType( $type ) 380 { 381 switch( strtolower( $type ) ) 382 { 383 case "tex": 384 $this->setTags( '<{', '}>' ); 385 break; 386 case "html": 387 $this->setTags( '{', '}' ); 388 break; 389 default: 390 return patErrorManager::raiseWarning( 391 PATTEMPLATE_WARNING_UNKNOWN_TYPE, 392 "Unknown type '$type'. Please use 'html' or 'tex'." 393 ); 394 } 395 return true; 396 } 397 398 /** 399 * set the start and end tag for variables 400 * 401 * @access public 402 * @param string start tag 403 * @param string end tag 404 * @return boolean true on success 405 */ 406 function setTags( $startTag, $endTag ) 407 { 408 $this->_options['startTag'] = $startTag; 409 $this->_options['endTag'] = $endTag; 410 411 $this->_startTag = $startTag; 412 $this->_endTag = $endTag; 413 return true; 414 } 415 416 /** 417 * get start tag for variables 418 * 419 * @access public 420 * @return string start tag 421 */ 422 function getStartTag() 423 { 424 return $this->_options['startTag']; 425 } 426 427 /** 428 * get end tag for variables 429 * 430 * @access public 431 * @return string end tag 432 */ 433 function getEndTag() 434 { 435 return $this->_options['endTag']; 436 } 437 438 /** 439 * add a directory where patTemplate should search for 440 * modules. 441 * 442 * You may either pass a string or an array of directories. 443 * 444 * patTemplate will be searching for a module in the same 445 * order you added them. If the module cannot be found in 446 * the custom folders, it will look in 447 * patTemplate/$moduleType. 448 * 449 * @access public 450 * @param string module type 451 * @param string|array directory or directories to search. 452 */ 453 function addModuleDir( $moduleType, $dir ) 454 { 455 if( !isset( $this->_moduleDirs[$moduleType] ) ) 456 $this->_moduleDirs[$moduleType] = array(); 457 if( is_array( $dir ) ) 458 $this->_moduleDirs[$moduleType] = array_merge( $this->_moduleDirs[$moduleType], $dir ); 459 else 460 array_push( $this->_moduleDirs[$moduleType], $dir ); 461 } 462 463 /** 464 * Sets an attribute of a template 465 * 466 * supported attributes: visibilty, loop, parse, unusedvars 467 * 468 * @param string $template name of the template 469 * @param string $attribute name of the attribute 470 * @param mixed $value value of the attribute 471 * @access public 472 * @see setAttributes(),getAttribute(), clearAttribute() 473 */ 474 function setAttribute( $template, $attribute, $value ) 475 { 476 $template = strtolower( $template ); 477 if( !isset( $this->_templates[$template] ) ) 478 { 479 return patErrorManager::raiseWarning( 480 PATTEMPLATE_WARNING_NO_TEMPLATE, 481 "Template '$template' does not exist." 482 ); 483 } 484 485 $attribute = strtolower( $attribute ); 486 $this->_templates[$template]['attributes'][$attribute] = $value; 487 return true; 488 } 489 490 /** 491 * Sets several attribute of a template 492 * 493 * $attributes has to be a assotiative arrays containing attribute/value pairs 494 * supported attributes: visibilty, loop, parse, unusedvars 495 * 496 * @param string $template name of the template 497 * @param array $attributes attribute/value pairs 498 * @access public 499 * @see setAttribute(), getAttribute(), clearAttribute() 500 */ 501 function setAttributes( $template, $attributes ) 502 { 503 if( !is_array( $attributes ) ) 504 { 505 return patErrorManager::raiseError( PATTEMPLATE_ERROR_EXPECTED_ARRAY, 'patTemplate::setAttributes: Expected array as second parameter, '.gettype( $attributes ).' given' ); 506 } 507 508 $template = strtolower( $template ); 509 $attributes = array_change_key_case( $attributes ); 510 if( !isset( $this->_templates[$template] ) ) 511 { 512 return patErrorManager::raiseWarning( 513 PATTEMPLATE_WARNING_NO_TEMPLATE, 514 "Template '$template' does not exist." 515 ); 516 } 517 518 $this->_templates[$template]['attributes'] = array_merge( $this->_templates[$template]['attributes'], $attributes ); 519 return true; 520 } 521 522 /** 523 * Get all attributes of a template 524 * 525 * @param string name of the template 526 * @return array attributes 527 * @access public 528 */ 529 function getAttributes( $template ) 530 { 531 $template = strtolower( $template ); 532 if( !isset( $this->_templates[$template] ) ) 533 { 534 return patErrorManager::raiseWarning( 535 PATTEMPLATE_WARNING_NO_TEMPLATE, 536 "Template '$template' does not exist." 537 ); 538 } 539 return $this->_templates[$template]['attributes']; 540 } 541 542 /** 543 * Gets an attribute of a template 544 * 545 * supported attributes: visibilty, loop, parse, unusedvars 546 * 547 * @param string $template name of the template 548 * @param string $attribute name of the attribute 549 * @return mixed value of the attribute 550 * @access public 551 * @see setAttribute(), setAttributes(), clearAttribute() 552 */ 553 function getAttribute( $template, $attribute ) 554 { 555 $template = strtolower( $template ); 556 $attribute = strtolower( $attribute ); 557 if( !isset( $this->_templates[$template] ) ) 558 { 559 return patErrorManager::raiseWarning( 560 PATTEMPLATE_WARNING_NO_TEMPLATE, 561 "Template '$template' does not exist." 562 ); 563 } 564 return $this->_templates[$template]['attributes'][$attribute]; 565 } 566 567 /** 568 * Clears an attribute of a template 569 * 570 * supported attributes: visibilty, loop, parse, unusedvars 571 * 572 * @param string $template name of the template 573 * @param string $attribute name of the attribute 574 * @access public 575 * @see setAttribute(), setAttributes(), getAttribute() 576 */ 577 function clearAttribute( $template, $attribute ) 578 { 579 $template = strtolower( $template ); 580 $attribute = strtolower( $attribute ); 581 582 if( !isset( $this->_templates[$template] ) ) 583 { 584 return patErrorManager::raiseWarning( 585 PATTEMPLATE_WARNING_NO_TEMPLATE, 586 "Template '$template' does not exist." 587 ); 588 } 589 $this->_templates[$template]['attributes'][$attribute] = '';; 590 return true; 591 } 592 593 /** 594 * Prepare a template 595 * 596 * This can be used if you want to add variables to 597 * a template, that has not been loaded yet. 598 * 599 * @access public 600 * @param string template name 601 */ 602 function prepareTemplate( $name ) 603 { 604 $name = strtolower( $name ); 605 if( !isset( $this->_vars[$name] ) ) 606 { 607 $this->_vars[$name] = array( 608 'scalar' => array(), 609 'rows' => array() 610 ); 611 } 612 } 613 614 /** 615 * add a variable to a template 616 * 617 * A variable may also be an indexed array, but _not_ 618 * an associative array! 619 * 620 * @access public 621 * @param string $template name of the template 622 * @param string $varname name of the variable 623 * @param mixed $value value of the variable 624 */ 625 function addVar( $template, $varname, $value ) 626 { 627 $template = strtolower( $template ); 628 $varname = strtoupper( $varname ); 629 630 if( !is_array( $value ) ) { 631 $this->_vars[$template]['scalar'][$varname] = $value; 632 return true; 633 } 634 635 $cnt = count( $value ); 636 for ($i = 0; $i < $cnt; $i++) { 637 if (!isset( $this->_vars[$template]['rows'][$i] )) { 638 $this->_vars[$template]['rows'][$i] = array(); 639 } 640 $this->_vars[$template]['rows'][$i][$varname] = $value[$i]; 641 } 642 643 return true; 644 } 645 646 /** 647 * get the value of a variable 648 * 649 * @access public 650 * @param string name of the template 651 * @param string name of the variable 652 * @return string value of the variable, null if the variable is not set 653 */ 654 function getVar( $template, $varname ) 655 { 656 $template = strtolower( $template ); 657 $varname = strtoupper( $varname ); 658 659 if( isset( $this->_vars[$template]['scalar'][$varname] ) ) 660 return $this->_vars[$template]['scalar'][$varname]; 661 662 $value = array(); 663 664 if(!isset($this->_vars[$template]['rows'])) 665 return null; 666 667 $cnt = count( $this->_vars[$template]['rows'] ); 668 for( $i = 0; $i < $cnt; $i++ ) 669 { 670 if( !isset( $this->_vars[$template]['rows'][$i][$varname] ) ) 671 continue; 672 array_push( $value, $this->_vars[$template]['rows'][$i][$varname] ); 673 } 674 if( !empty( $value ) ) 675 return $value; 676 return null; 677 } 678 679 /** 680 * clear the value of a variable 681 * 682 * @access public 683 * @param string name of the template 684 * @param string name of the variable 685 * @return boolean 686 * @see clearVars(), clearTemplate() 687 */ 688 function clearVar( $template, $varname ) 689 { 690 $template = strtolower( $template ); 691 $varname = strtoupper( $varname ); 692 693 if (isset( $this->_vars[$template]['scalar'][$varname] )) { 694 unset ($this->_vars[$template]['scalar'][$varname]); 695 return true; 696 } 697 698 $result = false; 699 $cnt = count( $this->_vars[$template]['rows'] ); 700 for ($i = 0; $i < $cnt; $i++) { 701 if (!isset($this->_vars[$template]['rows'][$i][$varname])) { 702 continue; 703 } 704 unset($this->_vars[$template]['rows'][$i][$varname]); 705 $result = true; 706 } 707 return $result; 708 } 709 710 711 /** 712 * Adds several variables to a template 713 * 714 * Each Template can have an unlimited amount of its own variables 715 * $variables has to be an assotiative array containing variable/value pairs 716 * 717 * @param string $template name of the template 718 * @param array $variables assotiative array of the variables 719 * @param string $prefix prefix for all variable names 720 * @access public 721 * @see addVar(), addRows(), addGlobalVar(), addGlobalVars() 722 */ 723 function addVars( $template, $variables, $prefix = '' ) 724 { 725 $template = strtolower( $template ); 726 $prefix = strtoupper( $prefix ); 727 $variables = array_change_key_case( $variables, CASE_UPPER ); 728 729 foreach ($variables as $varname => $value) { 730 $varname = $prefix.$varname; 731 732 if (!is_array($value)) { 733 if (!is_scalar($value)) { 734 continue; 735 } 736 $this->_vars[$template]['scalar'][$varname] = $value; 737 continue; 738 } 739 740 $cnt = count( $value ); 741 for( $i = 0; $i < $cnt; $i++ ) { 742 if( !isset( $this->_vars[$template]['rows'][$i] ) ) 743 $this->_vars[$template]['rows'][$i] = array(); 744 745 $this->_vars[$template]['rows'][$i][$varname] = $value[$i]; 746 } 747 } 748 } 749 750 /** 751 * Clear all variables in a template 752 * 753 * This clears only variables, but does 754 * 755 * @access public 756 * @param string $template name of the template 757 * @return boolean 758 * @see clearVar(), clearTemplate() 759 */ 760 function clearVars( $template ) 761 { 762 $template = strtolower($template); 763 $this->_vars[$template] = array( 764 'scalar' => array(), 765 'rows' => array() 766 ); 767 return true; 768 } 769 770 771 /** 772 * Adds several rows of variables to a template 773 * 774 * Each Template can have an unlimited amount of its own variables 775 * Can be used to add a database result as variables to a template 776 * 777 * @param string $template name of the template 778 * @param array $rows array containing assotiative arrays with variable/value pairs 779 * @param string $prefix prefix for all variable names 780 * @access public 781 * @see addVar(), addVars(), addGlobalVar(), addGlobalVars() 782 */ 783 function addRows( $template, $rows, $prefix = '' ) 784 { 785 $template = strtolower( $template ); 786 $prefix = strtoupper( $prefix ); 787 788 $cnt = count( $rows ); 789 for( $i = 0; $i < $cnt; $i++ ) 790 { 791 if( !isset( $this->_vars[$template]['rows'][$i] ) ) 792 $this->_vars[$template]['rows'][$i] = array(); 793 794 $rows[$i] = array_change_key_case( $rows[$i], CASE_UPPER ); 795 796 foreach( $rows[$i] as $varname => $value ) 797 { 798 $this->_vars[$template]['rows'][$i][$prefix.$varname] = $value; 799 } 800 } 801 } 802 803 /** 804 * Adds an object to a template 805 * 806 * All properties of the object will be available as template variables. 807 * 808 * @access public 809 * @param string name of the template 810 * @param object|array object or array of objects 811 * @param string prefix for all variable names 812 * @param boolean ignore private properties (starting with _) 813 * @see addVar(), addRows(), addGlobalVar(), addGlobalVars() 814 */ 815 function addObject( $template, $object, $prefix = '', $ignorePrivate = false ) 816 { 817 if( is_array( $object ) ) { 818 $rows = array(); 819 foreach($object as $o) { 820 array_push( $rows, $this->getObjectVars($o, $ignorePrivate) ); 821 } 822 823 return $this->addRows( $template, $rows, $prefix ); 824 } elseif (is_object($object)) { 825 return $this->addVars( $template, $this->getObjectVars($object, $ignorePrivate), $prefix ); 826 } 827 return false; 828 } 829 830 /** 831 * get the vars from an object 832 * 833 * @access private 834 * @param object 835 * @param boolean ignore private properties (starting with _) 836 * @return array 837 */ 838 function getObjectVars($obj, $ignorePrivate = false) 839 { 840 if (method_exists($obj, 'getVars')) { 841 return $obj->getVars(); 842 } 843 $vars = get_object_vars($obj); 844 if ($ignorePrivate === false) { 845 return $vars; 846 } 847 foreach ($vars as $var => $value) { 848 if ($var{0} == '_') { 849 unset($vars[$var]); 850 } 851 } 852 return $vars; 853 } 854 855 /** 856 * Adds a global variable 857 * 858 * Global variables are valid in all templates of this object. 859 * A global variable has to be scalar, it will be converted to a string. 860 * 861 * @access public 862 * @param string $varname name of the global variable 863 * @param string $value value of the variable 864 * @return boolean true on success 865 * @see addGlobalVars(), addVar(), addVars(), addRows() 866 */ 867 function addGlobalVar( $varname, $value ) 868 { 869 $this->_globals[strtoupper( $varname )] = ( string )$value; 870 return true; 871 } 872 873 /** 874 * Clears a global variable 875 * 876 * @access public 877 * @param string $varname name of the global variable 878 * @return boolean true on success 879 * @see clearVar(), clearVars(), clearGlobalVars() 880 */ 881 function clearGlobalVar( $varname ) 882 { 883 $varname = strtoupper( $varname ); 884 if (!isset($this->_globals[$varname])) { 885 return false; 886 } 887 unset($this->_globals[$varname]); 888 return true; 889 } 890 891 /** 892 * Clears all global variables 893 * 894 * @access public 895 * @return boolean true on success 896 * @see clearVar(), clearVars(), clearGlobalVar() 897 */ 898 function clearGlobalVars() 899 { 900 $this->_globals = array(); 901 return true; 902 } 903 904 /** 905 * Adds several global variables 906 * 907 * Global variables are valid in all templates of this object. 908 * 909 * $variables is an associative array, containing name/value pairs of the variables. 910 * 911 * @access public 912 * @param array $variables array containing the variables 913 * @param string $prefix prefix for variable names 914 * @return boolean true on success 915 * @see addGlobalVar(), addVar(), addVars(), addRows() 916 */ 917 function addGlobalVars( $variables, $prefix = '' ) 918 { 919 $variables = array_change_key_case( $variables, CASE_UPPER ); 920 $prefix = strtoupper( $prefix ); 921 foreach( $variables as $varname => $value ) 922 { 923 $this->_globals[$prefix.$varname] = ( string )$value; 924 } 925 926 return true; 927 } 928 929 /** 930 * get all global variables 931 * 932 * @access public 933 * @return array global variables 934 */ 935 function getGlobalVars() 936 { 937 return $this->_globals; 938 } 939 940 /** 941 * checks wether a template exists 942 * 943 * @access public 944 * @param string name of the template 945 * @return boolean true, if the template exists, false otherwise 946 */ 947 function exists( $name ) 948 { 949 return in_array( strtolower( $name ), $this->_templateList ); 950 } 951 952 /** 953 * enable a template cache 954 * 955 * A template cache will improve performace, as the templates 956 * do not have to be read on each request. 957 * 958 * @access public 959 * @param string name of the template cache 960 * @param array parameters for the template cache 961 * @return boolean true on success, patError otherwise 962 */ 963 function useTemplateCache( $cache, $params = array() ) 964 { 965 if( !is_object( $cache ) ) 966 { 967 $cache = &$this->loadModule( 'TemplateCache', $cache, $params ); 968 } 969 if( patErrorManager::isError( $cache ) ) 970 return $cache; 971 972 $this->_tmplCache = &$cache; 973 return true; 974 } 975 976 /** 977 * enable an output filter 978 * 979 * Output filters are used to modify the template 980 * result before it is sent to the browser. 981 * 982 * They are applied, when displayParsedTemplate() is called. 983 * 984 * @access public 985 * @param string name of the output filter 986 * @param array parameters for the output filter 987 * @return boolean true on success, patError otherwise 988 */ 989 function applyOutputFilter( $filter, $params = array(), $template = null ) 990 { 991 if (!is_object($filter)) { 992 $filter = &$this->loadModule( 'OutputFilter', $filter, $params ); 993 } 994 if (patErrorManager::isError($filter)) { 995 return $filter; 996 } 997 998 if ($template === null) { 999 $this->_outputFilters[] = &$filter; 1000 return true; 1001 } 1002 1003 $template = strtolower($template); 1004 if (!$this->exists($template)) { 1005 return patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'The selected template does not exist'); 1006 } 1007 $this->_templates[$template]['attributes']['outputfilter'] = &$filter; 1008 return true; 1009 } 1010 1011 /** 1012 * enable an input filter 1013 * 1014 * input filters are used to modify the template 1015 * stream before it is split into smaller templates- 1016 * 1017 * @access public 1018 * @param string name of the input filter 1019 * @param array parameters for the input filter 1020 * @return boolean true on success, patError otherwise 1021 */ 1022 function applyInputFilter( $filter, $params = array() ) 1023 { 1024 if( !is_object( $filter ) ) 1025 { 1026 $filter = &$this->loadModule( 'InputFilter', $filter, $params ); 1027 } 1028 if( patErrorManager::isError( $filter ) ) 1029 return $filter; 1030 1031 $this->_inputFilters[] = &$filter; 1032 return true; 1033 } 1034 1035 /** 1036 * open a file and parse for patTemplate tags 1037 * 1038 * @access public 1039 * @param name of the file 1040 * @return true, if the template could be parsed 1041 * @deprecated Use patTemplate::readTemplatesFromInput() instead, as the method name is misleading 1042 * @see readTemplatesFromInput() 1043 */ 1044 function readTemplatesFromFile( $filename ) 1045 { 1046 return $this->readTemplatesFromInput( $filename, 'File' ); 1047 } 1048 1049 /** 1050 * open any input and parse for patTemplate tags 1051 * 1052 * @access public 1053 * @param string name of the input (filename, shm segment, etc.) 1054 * @param string driver that is used as reader, you may also pass a Reader object 1055 * @param array additional options that will only be used for this template 1056 * @param string name of the template that should be used as a container, should not be used by public 1057 * calls. 1058 * @return boolean true, if the template could be parsed, false otherwise 1059 */ 1060 function readTemplatesFromInput( $input, $reader = 'File', $options = null, $parseInto = null ) 1061 { 1062 if ((string)$input === '') { 1063 return patErrorManager::raiseError(PATTEMPLATE_ERROR_NO_INPUT, 'No input to read has been passed.'); 1064 } 1065 1066 if (is_array($options)) { 1067 $options = array_merge( $this->_options, $options ); 1068 } else { 1069 $options = $this->_options; 1070 } 1071 1072 if (!is_null($parseInto)) { 1073 $parseInto = strtolower( $parseInto ); 1074 } 1075 1076 $templates = false; 1077 if ($this->_tmplCache !== null) { 1078 /** 1079 * get the unique cache key 1080 */ 1081 $key = $this->_tmplCache->getKey($input, $options); 1082 1083 $templates = $this->_loadTemplatesFromCache( $input, $reader, $options, $key ); 1084 1085 /** 1086 * check for error returned from cache 1087 */ 1088 if (patErrorManager::isError($templates)) { 1089 return $templates; 1090 } 1091 } 1092 1093 /** 1094 * templates have not been loaded from cache 1095 */ 1096 if ($templates === false) { 1097 if (!is_object( $reader)) { 1098 $reader = &$this->loadModule('Reader', $reader); 1099 if (patErrorManager::isError($reader)) { 1100 return $reader; 1101 } 1102 } 1103 1104 if ($reader->isInUse()) { 1105 $reader = &$this->loadModule( 'Reader', $reader->getName(), array(), true); 1106 if( patErrorManager::isError( $reader ) ) { 1107 return $reader; 1108 } 1109 } 1110 1111 $reader->setOptions($options); 1112 1113 /** 1114 * set the root attributes 1115 */ 1116 if( !is_null( $parseInto ) ) 1117 { 1118 $attributes = $this->getAttributes( $parseInto ); 1119 if( !patErrorManager::isError( $attributes ) ) 1120 { 1121 $reader->setRootAttributes( $attributes ); 1122 } 1123 } 1124 1125 $templates = $reader->readTemplates( $input ); 1126 1127 /** 1128 * check for error returned from reader 1129 */ 1130 if( patErrorManager::isError( $templates ) ) 1131 return $templates; 1132 1133 /** 1134 * store the 1135 */ 1136 if( $this->_tmplCache !== null ) 1137 { 1138 $this->_tmplCache->write( $key, $templates ); 1139 } 1140 } 1141 1142 /** 1143 * traverse all templates 1144 */ 1145 foreach( $templates as $name => $spec ) 1146 { 1147 1148 /** 1149 * root template 1150 */ 1151 if( $name == '__ptroot' ) 1152 { 1153 if( $parseInto === false ) 1154 { 1155 continue; 1156 } 1157 if( !in_array( $parseInto, $this->_templateList ) ) 1158 continue; 1159 1160 $spec['loaded'] = true; 1161 $spec['attributes'] = $this->_templates[$parseInto]['attributes']; 1162 $name = $parseInto; 1163 } 1164 else 1165 { 1166 /** 1167 * store the name 1168 */ 1169 array_push( $this->_templateList, $name ); 1170 } 1171 1172 /** 1173 * if this is the first template that has been loaded 1174 * set it as the root template 1175 */ 1176 if( $this->_root === null && is_null( $parseInto ) && isset( $spec['isRoot'] ) && $spec['isRoot'] == true ) 1177 { 1178 $this->_root = $name; 1179 } 1180 1181 /** 1182 * set some default values 1183 */ 1184 $spec['iteration'] = 0; 1185 $spec['lastMode'] = 'w'; 1186 $spec['result'] = ''; 1187 $spec['modifyVars'] = array(); 1188 $spec['copyVars'] = array(); 1189 $spec['defaultVars'] = array(); 1190 1191 /** 1192 * store the template 1193 */ 1194 $this->_templates[$name] = $spec; 1195 1196 $this->prepareTemplate( $name ); 1197 1198 /** 1199 * store the default values of the variables 1200 */ 1201 foreach( $spec['varspecs'] as $varname => $varspec ) 1202 { 1203 if (isset($varspec['modifier'])) { 1204 $this->_templates[$name]['modifyVars'][$varname] = $varspec['modifier']; 1205 } 1206 1207 if( isset( $varspec['copyfrom'] ) ) 1208 { 1209 $this->_templates[$name]['copyVars'][$varname] = $varspec['copyfrom']; 1210 } 1211 1212 if( !isset( $varspec['default'] ) ) 1213 continue; 1214 1215 $this->_templates[$name]['defaultVars'][$varname] = $varspec['default']; 1216 1217 if( !is_null( $this->getVar( $name, $varname ) ) ) 1218 continue; 1219 1220 $this->addVar( $name, $varname, $varspec['default'] ); 1221 } 1222 1223 unset($this->_templates[$name]['varspecs']); 1224 1225 /** 1226 * autoload the template 1227 * 1228 * Some error management is needed here... 1229 */ 1230 if( isset( $this->_templates[$name]['attributes']['src'] ) && $this->_templates[$name]['attributes']['autoload'] == 'on' ) 1231 { 1232 if( $this->_templates[$name]['loaded'] !== true ) 1233 { 1234 if( $this->_templates[$name]['attributes']['parse'] == 'on' ) 1235 { 1236 $this->readTemplatesFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], $options, $name ); 1237 } 1238 else 1239 { 1240 $this->loadTemplateFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], null, $name ); 1241 } 1242 $this->_templates[$name]['loaded'] = true; 1243 } 1244 } 1245 } 1246 1247 return true; 1248 } 1249 1250 /** 1251 * load from template cache 1252 * 1253 * @access private 1254 * @param string name of the input (filename, shm segment, etc.) 1255 * @param string driver that is used as reader, you may also pass a Reader object 1256 * @param array options for the reader 1257 * @param string cache key 1258 * @return array|boolean either an array containing the templates, or false 1259 */ 1260 function _loadTemplatesFromCache( $input, &$reader, $options, $key ) 1261 { 1262 if( is_object( $reader ) ) 1263 $statName = $reader->getName(); 1264 else 1265 $statName = $reader; 1266 1267 $stat = &$this->loadModule( 'Stat', $statName ); 1268 $stat->setOptions( $options ); 1269 1270 /** 1271 * get modification time 1272 */ 1273 $modTime = $stat->getModificationTime( $input ); 1274 $templates = $this->_tmplCache->load( $key, $modTime ); 1275 1276 return $templates; 1277 } 1278 1279 /** 1280 * open any input and load content into template 1281 * 1282 * @access public 1283 * @param string name of the input (filename, shm segment, etc.) 1284 * @param string driver that is used as reader 1285 * @param string name of the template that should be used as a container, 1286 * @return boolean true, if the template could be parsed, false otherwise 1287 */ 1288 function loadTemplateFromInput( $input, $reader = 'File', $options = null, $parseInto = false ) 1289 { 1290 if( is_array( $options ) ) 1291 $options = array_merge( $this->_options, $options ); 1292 else 1293 $options = $this->_options; 1294 1295 if( !is_null( $parseInto ) ) 1296 $parseInto = strtolower( $parseInto ); 1297 1298 $reader = &$this->loadModule( 'Reader', $reader ); 1299 if( patErrorManager::isError( $reader ) ) 1300 { 1301 return $reader; 1302 } 1303 $reader->setOptions($options); 1304 1305 $result = $reader->loadTemplate( $input ); 1306 1307 if( patErrorManager::isError( $result ) ) 1308 { 1309 return $result; 1310 } 1311 1312 $this->_templates[$parseInto]['content'] .= $result; 1313 $this->_templates[$parseInto]['loaded'] = true; 1314 return true; 1315 } 1316 1317 /** 1318 * load a template that had autoload="off" 1319 * 1320 * This is needed, if you change the source of a template and want to 1321 * load it, after changing the attribute. 1322 * 1323 * @access public 1324 * @param string template name 1325 * @return boolean true, if template could be loaded 1326 */ 1327 function loadTemplate( $template ) 1328 { 1329 $template = strtolower( $template ); 1330 if( !isset( $this->_templates[$template] ) ) 1331 { 1332 return patErrorManager::raiseWarning( 1333 PATTEMPLATE_WARNING_NO_TEMPLATE, 1334 "Template '$template' does not exist." 1335 ); 1336 } 1337 1338 if( $this->_templates[$template]['loaded'] === true ) 1339 return true; 1340 1341 if( $this->_templates[$template]['attributes']['parse'] == 'on' ) 1342 { 1343 return $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template ); 1344 } 1345 else 1346 { 1347 return $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template ); 1348 } 1349 } 1350 1351 /** 1352 * loads a patTemplate module 1353 * 1354 * Modules are located in the patTemplate folder and include: 1355 * - Readers 1356 * - Caches 1357 * - Variable Modifiers 1358 * - Filters 1359 * - Functions 1360 * - Stats 1361 * 1362 * @access public 1363 * @param string moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter) 1364 * @param string moduleName 1365 * @param array parameters for the module 1366 * @return object 1367 */ 1368 function &loadModule( $moduleType, $moduleName, $params = array(), $new = false ) 1369 { 1370 if( !isset( $this->_modules[$moduleType] ) ) 1371 $this->_modules[$moduleType] = array(); 1372 1373 $sig = md5( $moduleName . serialize( $params ) ); 1374 1375 if( isset( $this->_modules[$moduleType][$sig] ) && $new === false ) { 1376 return $this->_modules[$moduleType][$sig]; 1377 } 1378 1379 if( !class_exists( 'patTemplate_Module' ) ) 1380 { 1381 $file = sprintf( "%s/Module.php", $this->getIncludePath() ); 1382 if( !file_exists( $file ) or !include_once $file ) 1383 return patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, 'Could not load module base class.' ); 1384 } 1385 1386 $baseClass = 'patTemplate_' . $moduleType; 1387 if( !class_exists( $baseClass ) ) 1388 { 1389 $baseFile = sprintf( "%s/%s.php", $this->getIncludePath(), $moduleType ); 1390 if( !file_exists( $baseFile ) or !include_once $baseFile ) 1391 return patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, "Could not load base class for $moduleType ($baseFile)." ); 1392 } 1393 1394 $moduleClass = 'patTemplate_' . $moduleType . '_' .$moduleName; 1395 if( !class_exists( $moduleClass ) ) 1396 { 1397 if( isset( $this->_moduleDirs[$moduleType] ) ) 1398 $dirs = $this->_moduleDirs[$moduleType]; 1399 else 1400 $dirs = array(); 1401 array_push( $dirs, $this->getIncludePath() .'/'. $moduleType ); 1402 1403 $found = false; 1404 foreach( $dirs as $dir ) 1405 { 1406 $moduleFile = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) ); 1407 1408 if ( file_exists( $moduleFile ) and include_once $moduleFile) { 1409 $found = true; 1410 break; 1411 } 1412 } 1413 1414 if( !$found ) { 1415 return patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Could not load module $moduleClass ($moduleFile)." ); 1416 } 1417 } 1418 1419 if( !class_exists( $moduleClass ) ) 1420 { 1421 return patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Module file $moduleFile does not contain class $moduleClass." ); 1422 } 1423 1424 $this->_modules[$moduleType][$sig] = new $moduleClass; 1425 if( method_exists( $this->_modules[$moduleType][$sig], 'setTemplateReference' ) ) 1426 { 1427 $this->_modules[$moduleType][$sig]->setTemplateReference( $this ); 1428 } 1429 1430 $this->_modules[$moduleType][$sig]->setParams( $params ); 1431 1432 return $this->_modules[$moduleType][$sig]; 1433 } 1434 1435 /** 1436 * checks whether a module exists. 1437 * 1438 * Modules are located in the patTemplate folder and include: 1439 * - Readers 1440 * - Caches 1441 * - Variable Modifiers 1442 * - Filters 1443 * - Functions 1444 * - Stats 1445 * 1446 * @access public 1447 * @param string moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter) 1448 * @param string moduleName 1449 * @return boolean 1450 */ 1451 function moduleExists( $moduleType, $moduleName ) 1452 { 1453 // !!!JOOMLA VARIATION!!! 1454 // cache checks on files 1455 static $paths; 1456 1457 if (!$paths) 1458 { 1459 $paths = array(); 1460 } 1461 1462 if (isset($this->_moduleDirs[$moduleType])) { 1463 $dirs = $this->_moduleDirs[$moduleType]; 1464 } else { 1465 $dirs = array(); 1466 } 1467 array_push($dirs, $this->getIncludePath() .'/'. $moduleType); 1468 1469 foreach ($dirs as $dir) { 1470 $moduleFile = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) ); 1471 if (!isset( $paths[$moduleFile] )) 1472 { 1473 if (!file_exists($moduleFile)) { 1474 $paths[$moduleFile] = false; 1475 } 1476 else if (!is_readable($moduleFile)) { 1477 $paths[$moduleFile] = false; 1478 } 1479 else 1480 { 1481 $paths[$moduleFile] = true; 1482 } 1483 } 1484 1485 if (!$paths[$moduleFile]) { 1486 continue; 1487 } 1488 return true; 1489 } 1490 return false; 1491 } 1492 1493 /** 1494 * parses a template 1495 * 1496 * Parses a template and stores the parsed content. 1497 * mode can be "w" for write (delete already parsed content) or "a" for append (appends the 1498 * new parsed content to the already parsed content) 1499 * 1500 * @access public 1501 * @param string name of the template 1502 * @param string mode for the parsing 1503 */ 1504 function parseTemplate( $template, $mode = 'w' ) 1505 { 1506 $template = strtolower($template); 1507 1508 if (!isset($this->_templates[$template])) { 1509 return patErrorManager::raiseWarning( 1510 PATTEMPLATE_WARNING_NO_TEMPLATE, 1511 "Template '$template' does not exist." 1512 ); 1513 } 1514 1515 /** 1516 * template is not visible 1517 */ 1518 if ($this->_templates[$template]['attributes']['visibility'] == 'hidden') { 1519 $this->_templates[$template]['result'] = ''; 1520 $this->_templates[$template]['parsed'] = true; 1521 return true; 1522 } 1523 1524 /** 1525 * check, if the template has been loaded 1526 * and load it if necessary. 1527 */ 1528 if ($this->_templates[$template]['loaded'] !== true) { 1529 if ($this->_templates[$template]['attributes']['parse'] == 'on') { 1530 $result = $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template ); 1531 } else { 1532 $result = $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template ); 1533 } 1534 if (patErrorManager::isError($result)) { 1535 return $result; 1536 } 1537 } 1538 1539 /** 1540 * check for autoclear 1541 */ 1542 if( 1543 isset( $this->_templates[$template]['attributes']['autoclear'] ) && 1544 $this->_templates[$template]['attributes']['autoclear'] == 'yes' && 1545 $mode === 'w' && 1546 $this->_templates[$template]['lastMode'] != 'a' 1547 ) { 1548 $this->_templates[$template]['parsed'] = false; 1549 } 1550 1551 /** 1552 * template has been parsed and mode is not 'append' 1553 */ 1554 if ($this->_templates[$template]['parsed'] === true && $mode === 'w') { 1555 return true; 1556 } 1557 1558 $this->_templates[$template]['lastMode'] = $mode; 1559 1560 $this->_initTemplate( $template ); 1561 1562 if (!isset($this->_vars[$template]['rows'])) { 1563 $this->_vars[$template]['rows'] = array(); 1564 } 1565 $loop = count( $this->_vars[$template]['rows'] ); 1566 1567 /** 1568 * loop at least one times 1569 */ 1570 if ($loop < 1) { 1571 $loop = 1; 1572 } 1573 1574 if (isset($this->_templates[$template]['attributes']['maxloop'])) { 1575 $loop = ceil( $loop / $this->_templates[$template]['attributes']['maxloop'] ) * $this->_templates[$template]['attributes']['maxloop']; 1576 } 1577 1578 $this->_templates[$template]['loop'] = max( $this->_templates[$template]['attributes']['loop'], $loop ); 1579 1580 $start = 0; 1581 if (isset($this->_templates[$template]['attributes']['limit'])) { 1582 $p = strpos( $this->_templates[$template]['attributes']['limit'], ',' ); 1583 if ($p === false) { 1584 $this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $this->_templates[$template]['attributes']['limit'] ); 1585 $start = 0; 1586 } else { 1587 $start = substr( $this->_templates[$template]['attributes']['limit'], 0, $p ); 1588 $end = substr( $this->_templates[$template]['attributes']['limit'], $p+1 )+$start; 1589 1590 $this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $end ); 1591 } 1592 } 1593 1594 /** 1595 * template should be cleared before parsing 1596 */ 1597 if ($mode == 'w') { 1598 $this->_templates[$template]['result'] = ''; 1599 $this->_templates[$template]['iteration'] = $start; 1600 } 1601 1602 $loopCount = 0; 1603 for ($i = $start; $i < $this->_templates[$template]['loop']; $i++) { 1604 $finished = false; 1605 1606 unset( $this->_templates[$template]['vars'] ); 1607 1608 /** 1609 * fetch the variables 1610 */ 1611 $this->_fetchVariables( $template ); 1612 1613 /** 1614 * fetch the template 1615 */ 1616 $result = $this->_fetchTemplate($template); 1617 1618 if ($result === false) { 1619 $this->_templates[$template]['iteration']++; 1620 continue; 1621 } 1622 1623 /** 1624 * parse 1625 */ 1626 $this->_parseVariables( $template ); 1627 $result = $this->_parseDependencies( $template ); 1628 if (patErrorManager::isError($result)) { 1629 return $result; 1630 } 1631 1632 /** 1633 * store result 1634 */ 1635 $this->_templates[$template]['result'] .= $this->_templates[$template]['work']; 1636 1637 $this->_templates[$template]['iteration']++; 1638 1639 ++$loopCount; 1640 1641 /** 1642 * check for maximum loops 1643 */ 1644 if (isset($this->_templates[$template]['attributes']['maxloop'])) { 1645 if ($loopCount == $this->_templates[$template]['attributes']['maxloop'] && $i < ($loop-1)) { 1646 $loopCount = 0; 1647 $finished = true; 1648 $this->_templates[$template]['parsed'] = true; 1649 $this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a' ); 1650 $this->_templates[$template]['parsed'] = false; 1651 $this->_templates[$template]['result'] = ''; 1652 } 1653 } 1654 } 1655 1656 if (!$finished && isset($this->_templates[$template]['attributes']['maxloop'])) { 1657 $this->_templates[$template]['parsed'] = true; 1658 $this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a', false ); 1659 $this->_templates[$template]['parsed'] = false; 1660 $this->_templates[$template]['result'] = ''; 1661 $this->_templates[$this->_templates[$template]['attributes']['parent']]['work'] = ''; 1662 } 1663 1664 $this->_parseGlobals($template); 1665 1666 $this->_handleUnusedVars($template); 1667 1668 $this->_templates[$template]['parsed'] = true; 1669 1670 if (isset($this->_templates[$template]['attributes']['autoclear']) && $this->_templates[$template]['attributes']['autoclear'] == 'yes') { 1671 $this->_vars[$template] = array( 1672 'scalar' => array(), 1673 'rows' => array() 1674 ); 1675 } 1676 1677 if (isset($this->_templates[$template]['attributes']['outputfilter'])) { 1678 if (is_object($this->_templates[$template]['attributes']['outputfilter'])) { 1679 $filter = &$this->_templates[$template]['attributes']['outputfilter']; 1680 } else { 1681 $filter = &$this->loadModule('OutputFilter', $this->_templates[$template]['attributes']['outputfilter']); 1682 } 1683 1684 if (patErrorManager::isError($filter)) { 1685 return $filter; 1686 } 1687 1688 $this->_templates[$template]['result'] = $filter->apply($this->_templates[$template]['result']); 1689 } 1690 return true; 1691 } 1692 1693 /** 1694 * Initialize a template 1695 * 1696 * This method checks the variable specifications and 1697 * copys variables from other templates. 1698 * 1699 * @access private 1700 * @param string name of the template 1701 * @return boolean true on success 1702 */ 1703 function _initTemplate( $template ) 1704 { 1705 foreach( $this->_templates[$template]['copyVars'] as $dest => $src ) 1706 { 1707 /** 1708 * copy from the same template 1709 */ 1710 if( !is_array( $src ) ) 1711 { 1712 $srcTemplate = $template; 1713 $srcVar = $src; 1714 } 1715 else 1716 { 1717 $srcTemplate = $src[0]; 1718 $srcVar = $src[1]; 1719 } 1720 1721 $copied = false; 1722 1723 /** 1724 * copy from another template 1725 */ 1726 if( isset( $this->_vars[$srcTemplate] ) ) 1727 { 1728 if( isset( $this->_vars[$srcTemplate]['scalar'][$srcVar] ) ) 1729 { 1730 $this->_vars[$template]['scalar'][$dest] = $this->_vars[$srcTemplate]['scalar'][$srcVar]; 1731 continue; 1732 } 1733 1734 $rows = count( $this->_vars[$srcTemplate]['rows'] ); 1735 1736 for( $i = 0; $i < $rows; $i++ ) 1737 { 1738 if( !isset( $this->_vars[$srcTemplate]['rows'][$i][$srcVar] ) ) 1739 continue; 1740 if( !isset( $this->_vars[$template]['rows'][$i] ) ) 1741 $this->_vars[$template]['rows'][$i] = array(); 1742 $this->_vars[$template]['rows'][$i][$dest] = $this->_vars[$srcTemplate]['rows'][$i][$srcVar]; 1743 $copied = true; 1744 } 1745 } 1746 if( !$copied && isset( $this->_globals[$srcVar] )) 1747 { 1748 $this->_vars[$template]['scalar'][$dest] = $this->_globals[$srcVar]; 1749 } 1750 1751 } 1752 return true; 1753 } 1754 1755 /** 1756 * parse all variables in a template 1757 * 1758 * @access private 1759 * @param string 1760 */ 1761 function _parseVariables( $template ) 1762 { 1763 /** 1764 * modify variables before parsing 1765 */ 1766 $this->_applyModifers($template, $this->_templates[$template]['vars']); 1767 1768 foreach( $this->_templates[$template]['vars'] as $key => $value ) 1769 { 1770 if( is_array( $value ) ) 1771 { 1772 if( count( $this->_templates[$template]['currentDependencies'] ) == 1 ) 1773 { 1774 $child = $this->_templates[$template]['currentDependencies'][0]; 1775 } 1776 else 1777 { 1778 if( isset( $this->_templates[$template]['attributes']['child'] ) ) 1779 $child = $this->_templates[$template]['attributes']['child']; 1780 else 1781 continue; 1782 } 1783 1784 $this->setAttribute( $child, 'autoclear', 'yes' ); 1785 $this->addVar( $child, $key, $value ); 1786 continue; 1787 } 1788 1789 $var = $this->_startTag.$key.$this->_endTag; 1790 $this->_templates[$template]['work'] = str_replace( $var, $value, $this->_templates[$template]['work'] ); 1791 } 1792 return true; 1793 } 1794 1795 /** 1796 * parse global variables in the template 1797 * 1798 * @access private 1799 * @param string name of the template 1800 * @return boolean 1801 */ 1802 function _parseGlobals($template) 1803 { 1804 $globalVars = $this->_globals; 1805 $this->_applyModifers($template, $globalVars); 1806 1807 foreach( $globalVars as $key => $value ) 1808 { 1809 if( is_array( $value ) ) 1810 { 1811 continue; 1812 } 1813 1814 $var = $this->_startTag.$key.$this->_endTag; 1815 $this->_templates[$template]['result'] = str_replace( $var, $value, $this->_templates[$template]['result'] ); 1816 } 1817 return true; 1818 } 1819 1820 /** 1821 * apply variable modifiers 1822 * 1823 * The variables will be passed by reference. 1824 * 1825 * @access private 1826 * @param string name of the template (use modifiers from this template) 1827 * @param array variables to which the modifiers should be applied 1828 * @return boolean 1829 */ 1830 function _applyModifers($template, &$vars) 1831 { 1832 foreach ($this->_templates[$template]['modifyVars'] as $varname => $modifier) { 1833 if (!isset($vars[$varname])) { 1834 continue; 1835 } 1836 1837 if (($modifier['type'] === 'php' || $modifier['type'] === 'auto' ) && is_callable($modifier['mod'])) { 1838 $vars[$varname] = call_user_func($modifier['mod'], $vars[$varname]); 1839 continue; 1840 } 1841 1842 if ($modifier['type'] === 'php') { 1843 continue; 1844 } 1845 1846 $mod = &$this->loadModule( 'Modifier', ucfirst( $modifier['mod'] ) ); 1847 $vars[$varname] = $mod->modify( $vars[$varname], $modifier['params'] ); 1848 } 1849 1850 // apply the default modifier 1851 if (isset($this->_templates[$template]['attributes']['defaultmodifier'])) { 1852 1853 $defaultModifier = $this->_templates[$template]['attributes']['defaultmodifier']; 1854 if (is_callable($defaultModifier)) { 1855 $type = 'php'; 1856 } else { 1857 $type = 'custom'; 1858 $defaultModifier = &$this->loadModule('Modifier', ucfirst($defaultModifier)); 1859 } 1860 1861 1862 foreach (array_keys($vars) as $varname) { 1863 if (isset($this->_templates[$template]['modifyVars'][$varname])) { 1864 continue; 1865 } 1866 if ($type === 'php') { 1867 $vars[$varname] = call_user_func($defaultModifier, $vars[$varname]); 1868 } else { 1869 $vars[$varname] = $defaultModifier->modify($vars[$varname], array()); 1870 } 1871 } 1872 } 1873 1874 return true; 1875 } 1876 1877 /** 1878 * parse all dependencies in a template 1879 * 1880 * @access private 1881 * @param string 1882 */ 1883 function _parseDependencies($template) 1884 { 1885 $countDep = count( $this->_templates[$template]['currentDependencies'] ); 1886 for ($i = 0; $i < $countDep; $i++) { 1887 $depTemplate = $this->_templates[$template]['currentDependencies'][$i]; 1888 if ($depTemplate == $template) { 1889 return patErrorManager::raiseError(PATTEMPLATE_ERROR_RECURSION, 'You have an error in your template "' . $template . '", which leads to recursion'); 1890 } 1891 $this->parseTemplate($depTemplate); 1892 $var = $this->_startTag.'TMPL:'.strtoupper( $depTemplate) .$this->_endTag; 1893 $this->_templates[$template]['work'] = str_replace( $var, $this->_templates[$depTemplate]['result'], $this->_templates[$template]['work'] ); 1894 } 1895 return true; 1896 } 1897 1898 /** 1899 * fetch plain template 1900 * 1901 * The template content will be stored in the template 1902 * configuration so it can be used by other 1903 * methods. 1904 * 1905 * @access private 1906 * @param string template name 1907 * @return boolean 1908 */ 1909 function _fetchTemplate( $template ) 1910 { 1911 switch( $this->_templates[$template]['attributes']['type'] ) 1912 { 1913 /** 1914 * condition template 1915 */ 1916 case 'condition': 1917 $value = $this->_getConditionValue($template, $this->_templates[$template]['attributes']['conditionvar']); 1918 if ($value === false) { 1919 $this->_templates[$template]['work'] = ''; 1920 $this->_templates[$template]['currentDependencies'] = array(); 1921 } else { 1922 $this->_templates[$template]['work'] = $this->_templates[$template]['subtemplates'][$value]['data']; 1923 $this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['subtemplates'][$value]['dependencies']; 1924 } 1925 break; 1926 1927 /** 1928 * condition template 1929 */ 1930 case 'simplecondition': 1931 foreach( $this->_templates[$template]['attributes']['requiredvars'] as $var ) 1932 { 1933 // different template scope 1934 if( $var[0] !== $template ) { 1935 $this->_fetchVariables($var[0]); 1936 } 1937 $value = null; 1938 // fetch the local variable 1939 if( isset( $this->_templates[$var[0]]['vars'][$var[1]] ) 1940 && strlen( $this->_templates[$var[0]]['vars'][$var[1]] ) > 0 ) { 1941 $value = $this->_templates[$var[0]]['vars'][$var[1]]; 1942 } 1943 if (isset($this->_templates[$template]['attributes']['useglobals'])) { 1944 if(isset($this->_globals[$var[1]]) && strlen($this->_globals[$var[1]]) > 1) { 1945 $value = $this->_globals[$var[1]]; 1946 } 1947 } 1948 if ($value !== null) { 1949 if ($var[2] === null) { 1950 continue; 1951 } else { 1952 // Joomla! addition 23-June-2005 1953 // value wrapped in ## uses regex for comparison 1954 $condition = $var[2]; 1955 if (substr( $condition, 0, 1 ) == '#' && substr( $condition, -1, 1 ) == '#' ) { 1956 if (preg_match( $condition, $value )) { 1957 continue; 1958 } 1959 } else if ($condition == $value) { 1960 continue; 1961 } 1962 /* Pat Original 1963 if ($var[2] == $value) { 1964 continue; 1965 } 1966 */ 1967 } 1968 } 1969 1970 $this->_templates[$template]['work'] = ''; 1971 $this->_templates[$template]['currentDependencies'] = array(); 1972 break 2; 1973 } 1974 $this->_templates[$template]['work'] = $this->_templates[$template]['content']; 1975 $this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['dependencies']; 1976 break; 1977 1978 /** 1979 * modulo template 1980 */ 1981 case 'modulo': 1982 // check for empty template 1983 1984 if ($this->_hasVariables($template)) { 1985 $value = (string)($this->_templates[$template]['iteration'] + 1 ) % $this->_templates[$template]['attributes']['modulo']; 1986 } else { 1987 $value = '__empty'; 1988 } 1989 1990 $value = $this->_getConditionValue($template, $value, false); 1991 if ($value === false) { 1992 $this->_templates[$template]['work'] = ''; 1993 $this->_templates[$template]['currentDependencies'] = array(); 1994 } else { 1995 $this->_templates[$template]['work'] = $this->_templates[$template]['subtemplates'][$value]['data']; 1996 $this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['subtemplates'][$value]['dependencies']; 1997 } 1998 break; 1999 2000 /** 2001 * standard template 2002 */ 2003 default: 2004 $this->_templates[$template]['work'] = $this->_templates[$template]['content']; 2005 $this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['dependencies']; 2006 break; 2007 } 2008 return true; 2009 } 2010 2011 /** 2012 * check, whether a template contains variables 2013 * 2014 * @access private 2015 * @param string template name 2016 * @return boolean 2017 */ 2018 function _hasVariables($template) 2019 { 2020 if (!empty($this->_vars[$template]['scalar'])) { 2021 return true; 2022 } 2023 if (isset($this->_vars[$template]['rows'][$this->_templates[$template]['iteration']])) { 2024 return true; 2025 } 2026 return false; 2027 } 2028 2029 /** 2030 * fetch the value of a condition variable 2031 * 2032 * _fetchVariables() has to be called before this 2033 * method is being called. 2034 * 2035 * @access private 2036 * @param string template name 2037 * @param string condition value 2038 * @param boolean flag that indicates whether value is the name of the variable that should be resolved 2039 * 2040 * @todo split this method into smaller check methods that will be called according to 2041 * a priority list 2042 */ 2043 function _getConditionValue( $template, $value, $isVar = true ) 2044 { 2045 if ($isVar === true) { 2046 if (isset($this->_templates[$template]['attributes']['conditiontmpl'])) { 2047 $_template = $this->_templates[$template]['attributes']['conditiontmpl']; 2048 $this->_fetchVariables($_template); 2049 } else { 2050 $_template = $template; 2051 } 2052 2053 /** 2054 * get the value from the template variables 2055 */ 2056 if (!isset($this->_templates[$_template]['vars'][$value]) || strlen($this->_templates[$_template]['vars'][$value]) === 0) { 2057 if ($this->_templates[$template]['attributes']['useglobals'] == 'yes' || $this->_templates[$template]['attributes']['useglobals'] == 'useglobals') { 2058 if (isset( $this->_globals[$value] ) && strlen( $this->_globals[$value] ) > 0) { 2059 $value = $this->_globals[$value]; 2060 } else { 2061 $value = '__empty'; 2062 } 2063 } else { 2064 $value = '__empty'; 2065 } 2066 } else { 2067 $value = $this->_templates[$_template]['vars'][$value]; 2068 } 2069 } else { 2070 $_template = $template; 2071 } 2072 2073 // if value is empty and a template for empty has been defined, this 2074 // has priority 2075 if ($value === '__empty' && isset($this->_templates[$template]['subtemplates']['__empty'])) { 2076 return $value; 2077 } 2078 2079 // only one iteration (but not empty), use the __single condition 2080 if ($value !== '__empty' && $this->_templates[$_template]['loop'] === 1) { 2081 if( isset($this->_templates[$template]['subtemplates']['__single'])) { 2082 return '__single'; 2083 } 2084 } else { 2085 2086 // is __first? 2087 if( $this->_templates[$_template]['iteration'] == 0 ) { 2088 if( isset( $this->_templates[$template]['subtemplates']['__first'] ) ) { 2089 return '__first'; 2090 } 2091 } 2092 2093 /** 2094 * is __last? 2095 */ 2096 if (isset($this->_templates[$_template]['loop'])) { 2097 $max = $this->_templates[$_template]['loop'] - 1; 2098 if( $this->_templates[$_template]['iteration'] == $max ) { 2099 if( isset( $this->_templates[$template]['subtemplates']['__last'] ) ) { 2100 return '__last'; 2101 } 2102 } 2103 } 2104 } 2105 2106 // search for exact match 2107 foreach (array_keys($this->_templates[$template]['subtemplates']) as $key) { 2108 if (isset($this->_templates[$template]['subtemplates'][$key]['attributes']['var'])) { 2109 $var = $this->_templates[$template]['subtemplates'][$key]['attributes']['var']; 2110 if (isset($this->_templates[$template]['vars'][$var])) { 2111 $current = $this->_templates[$template]['vars'][$var]; 2112 } else { 2113 $current = null; 2114 } 2115 } else { 2116 $current = $key; 2117 } 2118 2119 if ((string)$value === (string)$current) { 2120 return $key; 2121 } 2122 } 2123 2124 /** 2125 * is __default? 2126 */ 2127 if( isset( $this->_templates[$template]['subtemplates']['__default'] ) ) { 2128 return '__default'; 2129 } 2130 2131 return false; 2132 } 2133 2134 /** 2135 * fetch variables for a template 2136 * 2137 * The variables will be stored in the template 2138 * configuration so they can be used by other 2139 * methods. 2140 * 2141 * @access private 2142 * @param string template name 2143 * @return boolean 2144 */ 2145 function _fetchVariables( $template ) 2146 { 2147 /** 2148 * variables already have been fetched 2149 */ 2150 if (isset($this->_templates[$template]['vars'])) { 2151 return true; 2152 } 2153 2154 $iteration = $this->_templates[$template]['iteration']; 2155 2156 $vars = array(); 2157 if( isset( $this->_templates[$template]['attributes']['varscope'] ) ) 2158 { 2159 if (!is_array($this->_templates[$template]['attributes']['varscope'])) { 2160 $this->_templates[$template]['attributes']['varscope'] = array($this->_templates[$template]['attributes']['varscope']); 2161 } 2162 foreach ($this->_templates[$template]['attributes']['varscope'] as $scopeTemplate) { 2163 if ($this->exists($scopeTemplate)) { 2164 $this->_fetchVariables( $scopeTemplate ); 2165 $vars = array_merge($this->_templates[$scopeTemplate]['vars'], $vars); 2166 } else { 2167 patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'Template \''.$scopeTemplate.'\' does not exist, referenced in varscope attribute of template \''.$template.'\''); 2168 } 2169 } 2170 } else { 2171 $vars = array(); 2172 } 2173 2174 /** 2175 * get the scalar variables 2176 */ 2177 if( isset( $this->_vars[$template] ) && isset( $this->_vars[$template]['scalar'] ) ) 2178 { 2179 $vars = array_merge( $vars, $this->_vars[$template]['scalar'] ); 2180 } 2181 2182 /** 2183 * get the row variables 2184 */ 2185 if( isset( $this->_vars[$template]['rows'][$iteration] ) ) 2186 { 2187 $vars = array_merge( $vars, $this->_vars[$template]['rows'][$iteration] ); 2188 } 2189 2190 /** 2191 * add some system variables 2192 */ 2193 $currentRow = $iteration + $this->_templates[$template]['attributes']['rowoffset']; 2194 $vars['PAT_ROW_VAR'] = $currentRow; 2195 2196 if( $this->_templates[$template]['attributes']['type'] == 'modulo' ) 2197 { 2198 $vars['PAT_MODULO_REP'] = ceil( $currentRow / $this->_templates[$template]['attributes']['modulo'] ); 2199 $vars['PAT_MODULO'] = ( $this->_templates[$template]['iteration'] + 1 ) % $this->_templates[$template]['attributes']['modulo']; 2200 } 2201 2202 if( $this->_templates[$template]['attributes']['addsystemvars'] !== false ) 2203 { 2204 $vars['PATTEMPLATE_VERSION'] = $this->_systemVars['appVersion']; 2205 $vars['PAT_LOOPS'] = $this->_templates[$template]['loop']; 2206 2207 switch ($this->_templates[$template]['attributes']['addsystemvars']) 2208 { 2209 case 'boolean': 2210 $trueValue = 'true'; 2211 $falseValue = 'false'; 2212 break; 2213 case 'integer': 2214 $trueValue = '1'; 2215 $falseValue = '0'; 2216 break; 2217 default: 2218 $trueValue = $this->_templates[$template]['attributes']['addsystemvars']; 2219 $falseValue = ''; 2220 break; 2221 } 2222 2223 $vars['PAT_IS_ODD'] = ( $currentRow % 2 == 1 ) ? $trueValue : $falseValue; 2224 $vars['PAT_IS_EVEN'] = ( $currentRow % 2 == 0 ) ? $trueValue : $falseValue; 2225 $vars['PAT_IS_FIRST'] = ( $currentRow == 1 ) ? $trueValue : $falseValue; 2226 $vars['PAT_IS_LAST'] = ( $currentRow == $this->_templates[$template]['loop'] ) ? $trueValue : $falseValue; 2227 $vars['PAT_ROW_TYPE'] = ( $currentRow % 2 == 1 ) ? 'odd' : 'even'; 2228 } 2229 2230 $this->_templates[$template]['vars'] = $vars; 2231 return true; 2232 } 2233 2234 /** 2235 * handle all unused variables in a template 2236 * 2237 * This is influenced by the 'unusedvars' attribute of the 2238 * template 2239 * 2240 * @access private 2241 * @param string 2242 */ 2243 function _handleUnusedVars( $template ) 2244 { 2245 $regexp = '/([^\\\])('.$this->_startTag.'[^a-z]+[^\\\]'.$this->_endTag.')/U'; 2246 2247 switch( $this->_templates[$template]['attributes']['unusedvars'] ) 2248 { 2249 case 'comment': 2250 $this->_templates[$template]['result'] = preg_replace( $regexp, '<!-- \\1\\2 -->', $this->_templates[$template]['result'] ); 2251 break; 2252 case 'strip': 2253 $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1', $this->_templates[$template]['result'] ); 2254 break; 2255 case 'nbsp': 2256 $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1 ', $this->_templates[$template]['result'] ); 2257 break; 2258 case 'ignore': 2259 break; 2260 default: 2261 $this->_templates[$template]['result'] = preg_replace( $regexp, '\\1'.$this->_templates[$template]['attributes']['unusedvars'], $this->_templates[$template]['result'] ); 2262 break; 2263 } 2264 2265 // replace quoted variables 2266 $regexp = '/[\\\]'.$this->_startTag.'([^a-z]+)[\\\]'.$this->_endTag.'/U'; 2267 $this->_templates[$template]['result'] = preg_replace( $regexp, $this->_startTag.'\\1'.$this->_endTag, $this->_templates[$template]['result'] ); 2268 2269 return true; 2270 } 2271 2272 /** 2273 * returns a parsed Template 2274 * 2275 * If the template already has been parsed, it just returns the parsed template. 2276 * If the template has not been loaded, it will be loaded. 2277 * 2278 * @access public 2279 * @param string name of the template 2280 * @param boolean whether to apply output filters 2281 * @return string Content of the parsed template 2282 * @see displayParsedTemplate() 2283 */ 2284 function getParsedTemplate( $name = null, $applyFilters = false ) 2285 { 2286 if (is_null($name)) { 2287 $name = $this->_root; 2288 } 2289 2290 $name = strtolower( $name ); 2291 $result = $this->parseTemplate( $name ); 2292 2293 if (patErrorManager::isError( $result )) { 2294 return $result; 2295 } 2296 2297 if ($applyFilters === false) { 2298 return $this->_templates[$name]['result']; 2299 } 2300 2301 $result = $this->_templates[$name]['result']; 2302 2303 $cnt = count ($this->_outputFilters); 2304 for ($i = 0; $i < $cnt; $i++) { 2305 $result = $this->_outputFilters[$i]->apply( $result ); 2306 } 2307 2308 return $result; 2309 } 2310 2311 /** 2312 * displays a parsed Template 2313 * 2314 * If the template has not been loaded, it will be loaded. 2315 * 2316 * @see getParsedTemplate() 2317 * @param string name of the template 2318 * @param boolean whether to apply output filters 2319 * @return boolean true on success 2320 * @access public 2321 */ 2322 function displayParsedTemplate($name = null, $applyFilters = true) 2323 { 2324 $result = $this->getParsedTemplate($name, $applyFilters); 2325 2326 /** 2327 * error happened 2328 */ 2329 if (patErrorManager::isError($result)) { 2330 return $result; 2331 } 2332 2333 echo $result; 2334 return true; 2335 } 2336 2337 /** 2338 * parse a template and push the result into a variable of any other 2339 * template 2340 * 2341 * If the template already has been parsed, it will just be pushed into the variable. 2342 * If the template has not been loaded, it will be loaded. 2343 * 2344 * @access public 2345 * @param string name of the template 2346 * @return string Content of the parsed template 2347 * @param boolean if set to true, the value will be appended to the value already stored. 2348 * @see getParsedTemplate() 2349 * @see addVar() 2350 */ 2351 function parseIntoVar( $srcTmpl, $destTmpl, $var, $append = false ) 2352 { 2353 $srcTmpl = strtolower( $srcTmpl ); 2354 $destTmpl = strtolower( $destTmpl ); 2355 $var = strtoupper($var); 2356 2357 $result = $this->parseTemplate( $srcTmpl ); 2358 2359 if( patErrorManager::isError( $result ) ) 2360 return $result; 2361 2362 if( $append !== true || !isset( $this->_vars[$destTmpl]['scalar'][$var] ) ) 2363 $this->_vars[$destTmpl]['scalar'][$var] = ''; 2364 2365 $this->_vars[$destTmpl]['scalar'][$var] .= $this->_templates[$srcTmpl]['result']; 2366 2367 return true; 2368 } 2369 2370 /** 2371 * clears a parsed Template 2372 * 2373 * Parsed Content, variables and the loop attribute are cleared 2374 * 2375 * If you will not be using this template anymore, then you should 2376 * call freeTemplate() 2377 * 2378 * @access public 2379 * @param string name of the template 2380 * @param boolean set this to true to clear all child templates, too 2381 * @see clearAllTemplates() 2382 * @see freeTemplate() 2383 */ 2384 function clearTemplate( $name, $recursive = false ) 2385 { 2386 $name = strtolower( $name ); 2387 $this->_templates[$name]['parsed'] = false; 2388 $this->_templates[$name]['work'] = ''; 2389 $this->_templates[$name]['iteration'] = 0; 2390 $this->_templates[$name]['result'] = ''; 2391 $this->_vars[$name] = array( 2392 'scalar' => array(), 2393 'rows' => array() 2394 ); 2395 2396 if (!empty($this->_templates[$name]['defaultVars'])) { 2397 foreach ($this->_templates[$name]['defaultVars'] as $varname => $value) { 2398 $this->addVar($name, $varname, $value); 2399 } 2400 } 2401 2402 /** 2403 * clear child templates as well 2404 */ 2405 if( $recursive === true ) 2406 { 2407 $deps = $this->_getDependencies( $name ); 2408 foreach( $deps as $dep ) 2409 { 2410 $this->clearTemplate( $dep, true ); 2411 } 2412 } 2413 return true; 2414 } 2415 2416 /** 2417 * clears all templates 2418 * 2419 * @access public 2420 * @uses clearTemplate() 2421 */ 2422 function clearAllTemplates() 2423 { 2424 $templates = array_keys( $this->_templates ); 2425 $cnt = count( $templates ); 2426 for( $i = 0; $i < $cnt; $i++ ) 2427 { 2428 $this->clearTemplate( $templates[$i] ); 2429 } 2430 return true; 2431 } 2432 2433 /** 2434 * frees a template 2435 * 2436 * All memory consumed by the template 2437 * will be freed. 2438 * 2439 * @access public 2440 * @param string name of the template 2441 * @param boolean clear dependencies of the template 2442 * @see freeAllTemplates() 2443 */ 2444 function freeTemplate( $name, $recursive = false ) 2445 { 2446 $name = strtolower( $name ); 2447 $key = array_search( $name, $this->_templateList ); 2448 if( $key === false ) 2449 { 2450 return patErrorManager::raiseWarning( 2451 PATTEMPLATE_WARNING_NO_TEMPLATE, 2452 "Template '$name' does not exist." 2453 ); 2454 } 2455 2456 unset( $this->_templateList[$key] ); 2457 $this->_templateList = array_values( $this->_templateList ); 2458 2459 /** 2460 * free child templates as well 2461 */ 2462 if( $recursive === true ) 2463 { 2464 $deps = $this->_getDependencies( $name ); 2465 foreach( $deps as $dep ) 2466 { 2467 $this->freeTemplate( $dep, true ); 2468 } 2469 } 2470 2471 unset( $this->_templates[$name] ); 2472 unset( $this->_vars[$name] ); 2473 if (isset($this->_discoveredPlaceholders[$name])) { 2474 unset($this->_discoveredPlaceholders[$name]); 2475 } 2476 2477 return true; 2478 } 2479 2480 /** 2481 * frees all templates 2482 * 2483 * All memory consumed by the templates 2484 * will be freed. 2485 * 2486 * @access public 2487 * @see freeTemplate() 2488 */ 2489 function freeAllTemplates() 2490 { 2491 $this->_templates = array(); 2492 $this->_vars = array(); 2493 $this->_templateList = array(); 2494 } 2495 2496 /** 2497 * get _all_ dependencies of a template, 2498 * regardless of the subtemplates 2499 * 2500 * @access private 2501 * @param string template name 2502 * @return array list of all subtemplates 2503 */ 2504 function _getDependencies( $template ) 2505 { 2506 $deps = array(); 2507 if( isset( $this->_templates[$template]['dependencies'] ) ) 2508 $deps = $this->_templates[$template]['dependencies']; 2509 2510 if( isset( $this->_templates[$template]['subtemplates'] ) ) 2511 { 2512 foreach( $this->_templates[$template]['subtemplates'] as $sub ) 2513 { 2514 if( isset( $sub['dependencies'] ) ) 2515 $deps = array_merge( $deps, $sub['dependencies'] ); 2516 } 2517 } 2518 $deps = array_unique( $deps ); 2519 return $deps; 2520 } 2521 2522 /** 2523 * Displays useful information about all or named templates 2524 * 2525 * This method breaks BC, as it now awaits an array instead of 2526 * unlimited parameters. 2527 * 2528 * @param mixed array of templates that should be dumped, or null if you 2529 * want all templates to be dumped 2530 * @param string dumper 2531 * @access public 2532 */ 2533 function dump( $restrict = null, $dumper = 'Html' ) 2534 { 2535 if( is_string( $restrict ) ) 2536 $restrict = array( $restrict ); 2537 2538 $dumper = &$this->loadModule( 'Dump', $dumper ); 2539 2540 if( patErrorManager::isError( $dumper ) ) 2541 { 2542 return $dumper; 2543 } 2544 2545 if( is_null( $restrict ) ) 2546 { 2547 $templates = $this->_templates; 2548 $vars = $this->_vars; 2549 } 2550 else 2551 { 2552 $restrict = array_map( 'strtolower', $restrict ); 2553 2554 $templates = array(); 2555 $vars = array(); 2556 2557 foreach( $this->_templates as $name => $spec ) 2558 { 2559 if( !in_array( $name, $restrict ) ) 2560 continue; 2561 $templates[$name] = $spec; 2562 $vars[$name] = $this->_vars[$name]; 2563 } 2564 } 2565 2566 $dumper->displayHeader(); 2567 $dumper->dumpGlobals( $this->_globals ); 2568 $dumper->dumpTemplates( $templates, $vars ); 2569 $dumper->displayFooter(); 2570 2571 return true; 2572 } 2573 2574 /** 2575 * get the include path 2576 * 2577 * @access public 2578 * @return string 2579 */ 2580 function getIncludePath() 2581 { 2582 return PATTEMPLATE_INCLUDE_PATH; 2583 } 2584 2585 /** 2586 * apply input filters that have been set 2587 * 2588 * This is being called by the readers. 2589 * 2590 * @access public 2591 * @param string template 2592 * @return string filtered templeta 2593 */ 2594 function applyInputFilters( $template ) 2595 { 2596 $cnt = count( $this->_inputFilters ); 2597 for( $i = 0; $i < $cnt; $i++ ) 2598 { 2599 $template = $this->_inputFilters[$i]->apply( $template ); 2600 } 2601 return $template; 2602 } 2603 2604 /** 2605 * checks, whether a placeholder exists in a template 2606 * 2607 * @access public 2608 * @param string name of the placeholder 2609 * @param string name of the template 2610 * @param boolean whether to use the cached result of a previous call 2611 */ 2612 function placeholderExists($placeholder, $tmpl, $cached = true) 2613 { 2614 $tmpl = strtolower($tmpl); 2615 $placeholder = strtoupper($placeholder); 2616 2617 if (!$this->exists($tmpl)) { 2618 return false; 2619 } 2620 2621 if ($cached === true) { 2622 if (isset($this->_discoveredPlaceholders[$tmpl]) && isset($this->_discoveredPlaceholders[$tmpl][$placeholder])) { 2623 return $this->_discoveredPlaceholders[$tmpl][$placeholder]; 2624 } 2625 } 2626 2627 if (isset($this->_templates[$tmpl]['subtemplates'])) { 2628 $content = ''; 2629 foreach ($this->_templates[$tmpl]['subtemplates'] as $temp) { 2630 if (!isset($temp['data'])) { 2631 continue; 2632 } 2633 $content .= $temp['data']; 2634 } 2635 } else { 2636 $content = $this->_templates[$tmpl]['content']; 2637 } 2638 2639 $search = $this->_startTag . $placeholder . $this->_endTag; 2640 if (strstr($content, $search) !== false) { 2641 $this->_discoveredPlaceholders[$tmpl][$placeholder] = true; 2642 return true; 2643 } 2644 $this->_discoveredPlaceholders[$tmpl][$placeholder] = false; 2645 return false; 2646 } 2647 2648 /** 2649 * Convert the template to its string representation. 2650 * 2651 * This method allows you to just echo the patTemplate 2652 * object in order to display the template. 2653 * 2654 * Requires PHP5 2655 * 2656 * <code> 2657 * $tmpl = new patTemplate(); 2658 * $tmpl->readTemplatesFromFile( 'myfile.tmpl' ); 2659 * echo $tmpl; 2660 * </code> 2661 * 2662 * @access private 2663 * @return string 2664 */ 2665 function __toString() 2666 { 2667 return $this->getParsedTemplate(); 2668 } 2669 } 2670 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Mar 28 15:54:07 2012 | Cross-referenced by PHPXref 0.7.1 |