PageRenderTime 62ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/DevApp/library/Zend/Controller/Action/Helper/ContextSwitch.php

http://firephp.googlecode.com/
PHP | 1368 lines | 729 code | 143 blank | 496 comment | 111 complexity | b13e7f442243d2c8aa999e24b237bd4e MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, MIT, Apache-2.0
  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-2008 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: ContextSwitch.php 12316 2008-11-05 22:33:18Z sidhighwind $
  21. */
  22. /**
  23. * @see Zend_Controller_Action_Helper_Abstract
  24. */
  25. require_once 'Zend/Controller/Action/Helper/Abstract.php';
  26. /**
  27. * Simplify context switching based on requested format
  28. *
  29. * @uses Zend_Controller_Action_Helper_Abstract
  30. * @category Zend
  31. * @package Zend_Controller
  32. * @subpackage Zend_Controller_Action_Helper
  33. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  34. * @license http://framework.zend.com/license/new-bsd New BSD License
  35. */
  36. class Zend_Controller_Action_Helper_ContextSwitch extends Zend_Controller_Action_Helper_Abstract
  37. {
  38. /**
  39. * Trigger type constants
  40. */
  41. const TRIGGER_INIT = 'TRIGGER_INIT';
  42. const TRIGGER_POST = 'TRIGGER_POST';
  43. /**
  44. * Supported contexts
  45. * @var array
  46. */
  47. protected $_contexts = array();
  48. /**
  49. * JSON auto-serialization flag
  50. * @var boolean
  51. */
  52. protected $_autoJsonSerialization = true;
  53. /**
  54. * Controller property key to utilize for context switching
  55. * @var string
  56. */
  57. protected $_contextKey = 'contexts';
  58. /**
  59. * Request parameter containing requested context
  60. * @var string
  61. */
  62. protected $_contextParam = 'format';
  63. /**
  64. * Current context
  65. * @var string
  66. */
  67. protected $_currentContext;
  68. /**
  69. * Default context (xml)
  70. * @var string
  71. */
  72. protected $_defaultContext = 'xml';
  73. /**
  74. * Whether or not to disable layouts when switching contexts
  75. * @var boolean
  76. */
  77. protected $_disableLayout = true;
  78. /**
  79. * Methods that require special configuration
  80. * @var array
  81. */
  82. protected $_specialConfig = array(
  83. 'setSuffix',
  84. 'setHeaders',
  85. 'setCallbacks',
  86. );
  87. /**
  88. * Methods that are not configurable via setOptions and setConfig
  89. * @var array
  90. */
  91. protected $_unconfigurable = array(
  92. 'setOptions',
  93. 'setConfig',
  94. 'setHeader',
  95. 'setCallback',
  96. 'setContext',
  97. 'setActionContext',
  98. 'setActionContexts',
  99. );
  100. /**
  101. * @var Zend_Controller_Action_Helper_ViewRenderer
  102. */
  103. protected $_viewRenderer;
  104. /**
  105. * Constructor
  106. *
  107. * @param array|Zend_Config $options
  108. * @return void
  109. */
  110. public function __construct($options = null)
  111. {
  112. if ($options instanceof Zend_Config) {
  113. $this->setConfig($options);
  114. } elseif (is_array($options)) {
  115. $this->setOptions($options);
  116. }
  117. if (empty($this->_contexts)) {
  118. $this->addContexts(array(
  119. 'json' => array(
  120. 'suffix' => 'json',
  121. 'headers' => array('Content-Type' => 'application/json'),
  122. 'callbacks' => array(
  123. 'init' => 'initJsonContext',
  124. 'post' => 'postJsonContext'
  125. )
  126. ),
  127. 'xml' => array(
  128. 'suffix' => 'xml',
  129. 'headers' => array('Content-Type' => 'application/xml'),
  130. )
  131. ));
  132. }
  133. }
  134. /**
  135. * Configure object from array of options
  136. *
  137. * @param array $options
  138. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  139. */
  140. public function setOptions(array $options)
  141. {
  142. if (isset($options['contexts'])) {
  143. $this->setContexts($options['contexts']);
  144. unset($options['contexts']);
  145. }
  146. foreach ($options as $key => $value) {
  147. $method = 'set' . ucfirst($key);
  148. if (in_array($method, $this->_unconfigurable)) {
  149. continue;
  150. }
  151. if (in_array($method, $this->_specialConfig)) {
  152. $method = '_' . $method;
  153. }
  154. if (method_exists($this, $method)) {
  155. $this->$method($value);
  156. }
  157. }
  158. return $this;
  159. }
  160. /**
  161. * Set object state from config object
  162. *
  163. * @param Zend_Config $config
  164. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  165. */
  166. public function setConfig(Zend_Config $config)
  167. {
  168. return $this->setOptions($config->toArray());
  169. }
  170. /**
  171. * Strategy pattern: return object
  172. *
  173. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  174. */
  175. public function direct()
  176. {
  177. return $this;
  178. }
  179. /**
  180. * Initialize context detection and switching
  181. *
  182. * @param mixed $format
  183. * @throws Zend_Controller_Action_Exception
  184. * @return void
  185. */
  186. public function initContext($format = null)
  187. {
  188. $this->_currentContext = null;
  189. $controller = $this->getActionController();
  190. $request = $this->getRequest();
  191. $action = $request->getActionName();
  192. // Return if no context switching enabled, or no context switching
  193. // enabled for this action
  194. $contexts = $this->getActionContexts($action);
  195. if (empty($contexts)) {
  196. return;
  197. }
  198. // Return if no context parameter provided
  199. if (!$context = $request->getParam($this->getContextParam())) {
  200. if ($format === null) {
  201. return;
  202. }
  203. $context = $format;
  204. $format = null;
  205. }
  206. // Check if context allowed by action controller
  207. if (!$this->hasActionContext($action, $context)) {
  208. return;
  209. }
  210. // Return if invalid context parameter provided and no format or invalid
  211. // format provided
  212. if (!$this->hasContext($context)) {
  213. if (empty($format) || !$this->hasContext($format)) {
  214. return;
  215. }
  216. }
  217. // Use provided format if passed
  218. if (!empty($format) && $this->hasContext($format)) {
  219. $context = $format;
  220. }
  221. $suffix = $this->getSuffix($context);
  222. $this->_getViewRenderer()->setViewSuffix($suffix);
  223. $headers = $this->getHeaders($context);
  224. if (!empty($headers)) {
  225. $response = $this->getResponse();
  226. foreach ($headers as $header => $content) {
  227. $response->setHeader($header, $content);
  228. }
  229. }
  230. if ($this->getAutoDisableLayout()) {
  231. /**
  232. * @see Zend_Layout
  233. */
  234. require_once 'Zend/Layout.php';
  235. $layout = Zend_Layout::getMvcInstance();
  236. if (null !== $layout) {
  237. $layout->disableLayout();
  238. }
  239. }
  240. if (null !== ($callback = $this->getCallback($context, self::TRIGGER_INIT))) {
  241. if (is_string($callback) && method_exists($this, $callback)) {
  242. $this->$callback();
  243. } elseif (is_string($callback) && function_exists($callback)) {
  244. $callback();
  245. } elseif (is_array($callback)) {
  246. call_user_func($callback);
  247. } else {
  248. /**
  249. * @see Zend_Controller_Action_Exception
  250. */
  251. require_once 'Zend/Controller/Action/Exception.php';
  252. throw new Zend_Controller_Action_Exception(sprintf('Invalid context callback registered for context "%s"', $context));
  253. }
  254. }
  255. $this->_currentContext = $context;
  256. }
  257. /**
  258. * JSON context extra initialization
  259. *
  260. * Turns off viewRenderer auto-rendering
  261. *
  262. * @return void
  263. */
  264. public function initJsonContext()
  265. {
  266. if (!$this->getAutoJsonSerialization()) {
  267. return;
  268. }
  269. $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
  270. $view = $viewRenderer->view;
  271. if ($view instanceof Zend_View_Interface) {
  272. $viewRenderer->setNoRender(true);
  273. }
  274. }
  275. /**
  276. * Should JSON contexts auto-serialize?
  277. *
  278. * @param boolean $flag
  279. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  280. */
  281. public function setAutoJsonSerialization($flag)
  282. {
  283. $this->_autoJsonSerialization = (bool) $flag;
  284. return $this;
  285. }
  286. /**
  287. * Get JSON context auto-serialization flag
  288. *
  289. * @return boolean
  290. */
  291. public function getAutoJsonSerialization()
  292. {
  293. return $this->_autoJsonSerialization;
  294. }
  295. /**
  296. * Set suffix from array
  297. *
  298. * @param array $spec
  299. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  300. */
  301. protected function _setSuffix(array $spec)
  302. {
  303. foreach ($spec as $context => $suffixInfo) {
  304. if (!is_string($context)) {
  305. $context = null;
  306. }
  307. if (is_string($suffixInfo)) {
  308. $this->setSuffix($context, $suffixInfo);
  309. continue;
  310. } elseif (is_array($suffixInfo)) {
  311. if (isset($suffixInfo['suffix'])) {
  312. $suffix = $suffixInfo['suffix'];
  313. $prependViewRendererSuffix = true;
  314. if ((null === $context) && isset($suffixInfo['context'])) {
  315. $context = $suffixInfo['context'];
  316. }
  317. if (isset($suffixInfo['prependViewRendererSuffix'])) {
  318. $prependViewRendererSuffix = $suffixInfo['prependViewRendererSuffix'];
  319. }
  320. $this->setSuffix($context, $suffix, $prependViewRendererSuffix);
  321. continue;
  322. }
  323. $count = count($suffixInfo);
  324. switch (true) {
  325. case (($count < 2) && (null === $context)):
  326. /**
  327. * @see Zend_Controller_Action_Exception
  328. */
  329. require_once 'Zend/Controller/Action/Exception.php';
  330. throw new Zend_Controller_Action_Exception('Invalid suffix information provided in config');
  331. case ($count < 2):
  332. $suffix = array_shift($suffixInfo);
  333. $this->setSuffix($context, $suffix);
  334. break;
  335. case (($count < 3) && (null === $context)):
  336. $context = array_shift($suffixInfo);
  337. $suffix = array_shift($suffixInfo);
  338. $this->setSuffix($context, $suffix);
  339. break;
  340. case (($count == 3) && (null === $context)):
  341. $context = array_shift($suffixInfo);
  342. $suffix = array_shift($suffixInfo);
  343. $prependViewRendererSuffix = array_shift($suffixInfo);
  344. $this->setSuffix($context, $suffix, $prependViewRendererSuffix);
  345. break;
  346. case ($count >= 2):
  347. $suffix = array_shift($suffixInfo);
  348. $prependViewRendererSuffix = array_shift($suffixInfo);
  349. $this->setSuffix($context, $suffix, $prependViewRendererSuffix);
  350. break;
  351. }
  352. }
  353. }
  354. return $this;
  355. }
  356. /**
  357. * Customize view script suffix to use when switching context.
  358. *
  359. * Passing an empty suffix value to the setters disables the view script
  360. * suffix change.
  361. *
  362. * @param string $context Context type for which to set suffix
  363. * @param string $suffix Suffix to use
  364. * @param boolean $prependViewRendererSuffix Whether or not to prepend the new suffix to the viewrenderer suffix
  365. * @throws Zend_Controller_Action_Exception
  366. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  367. */
  368. public function setSuffix($context, $suffix, $prependViewRendererSuffix = true)
  369. {
  370. if (!isset($this->_contexts[$context])) {
  371. /**
  372. * @see Zend_Controller_Action_Exception
  373. */
  374. require_once 'Zend/Controller/Action/Exception.php';
  375. throw new Zend_Controller_Action_Exception(sprintf('Cannot set suffix; invalid context type "%s"', $context));
  376. }
  377. if (empty($suffix)) {
  378. $suffix = '';
  379. }
  380. if (is_array($suffix)) {
  381. if (isset($suffix['prependViewRendererSuffix'])) {
  382. $prependViewRendererSuffix = $suffix['prependViewRendererSuffix'];
  383. }
  384. if (isset($suffix['suffix'])) {
  385. $suffix = $suffix['suffix'];
  386. } else {
  387. $suffix = '';
  388. }
  389. }
  390. $suffix = (string) $suffix;
  391. if ($prependViewRendererSuffix) {
  392. if (empty($suffix)) {
  393. $suffix = $this->_getViewRenderer()->getViewSuffix();
  394. } else {
  395. $suffix .= '.' . $this->_getViewRenderer()->getViewSuffix();
  396. }
  397. }
  398. $this->_contexts[$context]['suffix'] = $suffix;
  399. return $this;
  400. }
  401. /**
  402. * Retrieve suffix for given context type
  403. *
  404. * @param string $type Context type
  405. * @throws Zend_Controller_Action_Exception
  406. * @return string
  407. */
  408. public function getSuffix($type)
  409. {
  410. if (!isset($this->_contexts[$type])) {
  411. /**
  412. * @see Zend_Controller_Action_Exception
  413. */
  414. require_once 'Zend/Controller/Action/Exception.php';
  415. throw new Zend_Controller_Action_Exception(sprintf('Cannot retrieve suffix; invalid context type "%s"', $type));
  416. }
  417. return $this->_contexts[$type]['suffix'];
  418. }
  419. /**
  420. * Does the given context exist?
  421. *
  422. * @param string $context
  423. * @param boolean $throwException
  424. * @throws Zend_Controller_Action_Exception if context does not exist and throwException is true
  425. * @return bool
  426. */
  427. public function hasContext($context, $throwException = false)
  428. {
  429. if (is_string($context)) {
  430. if (isset($this->_contexts[$context])) {
  431. return true;
  432. }
  433. } elseif (is_array($context)) {
  434. $error = false;
  435. foreach ($context as $test) {
  436. if (!isset($this->_contexts[$test])) {
  437. $error = (string) $test;
  438. break;
  439. }
  440. }
  441. if (false === $error) {
  442. return true;
  443. }
  444. $context = $error;
  445. } elseif (true === $context) {
  446. return true;
  447. }
  448. if ($throwException) {
  449. /**
  450. * @see Zend_Controller_Action_Exception
  451. */
  452. require_once 'Zend/Controller/Action/Exception.php';
  453. throw new Zend_Controller_Action_Exception(sprintf('Context "%s" does not exist', $context));
  454. }
  455. return false;
  456. }
  457. /**
  458. * Add header to context
  459. *
  460. * @param string $context
  461. * @param string $header
  462. * @param string $content
  463. * @throws Zend_Controller_Action_Exception
  464. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  465. */
  466. public function addHeader($context, $header, $content)
  467. {
  468. $context = (string) $context;
  469. $this->hasContext($context, true);
  470. $header = (string) $header;
  471. $content = (string) $content;
  472. if (isset($this->_contexts[$context]['headers'][$header])) {
  473. /**
  474. * @see Zend_Controller_Action_Exception
  475. */
  476. require_once 'Zend/Controller/Action/Exception.php';
  477. throw new Zend_Controller_Action_Exception(sprintf('Cannot add "%s" header to context "%s": already exists', $header, $context));
  478. }
  479. $this->_contexts[$context]['headers'][$header] = $content;
  480. return $this;
  481. }
  482. /**
  483. * Customize response header to use when switching context
  484. *
  485. * Passing an empty header value to the setters disables the response
  486. * header.
  487. *
  488. * @param string $type Context type for which to set suffix
  489. * @param string $header Header to set
  490. * @param string $content Header content
  491. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  492. */
  493. public function setHeader($context, $header, $content)
  494. {
  495. $this->hasContext($context, true);
  496. $context = (string) $context;
  497. $header = (string) $header;
  498. $content = (string) $content;
  499. $this->_contexts[$context]['headers'][$header] = $content;
  500. return $this;
  501. }
  502. /**
  503. * Add multiple headers at once for a given context
  504. *
  505. * @param string $context
  506. * @param array $headers
  507. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  508. */
  509. public function addHeaders($context, array $headers)
  510. {
  511. foreach ($headers as $header => $content) {
  512. $this->addHeader($context, $header, $content);
  513. }
  514. return $this;
  515. }
  516. /**
  517. * Set headers from context => headers pairs
  518. *
  519. * @param array $options
  520. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  521. */
  522. protected function _setHeaders(array $options)
  523. {
  524. foreach ($options as $context => $headers) {
  525. if (!is_array($headers)) {
  526. continue;
  527. }
  528. $this->setHeaders($context, $headers);
  529. }
  530. return $this;
  531. }
  532. /**
  533. * Set multiple headers at once for a given context
  534. *
  535. * @param string $context
  536. * @param array $headers
  537. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  538. */
  539. public function setHeaders($context, array $headers)
  540. {
  541. $this->clearHeaders($context);
  542. foreach ($headers as $header => $content) {
  543. $this->setHeader($context, $header, $content);
  544. }
  545. return $this;
  546. }
  547. /**
  548. * Retrieve context header
  549. *
  550. * Returns the value of a given header for a given context type
  551. *
  552. * @param string $context
  553. * @param string $header
  554. * @return string|null
  555. */
  556. public function getHeader($context, $header)
  557. {
  558. $this->hasContext($context, true);
  559. $context = (string) $context;
  560. $header = (string) $header;
  561. if (isset($this->_contexts[$context]['headers'][$header])) {
  562. return $this->_contexts[$context]['headers'][$header];
  563. }
  564. return null;
  565. }
  566. /**
  567. * Retrieve context headers
  568. *
  569. * Returns all headers for a context as key/value pairs
  570. *
  571. * @param string $context
  572. * @return array
  573. */
  574. public function getHeaders($context)
  575. {
  576. $this->hasContext($context, true);
  577. $context = (string) $context;
  578. return $this->_contexts[$context]['headers'];
  579. }
  580. /**
  581. * Remove a single header from a context
  582. *
  583. * @param string $context
  584. * @param string $header
  585. * @return boolean
  586. */
  587. public function removeHeader($context, $header)
  588. {
  589. $this->hasContext($context, true);
  590. $context = (string) $context;
  591. $header = (string) $header;
  592. if (isset($this->_contexts[$context]['headers'][$header])) {
  593. unset($this->_contexts[$context]['headers'][$header]);
  594. return true;
  595. }
  596. return false;
  597. }
  598. /**
  599. * Clear all headers for a given context
  600. *
  601. * @param string $context
  602. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  603. */
  604. public function clearHeaders($context)
  605. {
  606. $this->hasContext($context, true);
  607. $context = (string) $context;
  608. $this->_contexts[$context]['headers'] = array();
  609. return $this;
  610. }
  611. /**
  612. * Validate trigger and return in normalized form
  613. *
  614. * @param string $trigger
  615. * @throws Zend_Controller_Action_Exception
  616. * @return string
  617. */
  618. protected function _validateTrigger($trigger)
  619. {
  620. $trigger = strtoupper($trigger);
  621. if ('TRIGGER_' !== substr($trigger, 0, 8)) {
  622. $trigger = 'TRIGGER_' . $trigger;
  623. }
  624. if (!in_array($trigger, array(self::TRIGGER_INIT, self::TRIGGER_POST))) {
  625. /**
  626. * @see Zend_Controller_Action_Exception
  627. */
  628. require_once 'Zend/Controller/Action/Exception.php';
  629. throw new Zend_Controller_Action_Exception(sprintf('Invalid trigger "%s"', $trigger));
  630. }
  631. return $trigger;
  632. }
  633. /**
  634. * Set a callback for a given context and trigger
  635. *
  636. * @param string $context
  637. * @param string $trigger
  638. * @param string|array $callback
  639. * @throws Zend_Controller_Action_Exception
  640. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  641. */
  642. public function setCallback($context, $trigger, $callback)
  643. {
  644. $this->hasContext($context, true);
  645. $trigger = $this->_validateTrigger($trigger);
  646. if (!is_string($callback)) {
  647. if (!is_array($callback) || (2 != count($callback))) {
  648. /**
  649. * @see Zend_Controller_Action_Exception
  650. */
  651. require_once 'Zend/Controller/Action/Exception.php';
  652. throw new Zend_Controller_Action_Exception('Invalid callback specified');
  653. }
  654. }
  655. $this->_contexts[$context]['callbacks'][$trigger] = $callback;
  656. return $this;
  657. }
  658. /**
  659. * Set callbacks from array of context => callbacks pairs
  660. *
  661. * @param array $options
  662. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  663. */
  664. protected function _setCallbacks(array $options)
  665. {
  666. foreach ($options as $context => $callbacks) {
  667. if (!is_array($callbacks)) {
  668. continue;
  669. }
  670. $this->setCallbacks($context, $callbacks);
  671. }
  672. return $this;
  673. }
  674. /**
  675. * Set callbacks for a given context
  676. *
  677. * Callbacks should be in trigger/callback pairs.
  678. *
  679. * @param string $context
  680. * @param array $callbacks
  681. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  682. */
  683. public function setCallbacks($context, array $callbacks)
  684. {
  685. $this->hasContext($context, true);
  686. $context = (string) $context;
  687. if (!isset($this->_contexts[$context]['callbacks'])) {
  688. $this->_contexts[$context]['callbacks'] = array();
  689. }
  690. foreach ($callbacks as $trigger => $callback) {
  691. $this->setCallback($context, $trigger, $callback);
  692. }
  693. return $this;
  694. }
  695. /**
  696. * Get a single callback for a given context and trigger
  697. *
  698. * @param string $context
  699. * @param string $trigger
  700. * @return string|array|null
  701. */
  702. public function getCallback($context, $trigger)
  703. {
  704. $this->hasContext($context, true);
  705. $trigger = $this->_validateTrigger($trigger);
  706. if (isset($this->_contexts[$context]['callbacks'][$trigger])) {
  707. return $this->_contexts[$context]['callbacks'][$trigger];
  708. }
  709. return null;
  710. }
  711. /**
  712. * Get all callbacks for a given context
  713. *
  714. * @param string $context
  715. * @return array
  716. */
  717. public function getCallbacks($context)
  718. {
  719. $this->hasContext($context, true);
  720. return $this->_contexts[$context]['callbacks'];
  721. }
  722. /**
  723. * Clear a callback for a given context and trigger
  724. *
  725. * @param string $context
  726. * @param string $trigger
  727. * @return boolean
  728. */
  729. public function removeCallback($context, $trigger)
  730. {
  731. $this->hasContext($context, true);
  732. $trigger = $this->_validateTrigger($trigger);
  733. if (isset($this->_contexts[$context]['callbacks'][$trigger])) {
  734. unset($this->_contexts[$context]['callbacks'][$trigger]);
  735. return true;
  736. }
  737. return false;
  738. }
  739. /**
  740. * Clear all callbacks for a given context
  741. *
  742. * @param string $context
  743. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  744. */
  745. public function clearCallbacks($context)
  746. {
  747. $this->hasContext($context, true);
  748. $this->_contexts[$context]['callbacks'] = array();
  749. return $this;
  750. }
  751. /**
  752. * Set name of parameter to use when determining context format
  753. *
  754. * @param string $name
  755. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  756. */
  757. public function setContextParam($name)
  758. {
  759. $this->_contextParam = (string) $name;
  760. return $this;
  761. }
  762. /**
  763. * Return context format request parameter name
  764. *
  765. * @return string
  766. */
  767. public function getContextParam()
  768. {
  769. return $this->_contextParam;
  770. }
  771. /**
  772. * Indicate default context to use when no context format provided
  773. *
  774. * @param string $type
  775. * @throws Zend_Controller_Action_Exception
  776. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  777. */
  778. public function setDefaultContext($type)
  779. {
  780. if (!isset($this->_contexts[$type])) {
  781. /**
  782. * @see Zend_Controller_Action_Exception
  783. */
  784. require_once 'Zend/Controller/Action/Exception.php';
  785. throw new Zend_Controller_Action_Exception(sprintf('Cannot set default context; invalid context type "%s"', $type));
  786. }
  787. $this->_defaultContext = $type;
  788. return $this;
  789. }
  790. /**
  791. * Return default context
  792. *
  793. * @return string
  794. */
  795. public function getDefaultContext()
  796. {
  797. return $this->_defaultContext;
  798. }
  799. /**
  800. * Set flag indicating if layout should be disabled
  801. *
  802. * @param boolean $flag
  803. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  804. */
  805. public function setAutoDisableLayout($flag)
  806. {
  807. $this->_disableLayout = ($flag) ? true : false;
  808. return $this;
  809. }
  810. /**
  811. * Retrieve auto layout disable flag
  812. *
  813. * @return boolean
  814. */
  815. public function getAutoDisableLayout()
  816. {
  817. return $this->_disableLayout;
  818. }
  819. /**
  820. * Add new context
  821. *
  822. * @param string $context Context type
  823. * @param array $spec Context specification
  824. * @throws Zend_Controller_Action_Exception
  825. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  826. */
  827. public function addContext($context, array $spec)
  828. {
  829. if ($this->hasContext($context)) {
  830. /**
  831. * @see Zend_Controller_Action_Exception
  832. */
  833. require_once 'Zend/Controller/Action/Exception.php';
  834. throw new Zend_Controller_Action_Exception(sprintf('Cannot add context "%s"; already exists', $context));
  835. }
  836. $context = (string) $context;
  837. $this->_contexts[$context] = array();
  838. $this->setSuffix($context, (isset($spec['suffix']) ? $spec['suffix'] : ''))
  839. ->setHeaders($context, (isset($spec['headers']) ? $spec['headers'] : array()))
  840. ->setCallbacks($context, (isset($spec['callbacks']) ? $spec['callbacks'] : array()));
  841. return $this;
  842. }
  843. /**
  844. * Overwrite existing context
  845. *
  846. * @param string $context Context type
  847. * @param array $spec Context specification
  848. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  849. */
  850. public function setContext($context, array $spec)
  851. {
  852. $this->removeContext($context);
  853. return $this->addContext($context, $spec);
  854. }
  855. /**
  856. * Add multiple contexts
  857. *
  858. * @param array $contexts
  859. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  860. */
  861. public function addContexts(array $contexts)
  862. {
  863. foreach ($contexts as $context => $spec) {
  864. $this->addContext($context, $spec);
  865. }
  866. return $this;
  867. }
  868. /**
  869. * Set multiple contexts, after first removing all
  870. *
  871. * @param array $contexts
  872. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  873. */
  874. public function setContexts(array $contexts)
  875. {
  876. $this->clearContexts();
  877. foreach ($contexts as $context => $spec) {
  878. $this->addContext($context, $spec);
  879. }
  880. return $this;
  881. }
  882. /**
  883. * Retrieve context specification
  884. *
  885. * @param string $context
  886. * @return array|null
  887. */
  888. public function getContext($context)
  889. {
  890. if ($this->hasContext($context)) {
  891. return $this->_contexts[(string) $context];
  892. }
  893. return null;
  894. }
  895. /**
  896. * Retrieve context definitions
  897. *
  898. * @return array
  899. */
  900. public function getContexts()
  901. {
  902. return $this->_contexts;
  903. }
  904. /**
  905. * Remove a context
  906. *
  907. * @param string $context
  908. * @return boolean
  909. */
  910. public function removeContext($context)
  911. {
  912. if ($this->hasContext($context)) {
  913. unset($this->_contexts[(string) $context]);
  914. return true;
  915. }
  916. return false;
  917. }
  918. /**
  919. * Remove all contexts
  920. *
  921. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  922. */
  923. public function clearContexts()
  924. {
  925. $this->_contexts = array();
  926. return $this;
  927. }
  928. /**
  929. * Return current context, if any
  930. *
  931. * @return null|string
  932. */
  933. public function getCurrentContext()
  934. {
  935. return $this->_currentContext;
  936. }
  937. /**
  938. * Post dispatch processing
  939. *
  940. * Execute postDispatch callback for current context, if available
  941. *
  942. * @throws Zend_Controller_Action_Exception
  943. * @return void
  944. */
  945. public function postDispatch()
  946. {
  947. $context = $this->getCurrentContext();
  948. if (null !== $context) {
  949. if (null !== ($callback = $this->getCallback($context, self::TRIGGER_POST))) {
  950. if (is_string($callback) && method_exists($this, $callback)) {
  951. $this->$callback();
  952. } elseif (is_string($callback) && function_exists($callback)) {
  953. $callback();
  954. } elseif (is_array($callback)) {
  955. call_user_func($callback);
  956. } else {
  957. /**
  958. * @see Zend_Controller_Action_Exception
  959. */
  960. require_once 'Zend/Controller/Action/Exception.php';
  961. throw new Zend_Controller_Action_Exception(sprintf('Invalid postDispatch context callback registered for context "%s"', $context));
  962. }
  963. }
  964. }
  965. }
  966. /**
  967. * JSON post processing
  968. *
  969. * JSON serialize view variables to response body
  970. *
  971. * @return void
  972. */
  973. public function postJsonContext()
  974. {
  975. if (!$this->getAutoJsonSerialization()) {
  976. return;
  977. }
  978. $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
  979. $view = $viewRenderer->view;
  980. if ($view instanceof Zend_View_Interface) {
  981. /**
  982. * @see Zend_Json
  983. */
  984. if(method_exists($view, 'getVars')) {
  985. require_once 'Zend/Json.php';
  986. $vars = Zend_Json::encode($view->getVars());
  987. $this->getResponse()->setBody($vars);
  988. } else {
  989. require_once 'Zend/Controller/Action/Exception.php';
  990. throw new Zend_Controller_Action_Exception('View does not implement the getVars() method needed to encode the view into JSON');
  991. }
  992. }
  993. }
  994. /**
  995. * Add one or more contexts to an action
  996. *
  997. * @param string $action
  998. * @param string|array $context
  999. * @return Zend_Controller_Action_Helper_ContextSwitch|void Provides a fluent interface
  1000. */
  1001. public function addActionContext($action, $context)
  1002. {
  1003. $this->hasContext($context, true);
  1004. $controller = $this->getActionController();
  1005. if (null === $controller) {
  1006. return;
  1007. }
  1008. $action = (string) $action;
  1009. $contextKey = $this->_contextKey;
  1010. if (!isset($controller->$contextKey)) {
  1011. $controller->$contextKey = array();
  1012. }
  1013. if (true === $context) {
  1014. $contexts = $this->getContexts();
  1015. $controller->{$contextKey}[$action] = array_keys($contexts);
  1016. return $this;
  1017. }
  1018. $context = (array) $context;
  1019. if (!isset($controller->{$contextKey}[$action])) {
  1020. $controller->{$contextKey}[$action] = $context;
  1021. } else {
  1022. $controller->{$contextKey}[$action] = array_merge(
  1023. $controller->{$contextKey}[$action],
  1024. $context
  1025. );
  1026. }
  1027. return $this;
  1028. }
  1029. /**
  1030. * Set a context as available for a given controller action
  1031. *
  1032. * @param string $action
  1033. * @param string|array $context
  1034. * @return Zend_Controller_Action_Helper_ContextSwitch|void Provides a fluent interface
  1035. */
  1036. public function setActionContext($action, $context)
  1037. {
  1038. $this->hasContext($context, true);
  1039. $controller = $this->getActionController();
  1040. if (null === $controller) {
  1041. return;
  1042. }
  1043. $action = (string) $action;
  1044. $contextKey = $this->_contextKey;
  1045. if (!isset($controller->$contextKey)) {
  1046. $controller->$contextKey = array();
  1047. }
  1048. if (true === $context) {
  1049. $contexts = $this->getContexts();
  1050. $controller->{$contextKey}[$action] = array_keys($contexts);
  1051. } else {
  1052. $controller->{$contextKey}[$action] = (array) $context;
  1053. }
  1054. return $this;
  1055. }
  1056. /**
  1057. * Add multiple action/context pairs at once
  1058. *
  1059. * @param array $contexts
  1060. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  1061. */
  1062. public function addActionContexts(array $contexts)
  1063. {
  1064. foreach ($contexts as $action => $context) {
  1065. $this->addActionContext($action, $context);
  1066. }
  1067. return $this;
  1068. }
  1069. /**
  1070. * Overwrite and set multiple action contexts at once
  1071. *
  1072. * @param array $contexts
  1073. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  1074. */
  1075. public function setActionContexts(array $contexts)
  1076. {
  1077. foreach ($contexts as $action => $context) {
  1078. $this->setActionContext($action, $context);
  1079. }
  1080. return $this;
  1081. }
  1082. /**
  1083. * Does a particular controller action have the given context(s)?
  1084. *
  1085. * @param string $action
  1086. * @param string|array $context
  1087. * @throws Zend_Controller_Action_Exception
  1088. * @return boolean
  1089. */
  1090. public function hasActionContext($action, $context)
  1091. {
  1092. $this->hasContext($context, true);
  1093. $controller = $this->getActionController();
  1094. if (null === $controller) {
  1095. return false;
  1096. }
  1097. $action = (string) $action;
  1098. $contextKey = $this->_contextKey;
  1099. if (!isset($controller->{$contextKey})) {
  1100. return false;
  1101. }
  1102. $allContexts = $controller->{$contextKey};
  1103. if (!is_array($allContexts)) {
  1104. /**
  1105. * @see Zend_Controller_Action_Exception
  1106. */
  1107. require_once 'Zend/Controller/Action/Exception.php';
  1108. throw new Zend_Controller_Action_Exception("Invalid contexts found for controller");
  1109. }
  1110. if (!isset($allContexts[$action])) {
  1111. return false;
  1112. }
  1113. if (true === $allContexts[$action]) {
  1114. return true;
  1115. }
  1116. $contexts = $allContexts[$action];
  1117. if (!is_array($contexts)) {
  1118. /**
  1119. * @see Zend_Controller_Action_Exception
  1120. */
  1121. require_once 'Zend/Controller/Action/Exception.php';
  1122. throw new Zend_Controller_Action_Exception(sprintf("Invalid contexts found for action '%s'", $action));
  1123. }
  1124. if (is_string($context) && in_array($context, $contexts)) {
  1125. return true;
  1126. } elseif (is_array($context)) {
  1127. $found = true;
  1128. foreach ($context as $test) {
  1129. if (!in_array($test, $contexts)) {
  1130. $found = false;
  1131. break;
  1132. }
  1133. }
  1134. return $found;
  1135. }
  1136. return false;
  1137. }
  1138. /**
  1139. * Get contexts for a given action or all actions in the controller
  1140. *
  1141. * @param string $action
  1142. * @return array
  1143. */
  1144. public function getActionContexts($action = null)
  1145. {
  1146. $controller = $this->getActionController();
  1147. if (null === $controller) {
  1148. return array();
  1149. }
  1150. $action = (string) $action;
  1151. $contextKey = $this->_contextKey;
  1152. if (!isset($controller->$contextKey)) {
  1153. return array();
  1154. }
  1155. if (null !== $action) {
  1156. if (isset($controller->{$contextKey}[$action])) {
  1157. return $controller->{$contextKey}[$action];
  1158. } else {
  1159. return array();
  1160. }
  1161. }
  1162. return $controller->$contextKey;
  1163. }
  1164. /**
  1165. * Remove one or more contexts for a given controller action
  1166. *
  1167. * @param string $action
  1168. * @param string|array $context
  1169. * @return boolean
  1170. */
  1171. public function removeActionContext($action, $context)
  1172. {
  1173. if ($this->hasActionContext($action, $context)) {
  1174. $controller = $this->getActionController();
  1175. $contextKey = $this->_contextKey;
  1176. $action = (string) $action;
  1177. $contexts = $controller->$contextKey;
  1178. $actionContexts = $contexts[$action];
  1179. $contexts = (array) $context;
  1180. foreach ($contexts as $context) {
  1181. $index = array_search($context, $actionContexts);
  1182. if (false !== $index) {
  1183. unset($controller->{$contextKey}[$action][$index]);
  1184. }
  1185. }
  1186. return true;
  1187. }
  1188. return false;
  1189. }
  1190. /**
  1191. * Clear all contexts for a given controller action or all actions
  1192. *
  1193. * @param string $action
  1194. * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
  1195. */
  1196. public function clearActionContexts($action = null)
  1197. {
  1198. $controller = $this->getActionController();
  1199. $contextKey = $this->_contextKey;
  1200. if (!isset($controller->$contextKey) || empty($controller->$contextKey)) {
  1201. return $this;
  1202. }
  1203. if (null === $action) {
  1204. $controller->$contextKey = array();
  1205. return $this;
  1206. }
  1207. $action = (string) $action;
  1208. if (isset($controller->{$contextKey}[$action])) {
  1209. unset($controller->{$contextKey}[$action]);
  1210. }
  1211. return $this;
  1212. }
  1213. /**
  1214. * Retrieve ViewRenderer
  1215. *
  1216. * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
  1217. */
  1218. protected function _getViewRenderer()
  1219. {
  1220. if (null === $this->_viewRenderer) {
  1221. $this->_viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
  1222. }
  1223. return $this->_viewRenderer;
  1224. }
  1225. }