[ Index ]
 

Code source de eGroupWare 1.2.106-2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/phpgwapi/inc/savant2/ -> Savant2.php (source)

   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  ?>


Généré le : Sun Feb 25 17:20:01 2007 par Balluche grâce à PHPXref 0.7