<commit_before>
namespace Ice;

use Ice\Mvc\ModuleInterface;

/**
 * The base class for Ice\Mvc\Dispatcher and Ice\CLI\Dispatcher.
 * For the response from router and in the specified module, create instance of handler with action and params.
 *
 * @package     Ice/Dispatcher
 * @category    Component
 * @author      Ice Team
 * @copyright   (c) 2014-2015 Ice Team
 * @license     http://iceframework.org/license
 */
abstract class Dispatcher 
{

    protected di;
    protected defaultNamespace { get, set };
    protected activeHandler { get };
    protected lastHandler { get };

    protected loops = 0 { get };
    protected finished { get };
    protected forwarded = false { get };
    protected silent = false { set };

    protected modules = [] { get, set };
    protected module = null { get, set };
    protected $namespace = null { get, set };
    protected handler = null { get, set };
    protected action = null { get, set };

    protected params = [] { get, set };
    protected returnedValue = null { get, set };

    protected handlerSuffix = "Handler" { get, set };
    protected actionSuffix = "Action" { get, set };

    protected previousModule = null;
    protected previousHandler = null;
    protected previousAction = null;

    const DISPATCH_CYCLIC = 1;
    const HANDLER_NOT_FOUND = 2;
    const ACTION_NOT_FOUND = 3;
    const INVALID_PARAMS = 4;

    /**
     * Di constructor. Fetch Di and set it as a property.
     */
    public function __construct()
    {
        let this->di = Di::$fetch();
    }

    /**
     * Whether or not an param exists by key.
     *
     * @param string key The param key
     * @return boolean
     */
    public function hasParam(string key) -> boolean
    {
        return isset this->params[key];
    }

    /**
     * Set a param by its name or numeric index.
     *
     * @param mixed param
     * @param mixed value
     */
    public function setParam(var param, var value)
    {
        let this->params[param] = value;
    }

    /**
     * Gets variable from params attribute applying filters if needed.
     * If no parameters are given, return all.
     *
     * <pre><code>
     *  //Returns value from $params["id"] without sanitizing
     *  $id = $this->router->getParam("id");
     *
     *  //Returns value from $params["title"] with sanitizing
     *  $title = $this->router->getParam("title", "escape|repeats");
     *
     *  //Returns value from $params["id"] with a default value
     *  $id = $this->router->getParam("id", null, 150);
     * </code></pre>
     *
     * @param string key Index to get
     * @param string|array filters Filters to apply
     * @param mixed defaultValue Default value if key not exist or value is empty and allowEmpty is false
     * @param boolean allowEmpty
     * @return mixed
     */
    public function getParam(string key = null, var filters = null, var defaultValue = null, boolean allowEmpty = false)
    {
        var params, value, filter;

        let params = new Arr(this->params);

        if !key {
            return params;
        } else {
            let value = params->get(key, defaultValue);

            if filters {
                let filter = Di::$fetch()->get("filter"),
                    value = filter->sanitize(value, filters);
            }

            if (value === "" || value === null) && allowEmpty === false {
                return defaultValue;
            }

            return value;
        }
    }

    /**
     * Returns the current method to be/executed in the dispatcher.
     *
     * @return string
     */
    public function getActiveMethod() -> string
    {
        return this->action . this->actionSuffix;
    }

    /**
     * Dispatches a handle action taking into account the routing parameters.
     *
     * @return object
     */
    public function dispatch()
    {
        var handler, response, handlerName, actionName, params, handlerSuffix, handlerClass, actionMethod;
        var fresh, module, modules, moduleNamespace, path, moduleClass, loader;

        let response = this->di->get("response"),
            fresh = true,
            handler = null,
            handlerSuffix = this->handlerSuffix,
            this->finished = false;

        while !this->finished {
            let this->loops++;

            // Throw an exception after 16 consecutive forwards
            if this->loops > 16 {
                if this->silent {
                    // 508 Loop Detected
                    response->setStatus(508);
                    response->setBody(response->getMessage(508));

                    return response;
                }
                throw new Exception("Dispatcher has detected a cyclic routing causing stability problems", self::DISPATCH_CYCLIC);
            }

            let this->finished = true,
                modules = this->modules;

            if modules {
                if !fetch module, modules[this->module] {
                    throw new Exception(["Module '%s' isn't registered in the application container", this->module]);<commit_msg>Dispatcher, add limit of forwards<commit_after>
namespace Ice;

use Ice\Mvc\ModuleInterface;

/**
 * The base class for Ice\Mvc\Dispatcher and Ice\CLI\Dispatcher.
 * For the response from router and in the specified module, create instance of handler with action and params.
 *
 * @package     Ice/Dispatcher
 * @category    Component
 * @author      I<NAME>
 * @copyright   (c) 2014-2015 Ice Team
 * @license     http://iceframework.org/license
 */
abstract class Dispatcher 
{

    protected di;
    protected defaultNamespace { get, set };
    protected activeHandler { get };
    protected lastHandler { get };

    protected loops = 16 { get, set };
    protected finished { get };
    protected forwards = 0 { get };
    protected forwarded = false { get };
    protected silent = false { set };

    protected modules = [] { get, set };
    protected module = null { get, set };
    protected $namespace = null { get, set };
    protected handler = null { get, set };
    protected action = null { get, set };

    protected params = [] { get, set };
    protected returnedValue = null { get, set };

    protected handlerSuffix = "Handler" { get, set };
    protected actionSuffix = "Action" { get, set };

    protected previousModule = null;
    protected previousHandler = null;
    protected previousAction = null;

    const DISPATCH_CYCLIC = 1;
    const HANDLER_NOT_FOUND = 2;
    const ACTION_NOT_FOUND = 3;
    const INVALID_PARAMS = 4;

    /**
     * Di constructor. Fetch Di and set it as a property.
     */
    public function __construct()
    {
        let this->di = Di::$fetch();
    }

    /**
     * Whether or not an param exists by key.
     *
     * @param string key The param key
     * @return boolean
     */
    public function hasParam(string key) -> boolean
    {
        return isset this->params[key];
    }

    /**
     * Set a param by its name or numeric index.
     *
     * @param mixed param
     * @param mixed value
     */
    public function setParam(var param, var value)
    {
        let this->params[param] = value;
    }

    /**
     * Gets variable from params attribute applying filters if needed.
     * If no parameters are given, return all.
     *
     * <pre><code>
     *  //Returns value from $params["id"] without sanitizing
     *  $id = $this->router->getParam("id");
     *
     *  //Returns value from $params["title"] with sanitizing
     *  $title = $this->router->getParam("title", "escape|repeats");
     *
     *  //Returns value from $params["id"] with a default value
     *  $id = $this->router->getParam("id", null, 150);
     * </code></pre>
     *
     * @param string key Index to get
     * @param string|array filters Filters to apply
     * @param mixed defaultValue Default value if key not exist or value is empty and allowEmpty is false
     * @param boolean allowEmpty
     * @return mixed
     */
    public function getParam(string key = null, var filters = null, var defaultValue = null, boolean allowEmpty = false)
    {
        var params, value, filter;

        let params = new Arr(this->params);

        if !key {
            return params;
        } else {
            let value = params->get(key, defaultValue);

            if filters {
                let filter = Di::$fetch()->get("filter"),
                    value = filter->sanitize(value, filters);
            }

            if (value === "" || value === null) && allowEmpty === false {
                return defaultValue;
            }

            return value;
        }
    }

    /**
     * Returns the current method to be/executed in the dispatcher.
     *
     * @return string
     */
    public function getActiveMethod() -> string
    {
        return this->action . this->actionSuffix;
    }

    /**
     * Dispatches a handle action taking into account the routing parameters.
     *
     * @return object
     */
    public function dispatch()
    {
        var handler, response, handlerName, actionName, params, handlerSuffix, handlerClass, actionMethod;
        var fresh, module, modules, moduleNamespace, path, moduleClass, loader;

        let response = this->di->get("response"),
            fresh = true,
            handler = null,
            handlerSuffix = this->handlerSuffix,
            this->finished = false;

        while !this->finished {
            let this->forwards++;

            // Throw an exception after 16 consecutive forwards
            if this->loops && this->forwards > this->loops {
                if this->silent {
                    // 508 Loop Detected
                    response->setStatus(508);
                    response->setBody(response->getMessage(508));

                    return response;
                }
                throw new Exception("Dispatcher has detected a cyclic routing causing stability problems", self::DISPATCH_CYCLIC);
            }

            let this->finished = true,
                modules = this->modules;

            if modules {
                if !fetch module, modules[this->module] {
                    throw new Exception(["Module '%s' isn't registered in the application container", this->module]);
{'fraction_non_alphanumeric': 0.1054172767203514, 'fraction_numerical': 0.005661298194241093, 'mean_word_length': 2.018856806128462, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 80, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5066778', 'n_tokens_mistral': 2778, 'n_tokens_neox': 2632, 'n_words': 908}