text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: ContextSwitch.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Controller_Action_Helper_Abstract
 */
require_once 'Zend/Controller/Action/Helper/Abstract.php';

/**
 * Simplify context switching based on requested format
 *
 * @uses       Zend_Controller_Action_Helper_Abstract
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Controller_Action_Helper_ContextSwitch extends Zend_Controller_Action_Helper_Abstract
{
    /**
     * Trigger type constants
     */
    const TRIGGER_INIT = 'TRIGGER_INIT';
    const TRIGGER_POST = 'TRIGGER_POST';

    /**
     * Supported contexts
     * @var array
     */
    protected $_contexts = array();

    /**
     * JSON auto-serialization flag
     * @var boolean
     */
    protected $_autoJsonSerialization = true;

    /**
     * Controller property key to utilize for context switching
     * @var string
     */
    protected $_contextKey = 'contexts';

    /**
     * Request parameter containing requested context
     * @var string
     */
    protected $_contextParam = 'format';

    /**
     * Current context
     * @var string
     */
    protected $_currentContext;

    /**
     * Default context (xml)
     * @var string
     */
    protected $_defaultContext = 'xml';

    /**
     * Whether or not to disable layouts when switching contexts
     * @var boolean
     */
    protected $_disableLayout = true;

    /**
     * Methods that require special configuration
     * @var array
     */
    protected $_specialConfig = array(
        'setSuffix',
        'setHeaders',
        'setCallbacks',
    );

    /**
     * Methods that are not configurable via setOptions and setConfig
     * @var array
     */
    protected $_unconfigurable = array(
        'setOptions',
        'setConfig',
        'setHeader',
        'setCallback',
        'setContext',
        'setActionContext',
        'setActionContexts',
    );

    /**
     * @var Zend_Controller_Action_Helper_ViewRenderer
     */
    protected $_viewRenderer;

    /**
     * Original view suffix prior to detecting context switch
     * @var string
     */
    protected $_viewSuffixOrig;

    /**
     * Constructor
     *
     * @param  array|Zend_Config $options
     * @return void
     */
    public function __construct($options = null)
    {
        if ($options instanceof Zend_Config) {
            $this->setConfig($options);
        } elseif (is_array($options)) {
            $this->setOptions($options);
        }

        if (empty($this->_contexts)) {
            $this->addContexts(array(
                'json' => array(
                    'suffix'    => 'json',
                    'headers'   => array('Content-Type' => 'application/json'),
                    'callbacks' => array(
                        'init' => 'initJsonContext',
                        'post' => 'postJsonContext'
                    )
                ),
                'xml'  => array(
                    'suffix'    => 'xml',
                    'headers'   => array('Content-Type' => 'application/xml'),
                )
            ));
        }

        $this->init();
    }

    /**
     * Initialize at start of action controller
     *
     * Reset the view script suffix to the original state, or store the
     * original state.
     *
     * @return void
     */
    public function init()
    {
        if (null === $this->_viewSuffixOrig) {
            $this->_viewSuffixOrig = $this->_getViewRenderer()->getViewSuffix();
        } else {
            $this->_getViewRenderer()->setViewSuffix($this->_viewSuffixOrig);
        }
    }

    /**
     * Configure object from array of options
     *
     * @param  array $options
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setOptions(array $options)
    {
        if (isset($options['contexts'])) {
            $this->setContexts($options['contexts']);
            unset($options['contexts']);
        }

        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $this->_unconfigurable)) {
                continue;
            }

            if (in_array($method, $this->_specialConfig)) {
                $method = '_' . $method;
            }

            if (method_exists($this, $method)) {
                $this->$method($value);
            }
        }
        return $this;
    }

    /**
     * Set object state from config object
     *
     * @param  Zend_Config $config
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setConfig(Zend_Config $config)
    {
        return $this->setOptions($config->toArray());
    }

    /**
     * Strategy pattern: return object
     *
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function direct()
    {
        return $this;
    }

    /**
     * Initialize context detection and switching
     *
     * @param  mixed $format
     * @throws Zend_Controller_Action_Exception
     * @return void
     */
    public function initContext($format = null)
    {
        $this->_currentContext = null;

        $controller = $this->getActionController();
        $request    = $this->getRequest();
        $action     = $request->getActionName();

        // Return if no context switching enabled, or no context switching
        // enabled for this action
        $contexts = $this->getActionContexts($action);
        if (empty($contexts)) {
            return;
        }

        // Return if no context parameter provided
        if (!$context = $request->getParam($this->getContextParam())) {
            if ($format === null) {
                return;
            }
            $context = $format;
            $format  = null;
        }

        // Check if context allowed by action controller
        if (!$this->hasActionContext($action, $context)) {
            return;
        }

        // Return if invalid context parameter provided and no format or invalid
        // format provided
        if (!$this->hasContext($context)) {
            if (empty($format) || !$this->hasContext($format)) {

                return;
            }
        }

        // Use provided format if passed
        if (!empty($format) && $this->hasContext($format)) {
            $context = $format;
        }

        $suffix = $this->getSuffix($context);

        $this->_getViewRenderer()->setViewSuffix($suffix);

        $headers = $this->getHeaders($context);
        if (!empty($headers)) {
            $response = $this->getResponse();
            foreach ($headers as $header => $content) {
                $response->setHeader($header, $content);
            }
        }

        if ($this->getAutoDisableLayout()) {
            /**
             * @see Zend_Layout
             */
            require_once 'Zend/Layout.php';
            $layout = Zend_Layout::getMvcInstance();
            if (null !== $layout) {
                $layout->disableLayout();
            }
        }

        if (null !== ($callback = $this->getCallback($context, self::TRIGGER_INIT))) {
            if (is_string($callback) && method_exists($this, $callback)) {
                $this->$callback();
            } elseif (is_string($callback) && function_exists($callback)) {
                $callback();
            } elseif (is_array($callback)) {
                call_user_func($callback);
            } else {
                /**
                 * @see Zend_Controller_Action_Exception
                 */
                require_once 'Zend/Controller/Action/Exception.php';
                throw new Zend_Controller_Action_Exception(sprintf('Invalid context callback registered for context "%s"', $context));
            }
        }

        $this->_currentContext = $context;
    }

    /**
     * JSON context extra initialization
     *
     * Turns off viewRenderer auto-rendering
     *
     * @return void
     */
    public function initJsonContext()
    {
        if (!$this->getAutoJsonSerialization()) {
            return;
        }

        $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
        $view = $viewRenderer->view;
        if ($view instanceof Zend_View_Interface) {
            $viewRenderer->setNoRender(true);
        }
    }

    /**
     * Should JSON contexts auto-serialize?
     *
     * @param  boolean $flag
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setAutoJsonSerialization($flag)
    {
        $this->_autoJsonSerialization = (bool) $flag;
        return $this;
    }

    /**
     * Get JSON context auto-serialization flag
     *
     * @return boolean
     */
    public function getAutoJsonSerialization()
    {
        return $this->_autoJsonSerialization;
    }

    /**
     * Set suffix from array
     *
     * @param  array $spec
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    protected function _setSuffix(array $spec)
    {
        foreach ($spec as $context => $suffixInfo) {
            if (!is_string($context)) {
                $context = null;
            }

            if (is_string($suffixInfo)) {
                $this->setSuffix($context, $suffixInfo);
                continue;
            } elseif (is_array($suffixInfo)) {
                if (isset($suffixInfo['suffix'])) {
                    $suffix                    = $suffixInfo['suffix'];
                    $prependViewRendererSuffix = true;

                    if ((null === $context) && isset($suffixInfo['context'])) {
                        $context = $suffixInfo['context'];
                    }

                    if (isset($suffixInfo['prependViewRendererSuffix'])) {
                        $prependViewRendererSuffix = $suffixInfo['prependViewRendererSuffix'];
                    }

                    $this->setSuffix($context, $suffix, $prependViewRendererSuffix);
                    continue;
                }

                $count = count($suffixInfo);
                switch (true) {
                    case (($count < 2) && (null === $context)):
                        /**
                         * @see Zend_Controller_Action_Exception
                         */
                        require_once 'Zend/Controller/Action/Exception.php';
                        throw new Zend_Controller_Action_Exception('Invalid suffix information provided in config');
                    case ($count < 2):
                        $suffix = array_shift($suffixInfo);
                        $this->setSuffix($context, $suffix);
                        break;
                    case (($count < 3) && (null === $context)):
                        $context = array_shift($suffixInfo);
                        $suffix  = array_shift($suffixInfo);
                        $this->setSuffix($context, $suffix);
                        break;
                    case (($count == 3) && (null === $context)):
                        $context = array_shift($suffixInfo);
                        $suffix  = array_shift($suffixInfo);
                        $prependViewRendererSuffix = array_shift($suffixInfo);
                        $this->setSuffix($context, $suffix, $prependViewRendererSuffix);
                        break;
                    case ($count >= 2):
                        $suffix  = array_shift($suffixInfo);
                        $prependViewRendererSuffix = array_shift($suffixInfo);
                        $this->setSuffix($context, $suffix, $prependViewRendererSuffix);
                        break;
                }
            }
        }
        return $this;
    }

    /**
     * Customize view script suffix to use when switching context.
     *
     * Passing an empty suffix value to the setters disables the view script
     * suffix change.
     *
     * @param  string  $context                   Context type for which to set suffix
     * @param  string  $suffix                    Suffix to use
     * @param  boolean $prependViewRendererSuffix Whether or not to prepend the new suffix to the viewrenderer suffix
     * @throws Zend_Controller_Action_Exception
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setSuffix($context, $suffix, $prependViewRendererSuffix = true)
    {
        if (!isset($this->_contexts[$context])) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception(sprintf('Cannot set suffix; invalid context type "%s"', $context));
        }

        if (empty($suffix)) {
            $suffix = '';
        }

        if (is_array($suffix)) {
            if (isset($suffix['prependViewRendererSuffix'])) {
                $prependViewRendererSuffix = $suffix['prependViewRendererSuffix'];
            }
            if (isset($suffix['suffix'])) {
                $suffix = $suffix['suffix'];
            } else {
                $suffix = '';
            }
        }

        $suffix = (string) $suffix;

        if ($prependViewRendererSuffix) {
            if (empty($suffix)) {
                $suffix = $this->_getViewRenderer()->getViewSuffix();
            } else {
                $suffix .= '.' . $this->_getViewRenderer()->getViewSuffix();
            }
        }

        $this->_contexts[$context]['suffix'] = $suffix;
        return $this;
    }

    /**
     * Retrieve suffix for given context type
     *
     * @param  string $type Context type
     * @throws Zend_Controller_Action_Exception
     * @return string
     */
    public function getSuffix($type)
    {
        if (!isset($this->_contexts[$type])) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception(sprintf('Cannot retrieve suffix; invalid context type "%s"', $type));
        }

        return $this->_contexts[$type]['suffix'];
    }

    /**
     * Does the given context exist?
     *
     * @param  string  $context
     * @param  boolean $throwException
     * @throws Zend_Controller_Action_Exception if context does not exist and throwException is true
     * @return bool
     */
    public function hasContext($context, $throwException = false)
    {
        if (is_string($context)) {
            if (isset($this->_contexts[$context])) {
                return true;
            }
        } elseif (is_array($context)) {
            $error = false;
            foreach ($context as $test) {
                if (!isset($this->_contexts[$test])) {
                    $error = (string) $test;
                    break;
                }
            }
            if (false === $error) {
                return true;
            }
            $context = $error;
        } elseif (true === $context) {
            return true;
        }

        if ($throwException) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception(sprintf('Context "%s" does not exist', $context));
        }

        return false;
    }

    /**
     * Add header to context
     *
     * @param  string $context
     * @param  string $header
     * @param  string $content
     * @throws Zend_Controller_Action_Exception
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function addHeader($context, $header, $content)
    {
        $context = (string) $context;
        $this->hasContext($context, true);

        $header  = (string) $header;
        $content = (string) $content;

        if (isset($this->_contexts[$context]['headers'][$header])) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception(sprintf('Cannot add "%s" header to context "%s": already exists', $header, $context));
        }

        $this->_contexts[$context]['headers'][$header] = $content;
        return $this;
    }

    /**
     * Customize response header to use when switching context
     *
     * Passing an empty header value to the setters disables the response
     * header.
     *
     * @param  string $type   Context type for which to set suffix
     * @param  string $header Header to set
     * @param  string $content Header content
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setHeader($context, $header, $content)
    {
        $this->hasContext($context, true);
        $context = (string) $context;
        $header  = (string) $header;
        $content = (string) $content;

        $this->_contexts[$context]['headers'][$header] = $content;
        return $this;
    }

    /**
     * Add multiple headers at once for a given context
     *
     * @param  string $context
     * @param  array  $headers
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function addHeaders($context, array $headers)
    {
        foreach ($headers as $header => $content) {
            $this->addHeader($context, $header, $content);
        }

        return $this;
    }

    /**
     * Set headers from context => headers pairs
     *
     * @param  array $options
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    protected function _setHeaders(array $options)
    {
        foreach ($options as $context => $headers) {
            if (!is_array($headers)) {
                continue;
            }
            $this->setHeaders($context, $headers);
        }

        return $this;
    }

    /**
     * Set multiple headers at once for a given context
     *
     * @param  string $context
     * @param  array  $headers
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setHeaders($context, array $headers)
    {
        $this->clearHeaders($context);
        foreach ($headers as $header => $content) {
            $this->setHeader($context, $header, $content);
        }

        return $this;
    }

    /**
     * Retrieve context header
     *
     * Returns the value of a given header for a given context type
     *
     * @param  string $context
     * @param  string $header
     * @return string|null
     */
    public function getHeader($context, $header)
    {
        $this->hasContext($context, true);
        $context = (string) $context;
        $header  = (string) $header;
        if (isset($this->_contexts[$context]['headers'][$header])) {
            return $this->_contexts[$context]['headers'][$header];
        }

        return null;
    }

    /**
     * Retrieve context headers
     *
     * Returns all headers for a context as key/value pairs
     *
     * @param  string $context
     * @return array
     */
    public function getHeaders($context)
    {
        $this->hasContext($context, true);
        $context = (string) $context;
        return $this->_contexts[$context]['headers'];
    }

    /**
     * Remove a single header from a context
     *
     * @param  string $context
     * @param  string $header
     * @return boolean
     */
    public function removeHeader($context, $header)
    {
        $this->hasContext($context, true);
        $context = (string) $context;
        $header  = (string) $header;
        if (isset($this->_contexts[$context]['headers'][$header])) {
            unset($this->_contexts[$context]['headers'][$header]);
            return true;
        }

        return false;
    }

    /**
     * Clear all headers for a given context
     *
     * @param  string $context
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function clearHeaders($context)
    {
        $this->hasContext($context, true);
        $context = (string) $context;
        $this->_contexts[$context]['headers'] = array();
        return $this;
    }

    /**
     * Validate trigger and return in normalized form
     *
     * @param  string $trigger
     * @throws Zend_Controller_Action_Exception
     * @return string
     */
    protected function _validateTrigger($trigger)
    {
        $trigger = strtoupper($trigger);
        if ('TRIGGER_' !== substr($trigger, 0, 8)) {
            $trigger = 'TRIGGER_' . $trigger;
        }

        if (!in_array($trigger, array(self::TRIGGER_INIT, self::TRIGGER_POST))) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception(sprintf('Invalid trigger "%s"', $trigger));
        }

        return $trigger;
    }

    /**
     * Set a callback for a given context and trigger
     *
     * @param  string       $context
     * @param  string       $trigger
     * @param  string|array $callback
     * @throws Zend_Controller_Action_Exception
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setCallback($context, $trigger, $callback)
    {
        $this->hasContext($context, true);
        $trigger = $this->_validateTrigger($trigger);

        if (!is_string($callback)) {
            if (!is_array($callback) || (2 != count($callback))) {
                /**
                 * @see Zend_Controller_Action_Exception
                 */
                require_once 'Zend/Controller/Action/Exception.php';
                throw new Zend_Controller_Action_Exception('Invalid callback specified');
            }
        }

        $this->_contexts[$context]['callbacks'][$trigger] = $callback;
        return $this;
    }

    /**
     * Set callbacks from array of context => callbacks pairs
     *
     * @param  array $options
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    protected function _setCallbacks(array $options)
    {
        foreach ($options as $context => $callbacks) {
            if (!is_array($callbacks)) {
                continue;
            }

            $this->setCallbacks($context, $callbacks);
        }
        return $this;
    }

    /**
     * Set callbacks for a given context
     *
     * Callbacks should be in trigger/callback pairs.
     *
     * @param  string $context
     * @param  array  $callbacks
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setCallbacks($context, array $callbacks)
    {
        $this->hasContext($context, true);
        $context = (string) $context;
        if (!isset($this->_contexts[$context]['callbacks'])) {
            $this->_contexts[$context]['callbacks'] = array();
        }

        foreach ($callbacks as $trigger => $callback) {
            $this->setCallback($context, $trigger, $callback);
        }
        return $this;
    }

    /**
     * Get a single callback for a given context and trigger
     *
     * @param  string $context
     * @param  string $trigger
     * @return string|array|null
     */
    public function getCallback($context, $trigger)
    {
        $this->hasContext($context, true);
        $trigger = $this->_validateTrigger($trigger);
        if (isset($this->_contexts[$context]['callbacks'][$trigger])) {
            return $this->_contexts[$context]['callbacks'][$trigger];
        }

        return null;
    }

    /**
     * Get all callbacks for a given context
     *
     * @param  string $context
     * @return array
     */
    public function getCallbacks($context)
    {
        $this->hasContext($context, true);
        return $this->_contexts[$context]['callbacks'];
    }

    /**
     * Clear a callback for a given context and trigger
     *
     * @param  string $context
     * @param  string $trigger
     * @return boolean
     */
    public function removeCallback($context, $trigger)
    {
        $this->hasContext($context, true);
        $trigger = $this->_validateTrigger($trigger);
        if (isset($this->_contexts[$context]['callbacks'][$trigger])) {
            unset($this->_contexts[$context]['callbacks'][$trigger]);
            return true;
        }

        return false;
    }

    /**
     * Clear all callbacks for a given context
     *
     * @param  string $context
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function clearCallbacks($context)
    {
        $this->hasContext($context, true);
        $this->_contexts[$context]['callbacks'] = array();
        return $this;
    }

    /**
     * Set name of parameter to use when determining context format
     *
     * @param  string $name
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setContextParam($name)
    {
        $this->_contextParam = (string) $name;
        return $this;
    }

    /**
     * Return context format request parameter name
     *
     * @return string
     */
    public function getContextParam()
    {
        return $this->_contextParam;
    }

    /**
     * Indicate default context to use when no context format provided
     *
     * @param  string $type
     * @throws Zend_Controller_Action_Exception
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setDefaultContext($type)
    {
        if (!isset($this->_contexts[$type])) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception(sprintf('Cannot set default context; invalid context type "%s"', $type));
        }

        $this->_defaultContext = $type;
        return $this;
    }

    /**
     * Return default context
     *
     * @return string
     */
    public function getDefaultContext()
    {
        return $this->_defaultContext;
    }

    /**
     * Set flag indicating if layout should be disabled
     *
     * @param  boolean $flag
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setAutoDisableLayout($flag)
    {
        $this->_disableLayout = ($flag) ? true : false;
        return $this;
    }

    /**
     * Retrieve auto layout disable flag
     *
     * @return boolean
     */
    public function getAutoDisableLayout()
    {
        return $this->_disableLayout;
    }

    /**
     * Add new context
     *
     * @param  string $context Context type
     * @param  array  $spec    Context specification
     * @throws Zend_Controller_Action_Exception
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function addContext($context, array $spec)
    {
        if ($this->hasContext($context)) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception(sprintf('Cannot add context "%s"; already exists', $context));
        }
        $context = (string) $context;

        $this->_contexts[$context] = array();

        $this->setSuffix($context,    (isset($spec['suffix'])    ? $spec['suffix']    : ''))
             ->setHeaders($context,   (isset($spec['headers'])   ? $spec['headers']   : array()))
             ->setCallbacks($context, (isset($spec['callbacks']) ? $spec['callbacks'] : array()));
        return $this;
    }

    /**
     * Overwrite existing context
     *
     * @param  string $context Context type
     * @param  array  $spec    Context specification
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setContext($context, array $spec)
    {
        $this->removeContext($context);
        return $this->addContext($context, $spec);
    }

    /**
     * Add multiple contexts
     *
     * @param  array $contexts
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function addContexts(array $contexts)
    {
        foreach ($contexts as $context => $spec) {
            $this->addContext($context, $spec);
        }
        return $this;
    }

    /**
     * Set multiple contexts, after first removing all
     *
     * @param  array $contexts
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setContexts(array $contexts)
    {
        $this->clearContexts();
        foreach ($contexts as $context => $spec) {
            $this->addContext($context, $spec);
        }
        return $this;
    }

    /**
     * Retrieve context specification
     *
     * @param  string $context
     * @return array|null
     */
    public function getContext($context)
    {
        if ($this->hasContext($context)) {
            return $this->_contexts[(string) $context];
        }
        return null;
    }

    /**
     * Retrieve context definitions
     *
     * @return array
     */
    public function getContexts()
    {
        return $this->_contexts;
    }

    /**
     * Remove a context
     *
     * @param  string $context
     * @return boolean
     */
    public function removeContext($context)
    {
        if ($this->hasContext($context)) {
            unset($this->_contexts[(string) $context]);
            return true;
        }
        return false;
    }

    /**
     * Remove all contexts
     *
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function clearContexts()
    {
        $this->_contexts = array();
        return $this;
    }

    /**
     * Return current context, if any
     *
     * @return null|string
     */
    public function getCurrentContext()
    {
        return $this->_currentContext;
    }

    /**
     * Post dispatch processing
     *
     * Execute postDispatch callback for current context, if available
     *
     * @throws Zend_Controller_Action_Exception
     * @return void
     */
    public function postDispatch()
    {
        $context = $this->getCurrentContext();
        if (null !== $context) {
            if (null !== ($callback = $this->getCallback($context, self::TRIGGER_POST))) {
                if (is_string($callback) && method_exists($this, $callback)) {
                    $this->$callback();
                } elseif (is_string($callback) && function_exists($callback)) {
                    $callback();
                } elseif (is_array($callback)) {
                    call_user_func($callback);
                } else {
                    /**
                     * @see Zend_Controller_Action_Exception
                     */
                    require_once 'Zend/Controller/Action/Exception.php';
                    throw new Zend_Controller_Action_Exception(sprintf('Invalid postDispatch context callback registered for context "%s"', $context));
                }
            }
        }
    }

    /**
     * JSON post processing
     *
     * JSON serialize view variables to response body
     *
     * @return void
     */
    public function postJsonContext()
    {
        if (!$this->getAutoJsonSerialization()) {
            return;
        }

        $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
        $view = $viewRenderer->view;
        if ($view instanceof Zend_View_Interface) {
            /**
             * @see Zend_Json
             */
            if(method_exists($view, 'getVars')) {
                require_once 'Zend/Json.php';
                $vars = Zend_Json::encode($view->getVars());
                $this->getResponse()->setBody($vars);
            } else {
                require_once 'Zend/Controller/Action/Exception.php';
                throw new Zend_Controller_Action_Exception('View does not implement the getVars() method needed to encode the view into JSON');
            }
        }
    }

    /**
     * Add one or more contexts to an action
     *
     * @param  string       $action
     * @param  string|array $context
     * @return Zend_Controller_Action_Helper_ContextSwitch|void Provides a fluent interface
     */
    public function addActionContext($action, $context)
    {
        $this->hasContext($context, true);
        $controller = $this->getActionController();
        if (null === $controller) {
            return;
        }
        $action     = (string) $action;
        $contextKey = $this->_contextKey;

        if (!isset($controller->$contextKey)) {
            $controller->$contextKey = array();
        }

        if (true === $context) {
            $contexts = $this->getContexts();
            $controller->{$contextKey}[$action] = array_keys($contexts);
            return $this;
        }

        $context = (array) $context;
        if (!isset($controller->{$contextKey}[$action])) {
            $controller->{$contextKey}[$action] = $context;
        } else {
            $controller->{$contextKey}[$action] = array_merge(
                $controller->{$contextKey}[$action],
                $context
            );
        }

        return $this;
    }

    /**
     * Set a context as available for a given controller action
     *
     * @param  string       $action
     * @param  string|array $context
     * @return Zend_Controller_Action_Helper_ContextSwitch|void Provides a fluent interface
     */
    public function setActionContext($action, $context)
    {
        $this->hasContext($context, true);
        $controller = $this->getActionController();
        if (null === $controller) {
            return;
        }
        $action     = (string) $action;
        $contextKey = $this->_contextKey;

        if (!isset($controller->$contextKey)) {
            $controller->$contextKey = array();
        }

        if (true === $context) {
            $contexts = $this->getContexts();
            $controller->{$contextKey}[$action] = array_keys($contexts);
        } else {
            $controller->{$contextKey}[$action] = (array) $context;
        }

        return $this;
    }

    /**
     * Add multiple action/context pairs at once
     *
     * @param  array $contexts
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function addActionContexts(array $contexts)
    {
        foreach ($contexts as $action => $context) {
            $this->addActionContext($action, $context);
        }
        return $this;
    }

    /**
     * Overwrite and set multiple action contexts at once
     *
     * @param  array $contexts
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function setActionContexts(array $contexts)
    {
        foreach ($contexts as $action => $context) {
            $this->setActionContext($action, $context);
        }
        return $this;
    }

    /**
     * Does a particular controller action have the given context(s)?
     *
     * @param  string       $action
     * @param  string|array $context
     * @throws Zend_Controller_Action_Exception
     * @return boolean
     */
    public function hasActionContext($action, $context)
    {
        $this->hasContext($context, true);
        $controller = $this->getActionController();
        if (null === $controller) {
            return false;
        }
        $action     = (string) $action;
        $contextKey = $this->_contextKey;

        if (!isset($controller->{$contextKey})) {
            return false;
        }

        $allContexts = $controller->{$contextKey};

        if (!is_array($allContexts)) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception("Invalid contexts found for controller");
        }

        if (!isset($allContexts[$action])) {
            return false;
        }

        if (true === $allContexts[$action]) {
            return true;
        }

        $contexts = $allContexts[$action];

        if (!is_array($contexts)) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception(sprintf("Invalid contexts found for action '%s'", $action));
        }

        if (is_string($context) && in_array($context, $contexts)) {
            return true;
        } elseif (is_array($context)) {
            $found = true;
            foreach ($context as $test) {
                if (!in_array($test, $contexts)) {
                    $found = false;
                    break;
                }
            }
            return $found;
        }

        return false;
    }

    /**
     * Get contexts for a given action or all actions in the controller
     *
     * @param  string $action
     * @return array
     */
    public function getActionContexts($action = null)
    {
        $controller = $this->getActionController();
        if (null === $controller) {
            return array();
        }
        $action     = (string) $action;
        $contextKey = $this->_contextKey;

        if (!isset($controller->$contextKey)) {
            return array();
        }

        if (null !== $action) {
            if (isset($controller->{$contextKey}[$action])) {
                return $controller->{$contextKey}[$action];
            } else {
                return array();
            }
        }

        return $controller->$contextKey;
    }

    /**
     * Remove one or more contexts for a given controller action
     *
     * @param  string       $action
     * @param  string|array $context
     * @return boolean
     */
    public function removeActionContext($action, $context)
    {
        if ($this->hasActionContext($action, $context)) {
            $controller     = $this->getActionController();
            $contextKey     = $this->_contextKey;
            $action         = (string) $action;
            $contexts       = $controller->$contextKey;
            $actionContexts = $contexts[$action];
            $contexts       = (array) $context;
            foreach ($contexts as $context) {
                $index = array_search($context, $actionContexts);
                if (false !== $index) {
                    unset($controller->{$contextKey}[$action][$index]);
                }
            }
            return true;
        }
        return false;
    }

    /**
     * Clear all contexts for a given controller action or all actions
     *
     * @param  string $action
     * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
     */
    public function clearActionContexts($action = null)
    {
        $controller = $this->getActionController();
        $contextKey = $this->_contextKey;

        if (!isset($controller->$contextKey) || empty($controller->$contextKey)) {
            return $this;
        }

        if (null === $action) {
            $controller->$contextKey = array();
            return $this;
        }

        $action = (string) $action;
        if (isset($controller->{$contextKey}[$action])) {
            unset($controller->{$contextKey}[$action]);
        }

        return $this;
    }

    /**
     * Retrieve ViewRenderer
     *
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    protected function _getViewRenderer()
    {
        if (null === $this->_viewRenderer) {
            $this->_viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
        }

        return $this->_viewRenderer;
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: AutoCompleteScriptaculous.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Controller_Action_Helper_AutoComplete_Abstract
 */
require_once 'Zend/Controller/Action/Helper/AutoComplete/Abstract.php';

/**
 * Create and send Scriptaculous-compatible autocompletion lists
 *
 * @uses       Zend_Controller_Action_Helper_AutoComplete_Abstract
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Controller_Action_Helper_AutoCompleteScriptaculous extends Zend_Controller_Action_Helper_AutoComplete_Abstract
{
    /**
     * Validate data for autocompletion
     *
     * @param  mixed $data
     * @return bool
     */
    public function validateData($data)
    {
        if (!is_array($data) && !is_scalar($data)) {
            return false;
        }

        return true;
    }

    /**
     * Prepare data for autocompletion
     *
     * @param  mixed   $data
     * @param  boolean $keepLayouts
     * @throws Zend_Controller_Action_Exception
     * @return string
     */
    public function prepareAutoCompletion($data, $keepLayouts = false)
    {
        if (!$this->validateData($data)) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception('Invalid data passed for autocompletion');
        }

        $data = (array) $data;
        $data = '

' . implode('

', $data) . '

';

        if (!$keepLayouts) {
            $this->disableLayouts();
        }

        return $data;
    }
}

repo_name: michael-romer/zf-boilerplate

repo_language: PHP

mime_type: text/html


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Url.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Controller_Action_Helper_Abstract
 */
require_once 'Zend/Controller/Action/Helper/Abstract.php';

/**
 * Helper for creating URLs for redirects and other tasks
 *
 * @uses       Zend_Controller_Action_Helper_Abstract
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Controller_Action_Helper_Url extends Zend_Controller_Action_Helper_Abstract
{
    /**
     * Create URL based on default route
     *
     * @param  string $action
     * @param  string $controller
     * @param  string $module
     * @param  array  $params
     * @return string
     */
    public function simple($action, $controller = null, $module = null, array $params = null)
    {
        $request = $this->getRequest();

        if (null === $controller) {
            $controller = $request->getControllerName();
        }

        if (null === $module) {
            $module = $request->getModuleName();
        }

        $url = $controller . '/' . $action;
        if ($module != $this->getFrontController()->getDispatcher()->getDefaultModule()) {
            $url = $module . '/' . $url;
        }

        if ('' !== ($baseUrl = $this->getFrontController()->getBaseUrl())) {
            $url = $baseUrl . '/' . $url;
        }

        if (null !== $params) {
            $paramPairs = array();
            foreach ($params as $key => $value) {
                $paramPairs[] = urlencode($key) . '/' . urlencode($value);
            }
            $paramString = implode('/', $paramPairs);
            $url .= '/' . $paramString;
        }

        $url = '/' . ltrim($url, '/');

        return $url;
    }

    /**
     * Assembles a URL based on a given route
     *
     * This method will typically be used for more complex operations, as it
     * ties into the route objects registered with the router.
     *
     * @param  array   $urlOptions Options passed to the assemble method of the Route object.
     * @param  mixed   $name       The name of a Route to use. If null it will use the current Route
     * @param  boolean $reset
     * @param  boolean $encode
     * @return string Url for the link href attribute.
     */
    public function url($urlOptions = array(), $name = null, $reset = false, $encode = true)
    {
        $router = $this->getFrontController()->getRouter();
        return $router->assemble($urlOptions, $name, $reset, $encode);
    }

    /**
     * Perform helper when called as $this->_helper->url() from an action controller
     *
     * Proxies to {@link simple()}
     *
     * @param  string $action
     * @param  string $controller
     * @param  string $module
     * @param  array  $params
     * @return string
     */
    public function direct($action, $controller = null, $module = null, array $params = null)
    {
        return $this->simple($action, $controller, $module, $params);
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: AutoCompleteDojo.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Controller_Action_Helper_AutoComplete_Abstract
 */
require_once 'Zend/Controller/Action/Helper/AutoComplete/Abstract.php';

/**
 * Create and send Dojo-compatible autocompletion lists
 *
 * @uses       Zend_Controller_Action_Helper_AutoComplete_Abstract
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Controller_Action_Helper_AutoCompleteDojo extends Zend_Controller_Action_Helper_AutoComplete_Abstract
{
    /**
     * Validate data for autocompletion
     *
     * Stub; unused
     *
     * @param  mixed $data
     * @return boolean
     */
    public function validateData($data)
    {
        return true;
    }

    /**
     * Prepare data for autocompletion
     *
     * @param  mixed   $data
     * @param  boolean $keepLayouts
     * @return string
     */
    public function prepareAutoCompletion($data, $keepLayouts = false)
    {
        if (!$data instanceof Zend_Dojo_Data) {
            require_once 'Zend/Dojo/Data.php';
            $items = array();
            foreach ($data as $key => $value) {
                $items[] = array('label' => $value, 'name' => $value);
            }
            $data = new Zend_Dojo_Data('name', $items);
        }

        if (!$keepLayouts) {
            require_once 'Zend/Controller/Action/HelperBroker.php';
            Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(true);

            require_once 'Zend/Layout.php';
            $layout = Zend_Layout::getMvcInstance();
            if ($layout instanceof Zend_Layout) {
                $layout->disableLayout();
            }
        }

        $response = Zend_Controller_Front::getInstance()->getResponse();
        $response->setHeader('Content-Type', 'application/json');

        return $data->toJson();
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: ViewRenderer.php 24282 2011-07-28 18:59:26Z matthew $
 */

/**
 * @see Zend_Controller_Action_Helper_Abstract
 */
require_once 'Zend/Controller/Action/Helper/Abstract.php';

/**
 * @see Zend_View
 */
require_once 'Zend/View.php';

/**
 * View script integration
 *
 * Zend_Controller_Action_Helper_ViewRenderer provides transparent view
 * integration for action controllers. It allows you to create a view object
 * once, and populate it throughout all actions. Several global options may be
 * set:
 *
 * - noController: if set true, render() will not look for view scripts in
 *   subdirectories named after the controller
 * - viewSuffix: what view script filename suffix to use
 *
 * The helper autoinitializes the action controller view preDispatch(). It
 * determines the path to the class file, and then determines the view base
 * directory from there. It also uses the module name as a class prefix for
 * helpers and views such that if your module name is 'Search', it will set the
 * helper class prefix to 'Search_View_Helper' and the filter class prefix to ;
 * 'Search_View_Filter'.
 *
 * Usage:
 * <code>
 * // In your bootstrap:
 * Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_ViewRenderer());
 *
 * // In your action controller methods:
 * $viewHelper = $this->_helper->getHelper('view');
 *
 * // Don't use controller subdirectories
 * $viewHelper->setNoController(true);
 *
 * // Specify a different script to render:
 * $this->_helper->viewRenderer('form');
 *
 * </code>
 *
 * @uses       Zend_Controller_Action_Helper_Abstract
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Controller_Action_Helper_ViewRenderer extends Zend_Controller_Action_Helper_Abstract
{
    /**
     * @var Zend_View_Interface
     */
    public $view;

    /**
     * Word delimiters
     * @var array
     */
    protected $_delimiters;

    /**
     * @var Zend_Filter_Inflector
     */
    protected $_inflector;

    /**
     * Inflector target
     * @var string
     */
    protected $_inflectorTarget = '';

    /**
     * Current module directory
     * @var string
     */
    protected $_moduleDir = '';

    /**
     * Whether or not to autorender using controller name as subdirectory;
     * global setting (not reset at next invocation)
     * @var boolean
     */
    protected $_neverController = false;

    /**
     * Whether or not to autorender postDispatch; global setting (not reset at
     * next invocation)
     * @var boolean
     */
    protected $_neverRender     = false;

    /**
     * Whether or not to use a controller name as a subdirectory when rendering
     * @var boolean
     */
    protected $_noController    = false;

    /**
     * Whether or not to autorender postDispatch; per controller/action setting (reset
     * at next invocation)
     * @var boolean
     */
    protected $_noRender        = false;

    /**
     * Characters representing path delimiters in the controller
     * @var string|array
     */
    protected $_pathDelimiters;

    /**
     * Which named segment of the response to utilize
     * @var string
     */
    protected $_responseSegment = null;

    /**
     * Which action view script to render
     * @var string
     */
    protected $_scriptAction    = null;

    /**
     * View object basePath
     * @var string
     */
    protected $_viewBasePathSpec = ':moduleDir/views';

    /**
     * View script path specification string
     * @var string
     */
    protected $_viewScriptPathSpec = ':controller/:action.:suffix';

    /**
     * View script path specification string, minus controller segment
     * @var string
     */
    protected $_viewScriptPathNoControllerSpec = ':action.:suffix';

    /**
     * View script suffix
     * @var string
     */
    protected $_viewSuffix      = 'phtml';

    /**
     * Constructor
     *
     * Optionally set view object and options.
     *
     * @param  Zend_View_Interface $view
     * @param  array               $options
     * @return void
     */
    public function __construct(Zend_View_Interface $view = null, array $options = array())
    {
        if (null !== $view) {
            $this->setView($view);
        }

        if (!empty($options)) {
            $this->_setOptions($options);
        }
    }

    /**
     * Clone - also make sure the view is cloned.
     *
     * @return void
     */
    public function __clone()
    {
        if (isset($this->view) && $this->view instanceof Zend_View_Interface) {
            $this->view = clone $this->view;

        }
    }

    /**
     * Set the view object
     *
     * @param  Zend_View_Interface $view
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setView(Zend_View_Interface $view)
    {
        $this->view = $view;
        return $this;
    }

    /**
     * Get current module name
     *
     * @return string
     */
    public function getModule()
    {
        $request = $this->getRequest();
        $module  = $request->getModuleName();
        if (null === $module) {
            $module = $this->getFrontController()->getDispatcher()->getDefaultModule();
        }

        return $module;
    }

    /**
     * Get module directory
     *
     * @throws Zend_Controller_Action_Exception
     * @return string
     */
    public function getModuleDirectory()
    {
        $module    = $this->getModule();
        $moduleDir = $this->getFrontController()->getControllerDirectory($module);
        if ((null === $moduleDir) || is_array($moduleDir)) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception('ViewRenderer cannot locate module directory for module "' . $module . '"');
        }
        $this->_moduleDir = dirname($moduleDir);
        return $this->_moduleDir;
    }

    /**
     * Get inflector
     *
     * @return Zend_Filter_Inflector
     */
    public function getInflector()
    {
        if (null === $this->_inflector) {
            /**
             * @see Zend_Filter_Inflector
             */
            require_once 'Zend/Filter/Inflector.php';
            /**
             * @see Zend_Filter_PregReplace
             */
            require_once 'Zend/Filter/PregReplace.php';
            /**
             * @see Zend_Filter_Word_UnderscoreToSeparator
             */
            require_once 'Zend/Filter/Word/UnderscoreToSeparator.php';
            $this->_inflector = new Zend_Filter_Inflector();
            $this->_inflector->setStaticRuleReference('moduleDir', $this->_moduleDir) // moduleDir must be specified before the less specific 'module'
                 ->addRules(array(
                     ':module'     => array('Word_CamelCaseToDash', 'StringToLower'),
                     ':controller' => array('Word_CamelCaseToDash', new Zend_Filter_Word_UnderscoreToSeparator('/'), 'StringToLower', new Zend_Filter_PregReplace('/\./', '-')),
                     ':action'     => array('Word_CamelCaseToDash', new Zend_Filter_PregReplace('#[^a-z0-9' . preg_quote('/', '#') . ']+#i', '-'), 'StringToLower'),
                 ))
                 ->setStaticRuleReference('suffix', $this->_viewSuffix)
                 ->setTargetReference($this->_inflectorTarget);
        }

        // Ensure that module directory is current
        $this->getModuleDirectory();

        return $this->_inflector;
    }

    /**
     * Set inflector
     *
     * @param  Zend_Filter_Inflector $inflector
     * @param  boolean               $reference Whether the moduleDir, target, and suffix should be set as references to ViewRenderer properties
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setInflector(Zend_Filter_Inflector $inflector, $reference = false)
    {
        $this->_inflector = $inflector;
        if ($reference) {
            $this->_inflector->setStaticRuleReference('suffix', $this->_viewSuffix)
                 ->setStaticRuleReference('moduleDir', $this->_moduleDir)
                 ->setTargetReference($this->_inflectorTarget);
        }
        return $this;
    }

    /**
     * Set inflector target
     *
     * @param  string $target
     * @return void
     */
    protected function _setInflectorTarget($target)
    {
        $this->_inflectorTarget = (string) $target;
    }

    /**
     * Set internal module directory representation
     *
     * @param  string $dir
     * @return void
     */
    protected function _setModuleDir($dir)
    {
        $this->_moduleDir = (string) $dir;
    }

    /**
     * Get internal module directory representation
     *
     * @return string
     */
    protected function _getModuleDir()
    {
        return $this->_moduleDir;
    }

    /**
     * Generate a class prefix for helper and filter classes
     *
     * @return string
     */
    protected function _generateDefaultPrefix()
    {
        $default = 'Zend_View';
        if (null === $this->_actionController) {
            return $default;
        }

        $class = get_class($this->_actionController);

        if (!strstr($class, '_')) {
            return $default;
        }

        $module = $this->getModule();
        if ('default' == $module) {
            return $default;
        }

        $prefix = substr($class, 0, strpos($class, '_')) . '_View';

        return $prefix;
    }

    /**
     * Retrieve base path based on location of current action controller
     *
     * @return string
     */
    protected function _getBasePath()
    {
        if (null === $this->_actionController) {
            return './views';
        }

        $inflector = $this->getInflector();
        $this->_setInflectorTarget($this->getViewBasePathSpec());

        $dispatcher = $this->getFrontController()->getDispatcher();
        $request = $this->getRequest();

        $parts = array(
            'module'     => (($moduleName = $request->getModuleName()) != '') ? $dispatcher->formatModuleName($moduleName) : $moduleName,
            'controller' => $request->getControllerName(),
            'action'     => $dispatcher->formatActionName($request->getActionName())
            );

        $path = $inflector->filter($parts);
        return $path;
    }

    /**
     * Set options
     *
     * @param  array $options
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    protected function _setOptions(array $options)
    {
        foreach ($options as $key => $value)
        {
            switch ($key) {
                case 'neverRender':
                case 'neverController':
                case 'noController':
                case 'noRender':
                    $property = '_' . $key;
                    $this->{$property} = ($value) ? true : false;
                    break;
                case 'responseSegment':
                case 'scriptAction':
                case 'viewBasePathSpec':
                case 'viewScriptPathSpec':
                case 'viewScriptPathNoControllerSpec':
                case 'viewSuffix':
                    $property = '_' . $key;
                    $this->{$property} = (string) $value;
                    break;
                default:
                    break;
            }
        }

        return $this;
    }

    /**
     * Initialize the view object
     *
     * $options may contain the following keys:
     * - neverRender - flag dis/enabling postDispatch() autorender (affects all subsequent calls)
     * - noController - flag indicating whether or not to look for view scripts in subdirectories named after the controller
     * - noRender - flag indicating whether or not to autorender postDispatch()
     * - responseSegment - which named response segment to render a view script to
     * - scriptAction - what action script to render
     * - viewBasePathSpec - specification to use for determining view base path
     * - viewScriptPathSpec - specification to use for determining view script paths
     * - viewScriptPathNoControllerSpec - specification to use for determining view script paths when noController flag is set
     * - viewSuffix - what view script filename suffix to use
     *
     * @param  string $path
     * @param  string $prefix
     * @param  array  $options
     * @throws Zend_Controller_Action_Exception
     * @return void
     */
    public function initView($path = null, $prefix = null, array $options = array())
    {
        if (null === $this->view) {
            $this->setView(new Zend_View());
        }

        // Reset some flags every time
        $options['noController'] = (isset($options['noController'])) ? $options['noController'] : false;
        $options['noRender']     = (isset($options['noRender'])) ? $options['noRender'] : false;
        $this->_scriptAction     = null;
        $this->_responseSegment  = null;

        // Set options first; may be used to determine other initializations
        $this->_setOptions($options);

        // Get base view path
        if (empty($path)) {
            $path = $this->_getBasePath();
            if (empty($path)) {
                /**
                 * @see Zend_Controller_Action_Exception
                 */
                require_once 'Zend/Controller/Action/Exception.php';
                throw new Zend_Controller_Action_Exception('ViewRenderer initialization failed: retrieved view base path is empty');
            }
        }

        if (null === $prefix) {
            $prefix = $this->_generateDefaultPrefix();
        }

        // Determine if this path has already been registered
        $currentPaths = $this->view->getScriptPaths();
        $path         = str_replace(array('/', '\\'), '/', $path);
        $pathExists   = false;
        foreach ($currentPaths as $tmpPath) {
            $tmpPath = str_replace(array('/', '\\'), '/', $tmpPath);
            if (strstr($tmpPath, $path)) {
                $pathExists = true;
                break;
            }
        }
        if (!$pathExists) {
            $this->view->addBasePath($path, $prefix);
        }

        // Register view with action controller (unless already registered)
        if ((null !== $this->_actionController) && (null === $this->_actionController->view)) {
            $this->_actionController->view       = $this->view;
            $this->_actionController->viewSuffix = $this->_viewSuffix;
        }
    }

    /**
     * init - initialize view
     *
     * @return void
     */
    public function init()
    {
        if ($this->getFrontController()->getParam('noViewRenderer')) {
            return;
        }

        $this->initView();
    }

    /**
     * Set view basePath specification
     *
     * Specification can contain one or more of the following:
     * - :moduleDir - current module directory
     * - :controller - name of current controller in the request
     * - :action - name of current action in the request
     * - :module - name of current module in the request
     *
     * @param  string $path
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setViewBasePathSpec($path)
    {
        $this->_viewBasePathSpec = (string) $path;
        return $this;
    }

    /**
     * Retrieve the current view basePath specification string
     *
     * @return string
     */
    public function getViewBasePathSpec()
    {
        return $this->_viewBasePathSpec;
    }

    /**
     * Set view script path specification
     *
     * Specification can contain one or more of the following:
     * - :moduleDir - current module directory
     * - :controller - name of current controller in the request
     * - :action - name of current action in the request
     * - :module - name of current module in the request
     *
     * @param  string $path
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setViewScriptPathSpec($path)
    {
        $this->_viewScriptPathSpec = (string) $path;
        return $this;
    }

    /**
     * Retrieve the current view script path specification string
     *
     * @return string
     */
    public function getViewScriptPathSpec()
    {
        return $this->_viewScriptPathSpec;
    }

    /**
     * Set view script path specification (no controller variant)
     *
     * Specification can contain one or more of the following:
     * - :moduleDir - current module directory
     * - :controller - name of current controller in the request
     * - :action - name of current action in the request
     * - :module - name of current module in the request
     *
     * :controller will likely be ignored in this variant.
     *
     * @param  string $path
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setViewScriptPathNoControllerSpec($path)
    {
        $this->_viewScriptPathNoControllerSpec = (string) $path;
        return $this;
    }

    /**
     * Retrieve the current view script path specification string (no controller variant)
     *
     * @return string
     */
    public function getViewScriptPathNoControllerSpec()
    {
        return $this->_viewScriptPathNoControllerSpec;
    }

    /**
     * Get a view script based on an action and/or other variables
     *
     * Uses values found in current request if no values passed in $vars.
     *
     * If {@link $_noController} is set, uses {@link $_viewScriptPathNoControllerSpec};
     * otherwise, uses {@link $_viewScriptPathSpec}.
     *
     * @param  string $action
     * @param  array  $vars
     * @return string
     */
    public function getViewScript($action = null, array $vars = array())
    {
        $request = $this->getRequest();
        if ((null === $action) && (!isset($vars['action']))) {
            $action = $this->getScriptAction();
            if (null === $action) {
                $action = $request->getActionName();
            }
            $vars['action'] = $action;
        } elseif (null !== $action) {
            $vars['action'] = $action;
        }

        $replacePattern = array('/[^a-z0-9]+$/i', '/^[^a-z0-9]+/i');
        $vars['action'] = preg_replace($replacePattern, '', $vars['action']);

        $inflector = $this->getInflector();
        if ($this->getNoController() || $this->getNeverController()) {
            $this->_setInflectorTarget($this->getViewScriptPathNoControllerSpec());
        } else {
            $this->_setInflectorTarget($this->getViewScriptPathSpec());
        }
        return $this->_translateSpec($vars);
    }

    /**
     * Set the neverRender flag (i.e., globally dis/enable autorendering)
     *
     * @param  boolean $flag
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setNeverRender($flag = true)
    {
        $this->_neverRender = ($flag) ? true : false;
        return $this;
    }

    /**
     * Retrieve neverRender flag value
     *
     * @return boolean
     */
    public function getNeverRender()
    {
        return $this->_neverRender;
    }

    /**
     * Set the noRender flag (i.e., whether or not to autorender)
     *
     * @param  boolean $flag
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setNoRender($flag = true)
    {
        $this->_noRender = ($flag) ? true : false;
        return $this;
    }

    /**
     * Retrieve noRender flag value
     *
     * @return boolean
     */
    public function getNoRender()
    {
        return $this->_noRender;
    }

    /**
     * Set the view script to use
     *
     * @param  string $name
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setScriptAction($name)
    {
        $this->_scriptAction = (string) $name;
        return $this;
    }

    /**
     * Retrieve view script name
     *
     * @return string
     */
    public function getScriptAction()
    {
        return $this->_scriptAction;
    }

    /**
     * Set the response segment name
     *
     * @param  string $name
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setResponseSegment($name)
    {
        if (null === $name) {
            $this->_responseSegment = null;
        } else {
            $this->_responseSegment = (string) $name;
        }

        return $this;
    }

    /**
     * Retrieve named response segment name
     *
     * @return string
     */
    public function getResponseSegment()
    {
        return $this->_responseSegment;
    }

    /**
     * Set the noController flag (i.e., whether or not to render into controller subdirectories)
     *
     * @param  boolean $flag
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setNoController($flag = true)
    {
        $this->_noController = ($flag) ? true : false;
        return $this;
    }

    /**
     * Retrieve noController flag value
     *
     * @return boolean
     */
    public function getNoController()
    {
        return $this->_noController;
    }

    /**
     * Set the neverController flag (i.e., whether or not to render into controller subdirectories)
     *
     * @param  boolean $flag
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setNeverController($flag = true)
    {
        $this->_neverController = ($flag) ? true : false;
        return $this;
    }

    /**
     * Retrieve neverController flag value
     *
     * @return boolean
     */
    public function getNeverController()
    {
        return $this->_neverController;
    }

    /**
     * Set view script suffix
     *
     * @param  string $suffix
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setViewSuffix($suffix)
    {
        $this->_viewSuffix = (string) $suffix;
        return $this;
    }

    /**
     * Get view script suffix
     *
     * @return string
     */
    public function getViewSuffix()
    {
        return $this->_viewSuffix;
    }

    /**
     * Set options for rendering a view script
     *
     * @param  string  $action       View script to render
     * @param  string  $name         Response named segment to render to
     * @param  boolean $noController Whether or not to render within a subdirectory named after the controller
     * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
     */
    public function setRender($action = null, $name = null, $noController = null)
    {
        if (null !== $action) {
            $this->setScriptAction($action);
        }

        if (null !== $name) {
            $this->setResponseSegment($name);
        }

        if (null !== $noController) {
            $this->setNoController($noController);
        }

        return $this;
    }

    /**
     * Inflect based on provided vars
     *
     * Allowed variables are:
     * - :moduleDir - current module directory
     * - :module - current module name
     * - :controller - current controller name
     * - :action - current action name
     * - :suffix - view script file suffix
     *
     * @param  array $vars
     * @return string
     */
    protected function _translateSpec(array $vars = array())
    {
        $inflector  = $this->getInflector();
        $request    = $this->getRequest();
        $dispatcher = $this->getFrontController()->getDispatcher();
        $module     = $dispatcher->formatModuleName($request->getModuleName());
        $controller = $request->getControllerName();
        $action     = $dispatcher->formatActionName($request->getActionName());

        $params     = compact('module', 'controller', 'action');
        foreach ($vars as $key => $value) {
            switch ($key) {
                case 'module':
                case 'controller':
                case 'action':
                case 'moduleDir':
                case 'suffix':
                    $params[$key] = (string) $value;
                    break;
                default:
                    break;
            }
        }

        if (isset($params['suffix'])) {
            $origSuffix = $this->getViewSuffix();
            $this->setViewSuffix($params['suffix']);
        }
        if (isset($params['moduleDir'])) {
            $origModuleDir = $this->_getModuleDir();
            $this->_setModuleDir($params['moduleDir']);
        }

        $filtered = $inflector->filter($params);

        if (isset($params['suffix'])) {
            $this->setViewSuffix($origSuffix);
        }
        if (isset($params['moduleDir'])) {
            $this->_setModuleDir($origModuleDir);
        }

        return $filtered;
    }

    /**
     * Render a view script (optionally to a named response segment)
     *
     * Sets the noRender flag to true when called.
     *
     * @param  string $script
     * @param  string $name
     * @return void
     */
    public function renderScript($script, $name = null)
    {
        if (null === $name) {
            $name = $this->getResponseSegment();
        }

        $this->getResponse()->appendBody(
            $this->view->render($script),
            $name
        );

        $this->setNoRender();
    }

    /**
     * Render a view based on path specifications
     *
     * Renders a view based on the view script path specifications.
     *
     * @param  string  $action
     * @param  string  $name
     * @param  boolean $noController
     * @return void
     */
    public function render($action = null, $name = null, $noController = null)
    {
        $this->setRender($action, $name, $noController);
        $path = $this->getViewScript();
        $this->renderScript($path, $name);
    }

    /**
     * Render a script based on specification variables
     *
     * Pass an action, and one or more specification variables (view script suffix)
     * to determine the view script path, and render that script.
     *
     * @param  string $action
     * @param  array  $vars
     * @param  string $name
     * @return void
     */
    public function renderBySpec($action = null, array $vars = array(), $name = null)
    {
        if (null !== $name) {
            $this->setResponseSegment($name);
        }

        $path = $this->getViewScript($action, $vars);

        $this->renderScript($path);
    }

    /**
     * postDispatch - auto render a view
     *
     * Only autorenders if:
     * - _noRender is false
     * - action controller is present
     * - request has not been re-dispatched (i.e., _forward() has not been called)
     * - response is not a redirect
     *
     * @return void
     */
    public function postDispatch()
    {
        if ($this->_shouldRender()) {
            $this->render();
        }
    }

    /**
     * Should the ViewRenderer render a view script?
     *
     * @return boolean
     */
    protected function _shouldRender()
    {
        return (!$this->getFrontController()->getParam('noViewRenderer')
            && !$this->_neverRender
            && !$this->_noRender
            && (null !== $this->_actionController)
            && $this->getRequest()->isDispatched()
            && !$this->getResponse()->isRedirect()
        );
    }

    /**
     * Use this helper as a method; proxies to setRender()
     *
     * @param  string  $action
     * @param  string  $name
     * @param  boolean $noController
     * @return void
     */
    public function direct($action = null, $name = null, $noController = null)
    {
        $this->setRender($action, $name, $noController);
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: AjaxContext.php 24131 2011-06-09 08:37:20Z freak $
 */

/**
 * @see Zend_Controller_Action_Helper_ContextSwitch
 */
require_once 'Zend/Controller/Action/Helper/ContextSwitch.php';

/**
 * Simplify AJAX context switching based on requested format
 *
 * @uses       Zend_Controller_Action_Helper_Abstract
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Controller_Action_Helper_AjaxContext extends Zend_Controller_Action_Helper_ContextSwitch
{
    /**
     * Controller property to utilize for context switching
     * @var string
     */
    protected $_contextKey = 'ajaxable';

    /**
     * Constructor
     *
     * Add HTML context
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
        $this->addContext('html', array('suffix' => 'ajax'));
    }

    /**
     * Initialize AJAX context switching
     *
     * Checks for XHR requests; if detected, attempts to perform context switch.
     *
     * @param  string $format
     * @return void
     */
    public function initContext($format = null)
    {
        $this->_currentContext = null;

        $request = $this->getRequest();
        if (!method_exists($request, 'isXmlHttpRequest') ||
            !$this->getRequest()->isXmlHttpRequest())
        {
            return;
        }

        return parent::initContext($format);
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Cache.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Controller_Action_Helper_Abstract
 */
require_once 'Zend/Controller/Action/Helper/Abstract.php';

/**
 * @see Zend_Controller_Action_Exception
 */
require_once 'Zend/Controller/Action/Exception.php';

/**
 * @see Zend_Cache_Manager
 */
require_once 'Zend/Cache/Manager.php';

/**
 * @category   Zend
 * @package    Zend_Controller
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Controller_Action_Helper_Cache
    extends Zend_Controller_Action_Helper_Abstract
{

    /**
     * Local Cache Manager object used by Helper
     *
     * @var Zend_Cache_Manager
     */
    protected $_manager = null;

    /**
     * Indexed map of Actions to attempt Page caching on by Controller
     *
     * @var array
     */
    protected $_caching = array();

    /**
     * Indexed map of Tags by Controller and Action
     *
     * @var array
     */
    protected $_tags = array();

    /**
     * Indexed map of Extensions by Controller and Action
     *
     * @var array
     */
    protected $_extensions = array();

    /**
     * Track output buffering condition
     */
    protected $_obStarted = false;

    /**
     * Tell the helper which actions are cacheable and under which
     * tags (if applicable) they should be recorded with
     *
     * @param array $actions
     * @param array $tags
     * @return void
     */
    public function direct(array $actions, array $tags = array(), $extension = null)
    {
        $controller = $this->getRequest()->getControllerName();
        $actions = array_unique($actions);
        if (!isset($this->_caching[$controller])) {
            $this->_caching[$controller] = array();
        }
        if (!empty($tags)) {
            $tags = array_unique($tags);
            if (!isset($this->_tags[$controller])) {
                $this->_tags[$controller] = array();
            }
        }
        foreach ($actions as $action) {
            $this->_caching[$controller][] = $action;
            if (!empty($tags)) {
                $this->_tags[$controller][$action] = array();
                foreach ($tags as $tag) {
                    $this->_tags[$controller][$action][] = $tag;
                }
            }
        }
        if ($extension) {
            if (!isset($this->_extensions[$controller])) {
                $this->_extensions[$controller] = array();
            }
            foreach ($actions as $action) {
                $this->_extensions[$controller][$action] = $extension;
            }
        }
    }

    /**
     * Remove a specific page cache static file based on its
     * relative URL from the application's public directory.
     * The file extension is not required here; usually matches
     * the original REQUEST_URI that was cached.
     *
     * @param string $relativeUrl
     * @param bool $recursive
     * @return mixed
     */
    public function removePage($relativeUrl, $recursive = false)
    {
        $cache = $this->getCache(Zend_Cache_Manager::PAGECACHE);
        if ($recursive) {
            $backend = $cache->getBackend();
            if (($backend instanceof Zend_Cache_Backend)
                && method_exists($backend, 'removeRecursively')
            ) {
                return $backend->removeRecursively($relativeUrl);
            }
        }

        return $cache->remove($relativeUrl);
    }

    /**
     * Remove a specific page cache static file based on its
     * relative URL from the application's public directory.
     * The file extension is not required here; usually matches
     * the original REQUEST_URI that was cached.
     *
     * @param array $tags
     * @return mixed
     */
    public function removePagesTagged(array $tags)
    {
        return $this->getCache(Zend_Cache_Manager::PAGECACHE)
            ->clean(Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, $tags);
    }

    /**
     * Commence page caching for any cacheable actions
     *
     * @return void
     */
    public function preDispatch()
    {
        $controller = $this->getRequest()->getControllerName();
        $action = $this->getRequest()->getActionName();
        $stats = ob_get_status(true);
        foreach ($stats as $status) {
            if ($status['name'] == 'Zend_Cache_Frontend_Page::_flush'
            || $status['name'] == 'Zend_Cache_Frontend_Capture::_flush') {
                $obStarted = true;
            }
        }
        if (!isset($obStarted) && isset($this->_caching[$controller]) &&
        in_array($action, $this->_caching[$controller])) {
            $reqUri = $this->getRequest()->getRequestUri();
            $tags = array();
            if (isset($this->_tags[$controller][$action])
            && !empty($this->_tags[$controller][$action])) {
                $tags = array_unique($this->_tags[$controller][$action]);
            }
            $extension = null;
            if (isset($this->_extensions[$controller][$action])) {
                $extension = $this->_extensions[$controller][$action];
            }
            $this->getCache(Zend_Cache_Manager::PAGECACHE)
                ->start($this->_encodeCacheId($reqUri), $tags, $extension);
        }
    }

    /**
     * Encode a Cache ID as hexadecimal. This is a workaround because Backend ID validation
     * is trapped in the Frontend classes. Will try to get this reversed for ZF 2.0
     * because it's a major annoyance to have IDs so restricted!
     *
     * @return string
     * @param string $requestUri
     */
    protected function _encodeCacheId($requestUri)
    {
        return bin2hex($requestUri);
    }

    /**
     * Set an instance of the Cache Manager for this helper
     *
     * @param Zend_Cache_Manager $manager
     * @return void
     */
    public function setManager(Zend_Cache_Manager $manager)
    {
        $this->_manager = $manager;
        return $this;
    }

    /**
     * Get the Cache Manager instance or instantiate the object if not
     * exists. Attempts to load from bootstrap if available.
     *
     * @return Zend_Cache_Manager
     */
    public function getManager()
    {
        if ($this->_manager !== null) {
            return $this->_manager;
        }
        $front = Zend_Controller_Front::getInstance();
        if ($front->getParam('bootstrap')
        && $front->getParam('bootstrap')->getResource('CacheManager')) {
            return $front->getParam('bootstrap')
                ->getResource('CacheManager');
        }
        $this->_manager = new Zend_Cache_Manager;
        return $this->_manager;
    }

    /**
     * Return a list of actions for the current Controller marked for
     * caching
     *
     * @return array
     */
    public function getCacheableActions()
    {
        return $this->_caching;
    }

    /**
     * Return a list of tags set for all cacheable actions
     *
     * @return array
     */
    public function getCacheableTags()
    {
        return $this->_tags;
    }

    /**
     * Proxy non-matched methods back to Zend_Cache_Manager where
     * appropriate
     *
     * @param string $method
     * @param array $args
     * @return mixed
     */
    public function __call($method, $args)
    {
        if (method_exists($this->getManager(), $method)) {
            return call_user_func_array(
                array($this->getManager(), $method), $args
            );
        }
        throw new Zend_Controller_Action_Exception('Method does not exist:'
            . $method);
    }

}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Abstract.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Controller_Action
 */
require_once 'Zend/Controller/Action.php';

/**
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
abstract class Zend_Controller_Action_Helper_Abstract
{
    /**
     * $_actionController
     *
     * @var Zend_Controller_Action $_actionController
     */
    protected $_actionController = null;

    /**
     * @var mixed $_frontController
     */
    protected $_frontController = null;

    /**
     * setActionController()
     *
     * @param  Zend_Controller_Action $actionController
     * @return Zend_Controller_ActionHelper_Abstract Provides a fluent interface
     */
    public function setActionController(Zend_Controller_Action $actionController = null)
    {
        $this->_actionController = $actionController;
        return $this;
    }

    /**
     * Retrieve current action controller
     *
     * @return Zend_Controller_Action
     */
    public function getActionController()
    {
        return $this->_actionController;
    }

    /**
     * Retrieve front controller instance
     *
     * @return Zend_Controller_Front
     */
    public function getFrontController()
    {
        return Zend_Controller_Front::getInstance();
    }

    /**
     * Hook into action controller initialization
     *
     * @return void
     */
    public function init()
    {
    }

    /**
     * Hook into action controller preDispatch() workflow
     *
     * @return void
     */
    public function preDispatch()
    {
    }

    /**
     * Hook into action controller postDispatch() workflow
     *
     * @return void
     */
    public function postDispatch()
    {
    }

    /**
     * getRequest() -
     *
     * @return Zend_Controller_Request_Abstract $request
     */
    public function getRequest()
    {
        $controller = $this->getActionController();
        if (null === $controller) {
            $controller = $this->getFrontController();
        }

        return $controller->getRequest();
    }

    /**
     * getResponse() -
     *
     * @return Zend_Controller_Response_Abstract $response
     */
    public function getResponse()
    {
        $controller = $this->getActionController();
        if (null === $controller) {
            $controller = $this->getFrontController();
        }

        return $controller->getResponse();
    }

    /**
     * getName()
     *
     * @return string
     */
    public function getName()
    {
        $fullClassName = get_class($this);
        if (strpos($fullClassName, '_') !== false) {
            $helperName = strrchr($fullClassName, '_');
            return ltrim($helperName, '_');
        } elseif (strpos($fullClassName, '\\') !== false) {
            $helperName = strrchr($fullClassName, '\\');
            return ltrim($helperName, '\\');
        } else {
            return $fullClassName;
        }
    }
}


text:
<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: ActionStack.php 23775 2011-03-01 17:25:24Z ralph $
 */

/**
 * @see Zend_Controller_Action_Helper_Abstract
 */
require_once 'Zend/Controller/Action/Helper/Abstract.php';

/**
 * Add to action stack
 *
 * @uses       Zend_Controller_Action_Helper_Abstract
 * @category   Zend
 * @package    Zend_Controller
 * @subpackage Zend_Controller_Action_Helper
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Controller_Action_Helper_ActionStack extends Zend_Controller_Action_Helper_Abstract
{
    /**
     * @var Zend_Controller_Plugin_ActionStack
     */
    protected $_actionStack;

    /**
     * Constructor
     *
     * Register action stack plugin
     *
     * @return void
     */
    public function __construct()
    {
        $front = Zend_Controller_Front::getInstance();
        if (!$front->hasPlugin('Zend_Controller_Plugin_ActionStack')) {
            /**
             * @see Zend_Controller_Plugin_ActionStack
             */
            require_once 'Zend/Controller/Plugin/ActionStack.php';
            $this->_actionStack = new Zend_Controller_Plugin_ActionStack();
            $front->registerPlugin($this->_actionStack, 97);
        } else {
            $this->_actionStack = $front->getPlugin('Zend_Controller_Plugin_ActionStack');
        }
    }

    /**
     * Push onto the stack
     *
     * @param  Zend_Controller_Request_Abstract $next
     * @return Zend_Controller_Action_Helper_ActionStack Provides a fluent interface
     */
    public function pushStack(Zend_Controller_Request_Abstract $next)
    {
        $this->_actionStack->pushStack($next);
        return $this;
    }

    /**
     * Push a new action onto the stack
     *
     * @param  string $action
     * @param  string $controller
     * @param  string $module
     * @param  array  $params
     * @throws Zend_Controller_Action_Exception
     * @return Zend_Controller_Action_Helper_ActionStack
     */
    public function actionToStack($action, $controller = null, $module = null, array $params = array())
    {
        if ($action instanceof Zend_Controller_Request_Abstract) {
            return $this->pushStack($action);
        } elseif (!is_string($action)) {
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception('ActionStack requires either a request object or minimally a string action');
        }

        $request = $this->getRequest();

        if ($request instanceof Zend_Controller_Request_Abstract === false){
            /**
             * @see Zend_Controller_Action_Exception
             */
            require_once 'Zend/Controller/Action/Exception.php';
            throw new Zend_Controller_Action_Exception('Request object not set yet');
        }

        $controller = (null === $controller) ? $request->getControllerName() : $controller;
        $module = (null === $module) ? $request->getModuleName() : $module;

        /**
         * @see Zend_Controller_Request_Simple
         */
        require_once 'Zend/Controller/Request/Simple.php';
        $newRequest = new Zend_Controller_Request_Simple($action, $controller, $module, $params);

        return $this->pushStack($newRequest);
    }

    /**
     * Perform helper when called as $this->_helper->actionStack() from an action controller
     *
     * Proxies to {@link simple()}
     *
     * @param  string $action
     * @param  string $controller
     * @param  string $module
     * @param  array $params
     * @return boolean
     */
    public function direct($action, $controller = null, $module = null, array $params = array())
    {
        return $this->actionToStack($action, $controller, $module, $params);
    }
}