Abstract.php 31 KB

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