web/lib/Zend/View/Abstract.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_View
       
    17  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    19  * @version    $Id: Abstract.php 22446 2010-06-18 12:11:43Z matthew $
       
    20  */
       
    21 
       
    22 /** @see Zend_Loader */
       
    23 require_once 'Zend/Loader.php';
       
    24 
       
    25 /** @see Zend_Loader_PluginLoader */
       
    26 require_once 'Zend/Loader/PluginLoader.php';
       
    27 
       
    28 /** @see Zend_View_Interface */
       
    29 require_once 'Zend/View/Interface.php';
       
    30 
       
    31 /**
       
    32  * Abstract class for Zend_View to help enforce private constructs.
       
    33  *
       
    34  * @category   Zend
       
    35  * @package    Zend_View
       
    36  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    37  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    38  */
       
    39 abstract class Zend_View_Abstract implements Zend_View_Interface
       
    40 {
       
    41     /**
       
    42      * Path stack for script, helper, and filter directories.
       
    43      *
       
    44      * @var array
       
    45      */
       
    46     private $_path = array(
       
    47         'script' => array(),
       
    48         'helper' => array(),
       
    49         'filter' => array(),
       
    50     );
       
    51 
       
    52     /**
       
    53      * Script file name to execute
       
    54      *
       
    55      * @var string
       
    56      */
       
    57     private $_file = null;
       
    58 
       
    59     /**
       
    60      * Instances of helper objects.
       
    61      *
       
    62      * @var array
       
    63      */
       
    64     private $_helper = array();
       
    65 
       
    66     /**
       
    67      * Map of helper => class pairs to help in determining helper class from
       
    68      * name
       
    69      * @var array
       
    70      */
       
    71     private $_helperLoaded = array();
       
    72 
       
    73     /**
       
    74      * Map of helper => classfile pairs to aid in determining helper classfile
       
    75      * @var array
       
    76      */
       
    77     private $_helperLoadedDir = array();
       
    78 
       
    79     /**
       
    80      * Stack of Zend_View_Filter names to apply as filters.
       
    81      * @var array
       
    82      */
       
    83     private $_filter = array();
       
    84 
       
    85     /**
       
    86      * Stack of Zend_View_Filter objects that have been loaded
       
    87      * @var array
       
    88      */
       
    89     private $_filterClass = array();
       
    90 
       
    91     /**
       
    92      * Map of filter => class pairs to help in determining filter class from
       
    93      * name
       
    94      * @var array
       
    95      */
       
    96     private $_filterLoaded = array();
       
    97 
       
    98     /**
       
    99      * Map of filter => classfile pairs to aid in determining filter classfile
       
   100      * @var array
       
   101      */
       
   102     private $_filterLoadedDir = array();
       
   103 
       
   104     /**
       
   105      * Callback for escaping.
       
   106      *
       
   107      * @var string
       
   108      */
       
   109     private $_escape = 'htmlspecialchars';
       
   110 
       
   111     /**
       
   112      * Encoding to use in escaping mechanisms; defaults to utf-8
       
   113      * @var string
       
   114      */
       
   115     private $_encoding = 'UTF-8';
       
   116 
       
   117     /**
       
   118      * Flag indicating whether or not LFI protection for rendering view scripts is enabled
       
   119      * @var bool
       
   120      */
       
   121     private $_lfiProtectionOn = true;
       
   122 
       
   123     /**
       
   124      * Plugin loaders
       
   125      * @var array
       
   126      */
       
   127     private $_loaders = array();
       
   128 
       
   129     /**
       
   130      * Plugin types
       
   131      * @var array
       
   132      */
       
   133     private $_loaderTypes = array('filter', 'helper');
       
   134 
       
   135     /**
       
   136      * Strict variables flag; when on, undefined variables accessed in the view
       
   137      * scripts will trigger notices
       
   138      * @var boolean
       
   139      */
       
   140     private $_strictVars = false;
       
   141 
       
   142     /**
       
   143      * Constructor.
       
   144      *
       
   145      * @param array $config Configuration key-value pairs.
       
   146      */
       
   147     public function __construct($config = array())
       
   148     {
       
   149         // set inital paths and properties
       
   150         $this->setScriptPath(null);
       
   151 
       
   152         // $this->setHelperPath(null);
       
   153         $this->setFilterPath(null);
       
   154 
       
   155         // user-defined escaping callback
       
   156         if (array_key_exists('escape', $config)) {
       
   157             $this->setEscape($config['escape']);
       
   158         }
       
   159 
       
   160         // encoding
       
   161         if (array_key_exists('encoding', $config)) {
       
   162             $this->setEncoding($config['encoding']);
       
   163         }
       
   164 
       
   165         // base path
       
   166         if (array_key_exists('basePath', $config)) {
       
   167             $prefix = 'Zend_View';
       
   168             if (array_key_exists('basePathPrefix', $config)) {
       
   169                 $prefix = $config['basePathPrefix'];
       
   170             }
       
   171             $this->setBasePath($config['basePath'], $prefix);
       
   172         }
       
   173 
       
   174         // user-defined view script path
       
   175         if (array_key_exists('scriptPath', $config)) {
       
   176             $this->addScriptPath($config['scriptPath']);
       
   177         }
       
   178 
       
   179         // user-defined helper path
       
   180         if (array_key_exists('helperPath', $config)) {
       
   181             if (is_array($config['helperPath'])) {
       
   182                 foreach ($config['helperPath'] as $prefix => $path) {
       
   183                     $this->addHelperPath($path, $prefix);
       
   184                 }
       
   185             } else {
       
   186                 $prefix = 'Zend_View_Helper';
       
   187                 if (array_key_exists('helperPathPrefix', $config)) {
       
   188                     $prefix = $config['helperPathPrefix'];
       
   189                 }
       
   190                 $this->addHelperPath($config['helperPath'], $prefix);
       
   191             }
       
   192         }
       
   193 
       
   194         // user-defined filter path
       
   195         if (array_key_exists('filterPath', $config)) {
       
   196             if (is_array($config['filterPath'])) {
       
   197                 foreach ($config['filterPath'] as $prefix => $path) {
       
   198                     $this->addFilterPath($path, $prefix);
       
   199                 }
       
   200             } else {
       
   201                 $prefix = 'Zend_View_Filter';
       
   202                 if (array_key_exists('filterPathPrefix', $config)) {
       
   203                     $prefix = $config['filterPathPrefix'];
       
   204                 }
       
   205                 $this->addFilterPath($config['filterPath'], $prefix);
       
   206             }
       
   207         }
       
   208 
       
   209         // user-defined filters
       
   210         if (array_key_exists('filter', $config)) {
       
   211             $this->addFilter($config['filter']);
       
   212         }
       
   213 
       
   214         // strict vars
       
   215         if (array_key_exists('strictVars', $config)) {
       
   216             $this->strictVars($config['strictVars']);
       
   217         }
       
   218 
       
   219         // LFI protection flag
       
   220         if (array_key_exists('lfiProtectionOn', $config)) {
       
   221             $this->setLfiProtection($config['lfiProtectionOn']);
       
   222         }
       
   223 
       
   224         $this->init();
       
   225     }
       
   226 
       
   227     /**
       
   228      * Return the template engine object
       
   229      *
       
   230      * Returns the object instance, as it is its own template engine
       
   231      *
       
   232      * @return Zend_View_Abstract
       
   233      */
       
   234     public function getEngine()
       
   235     {
       
   236         return $this;
       
   237     }
       
   238 
       
   239     /**
       
   240      * Allow custom object initialization when extending Zend_View_Abstract or
       
   241      * Zend_View
       
   242      *
       
   243      * Triggered by {@link __construct() the constructor} as its final action.
       
   244      *
       
   245      * @return void
       
   246      */
       
   247     public function init()
       
   248     {
       
   249     }
       
   250 
       
   251     /**
       
   252      * Prevent E_NOTICE for nonexistent values
       
   253      *
       
   254      * If {@link strictVars()} is on, raises a notice.
       
   255      *
       
   256      * @param  string $key
       
   257      * @return null
       
   258      */
       
   259     public function __get($key)
       
   260     {
       
   261         if ($this->_strictVars) {
       
   262             trigger_error('Key "' . $key . '" does not exist', E_USER_NOTICE);
       
   263         }
       
   264 
       
   265         return null;
       
   266     }
       
   267 
       
   268     /**
       
   269      * Allows testing with empty() and isset() to work inside
       
   270      * templates.
       
   271      *
       
   272      * @param  string $key
       
   273      * @return boolean
       
   274      */
       
   275     public function __isset($key)
       
   276     {
       
   277         if ('_' != substr($key, 0, 1)) {
       
   278             return isset($this->$key);
       
   279         }
       
   280 
       
   281         return false;
       
   282     }
       
   283 
       
   284     /**
       
   285      * Directly assigns a variable to the view script.
       
   286      *
       
   287      * Checks first to ensure that the caller is not attempting to set a
       
   288      * protected or private member (by checking for a prefixed underscore); if
       
   289      * not, the public member is set; otherwise, an exception is raised.
       
   290      *
       
   291      * @param string $key The variable name.
       
   292      * @param mixed $val The variable value.
       
   293      * @return void
       
   294      * @throws Zend_View_Exception if an attempt to set a private or protected
       
   295      * member is detected
       
   296      */
       
   297     public function __set($key, $val)
       
   298     {
       
   299         if ('_' != substr($key, 0, 1)) {
       
   300             $this->$key = $val;
       
   301             return;
       
   302         }
       
   303 
       
   304         require_once 'Zend/View/Exception.php';
       
   305         $e = new Zend_View_Exception('Setting private or protected class members is not allowed');
       
   306         $e->setView($this);
       
   307         throw $e;
       
   308     }
       
   309 
       
   310     /**
       
   311      * Allows unset() on object properties to work
       
   312      *
       
   313      * @param string $key
       
   314      * @return void
       
   315      */
       
   316     public function __unset($key)
       
   317     {
       
   318         if ('_' != substr($key, 0, 1) && isset($this->$key)) {
       
   319             unset($this->$key);
       
   320         }
       
   321     }
       
   322 
       
   323     /**
       
   324      * Accesses a helper object from within a script.
       
   325      *
       
   326      * If the helper class has a 'view' property, sets it with the current view
       
   327      * object.
       
   328      *
       
   329      * @param string $name The helper name.
       
   330      * @param array $args The parameters for the helper.
       
   331      * @return string The result of the helper output.
       
   332      */
       
   333     public function __call($name, $args)
       
   334     {
       
   335         // is the helper already loaded?
       
   336         $helper = $this->getHelper($name);
       
   337 
       
   338         // call the helper method
       
   339         return call_user_func_array(
       
   340             array($helper, $name),
       
   341             $args
       
   342         );
       
   343     }
       
   344 
       
   345     /**
       
   346      * Given a base path, sets the script, helper, and filter paths relative to it
       
   347      *
       
   348      * Assumes a directory structure of:
       
   349      * <code>
       
   350      * basePath/
       
   351      *     scripts/
       
   352      *     helpers/
       
   353      *     filters/
       
   354      * </code>
       
   355      *
       
   356      * @param  string $path
       
   357      * @param  string $prefix Prefix to use for helper and filter paths
       
   358      * @return Zend_View_Abstract
       
   359      */
       
   360     public function setBasePath($path, $classPrefix = 'Zend_View')
       
   361     {
       
   362         $path        = rtrim($path, '/');
       
   363         $path        = rtrim($path, '\\');
       
   364         $path       .= DIRECTORY_SEPARATOR;
       
   365         $classPrefix = rtrim($classPrefix, '_') . '_';
       
   366         $this->setScriptPath($path . 'scripts');
       
   367         $this->setHelperPath($path . 'helpers', $classPrefix . 'Helper');
       
   368         $this->setFilterPath($path . 'filters', $classPrefix . 'Filter');
       
   369         return $this;
       
   370     }
       
   371 
       
   372     /**
       
   373      * Given a base path, add script, helper, and filter paths relative to it
       
   374      *
       
   375      * Assumes a directory structure of:
       
   376      * <code>
       
   377      * basePath/
       
   378      *     scripts/
       
   379      *     helpers/
       
   380      *     filters/
       
   381      * </code>
       
   382      *
       
   383      * @param  string $path
       
   384      * @param  string $prefix Prefix to use for helper and filter paths
       
   385      * @return Zend_View_Abstract
       
   386      */
       
   387     public function addBasePath($path, $classPrefix = 'Zend_View')
       
   388     {
       
   389         $path        = rtrim($path, '/');
       
   390         $path        = rtrim($path, '\\');
       
   391         $path       .= DIRECTORY_SEPARATOR;
       
   392         $classPrefix = rtrim($classPrefix, '_') . '_';
       
   393         $this->addScriptPath($path . 'scripts');
       
   394         $this->addHelperPath($path . 'helpers', $classPrefix . 'Helper');
       
   395         $this->addFilterPath($path . 'filters', $classPrefix . 'Filter');
       
   396         return $this;
       
   397     }
       
   398 
       
   399     /**
       
   400      * Adds to the stack of view script paths in LIFO order.
       
   401      *
       
   402      * @param string|array The directory (-ies) to add.
       
   403      * @return Zend_View_Abstract
       
   404      */
       
   405     public function addScriptPath($path)
       
   406     {
       
   407         $this->_addPath('script', $path);
       
   408         return $this;
       
   409     }
       
   410 
       
   411     /**
       
   412      * Resets the stack of view script paths.
       
   413      *
       
   414      * To clear all paths, use Zend_View::setScriptPath(null).
       
   415      *
       
   416      * @param string|array The directory (-ies) to set as the path.
       
   417      * @return Zend_View_Abstract
       
   418      */
       
   419     public function setScriptPath($path)
       
   420     {
       
   421         $this->_path['script'] = array();
       
   422         $this->_addPath('script', $path);
       
   423         return $this;
       
   424     }
       
   425 
       
   426     /**
       
   427      * Return full path to a view script specified by $name
       
   428      *
       
   429      * @param  string $name
       
   430      * @return false|string False if script not found
       
   431      * @throws Zend_View_Exception if no script directory set
       
   432      */
       
   433     public function getScriptPath($name)
       
   434     {
       
   435         try {
       
   436             $path = $this->_script($name);
       
   437             return $path;
       
   438         } catch (Zend_View_Exception $e) {
       
   439             if (strstr($e->getMessage(), 'no view script directory set')) {
       
   440                 throw $e;
       
   441             }
       
   442 
       
   443             return false;
       
   444         }
       
   445     }
       
   446 
       
   447     /**
       
   448      * Returns an array of all currently set script paths
       
   449      *
       
   450      * @return array
       
   451      */
       
   452     public function getScriptPaths()
       
   453     {
       
   454         return $this->_getPaths('script');
       
   455     }
       
   456 
       
   457     /**
       
   458      * Set plugin loader for a particular plugin type
       
   459      *
       
   460      * @param  Zend_Loader_PluginLoader $loader
       
   461      * @param  string $type
       
   462      * @return Zend_View_Abstract
       
   463      */
       
   464     public function setPluginLoader(Zend_Loader_PluginLoader $loader, $type)
       
   465     {
       
   466         $type = strtolower($type);
       
   467         if (!in_array($type, $this->_loaderTypes)) {
       
   468             require_once 'Zend/View/Exception.php';
       
   469             $e = new Zend_View_Exception(sprintf('Invalid plugin loader type "%s"', $type));
       
   470             $e->setView($this);
       
   471             throw $e;
       
   472         }
       
   473 
       
   474         $this->_loaders[$type] = $loader;
       
   475         return $this;
       
   476     }
       
   477 
       
   478     /**
       
   479      * Retrieve plugin loader for a specific plugin type
       
   480      *
       
   481      * @param  string $type
       
   482      * @return Zend_Loader_PluginLoader
       
   483      */
       
   484     public function getPluginLoader($type)
       
   485     {
       
   486         $type = strtolower($type);
       
   487         if (!in_array($type, $this->_loaderTypes)) {
       
   488             require_once 'Zend/View/Exception.php';
       
   489             $e = new Zend_View_Exception(sprintf('Invalid plugin loader type "%s"; cannot retrieve', $type));
       
   490             $e->setView($this);
       
   491             throw $e;
       
   492         }
       
   493 
       
   494         if (!array_key_exists($type, $this->_loaders)) {
       
   495             $prefix     = 'Zend_View_';
       
   496             $pathPrefix = 'Zend/View/';
       
   497 
       
   498             $pType = ucfirst($type);
       
   499             switch ($type) {
       
   500                 case 'filter':
       
   501                 case 'helper':
       
   502                 default:
       
   503                     $prefix     .= $pType;
       
   504                     $pathPrefix .= $pType;
       
   505                     $loader = new Zend_Loader_PluginLoader(array(
       
   506                         $prefix => $pathPrefix
       
   507                     ));
       
   508                     $this->_loaders[$type] = $loader;
       
   509                     break;
       
   510             }
       
   511         }
       
   512         return $this->_loaders[$type];
       
   513     }
       
   514 
       
   515     /**
       
   516      * Adds to the stack of helper paths in LIFO order.
       
   517      *
       
   518      * @param string|array The directory (-ies) to add.
       
   519      * @param string $classPrefix Class prefix to use with classes in this
       
   520      * directory; defaults to Zend_View_Helper
       
   521      * @return Zend_View_Abstract
       
   522      */
       
   523     public function addHelperPath($path, $classPrefix = 'Zend_View_Helper_')
       
   524     {
       
   525         return $this->_addPluginPath('helper', $classPrefix, (array) $path);
       
   526     }
       
   527 
       
   528     /**
       
   529      * Resets the stack of helper paths.
       
   530      *
       
   531      * To clear all paths, use Zend_View::setHelperPath(null).
       
   532      *
       
   533      * @param string|array $path The directory (-ies) to set as the path.
       
   534      * @param string $classPrefix The class prefix to apply to all elements in
       
   535      * $path; defaults to Zend_View_Helper
       
   536      * @return Zend_View_Abstract
       
   537      */
       
   538     public function setHelperPath($path, $classPrefix = 'Zend_View_Helper_')
       
   539     {
       
   540         unset($this->_loaders['helper']);
       
   541         return $this->addHelperPath($path, $classPrefix);
       
   542     }
       
   543 
       
   544     /**
       
   545      * Get full path to a helper class file specified by $name
       
   546      *
       
   547      * @param  string $name
       
   548      * @return string|false False on failure, path on success
       
   549      */
       
   550     public function getHelperPath($name)
       
   551     {
       
   552         return $this->_getPluginPath('helper', $name);
       
   553     }
       
   554 
       
   555     /**
       
   556      * Returns an array of all currently set helper paths
       
   557      *
       
   558      * @return array
       
   559      */
       
   560     public function getHelperPaths()
       
   561     {
       
   562         return $this->getPluginLoader('helper')->getPaths();
       
   563     }
       
   564 
       
   565     /**
       
   566      * Registers a helper object, bypassing plugin loader
       
   567      *
       
   568      * @param  Zend_View_Helper_Abstract|object $helper
       
   569      * @param  string $name
       
   570      * @return Zend_View_Abstract
       
   571      * @throws Zend_View_Exception
       
   572      */
       
   573     public function registerHelper($helper, $name)
       
   574     {
       
   575         if (!is_object($helper)) {
       
   576             require_once 'Zend/View/Exception.php';
       
   577             $e = new Zend_View_Exception('View helper must be an object');
       
   578             $e->setView($this);
       
   579             throw $e;
       
   580         }
       
   581 
       
   582         if (!$helper instanceof Zend_View_Interface) {
       
   583             if (!method_exists($helper, $name)) {
       
   584                 require_once 'Zend/View/Exception.php';
       
   585                 $e =  new Zend_View_Exception(
       
   586                     'View helper must implement Zend_View_Interface or have a method matching the name provided'
       
   587                 );
       
   588                 $e->setView($this);
       
   589                 throw $e;
       
   590             }
       
   591         }
       
   592 
       
   593         if (method_exists($helper, 'setView')) {
       
   594             $helper->setView($this);
       
   595         }
       
   596 
       
   597         $name = ucfirst($name);
       
   598         $this->_helper[$name] = $helper;
       
   599         return $this;
       
   600     }
       
   601 
       
   602     /**
       
   603      * Get a helper by name
       
   604      *
       
   605      * @param  string $name
       
   606      * @return object
       
   607      */
       
   608     public function getHelper($name)
       
   609     {
       
   610         return $this->_getPlugin('helper', $name);
       
   611     }
       
   612 
       
   613     /**
       
   614      * Get array of all active helpers
       
   615      *
       
   616      * Only returns those that have already been instantiated.
       
   617      *
       
   618      * @return array
       
   619      */
       
   620     public function getHelpers()
       
   621     {
       
   622         return $this->_helper;
       
   623     }
       
   624 
       
   625     /**
       
   626      * Adds to the stack of filter paths in LIFO order.
       
   627      *
       
   628      * @param string|array The directory (-ies) to add.
       
   629      * @param string $classPrefix Class prefix to use with classes in this
       
   630      * directory; defaults to Zend_View_Filter
       
   631      * @return Zend_View_Abstract
       
   632      */
       
   633     public function addFilterPath($path, $classPrefix = 'Zend_View_Filter_')
       
   634     {
       
   635         return $this->_addPluginPath('filter', $classPrefix, (array) $path);
       
   636     }
       
   637 
       
   638     /**
       
   639      * Resets the stack of filter paths.
       
   640      *
       
   641      * To clear all paths, use Zend_View::setFilterPath(null).
       
   642      *
       
   643      * @param string|array The directory (-ies) to set as the path.
       
   644      * @param string $classPrefix The class prefix to apply to all elements in
       
   645      * $path; defaults to Zend_View_Filter
       
   646      * @return Zend_View_Abstract
       
   647      */
       
   648     public function setFilterPath($path, $classPrefix = 'Zend_View_Filter_')
       
   649     {
       
   650         unset($this->_loaders['filter']);
       
   651         return $this->addFilterPath($path, $classPrefix);
       
   652     }
       
   653 
       
   654     /**
       
   655      * Get full path to a filter class file specified by $name
       
   656      *
       
   657      * @param  string $name
       
   658      * @return string|false False on failure, path on success
       
   659      */
       
   660     public function getFilterPath($name)
       
   661     {
       
   662         return $this->_getPluginPath('filter', $name);
       
   663     }
       
   664 
       
   665     /**
       
   666      * Get a filter object by name
       
   667      *
       
   668      * @param  string $name
       
   669      * @return object
       
   670      */
       
   671     public function getFilter($name)
       
   672     {
       
   673         return $this->_getPlugin('filter', $name);
       
   674     }
       
   675 
       
   676     /**
       
   677      * Return array of all currently active filters
       
   678      *
       
   679      * Only returns those that have already been instantiated.
       
   680      *
       
   681      * @return array
       
   682      */
       
   683     public function getFilters()
       
   684     {
       
   685         return $this->_filter;
       
   686     }
       
   687 
       
   688     /**
       
   689      * Returns an array of all currently set filter paths
       
   690      *
       
   691      * @return array
       
   692      */
       
   693     public function getFilterPaths()
       
   694     {
       
   695         return $this->getPluginLoader('filter')->getPaths();
       
   696     }
       
   697 
       
   698     /**
       
   699      * Return associative array of path types => paths
       
   700      *
       
   701      * @return array
       
   702      */
       
   703     public function getAllPaths()
       
   704     {
       
   705         $paths = $this->_path;
       
   706         $paths['helper'] = $this->getHelperPaths();
       
   707         $paths['filter'] = $this->getFilterPaths();
       
   708         return $paths;
       
   709     }
       
   710 
       
   711     /**
       
   712      * Add one or more filters to the stack in FIFO order.
       
   713      *
       
   714      * @param string|array One or more filters to add.
       
   715      * @return Zend_View_Abstract
       
   716      */
       
   717     public function addFilter($name)
       
   718     {
       
   719         foreach ((array) $name as $val) {
       
   720             $this->_filter[] = $val;
       
   721         }
       
   722         return $this;
       
   723     }
       
   724 
       
   725     /**
       
   726      * Resets the filter stack.
       
   727      *
       
   728      * To clear all filters, use Zend_View::setFilter(null).
       
   729      *
       
   730      * @param string|array One or more filters to set.
       
   731      * @return Zend_View_Abstract
       
   732      */
       
   733     public function setFilter($name)
       
   734     {
       
   735         $this->_filter = array();
       
   736         $this->addFilter($name);
       
   737         return $this;
       
   738     }
       
   739 
       
   740     /**
       
   741      * Sets the _escape() callback.
       
   742      *
       
   743      * @param mixed $spec The callback for _escape() to use.
       
   744      * @return Zend_View_Abstract
       
   745      */
       
   746     public function setEscape($spec)
       
   747     {
       
   748         $this->_escape = $spec;
       
   749         return $this;
       
   750     }
       
   751 
       
   752     /**
       
   753      * Set LFI protection flag
       
   754      *
       
   755      * @param  bool $flag
       
   756      * @return Zend_View_Abstract
       
   757      */
       
   758     public function setLfiProtection($flag)
       
   759     {
       
   760         $this->_lfiProtectionOn = (bool) $flag;
       
   761         return $this;
       
   762     }
       
   763 
       
   764     /**
       
   765      * Return status of LFI protection flag
       
   766      *
       
   767      * @return bool
       
   768      */
       
   769     public function isLfiProtectionOn()
       
   770     {
       
   771         return $this->_lfiProtectionOn;
       
   772     }
       
   773 
       
   774     /**
       
   775      * Assigns variables to the view script via differing strategies.
       
   776      *
       
   777      * Zend_View::assign('name', $value) assigns a variable called 'name'
       
   778      * with the corresponding $value.
       
   779      *
       
   780      * Zend_View::assign($array) assigns the array keys as variable
       
   781      * names (with the corresponding array values).
       
   782      *
       
   783      * @see    __set()
       
   784      * @param  string|array The assignment strategy to use.
       
   785      * @param  mixed (Optional) If assigning a named variable, use this
       
   786      * as the value.
       
   787      * @return Zend_View_Abstract Fluent interface
       
   788      * @throws Zend_View_Exception if $spec is neither a string nor an array,
       
   789      * or if an attempt to set a private or protected member is detected
       
   790      */
       
   791     public function assign($spec, $value = null)
       
   792     {
       
   793         // which strategy to use?
       
   794         if (is_string($spec)) {
       
   795             // assign by name and value
       
   796             if ('_' == substr($spec, 0, 1)) {
       
   797                 require_once 'Zend/View/Exception.php';
       
   798                 $e = new Zend_View_Exception('Setting private or protected class members is not allowed');
       
   799                 $e->setView($this);
       
   800                 throw $e;
       
   801             }
       
   802             $this->$spec = $value;
       
   803         } elseif (is_array($spec)) {
       
   804             // assign from associative array
       
   805             $error = false;
       
   806             foreach ($spec as $key => $val) {
       
   807                 if ('_' == substr($key, 0, 1)) {
       
   808                     $error = true;
       
   809                     break;
       
   810                 }
       
   811                 $this->$key = $val;
       
   812             }
       
   813             if ($error) {
       
   814                 require_once 'Zend/View/Exception.php';
       
   815                 $e = new Zend_View_Exception('Setting private or protected class members is not allowed');
       
   816                 $e->setView($this);
       
   817                 throw $e;
       
   818             }
       
   819         } else {
       
   820             require_once 'Zend/View/Exception.php';
       
   821             $e = new Zend_View_Exception('assign() expects a string or array, received ' . gettype($spec));
       
   822             $e->setView($this);
       
   823             throw $e;
       
   824         }
       
   825 
       
   826         return $this;
       
   827     }
       
   828 
       
   829     /**
       
   830      * Return list of all assigned variables
       
   831      *
       
   832      * Returns all public properties of the object. Reflection is not used
       
   833      * here as testing reflection properties for visibility is buggy.
       
   834      *
       
   835      * @return array
       
   836      */
       
   837     public function getVars()
       
   838     {
       
   839         $vars   = get_object_vars($this);
       
   840         foreach ($vars as $key => $value) {
       
   841             if ('_' == substr($key, 0, 1)) {
       
   842                 unset($vars[$key]);
       
   843             }
       
   844         }
       
   845 
       
   846         return $vars;
       
   847     }
       
   848 
       
   849     /**
       
   850      * Clear all assigned variables
       
   851      *
       
   852      * Clears all variables assigned to Zend_View either via {@link assign()} or
       
   853      * property overloading ({@link __set()}).
       
   854      *
       
   855      * @return void
       
   856      */
       
   857     public function clearVars()
       
   858     {
       
   859         $vars   = get_object_vars($this);
       
   860         foreach ($vars as $key => $value) {
       
   861             if ('_' != substr($key, 0, 1)) {
       
   862                 unset($this->$key);
       
   863             }
       
   864         }
       
   865     }
       
   866 
       
   867     /**
       
   868      * Processes a view script and returns the output.
       
   869      *
       
   870      * @param string $name The script name to process.
       
   871      * @return string The script output.
       
   872      */
       
   873     public function render($name)
       
   874     {
       
   875         // find the script file name using the parent private method
       
   876         $this->_file = $this->_script($name);
       
   877         unset($name); // remove $name from local scope
       
   878 
       
   879         ob_start();
       
   880         $this->_run($this->_file);
       
   881 
       
   882         return $this->_filter(ob_get_clean()); // filter output
       
   883     }
       
   884 
       
   885     /**
       
   886      * Escapes a value for output in a view script.
       
   887      *
       
   888      * If escaping mechanism is one of htmlspecialchars or htmlentities, uses
       
   889      * {@link $_encoding} setting.
       
   890      *
       
   891      * @param mixed $var The output to escape.
       
   892      * @return mixed The escaped value.
       
   893      */
       
   894     public function escape($var)
       
   895     {
       
   896         if (in_array($this->_escape, array('htmlspecialchars', 'htmlentities'))) {
       
   897             return call_user_func($this->_escape, $var, ENT_COMPAT, $this->_encoding);
       
   898         }
       
   899 
       
   900         if (1 == func_num_args()) {
       
   901             return call_user_func($this->_escape, $var);
       
   902         }
       
   903         $args = func_get_args();
       
   904         return call_user_func_array($this->_escape, $args);
       
   905     }
       
   906 
       
   907     /**
       
   908      * Set encoding to use with htmlentities() and htmlspecialchars()
       
   909      *
       
   910      * @param string $encoding
       
   911      * @return Zend_View_Abstract
       
   912      */
       
   913     public function setEncoding($encoding)
       
   914     {
       
   915         $this->_encoding = $encoding;
       
   916         return $this;
       
   917     }
       
   918 
       
   919     /**
       
   920      * Return current escape encoding
       
   921      *
       
   922      * @return string
       
   923      */
       
   924     public function getEncoding()
       
   925     {
       
   926         return $this->_encoding;
       
   927     }
       
   928 
       
   929     /**
       
   930      * Enable or disable strict vars
       
   931      *
       
   932      * If strict variables are enabled, {@link __get()} will raise a notice
       
   933      * when a variable is not defined.
       
   934      *
       
   935      * Use in conjunction with {@link Zend_View_Helper_DeclareVars the declareVars() helper}
       
   936      * to enforce strict variable handling in your view scripts.
       
   937      *
       
   938      * @param  boolean $flag
       
   939      * @return Zend_View_Abstract
       
   940      */
       
   941     public function strictVars($flag = true)
       
   942     {
       
   943         $this->_strictVars = ($flag) ? true : false;
       
   944 
       
   945         return $this;
       
   946     }
       
   947 
       
   948     /**
       
   949      * Finds a view script from the available directories.
       
   950      *
       
   951      * @param $name string The base name of the script.
       
   952      * @return void
       
   953      */
       
   954     protected function _script($name)
       
   955     {
       
   956         if ($this->isLfiProtectionOn() && preg_match('#\.\.[\\\/]#', $name)) {
       
   957             require_once 'Zend/View/Exception.php';
       
   958             $e = new Zend_View_Exception('Requested scripts may not include parent directory traversal ("../", "..\\" notation)');
       
   959             $e->setView($this);
       
   960             throw $e;
       
   961         }
       
   962 
       
   963         if (0 == count($this->_path['script'])) {
       
   964             require_once 'Zend/View/Exception.php';
       
   965             $e = new Zend_View_Exception('no view script directory set; unable to determine location for view script');
       
   966             $e->setView($this);
       
   967             throw $e;
       
   968         }
       
   969 
       
   970         foreach ($this->_path['script'] as $dir) {
       
   971             if (is_readable($dir . $name)) {
       
   972                 return $dir . $name;
       
   973             }
       
   974         }
       
   975 
       
   976         require_once 'Zend/View/Exception.php';
       
   977         $message = "script '$name' not found in path ("
       
   978                  . implode(PATH_SEPARATOR, $this->_path['script'])
       
   979                  . ")";
       
   980         $e = new Zend_View_Exception($message);
       
   981         $e->setView($this);
       
   982         throw $e;
       
   983     }
       
   984 
       
   985     /**
       
   986      * Applies the filter callback to a buffer.
       
   987      *
       
   988      * @param string $buffer The buffer contents.
       
   989      * @return string The filtered buffer.
       
   990      */
       
   991     private function _filter($buffer)
       
   992     {
       
   993         // loop through each filter class
       
   994         foreach ($this->_filter as $name) {
       
   995             // load and apply the filter class
       
   996             $filter = $this->getFilter($name);
       
   997             $buffer = call_user_func(array($filter, 'filter'), $buffer);
       
   998         }
       
   999 
       
  1000         // done!
       
  1001         return $buffer;
       
  1002     }
       
  1003 
       
  1004     /**
       
  1005      * Adds paths to the path stack in LIFO order.
       
  1006      *
       
  1007      * Zend_View::_addPath($type, 'dirname') adds one directory
       
  1008      * to the path stack.
       
  1009      *
       
  1010      * Zend_View::_addPath($type, $array) adds one directory for
       
  1011      * each array element value.
       
  1012      *
       
  1013      * In the case of filter and helper paths, $prefix should be used to
       
  1014      * specify what class prefix to use with the given path.
       
  1015      *
       
  1016      * @param string $type The path type ('script', 'helper', or 'filter').
       
  1017      * @param string|array $path The path specification.
       
  1018      * @param string $prefix Class prefix to use with path (helpers and filters
       
  1019      * only)
       
  1020      * @return void
       
  1021      */
       
  1022     private function _addPath($type, $path, $prefix = null)
       
  1023     {
       
  1024         foreach ((array) $path as $dir) {
       
  1025             // attempt to strip any possible separator and
       
  1026             // append the system directory separator
       
  1027             $dir  = rtrim($dir, '/');
       
  1028             $dir  = rtrim($dir, '\\');
       
  1029             $dir .= '/';
       
  1030 
       
  1031             switch ($type) {
       
  1032                 case 'script':
       
  1033                     // add to the top of the stack.
       
  1034                     array_unshift($this->_path[$type], $dir);
       
  1035                     break;
       
  1036                 case 'filter':
       
  1037                 case 'helper':
       
  1038                 default:
       
  1039                     // add as array with prefix and dir keys
       
  1040                     array_unshift($this->_path[$type], array('prefix' => $prefix, 'dir' => $dir));
       
  1041                     break;
       
  1042             }
       
  1043         }
       
  1044     }
       
  1045 
       
  1046     /**
       
  1047      * Resets the path stack for helpers and filters.
       
  1048      *
       
  1049      * @param string $type The path type ('helper' or 'filter').
       
  1050      * @param string|array $path The directory (-ies) to set as the path.
       
  1051      * @param string $classPrefix Class prefix to apply to elements of $path
       
  1052      */
       
  1053     private function _setPath($type, $path, $classPrefix = null)
       
  1054     {
       
  1055         $dir = DIRECTORY_SEPARATOR . ucfirst($type) . DIRECTORY_SEPARATOR;
       
  1056 
       
  1057         switch ($type) {
       
  1058             case 'script':
       
  1059                 $this->_path[$type] = array(dirname(__FILE__) . $dir);
       
  1060                 $this->_addPath($type, $path);
       
  1061                 break;
       
  1062             case 'filter':
       
  1063             case 'helper':
       
  1064             default:
       
  1065                 $this->_path[$type] = array(array(
       
  1066                     'prefix' => 'Zend_View_' . ucfirst($type) . '_',
       
  1067                     'dir'    => dirname(__FILE__) . $dir
       
  1068                 ));
       
  1069                 $this->_addPath($type, $path, $classPrefix);
       
  1070                 break;
       
  1071         }
       
  1072     }
       
  1073 
       
  1074     /**
       
  1075      * Return all paths for a given path type
       
  1076      *
       
  1077      * @param string $type The path type  ('helper', 'filter', 'script')
       
  1078      * @return array
       
  1079      */
       
  1080     private function _getPaths($type)
       
  1081     {
       
  1082         return $this->_path[$type];
       
  1083     }
       
  1084 
       
  1085     /**
       
  1086      * Register helper class as loaded
       
  1087      *
       
  1088      * @param  string $name
       
  1089      * @param  string $class
       
  1090      * @param  string $file path to class file
       
  1091      * @return void
       
  1092      */
       
  1093     private function _setHelperClass($name, $class, $file)
       
  1094     {
       
  1095         $this->_helperLoadedDir[$name] = $file;
       
  1096         $this->_helperLoaded[$name]    = $class;
       
  1097     }
       
  1098 
       
  1099     /**
       
  1100      * Register filter class as loaded
       
  1101      *
       
  1102      * @param  string $name
       
  1103      * @param  string $class
       
  1104      * @param  string $file path to class file
       
  1105      * @return void
       
  1106      */
       
  1107     private function _setFilterClass($name, $class, $file)
       
  1108     {
       
  1109         $this->_filterLoadedDir[$name] = $file;
       
  1110         $this->_filterLoaded[$name]    = $class;
       
  1111     }
       
  1112 
       
  1113     /**
       
  1114      * Add a prefixPath for a plugin type
       
  1115      *
       
  1116      * @param  string $type
       
  1117      * @param  string $classPrefix
       
  1118      * @param  array $paths
       
  1119      * @return Zend_View_Abstract
       
  1120      */
       
  1121     private function _addPluginPath($type, $classPrefix, array $paths)
       
  1122     {
       
  1123         $loader = $this->getPluginLoader($type);
       
  1124         foreach ($paths as $path) {
       
  1125             $loader->addPrefixPath($classPrefix, $path);
       
  1126         }
       
  1127         return $this;
       
  1128     }
       
  1129 
       
  1130     /**
       
  1131      * Get a path to a given plugin class of a given type
       
  1132      *
       
  1133      * @param  string $type
       
  1134      * @param  string $name
       
  1135      * @return string|false
       
  1136      */
       
  1137     private function _getPluginPath($type, $name)
       
  1138     {
       
  1139         $loader = $this->getPluginLoader($type);
       
  1140         if ($loader->isLoaded($name)) {
       
  1141             return $loader->getClassPath($name);
       
  1142         }
       
  1143 
       
  1144         try {
       
  1145             $loader->load($name);
       
  1146             return $loader->getClassPath($name);
       
  1147         } catch (Zend_Loader_Exception $e) {
       
  1148             return false;
       
  1149         }
       
  1150     }
       
  1151 
       
  1152     /**
       
  1153      * Retrieve a plugin object
       
  1154      *
       
  1155      * @param  string $type
       
  1156      * @param  string $name
       
  1157      * @return object
       
  1158      */
       
  1159     private function _getPlugin($type, $name)
       
  1160     {
       
  1161         $name = ucfirst($name);
       
  1162         switch ($type) {
       
  1163             case 'filter':
       
  1164                 $storeVar = '_filterClass';
       
  1165                 $store    = $this->_filterClass;
       
  1166                 break;
       
  1167             case 'helper':
       
  1168                 $storeVar = '_helper';
       
  1169                 $store    = $this->_helper;
       
  1170                 break;
       
  1171         }
       
  1172 
       
  1173         if (!isset($store[$name])) {
       
  1174             $class = $this->getPluginLoader($type)->load($name);
       
  1175             $store[$name] = new $class();
       
  1176             if (method_exists($store[$name], 'setView')) {
       
  1177                 $store[$name]->setView($this);
       
  1178             }
       
  1179         }
       
  1180 
       
  1181         $this->$storeVar = $store;
       
  1182         return $store[$name];
       
  1183     }
       
  1184 
       
  1185     /**
       
  1186      * Use to include the view script in a scope that only allows public
       
  1187      * members.
       
  1188      *
       
  1189      * @return mixed
       
  1190      */
       
  1191     abstract protected function _run();
       
  1192 }