ViewRenderer.php 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  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_Controller
  17. * @subpackage Zend_Controller_Action_Helper
  18. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * @see Zend_Controller_Action_Helper_Abstract
  24. */
  25. require_once 'Zend/Controller/Action/Helper/Abstract.php';
  26. /**
  27. * @see Zend_View
  28. */
  29. require_once 'Zend/View.php';
  30. /**
  31. * View script integration
  32. *
  33. * Zend_Controller_Action_Helper_ViewRenderer provides transparent view
  34. * integration for action controllers. It allows you to create a view object
  35. * once, and populate it throughout all actions. Several global options may be
  36. * set:
  37. *
  38. * - noController: if set true, render() will not look for view scripts in
  39. * subdirectories named after the controller
  40. * - viewSuffix: what view script filename suffix to use
  41. *
  42. * The helper autoinitializes the action controller view preDispatch(). It
  43. * determines the path to the class file, and then determines the view base
  44. * directory from there. It also uses the module name as a class prefix for
  45. * helpers and views such that if your module name is 'Search', it will set the
  46. * helper class prefix to 'Search_View_Helper' and the filter class prefix to ;
  47. * 'Search_View_Filter'.
  48. *
  49. * Usage:
  50. * <code>
  51. * // In your bootstrap:
  52. * Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_ViewRenderer());
  53. *
  54. * // In your action controller methods:
  55. * $viewHelper = $this->_helper->getHelper('view');
  56. *
  57. * // Don't use controller subdirectories
  58. * $viewHelper->setNoController(true);
  59. *
  60. * // Specify a different script to render:
  61. * $this->_helper->viewRenderer('form');
  62. *
  63. * </code>
  64. *
  65. * @uses Zend_Controller_Action_Helper_Abstract
  66. * @package Zend_Controller
  67. * @subpackage Zend_Controller_Action_Helper
  68. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  69. * @license http://framework.zend.com/license/new-bsd New BSD License
  70. */
  71. class Zend_Controller_Action_Helper_ViewRenderer extends Zend_Controller_Action_Helper_Abstract
  72. {
  73. /**
  74. * @var Zend_View_Interface
  75. */
  76. public $view;
  77. /**
  78. * Word delimiters
  79. * @var array
  80. */
  81. protected $_delimiters;
  82. /**
  83. * @var Zend_Filter_Inflector
  84. */
  85. protected $_inflector;
  86. /**
  87. * Inflector target
  88. * @var string
  89. */
  90. protected $_inflectorTarget = '';
  91. /**
  92. * Current module directory
  93. * @var string
  94. */
  95. protected $_moduleDir = '';
  96. /**
  97. * Whether or not to autorender using controller name as subdirectory;
  98. * global setting (not reset at next invocation)
  99. * @var boolean
  100. */
  101. protected $_neverController = false;
  102. /**
  103. * Whether or not to autorender postDispatch; global setting (not reset at
  104. * next invocation)
  105. * @var boolean
  106. */
  107. protected $_neverRender = false;
  108. /**
  109. * Whether or not to use a controller name as a subdirectory when rendering
  110. * @var boolean
  111. */
  112. protected $_noController = false;
  113. /**
  114. * Whether or not to autorender postDispatch; per controller/action setting (reset
  115. * at next invocation)
  116. * @var boolean
  117. */
  118. protected $_noRender = false;
  119. /**
  120. * Characters representing path delimiters in the controller
  121. * @var string|array
  122. */
  123. protected $_pathDelimiters;
  124. /**
  125. * Which named segment of the response to utilize
  126. * @var string
  127. */
  128. protected $_responseSegment = null;
  129. /**
  130. * Which action view script to render
  131. * @var string
  132. */
  133. protected $_scriptAction = null;
  134. /**
  135. * View object basePath
  136. * @var string
  137. */
  138. protected $_viewBasePathSpec = ':moduleDir/views';
  139. /**
  140. * View script path specification string
  141. * @var string
  142. */
  143. protected $_viewScriptPathSpec = ':controller/:action.:suffix';
  144. /**
  145. * View script path specification string, minus controller segment
  146. * @var string
  147. */
  148. protected $_viewScriptPathNoControllerSpec = ':action.:suffix';
  149. /**
  150. * View script suffix
  151. * @var string
  152. */
  153. protected $_viewSuffix = 'phtml';
  154. /**
  155. * Constructor
  156. *
  157. * Optionally set view object and options.
  158. *
  159. * @param Zend_View_Interface $view
  160. * @param array $options
  161. * @return void
  162. */
  163. public function __construct(Zend_View_Interface $view = null, array $options = array())
  164. {
  165. if (null !== $view) {
  166. $this->setView($view);
  167. }
  168. if (!empty($options)) {
  169. $this->_setOptions($options);
  170. }
  171. }
  172. /**
  173. * Clone - also make sure the view is cloned.
  174. *
  175. * @return void
  176. */
  177. public function __clone()
  178. {
  179. if (isset($this->view) && $this->view instanceof Zend_View_Interface) {
  180. $this->view = clone $this->view;
  181. }
  182. }
  183. /**
  184. * Set the view object
  185. *
  186. * @param Zend_View_Interface $view
  187. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  188. */
  189. public function setView(Zend_View_Interface $view)
  190. {
  191. $this->view = $view;
  192. return $this;
  193. }
  194. /**
  195. * Get current module name
  196. *
  197. * @return string
  198. */
  199. public function getModule()
  200. {
  201. $request = $this->getRequest();
  202. $module = $request->getModuleName();
  203. if (null === $module) {
  204. $module = $this->getFrontController()->getDispatcher()->getDefaultModule();
  205. }
  206. return $module;
  207. }
  208. /**
  209. * Get module directory
  210. *
  211. * @throws Zend_Controller_Action_Exception
  212. * @return string
  213. */
  214. public function getModuleDirectory()
  215. {
  216. $module = $this->getModule();
  217. $moduleDir = $this->getFrontController()->getControllerDirectory($module);
  218. if ((null === $moduleDir) || is_array($moduleDir)) {
  219. /**
  220. * @see Zend_Controller_Action_Exception
  221. */
  222. require_once 'Zend/Controller/Action/Exception.php';
  223. throw new Zend_Controller_Action_Exception('ViewRenderer cannot locate module directory for module "' . $module . '"');
  224. }
  225. $this->_moduleDir = dirname($moduleDir);
  226. return $this->_moduleDir;
  227. }
  228. /**
  229. * Get inflector
  230. *
  231. * @return Zend_Filter_Inflector
  232. */
  233. public function getInflector()
  234. {
  235. if (null === $this->_inflector) {
  236. /**
  237. * @see Zend_Filter_Inflector
  238. */
  239. require_once 'Zend/Filter/Inflector.php';
  240. /**
  241. * @see Zend_Filter_PregReplace
  242. */
  243. require_once 'Zend/Filter/PregReplace.php';
  244. /**
  245. * @see Zend_Filter_Word_UnderscoreToSeparator
  246. */
  247. require_once 'Zend/Filter/Word/UnderscoreToSeparator.php';
  248. $this->_inflector = new Zend_Filter_Inflector();
  249. $this->_inflector->setStaticRuleReference('moduleDir', $this->_moduleDir) // moduleDir must be specified before the less specific 'module'
  250. ->addRules(array(
  251. ':module' => array('Word_CamelCaseToDash', 'StringToLower'),
  252. ':controller' => array('Word_CamelCaseToDash', new Zend_Filter_Word_UnderscoreToSeparator('/'), 'StringToLower', new Zend_Filter_PregReplace('/\./', '-')),
  253. ':action' => array('Word_CamelCaseToDash', new Zend_Filter_PregReplace('#[^a-z0-9' . preg_quote('/', '#') . ']+#i', '-'), 'StringToLower'),
  254. ))
  255. ->setStaticRuleReference('suffix', $this->_viewSuffix)
  256. ->setTargetReference($this->_inflectorTarget);
  257. }
  258. // Ensure that module directory is current
  259. $this->getModuleDirectory();
  260. return $this->_inflector;
  261. }
  262. /**
  263. * Set inflector
  264. *
  265. * @param Zend_Filter_Inflector $inflector
  266. * @param boolean $reference Whether the moduleDir, target, and suffix should be set as references to ViewRenderer properties
  267. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  268. */
  269. public function setInflector(Zend_Filter_Inflector $inflector, $reference = false)
  270. {
  271. $this->_inflector = $inflector;
  272. if ($reference) {
  273. $this->_inflector->setStaticRuleReference('suffix', $this->_viewSuffix)
  274. ->setStaticRuleReference('moduleDir', $this->_moduleDir)
  275. ->setTargetReference($this->_inflectorTarget);
  276. }
  277. return $this;
  278. }
  279. /**
  280. * Set inflector target
  281. *
  282. * @param string $target
  283. * @return void
  284. */
  285. protected function _setInflectorTarget($target)
  286. {
  287. $this->_inflectorTarget = (string) $target;
  288. }
  289. /**
  290. * Set internal module directory representation
  291. *
  292. * @param string $dir
  293. * @return void
  294. */
  295. protected function _setModuleDir($dir)
  296. {
  297. $this->_moduleDir = (string) $dir;
  298. }
  299. /**
  300. * Get internal module directory representation
  301. *
  302. * @return string
  303. */
  304. protected function _getModuleDir()
  305. {
  306. return $this->_moduleDir;
  307. }
  308. /**
  309. * Generate a class prefix for helper and filter classes
  310. *
  311. * @return string
  312. */
  313. protected function _generateDefaultPrefix()
  314. {
  315. $default = 'Zend_View';
  316. if (null === $this->_actionController) {
  317. return $default;
  318. }
  319. $class = get_class($this->_actionController);
  320. if (!strstr($class, '_')) {
  321. return $default;
  322. }
  323. $module = $this->getModule();
  324. if ('default' == $module) {
  325. return $default;
  326. }
  327. $prefix = substr($class, 0, strpos($class, '_')) . '_View';
  328. return $prefix;
  329. }
  330. /**
  331. * Retrieve base path based on location of current action controller
  332. *
  333. * @return string
  334. */
  335. protected function _getBasePath()
  336. {
  337. if (null === $this->_actionController) {
  338. return './views';
  339. }
  340. $inflector = $this->getInflector();
  341. $this->_setInflectorTarget($this->getViewBasePathSpec());
  342. $dispatcher = $this->getFrontController()->getDispatcher();
  343. $request = $this->getRequest();
  344. $parts = array(
  345. 'module' => (($moduleName = $request->getModuleName()) != '') ? $dispatcher->formatModuleName($moduleName) : $moduleName,
  346. 'controller' => $request->getControllerName(),
  347. 'action' => $dispatcher->formatActionName($request->getActionName())
  348. );
  349. $path = $inflector->filter($parts);
  350. return $path;
  351. }
  352. /**
  353. * Set options
  354. *
  355. * @param array $options
  356. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  357. */
  358. protected function _setOptions(array $options)
  359. {
  360. foreach ($options as $key => $value)
  361. {
  362. switch ($key) {
  363. case 'neverRender':
  364. case 'neverController':
  365. case 'noController':
  366. case 'noRender':
  367. $property = '_' . $key;
  368. $this->{$property} = ($value) ? true : false;
  369. break;
  370. case 'responseSegment':
  371. case 'scriptAction':
  372. case 'viewBasePathSpec':
  373. case 'viewScriptPathSpec':
  374. case 'viewScriptPathNoControllerSpec':
  375. case 'viewSuffix':
  376. $property = '_' . $key;
  377. $this->{$property} = (string) $value;
  378. break;
  379. default:
  380. break;
  381. }
  382. }
  383. return $this;
  384. }
  385. /**
  386. * Initialize the view object
  387. *
  388. * $options may contain the following keys:
  389. * - neverRender - flag dis/enabling postDispatch() autorender (affects all subsequent calls)
  390. * - noController - flag indicating whether or not to look for view scripts in subdirectories named after the controller
  391. * - noRender - flag indicating whether or not to autorender postDispatch()
  392. * - responseSegment - which named response segment to render a view script to
  393. * - scriptAction - what action script to render
  394. * - viewBasePathSpec - specification to use for determining view base path
  395. * - viewScriptPathSpec - specification to use for determining view script paths
  396. * - viewScriptPathNoControllerSpec - specification to use for determining view script paths when noController flag is set
  397. * - viewSuffix - what view script filename suffix to use
  398. *
  399. * @param string $path
  400. * @param string $prefix
  401. * @param array $options
  402. * @throws Zend_Controller_Action_Exception
  403. * @return void
  404. */
  405. public function initView($path = null, $prefix = null, array $options = array())
  406. {
  407. if (null === $this->view) {
  408. $this->setView(new Zend_View());
  409. }
  410. // Reset some flags every time
  411. $options['noController'] = (isset($options['noController'])) ? $options['noController'] : false;
  412. $options['noRender'] = (isset($options['noRender'])) ? $options['noRender'] : false;
  413. $this->_scriptAction = null;
  414. $this->_responseSegment = null;
  415. // Set options first; may be used to determine other initializations
  416. $this->_setOptions($options);
  417. // Get base view path
  418. if (empty($path)) {
  419. $path = $this->_getBasePath();
  420. if (empty($path)) {
  421. /**
  422. * @see Zend_Controller_Action_Exception
  423. */
  424. require_once 'Zend/Controller/Action/Exception.php';
  425. throw new Zend_Controller_Action_Exception('ViewRenderer initialization failed: retrieved view base path is empty');
  426. }
  427. }
  428. if (null === $prefix) {
  429. $prefix = $this->_generateDefaultPrefix();
  430. }
  431. // Determine if this path has already been registered
  432. $currentPaths = $this->view->getScriptPaths();
  433. $path = str_replace(array('/', '\\'), '/', $path);
  434. $pathExists = false;
  435. foreach ($currentPaths as $tmpPath) {
  436. $tmpPath = str_replace(array('/', '\\'), '/', $tmpPath);
  437. if (strstr($tmpPath, $path)) {
  438. $pathExists = true;
  439. break;
  440. }
  441. }
  442. if (!$pathExists) {
  443. $this->view->addBasePath($path, $prefix);
  444. }
  445. // Register view with action controller (unless already registered)
  446. if ((null !== $this->_actionController) && (null === $this->_actionController->view)) {
  447. $this->_actionController->view = $this->view;
  448. $this->_actionController->viewSuffix = $this->_viewSuffix;
  449. }
  450. }
  451. /**
  452. * init - initialize view
  453. *
  454. * @return void
  455. */
  456. public function init()
  457. {
  458. if ($this->getFrontController()->getParam('noViewRenderer')) {
  459. return;
  460. }
  461. $this->initView();
  462. }
  463. /**
  464. * Set view basePath specification
  465. *
  466. * Specification can contain one or more of the following:
  467. * - :moduleDir - current module directory
  468. * - :controller - name of current controller in the request
  469. * - :action - name of current action in the request
  470. * - :module - name of current module in the request
  471. *
  472. * @param string $path
  473. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  474. */
  475. public function setViewBasePathSpec($path)
  476. {
  477. $this->_viewBasePathSpec = (string) $path;
  478. return $this;
  479. }
  480. /**
  481. * Retrieve the current view basePath specification string
  482. *
  483. * @return string
  484. */
  485. public function getViewBasePathSpec()
  486. {
  487. return $this->_viewBasePathSpec;
  488. }
  489. /**
  490. * Set view script path specification
  491. *
  492. * Specification can contain one or more of the following:
  493. * - :moduleDir - current module directory
  494. * - :controller - name of current controller in the request
  495. * - :action - name of current action in the request
  496. * - :module - name of current module in the request
  497. *
  498. * @param string $path
  499. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  500. */
  501. public function setViewScriptPathSpec($path)
  502. {
  503. $this->_viewScriptPathSpec = (string) $path;
  504. return $this;
  505. }
  506. /**
  507. * Retrieve the current view script path specification string
  508. *
  509. * @return string
  510. */
  511. public function getViewScriptPathSpec()
  512. {
  513. return $this->_viewScriptPathSpec;
  514. }
  515. /**
  516. * Set view script path specification (no controller variant)
  517. *
  518. * Specification can contain one or more of the following:
  519. * - :moduleDir - current module directory
  520. * - :controller - name of current controller in the request
  521. * - :action - name of current action in the request
  522. * - :module - name of current module in the request
  523. *
  524. * :controller will likely be ignored in this variant.
  525. *
  526. * @param string $path
  527. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  528. */
  529. public function setViewScriptPathNoControllerSpec($path)
  530. {
  531. $this->_viewScriptPathNoControllerSpec = (string) $path;
  532. return $this;
  533. }
  534. /**
  535. * Retrieve the current view script path specification string (no controller variant)
  536. *
  537. * @return string
  538. */
  539. public function getViewScriptPathNoControllerSpec()
  540. {
  541. return $this->_viewScriptPathNoControllerSpec;
  542. }
  543. /**
  544. * Get a view script based on an action and/or other variables
  545. *
  546. * Uses values found in current request if no values passed in $vars.
  547. *
  548. * If {@link $_noController} is set, uses {@link $_viewScriptPathNoControllerSpec};
  549. * otherwise, uses {@link $_viewScriptPathSpec}.
  550. *
  551. * @param string $action
  552. * @param array $vars
  553. * @return string
  554. */
  555. public function getViewScript($action = null, array $vars = array())
  556. {
  557. $request = $this->getRequest();
  558. if ((null === $action) && (!isset($vars['action']))) {
  559. $action = $this->getScriptAction();
  560. if (null === $action) {
  561. $action = $request->getActionName();
  562. }
  563. $vars['action'] = $action;
  564. } elseif (null !== $action) {
  565. $vars['action'] = $action;
  566. }
  567. $replacePattern = array('/[^a-z0-9]+$/i', '/^[^a-z0-9]+/i');
  568. $vars['action'] = preg_replace($replacePattern, '', $vars['action']);
  569. $inflector = $this->getInflector();
  570. if ($this->getNoController() || $this->getNeverController()) {
  571. $this->_setInflectorTarget($this->getViewScriptPathNoControllerSpec());
  572. } else {
  573. $this->_setInflectorTarget($this->getViewScriptPathSpec());
  574. }
  575. return $this->_translateSpec($vars);
  576. }
  577. /**
  578. * Set the neverRender flag (i.e., globally dis/enable autorendering)
  579. *
  580. * @param boolean $flag
  581. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  582. */
  583. public function setNeverRender($flag = true)
  584. {
  585. $this->_neverRender = ($flag) ? true : false;
  586. return $this;
  587. }
  588. /**
  589. * Retrieve neverRender flag value
  590. *
  591. * @return boolean
  592. */
  593. public function getNeverRender()
  594. {
  595. return $this->_neverRender;
  596. }
  597. /**
  598. * Set the noRender flag (i.e., whether or not to autorender)
  599. *
  600. * @param boolean $flag
  601. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  602. */
  603. public function setNoRender($flag = true)
  604. {
  605. $this->_noRender = ($flag) ? true : false;
  606. return $this;
  607. }
  608. /**
  609. * Retrieve noRender flag value
  610. *
  611. * @return boolean
  612. */
  613. public function getNoRender()
  614. {
  615. return $this->_noRender;
  616. }
  617. /**
  618. * Set the view script to use
  619. *
  620. * @param string $name
  621. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  622. */
  623. public function setScriptAction($name)
  624. {
  625. $this->_scriptAction = (string) $name;
  626. return $this;
  627. }
  628. /**
  629. * Retrieve view script name
  630. *
  631. * @return string
  632. */
  633. public function getScriptAction()
  634. {
  635. return $this->_scriptAction;
  636. }
  637. /**
  638. * Set the response segment name
  639. *
  640. * @param string $name
  641. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  642. */
  643. public function setResponseSegment($name)
  644. {
  645. if (null === $name) {
  646. $this->_responseSegment = null;
  647. } else {
  648. $this->_responseSegment = (string) $name;
  649. }
  650. return $this;
  651. }
  652. /**
  653. * Retrieve named response segment name
  654. *
  655. * @return string
  656. */
  657. public function getResponseSegment()
  658. {
  659. return $this->_responseSegment;
  660. }
  661. /**
  662. * Set the noController flag (i.e., whether or not to render into controller subdirectories)
  663. *
  664. * @param boolean $flag
  665. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  666. */
  667. public function setNoController($flag = true)
  668. {
  669. $this->_noController = ($flag) ? true : false;
  670. return $this;
  671. }
  672. /**
  673. * Retrieve noController flag value
  674. *
  675. * @return boolean
  676. */
  677. public function getNoController()
  678. {
  679. return $this->_noController;
  680. }
  681. /**
  682. * Set the neverController flag (i.e., whether or not to render into controller subdirectories)
  683. *
  684. * @param boolean $flag
  685. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  686. */
  687. public function setNeverController($flag = true)
  688. {
  689. $this->_neverController = ($flag) ? true : false;
  690. return $this;
  691. }
  692. /**
  693. * Retrieve neverController flag value
  694. *
  695. * @return boolean
  696. */
  697. public function getNeverController()
  698. {
  699. return $this->_neverController;
  700. }
  701. /**
  702. * Set view script suffix
  703. *
  704. * @param string $suffix
  705. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  706. */
  707. public function setViewSuffix($suffix)
  708. {
  709. $this->_viewSuffix = (string) $suffix;
  710. return $this;
  711. }
  712. /**
  713. * Get view script suffix
  714. *
  715. * @return string
  716. */
  717. public function getViewSuffix()
  718. {
  719. return $this->_viewSuffix;
  720. }
  721. /**
  722. * Set options for rendering a view script
  723. *
  724. * @param string $action View script to render
  725. * @param string $name Response named segment to render to
  726. * @param boolean $noController Whether or not to render within a subdirectory named after the controller
  727. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  728. */
  729. public function setRender($action = null, $name = null, $noController = null)
  730. {
  731. if (null !== $action) {
  732. $this->setScriptAction($action);
  733. }
  734. if (null !== $name) {
  735. $this->setResponseSegment($name);
  736. }
  737. if (null !== $noController) {
  738. $this->setNoController($noController);
  739. }
  740. return $this;
  741. }
  742. /**
  743. * Inflect based on provided vars
  744. *
  745. * Allowed variables are:
  746. * - :moduleDir - current module directory
  747. * - :module - current module name
  748. * - :controller - current controller name
  749. * - :action - current action name
  750. * - :suffix - view script file suffix
  751. *
  752. * @param array $vars
  753. * @return string
  754. */
  755. protected function _translateSpec(array $vars = array())
  756. {
  757. $inflector = $this->getInflector();
  758. $request = $this->getRequest();
  759. $dispatcher = $this->getFrontController()->getDispatcher();
  760. // Format module name
  761. $module = $dispatcher->formatModuleName($request->getModuleName());
  762. // Format controller name
  763. require_once 'Zend/Filter/Word/CamelCaseToDash.php';
  764. $filter = new Zend_Filter_Word_CamelCaseToDash();
  765. $controller = $filter->filter($request->getControllerName());
  766. $controller = $dispatcher->formatControllerName($controller);
  767. if ('Controller' == substr($controller, -10)) {
  768. $controller = substr($controller, 0, -10);
  769. }
  770. // Format action name
  771. $action = $dispatcher->formatActionName($request->getActionName());
  772. $params = compact('module', 'controller', 'action');
  773. foreach ($vars as $key => $value) {
  774. switch ($key) {
  775. case 'module':
  776. case 'controller':
  777. case 'action':
  778. case 'moduleDir':
  779. case 'suffix':
  780. $params[$key] = (string) $value;
  781. break;
  782. default:
  783. break;
  784. }
  785. }
  786. if (isset($params['suffix'])) {
  787. $origSuffix = $this->getViewSuffix();
  788. $this->setViewSuffix($params['suffix']);
  789. }
  790. if (isset($params['moduleDir'])) {
  791. $origModuleDir = $this->_getModuleDir();
  792. $this->_setModuleDir($params['moduleDir']);
  793. }
  794. $filtered = $inflector->filter($params);
  795. if (isset($params['suffix'])) {
  796. $this->setViewSuffix($origSuffix);
  797. }
  798. if (isset($params['moduleDir'])) {
  799. $this->_setModuleDir($origModuleDir);
  800. }
  801. return $filtered;
  802. }
  803. /**
  804. * Render a view script (optionally to a named response segment)
  805. *
  806. * Sets the noRender flag to true when called.
  807. *
  808. * @param string $script
  809. * @param string $name
  810. * @return void
  811. */
  812. public function renderScript($script, $name = null)
  813. {
  814. if (null === $name) {
  815. $name = $this->getResponseSegment();
  816. }
  817. $this->getResponse()->appendBody(
  818. $this->view->render($script),
  819. $name
  820. );
  821. $this->setNoRender();
  822. }
  823. /**
  824. * Render a view based on path specifications
  825. *
  826. * Renders a view based on the view script path specifications.
  827. *
  828. * @param string $action
  829. * @param string $name
  830. * @param boolean $noController
  831. * @return void
  832. */
  833. public function render($action = null, $name = null, $noController = null)
  834. {
  835. $this->setRender($action, $name, $noController);
  836. $path = $this->getViewScript();
  837. $this->renderScript($path, $name);
  838. }
  839. /**
  840. * Render a script based on specification variables
  841. *
  842. * Pass an action, and one or more specification variables (view script suffix)
  843. * to determine the view script path, and render that script.
  844. *
  845. * @param string $action
  846. * @param array $vars
  847. * @param string $name
  848. * @return void
  849. */
  850. public function renderBySpec($action = null, array $vars = array(), $name = null)
  851. {
  852. if (null !== $name) {
  853. $this->setResponseSegment($name);
  854. }
  855. $path = $this->getViewScript($action, $vars);
  856. $this->renderScript($path);
  857. }
  858. /**
  859. * postDispatch - auto render a view
  860. *
  861. * Only autorenders if:
  862. * - _noRender is false
  863. * - action controller is present
  864. * - request has not been re-dispatched (i.e., _forward() has not been called)
  865. * - response is not a redirect
  866. *
  867. * @return void
  868. */
  869. public function postDispatch()
  870. {
  871. if ($this->_shouldRender()) {
  872. $this->render();
  873. }
  874. }
  875. /**
  876. * Should the ViewRenderer render a view script?
  877. *
  878. * @return boolean
  879. */
  880. protected function _shouldRender()
  881. {
  882. return (!$this->getFrontController()->getParam('noViewRenderer')
  883. && !$this->_neverRender
  884. && !$this->_noRender
  885. && (null !== $this->_actionController)
  886. && $this->getRequest()->isDispatched()
  887. && !$this->getResponse()->isRedirect()
  888. );
  889. }
  890. /**
  891. * Use this helper as a method; proxies to setRender()
  892. *
  893. * @param string $action
  894. * @param string $name
  895. * @param boolean $noController
  896. * @return void
  897. */
  898. public function direct($action = null, $name = null, $noController = null)
  899. {
  900. $this->setRender($action, $name, $noController);
  901. }
  902. }