File indexing completed on 2025-01-26 05:24:53
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Controller 0017 * @subpackage Zend_Controller_Action_Helper 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** 0024 * @see Zend_Controller_Action_Helper_Abstract 0025 */ 0026 // require_once 'Zend/Controller/Action/Helper/Abstract.php'; 0027 0028 /** 0029 * Simplify context switching based on requested format 0030 * 0031 * @uses Zend_Controller_Action_Helper_Abstract 0032 * @category Zend 0033 * @package Zend_Controller 0034 * @subpackage Zend_Controller_Action_Helper 0035 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0036 * @license http://framework.zend.com/license/new-bsd New BSD License 0037 */ 0038 class Zend_Controller_Action_Helper_ContextSwitch extends Zend_Controller_Action_Helper_Abstract 0039 { 0040 /** 0041 * Trigger type constants 0042 */ 0043 const TRIGGER_INIT = 'TRIGGER_INIT'; 0044 const TRIGGER_POST = 'TRIGGER_POST'; 0045 0046 /** 0047 * Supported contexts 0048 * @var array 0049 */ 0050 protected $_contexts = array(); 0051 0052 /** 0053 * JSON auto-serialization flag 0054 * @var boolean 0055 */ 0056 protected $_autoJsonSerialization = true; 0057 0058 /** 0059 * Controller property key to utilize for context switching 0060 * @var string 0061 */ 0062 protected $_contextKey = 'contexts'; 0063 0064 /** 0065 * Request parameter containing requested context 0066 * @var string 0067 */ 0068 protected $_contextParam = 'format'; 0069 0070 /** 0071 * Current context 0072 * @var string 0073 */ 0074 protected $_currentContext; 0075 0076 /** 0077 * Default context (xml) 0078 * @var string 0079 */ 0080 protected $_defaultContext = 'xml'; 0081 0082 /** 0083 * Whether or not to disable layouts when switching contexts 0084 * @var boolean 0085 */ 0086 protected $_disableLayout = true; 0087 0088 /** 0089 * Methods that require special configuration 0090 * @var array 0091 */ 0092 protected $_specialConfig = array( 0093 'setSuffix', 0094 'setHeaders', 0095 'setCallbacks', 0096 ); 0097 0098 /** 0099 * Methods that are not configurable via setOptions and setConfig 0100 * @var array 0101 */ 0102 protected $_unconfigurable = array( 0103 'setOptions', 0104 'setConfig', 0105 'setHeader', 0106 'setCallback', 0107 'setContext', 0108 'setActionContext', 0109 'setActionContexts', 0110 ); 0111 0112 /** 0113 * @var Zend_Controller_Action_Helper_ViewRenderer 0114 */ 0115 protected $_viewRenderer; 0116 0117 /** 0118 * Original view suffix prior to detecting context switch 0119 * @var string 0120 */ 0121 protected $_viewSuffixOrig; 0122 0123 /** 0124 * Constructor 0125 * 0126 * @param array|Zend_Config $options 0127 * @return void 0128 */ 0129 public function __construct($options = null) 0130 { 0131 if ($options instanceof Zend_Config) { 0132 $this->setConfig($options); 0133 } elseif (is_array($options)) { 0134 $this->setOptions($options); 0135 } 0136 0137 if (empty($this->_contexts)) { 0138 $this->addContexts(array( 0139 'json' => array( 0140 'suffix' => 'json', 0141 'headers' => array('Content-Type' => 'application/json'), 0142 'callbacks' => array( 0143 'init' => 'initJsonContext', 0144 'post' => 'postJsonContext' 0145 ) 0146 ), 0147 'xml' => array( 0148 'suffix' => 'xml', 0149 'headers' => array('Content-Type' => 'application/xml'), 0150 ) 0151 )); 0152 } 0153 0154 $this->init(); 0155 } 0156 0157 /** 0158 * Initialize at start of action controller 0159 * 0160 * Reset the view script suffix to the original state, or store the 0161 * original state. 0162 * 0163 * @return void 0164 */ 0165 public function init() 0166 { 0167 if (null === $this->_viewSuffixOrig) { 0168 $this->_viewSuffixOrig = $this->_getViewRenderer()->getViewSuffix(); 0169 } else { 0170 $this->_getViewRenderer()->setViewSuffix($this->_viewSuffixOrig); 0171 } 0172 } 0173 0174 /** 0175 * Configure object from array of options 0176 * 0177 * @param array $options 0178 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0179 */ 0180 public function setOptions(array $options) 0181 { 0182 if (isset($options['contexts'])) { 0183 $this->setContexts($options['contexts']); 0184 unset($options['contexts']); 0185 } 0186 0187 foreach ($options as $key => $value) { 0188 $method = 'set' . ucfirst($key); 0189 if (in_array($method, $this->_unconfigurable)) { 0190 continue; 0191 } 0192 0193 if (in_array($method, $this->_specialConfig)) { 0194 $method = '_' . $method; 0195 } 0196 0197 if (method_exists($this, $method)) { 0198 $this->$method($value); 0199 } 0200 } 0201 return $this; 0202 } 0203 0204 /** 0205 * Set object state from config object 0206 * 0207 * @param Zend_Config $config 0208 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0209 */ 0210 public function setConfig(Zend_Config $config) 0211 { 0212 return $this->setOptions($config->toArray()); 0213 } 0214 0215 /** 0216 * Strategy pattern: return object 0217 * 0218 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0219 */ 0220 public function direct() 0221 { 0222 return $this; 0223 } 0224 0225 /** 0226 * Initialize context detection and switching 0227 * 0228 * @param mixed $format 0229 * @throws Zend_Controller_Action_Exception 0230 * @return void 0231 */ 0232 public function initContext($format = null) 0233 { 0234 $this->_currentContext = null; 0235 0236 $controller = $this->getActionController(); 0237 $request = $this->getRequest(); 0238 $action = $request->getActionName(); 0239 0240 // Return if no context switching enabled, or no context switching 0241 // enabled for this action 0242 $contexts = $this->getActionContexts($action); 0243 if (empty($contexts)) { 0244 return; 0245 } 0246 0247 // Return if no context parameter provided 0248 if (!$context = $request->getParam($this->getContextParam())) { 0249 if ($format === null) { 0250 return; 0251 } 0252 $context = $format; 0253 $format = null; 0254 } 0255 0256 // Check if context allowed by action controller 0257 if (!$this->hasActionContext($action, $context)) { 0258 return; 0259 } 0260 0261 // Return if invalid context parameter provided and no format or invalid 0262 // format provided 0263 if (!$this->hasContext($context)) { 0264 if (empty($format) || !$this->hasContext($format)) { 0265 0266 return; 0267 } 0268 } 0269 0270 // Use provided format if passed 0271 if (!empty($format) && $this->hasContext($format)) { 0272 $context = $format; 0273 } 0274 0275 $suffix = $this->getSuffix($context); 0276 0277 $this->_getViewRenderer()->setViewSuffix($suffix); 0278 0279 $headers = $this->getHeaders($context); 0280 if (!empty($headers)) { 0281 $response = $this->getResponse(); 0282 foreach ($headers as $header => $content) { 0283 $response->setHeader($header, $content); 0284 } 0285 } 0286 0287 if ($this->getAutoDisableLayout()) { 0288 /** 0289 * @see Zend_Layout 0290 */ 0291 // require_once 'Zend/Layout.php'; 0292 $layout = Zend_Layout::getMvcInstance(); 0293 if (null !== $layout) { 0294 $layout->disableLayout(); 0295 } 0296 } 0297 0298 if (null !== ($callback = $this->getCallback($context, self::TRIGGER_INIT))) { 0299 if (is_string($callback) && method_exists($this, $callback)) { 0300 $this->$callback(); 0301 } elseif (is_string($callback) && function_exists($callback)) { 0302 $callback(); 0303 } elseif (is_array($callback)) { 0304 call_user_func($callback); 0305 } else { 0306 /** 0307 * @see Zend_Controller_Action_Exception 0308 */ 0309 // require_once 'Zend/Controller/Action/Exception.php'; 0310 throw new Zend_Controller_Action_Exception(sprintf('Invalid context callback registered for context "%s"', $context)); 0311 } 0312 } 0313 0314 $this->_currentContext = $context; 0315 } 0316 0317 /** 0318 * JSON context extra initialization 0319 * 0320 * Turns off viewRenderer auto-rendering 0321 * 0322 * @return void 0323 */ 0324 public function initJsonContext() 0325 { 0326 if (!$this->getAutoJsonSerialization()) { 0327 return; 0328 } 0329 0330 $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); 0331 $view = $viewRenderer->view; 0332 if ($view instanceof Zend_View_Interface) { 0333 $viewRenderer->setNoRender(true); 0334 } 0335 } 0336 0337 /** 0338 * Should JSON contexts auto-serialize? 0339 * 0340 * @param boolean $flag 0341 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0342 */ 0343 public function setAutoJsonSerialization($flag) 0344 { 0345 $this->_autoJsonSerialization = (bool) $flag; 0346 return $this; 0347 } 0348 0349 /** 0350 * Get JSON context auto-serialization flag 0351 * 0352 * @return boolean 0353 */ 0354 public function getAutoJsonSerialization() 0355 { 0356 return $this->_autoJsonSerialization; 0357 } 0358 0359 /** 0360 * Set suffix from array 0361 * 0362 * @param array $spec 0363 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0364 */ 0365 protected function _setSuffix(array $spec) 0366 { 0367 foreach ($spec as $context => $suffixInfo) { 0368 if (!is_string($context)) { 0369 $context = null; 0370 } 0371 0372 if (is_string($suffixInfo)) { 0373 $this->setSuffix($context, $suffixInfo); 0374 continue; 0375 } elseif (is_array($suffixInfo)) { 0376 if (isset($suffixInfo['suffix'])) { 0377 $suffix = $suffixInfo['suffix']; 0378 $prependViewRendererSuffix = true; 0379 0380 if ((null === $context) && isset($suffixInfo['context'])) { 0381 $context = $suffixInfo['context']; 0382 } 0383 0384 if (isset($suffixInfo['prependViewRendererSuffix'])) { 0385 $prependViewRendererSuffix = $suffixInfo['prependViewRendererSuffix']; 0386 } 0387 0388 $this->setSuffix($context, $suffix, $prependViewRendererSuffix); 0389 continue; 0390 } 0391 0392 $count = count($suffixInfo); 0393 switch (true) { 0394 case (($count < 2) && (null === $context)): 0395 /** 0396 * @see Zend_Controller_Action_Exception 0397 */ 0398 // require_once 'Zend/Controller/Action/Exception.php'; 0399 throw new Zend_Controller_Action_Exception('Invalid suffix information provided in config'); 0400 case ($count < 2): 0401 $suffix = array_shift($suffixInfo); 0402 $this->setSuffix($context, $suffix); 0403 break; 0404 case (($count < 3) && (null === $context)): 0405 $context = array_shift($suffixInfo); 0406 $suffix = array_shift($suffixInfo); 0407 $this->setSuffix($context, $suffix); 0408 break; 0409 case (($count == 3) && (null === $context)): 0410 $context = array_shift($suffixInfo); 0411 $suffix = array_shift($suffixInfo); 0412 $prependViewRendererSuffix = array_shift($suffixInfo); 0413 $this->setSuffix($context, $suffix, $prependViewRendererSuffix); 0414 break; 0415 case ($count >= 2): 0416 $suffix = array_shift($suffixInfo); 0417 $prependViewRendererSuffix = array_shift($suffixInfo); 0418 $this->setSuffix($context, $suffix, $prependViewRendererSuffix); 0419 break; 0420 } 0421 } 0422 } 0423 return $this; 0424 } 0425 0426 /** 0427 * Customize view script suffix to use when switching context. 0428 * 0429 * Passing an empty suffix value to the setters disables the view script 0430 * suffix change. 0431 * 0432 * @param string $context Context type for which to set suffix 0433 * @param string $suffix Suffix to use 0434 * @param boolean $prependViewRendererSuffix Whether or not to prepend the new suffix to the viewrenderer suffix 0435 * @throws Zend_Controller_Action_Exception 0436 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0437 */ 0438 public function setSuffix($context, $suffix, $prependViewRendererSuffix = true) 0439 { 0440 if (!isset($this->_contexts[$context])) { 0441 /** 0442 * @see Zend_Controller_Action_Exception 0443 */ 0444 // require_once 'Zend/Controller/Action/Exception.php'; 0445 throw new Zend_Controller_Action_Exception(sprintf('Cannot set suffix; invalid context type "%s"', $context)); 0446 } 0447 0448 if (empty($suffix)) { 0449 $suffix = ''; 0450 } 0451 0452 if (is_array($suffix)) { 0453 if (isset($suffix['prependViewRendererSuffix'])) { 0454 $prependViewRendererSuffix = $suffix['prependViewRendererSuffix']; 0455 } 0456 if (isset($suffix['suffix'])) { 0457 $suffix = $suffix['suffix']; 0458 } else { 0459 $suffix = ''; 0460 } 0461 } 0462 0463 $suffix = (string) $suffix; 0464 0465 if ($prependViewRendererSuffix) { 0466 if (empty($suffix)) { 0467 $suffix = $this->_getViewRenderer()->getViewSuffix(); 0468 } else { 0469 $suffix .= '.' . $this->_getViewRenderer()->getViewSuffix(); 0470 } 0471 } 0472 0473 $this->_contexts[$context]['suffix'] = $suffix; 0474 return $this; 0475 } 0476 0477 /** 0478 * Retrieve suffix for given context type 0479 * 0480 * @param string $type Context type 0481 * @throws Zend_Controller_Action_Exception 0482 * @return string 0483 */ 0484 public function getSuffix($type) 0485 { 0486 if (!isset($this->_contexts[$type])) { 0487 /** 0488 * @see Zend_Controller_Action_Exception 0489 */ 0490 // require_once 'Zend/Controller/Action/Exception.php'; 0491 throw new Zend_Controller_Action_Exception(sprintf('Cannot retrieve suffix; invalid context type "%s"', $type)); 0492 } 0493 0494 return $this->_contexts[$type]['suffix']; 0495 } 0496 0497 /** 0498 * Does the given context exist? 0499 * 0500 * @param string $context 0501 * @param boolean $throwException 0502 * @throws Zend_Controller_Action_Exception if context does not exist and throwException is true 0503 * @return bool 0504 */ 0505 public function hasContext($context, $throwException = false) 0506 { 0507 if (is_string($context)) { 0508 if (isset($this->_contexts[$context])) { 0509 return true; 0510 } 0511 } elseif (is_array($context)) { 0512 $error = false; 0513 foreach ($context as $test) { 0514 if (!isset($this->_contexts[$test])) { 0515 $error = (string) $test; 0516 break; 0517 } 0518 } 0519 if (false === $error) { 0520 return true; 0521 } 0522 $context = $error; 0523 } elseif (true === $context) { 0524 return true; 0525 } 0526 0527 if ($throwException) { 0528 /** 0529 * @see Zend_Controller_Action_Exception 0530 */ 0531 // require_once 'Zend/Controller/Action/Exception.php'; 0532 throw new Zend_Controller_Action_Exception(sprintf('Context "%s" does not exist', $context)); 0533 } 0534 0535 return false; 0536 } 0537 0538 /** 0539 * Add header to context 0540 * 0541 * @param string $context 0542 * @param string $header 0543 * @param string $content 0544 * @throws Zend_Controller_Action_Exception 0545 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0546 */ 0547 public function addHeader($context, $header, $content) 0548 { 0549 $context = (string) $context; 0550 $this->hasContext($context, true); 0551 0552 $header = (string) $header; 0553 $content = (string) $content; 0554 0555 if (isset($this->_contexts[$context]['headers'][$header])) { 0556 /** 0557 * @see Zend_Controller_Action_Exception 0558 */ 0559 // require_once 'Zend/Controller/Action/Exception.php'; 0560 throw new Zend_Controller_Action_Exception(sprintf('Cannot add "%s" header to context "%s": already exists', $header, $context)); 0561 } 0562 0563 $this->_contexts[$context]['headers'][$header] = $content; 0564 return $this; 0565 } 0566 0567 /** 0568 * Customize response header to use when switching context 0569 * 0570 * Passing an empty header value to the setters disables the response 0571 * header. 0572 * 0573 * @param string $type Context type for which to set suffix 0574 * @param string $header Header to set 0575 * @param string $content Header content 0576 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0577 */ 0578 public function setHeader($context, $header, $content) 0579 { 0580 $this->hasContext($context, true); 0581 $context = (string) $context; 0582 $header = (string) $header; 0583 $content = (string) $content; 0584 0585 $this->_contexts[$context]['headers'][$header] = $content; 0586 return $this; 0587 } 0588 0589 /** 0590 * Add multiple headers at once for a given context 0591 * 0592 * @param string $context 0593 * @param array $headers 0594 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0595 */ 0596 public function addHeaders($context, array $headers) 0597 { 0598 foreach ($headers as $header => $content) { 0599 $this->addHeader($context, $header, $content); 0600 } 0601 0602 return $this; 0603 } 0604 0605 /** 0606 * Set headers from context => headers pairs 0607 * 0608 * @param array $options 0609 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0610 */ 0611 protected function _setHeaders(array $options) 0612 { 0613 foreach ($options as $context => $headers) { 0614 if (!is_array($headers)) { 0615 continue; 0616 } 0617 $this->setHeaders($context, $headers); 0618 } 0619 0620 return $this; 0621 } 0622 0623 /** 0624 * Set multiple headers at once for a given context 0625 * 0626 * @param string $context 0627 * @param array $headers 0628 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0629 */ 0630 public function setHeaders($context, array $headers) 0631 { 0632 $this->clearHeaders($context); 0633 foreach ($headers as $header => $content) { 0634 $this->setHeader($context, $header, $content); 0635 } 0636 0637 return $this; 0638 } 0639 0640 /** 0641 * Retrieve context header 0642 * 0643 * Returns the value of a given header for a given context type 0644 * 0645 * @param string $context 0646 * @param string $header 0647 * @return string|null 0648 */ 0649 public function getHeader($context, $header) 0650 { 0651 $this->hasContext($context, true); 0652 $context = (string) $context; 0653 $header = (string) $header; 0654 if (isset($this->_contexts[$context]['headers'][$header])) { 0655 return $this->_contexts[$context]['headers'][$header]; 0656 } 0657 0658 return null; 0659 } 0660 0661 /** 0662 * Retrieve context headers 0663 * 0664 * Returns all headers for a context as key/value pairs 0665 * 0666 * @param string $context 0667 * @return array 0668 */ 0669 public function getHeaders($context) 0670 { 0671 $this->hasContext($context, true); 0672 $context = (string) $context; 0673 return $this->_contexts[$context]['headers']; 0674 } 0675 0676 /** 0677 * Remove a single header from a context 0678 * 0679 * @param string $context 0680 * @param string $header 0681 * @return boolean 0682 */ 0683 public function removeHeader($context, $header) 0684 { 0685 $this->hasContext($context, true); 0686 $context = (string) $context; 0687 $header = (string) $header; 0688 if (isset($this->_contexts[$context]['headers'][$header])) { 0689 unset($this->_contexts[$context]['headers'][$header]); 0690 return true; 0691 } 0692 0693 return false; 0694 } 0695 0696 /** 0697 * Clear all headers for a given context 0698 * 0699 * @param string $context 0700 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0701 */ 0702 public function clearHeaders($context) 0703 { 0704 $this->hasContext($context, true); 0705 $context = (string) $context; 0706 $this->_contexts[$context]['headers'] = array(); 0707 return $this; 0708 } 0709 0710 /** 0711 * Validate trigger and return in normalized form 0712 * 0713 * @param string $trigger 0714 * @throws Zend_Controller_Action_Exception 0715 * @return string 0716 */ 0717 protected function _validateTrigger($trigger) 0718 { 0719 $trigger = strtoupper($trigger); 0720 if ('TRIGGER_' !== substr($trigger, 0, 8)) { 0721 $trigger = 'TRIGGER_' . $trigger; 0722 } 0723 0724 if (!in_array($trigger, array(self::TRIGGER_INIT, self::TRIGGER_POST))) { 0725 /** 0726 * @see Zend_Controller_Action_Exception 0727 */ 0728 // require_once 'Zend/Controller/Action/Exception.php'; 0729 throw new Zend_Controller_Action_Exception(sprintf('Invalid trigger "%s"', $trigger)); 0730 } 0731 0732 return $trigger; 0733 } 0734 0735 /** 0736 * Set a callback for a given context and trigger 0737 * 0738 * @param string $context 0739 * @param string $trigger 0740 * @param string|array $callback 0741 * @throws Zend_Controller_Action_Exception 0742 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0743 */ 0744 public function setCallback($context, $trigger, $callback) 0745 { 0746 $this->hasContext($context, true); 0747 $trigger = $this->_validateTrigger($trigger); 0748 0749 if (!is_string($callback)) { 0750 if (!is_array($callback) || (2 != count($callback))) { 0751 /** 0752 * @see Zend_Controller_Action_Exception 0753 */ 0754 // require_once 'Zend/Controller/Action/Exception.php'; 0755 throw new Zend_Controller_Action_Exception('Invalid callback specified'); 0756 } 0757 } 0758 0759 $this->_contexts[$context]['callbacks'][$trigger] = $callback; 0760 return $this; 0761 } 0762 0763 /** 0764 * Set callbacks from array of context => callbacks pairs 0765 * 0766 * @param array $options 0767 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0768 */ 0769 protected function _setCallbacks(array $options) 0770 { 0771 foreach ($options as $context => $callbacks) { 0772 if (!is_array($callbacks)) { 0773 continue; 0774 } 0775 0776 $this->setCallbacks($context, $callbacks); 0777 } 0778 return $this; 0779 } 0780 0781 /** 0782 * Set callbacks for a given context 0783 * 0784 * Callbacks should be in trigger/callback pairs. 0785 * 0786 * @param string $context 0787 * @param array $callbacks 0788 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0789 */ 0790 public function setCallbacks($context, array $callbacks) 0791 { 0792 $this->hasContext($context, true); 0793 $context = (string) $context; 0794 if (!isset($this->_contexts[$context]['callbacks'])) { 0795 $this->_contexts[$context]['callbacks'] = array(); 0796 } 0797 0798 foreach ($callbacks as $trigger => $callback) { 0799 $this->setCallback($context, $trigger, $callback); 0800 } 0801 return $this; 0802 } 0803 0804 /** 0805 * Get a single callback for a given context and trigger 0806 * 0807 * @param string $context 0808 * @param string $trigger 0809 * @return string|array|null 0810 */ 0811 public function getCallback($context, $trigger) 0812 { 0813 $this->hasContext($context, true); 0814 $trigger = $this->_validateTrigger($trigger); 0815 if (isset($this->_contexts[$context]['callbacks'][$trigger])) { 0816 return $this->_contexts[$context]['callbacks'][$trigger]; 0817 } 0818 0819 return null; 0820 } 0821 0822 /** 0823 * Get all callbacks for a given context 0824 * 0825 * @param string $context 0826 * @return array 0827 */ 0828 public function getCallbacks($context) 0829 { 0830 $this->hasContext($context, true); 0831 return $this->_contexts[$context]['callbacks']; 0832 } 0833 0834 /** 0835 * Clear a callback for a given context and trigger 0836 * 0837 * @param string $context 0838 * @param string $trigger 0839 * @return boolean 0840 */ 0841 public function removeCallback($context, $trigger) 0842 { 0843 $this->hasContext($context, true); 0844 $trigger = $this->_validateTrigger($trigger); 0845 if (isset($this->_contexts[$context]['callbacks'][$trigger])) { 0846 unset($this->_contexts[$context]['callbacks'][$trigger]); 0847 return true; 0848 } 0849 0850 return false; 0851 } 0852 0853 /** 0854 * Clear all callbacks for a given context 0855 * 0856 * @param string $context 0857 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0858 */ 0859 public function clearCallbacks($context) 0860 { 0861 $this->hasContext($context, true); 0862 $this->_contexts[$context]['callbacks'] = array(); 0863 return $this; 0864 } 0865 0866 /** 0867 * Set name of parameter to use when determining context format 0868 * 0869 * @param string $name 0870 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0871 */ 0872 public function setContextParam($name) 0873 { 0874 $this->_contextParam = (string) $name; 0875 return $this; 0876 } 0877 0878 /** 0879 * Return context format request parameter name 0880 * 0881 * @return string 0882 */ 0883 public function getContextParam() 0884 { 0885 return $this->_contextParam; 0886 } 0887 0888 /** 0889 * Indicate default context to use when no context format provided 0890 * 0891 * @param string $type 0892 * @throws Zend_Controller_Action_Exception 0893 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0894 */ 0895 public function setDefaultContext($type) 0896 { 0897 if (!isset($this->_contexts[$type])) { 0898 /** 0899 * @see Zend_Controller_Action_Exception 0900 */ 0901 // require_once 'Zend/Controller/Action/Exception.php'; 0902 throw new Zend_Controller_Action_Exception(sprintf('Cannot set default context; invalid context type "%s"', $type)); 0903 } 0904 0905 $this->_defaultContext = $type; 0906 return $this; 0907 } 0908 0909 /** 0910 * Return default context 0911 * 0912 * @return string 0913 */ 0914 public function getDefaultContext() 0915 { 0916 return $this->_defaultContext; 0917 } 0918 0919 /** 0920 * Set flag indicating if layout should be disabled 0921 * 0922 * @param boolean $flag 0923 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0924 */ 0925 public function setAutoDisableLayout($flag) 0926 { 0927 $this->_disableLayout = ($flag) ? true : false; 0928 return $this; 0929 } 0930 0931 /** 0932 * Retrieve auto layout disable flag 0933 * 0934 * @return boolean 0935 */ 0936 public function getAutoDisableLayout() 0937 { 0938 return $this->_disableLayout; 0939 } 0940 0941 /** 0942 * Add new context 0943 * 0944 * @param string $context Context type 0945 * @param array $spec Context specification 0946 * @throws Zend_Controller_Action_Exception 0947 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0948 */ 0949 public function addContext($context, array $spec) 0950 { 0951 if ($this->hasContext($context)) { 0952 /** 0953 * @see Zend_Controller_Action_Exception 0954 */ 0955 // require_once 'Zend/Controller/Action/Exception.php'; 0956 throw new Zend_Controller_Action_Exception(sprintf('Cannot add context "%s"; already exists', $context)); 0957 } 0958 $context = (string) $context; 0959 0960 $this->_contexts[$context] = array(); 0961 0962 $this->setSuffix($context, (isset($spec['suffix']) ? $spec['suffix'] : '')) 0963 ->setHeaders($context, (isset($spec['headers']) ? $spec['headers'] : array())) 0964 ->setCallbacks($context, (isset($spec['callbacks']) ? $spec['callbacks'] : array())); 0965 return $this; 0966 } 0967 0968 /** 0969 * Overwrite existing context 0970 * 0971 * @param string $context Context type 0972 * @param array $spec Context specification 0973 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0974 */ 0975 public function setContext($context, array $spec) 0976 { 0977 $this->removeContext($context); 0978 return $this->addContext($context, $spec); 0979 } 0980 0981 /** 0982 * Add multiple contexts 0983 * 0984 * @param array $contexts 0985 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 0986 */ 0987 public function addContexts(array $contexts) 0988 { 0989 foreach ($contexts as $context => $spec) { 0990 $this->addContext($context, $spec); 0991 } 0992 return $this; 0993 } 0994 0995 /** 0996 * Set multiple contexts, after first removing all 0997 * 0998 * @param array $contexts 0999 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 1000 */ 1001 public function setContexts(array $contexts) 1002 { 1003 $this->clearContexts(); 1004 foreach ($contexts as $context => $spec) { 1005 $this->addContext($context, $spec); 1006 } 1007 return $this; 1008 } 1009 1010 /** 1011 * Retrieve context specification 1012 * 1013 * @param string $context 1014 * @return array|null 1015 */ 1016 public function getContext($context) 1017 { 1018 if ($this->hasContext($context)) { 1019 return $this->_contexts[(string) $context]; 1020 } 1021 return null; 1022 } 1023 1024 /** 1025 * Retrieve context definitions 1026 * 1027 * @return array 1028 */ 1029 public function getContexts() 1030 { 1031 return $this->_contexts; 1032 } 1033 1034 /** 1035 * Remove a context 1036 * 1037 * @param string $context 1038 * @return boolean 1039 */ 1040 public function removeContext($context) 1041 { 1042 if ($this->hasContext($context)) { 1043 unset($this->_contexts[(string) $context]); 1044 return true; 1045 } 1046 return false; 1047 } 1048 1049 /** 1050 * Remove all contexts 1051 * 1052 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 1053 */ 1054 public function clearContexts() 1055 { 1056 $this->_contexts = array(); 1057 return $this; 1058 } 1059 1060 /** 1061 * Return current context, if any 1062 * 1063 * @return null|string 1064 */ 1065 public function getCurrentContext() 1066 { 1067 return $this->_currentContext; 1068 } 1069 1070 /** 1071 * Post dispatch processing 1072 * 1073 * Execute postDispatch callback for current context, if available 1074 * 1075 * @throws Zend_Controller_Action_Exception 1076 * @return void 1077 */ 1078 public function postDispatch() 1079 { 1080 $context = $this->getCurrentContext(); 1081 if (null !== $context) { 1082 if (null !== ($callback = $this->getCallback($context, self::TRIGGER_POST))) { 1083 if (is_string($callback) && method_exists($this, $callback)) { 1084 $this->$callback(); 1085 } elseif (is_string($callback) && function_exists($callback)) { 1086 $callback(); 1087 } elseif (is_array($callback)) { 1088 call_user_func($callback); 1089 } else { 1090 /** 1091 * @see Zend_Controller_Action_Exception 1092 */ 1093 // require_once 'Zend/Controller/Action/Exception.php'; 1094 throw new Zend_Controller_Action_Exception(sprintf('Invalid postDispatch context callback registered for context "%s"', $context)); 1095 } 1096 } 1097 } 1098 } 1099 1100 /** 1101 * JSON post processing 1102 * 1103 * JSON serialize view variables to response body 1104 * 1105 * @return void 1106 */ 1107 public function postJsonContext() 1108 { 1109 if (!$this->getAutoJsonSerialization()) { 1110 return; 1111 } 1112 1113 $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); 1114 $view = $viewRenderer->view; 1115 if ($view instanceof Zend_View_Interface) { 1116 /** 1117 * @see Zend_Json 1118 */ 1119 if(method_exists($view, 'getVars')) { 1120 // require_once 'Zend/Json.php'; 1121 $vars = Zend_Json::encode($view->getVars()); 1122 $this->getResponse()->setBody($vars); 1123 } else { 1124 // require_once 'Zend/Controller/Action/Exception.php'; 1125 throw new Zend_Controller_Action_Exception('View does not implement the getVars() method needed to encode the view into JSON'); 1126 } 1127 } 1128 } 1129 1130 /** 1131 * Add one or more contexts to an action 1132 * 1133 * @param string $action 1134 * @param string|array $context 1135 * @return Zend_Controller_Action_Helper_ContextSwitch|void Provides a fluent interface 1136 */ 1137 public function addActionContext($action, $context) 1138 { 1139 $this->hasContext($context, true); 1140 $controller = $this->getActionController(); 1141 if (null === $controller) { 1142 return; 1143 } 1144 $action = (string) $action; 1145 $contextKey = $this->_contextKey; 1146 1147 if (!isset($controller->$contextKey)) { 1148 $controller->$contextKey = array(); 1149 } 1150 1151 if (true === $context) { 1152 $contexts = $this->getContexts(); 1153 $controller->{$contextKey}[$action] = array_keys($contexts); 1154 return $this; 1155 } 1156 1157 $context = (array) $context; 1158 if (!isset($controller->{$contextKey}[$action])) { 1159 $controller->{$contextKey}[$action] = $context; 1160 } else { 1161 $controller->{$contextKey}[$action] = array_merge( 1162 $controller->{$contextKey}[$action], 1163 $context 1164 ); 1165 } 1166 1167 return $this; 1168 } 1169 1170 /** 1171 * Set a context as available for a given controller action 1172 * 1173 * @param string $action 1174 * @param string|array $context 1175 * @return Zend_Controller_Action_Helper_ContextSwitch|void Provides a fluent interface 1176 */ 1177 public function setActionContext($action, $context) 1178 { 1179 $this->hasContext($context, true); 1180 $controller = $this->getActionController(); 1181 if (null === $controller) { 1182 return; 1183 } 1184 $action = (string) $action; 1185 $contextKey = $this->_contextKey; 1186 1187 if (!isset($controller->$contextKey)) { 1188 $controller->$contextKey = array(); 1189 } 1190 1191 if (true === $context) { 1192 $contexts = $this->getContexts(); 1193 $controller->{$contextKey}[$action] = array_keys($contexts); 1194 } else { 1195 $controller->{$contextKey}[$action] = (array) $context; 1196 } 1197 1198 return $this; 1199 } 1200 1201 /** 1202 * Add multiple action/context pairs at once 1203 * 1204 * @param array $contexts 1205 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 1206 */ 1207 public function addActionContexts(array $contexts) 1208 { 1209 foreach ($contexts as $action => $context) { 1210 $this->addActionContext($action, $context); 1211 } 1212 return $this; 1213 } 1214 1215 /** 1216 * Overwrite and set multiple action contexts at once 1217 * 1218 * @param array $contexts 1219 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 1220 */ 1221 public function setActionContexts(array $contexts) 1222 { 1223 foreach ($contexts as $action => $context) { 1224 $this->setActionContext($action, $context); 1225 } 1226 return $this; 1227 } 1228 1229 /** 1230 * Does a particular controller action have the given context(s)? 1231 * 1232 * @param string $action 1233 * @param string|array $context 1234 * @throws Zend_Controller_Action_Exception 1235 * @return boolean 1236 */ 1237 public function hasActionContext($action, $context) 1238 { 1239 $this->hasContext($context, true); 1240 $controller = $this->getActionController(); 1241 if (null === $controller) { 1242 return false; 1243 } 1244 $action = (string) $action; 1245 $contextKey = $this->_contextKey; 1246 1247 if (!isset($controller->{$contextKey})) { 1248 return false; 1249 } 1250 1251 $allContexts = $controller->{$contextKey}; 1252 1253 if (!is_array($allContexts)) { 1254 /** 1255 * @see Zend_Controller_Action_Exception 1256 */ 1257 // require_once 'Zend/Controller/Action/Exception.php'; 1258 throw new Zend_Controller_Action_Exception("Invalid contexts found for controller"); 1259 } 1260 1261 if (!isset($allContexts[$action])) { 1262 return false; 1263 } 1264 1265 if (true === $allContexts[$action]) { 1266 return true; 1267 } 1268 1269 $contexts = $allContexts[$action]; 1270 1271 if (!is_array($contexts)) { 1272 /** 1273 * @see Zend_Controller_Action_Exception 1274 */ 1275 // require_once 'Zend/Controller/Action/Exception.php'; 1276 throw new Zend_Controller_Action_Exception(sprintf("Invalid contexts found for action '%s'", $action)); 1277 } 1278 1279 if (is_string($context) && in_array($context, $contexts)) { 1280 return true; 1281 } elseif (is_array($context)) { 1282 $found = true; 1283 foreach ($context as $test) { 1284 if (!in_array($test, $contexts)) { 1285 $found = false; 1286 break; 1287 } 1288 } 1289 return $found; 1290 } 1291 1292 return false; 1293 } 1294 1295 /** 1296 * Get contexts for a given action or all actions in the controller 1297 * 1298 * @param string $action 1299 * @return array 1300 */ 1301 public function getActionContexts($action = null) 1302 { 1303 $controller = $this->getActionController(); 1304 if (null === $controller) { 1305 return array(); 1306 } 1307 $contextKey = $this->_contextKey; 1308 1309 if (!isset($controller->$contextKey)) { 1310 return array(); 1311 } 1312 1313 if (null !== $action) { 1314 $action = (string) $action; 1315 if (isset($controller->{$contextKey}[$action])) { 1316 return $controller->{$contextKey}[$action]; 1317 } else { 1318 return array(); 1319 } 1320 } 1321 1322 return $controller->$contextKey; 1323 } 1324 1325 /** 1326 * Remove one or more contexts for a given controller action 1327 * 1328 * @param string $action 1329 * @param string|array $context 1330 * @return boolean 1331 */ 1332 public function removeActionContext($action, $context) 1333 { 1334 if ($this->hasActionContext($action, $context)) { 1335 $controller = $this->getActionController(); 1336 $contextKey = $this->_contextKey; 1337 $action = (string) $action; 1338 $contexts = $controller->$contextKey; 1339 $actionContexts = $contexts[$action]; 1340 $contexts = (array) $context; 1341 foreach ($contexts as $context) { 1342 $index = array_search($context, $actionContexts); 1343 if (false !== $index) { 1344 unset($controller->{$contextKey}[$action][$index]); 1345 } 1346 } 1347 return true; 1348 } 1349 return false; 1350 } 1351 1352 /** 1353 * Clear all contexts for a given controller action or all actions 1354 * 1355 * @param string $action 1356 * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface 1357 */ 1358 public function clearActionContexts($action = null) 1359 { 1360 $controller = $this->getActionController(); 1361 $contextKey = $this->_contextKey; 1362 1363 if (!isset($controller->$contextKey) || empty($controller->$contextKey)) { 1364 return $this; 1365 } 1366 1367 if (null === $action) { 1368 $controller->$contextKey = array(); 1369 return $this; 1370 } 1371 1372 $action = (string) $action; 1373 if (isset($controller->{$contextKey}[$action])) { 1374 unset($controller->{$contextKey}[$action]); 1375 } 1376 1377 return $this; 1378 } 1379 1380 /** 1381 * Retrieve ViewRenderer 1382 * 1383 * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface 1384 */ 1385 protected function _getViewRenderer() 1386 { 1387 if (null === $this->_viewRenderer) { 1388 $this->_viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); 1389 } 1390 1391 return $this->_viewRenderer; 1392 } 1393 } 1394