[ Index ] |
|
Code source de PHP PEAR 1.4.5 |
1 <?php 2 // 3 // +----------------------------------------------------------------------+ 4 // | Copyright (c) 1997-2005 Ulf Wendel, Pierre-Alain Joye | 5 // +----------------------------------------------------------------------+ 6 // | This source file is subject to the New BSD license, That is bundled | 7 // | with this package in the file LICENSE, and is available through | 8 // | the world-wide-web at | 9 // | http://www.opensource.org/licenses/bsd-license.php | 10 // | If you did not receive a copy of the new BSDlicense and are unable | 11 // | to obtain it through the world-wide-web, please send a note to | 12 // | pajoye@php.net so we can mail you a copy immediately. | 13 // +----------------------------------------------------------------------+ 14 // | Author: Ulf Wendel <ulf.wendel@phpdoc.de> | 15 // | Pierre-Alain Joye <pajoye@php.net> | 16 // +----------------------------------------------------------------------+ 17 // 18 // $Id: IT.php,v 1.20 2006/08/17 15:47:22 dsp Exp $ 19 // 20 21 require_once 'PEAR.php'; 22 23 define('IT_OK', 1); 24 define('IT_ERROR', -1); 25 define('IT_TPL_NOT_FOUND', -2); 26 define('IT_BLOCK_NOT_FOUND', -3); 27 define('IT_BLOCK_DUPLICATE', -4); 28 define('IT_UNKNOWN_OPTION', -6); 29 /** 30 * Integrated Template - IT 31 * 32 * Well there's not much to say about it. I needed a template class that 33 * supports a single template file with multiple (nested) blocks inside and 34 * a simple block API. 35 * 36 * The Isotemplate API is somewhat tricky for a beginner although it is the best 37 * one you can build. template::parse() [phplib template = Isotemplate] requests 38 * you to name a source and a target where the current block gets parsed into. 39 * Source and target can be block names or even handler names. This API gives you 40 * a maximum of fexibility but you always have to know what you do which is 41 * quite unusual for php skripter like me. 42 * 43 * I noticed that I do not any control on which block gets parsed into which one. 44 * If all blocks are within one file, the script knows how they are nested and in 45 * which way you have to parse them. IT knows that inner1 is a child of block2, there's 46 * no need to tell him about this. 47 * 48 * <table border> 49 * <tr> 50 * <td colspan=2> 51 * __global__ 52 * <p> 53 * (hidden and automatically added) 54 * </td> 55 * </tr> 56 * <tr> 57 * <td>block1</td> 58 * <td> 59 * <table border> 60 * <tr> 61 * <td colspan=2>block2</td> 62 * </tr> 63 * <tr> 64 * <td>inner1</td> 65 * <td>inner2</td> 66 * </tr> 67 * </table> 68 * </td> 69 * </tr> 70 * </table> 71 * 72 * To add content to block1 you simply type: 73 * <code>$tpl->setCurrentBlock("block1");</code> 74 * and repeat this as often as needed: 75 * <code> 76 * $tpl->setVariable(...); 77 * $tpl->parseCurrentBlock(); 78 * </code> 79 * 80 * To add content to block2 you would type something like: 81 * <code> 82 * $tpl->setCurrentBlock("inner1"); 83 * $tpl->setVariable(...); 84 * $tpl->parseCurrentBlock(); 85 * 86 * $tpl->setVariable(...); 87 * $tpl->parseCurrentBlock(); 88 * 89 * $tpl->parse("block1"); 90 * </code> 91 * 92 * This will result in one repition of block1 which contains two repitions 93 * of inner1. inner2 will be removed if $removeEmptyBlock is set to true which is the default. 94 * 95 * Usage: 96 * <code> 97 * $tpl = new HTML_Template_IT( [string filerootdir] ); 98 * 99 * // load a template or set it with setTemplate() 100 * $tpl->loadTemplatefile( string filename [, boolean removeUnknownVariables, boolean removeEmptyBlocks] ) 101 * 102 * // set "global" Variables meaning variables not beeing within a (inner) block 103 * $tpl->setVariable( string variablename, mixed value ); 104 * 105 * // like with the Isotemplates there's a second way to use setVariable() 106 * $tpl->setVariable( array ( string varname => mixed value ) ); 107 * 108 * // Let's use any block, even a deeply nested one 109 * $tpl->setCurrentBlock( string blockname ); 110 * 111 * // repeat this as often as you need it. 112 * $tpl->setVariable( array ( string varname => mixed value ) ); 113 * $tpl->parseCurrentBlock(); 114 * 115 * // get the parsed template or print it: $tpl->show() 116 * $tpl->get(); 117 * </code> 118 * 119 * @author Ulf Wendel <uw@netuse.de> 120 * @version $Id: IT.php,v 1.20 2006/08/17 15:47:22 dsp Exp $ 121 * @access public 122 * @package HTML_Template_IT 123 */ 124 class HTML_Template_IT 125 { 126 /** 127 * Contains the error objects 128 * @var array 129 * @access public 130 * @see halt(), $printError, $haltOnError 131 */ 132 var $err = array(); 133 134 /** 135 * Clear cache on get()? 136 * @var boolean 137 */ 138 var $clearCache = false; 139 140 /** 141 * First character of a variable placeholder ( _{_VARIABLE} ). 142 * @var string 143 * @access public 144 * @see $closingDelimiter, $blocknameRegExp, $variablenameRegExp 145 */ 146 var $openingDelimiter = '{'; 147 148 /** 149 * Last character of a variable placeholder ( {VARIABLE_}_ ). 150 * @var string 151 * @access public 152 * @see $openingDelimiter, $blocknameRegExp, $variablenameRegExp 153 */ 154 var $closingDelimiter = '}'; 155 156 /** 157 * RegExp matching a block in the template. 158 * Per default "sm" is used as the regexp modifier, "i" is missing. 159 * That means a case sensitive search is done. 160 * @var string 161 * @access public 162 * @see $variablenameRegExp, $openingDelimiter, $closingDelimiter 163 */ 164 var $blocknameRegExp = '[\.0-9A-Za-z_-]+'; 165 166 /** 167 * RegExp matching a variable placeholder in the template. 168 * Per default "sm" is used as the regexp modifier, "i" is missing. 169 * That means a case sensitive search is done. 170 * @var string 171 * @access public 172 * @see $blocknameRegExp, $openingDelimiter, $closingDelimiter 173 */ 174 var $variablenameRegExp = '[\.0-9A-Za-z_-]+'; 175 176 /** 177 * RegExp used to find variable placeholder, filled by the constructor. 178 * @var string Looks somewhat like @(delimiter varname delimiter)@ 179 * @access public 180 * @see IntegratedTemplate() 181 */ 182 var $variablesRegExp = ''; 183 184 /** 185 * RegExp used to strip unused variable placeholder. 186 * @brother $variablesRegExp 187 */ 188 var $removeVariablesRegExp = ''; 189 190 /** 191 * Controls the handling of unknown variables, default is remove. 192 * @var boolean 193 * @access public 194 */ 195 var $removeUnknownVariables = true; 196 197 /** 198 * Controls the handling of empty blocks, default is remove. 199 * @var boolean 200 * @access public 201 */ 202 var $removeEmptyBlocks = true; 203 204 /** 205 * RegExp used to find blocks an their content, filled by the constructor. 206 * @var string 207 * @see IntegratedTemplate() 208 */ 209 var $blockRegExp = ''; 210 211 /** 212 * Name of the current block. 213 * @var string 214 */ 215 var $currentBlock = '__global__'; 216 217 /** 218 * Content of the template. 219 * @var string 220 */ 221 var $template = ''; 222 223 /** 224 * Array of all blocks and their content. 225 * 226 * @var array 227 * @see findBlocks() 228 */ 229 var $blocklist = array(); 230 231 /** 232 * Array with the parsed content of a block. 233 * 234 * @var array 235 */ 236 var $blockdata = array(); 237 238 /** 239 * Array of variables in a block. 240 * @var array 241 */ 242 var $blockvariables = array(); 243 244 /** 245 * Array of inner blocks of a block. 246 * @var array 247 */ 248 var $blockinner = array(); 249 250 /** 251 * List of blocks to preverse even if they are "empty". 252 * 253 * This is something special. Sometimes you have blocks that 254 * should be preserved although they are empty (no placeholder replaced). 255 * Think of a shopping basket. If it's empty you have to drop a message to 256 * the user. If it's filled you have to show the contents of 257 * the shopping baseket. Now where do you place the message that the basket 258 * is empty? It's no good idea to place it in you applications as customers 259 * tend to like unecessary minor text changes. Having another template file 260 * for an empty basket means that it's very likely that one fine day 261 * the filled and empty basket templates have different layout. I decided 262 * to introduce blocks that to not contain any placeholder but only 263 * text such as the message "Your shopping basked is empty". 264 * 265 * Now if there is no replacement done in such a block the block will 266 * be recognized as "empty" and by default ($removeEmptyBlocks = true) be 267 * stripped off. To avoid thisyou can now call touchBlock() to avoid this. 268 * 269 * The array $touchedBlocks stores a list of touched block which must not 270 * be removed even if they are empty. 271 * 272 * @var array $touchedBlocks 273 * @see touchBlock(), $removeEmptyBlocks 274 */ 275 var $touchedBlocks = array(); 276 277 /** 278 * List of blocks which should not be shown even if not "empty" 279 * @var array $_hiddenBlocks 280 * @see hideBlock(), $removeEmptyBlocks 281 */ 282 var $_hiddenBlocks = array(); 283 284 /** 285 * Variable cache. 286 * 287 * Variables get cached before any replacement is done. 288 * Advantage: empty blocks can be removed automatically. 289 * Disadvantage: might take some more memory 290 * 291 * @var array 292 * @see setVariable(), $clearCacheOnParse 293 */ 294 var $variableCache = array(); 295 296 /** 297 * Clear the variable cache on parse? 298 * 299 * If you're not an expert just leave the default false. 300 * True reduces memory consumption somewhat if you tend to 301 * add lots of values for unknown placeholder. 302 * 303 * @var boolean 304 */ 305 var $clearCacheOnParse = false; 306 307 /** 308 * Root directory for all file operations. 309 * The string gets prefixed to all filenames given. 310 * @var string 311 * @see HTML_Template_IT(), setRoot() 312 */ 313 var $fileRoot = ''; 314 315 /** 316 * Internal flag indicating that a blockname was used multiple times. 317 * @var boolean 318 */ 319 var $flagBlocktrouble = false; 320 321 /** 322 * Flag indicating that the global block was parsed. 323 * @var boolean 324 */ 325 var $flagGlobalParsed = false; 326 327 /** 328 * EXPERIMENTAL! FIXME! 329 * Flag indication that a template gets cached. 330 * 331 * Complex templates require some times to be preparsed 332 * before the replacement can take place. Often I use 333 * one template file over and over again but I don't know 334 * before that I will use the same template file again. 335 * Now IT could notice this and skip the preparse. 336 * 337 * @var boolean 338 */ 339 var $flagCacheTemplatefile = true; 340 341 /** 342 * EXPERIMENTAL! FIXME! 343 */ 344 var $lastTemplatefile = ''; 345 346 /** 347 * $_options['preserve_data'] Whether to substitute variables and remove 348 * empty placeholders in data passed through setVariable 349 * (see also bugs #20199, #21951). 350 * $_options['use_preg'] Whether to use preg_replace instead of 351 * str_replace in parse() 352 * (this is a backwards compatibility feature, see also bugs #21951, #20392) 353 */ 354 var $_options = array( 355 'preserve_data' => false, 356 'use_preg' => true 357 ); 358 359 /** 360 * Builds some complex regular expressions and optinally sets the 361 * file root directory. 362 * 363 * Make sure that you call this constructor if you derive your template 364 * class from this one. 365 * 366 * @param string File root directory, prefix for all filenames 367 * given to the object. 368 * @see setRoot() 369 */ 370 function HTML_Template_IT($root = '', $options = null) 371 { 372 if (!is_null($options)) { 373 $this->setOptions($options); 374 } 375 $this->variablesRegExp = '@' . $this->openingDelimiter . 376 '(' . $this->variablenameRegExp . ')' . 377 $this->closingDelimiter . '@sm'; 378 $this->removeVariablesRegExp = '@' . $this->openingDelimiter . 379 "\s*(" . $this->variablenameRegExp . 380 ")\s*" . $this->closingDelimiter .'@sm'; 381 382 $this->blockRegExp = '@<!--\s+BEGIN\s+(' . $this->blocknameRegExp . 383 ')\s+-->(.*)<!--\s+END\s+\1\s+-->@sm'; 384 385 $this->setRoot($root); 386 } // end constructor 387 388 389 /** 390 * Sets the option for the template class 391 * 392 * @access public 393 * @param string option name 394 * @param mixed option value 395 * @return mixed IT_OK on success, error object on failure 396 */ 397 function setOption($option, $value) 398 { 399 if (array_key_exists($option, $this->_options)) { 400 $this->_options[$option] = $value; 401 return IT_OK; 402 } 403 404 return PEAR::raiseError( 405 $this->errorMessage(IT_UNKNOWN_OPTION) . ": '{$option}'", 406 IT_UNKNOWN_OPTION 407 ); 408 } 409 410 /** 411 * Sets the options for the template class 412 * 413 * @access public 414 * @param string options array of options 415 * default value: 416 * 'preserve_data' => false, 417 * 'use_preg' => true 418 * @param mixed option value 419 * @return mixed IT_OK on success, error object on failure 420 * @see $options 421 */ 422 function setOptions($options) 423 { 424 if (is_array($options)) { 425 foreach ($options as $option => $value) { 426 $error = $this->setOption($option, $value); 427 if (PEAR::isError($error)) { 428 return $error; 429 } 430 } 431 } 432 433 return IT_OK; 434 } 435 436 /** 437 * Print a certain block with all replacements done. 438 * @brother get() 439 */ 440 function show($block = '__global__') 441 { 442 print $this->get($block); 443 } // end func show 444 445 /** 446 * Returns a block with all replacements done. 447 * 448 * @param string name of the block 449 * @return string 450 * @throws PEAR_Error 451 * @access public 452 * @see show() 453 */ 454 function get($block = '__global__') 455 { 456 if ($block == '__global__' && !$this->flagGlobalParsed) { 457 $this->parse('__global__'); 458 } 459 460 if (!isset($this->blocklist[$block])) { 461 $this->err[] = PEAR::raiseError( 462 $this->errorMessage(IT_BLOCK_NOT_FOUND) . 463 '"' . $block . "'", 464 IT_BLOCK_NOT_FOUND 465 ); 466 return ''; 467 } 468 469 if (isset($this->blockdata[$block])) { 470 $ret = $this->blockdata[$block]; 471 if ($this->clearCache) { 472 unset($this->blockdata[$block]); 473 } 474 if ($this->_options['preserve_data']) { 475 $ret = str_replace( 476 $this->openingDelimiter . 477 '%preserved%' . $this->closingDelimiter, 478 $this->openingDelimiter, 479 $ret 480 ); 481 } 482 return $ret; 483 } 484 485 return ''; 486 } // end func get() 487 488 /** 489 * Parses the given block. 490 * 491 * @param string name of the block to be parsed 492 * @access public 493 * @see parseCurrentBlock() 494 * @throws PEAR_Error 495 */ 496 function parse($block = '__global__', $flag_recursion = false) 497 { 498 static $regs, $values; 499 500 if (!isset($this->blocklist[$block])) { 501 return PEAR::raiseError( 502 $this->errorMessage( IT_BLOCK_NOT_FOUND ) . '"' . $block . "'", 503 IT_BLOCK_NOT_FOUND 504 ); 505 } 506 507 if ($block == '__global__') { 508 $this->flagGlobalParsed = true; 509 } 510 511 if (!$flag_recursion) { 512 $regs = array(); 513 $values = array(); 514 } 515 $outer = $this->blocklist[$block]; 516 $empty = true; 517 518 if ($this->clearCacheOnParse) { 519 foreach ($this->variableCache as $name => $value) { 520 $regs[] = $this->openingDelimiter . 521 $name . $this->closingDelimiter; 522 $values[] = $value; 523 $empty = false; 524 } 525 $this->variableCache = array(); 526 } else { 527 foreach ($this->blockvariables[$block] as $allowedvar => $v) { 528 529 if (isset($this->variableCache[$allowedvar])) { 530 $regs[] = $this->openingDelimiter . 531 $allowedvar . $this->closingDelimiter; 532 $values[] = $this->variableCache[$allowedvar]; 533 unset($this->variableCache[$allowedvar]); 534 $empty = false; 535 } 536 } 537 } 538 539 if (isset($this->blockinner[$block])) { 540 foreach ($this->blockinner[$block] as $k => $innerblock) { 541 542 $this->parse($innerblock, true); 543 if ($this->blockdata[$innerblock] != '') { 544 $empty = false; 545 } 546 547 $placeholder = $this->openingDelimiter . "__" . 548 $innerblock . "__" . $this->closingDelimiter; 549 $outer = str_replace( 550 $placeholder, 551 $this->blockdata[$innerblock], $outer 552 ); 553 $this->blockdata[$innerblock] = ""; 554 } 555 556 } 557 558 if (!$flag_recursion && 0 != count($values)) { 559 if ($this->_options['use_preg']) { 560 $regs = array_map(array( 561 &$this, '_addPregDelimiters'), 562 $regs 563 ); 564 $funcReplace = 'preg_replace'; 565 } else { 566 $funcReplace = 'str_replace'; 567 } 568 569 if ($this->_options['preserve_data']) { 570 $values = array_map( 571 array(&$this, '_preserveOpeningDelimiter'), $values 572 ); 573 } 574 575 $outer = $funcReplace($regs, $values, $outer); 576 577 if ($this->removeUnknownVariables) { 578 $outer = preg_replace($this->removeVariablesRegExp, "", $outer); 579 } 580 } 581 582 if ($empty) { 583 if (!$this->removeEmptyBlocks) { 584 $this->blockdata[$block ].= $outer; 585 } else { 586 if (isset($this->touchedBlocks[$block])) { 587 $this->blockdata[$block] .= $outer; 588 unset($this->touchedBlocks[$block]); 589 } 590 } 591 } else { 592 if (empty($this->blockdata[$block])) { 593 $this->blockdata[$block] = $outer; 594 } else { 595 $this->blockdata[$block] .= $outer; 596 } 597 } 598 599 return $empty; 600 } // end func parse 601 602 /** 603 * Parses the current block 604 * @see parse(), setCurrentBlock(), $currentBlock 605 * @access public 606 */ 607 function parseCurrentBlock() 608 { 609 return $this->parse($this->currentBlock); 610 } // end func parseCurrentBlock 611 612 /** 613 * Sets a variable value. 614 * 615 * The function can be used eighter like setVariable( "varname", "value") 616 * or with one array $variables["varname"] = "value" 617 * given setVariable($variables) quite like phplib templates set_var(). 618 * 619 * @param mixed string with the variable name or an array 620 * %variables["varname"] = "value" 621 * @param string value of the variable or empty if $variable 622 * is an array. 623 * @param string prefix for variable names 624 * @access public 625 */ 626 function setVariable($variable, $value = '') 627 { 628 if (is_array($variable)) { 629 $this->variableCache = array_merge( 630 $this->variableCache, $variable 631 ); 632 } else { 633 $this->variableCache[$variable] = $value; 634 } 635 } // end func setVariable 636 637 /** 638 * Sets the name of the current block that is the block where variables 639 * are added. 640 * 641 * @param string name of the block 642 * @return boolean false on failure, otherwise true 643 * @throws PEAR_Error 644 * @access public 645 */ 646 function setCurrentBlock($block = '__global__') 647 { 648 649 if (!isset($this->blocklist[$block])) { 650 return PEAR::raiseError( 651 $this->errorMessage( IT_BLOCK_NOT_FOUND ) . 652 '"' . $block . "'", IT_BLOCK_NOT_FOUND 653 ); 654 } 655 656 $this->currentBlock = $block; 657 658 return true; 659 } // end func setCurrentBlock 660 661 /** 662 * Preserves an empty block even if removeEmptyBlocks is true. 663 * 664 * @param string name of the block 665 * @return boolean false on false, otherwise true 666 * @throws PEAR_Error 667 * @access public 668 * @see $removeEmptyBlocks 669 */ 670 function touchBlock($block) 671 { 672 if (!isset($this->blocklist[$block])) { 673 return PEAR::raiseError( 674 $this->errorMessage(IT_BLOCK_NOT_FOUND) . 675 '"' . $block . "'", IT_BLOCK_NOT_FOUND); 676 } 677 678 $this->touchedBlocks[$block] = true; 679 680 return true; 681 } // end func touchBlock 682 683 /** 684 * Clears all datafields of the object and rebuild the internal blocklist 685 * 686 * LoadTemplatefile() and setTemplate() automatically call this function 687 * when a new template is given. Don't use this function 688 * unless you know what you're doing. 689 * 690 * @access public 691 * @see free() 692 */ 693 function init() 694 { 695 $this->free(); 696 $this->findBlocks($this->template); 697 // we don't need it any more 698 $this->template = ''; 699 $this->buildBlockvariablelist(); 700 } // end func init 701 702 /** 703 * Clears all datafields of the object. 704 * 705 * Don't use this function unless you know what you're doing. 706 * 707 * @access public 708 * @see init() 709 */ 710 function free() 711 { 712 $this->err = array(); 713 714 $this->currentBlock = '__global__'; 715 716 $this->variableCache = array(); 717 $this->blocklist = array(); 718 $this->touchedBlocks = array(); 719 720 $this->flagBlocktrouble = false; 721 $this->flagGlobalParsed = false; 722 } // end func free 723 724 /** 725 * Sets the template. 726 * 727 * You can eighter load a template file from disk with 728 * LoadTemplatefile() or set the template manually using this function. 729 * 730 * @param string template content 731 * @param boolean remove unknown/unused variables? 732 * @param boolean remove empty blocks? 733 * @see LoadTemplatefile(), $template 734 * @access public 735 * @return boolean 736 */ 737 function setTemplate( $template, $removeUnknownVariables = true, 738 $removeEmptyBlocks = true) 739 { 740 $this->removeUnknownVariables = $removeUnknownVariables; 741 $this->removeEmptyBlocks = $removeEmptyBlocks; 742 743 if ($template == '' && $this->flagCacheTemplatefile) { 744 $this->variableCache = array(); 745 $this->blockdata = array(); 746 $this->touchedBlocks = array(); 747 $this->currentBlock = '__global__'; 748 } else { 749 $this->template = '<!-- BEGIN __global__ -->' . $template . 750 '<!-- END __global__ -->'; 751 $this->init(); 752 } 753 754 if ($this->flagBlocktrouble) { 755 return false; 756 } 757 758 return true; 759 } // end func setTemplate 760 761 /** 762 * Reads a template file from the disk. 763 * 764 * @param string name of the template file 765 * @param bool how to handle unknown variables. 766 * @param bool how to handle empty blocks. 767 * @access public 768 * @return boolean false on failure, otherwise true 769 * @see $template, setTemplate(), $removeUnknownVariables, 770 * $removeEmptyBlocks 771 */ 772 function loadTemplatefile( $filename, 773 $removeUnknownVariables = true, 774 $removeEmptyBlocks = true ) 775 { 776 $template = ''; 777 if (!$this->flagCacheTemplatefile || 778 $this->lastTemplatefile != $filename 779 ) { 780 $template = $this->getFile($filename); 781 } 782 $this->lastTemplatefile = $filename; 783 784 return $template != '' ? 785 $this->setTemplate( 786 $template,$removeUnknownVariables, $removeEmptyBlocks 787 ) : false; 788 } // end func LoadTemplatefile 789 790 /** 791 * Sets the file root. The file root gets prefixed to all filenames passed 792 * to the object. 793 * 794 * Make sure that you override this function when using the class 795 * on windows. 796 * 797 * @param string 798 * @see HTML_Template_IT() 799 * @access public 800 */ 801 function setRoot($root) 802 { 803 if ($root != '' && substr($root, -1) != '/') { 804 $root .= '/'; 805 } 806 807 $this->fileRoot = $root; 808 } // end func setRoot 809 810 /** 811 * Build a list of all variables within of a block 812 */ 813 function buildBlockvariablelist() 814 { 815 foreach ($this->blocklist as $name => $content) { 816 preg_match_all($this->variablesRegExp, $content, $regs); 817 818 if (count($regs[1]) != 0) { 819 foreach ($regs[1] as $k => $var) { 820 $this->blockvariables[$name][$var] = true; 821 } 822 } else { 823 $this->blockvariables[$name] = array(); 824 } 825 } 826 } // end func buildBlockvariablelist 827 828 /** 829 * Returns a list of all global variables 830 */ 831 function getGlobalvariables() 832 { 833 $regs = array(); 834 $values = array(); 835 836 foreach ($this->blockvariables['__global__'] as $allowedvar => $v) { 837 if (isset($this->variableCache[$allowedvar])) { 838 $regs[] = '@' . $this->openingDelimiter . 839 $allowedvar . $this->closingDelimiter . '@'; 840 $values[] = $this->variableCache[$allowedvar]; 841 unset($this->variableCache[$allowedvar]); 842 } 843 } 844 845 return array($regs, $values); 846 } // end func getGlobalvariables 847 848 /** 849 * Recusively builds a list of all blocks within the template. 850 * 851 * @param string string that gets scanned 852 * @see $blocklist 853 */ 854 function findBlocks($string) 855 { 856 $blocklist = array(); 857 858 if (preg_match_all($this->blockRegExp, $string, $regs, PREG_SET_ORDER)) { 859 foreach ($regs as $k => $match) { 860 $blockname = $match[1]; 861 $blockcontent = $match[2]; 862 863 if (isset($this->blocklist[$blockname])) { 864 $this->err[] = PEAR::raiseError( 865 $this->errorMessage( 866 IT_BLOCK_DUPLICATE, $blockname), 867 IT_BLOCK_DUPLICATE 868 ); 869 $this->flagBlocktrouble = true; 870 } 871 872 $this->blocklist[$blockname] = $blockcontent; 873 $this->blockdata[$blockname] = ""; 874 875 $blocklist[] = $blockname; 876 877 $inner = $this->findBlocks($blockcontent); 878 foreach ($inner as $k => $name) { 879 $pattern = sprintf( 880 '@<!--\s+BEGIN\s+%s\s+-->(.*)<!--\s+END\s+%s\s+-->@sm', 881 $name, 882 $name 883 ); 884 885 $this->blocklist[$blockname] = preg_replace( 886 $pattern, 887 $this->openingDelimiter . 888 '__' . $name . '__' . 889 $this->closingDelimiter, 890 $this->blocklist[$blockname] 891 ); 892 $this->blockinner[$blockname][] = $name; 893 $this->blockparents[$name] = $blockname; 894 } 895 } 896 } 897 898 return $blocklist; 899 } // end func findBlocks 900 901 /** 902 * Reads a file from disk and returns its content. 903 * @param string Filename 904 * @return string Filecontent 905 */ 906 function getFile($filename) 907 { 908 if ($filename{0} == '/' && substr($this->fileRoot, -1) == '/') { 909 $filename = substr($filename, 1); 910 } 911 912 $filename = $this->fileRoot . $filename; 913 914 if (!($fh = @fopen($filename, 'r'))) { 915 $this->err[] = PEAR::raiseError( 916 $this->errorMessage(IT_TPL_NOT_FOUND) . 917 ': "' .$filename .'"', 918 IT_TPL_NOT_FOUND 919 ); 920 return ""; 921 } 922 923 $fsize = filesize($filename); 924 if ($fsize < 1) { 925 fclose($fh); 926 return ''; 927 } 928 929 $content = fread($fh, $fsize); 930 fclose($fh); 931 932 return preg_replace( 933 "#<!-- INCLUDE (.*) -->#ime", "\$this->getFile('\\1')", $content 934 ); 935 } // end func getFile 936 937 /** 938 * Adds delimiters to a string, so it can be used as a pattern 939 * in preg_* functions 940 * 941 * @param string 942 * @return string 943 */ 944 function _addPregDelimiters($str) 945 { 946 return '@' . $str . '@'; 947 } 948 949 /** 950 * Replaces an opening delimiter by a special string 951 * 952 * @param string 953 * @return string 954 */ 955 function _preserveOpeningDelimiter($str) 956 { 957 return (false === strpos($str, $this->openingDelimiter))? 958 $str: 959 str_replace( 960 $this->openingDelimiter, 961 $this->openingDelimiter . 962 '%preserved%' . $this->closingDelimiter, 963 $str 964 ); 965 } 966 967 /** 968 * Return a textual error message for a IT error code 969 * 970 * @param integer $value error code 971 * 972 * @return string error message, or false if the error code was 973 * not recognized 974 */ 975 function errorMessage($value, $blockname = '') 976 { 977 static $errorMessages; 978 if (!isset($errorMessages)) { 979 $errorMessages = array( 980 IT_OK => '', 981 IT_ERROR => 'unknown error', 982 IT_TPL_NOT_FOUND => 'Cannot read the template file', 983 IT_BLOCK_NOT_FOUND => 'Cannot find this block', 984 IT_BLOCK_DUPLICATE => 'The name of a block must be'. 985 ' uniquewithin a template.'. 986 ' Found "' . $blockname . '" twice.'. 987 'Unpredictable results '. 988 'may appear.', 989 IT_UNKNOWN_OPTION => 'Unknown option' 990 ); 991 } 992 993 if (PEAR::isError($value)) { 994 $value = $value->getCode(); 995 } 996 997 return isset($errorMessages[$value]) ? 998 $errorMessages[$value] : $errorMessages[IT_ERROR]; 999 } 1000 } // end class IntegratedTemplate 1001 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 14:08:00 2007 | par Balluche grâce à PHPXref 0.7 |