<?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 [email protected] so we can send you a copy immediately.
14 *
15 * @category Zend
16 * @package Zend_View
17 * @copyright Copyright (c) 2005-2012 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 24593 2012-01-05 20:35:02Z 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-2012 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 if (array_key_exists('assign', $config)
225 && is_array($config['assign'])
226 ) {
227 foreach ($config['assign'] as $key => $value) {
228 $this->assign($key, $value);
229 }
230 }
231
232 $this->init();
233 }
234
235 /**
236 * Return the template engine object
237 *
238 * Returns the object instance, as it is its own template engine
239 *
240 * @return Zend_View_Abstract
241 */
242 public function getEngine()
243 {
244 return $this;
245 }
246
247 /**
248 * Allow custom object initialization when extending Zend_View_Abstract or
249 * Zend_View
250 *
251 * Triggered by {@link __construct() the constructor} as its final action.
252 *
253 * @return void
254 */
255 public function init()
256 {
257 }
258
259 /**
260 * Prevent E_NOTICE for nonexistent values
261 *
262 * If {@link strictVars()} is on, raises a notice.
263 *
264 * @param string $key
265 * @return null
266 */
267 public function __get($key)
268 {
269 if ($this->_strictVars) {
270 trigger_error('Key "' . $key . '" does not exist', E_USER_NOTICE);
271 }
272
273 return null;
274 }
275
276 /**
277 * Allows testing with empty() and isset() to work inside
278 * templates.
279 *
280 * @param string $key
281 * @return boolean
282 */
283 public function __isset($key)
284 {
285 if ('_' != substr($key, 0, 1)) {
286 return isset($this->$key);
287 }
288
289 return false;
290 }
291
292 /**
293 * Directly assigns a variable to the view script.
294 *
295 * Checks first to ensure that the caller is not attempting to set a
296 * protected or private member (by checking for a prefixed underscore); if
297 * not, the public member is set; otherwise, an exception is raised.
298 *
299 * @param string $key The variable name.
300 * @param mixed $val The variable value.
301 * @return void
302 * @throws Zend_View_Exception if an attempt to set a private or protected
303 * member is detected
304 */
305 public function __set($key, $val)
306 {
307 if ('_' != substr($key, 0, 1)) {
308 $this->$key = $val;
309 return;
310 }
311
312 require_once 'Zend/View/Exception.php';
313 $e = new Zend_View_Exception('Setting private or protected class members is not allowed');
314 $e->setView($this);
315 throw $e;
316 }
317
318 /**
319 * Allows unset() on object properties to work
320 *
321 * @param string $key
322 * @return void
323 */
324 public function __unset($key)
325 {
326 if ('_' != substr($key, 0, 1) && isset($this->$key)) {
327 unset($this->$key);
328 }
329 }
330
331 /**
332 * Accesses a helper object from within a script.
333 *
334 * If the helper class has a 'view' property, sets it with the current view
335 * object.
336 *
337 * @param string $name The helper name.
338 * @param array $args The parameters for the helper.
339 * @return string The result of the helper output.
340 */
341 public function __call($name, $args)
342 {
343 // is the helper already loaded?
344 $helper = $this->getHelper($name);
345
346 // call the helper method
347 return call_user_func_array(
348 array($helper, $name),
349 $args
350 );
351 }
352
353 /**
354 * Given a base path, sets the script, helper, and filter paths relative to it
355 *
356 * Assumes a directory structure of:
357 * <code>
358 * basePath/
359 * scripts/
360 * helpers/
361 * filters/
362 * </code>
363 *
364 * @param string $path
365 * @param string $prefix Prefix to use for helper and filter paths
366 * @return Zend_View_Abstract
367 */
368 public function setBasePath($path, $classPrefix = 'Zend_View')
369 {
370 $path = rtrim($path, '/');
371 $path = rtrim($path, '\\');
372 $path .= DIRECTORY_SEPARATOR;
373 $classPrefix = rtrim($classPrefix, '_') . '_';
374 $this->setScriptPath($path . 'scripts');
375 $this->setHelperPath($path . 'helpers', $classPrefix . 'Helper');
376 $this->setFilterPath($path . 'filters', $classPrefix . 'Filter');
377 return $this;
378 }
379
380 /**
381 * Given a base path, add script, helper, and filter paths relative to it
382 *
383 * Assumes a directory structure of:
384 * <code>
385 * basePath/
386 * scripts/
387 * helpers/
388 * filters/
389 * </code>
390 *
391 * @param string $path
392 * @param string $prefix Prefix to use for helper and filter paths
393 * @return Zend_View_Abstract
394 */
395 public function addBasePath($path, $classPrefix = 'Zend_View')
396 {
397 $path = rtrim($path, '/');
398 $path = rtrim($path, '\\');
399 $path .= DIRECTORY_SEPARATOR;
400 $classPrefix = rtrim($classPrefix, '_') . '_';
401 $this->addScriptPath($path . 'scripts');
402 $this->addHelperPath($path . 'helpers', $classPrefix . 'Helper');
403 $this->addFilterPath($path . 'filters', $classPrefix . 'Filter');
404 return $this;
405 }
406
407 /**
408 * Adds to the stack of view script paths in LIFO order.
409 *
410 * @param string|array The directory (-ies) to add.
411 * @return Zend_View_Abstract
412 */
413 public function addScriptPath($path)
414 {
415 $this->_addPath('script', $path);
416 return $this;
417 }
418
419 /**
420 * Resets the stack of view script paths.
421 *
422 * To clear all paths, use Zend_View::setScriptPath(null).
423 *
424 * @param string|array The directory (-ies) to set as the path.
425 * @return Zend_View_Abstract
426 */
427 public function setScriptPath($path)
428 {
429 $this->_path['script'] = array();
430 $this->_addPath('script', $path);
431 return $this;
432 }
433
434 /**
435 * Return full path to a view script specified by $name
436 *
437 * @param string $name
438 * @return false|string False if script not found
439 * @throws Zend_View_Exception if no script directory set
440 */
441 public function getScriptPath($name)
442 {
443 try {
444 $path = $this->_script($name);
445 return $path;
446 } catch (Zend_View_Exception $e) {
447 if (strstr($e->getMessage(), 'no view script directory set')) {
448 throw $e;
449 }
450
451 return false;
452 }
453 }
454
455 /**
456 * Returns an array of all currently set script paths
457 *
458 * @return array
459 */
460 public function getScriptPaths()
461 {
462 return $this->_getPaths('script');
463 }
464
465 /**
466 * Set plugin loader for a particular plugin type
467 *
468 * @param Zend_Loader_PluginLoader $loader
469 * @param string $type
470 * @return Zend_View_Abstract
471 */
472 public function setPluginLoader(Zend_Loader_PluginLoader $loader, $type)
473 {
474 $type = strtolower($type);
475 if (!in_array($type, $this->_loaderTypes)) {
476 require_once 'Zend/View/Exception.php';
477 $e = new Zend_View_Exception(sprintf('Invalid plugin loader type "%s"', $type));
478 $e->setView($this);
479 throw $e;
480 }
481
482 $this->_loaders[$type] = $loader;
483 return $this;
484 }
485
486 /**
487 * Retrieve plugin loader for a specific plugin type
488 *
489 * @param string $type
490 * @return Zend_Loader_PluginLoader
491 */
492 public function getPluginLoader($type)
493 {
494 $type = strtolower($type);
495 if (!in_array($type, $this->_loaderTypes)) {
496 require_once 'Zend/View/Exception.php';
497 $e = new Zend_View_Exception(sprintf('Invalid plugin loader type "%s"; cannot retrieve', $type));
498 $e->setView($this);
499 throw $e;
500 }
501
502 if (!array_key_exists($type, $this->_loaders)) {
503 $prefix = 'Zend_View_';
504 $pathPrefix = 'Zend/View/';
505
506 $pType = ucfirst($type);
507 switch ($type) {
508 case 'filter':
509 case 'helper':
510 default:
511 $prefix .= $pType;
512 $pathPrefix .= $pType;
513 $loader = new Zend_Loader_PluginLoader(array(
514 $prefix => $pathPrefix
515 ));
516 $this->_loaders[$type] = $loader;
517 break;
518 }
519 }
520 return $this->_loaders[$type];
521 }
522
523 /**
524 * Adds to the stack of helper paths in LIFO order.
525 *
526 * @param string|array The directory (-ies) to add.
527 * @param string $classPrefix Class prefix to use with classes in this
528 * directory; defaults to Zend_View_Helper
529 * @return Zend_View_Abstract
530 */
531 public function addHelperPath($path, $classPrefix = 'Zend_View_Helper_')
532 {
533 return $this->_addPluginPath('helper', $classPrefix, (array) $path);
534 }
535
536 /**
537 * Resets the stack of helper paths.
538 *
539 * To clear all paths, use Zend_View::setHelperPath(null).
540 *
541 * @param string|array $path The directory (-ies) to set as the path.
542 * @param string $classPrefix The class prefix to apply to all elements in
543 * $path; defaults to Zend_View_Helper
544 * @return Zend_View_Abstract
545 */
546 public function setHelperPath($path, $classPrefix = 'Zend_View_Helper_')
547 {
548 unset($this->_loaders['helper']);
549 return $this->addHelperPath($path, $classPrefix);
550 }
551
552 /**
553 * Get full path to a helper class file specified by $name
554 *
555 * @param string $name
556 * @return string|false False on failure, path on success
557 */
558 public function getHelperPath($name)
559 {
560 return $this->_getPluginPath('helper', $name);
561 }
562
563 /**
564 * Returns an array of all currently set helper paths
565 *
566 * @return array
567 */
568 public function getHelperPaths()
569 {
570 return $this->getPluginLoader('helper')->getPaths();
571 }
572
573 /**
574 * Registers a helper object, bypassing plugin loader
575 *
576 * @param Zend_View_Helper_Abstract|object $helper
577 * @param string $name
578 * @return Zend_View_Abstract
579 * @throws Zend_View_Exception
580 */
581 public function registerHelper($helper, $name)
582 {
583 if (!is_object($helper)) {
584 require_once 'Zend/View/Exception.php';
585 $e = new Zend_View_Exception('View helper must be an object');
586 $e->setView($this);
587 throw $e;
588 }
589
590 if (!$helper instanceof Zend_View_Interface) {
591 if (!method_exists($helper, $name)) {
592 require_once 'Zend/View/Exception.php';
593 $e = new Zend_View_Exception(
594 'View helper must implement Zend_View_Interface or have a method matching the name provided'
595 );
596 $e->setView($this);
597 throw $e;
598 }
599 }
600
601 if (method_exists($helper, 'setView')) {
602 $helper->setView($this);
603 }
604
605 $name = ucfirst($name);
606 $this->_helper[$name] = $helper;
607 return $this;
608 }
609
610 /**
611 * Get a helper by name
612 *
613 * @param string $name
614 * @return object
615 */
616 public function getHelper($name)
617 {
618 return $this->_getPlugin('helper', $name);
619 }
620
621 /**
622 * Get array of all active helpers
623 *
624 * Only returns those that have already been instantiated.
625 *
626 * @return array
627 */
628 public function getHelpers()
629 {
630 return $this->_helper;
631 }
632
633 /**
634 * Adds to the stack of filter paths in LIFO order.
635 *
636 * @param string|array The directory (-ies) to add.
637 * @param string $classPrefix Class prefix to use with classes in this
638 * directory; defaults to Zend_View_Filter
639 * @return Zend_View_Abstract
640 */
641 public function addFilterPath($path, $classPrefix = 'Zend_View_Filter_')
642 {
643 return $this->_addPluginPath('filter', $classPrefix, (array) $path);
644 }
645
646 /**
647 * Resets the stack of filter paths.
648 *
649 * To clear all paths, use Zend_View::setFilterPath(null).
650 *
651 * @param string|array The directory (-ies) to set as the path.
652 * @param string $classPrefix The class prefix to apply to all elements in
653 * $path; defaults to Zend_View_Filter
654 * @return Zend_View_Abstract
655 */
656 public function setFilterPath($path, $classPrefix = 'Zend_View_Filter_')
657 {
658 unset($this->_loaders['filter']);
659 return $this->addFilterPath($path, $classPrefix);
660 }
661
662 /**
663 * Get full path to a filter class file specified by $name
664 *
665 * @param string $name
666 * @return string|false False on failure, path on success
667 */
668 public function getFilterPath($name)
669 {
670 return $this->_getPluginPath('filter', $name);
671 }
672
673 /**
674 * Get a filter object by name
675 *
676 * @param string $name
677 * @return object
678 */
679 public function getFilter($name)
680 {
681 return $this->_getPlugin('filter', $name);
682 }
683
684 /**
685 * Return array of all currently active filters
686 *
687 * Only returns those that have already been instantiated.
688 *
689 * @return array
690 */
691 public function getFilters()
692 {
693 return $this->_filter;
694 }
695
696 /**
697 * Returns an array of all currently set filter paths
698 *
699 * @return array
700 */
701 public function getFilterPaths()
702 {
703 return $this->getPluginLoader('filter')->getPaths();
704 }
705
706 /**
707 * Return associative array of path types => paths
708 *
709 * @return array
710 */
711 public function getAllPaths()
712 {
713 $paths = $this->_path;
714 $paths['helper'] = $this->getHelperPaths();
715 $paths['filter'] = $this->getFilterPaths();
716 return $paths;
717 }
718
719 /**
720 * Add one or more filters to the stack in FIFO order.
721 *
722 * @param string|array One or more filters to add.
723 * @return Zend_View_Abstract
724 */
725 public function addFilter($name)
726 {
727 foreach ((array) $name as $val) {
728 $this->_filter[] = $val;
729 }
730 return $this;
731 }
732
733 /**
734 * Resets the filter stack.
735 *
736 * To clear all filters, use Zend_View::setFilter(null).
737 *
738 * @param string|array One or more filters to set.
739 * @return Zend_View_Abstract
740 */
741 public function setFilter($name)
742 {
743 $this->_filter = array();
744 $this->addFilter($name);
745 return $this;
746 }
747
748 /**
749 * Sets the _escape() callback.
750 *
751 * @param mixed $spec The callback for _escape() to use.
752 * @return Zend_View_Abstract
753 */
754 public function setEscape($spec)
755 {
756 $this->_escape = $spec;
757 return $this;
758 }
759
760 /**
761 * Set LFI protection flag
762 *
763 * @param bool $flag
764 * @return Zend_View_Abstract
765 */
766 public function setLfiProtection($flag)
767 {
768 $this->_lfiProtectionOn = (bool) $flag;
769 return $this;
770 }
771
772 /**
773 * Return status of LFI protection flag
774 *
775 * @return bool
776 */
777 public function isLfiProtectionOn()
778 {
779 return $this->_lfiProtectionOn;
780 }
781
782 /**
783 * Assigns variables to the view script via differing strategies.
784 *
785 * Zend_View::assign('name', $value) assigns a variable called 'name'
786 * with the corresponding $value.
787 *
788 * Zend_View::assign($array) assigns the array keys as variable
789 * names (with the corresponding array values).
790 *
791 * @see __set()
792 * @param string|array The assignment strategy to use.
793 * @param mixed (Optional) If assigning a named variable, use this
794 * as the value.
795 * @return Zend_View_Abstract Fluent interface
796 * @throws Zend_View_Exception if $spec is neither a string nor an array,
797 * or if an attempt to set a private or protected member is detected
798 */
799 public function assign($spec, $value = null)
800 {
801 // which strategy to use?
802 if (is_string($spec)) {
803 // assign by name and value
804 if ('_' == substr($spec, 0, 1)) {
805 require_once 'Zend/View/Exception.php';
806 $e = new Zend_View_Exception('Setting private or protected class members is not allowed');
807 $e->setView($this);
808 throw $e;
809 }
810 $this->$spec = $value;
811 } elseif (is_array($spec)) {
812 // assign from associative array
813 $error = false;
814 foreach ($spec as $key => $val) {
815 if ('_' == substr($key, 0, 1)) {
816 $error = true;
817 break;
818 }
819 $this->$key = $val;
820 }
821 if ($error) {
822 require_once 'Zend/View/Exception.php';
823 $e = new Zend_View_Exception('Setting private or protected class members is not allowed');
824 $e->setView($this);
825 throw $e;
826 }
827 } else {
828 require_once 'Zend/View/Exception.php';
829 $e = new Zend_View_Exception('assign() expects a string or array, received ' . gettype($spec));
830 $e->setView($this);
831 throw $e;
832 }
833
834 return $this;
835 }
836
837 /**
838 * Return list of all assigned variables
839 *
840 * Returns all public properties of the object. Reflection is not used
841 * here as testing reflection properties for visibility is buggy.
842 *
843 * @return array
844 */
845 public function getVars()
846 {
847 $vars = get_object_vars($this);
848 foreach ($vars as $key => $value) {
849 if ('_' == substr($key, 0, 1)) {
850 unset($vars[$key]);
851 }
852 }
853
854 return $vars;
855 }
856
857 /**
858 * Clear all assigned variables
859 *
860 * Clears all variables assigned to Zend_View either via {@link assign()} or
861 * property overloading ({@link __set()}).
862 *
863 * @return void
864 */
865 public function clearVars()
866 {
867 $vars = get_object_vars($this);
868 foreach ($vars as $key => $value) {
869 if ('_' != substr($key, 0, 1)) {
870 unset($this->$key);
871 }
872 }
873 }
874
875 /**
876 * Processes a view script and returns the output.
877 *
878 * @param string $name The script name to process.
879 * @return string The script output.
880 */
881 public function render($name)
882 {
883 // find the script file name using the parent private method
884 $this->_file = $this->_script($name);
885 unset($name); // remove $name from local scope
886
887 ob_start();
888 $this->_run($this->_file);
889
890 return $this->_filter(ob_get_clean()); // filter output
891 }
892
893 /**
894 * Escapes a value for output in a view script.
895 *
896 * If escaping mechanism is one of htmlspecialchars or htmlentities, uses
897 * {@link $_encoding} setting.
898 *
899 * @param mixed $var The output to escape.
900 * @return mixed The escaped value.
901 */
902 public function escape($var)
903 {
904 if (in_array($this->_escape, array('htmlspecialchars', 'htmlentities'))) {
905 return call_user_func($this->_escape, $var, ENT_COMPAT, $this->_encoding);
906 }
907
908 if (1 == func_num_args()) {
909 return call_user_func($this->_escape, $var);
910 }
911 $args = func_get_args();
912 return call_user_func_array($this->_escape, $args);
913 }
914
915 /**
916 * Set encoding to use with htmlentities() and htmlspecialchars()
917 *
918 * @param string $encoding
919 * @return Zend_View_Abstract
920 */
921 public function setEncoding($encoding)
922 {
923 $this->_encoding = $encoding;
924 return $this;
925 }
926
927 /**
928 * Return current escape encoding
929 *
930 * @return string
931 */
932 public function getEncoding()
933 {
934 return $this->_encoding;
935 }
936
937 /**
938 * Enable or disable strict vars
939 *
940 * If strict variables are enabled, {@link __get()} will raise a notice
941 * when a variable is not defined.
942 *
943 * Use in conjunction with {@link Zend_View_Helper_DeclareVars the declareVars() helper}
944 * to enforce strict variable handling in your view scripts.
945 *
946 * @param boolean $flag
947 * @return Zend_View_Abstract
948 */
949 public function strictVars($flag = true)
950 {
951 $this->_strictVars = ($flag) ? true : false;
952
953 return $this;
954 }
955
956 /**
957 * Finds a view script from the available directories.
958 *
959 * @param string $name The base name of the script.
960 * @return void
961 */
962 protected function _script($name)
963 {
964 if ($this->isLfiProtectionOn() && preg_match('#\.\.[\\\/]#', $name)) {
965 require_once 'Zend/View/Exception.php';
966 $e = new Zend_View_Exception('Requested scripts may not include parent directory traversal ("../", "..\\" notation)');
967 $e->setView($this);
968 throw $e;
969 }
970
971 if (0 == count($this->_path['script'])) {
972 require_once 'Zend/View/Exception.php';
973 $e = new Zend_View_Exception('no view script directory set; unable to determine location for view script');
974 $e->setView($this);
975 throw $e;
976 }
977
978 foreach ($this->_path['script'] as $dir) {
979 if (is_readable($dir . $name)) {
980 return $dir . $name;
981 }
982 }
983
984 require_once 'Zend/View/Exception.php';
985 $message = "script '$name' not found in path ("
986 . implode(PATH_SEPARATOR, $this->_path['script'])
987 . ")";
988 $e = new Zend_View_Exception($message);
989 $e->setView($this);
990 throw $e;
991 }
992
993 /**
994 * Applies the filter callback to a buffer.
995 *
996 * @param string $buffer The buffer contents.
997 * @return string The filtered buffer.
998 */
999 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 }
1201