PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/src/frapi/library/Zend/Controller/Action/Helper/ContextSwitch.php

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