array('json'), * 'action-two' => array('json' => 'post'), * 'action-three' => array('json' => array('post', 'put') * ); * * The above contexts definition indicates that action-one supports * the json context for all request methods; whereas 'action-two' * only supports json for http post requests and 'action-three' * supports json for post and put. * * @copyright 2011 Perforce Software. All rights reserved. * @license Please see LICENSE.txt in top-level folder of this distribution. * @version / */ class P4Cms_Controller_Action_Helper_ContextSwitch extends Zend_Controller_Action_Helper_ContextSwitch { protected $_autoInit = true; protected $_contextKey = 'normalizedContexts'; protected $_complexContextKey = 'contexts'; /** * Automatically initialize context prior to dispatch. */ public function preDispatch() { // disabled layouts if auto init/disable is on and a format // is specified. in particular this makes partial mostly work // for actions that don't directly support it. if ($this->_autoInit && $this->getAutoDisableLayout() && $this->getRequest()->getParam($this->getContextParam()) ) { $layout = Zend_Layout::getMvcInstance(); if (null !== $layout) { $layout->disableLayout(); } } // init contexts if auto-init true and controller defines contexts. if ($this->_autoInit && !empty($this->getActionController()->contexts)) { // disable automatic json serialization when auto initializing. $this->setAutoJsonSerialization(false); $this->initContext(); $this->_autoInit = true; } // make the helper easier to access from the controller. $this->getActionController()->contextSwitch = $this; return parent::preDispatch(); } /** * Extend init context to disable auto-init when called. * * @param mixed $format The default context. * @throws Zend_Controller_Action_Exception * @return void */ public function initContext($format = null) { // normalize controller contexts for parent. $controller = $this->getActionController(); $contextKey = $this->_complexContextKey; $normalized = array(); $contexts = isset($controller->$contextKey) ? $controller->$contextKey : array(); foreach ($contexts as $action => $actionContexts) { if ($actionContexts === true) { $normalized[$action] = true; continue; } $normalized[$action] = array(); foreach ($actionContexts as $key => $value) { $context = is_string($key) ? $key : $value; $normalized[$action][] = $context; // automatically add any missing contexts. if (!$this->hasContext($context)) { $this->addContext($context, array('suffix' => $context)); } } } // copy normalized contexts to standard context key. $contextKey = $this->_contextKey; $controller->$contextKey = $normalized; $this->_autoInit = false; return parent::initContext($format); } /** * Extend hasActionContext to be aware of request method limitations. * * @param string $action Action to evaluate. * @param string|array $context Context to evaluate. * @throws Zend_Controller_Action_Exception * @return boolean */ public function hasActionContext($action, $context) { $result = parent::hasActionContext($action, $context); // if action doesn't have this context, exit early. if (!$result) { return false; } // ensure that context is valid for the current request method. $contextKey = $this->_complexContextKey; $contexts = $this->getActionController()->$contextKey; // if action contexts is true, request method doesn't matter. if ($contexts[$action] === true) { return true; } // check for request method limit on this action/context. if (array_key_exists($context, $contexts[$action])) { $requestMethod = $this->getRequest()->getMethod(); $actionMethods = (array) $contexts[$action][$context]; foreach ($actionMethods as $method) { if (strtoupper($method) === $requestMethod) { return true; } } return false; } // must be valid. return true; } }