[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 <?php 2 3 /** 4 * 5 * Error constants. 6 * 7 */ 8 9 define('SAVANT2_ERROR_ASSIGN', -1); 10 define('SAVANT2_ERROR_ASSIGNREF', -2); 11 define('SAVANT2_ERROR_COMPILER', -3); 12 define('SAVANT2_ERROR_NOFILTER', -4); 13 define('SAVANT2_ERROR_NOPLUGIN', -5); 14 define('SAVANT2_ERROR_NOSCRIPT', -6); 15 define('SAVANT2_ERROR_NOTEMPLATE', -7); 16 define('SAVANT2_ERROR_COMPILE_FAIL', -8); 17 18 19 /** 20 * 21 * Error messages. 22 * 23 */ 24 25 if (! isset($GLOBALS['_SAVANT2']['error'])) { 26 $GLOBALS['_SAVANT2']['error'] = array( 27 SAVANT2_ERROR_ASSIGN => 'assign() parameters not correct', 28 SAVANT2_ERROR_ASSIGNREF => 'assignRef() parameters not correct', 29 SAVANT2_ERROR_COMPILER => 'compiler not an object or has no compile() method', 30 SAVANT2_ERROR_NOFILTER => 'filter file not found', 31 SAVANT2_ERROR_NOPLUGIN => 'plugin file not found', 32 SAVANT2_ERROR_NOSCRIPT => 'compiled template script file not found', 33 SAVANT2_ERROR_NOTEMPLATE => 'template source file not found', 34 SAVANT2_ERROR_COMPILE_FAIL => 'template source failed to compile' 35 ); 36 } 37 38 39 /** 40 * 41 * Provides an object-oriented template system. 42 * 43 * Savant2 helps you separate model logic from view logic using PHP as 44 * the template language. By default, Savant2 does not compile templates. 45 * However, you may pass an optional compiler object to compile template 46 * source to include-able PHP code. 47 * 48 * Please see the documentation at {@link http://phpsavant.com/}, and be 49 * sure to donate! :-) 50 * 51 * $Id: Savant2.php 18360 2005-05-26 19:38:09Z mipmip $ 52 * 53 * @author Paul M. Jones <pmjones@ciaweb.net> 54 * 55 * @package Savant2 56 * 57 * @version 2.3.3 stable 58 * 59 * @license http://www.gnu.org/copyleft/lesser.html LGPL 60 * 61 * This program is free software; you can redistribute it and/or modify 62 * it under the terms of the GNU Lesser General Public License as 63 * published by the Free Software Foundation; either version 2.1 of the 64 * License, or (at your option) any later version. 65 * 66 * This program is distributed in the hope that it will be useful, but 67 * WITHOUT ANY WARRANTY; without even the implied warranty of 68 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 69 * Lesser General Public License for more details. 70 * 71 */ 72 73 class Savant2 { 74 75 76 /** 77 * 78 * PHP5 ONLY: What method __call() will alias to. 79 * 80 * Generally 'plugin' or 'splugin' (as __call() is intended for those). 81 * 82 * @access private 83 * 84 * @var string 85 * 86 */ 87 88 var $_call = 'plugin'; 89 90 91 /** 92 * 93 * The custom compiler (pre-processor) object, if any. 94 * 95 * @access private 96 * 97 * @var object 98 * 99 */ 100 101 var $_compiler = null; 102 103 104 /** 105 * 106 * The class type to use when instantiating error objects. 107 * 108 * @access private 109 * 110 * @var string 111 * 112 */ 113 114 var $_error = null; 115 116 117 /** 118 * 119 * Whether or not to extract assigned variables into fetch() scope. 120 * 121 * When true, all variables and references assigned to Savant2 are 122 * extracted into the local scope of the template script at fetch() 123 * time, and may be addressed as "$varname" instead of 124 * "$this->varname". The "$this->varname" notation will also work. 125 * 126 * When false, you //must// use "$this->varname" in your templates to 127 * address a variable instead of "$varname". This has three 128 * benefits: speed (no time spent extracting variables), memory use 129 * (saves RAM by not making new references to variables), and clarity 130 * (any $this->varname is obviously an assigned var, and vars created 131 * within the template are not prefixed with $this). 132 * 133 * @access private 134 * 135 * @var bool 136 * 137 */ 138 139 var $_extract = false; 140 141 142 /** 143 * 144 * The output of the template script. 145 * 146 * @access private 147 * 148 * @var string 149 * 150 */ 151 152 var $_output = null; 153 154 155 /** 156 * 157 * The set of search directories for resources (plugins/filters) and 158 * templates. 159 * 160 * @access private 161 * 162 * @var array 163 * 164 */ 165 166 var $_path = array( 167 'resource' => array(), 168 'template' => array() 169 ); 170 171 172 /** 173 * 174 * Array of resource (plugin/filter) object instances. 175 * 176 * @access private 177 * 178 * @var array 179 * 180 */ 181 182 var $_resource = array( 183 'plugin' => array(), 184 'filter' => array() 185 ); 186 187 188 /** 189 * 190 * Whether or not to automatically self-reference in plugins and filters. 191 * 192 * @access private 193 * 194 * @var bool 195 * 196 */ 197 198 var $_reference = false; 199 200 201 /** 202 * 203 * The path to the compiled template script file. 204 * 205 * By default, the template source and template script are the same file. 206 * 207 * @access private 208 * 209 * @var string 210 * 211 */ 212 213 var $_script = null; 214 215 216 /** 217 * 218 * The name of the default template source file. 219 * 220 * @access private 221 * 222 * @var string 223 * 224 */ 225 226 var $_template = null; 227 228 var $_restrict = false; 229 230 231 // ----------------------------------------------------------------- 232 // 233 // Constructor and general property setters 234 // 235 // ----------------------------------------------------------------- 236 237 238 /** 239 * 240 * Constructor. 241 * 242 * @access public 243 * 244 * @param array $conf An associative array of configuration keys for 245 * the Savant2 object. Any, or none, of the keys may be set. The 246 * keys are: 247 * 248 * 'template_path' => The default path string or array of directories 249 * to search for templates. 250 * 251 * 'resource_path' => The default path string or array of directories 252 * to search for plugin and filter resources. 253 * 254 * 'error' => The custom error class that Savant2 should use 255 * when returning errors. 256 * 257 * 'extract' => Whether or not to extract variables into the local 258 * scope when executing a template. 259 * 260 * 'template' => The default template source name to use. 261 * 262 */ 263 264 function Savant2($conf = array()) 265 { 266 // set the default template search dirs 267 if (isset($conf['template_path'])) { 268 // user-defined dirs 269 $this->setPath('template', $conf['template_path']); 270 } else { 271 // default directory only 272 $this->setPath('template', null); 273 } 274 275 // set the default filter search dirs 276 if (isset($conf['resource_path'])) { 277 // user-defined dirs 278 $this->setPath('resource', $conf['resource_path']); 279 } else { 280 // default directory only 281 $this->setPath('resource', null); 282 } 283 284 // set the error class 285 if (isset($conf['error'])) { 286 $this->setError($conf['error']); 287 } 288 289 // set the extraction flag 290 if (isset($conf['extract'])) { 291 $this->setExtract($conf['extract']); 292 } 293 294 // set the restrict flag 295 if (isset($conf['restrict'])) { 296 $this->setRestrict($conf['restrict']); 297 } 298 299 // set the Savant reference flag 300 if (isset($conf['reference'])) { 301 $this->setReference($conf['reference']); 302 } 303 304 // set the default template 305 if (isset($conf['template'])) { 306 $this->setTemplate($conf['template']); 307 } 308 } 309 310 311 /** 312 * 313 * Sets a custom compiler/pre-processor for template sources. 314 * 315 * By default, Savant2 does not use a compiler; use this to set your 316 * own custom compiler (pre-processor) for template sources. 317 * 318 * @access public 319 * 320 * @param object $compiler The compiler object; it must have a 321 * "compile()" method. If null or false, the current compiler object 322 * is removed from Savant2. 323 * 324 * @return void 325 * 326 * @throws object An error object with a SAVANT2_ERROR_COMPILER code. 327 * 328 */ 329 330 function setCompiler(&$compiler) 331 { 332 if (! $compiler) { 333 // nullify any current compiler 334 $this->_compiler = null; 335 } elseif (is_object($compiler) && method_exists($compiler, 'compile')) { 336 // refer to a compiler object 337 $this->_compiler =& $compiler; 338 } else { 339 // no usable compiler passed 340 $this->_compiler = null; 341 return $this->error(SAVANT2_ERROR_COMPILER); 342 } 343 } 344 345 346 /** 347 * 348 * Sets the method that __call() will alias to. 349 * 350 * @access public 351 * 352 * @param string $method The Savant2 method for __call() to alias to, 353 * generally 'plugin' or 'splugin'. 354 * 355 * @return void 356 * 357 */ 358 359 function setCall($method = 'plugin') 360 { 361 $this->_call = $method; 362 } 363 364 365 /** 366 * 367 * Sets the custom error class for Savant2 errors. 368 * 369 * @access public 370 * 371 * @param string $error The name of the custom error class name; if 372 * null or false, resets the error class to 'Savant2_Error'. 373 * 374 * @return void 375 * 376 */ 377 378 function setError($error) 379 { 380 if (! $error) { 381 $this->_error = null; 382 } else { 383 $this->_error = $error; 384 } 385 } 386 387 388 /** 389 * 390 * Turns path checking on/off. 391 * 392 * @access public 393 * 394 * @param bool $flag True to turn on path checks, false to turn off. 395 * 396 * @return void 397 * 398 */ 399 400 function setRestrict($flag = false) 401 { 402 if ($flag) { 403 $this->_restrict = true; 404 } else { 405 $this->_restrict = false; 406 } 407 } 408 409 410 /** 411 * 412 * Turns extraction of variables on/off. 413 * 414 * @access public 415 * 416 * @param bool $flag True to turn on extraction, false to turn off. 417 * 418 * @return void 419 * 420 */ 421 422 function setExtract($flag = true) 423 { 424 if ($flag) { 425 $this->_extract = true; 426 } else { 427 $this->_extract = false; 428 } 429 } 430 431 432 /** 433 * 434 * Sets the automated Savant reference for plugins and filters. 435 * 436 * @access public 437 * 438 * @param bool $flag Whether to reference Savant2 or not. 439 * 440 * @return void 441 * 442 */ 443 444 function setReference($flag = false) 445 { 446 $this->_reference = $flag; 447 } 448 449 450 /** 451 * 452 * Sets the default template name. 453 * 454 * @access public 455 * 456 * @param string $template The default template name. 457 * 458 * @return void 459 * 460 */ 461 462 function setTemplate($template) 463 { 464 $this->_template = $template; 465 } 466 467 468 // ----------------------------------------------------------------- 469 // 470 // Path management and file finding 471 // 472 // ----------------------------------------------------------------- 473 474 475 /** 476 * 477 * Sets an entire array of search paths. 478 * 479 * @access public 480 * 481 * @param string $type The type of path to set, typcially 'template' 482 * or 'resource'. 483 * 484 * @param string|array $new The new set of search paths. If null or 485 * false, resets to the current directory only. 486 * 487 * @return void 488 * 489 */ 490 491 function setPath($type, $new) 492 { 493 // clear out the prior search dirs 494 $this->_path[$type] = array(); 495 496 // convert from string to path 497 if (is_string($new) && ! strpos('://', $new)) { 498 // the search config is a string, and it's not a stream 499 // identifier (the "://" piece), add it as a path 500 // string. 501 $new = explode(PATH_SEPARATOR, $new); 502 } else { 503 // force to array 504 settype($new, 'array'); 505 } 506 507 // always add the fallback directories as last resort 508 switch (strtolower($type)) { 509 case 'template': 510 $this->addPath($type, '.'); 511 break; 512 case 'resource': 513 $this->addPath($type, dirname(__FILE__) . '/Savant2/'); 514 break; 515 } 516 517 // actually add the user-specified directories 518 foreach ($new as $dir) { 519 $this->addPath($type, $dir); 520 } 521 } 522 523 524 /** 525 * 526 * Adds a search directory for templates. 527 * 528 * @access public 529 * 530 * @param string $dir The directory or stream to search. 531 * 532 * @return void 533 * 534 */ 535 536 function addPath($type, $dir) 537 { 538 // no surrounding spaces allowed! 539 $dir = trim($dir); 540 541 // add trailing separators as needed 542 if (strpos($dir, '://') && substr($dir, -1) != '/') { 543 // stream 544 $dir .= '/'; 545 } elseif (substr($dir, -1) != DIRECTORY_SEPARATOR) { 546 // directory 547 $dir .= DIRECTORY_SEPARATOR; 548 } 549 550 // add to the top of the search dirs 551 array_unshift($this->_path[$type], $dir); 552 } 553 554 555 /** 556 * 557 * Gets the array of search directories for template sources. 558 * 559 * @access public 560 * 561 * @return array The array of search directories for template sources. 562 * 563 */ 564 565 function getPath($type = null) 566 { 567 if (! $type) { 568 return $this->_path; 569 } else { 570 return $this->_path[$type]; 571 } 572 } 573 574 575 /** 576 * 577 * Searches a series of paths for a given file. 578 * 579 * @param array $type The type of paths to search (template, plugin, 580 * or filter). 581 * 582 * @param string $file The file name to look for. 583 * 584 * @return string|bool The full path and file name for the target file, 585 * or boolean false if the file is not found in any of the paths. 586 * 587 */ 588 589 function findFile($type, $file) 590 { 591 // get the set of paths 592 $set = $this->getPath($type); 593 594 // start looping through them 595 foreach ($set as $path) { 596 597 // get the path to the file 598 $fullname = $path . $file; 599 600 // are we doing path checks? 601 if (! $this->_restrict) { 602 603 // no. this is faster but less secure. 604 if (file_exists($fullname) && is_readable($fullname)) { 605 return $fullname; 606 } 607 608 } else { 609 610 // yes. this is slower, but attempts to restrict 611 // access only to defined paths. 612 613 // is the path based on a stream? 614 if (strpos('://', $path) === false) { 615 // not a stream, so do a realpath() to avoid 616 // directory traversal attempts on the local file 617 // system. Suggested by Ian Eure, initially 618 // rejected, but then adopted when the secure 619 // compiler was added. 620 $path = realpath($path); // needed for substr() later 621 $fullname = realpath($fullname); 622 } 623 624 // the substr() check added by Ian Eure to make sure 625 // that the realpath() results in a directory registered 626 // with Savant so that non-registered directores are not 627 // accessible via directory traversal attempts. 628 if (file_exists($fullname) && is_readable($fullname) && 629 substr($fullname, 0, strlen($path)) == $path) { 630 return $fullname; 631 } 632 } 633 } 634 635 // could not find the file in the set of paths 636 return false; 637 } 638 639 640 // ----------------------------------------------------------------- 641 // 642 // Variable and reference assignment 643 // 644 // ----------------------------------------------------------------- 645 646 647 /** 648 * 649 * Sets variables for the template. 650 * 651 * This method is overloaded; you can assign all the properties of 652 * an object, an associative array, or a single value by name. 653 * 654 * You are not allowed to set variables that begin with an underscore; 655 * these are either private properties for Savant2 or private variables 656 * within the template script itself. 657 * 658 * <code> 659 * 660 * $Savant2 =& new Savant2(); 661 * 662 * // assign directly 663 * $Savant2->var1 = 'something'; 664 * $Savant2->var2 = 'else'; 665 * 666 * // assign by name and value 667 * $Savant2->assign('var1', 'something'); 668 * $Savant2->assign('var2', 'else'); 669 * 670 * // assign by assoc-array 671 * $ary = array('var1' => 'something', 'var2' => 'else'); 672 * $Savant2->assign($obj); 673 * 674 * // assign by object 675 * $obj = new stdClass; 676 * $obj->var1 = 'something'; 677 * $obj->var2 = 'else'; 678 * $Savant2->assign($obj); 679 * 680 * </code> 681 * 682 * Greg Beaver came up with the idea of assigning to public class 683 * properties. 684 * 685 * @access public 686 * 687 * @return void 688 * 689 * @throws object An error object with a SAVANT2_ERROR_ASSIGN code. 690 * 691 */ 692 693 function assign() 694 { 695 // this method is overloaded. 696 $arg = func_get_args(); 697 698 // must have at least one argument. no error, just do nothing. 699 if (! isset($arg[0])) { 700 return; 701 } 702 703 // assign by object 704 if (is_object($arg[0])) { 705 // assign public properties 706 foreach (get_object_vars($arg[0]) as $key => $val) { 707 if (substr($key, 0, 1) != '_') { 708 $this->$key = $val; 709 } 710 } 711 return; 712 } 713 714 // assign by associative array 715 if (is_array($arg[0])) { 716 foreach ($arg[0] as $key => $val) { 717 if (substr($key, 0, 1) != '_') { 718 $this->$key = $val; 719 } 720 } 721 return; 722 } 723 724 // assign by string name and mixed value. 725 // 726 // we use array_key_exists() instead of isset() becuase isset() 727 // fails if the value is set to null. 728 if (is_string($arg[0]) && 729 substr($arg[0], 0, 1) != '_' && 730 array_key_exists(1, $arg)) { 731 $this->$arg[0] = $arg[1]; 732 } else { 733 return $this->error(SAVANT2_ERROR_ASSIGN, $arg); 734 } 735 } 736 737 738 /** 739 * 740 * Sets references for the template. 741 * 742 * // assign by name and value 743 * $Savant2->assignRef('ref', $reference); 744 * 745 * // assign directly 746 * $Savant2->ref =& $reference; 747 * 748 * Greg Beaver came up with the idea of assigning to public class 749 * properties. 750 * 751 * @access public 752 * 753 * @param string $key The name for the reference in the template. 754 * 755 * @param mixed &$val The referenced variable. 756 * 757 * @return void 758 * 759 * @throws object An error object with a SAVANT2_ERROR_ASSIGNREF code. 760 * 761 */ 762 763 function assignRef($key, &$val) 764 { 765 if (is_string($key) && substr($key, 0, 1) != '_') { 766 $this->$key =& $val; 767 } else { 768 return $this->error( 769 SAVANT2_ERROR_ASSIGNREF, 770 array('key' => $key, 'val' => $val) 771 ); 772 } 773 } 774 775 776 /** 777 * 778 * Unsets assigned variables and references. 779 * 780 * @access public 781 * 782 * @param mixed $var If null, clears all variables; if a string, clears 783 * the one variable named by the string; if a sequential array, clears 784 * the variables names in that array. 785 * 786 * @return void 787 * 788 */ 789 790 function clear($var = null) 791 { 792 if (is_null($var)) { 793 // clear all variables 794 $var = array_keys(get_object_vars($this)); 795 } else { 796 // clear specific variables 797 settype($var, 'array'); 798 } 799 800 // clear out the selected variables 801 foreach ($var as $name) { 802 if (substr($name, 0, 1) != '_' && isset($this->$name)) { 803 unset($this->$name); 804 } 805 } 806 } 807 808 809 /** 810 * 811 * Gets the current value of one, many, or all assigned variables. 812 * 813 * Never returns variables starting with an underscore; these are 814 * reserved for internal Savant2 use. 815 * 816 * @access public 817 * 818 * @param mixed $key If null, returns a copy of all variables and 819 * their values; if an array, returns an only those variables named 820 * in the array; if a string, returns only that variable. 821 * 822 * @return mixed If multiple variables were reqested, returns an 823 * associative array where the key is the variable name and the 824 * value is the variable value; if one variable was requested, 825 * returns the variable value only. 826 * 827 */ 828 829 function getVars($key = null) 830 { 831 if (is_null($key)) { 832 $key = array_keys(get_object_vars($this)); 833 } 834 835 if (is_array($key)) { 836 // return a series of vars 837 $tmp = array(); 838 foreach ($key as $var) { 839 if (substr($var, 0, 1) != '_' && isset($this->$var)) { 840 $tmp[$var] = $this->$var; 841 } 842 } 843 return $tmp; 844 } else { 845 // return a single var 846 if (substr($key, 0, 1) != '_' && isset($this->$key)) { 847 return $this->$key; 848 } 849 } 850 } 851 852 853 // ----------------------------------------------------------------- 854 // 855 // Template processing 856 // 857 // ----------------------------------------------------------------- 858 859 860 /** 861 * 862 * Loads a template script for execution (does not execute the script). 863 * 864 * This will optionally compile the template source into a PHP script 865 * if a compiler object has been passed into Savant2. 866 * 867 * Also good for including templates from the template paths within 868 * another template, like so: 869 * 870 * include $this->loadTemplate('template.tpl.php'); 871 * 872 * @access public 873 * 874 * @param string $tpl The template source name to look for. 875 * 876 * @param bool $setScript Default false; if true, sets the $this->_script 877 * property to the resulting script path (or null on error). Normally, 878 * only $this->fetch() will need to set this to true. 879 * 880 * @return string The full path to the compiled template script. 881 * 882 * @throws object An error object with a SAVANT2_ERROR_NOTEMPLATE code. 883 * 884 */ 885 886 function loadTemplate($tpl = null, $setScript = false) 887 { 888 // set to default template if none specified. 889 if (is_null($tpl)) { 890 $tpl = $this->_template; 891 } 892 893 // find the template source. 894 $file = $this->findFile('template', $tpl); 895 if (! $file) { 896 return $this->error( 897 SAVANT2_ERROR_NOTEMPLATE, 898 array('template' => $tpl) 899 ); 900 } 901 902 // are we compiling source into a script? 903 if (is_object($this->_compiler)) { 904 // compile the template source and get the path to the 905 // compiled script (will be returned instead of the 906 // source path) 907 $result = $this->_compiler->compile($file); 908 } else { 909 // no compiling requested, return the source path 910 $result = $file; 911 } 912 913 // is there a script from the compiler? 914 if (! $result || $this->isError($result)) { 915 916 if ($setScript) { 917 $this->_script = null; 918 } 919 920 // return an error, along with any error info 921 // generated by the compiler. 922 return $this->error( 923 SAVANT2_ERROR_NOSCRIPT, 924 array( 925 'template' => $tpl, 926 'compiler' => $result 927 ) 928 ); 929 930 } else { 931 932 if ($setScript) { 933 $this->_script = $result; 934 } 935 936 return $result; 937 938 } 939 } 940 941 942 /** 943 * 944 * This is a an alias to loadTemplate() that cannot set the script. 945 * 946 * @access public 947 * 948 * @param string $tpl The template source name to look for. 949 * 950 * @return string The full path to the compiled template script. 951 * 952 * @throws object An error object with a SAVANT2_ERROR_NOTEMPLATE code. 953 * 954 */ 955 956 function findTemplate($tpl = null) 957 { 958 return $this->loadTemplate($tpl, false); 959 } 960 961 962 /** 963 * 964 * Executes a template script and returns the results as a string. 965 * 966 * @param string $_tpl The name of the template source file ... 967 * automatically searches the template paths and compiles as needed. 968 * 969 * @return string The output of the the template script. 970 * 971 * @throws object An error object with a SAVANT2_ERROR_NOSCRIPT code. 972 * 973 */ 974 975 function fetch($_tpl = null) 976 { 977 // clear prior output 978 $this->_output = null; 979 980 // load the template script 981 $_result = $this->loadTemplate($_tpl, true); 982 983 // is there a template script to be processed? 984 if ($this->isError($_result)) { 985 return $_result; 986 } 987 988 // unset so as not to introduce into template scope 989 unset($_tpl); 990 unset($_result); 991 992 // never allow a 'this' property 993 if (isset($this->this)) { 994 unset($this->this); 995 } 996 997 // are we extracting variables into local scope? 998 if ($this->_extract) { 999 // extract references to this object's public properties. 1000 // this allows variables assigned by-reference to refer all 1001 // the way back to the model logic. variables assigned 1002 // by-copy only refer back to the property. 1003 foreach (array_keys(get_object_vars($this)) as $_prop) { 1004 if (substr($_prop, 0, 1) != '_') { 1005 // set a variable-variable to an object property 1006 // reference 1007 $$_prop =& $this->$_prop; 1008 } 1009 } 1010 1011 // unset private loop vars 1012 unset($_prop); 1013 } 1014 1015 // start capturing output into a buffer 1016 ob_start(); 1017 1018 // include the requested template filename in the local scope 1019 // (this will execute the view logic). 1020 include $this->_script; 1021 1022 // done with the requested template; get the buffer and 1023 // clear it. 1024 $this->_output = ob_get_contents(); 1025 ob_end_clean(); 1026 1027 // done! 1028 return $this->applyFilters(); 1029 } 1030 1031 1032 /** 1033 * 1034 * Execute and display a template script. 1035 * 1036 * @param string $tpl The name of the template file to parse; 1037 * automatically searches through the template paths. 1038 * 1039 * @return void 1040 * 1041 * @throws object An error object with a SAVANT2_ERROR_NOSCRIPT code. 1042 * 1043 * @see fetch() 1044 * 1045 */ 1046 1047 function display($tpl = null) 1048 { 1049 $result = $this->fetch($tpl); 1050 if ($this->isError($result)) { 1051 return $result; 1052 } else { 1053 echo $result; 1054 } 1055 } 1056 1057 1058 // ----------------------------------------------------------------- 1059 // 1060 // Plugins 1061 // 1062 // ----------------------------------------------------------------- 1063 1064 1065 /** 1066 * 1067 * Loads a plugin class and instantiates it within Savant2. 1068 * 1069 * @access public 1070 * 1071 * @param string $name The plugin name (not including Savant2_Plugin_ 1072 * prefix). 1073 * 1074 * @param array $conf An associative array of plugin configuration 1075 * options. 1076 * 1077 * @param bool $savantRef Default false. When true, sets the $Savant 1078 * property of the filter to a reference to this Savant object. 1079 * 1080 * @return void 1081 * 1082 * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code. 1083 * 1084 */ 1085 1086 function loadPlugin($name, $conf = array(), $savantRef = null) 1087 { 1088 // if no $savantRef is provided, use the default. 1089 if (is_null($savantRef)) { 1090 $savantRef = $this->_reference; 1091 } 1092 1093 // some basic information 1094 $class = "Savant2_Plugin_$name"; 1095 $file = "$class.php"; 1096 1097 // is it loaded? 1098 if (! class_exists($class)) { 1099 1100 $result = $this->findFile('resource', $file); 1101 if (! $result) { 1102 return $this->error( 1103 SAVANT2_ERROR_NOPLUGIN, 1104 array('plugin' => $name) 1105 ); 1106 } else { 1107 include_once $result; 1108 } 1109 } 1110 1111 // is it instantiated? 1112 if (! isset($this->_resource['plugin'][$name]) || 1113 ! is_object($this->_resource['plugin'][$name]) || 1114 ! is_a($this->_resource['plugin'][$name], $class)) { 1115 1116 // instantiate it 1117 $this->_resource['plugin'][$name] =& new $class($conf); 1118 1119 // add a Savant reference if requested 1120 if ($savantRef) { 1121 $this->_resource['plugin'][$name]->Savant =& $this; 1122 } 1123 1124 } 1125 } 1126 1127 1128 /** 1129 * 1130 * Unloads one or more plugins from Savant2. 1131 * 1132 * @access public 1133 * 1134 * @param string|array $name The plugin name (not including Savant2_Plugin_ 1135 * prefix). If null, unloads all plugins; if a string, unloads that one 1136 * plugin; if an array, unloads all plugins named as values in the array. 1137 * 1138 * @return void 1139 * 1140 */ 1141 1142 function unloadPlugin($name = null) 1143 { 1144 if (is_null($name)) { 1145 $this->_resource['plugin'] = array(); 1146 } else { 1147 settype($name, 'array'); 1148 foreach ($name as $key) { 1149 if (isset($this->_resource['plugin'][$key])) { 1150 unset($this->_resource['plugin'][$key]); 1151 } 1152 } 1153 } 1154 } 1155 1156 1157 /** 1158 * 1159 * Executes a plugin with arbitrary parameters and returns the 1160 * result. 1161 * 1162 * @access public 1163 * 1164 * @param string $name The plugin name (not including Savant2_Plugin_ 1165 * prefix). 1166 * 1167 * @return mixed The plugin results. 1168 * 1169 * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code. 1170 * 1171 * @see loadPlugin() 1172 * 1173 */ 1174 1175 function splugin($name) 1176 { 1177 // attempt to load the plugin 1178 $result = $this->loadPlugin($name); 1179 if ($this->isError($result)) { 1180 return $result; 1181 } 1182 1183 // call the plugin's "plugin()" method with arguments, 1184 // dropping the first argument (the plugin name) 1185 $args = func_get_args(); 1186 array_shift($args); 1187 return call_user_func_array( 1188 array(&$this->_resource['plugin'][$name], 'plugin'), $args 1189 ); 1190 } 1191 1192 1193 /** 1194 * 1195 * Executes a plugin with arbitrary parameters and displays the 1196 * result. 1197 * 1198 * @access public 1199 * 1200 * @param string $name The plugin name (not including Savant2_Plugin_ 1201 * prefix). 1202 * 1203 * @return void 1204 * 1205 * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code. 1206 * 1207 */ 1208 1209 function plugin($name) 1210 { 1211 $args = func_get_args(); 1212 1213 $result = call_user_func_array( 1214 array(&$this, 'splugin'), 1215 $args 1216 ); 1217 1218 if ($this->isError($result)) { 1219 return $result; 1220 } else { 1221 echo $result; 1222 } 1223 } 1224 1225 1226 /** 1227 * 1228 * PHP5 ONLY: Magic method alias to plugin(). 1229 * 1230 * E.g., instead of $this->plugin('form', ...) you would use 1231 * $this->form(...). You can set this to use any other Savant2 method 1232 * by issuing, for example, setCall('splugin') to use splugin() ... which 1233 * is really the only other sensible choice. 1234 * 1235 * @access public 1236 * 1237 * @param string $func The plugin name. 1238 * 1239 * @param array $args Arguments passed to the plugin. 1240 * 1241 * @return void 1242 * 1243 * @throws object An error object with a SAVANT2_ERROR_NOPLUGIN code. 1244 * 1245 */ 1246 1247 function __call($func, $args) 1248 { 1249 // add the plugin name to the args 1250 array_unshift($args, $func); 1251 1252 // call the plugin() method 1253 return call_user_func_array( 1254 array(&$this, $this->_call), 1255 $args 1256 ); 1257 } 1258 1259 1260 // ----------------------------------------------------------------- 1261 // 1262 // Filters 1263 // 1264 // ----------------------------------------------------------------- 1265 1266 1267 /** 1268 * 1269 * Loads a filter class and instantiates it within Savant2. 1270 * 1271 * @access public 1272 * 1273 * @param string $name The filter name (not including Savant2_Filter_ 1274 * prefix). 1275 * 1276 * @param array $conf An associative array of filter configuration 1277 * options. 1278 * 1279 * @param bool $savantRef Default false. When true, sets the $Savant 1280 * property of the filter to a reference to this Savant object. 1281 * 1282 * @return void 1283 * 1284 * @throws object An error object with a SAVANT2_ERROR_NOFILTER code. 1285 * 1286 */ 1287 1288 function loadFilter($name, $conf = array(), $savantRef = null) 1289 { 1290 // if no $savantRef is provided, use the default. 1291 if (is_null($savantRef)) { 1292 $savantRef = $this->_reference; 1293 } 1294 1295 // some basic information 1296 $class = "Savant2_Filter_$name"; 1297 $file = "$class.php"; 1298 1299 // is it loaded? 1300 if (! class_exists($class)) { 1301 1302 $result = $this->findFile('resource', $file); 1303 if (! $result) { 1304 return $this->error( 1305 SAVANT2_ERROR_NOFILTER, 1306 array('filter' => $name) 1307 ); 1308 } else { 1309 include_once $result; 1310 } 1311 } 1312 1313 // is it instantiated? 1314 if (! isset($this->_resource['filter'][$name]) || 1315 ! is_object($this->_resource['filter'][$name]) || 1316 ! is_a($this->_resource['filter'][$name], $class)) { 1317 1318 // instantiate it 1319 $this->_resource['filter'][$name] =& new $class($conf); 1320 1321 // add a Savant reference if requested 1322 if ($savantRef) { 1323 $this->_resource['filter'][$name]->Savant =& $this; 1324 } 1325 1326 } 1327 } 1328 1329 1330 /** 1331 * 1332 * Unloads one or more filters from Savant2. 1333 * 1334 * @access public 1335 * 1336 * @param string|array $name The filter name (not including Savant2_Filter_ 1337 * prefix). If null, unloads all filters; if a string, unloads that one 1338 * filter; if an array, unloads all filters named as values in the array. 1339 * 1340 * @return void 1341 * 1342 */ 1343 1344 function unloadFilter($name = null) 1345 { 1346 if (is_null($name)) { 1347 $this->_resource['filter'] = array(); 1348 } else { 1349 settype($name, 'array'); 1350 foreach ($name as $key) { 1351 if (isset($this->_resource['filter'][$key])) { 1352 unset($this->_resource['filter'][$key]); 1353 } 1354 } 1355 } 1356 } 1357 1358 1359 /** 1360 * 1361 * Apply all loaded filters, in order, to text. 1362 * 1363 * @access public 1364 * 1365 * @param string $text The text to which filters should be applied. 1366 * If null, sets the text to $this->_output. 1367 * 1368 * @return string The text after being passed through all loded 1369 * filters. 1370 * 1371 */ 1372 1373 function applyFilters($text = null) 1374 { 1375 // set to output text if no text specified 1376 if (is_null($text)) { 1377 $text = $this->_output; 1378 } 1379 1380 // get the list of filter names... 1381 $filter = array_keys($this->_resource['filter']); 1382 1383 // ... and apply them each in turn. 1384 foreach ($filter as $name) { 1385 $this->_resource['filter'][$name]->filter($text); 1386 } 1387 1388 // done 1389 return $text; 1390 } 1391 1392 1393 // ----------------------------------------------------------------- 1394 // 1395 // Error handling 1396 // 1397 // ----------------------------------------------------------------- 1398 1399 1400 /** 1401 * 1402 * Returns an error object. 1403 * 1404 * @access public 1405 * 1406 * @param int $code A SAVANT2_ERROR_* constant. 1407 * 1408 * @param array $info An array of error-specific information. 1409 * 1410 * @return object An error object of the type specified by 1411 * $this->_error. 1412 * 1413 */ 1414 1415 function &error($code, $info = array()) 1416 { 1417 // the error config array 1418 $conf = array( 1419 'code' => $code, 1420 'text' => 'Savant2: ', 1421 'info' => (array) $info 1422 ); 1423 1424 // set an error message from the globals 1425 if (isset($GLOBALS['_SAVANT2']['error'][$code])) { 1426 $conf['text'] .= $GLOBALS['_SAVANT2']['error'][$code]; 1427 } else { 1428 $conf['text'] .= '???'; 1429 } 1430 1431 // set up the error class name 1432 if ($this->_error) { 1433 $class = 'Savant2_Error_' . $this->_error; 1434 } else { 1435 $class = 'Savant2_Error'; 1436 } 1437 1438 // set up the error class file name 1439 $file = $class . '.php'; 1440 1441 // is it loaded? 1442 if (! class_exists($class)) { 1443 1444 // find the error class 1445 $result = $this->findFile('resource', $file); 1446 if (! $result) { 1447 // could not find the custom error class, revert to 1448 // Savant_Error base class. 1449 $class = 'Savant2_Error'; 1450 $result = dirname(__FILE__) . '/Savant2/Error.php'; 1451 } 1452 1453 // include the error class 1454 include_once $result; 1455 } 1456 1457 // instantiate and return the error class 1458 $err =& new $class($conf); 1459 return $err; 1460 } 1461 1462 1463 /** 1464 * 1465 * Tests if an object is of the Savant2_Error class. 1466 * 1467 * @access public 1468 * 1469 * @param object &$obj The object to be tested. 1470 * 1471 * @return boolean True if $obj is an error object of the type 1472 * Savant2_Error, or is a subclass that Savant2_Error. False if not. 1473 * 1474 */ 1475 1476 function isError(&$obj) 1477 { 1478 if (is_object($obj)) { 1479 if (is_a($obj, 'Savant2_Error') || 1480 is_subclass_of($obj, 'Savant2_Error')) { 1481 return true; 1482 } 1483 } 1484 1485 return false; 1486 } 1487 } 1488 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |