Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/cakephp/cakephp/src/Routing/DispatcherFilter.php
<?php
/**
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 * @link          https://cakephp.org CakePHP(tm) Project
 * @since         2.2.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 */
namespace Cake\Routing;

use
Cake\Core\InstanceConfigTrait;
use
Cake\Event\Event;
use
Cake\Event\EventListenerInterface;
use
InvalidArgumentException;

/**
 * This abstract class represents a filter to be applied to a dispatcher cycle. It acts as an
 * event listener with the ability to alter the request or response as needed before it is handled
 * by a controller or after the response body has already been built.
 *
 * Subclasses of this class use a class naming convention having a `Filter` suffix.
 *
 * ### Limiting filters to specific paths
 *
 * By using the `for` option you can limit with request paths a filter is applied to.
 * Both the before and after event will have the same conditions applied to them. For
 * example, if you only wanted a filter applied to blog requests you could do:
 *
 * ```
 * $filter = new BlogFilter(['for' => '/blog']);
 * ```
 *
 * When the above filter is connected to a dispatcher it will only fire
 * its `beforeDispatch` and `afterDispatch` methods on requests that start with `/blog`.
 *
 * The for condition can also be a regular expression by using the `preg:` prefix:
 *
 * ```
 * $filter = new BlogFilter(['for' => 'preg:#^/blog/\d+$#']);
 * ```
 *
 * ### Limiting filters based on conditions
 *
 * In addition to simple path based matching you can use a closure to match on arbitrary request
 * or response conditions. For example:
 *
 * ```
 * $cookieMonster = new CookieFilter([
 *   'when' => function ($req, $res) {
 *     // Custom code goes here.
 *   }
 * ]);
 * ```
 *
 * If your when condition returns `true` the before/after methods will be called.
 *
 * When using the `for` or `when` matchers, conditions will be re-checked on the before and after
 * callback as the conditions could change during the dispatch cycle.
 */
class DispatcherFilter implements EventListenerInterface
{
    use
InstanceConfigTrait;

   
/**
     * Default priority for all methods in this filter
     *
     * @var int
     */
   
protected $_priority = 10;

   
/**
     * Default config
     *
     * These are merged with user-provided config when the class is used.
     * The when and for options allow you to define conditions that are checked before
     * your filter is called.
     *
     * @var array
     */
   
protected $_defaultConfig = [
       
'when' => null,
       
'for' => null,
       
'priority' => null,
    ];

   
/**
     * Constructor.
     *
     * @param array $config Settings for the filter.
     * @throws \InvalidArgumentException When 'when' conditions are not callable.
     */
   
public function __construct($config = [])
    {
        if (!isset(
$config['priority'])) {
           
$config['priority'] = $this->_priority;
        }
       
$this->setConfig($config);
        if (isset(
$config['when']) && !is_callable($config['when'])) {
            throw new
InvalidArgumentException('"when" conditions must be a callable.');
        }
    }

   
/**
     * Returns the list of events this filter listens to.
     * Dispatcher notifies 2 different events `Dispatcher.before` and `Dispatcher.after`.
     * By default this class will attach `preDispatch` and `postDispatch` method respectively.
     *
     * Override this method at will to only listen to the events you are interested in.
     *
     * @return array
     */
   
public function implementedEvents()
    {
        return [
           
'Dispatcher.beforeDispatch' => [
               
'callable' => 'handle',
               
'priority' => $this->_config['priority'],
            ],
           
'Dispatcher.afterDispatch' => [
               
'callable' => 'handle',
               
'priority' => $this->_config['priority'],
            ],
        ];
    }

   
/**
     * Handler method that applies conditions and resolves the correct method to call.
     *
     * @param \Cake\Event\Event $event The event instance.
     * @return mixed
     */
   
public function handle(Event $event)
    {
       
$name = $event->getName();
        list(,
$method) = explode('.', $name);
        if (empty(
$this->_config['for']) && empty($this->_config['when'])) {
            return
$this->{$method}($event);
        }
        if (
$this->matches($event)) {
            return
$this->{$method}($event);
        }
    }

   
/**
     * Check to see if the incoming request matches this filter's criteria.
     *
     * @param \Cake\Event\Event $event The event to match.
     * @return bool
     */
   
public function matches(Event $event)
    {
       
/** @var \Cake\Http\ServerRequest $request */
       
$request = $event->getData('request');
       
$pass = true;
        if (!empty(
$this->_config['for'])) {
           
$len = strlen('preg:');
           
$for = $this->_config['for'];
           
$url = $request->getRequestTarget();
            if (
substr($for, 0, $len) === 'preg:') {
               
$pass = (bool)preg_match(substr($for, $len), $url);
            } else {
               
$pass = strpos($url, $for) === 0;
            }
        }
        if (
$pass && !empty($this->_config['when'])) {
           
$response = $event->getData('response');
           
$pass = $this->_config['when']($request, $response);
        }

        return
$pass;
    }

   
/**
     * Method called before the controller is instantiated and called to serve a request.
     * If used with default priority, it will be called after the Router has parsed the
     * URL and set the routing params into the request object.
     *
     * If a Cake\Http\Response object instance is returned, it will be served at the end of the
     * event cycle, not calling any controller as a result. This will also have the effect of
     * not calling the after event in the dispatcher.
     *
     * If false is returned, the event will be stopped and no more listeners will be notified.
     * Alternatively you can call `$event->stopPropagation()` to achieve the same result.
     *
     * @param \Cake\Event\Event $event container object having the `request`, `response` and `additionalParams`
     *    keys in the data property.
     * @return void
     */
   
public function beforeDispatch(Event $event)
    {
    }

   
/**
     * Method called after the controller served a request and generated a response.
     * It is possible to alter the response object at this point as it is not sent to the
     * client yet.
     *
     * If false is returned, the event will be stopped and no more listeners will be notified.
     * Alternatively you can call `$event->stopPropagation()` to achieve the same result.
     *
     * @param \Cake\Event\Event $event container object having the `request` and  `response`
     *    keys in the data property.
     * @return void
     */
   
public function afterDispatch(Event $event)
    {
    }
}