ContextSwitch.php #1

  • //
  • guest/
  • perforce_software/
  • chronicle/
  • main/
  • library/
  • P4Cms/
  • Controller/
  • Action/
  • Helper/
  • ContextSwitch.php
  • View
  • Commits
  • Open Download .zip Download (5 KB)
<?php
/**
 * Enhances ContextSwitch to automatically initialize context
 * if contexts are defined in the action controller and initContext
 * has not been called explicitly. Automatically adds unknown
 * contexts using the context name as the view script suffix
 * (ie. no need to pre-declare formats, just use them).
 *
 * In addition, allows controller to specify which request methods
 * a given context is valid for by expanding the contexts definition
 * to accommodate a list of http request methods for each context.
 * For example:
 *
 *  $contexts = array(
 *      'action-one'   => 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     <release>/<patch>
 */
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;
    }
}
# Change User Description Committed
#1 16170 perforce_software Move Chronicle files to follow new path scheme for branching.
//guest/perforce_software/chronicle/library/P4Cms/Controller/Action/Helper/ContextSwitch.php
#1 8972 Matt Attaway Initial add of the Chronicle source code