<commit_before><?php

namespace Vectorface\SnappyRouter\Handler;

use Vectorface\SnappyRouter\Di\Di;
use Vectorface\SnappyRouter\Di\DiProvider;
use Vectorface\SnappyRouter\Di\ServiceProvider;
use Vectorface\SnappyRouter\Exception\PluginException;

/**
 * The base class for all handlers.
 * @copyright Copyright (c) 2014, VectorFace, Inc.
 * @author <NAME> <<EMAIL>>
 */
abstract class AbstractHandler implements DiProvider
{
    const KEY_CLASS    = 'class';
    const KEY_OPTIONS  = 'options';
    const KEY_SERVICES = 'services';
    const KEY_PLUGINS  = 'plugins';

    /** an array of handler-specific options */
    protected $options;

    /** a sorted array of handler plugins */
    private $plugins;

    /** the service provider to use */
    private $serviceProvider;

    /**
     * Constructor for the class.
     * @param array $options An array of options for the plugin.
     */
    public function __construct($options)
    {
        $this->options = $options;
        $this->plugins = array();
        if (isset($options[self::KEY_PLUGINS])) {
            $this->setPlugins((array)$options[self::KEY_PLUGINS]);
        }
        $services = array();
        if (isset($options[self::KEY_SERVICES])) {
            $services = (array)$options[self::KEY_SERVICES];
        }
        $this->serviceProvider = new ServiceProvider($services);
    }

    /**
     * Retrieve an element from the DI container.
     * @param string $key The DI key.
     * @param boolean $useCache (optional) An optional indicating whether we
     *        should use the cached version of the element (true by default).
     * @return Returns the DI element mapped to that key.
     */
    public function get($key, $useCache = true)
    {
        return Di::getDefault()->get($key, $useCache);
    }

    /**
     * Sets an element in the DI container for the specified key.
     * @param string $key The DI key.
     * @param mixed  $element The DI element to store.
     * @return Di Returns the Di instance.
     */
    public function set($key, $element)
    {
        return Di::getDefault()->set($key, $element);
    }

    /**
     * Returns the active service provider for this handler.
     * @return ServiceProvider The active service provider for this handler.
     */
    public function getServiceProvider()
    {
        return $this->serviceProvider;
    }

    /**
     * Performs the actual routing.
     * @return Returns the result of the route.
     */
    abstract public function performRoute();

    /**
     * Returns the array of plugins registered with this handler.
     */
    public function getPlugins()
    {
        return $this->plugins;
    }

    /**
     * Sets the current list of plugins.
     * @param array $plugins The array of plugins.
     * @return AbstractHandler Returns $this.
     */
    public function setPlugins($plugins)
    {
        $this->plugins = array();
        foreach ($plugins as $key => $plugin) {
            $pluginClass = $plugin;
            if (is_array($plugin)) {
                if (!isset($plugin[AbstractHandler::KEY_CLASS])) {
                    throw new PluginException('Invalid or missing class for plugin '.$key);
                } elseif (!class_exists($plugin[AbstractHandler::KEY_CLASS])) {
                    throw new PluginException('Invalid or missing class for plugin '.$key);
                }
                $pluginClass = $plugin[AbstractHandler::KEY_CLASS];
            }
            $options = array();
            if (isset($plugin[AbstractHandler::KEY_OPTIONS])) {
                $options = (array($plugin[AbstractHandler::KEY_OPTIONS]));
            }
            $this->plugins[] = new $pluginClass($options);
        }
        $this->plugins = $this->sortPlugins($this->plugins);
        return $this;
    }

    // sorts the list of plugins according to their execution order
    private function sortPlugins($plugins)
    {
        usort($plugins, function ($a, $b) {
            return $a->getExecutionOrder() - $b->getExecutionOrder();
        });
        return $plugins;
    }

    /**
     * Invokes the plugin hook against all the listed plugins.
     * @param string $hook The hook to invoke.
     * @param array $args The arguments to pass to the call.
     */
    public function invokePluginsHook($hook, $args)
    {
        foreach ($this->getPlugins() as $plugin) {
            call_user_func_array(array($plugin, $hook), $args);
        }
    }
}<commit_msg>AbstractHandler::invokePluginHooks now only invokes the hook if the specified plugin supports that method.<commit_after><?php

namespace Vectorface\SnappyRouter\Handler;

use Vectorface\SnappyRouter\Di\Di;
use Vectorface\SnappyRouter\Di\DiProvider;
use Vectorface\SnappyRouter\Di\ServiceProvider;
use Vectorface\SnappyRouter\Exception\PluginException;

/**
 * The base class for all handlers.
 * @copyright Copyright (c) 2014, VectorFace, Inc.
 * @author <NAME> <<EMAIL>>
 */
abstract class AbstractHandler implements DiProvider
{
    const KEY_CLASS    = 'class';
    const KEY_OPTIONS  = 'options';
    const KEY_SERVICES = 'services';
    const KEY_PLUGINS  = 'plugins';

    /** an array of handler-specific options */
    protected $options;

    /** a sorted array of handler plugins */
    private $plugins;

    /** the service provider to use */
    private $serviceProvider;

    /**
     * Constructor for the class.
     * @param array $options An array of options for the plugin.
     */
    public function __construct($options)
    {
        $this->options = $options;
        $this->plugins = array();
        if (isset($options[self::KEY_PLUGINS])) {
            $this->setPlugins((array)$options[self::KEY_PLUGINS]);
        }
        $services = array();
        if (isset($options[self::KEY_SERVICES])) {
            $services = (array)$options[self::KEY_SERVICES];
        }
        $this->serviceProvider = new ServiceProvider($services);
    }

    /**
     * Retrieve an element from the DI container.
     * @param string $key The DI key.
     * @param boolean $useCache (optional) An optional indicating whether we
     *        should use the cached version of the element (true by default).
     * @return Returns the DI element mapped to that key.
     */
    public function get($key, $useCache = true)
    {
        return Di::getDefault()->get($key, $useCache);
    }

    /**
     * Sets an element in the DI container for the specified key.
     * @param string $key The DI key.
     * @param mixed  $element The DI element to store.
     * @return Di Returns the Di instance.
     */
    public function set($key, $element)
    {
        return Di::getDefault()->set($key, $element);
    }

    /**
     * Returns the active service provider for this handler.
     * @return ServiceProvider The active service provider for this handler.
     */
    public function getServiceProvider()
    {
        return $this->serviceProvider;
    }

    /**
     * Performs the actual routing.
     * @return Returns the result of the route.
     */
    abstract public function performRoute();

    /**
     * Returns the array of plugins registered with this handler.
     */
    public function getPlugins()
    {
        return $this->plugins;
    }

    /**
     * Sets the current list of plugins.
     * @param array $plugins The array of plugins.
     * @return AbstractHandler Returns $this.
     */
    public function setPlugins($plugins)
    {
        $this->plugins = array();
        foreach ($plugins as $key => $plugin) {
            $pluginClass = $plugin;
            if (is_array($plugin)) {
                if (!isset($plugin[AbstractHandler::KEY_CLASS])) {
                    throw new PluginException('Invalid or missing class for plugin '.$key);
                } elseif (!class_exists($plugin[AbstractHandler::KEY_CLASS])) {
                    throw new PluginException('Invalid or missing class for plugin '.$key);
                }
                $pluginClass = $plugin[AbstractHandler::KEY_CLASS];
            }
            $options = array();
            if (isset($plugin[AbstractHandler::KEY_OPTIONS])) {
                $options = (array($plugin[AbstractHandler::KEY_OPTIONS]));
            }
            $this->plugins[] = new $pluginClass($options);
        }
        $this->plugins = $this->sortPlugins($this->plugins);
        return $this;
    }

    // sorts the list of plugins according to their execution order
    private function sortPlugins($plugins)
    {
        usort($plugins, function ($a, $b) {
            return $a->getExecutionOrder() - $b->getExecutionOrder();
        });
        return $plugins;
    }

    /**
     * Invokes the plugin hook against all the listed plugins.
     * @param string $hook The hook to invoke.
     * @param array $args The arguments to pass to the call.
     */
    public function invokePluginsHook($hook, $args)
    {
        foreach ($this->getPlugins() as $plugin) {
            if (method_exists($plugin, $hook)) {
                call_user_func_array(array($plugin, $hook), $args);
            }
        }
    }
}
{'fraction_non_alphanumeric': 0.11587510993843447, 'fraction_numerical': 0.0008795074758135445, 'mean_word_length': 2.343256155825064, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 43, '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': '6268266', 'n_tokens_mistral': 2452, 'n_tokens_neox': 2397, 'n_words': 743}