File indexing completed on 2024-12-22 05:37:14

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_View
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  * @version    $Id$
0020  */
0021 
0022 /** @see Zend_Loader */
0023 // require_once 'Zend/Loader.php';
0024 
0025 /** @see Zend_Loader_PluginLoader */
0026 // require_once 'Zend/Loader/PluginLoader.php';
0027 
0028 /** @see Zend_View_Interface */
0029 // require_once 'Zend/View/Interface.php';
0030 
0031 /**
0032  * Abstract class for Zend_View to help enforce private constructs.
0033  *
0034  * @category   Zend
0035  * @package    Zend_View
0036  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0037  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0038  */
0039 abstract class Zend_View_Abstract implements Zend_View_Interface
0040 {
0041     /**
0042      * Path stack for script, helper, and filter directories.
0043      *
0044      * @var array
0045      */
0046     private $_path = array(
0047         'script' => array(),
0048         'helper' => array(),
0049         'filter' => array(),
0050     );
0051 
0052     /**
0053      * Script file name to execute
0054      *
0055      * @var string
0056      */
0057     private $_file = null;
0058 
0059     /**
0060      * Instances of helper objects.
0061      *
0062      * @var array
0063      */
0064     private $_helper = array();
0065 
0066     /**
0067      * Map of helper => class pairs to help in determining helper class from
0068      * name
0069      * @var array
0070      */
0071     private $_helperLoaded = array();
0072 
0073     /**
0074      * Map of helper => classfile pairs to aid in determining helper classfile
0075      * @var array
0076      */
0077     private $_helperLoadedDir = array();
0078 
0079     /**
0080      * Stack of Zend_View_Filter names to apply as filters.
0081      * @var array
0082      */
0083     private $_filter = array();
0084 
0085     /**
0086      * Stack of Zend_View_Filter objects that have been loaded
0087      * @var array
0088      */
0089     private $_filterClass = array();
0090 
0091     /**
0092      * Map of filter => class pairs to help in determining filter class from
0093      * name
0094      * @var array
0095      */
0096     private $_filterLoaded = array();
0097 
0098     /**
0099      * Map of filter => classfile pairs to aid in determining filter classfile
0100      * @var array
0101      */
0102     private $_filterLoadedDir = array();
0103 
0104     /**
0105      * Callback for escaping.
0106      *
0107      * @var string
0108      */
0109     private $_escape = 'htmlspecialchars';
0110 
0111     /**
0112      * Encoding to use in escaping mechanisms; defaults to utf-8
0113      * @var string
0114      */
0115     private $_encoding = 'UTF-8';
0116 
0117     /**
0118      * Flag indicating whether or not LFI protection for rendering view scripts is enabled
0119      * @var bool
0120      */
0121     private $_lfiProtectionOn = true;
0122 
0123     /**
0124      * Plugin loaders
0125      * @var array
0126      */
0127     private $_loaders = array();
0128 
0129     /**
0130      * Plugin types
0131      * @var array
0132      */
0133     private $_loaderTypes = array('filter', 'helper');
0134 
0135     /**
0136      * Strict variables flag; when on, undefined variables accessed in the view
0137      * scripts will trigger notices
0138      * @var boolean
0139      */
0140     private $_strictVars = false;
0141 
0142     /**
0143      * Constructor.
0144      *
0145      * @param array $config Configuration key-value pairs.
0146      */
0147     public function __construct($config = array())
0148     {
0149         // set inital paths and properties
0150         $this->setScriptPath(null);
0151 
0152         // $this->setHelperPath(null);
0153         $this->setFilterPath(null);
0154 
0155         // user-defined escaping callback
0156         if (array_key_exists('escape', $config)) {
0157             $this->setEscape($config['escape']);
0158         }
0159 
0160         // encoding
0161         if (array_key_exists('encoding', $config)) {
0162             $this->setEncoding($config['encoding']);
0163         }
0164 
0165         // base path
0166         if (array_key_exists('basePath', $config)) {
0167             $prefix = 'Zend_View';
0168             if (array_key_exists('basePathPrefix', $config)) {
0169                 $prefix = $config['basePathPrefix'];
0170             }
0171             $this->setBasePath($config['basePath'], $prefix);
0172         }
0173 
0174         // user-defined view script path
0175         if (array_key_exists('scriptPath', $config)) {
0176             $this->addScriptPath($config['scriptPath']);
0177         }
0178 
0179         // user-defined helper path
0180         if (array_key_exists('helperPath', $config)) {
0181             if (is_array($config['helperPath'])) {
0182                 foreach ($config['helperPath'] as $prefix => $path) {
0183                     $this->addHelperPath($path, $prefix);
0184                 }
0185             } else {
0186                 $prefix = 'Zend_View_Helper';
0187                 if (array_key_exists('helperPathPrefix', $config)) {
0188                     $prefix = $config['helperPathPrefix'];
0189                 }
0190                 $this->addHelperPath($config['helperPath'], $prefix);
0191             }
0192         }
0193 
0194         // user-defined filter path
0195         if (array_key_exists('filterPath', $config)) {
0196             if (is_array($config['filterPath'])) {
0197                 foreach ($config['filterPath'] as $prefix => $path) {
0198                     $this->addFilterPath($path, $prefix);
0199                 }
0200             } else {
0201                 $prefix = 'Zend_View_Filter';
0202                 if (array_key_exists('filterPathPrefix', $config)) {
0203                     $prefix = $config['filterPathPrefix'];
0204                 }
0205                 $this->addFilterPath($config['filterPath'], $prefix);
0206             }
0207         }
0208 
0209         // user-defined filters
0210         if (array_key_exists('filter', $config)) {
0211             $this->addFilter($config['filter']);
0212         }
0213 
0214         // strict vars
0215         if (array_key_exists('strictVars', $config)) {
0216             $this->strictVars($config['strictVars']);
0217         }
0218 
0219         // LFI protection flag
0220         if (array_key_exists('lfiProtectionOn', $config)) {
0221             $this->setLfiProtection($config['lfiProtectionOn']);
0222         }
0223 
0224         if (array_key_exists('assign', $config)
0225             && is_array($config['assign'])
0226         ) {
0227             foreach ($config['assign'] as $key => $value) {
0228                 $this->assign($key, $value);
0229             }
0230         }
0231 
0232         $this->init();
0233     }
0234 
0235     /**
0236      * Return the template engine object
0237      *
0238      * Returns the object instance, as it is its own template engine
0239      *
0240      * @return Zend_View_Abstract
0241      */
0242     public function getEngine()
0243     {
0244         return $this;
0245     }
0246 
0247     /**
0248      * Allow custom object initialization when extending Zend_View_Abstract or
0249      * Zend_View
0250      *
0251      * Triggered by {@link __construct() the constructor} as its final action.
0252      *
0253      * @return void
0254      */
0255     public function init()
0256     {
0257     }
0258 
0259     /**
0260      * Prevent E_NOTICE for nonexistent values
0261      *
0262      * If {@link strictVars()} is on, raises a notice.
0263      *
0264      * @param  string $key
0265      * @return null
0266      */
0267     public function __get($key)
0268     {
0269         if ($this->_strictVars) {
0270             trigger_error('Key "' . $key . '" does not exist', E_USER_NOTICE);
0271         }
0272 
0273         return null;
0274     }
0275 
0276     /**
0277      * Allows testing with empty() and isset() to work inside
0278      * templates.
0279      *
0280      * @param  string $key
0281      * @return boolean
0282      */
0283     public function __isset($key)
0284     {
0285         if ('_' != substr($key, 0, 1)) {
0286             return isset($this->$key);
0287         }
0288 
0289         return false;
0290     }
0291 
0292     /**
0293      * Directly assigns a variable to the view script.
0294      *
0295      * Checks first to ensure that the caller is not attempting to set a
0296      * protected or private member (by checking for a prefixed underscore); if
0297      * not, the public member is set; otherwise, an exception is raised.
0298      *
0299      * @param string $key The variable name.
0300      * @param mixed $val The variable value.
0301      * @return void
0302      * @throws Zend_View_Exception if an attempt to set a private or protected
0303      * member is detected
0304      */
0305     public function __set($key, $val)
0306     {
0307         if ('_' != substr($key, 0, 1)) {
0308             $this->$key = $val;
0309             return;
0310         }
0311 
0312         // require_once 'Zend/View/Exception.php';
0313         $e = new Zend_View_Exception('Setting private or protected class members is not allowed');
0314         $e->setView($this);
0315         throw $e;
0316     }
0317 
0318     /**
0319      * Allows unset() on object properties to work
0320      *
0321      * @param string $key
0322      * @return void
0323      */
0324     public function __unset($key)
0325     {
0326         if ('_' != substr($key, 0, 1) && isset($this->$key)) {
0327             unset($this->$key);
0328         }
0329     }
0330 
0331     /**
0332      * Accesses a helper object from within a script.
0333      *
0334      * If the helper class has a 'view' property, sets it with the current view
0335      * object.
0336      *
0337      * @param string $name The helper name.
0338      * @param array $args The parameters for the helper.
0339      * @return string The result of the helper output.
0340      */
0341     public function __call($name, $args)
0342     {
0343         // is the helper already loaded?
0344         $helper = $this->getHelper($name);
0345 
0346         // call the helper method
0347         return call_user_func_array(
0348             array($helper, $name),
0349             $args
0350         );
0351     }
0352 
0353     /**
0354      * Given a base path, sets the script, helper, and filter paths relative to it
0355      *
0356      * Assumes a directory structure of:
0357      * <code>
0358      * basePath/
0359      *     scripts/
0360      *     helpers/
0361      *     filters/
0362      * </code>
0363      *
0364      * @param  string $path
0365      * @param  string $prefix Prefix to use for helper and filter paths
0366      * @return Zend_View_Abstract
0367      */
0368     public function setBasePath($path, $classPrefix = 'Zend_View')
0369     {
0370         $path        = rtrim($path, '/');
0371         $path        = rtrim($path, '\\');
0372         $path       .= DIRECTORY_SEPARATOR;
0373         $classPrefix = rtrim($classPrefix, '_') . '_';
0374         $this->setScriptPath($path . 'scripts');
0375         $this->setHelperPath($path . 'helpers', $classPrefix . 'Helper');
0376         $this->setFilterPath($path . 'filters', $classPrefix . 'Filter');
0377         return $this;
0378     }
0379 
0380     /**
0381      * Given a base path, add script, helper, and filter paths relative to it
0382      *
0383      * Assumes a directory structure of:
0384      * <code>
0385      * basePath/
0386      *     scripts/
0387      *     helpers/
0388      *     filters/
0389      * </code>
0390      *
0391      * @param  string $path
0392      * @param  string $prefix Prefix to use for helper and filter paths
0393      * @return Zend_View_Abstract
0394      */
0395     public function addBasePath($path, $classPrefix = 'Zend_View')
0396     {
0397         $path        = rtrim($path, '/');
0398         $path        = rtrim($path, '\\');
0399         $path       .= DIRECTORY_SEPARATOR;
0400         $classPrefix = rtrim($classPrefix, '_') . '_';
0401         $this->addScriptPath($path . 'scripts');
0402         $this->addHelperPath($path . 'helpers', $classPrefix . 'Helper');
0403         $this->addFilterPath($path . 'filters', $classPrefix . 'Filter');
0404         return $this;
0405     }
0406 
0407     /**
0408      * Adds to the stack of view script paths in LIFO order.
0409      *
0410      * @param string|array The directory (-ies) to add.
0411      * @return Zend_View_Abstract
0412      */
0413     public function addScriptPath($path)
0414     {
0415         $this->_addPath('script', $path);
0416         return $this;
0417     }
0418 
0419     /**
0420      * Resets the stack of view script paths.
0421      *
0422      * To clear all paths, use Zend_View::setScriptPath(null).
0423      *
0424      * @param string|array The directory (-ies) to set as the path.
0425      * @return Zend_View_Abstract
0426      */
0427     public function setScriptPath($path)
0428     {
0429         $this->_path['script'] = array();
0430         $this->_addPath('script', $path);
0431         return $this;
0432     }
0433 
0434     /**
0435      * Return full path to a view script specified by $name
0436      *
0437      * @param  string $name
0438      * @return false|string False if script not found
0439      * @throws Zend_View_Exception if no script directory set
0440      */
0441     public function getScriptPath($name)
0442     {
0443         try {
0444             $path = $this->_script($name);
0445             return $path;
0446         } catch (Zend_View_Exception $e) {
0447             if (strstr($e->getMessage(), 'no view script directory set')) {
0448                 throw $e;
0449             }
0450 
0451             return false;
0452         }
0453     }
0454 
0455     /**
0456      * Returns an array of all currently set script paths
0457      *
0458      * @return array
0459      */
0460     public function getScriptPaths()
0461     {
0462         return $this->_getPaths('script');
0463     }
0464 
0465     /**
0466      * Set plugin loader for a particular plugin type
0467      *
0468      * @param  Zend_Loader_PluginLoader $loader
0469      * @param  string $type
0470      * @return Zend_View_Abstract
0471      */
0472     public function setPluginLoader(Zend_Loader_PluginLoader $loader, $type)
0473     {
0474         $type = strtolower($type);
0475         if (!in_array($type, $this->_loaderTypes)) {
0476             // require_once 'Zend/View/Exception.php';
0477             $e = new Zend_View_Exception(sprintf('Invalid plugin loader type "%s"', $type));
0478             $e->setView($this);
0479             throw $e;
0480         }
0481 
0482         $this->_loaders[$type] = $loader;
0483         return $this;
0484     }
0485 
0486     /**
0487      * Retrieve plugin loader for a specific plugin type
0488      *
0489      * @param  string $type
0490      * @return Zend_Loader_PluginLoader
0491      */
0492     public function getPluginLoader($type)
0493     {
0494         $type = strtolower($type);
0495         if (!in_array($type, $this->_loaderTypes)) {
0496             // require_once 'Zend/View/Exception.php';
0497             $e = new Zend_View_Exception(sprintf('Invalid plugin loader type "%s"; cannot retrieve', $type));
0498             $e->setView($this);
0499             throw $e;
0500         }
0501 
0502         if (!array_key_exists($type, $this->_loaders)) {
0503             $prefix     = 'Zend_View_';
0504             $pathPrefix = 'Zend/View/';
0505 
0506             $pType = ucfirst($type);
0507             switch ($type) {
0508                 case 'filter':
0509                 case 'helper':
0510                 default:
0511                     $prefix     .= $pType;
0512                     $pathPrefix .= $pType;
0513                     $loader = new Zend_Loader_PluginLoader(array(
0514                         $prefix => $pathPrefix
0515                     ));
0516                     $this->_loaders[$type] = $loader;
0517                     break;
0518             }
0519         }
0520         return $this->_loaders[$type];
0521     }
0522 
0523     /**
0524      * Adds to the stack of helper paths in LIFO order.
0525      *
0526      * @param string|array The directory (-ies) to add.
0527      * @param string $classPrefix Class prefix to use with classes in this
0528      * directory; defaults to Zend_View_Helper
0529      * @return Zend_View_Abstract
0530      */
0531     public function addHelperPath($path, $classPrefix = 'Zend_View_Helper_')
0532     {
0533         return $this->_addPluginPath('helper', $classPrefix, (array) $path);
0534     }
0535 
0536     /**
0537      * Resets the stack of helper paths.
0538      *
0539      * To clear all paths, use Zend_View::setHelperPath(null).
0540      *
0541      * @param string|array $path The directory (-ies) to set as the path.
0542      * @param string $classPrefix The class prefix to apply to all elements in
0543      * $path; defaults to Zend_View_Helper
0544      * @return Zend_View_Abstract
0545      */
0546     public function setHelperPath($path, $classPrefix = 'Zend_View_Helper_')
0547     {
0548         unset($this->_loaders['helper']);
0549         return $this->addHelperPath($path, $classPrefix);
0550     }
0551 
0552     /**
0553      * Get full path to a helper class file specified by $name
0554      *
0555      * @param  string $name
0556      * @return string|false False on failure, path on success
0557      */
0558     public function getHelperPath($name)
0559     {
0560         return $this->_getPluginPath('helper', $name);
0561     }
0562 
0563     /**
0564      * Returns an array of all currently set helper paths
0565      *
0566      * @return array
0567      */
0568     public function getHelperPaths()
0569     {
0570         return $this->getPluginLoader('helper')->getPaths();
0571     }
0572 
0573     /**
0574      * Registers a helper object, bypassing plugin loader
0575      *
0576      * @param  Zend_View_Helper_Abstract|object $helper
0577      * @param  string $name
0578      * @return Zend_View_Abstract
0579      * @throws Zend_View_Exception
0580      */
0581     public function registerHelper($helper, $name)
0582     {
0583         if (!is_object($helper)) {
0584             // require_once 'Zend/View/Exception.php';
0585             $e = new Zend_View_Exception('View helper must be an object');
0586             $e->setView($this);
0587             throw $e;
0588         }
0589 
0590         if (!$helper instanceof Zend_View_Interface) {
0591             if (!method_exists($helper, $name)) {
0592                 // require_once 'Zend/View/Exception.php';
0593                 $e =  new Zend_View_Exception(
0594                     'View helper must implement Zend_View_Interface or have a method matching the name provided'
0595                 );
0596                 $e->setView($this);
0597                 throw $e;
0598             }
0599         }
0600 
0601         if (method_exists($helper, 'setView')) {
0602             $helper->setView($this);
0603         }
0604 
0605         $name = ucfirst($name);
0606         $this->_helper[$name] = $helper;
0607         return $this;
0608     }
0609 
0610     /**
0611      * Get a helper by name
0612      *
0613      * @param  string $name
0614      * @return object
0615      */
0616     public function getHelper($name)
0617     {
0618         return $this->_getPlugin('helper', $name);
0619     }
0620 
0621     /**
0622      * Get array of all active helpers
0623      *
0624      * Only returns those that have already been instantiated.
0625      *
0626      * @return array
0627      */
0628     public function getHelpers()
0629     {
0630         return $this->_helper;
0631     }
0632 
0633     /**
0634      * Adds to the stack of filter paths in LIFO order.
0635      *
0636      * @param string|array The directory (-ies) to add.
0637      * @param string $classPrefix Class prefix to use with classes in this
0638      * directory; defaults to Zend_View_Filter
0639      * @return Zend_View_Abstract
0640      */
0641     public function addFilterPath($path, $classPrefix = 'Zend_View_Filter_')
0642     {
0643         return $this->_addPluginPath('filter', $classPrefix, (array) $path);
0644     }
0645 
0646     /**
0647      * Resets the stack of filter paths.
0648      *
0649      * To clear all paths, use Zend_View::setFilterPath(null).
0650      *
0651      * @param string|array The directory (-ies) to set as the path.
0652      * @param string $classPrefix The class prefix to apply to all elements in
0653      * $path; defaults to Zend_View_Filter
0654      * @return Zend_View_Abstract
0655      */
0656     public function setFilterPath($path, $classPrefix = 'Zend_View_Filter_')
0657     {
0658         unset($this->_loaders['filter']);
0659         return $this->addFilterPath($path, $classPrefix);
0660     }
0661 
0662     /**
0663      * Get full path to a filter class file specified by $name
0664      *
0665      * @param  string $name
0666      * @return string|false False on failure, path on success
0667      */
0668     public function getFilterPath($name)
0669     {
0670         return $this->_getPluginPath('filter', $name);
0671     }
0672 
0673     /**
0674      * Get a filter object by name
0675      *
0676      * @param  string $name
0677      * @return object
0678      */
0679     public function getFilter($name)
0680     {
0681         return $this->_getPlugin('filter', $name);
0682     }
0683 
0684     /**
0685      * Return array of all currently active filters
0686      *
0687      * Only returns those that have already been instantiated.
0688      *
0689      * @return array
0690      */
0691     public function getFilters()
0692     {
0693         return $this->_filter;
0694     }
0695 
0696     /**
0697      * Returns an array of all currently set filter paths
0698      *
0699      * @return array
0700      */
0701     public function getFilterPaths()
0702     {
0703         return $this->getPluginLoader('filter')->getPaths();
0704     }
0705 
0706     /**
0707      * Return associative array of path types => paths
0708      *
0709      * @return array
0710      */
0711     public function getAllPaths()
0712     {
0713         $paths = $this->_path;
0714         $paths['helper'] = $this->getHelperPaths();
0715         $paths['filter'] = $this->getFilterPaths();
0716         return $paths;
0717     }
0718 
0719     /**
0720      * Add one or more filters to the stack in FIFO order.
0721      *
0722      * @param string|array One or more filters to add.
0723      * @return Zend_View_Abstract
0724      */
0725     public function addFilter($name)
0726     {
0727         foreach ((array) $name as $val) {
0728             $this->_filter[] = $val;
0729         }
0730         return $this;
0731     }
0732 
0733     /**
0734      * Resets the filter stack.
0735      *
0736      * To clear all filters, use Zend_View::setFilter(null).
0737      *
0738      * @param string|array One or more filters to set.
0739      * @return Zend_View_Abstract
0740      */
0741     public function setFilter($name)
0742     {
0743         $this->_filter = array();
0744         $this->addFilter($name);
0745         return $this;
0746     }
0747 
0748     /**
0749      * Sets the _escape() callback.
0750      *
0751      * @param mixed $spec The callback for _escape() to use.
0752      * @return Zend_View_Abstract
0753      */
0754     public function setEscape($spec)
0755     {
0756         $this->_escape = $spec;
0757         return $this;
0758     }
0759 
0760     /**
0761      * Set LFI protection flag
0762      *
0763      * @param  bool $flag
0764      * @return Zend_View_Abstract
0765      */
0766     public function setLfiProtection($flag)
0767     {
0768         $this->_lfiProtectionOn = (bool) $flag;
0769         return $this;
0770     }
0771 
0772     /**
0773      * Return status of LFI protection flag
0774      *
0775      * @return bool
0776      */
0777     public function isLfiProtectionOn()
0778     {
0779         return $this->_lfiProtectionOn;
0780     }
0781 
0782     /**
0783      * Assigns variables to the view script via differing strategies.
0784      *
0785      * Zend_View::assign('name', $value) assigns a variable called 'name'
0786      * with the corresponding $value.
0787      *
0788      * Zend_View::assign($array) assigns the array keys as variable
0789      * names (with the corresponding array values).
0790      *
0791      * @see    __set()
0792      * @param  string|array The assignment strategy to use.
0793      * @param  mixed (Optional) If assigning a named variable, use this
0794      * as the value.
0795      * @return Zend_View_Abstract Fluent interface
0796      * @throws Zend_View_Exception if $spec is neither a string nor an array,
0797      * or if an attempt to set a private or protected member is detected
0798      */
0799     public function assign($spec, $value = null)
0800     {
0801         // which strategy to use?
0802         if (is_string($spec)) {
0803             // assign by name and value
0804             if ('_' == substr($spec, 0, 1)) {
0805                 // require_once 'Zend/View/Exception.php';
0806                 $e = new Zend_View_Exception('Setting private or protected class members is not allowed');
0807                 $e->setView($this);
0808                 throw $e;
0809             }
0810             $this->$spec = $value;
0811         } elseif (is_array($spec)) {
0812             // assign from associative array
0813             $error = false;
0814             foreach ($spec as $key => $val) {
0815                 if ('_' == substr($key, 0, 1)) {
0816                     $error = true;
0817                     break;
0818                 }
0819                 $this->$key = $val;
0820             }
0821             if ($error) {
0822                 // require_once 'Zend/View/Exception.php';
0823                 $e = new Zend_View_Exception('Setting private or protected class members is not allowed');
0824                 $e->setView($this);
0825                 throw $e;
0826             }
0827         } else {
0828             // require_once 'Zend/View/Exception.php';
0829             $e = new Zend_View_Exception('assign() expects a string or array, received ' . gettype($spec));
0830             $e->setView($this);
0831             throw $e;
0832         }
0833 
0834         return $this;
0835     }
0836 
0837     /**
0838      * Return list of all assigned variables
0839      *
0840      * Returns all public properties of the object. Reflection is not used
0841      * here as testing reflection properties for visibility is buggy.
0842      *
0843      * @return array
0844      */
0845     public function getVars()
0846     {
0847         $vars   = get_object_vars($this);
0848         foreach ($vars as $key => $value) {
0849             if ('_' == substr($key, 0, 1)) {
0850                 unset($vars[$key]);
0851             }
0852         }
0853 
0854         return $vars;
0855     }
0856 
0857     /**
0858      * Clear all assigned variables
0859      *
0860      * Clears all variables assigned to Zend_View either via {@link assign()} or
0861      * property overloading ({@link __set()}).
0862      *
0863      * @return void
0864      */
0865     public function clearVars()
0866     {
0867         $vars   = get_object_vars($this);
0868         foreach ($vars as $key => $value) {
0869             if ('_' != substr($key, 0, 1)) {
0870                 unset($this->$key);
0871             }
0872         }
0873     }
0874 
0875     /**
0876      * Processes a view script and returns the output.
0877      *
0878      * @param string $name The script name to process.
0879      * @return string The script output.
0880      */
0881     public function render($name)
0882     {
0883         // find the script file name using the parent private method
0884         $this->_file = $this->_script($name);
0885         unset($name); // remove $name from local scope
0886 
0887         ob_start();
0888         $this->_run($this->_file);
0889 
0890         return $this->_filter(ob_get_clean()); // filter output
0891     }
0892 
0893     /**
0894      * Escapes a value for output in a view script.
0895      *
0896      * If escaping mechanism is one of htmlspecialchars or htmlentities, uses
0897      * {@link $_encoding} setting.
0898      *
0899      * @param mixed $var The output to escape.
0900      * @return mixed The escaped value.
0901      */
0902     public function escape($var)
0903     {
0904         if (in_array($this->_escape, array('htmlspecialchars', 'htmlentities'))) {
0905             return call_user_func($this->_escape, $var, ENT_COMPAT, $this->_encoding);
0906         }
0907 
0908         if (1 == func_num_args()) {
0909             return call_user_func($this->_escape, $var);
0910         }
0911         $args = func_get_args();
0912         return call_user_func_array($this->_escape, $args);
0913     }
0914 
0915     /**
0916      * Set encoding to use with htmlentities() and htmlspecialchars()
0917      *
0918      * @param string $encoding
0919      * @return Zend_View_Abstract
0920      */
0921     public function setEncoding($encoding)
0922     {
0923         $this->_encoding = $encoding;
0924         return $this;
0925     }
0926 
0927     /**
0928      * Return current escape encoding
0929      *
0930      * @return string
0931      */
0932     public function getEncoding()
0933     {
0934         return $this->_encoding;
0935     }
0936 
0937     /**
0938      * Enable or disable strict vars
0939      *
0940      * If strict variables are enabled, {@link __get()} will raise a notice
0941      * when a variable is not defined.
0942      *
0943      * Use in conjunction with {@link Zend_View_Helper_DeclareVars the declareVars() helper}
0944      * to enforce strict variable handling in your view scripts.
0945      *
0946      * @param  boolean $flag
0947      * @return Zend_View_Abstract
0948      */
0949     public function strictVars($flag = true)
0950     {
0951         $this->_strictVars = ($flag) ? true : false;
0952 
0953         return $this;
0954     }
0955 
0956     /**
0957      * Finds a view script from the available directories.
0958      *
0959      * @param string $name The base name of the script.
0960      * @return void
0961      */
0962     protected function _script($name)
0963     {
0964         if ($this->isLfiProtectionOn() && preg_match('#\.\.[\\\/]#', $name)) {
0965             // require_once 'Zend/View/Exception.php';
0966             $e = new Zend_View_Exception('Requested scripts may not include parent directory traversal ("../", "..\\" notation)');
0967             $e->setView($this);
0968             throw $e;
0969         }
0970 
0971         if (0 == count($this->_path['script'])) {
0972             // require_once 'Zend/View/Exception.php';
0973             $e = new Zend_View_Exception('no view script directory set; unable to determine location for view script');
0974             $e->setView($this);
0975             throw $e;
0976         }
0977 
0978         foreach ($this->_path['script'] as $dir) {
0979             if (is_readable($dir . $name)) {
0980                 return $dir . $name;
0981             }
0982         }
0983 
0984         // require_once 'Zend/View/Exception.php';
0985         $message = "script '$name' not found in path ("
0986                  . implode(PATH_SEPARATOR, $this->_path['script'])
0987                  . ")";
0988         $e = new Zend_View_Exception($message);
0989         $e->setView($this);
0990         throw $e;
0991     }
0992 
0993     /**
0994      * Applies the filter callback to a buffer.
0995      *
0996      * @param string $buffer The buffer contents.
0997      * @return string The filtered buffer.
0998      */
0999     private function _filter($buffer)
1000     {
1001         // loop through each filter class
1002         foreach ($this->_filter as $name) {
1003             // load and apply the filter class
1004             $filter = $this->getFilter($name);
1005             $buffer = call_user_func(array($filter, 'filter'), $buffer);
1006         }
1007 
1008         // done!
1009         return $buffer;
1010     }
1011 
1012     /**
1013      * Adds paths to the path stack in LIFO order.
1014      *
1015      * Zend_View::_addPath($type, 'dirname') adds one directory
1016      * to the path stack.
1017      *
1018      * Zend_View::_addPath($type, $array) adds one directory for
1019      * each array element value.
1020      *
1021      * In the case of filter and helper paths, $prefix should be used to
1022      * specify what class prefix to use with the given path.
1023      *
1024      * @param string $type The path type ('script', 'helper', or 'filter').
1025      * @param string|array $path The path specification.
1026      * @param string $prefix Class prefix to use with path (helpers and filters
1027      * only)
1028      * @return void
1029      */
1030     private function _addPath($type, $path, $prefix = null)
1031     {
1032         foreach ((array) $path as $dir) {
1033             // attempt to strip any possible separator and
1034             // append the system directory separator
1035             $dir  = rtrim($dir, '/');
1036             $dir  = rtrim($dir, '\\');
1037             $dir .= '/';
1038 
1039             switch ($type) {
1040                 case 'script':
1041                     // add to the top of the stack.
1042                     array_unshift($this->_path[$type], $dir);
1043                     break;
1044                 case 'filter':
1045                 case 'helper':
1046                 default:
1047                     // add as array with prefix and dir keys
1048                     array_unshift($this->_path[$type], array('prefix' => $prefix, 'dir' => $dir));
1049                     break;
1050             }
1051         }
1052     }
1053 
1054     /**
1055      * Resets the path stack for helpers and filters.
1056      *
1057      * @param string $type The path type ('helper' or 'filter').
1058      * @param string|array $path The directory (-ies) to set as the path.
1059      * @param string $classPrefix Class prefix to apply to elements of $path
1060      */
1061     private function _setPath($type, $path, $classPrefix = null)
1062     {
1063         $dir = DIRECTORY_SEPARATOR . ucfirst($type) . DIRECTORY_SEPARATOR;
1064 
1065         switch ($type) {
1066             case 'script':
1067                 $this->_path[$type] = array(dirname(__FILE__) . $dir);
1068                 $this->_addPath($type, $path);
1069                 break;
1070             case 'filter':
1071             case 'helper':
1072             default:
1073                 $this->_path[$type] = array(array(
1074                     'prefix' => 'Zend_View_' . ucfirst($type) . '_',
1075                     'dir'    => dirname(__FILE__) . $dir
1076                 ));
1077                 $this->_addPath($type, $path, $classPrefix);
1078                 break;
1079         }
1080     }
1081 
1082     /**
1083      * Return all paths for a given path type
1084      *
1085      * @param string $type The path type  ('helper', 'filter', 'script')
1086      * @return array
1087      */
1088     private function _getPaths($type)
1089     {
1090         return $this->_path[$type];
1091     }
1092 
1093     /**
1094      * Register helper class as loaded
1095      *
1096      * @param  string $name
1097      * @param  string $class
1098      * @param  string $file path to class file
1099      * @return void
1100      */
1101     private function _setHelperClass($name, $class, $file)
1102     {
1103         $this->_helperLoadedDir[$name] = $file;
1104         $this->_helperLoaded[$name]    = $class;
1105     }
1106 
1107     /**
1108      * Register filter class as loaded
1109      *
1110      * @param  string $name
1111      * @param  string $class
1112      * @param  string $file path to class file
1113      * @return void
1114      */
1115     private function _setFilterClass($name, $class, $file)
1116     {
1117         $this->_filterLoadedDir[$name] = $file;
1118         $this->_filterLoaded[$name]    = $class;
1119     }
1120 
1121     /**
1122      * Add a prefixPath for a plugin type
1123      *
1124      * @param  string $type
1125      * @param  string $classPrefix
1126      * @param  array $paths
1127      * @return Zend_View_Abstract
1128      */
1129     private function _addPluginPath($type, $classPrefix, array $paths)
1130     {
1131         $loader = $this->getPluginLoader($type);
1132         foreach ($paths as $path) {
1133             $loader->addPrefixPath($classPrefix, $path);
1134         }
1135         return $this;
1136     }
1137 
1138     /**
1139      * Get a path to a given plugin class of a given type
1140      *
1141      * @param  string $type
1142      * @param  string $name
1143      * @return string|false
1144      */
1145     private function _getPluginPath($type, $name)
1146     {
1147         $loader = $this->getPluginLoader($type);
1148         if ($loader->isLoaded($name)) {
1149             return $loader->getClassPath($name);
1150         }
1151 
1152         try {
1153             $loader->load($name);
1154             return $loader->getClassPath($name);
1155         } catch (Zend_Loader_Exception $e) {
1156             return false;
1157         }
1158     }
1159 
1160     /**
1161      * Retrieve a plugin object
1162      *
1163      * @param  string $type
1164      * @param  string $name
1165      * @return object
1166      */
1167     private function _getPlugin($type, $name)
1168     {
1169         $name = ucfirst($name);
1170         switch ($type) {
1171             case 'filter':
1172                 $storeVar = '_filterClass';
1173                 $store    = $this->_filterClass;
1174                 break;
1175             case 'helper':
1176                 $storeVar = '_helper';
1177                 $store    = $this->_helper;
1178                 break;
1179         }
1180 
1181         if (!isset($store[$name])) {
1182             $class = $this->getPluginLoader($type)->load($name);
1183             $store[$name] = new $class();
1184             if (method_exists($store[$name], 'setView')) {
1185                 $store[$name]->setView($this);
1186             }
1187         }
1188 
1189         $this->$storeVar = $store;
1190         return $store[$name];
1191     }
1192 
1193     /**
1194      * Use to include the view script in a scope that only allows public
1195      * members.
1196      *
1197      * @return mixed
1198      */
1199     abstract protected function _run();
1200 }