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