<?php

/*
 * This file is part of the Valkyrja framework.
 *
 * (c) Melech Mizrachi
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Valkyrja\Dispatcher;

use Valkyrja\Application;
use Valkyrja\Container\Service;
use Valkyrja\Dispatcher\Exceptions\InvalidClosureException;
use Valkyrja\Dispatcher\Exceptions\InvalidDispatchCapabilityException;
use Valkyrja\Dispatcher\Exceptions\InvalidFunctionException;
use Valkyrja\Dispatcher\Exceptions\InvalidMethodException;
use Valkyrja\Dispatcher\Exceptions\InvalidPropertyException;

/**
 * Class Dispatcher.
 *
 * @author Melech Mizrachi
 */
class NativeDispatcher implements Dispatcher
{
    /**
     * The return value to use when a dispatch was successful
     * but no data was returned from the dispatch.
     * This avoids having to check each and every
     * other type of dispatch down the chain.
     *
     * @var string
     */
    protected $DISPATCHED = 'dispatcher.dispatched';

    /**
     * The application.
     *
     * @var \Valkyrja\Application
     */
    protected $app;

    /**
     * Dispatcher constructor.
     *
     * @param Application $application The application
     */
    public function __construct(Application $application)
    {
        $this->app = $application;
    }

    /**
     * Verify the class and method of a dispatch.
     *
     * @param Dispatch $dispatch The dispatch
     *
     * @throws \Valkyrja\Dispatcher\Exceptions\InvalidMethodException
     *
     * @return void
     */
    public function verifyClassMethod(Dispatch $dispatch): void
    {
        // If a class and method are set and not callable
        if (
            null !== $dispatch->getClass()
            && null !== $dispatch->getMethod()
            && ! method_exists(
                $dispatch->getClass(),
                $dispatch->getMethod()
            )
        ) {
            // Throw a new invalid method exception
            throw new InvalidMethodException(
                'Method does not exist in class : '
                . $dispatch->getName() . ' '
                . $dispatch->getClass()
                . '@'
                . $dispatch->getMethod()
            );
        }
    }

    /**
     * Verify the class and property of a dispatch.
     *
     * @param Dispatch $dispatch The dispatch
     *
     * @throws \Valkyrja\Dispatcher\Exceptions\InvalidPropertyException
     *
     * @return void
     */
    public function verifyClassProperty(Dispatch $dispatch): void
    {
        // If a class and method are set and not callable
        if (
            null !== $dispatch->getClass()
            && null !== $dispatch->getProperty()
            && ! property_exists(
                $dispatch->getClass(),
                $dispatch->getProperty()
            )
        ) {
            // Throw a new invalid property exception
            throw new InvalidPropertyException(
                'Property does not exist in class : '
                . $dispatch->getName() . ' '
                . $dispatch->getClass()
                . '@'
                . $dispatch->getProperty()
            );
        }
    }

    /**
     * Verify the function of a dispatch.
     *
     * @param Dispatch $dispatch The dispatch
     *
     * @throws \Valkyrja\Dispatcher\Exceptions\InvalidFunctionException
     *
     * @return void
     */
    public function verifyFunction(Dispatch $dispatch): void
    {
        // If a function is set and is not callable
        if (
            null !== $dispatch->getFunction()
            && ! \is_callable($dispatch->getFunction())
        ) {
            // Throw a new invalid function exception
            throw new InvalidFunctionException(
                'Function is not callable for : '
                . $dispatch->getName() . ' '
                . $dispatch->getFunction()
            );
        }
    }

    /**
     * Verify the closure of a dispatch.
     *
     * @param Dispatch $dispatch The dispatch
     *
     * @throws \Valkyrja\Dispatcher\Exceptions\InvalidClosureException
     *
     * @return void
     */
    public function verifyClosure(Dispatch $dispatch): void
    {
        // If a closure is set and is not callable
        if (
            null === $dispatch->getFunction()
            && null === $dispatch->getClass()
            && null === $dispatch->getMethod()
            && null === $dispatch->getProperty()
            && null === $dispatch->getClosure()
        ) {
            // Throw a new invalid closure exception
            throw new InvalidClosureException(
                'Closure is not valid for : '
                . $dispatch->getName()
            );
        }
    }

    /**
     * Verify the dispatch's dispatch capabilities.
     *
     * @param Dispatch $dispatch The dispatch
     *
     * @throws \Valkyrja\Dispatcher\Exceptions\InvalidClosureException
     * @throws \Valkyrja\Dispatcher\Exceptions\InvalidDispatchCapabilityException
     * @throws \Valkyrja\Dispatcher\Exceptions\InvalidFunctionException
     * @throws \Valkyrja\Dispatcher\Exceptions\InvalidMethodException
     * @throws \Valkyrja\Dispatcher\Exceptions\InvalidPropertyException
     *
     * @return void
     */
    public function verifyDispatch(Dispatch $dispatch): void
    {
        // If a function, closure, and class or method are not set
        if (
            null === $dispatch->getFunction()
            && null === $dispatch->getClosure()
            && null === $dispatch->getClass()
            && null === $dispatch->getMethod()
            && null === $dispatch->getProperty()

        ) {
            // Throw a new invalid dispatch capability exception
            throw new InvalidDispatchCapabilityException(
                'Dispatch capability is not valid for : '
                . $dispatch->getName()
            );
        }

        $this->verifyClassMethod($dispatch);
        $this->verifyClassProperty($dispatch);
        $this->verifyFunction($dispatch);
        $this->verifyClosure($dispatch);
    }

    /**
     * Get a dispatch's dependencies.
     *
     * @param Dispatch $dispatch The dispatch
     *
     * @return array
     */
    protected function getDependencies(Dispatch $dispatch): ? array
    {
        $dependencies = null;

        // If the dispatch is static it doesn't need dependencies
        if ($dispatch->isStatic()) {
            return $dependencies;
        }

        $dependencies = [];
        $context      = $dispatch->getClass() ?? $dispatch->getFunction();
        $member       = $dispatch->getProperty() ?? $dispatch->getMethod();

        // If there are dependencies
        if ($dispatch->getDependencies()) {
            // Iterate through all the dependencies
            foreach ($dispatch->getDependencies() as $dependency) {
                // Set the dependency in the list
                $dependencies[] = $this->app->container()->get(
                    $dependency,
                    null,
                    $context,
                    $member
                );
            }
        }

        return $dependencies;
    }

    /**
     * Get a dispatch's arguments.
     *
     * @param Dispatch $dispatch  The dispatch
     * @param array    $arguments [optional] The arguments
     *
     * @return array
     */
    protected function getArguments(Dispatch $dispatch, array $arguments = null): ? array
    {
        // Get either the arguments passed or from the dispatch model
        $arguments = $arguments ?? $dispatch->getArguments();
        $context   = $dispatch->getClass() ?? $dispatch->getFunction();
        $member    = $dispatch->getProperty() ?? $dispatch->getMethod();

        // Set the listener arguments to a new blank array
        $dependencies = $this->getDependencies($dispatch);

        // If there are no arguments
        if (null === $arguments) {
            // Return the dependencies only
            return $dependencies;
        }

        // Iterate through the arguments
        foreach ($arguments as $argument) {
            // If the argument is a service
            if ($argument instanceof Service) {
                // Dispatch the argument and set the results to the argument
                $argument = $this->app->container()->get(
                    $argument->getId(),
                    null,
                    $context,
                    $member
                );
            } // If the argument is a dispatch
            elseif ($argument instanceof Dispatch) {
                // Dispatch the argument and set the results to the argument
                $argument = $this->dispatchCallable($argument);
            }

            // Append the argument to the arguments list
            $dependencies[] = $argument;
        }

        return $dependencies;
    }

    /**
     * Dispatch a class method.
     *
     * @param Dispatch $dispatch  The dispatch
     * @param array    $arguments [optional] The arguments
     *
     * @return mixed
     */
    public function dispatchClassMethod(Dispatch $dispatch, array $arguments = null)
    {
        $response = null;

        // Ensure a class and method exist before continuing
        if (null === $dispatch->getClass() || null === $dispatch->getMethod()) {
            return $response;
        }

        // Set the class through the container if this isn't a static method
        $class    = $dispatch->isStatic()
            ? $dispatch->getClass()
            : $this->app->container()->get($dispatch->getClass());
        $method   = $dispatch->getMethod();
        $response = null;

        // If there are arguments
        if (null !== $arguments) {
            // Unpack arguments and dispatch
            if ($dispatch->isStatic()) {
                $response = $class::$method(...$arguments);
            } else {
                $response = $class->$method(...$arguments);
            }
        } else {
            // Dispatch without unpacking
            if ($dispatch->isStatic()) {
                $response = $class::$method();
            } else {
                $response = $class->$method();
            }
        }

        return $response ?? $this->DISPATCHED;
    }

    /**
     * Dispatch a class property.
     *
     * @param Dispatch $dispatch The dispatch
     *
     * @return mixed
     */
    public function dispatchClassProperty(Dispatch $dispatch)
    {
        $response = null;

        // Ensure a class and property exist before continuing
        if (
            null === $dispatch->getClass()
            || null === $dispatch->getProperty()
        ) {
            return $response;
        }

        $class    = $dispatch->getClass();
        $property = $dispatch->getProperty();

        // If this is a static property
        if ($dispatch->isStatic()) {
            $response = $class::$$property;
        } else {
            // Get the class from the container
            $class    = $this->app->container()->get($dispatch->getClass());
            $response = $class->{$property};
        }

        return $response ?? $this->DISPATCHED;
    }

    /**
     * Dispatch a class.
     *
     * @param Dispatch $dispatch  The dispatch
     * @param array    $arguments [optional] The arguments
     *
     * @return mixed
     */
    public function dispatchClass(Dispatch $dispatch, array $arguments = null)
    {
        // Ensure a class exists before continuing
        if (null === $dispatch->getClass()) {
            return $dispatch->getClass();
        }

        // If the class is the id then this item is not yet set
        // in the service container yet so it needs a new
        // instance returned
        if ($dispatch->getClass() === $dispatch->getId()) {
            // Get the class from the dispatcher
            $class = $dispatch->getClass();

            // If there are argument
            if (null !== $arguments) {
                // Get a new class instance with the arguments
                $class = new $class(...$arguments);
            } else {
                // Otherwise just get a new class instance
                $class = new $class();
            }
        } else {
            // Set the class through the container
            $class = $this->app->container()->get(
                $dispatch->getClass(),
                $arguments
            );
        }

        return $class ?? $this->DISPATCHED;
    }

    /**
     * Dispatch a function.
     *
     * @param Dispatch $dispatch  The dispatch
     * @param array    $arguments [optional] The arguments
     *
     * @return mixed
     */
    public function dispatchFunction(Dispatch $dispatch, array $arguments = null)
    {
        // Ensure a function exists before continuing
        if (null === $dispatch->getFunction()) {
            return $dispatch->getFunction();
        }

        $function = $dispatch->getFunction();
        $response = null;

        // If there are arguments
        if (null !== $arguments) {
            // Unpack arguments and dispatch
            $response = $function(...$arguments);
        } else {
            // Dispatch without unpacking
            $response = $function();
        }

        return $response ?? $this->DISPATCHED;
    }

    /**
     * Dispatch a closure.
     *
     * @param Dispatch $dispatch  The dispatch
     * @param array    $arguments [optional] The arguments
     *
     * @return mixed
     */
    public function dispatchClosure(Dispatch $dispatch, array $arguments = null)
    {
        // Ensure a closure exists before continuing
        if (null === $dispatch->getClosure()) {
            return $dispatch->getClosure();
        }

        $closure  = $dispatch->getClosure();
        $response = null;

        // If there are arguments
        if (null !== $arguments) {
            // Unpack arguments and dispatch
            $response = $closure(...$arguments);
        } else {
            // Dispatch without unpacking
            $response = $closure();
        }

        return $response ?? $this->DISPATCHED;
    }

    /**
     * Dispatch a callable.
     *
     * @param Dispatch $dispatch  The dispatch
     * @param array    $arguments [optional] The arguments
     *
     * @return mixed
     */
    public function dispatchCallable(Dispatch $dispatch, array $arguments = null)
    {
        // Get the arguments with dependencies
        $arguments = $this->getArguments($dispatch, $arguments);

        // Attempt to dispatch the dispatch
        $response = $this->dispatchClassMethod($dispatch, $arguments)
            ?? $this->dispatchClassProperty($dispatch)
            ?? $this->dispatchClass($dispatch, $arguments)
            ?? $this->dispatchFunction($dispatch, $arguments)
            ?? $this->dispatchClosure($dispatch, $arguments);
        // TODO: Add Constant and Variable ability

        // If the response was initially null and we added the dispatched
        // text to avoid calling each subsequent dispatcher thereafter
        if ($response === $this->DISPATCHED) {
            // Reset the response to null
            $response = null;
        }

        return $response;
    }
}


<?php

namespace Reaction\Web\Sessions;

/**
 * SessionIterator implements an [[\Iterator|iterator]] for traversing session variables managed by [[Session]].
 */
class SessionIterator implements \Iterator
{
    /**
     * @var array list of keys in the map
     */
    private $_keys;
    /**
     * @var mixed current key
     */
    private $_key;
    /**
     * @var RequestSessionInterface session data
     */
    private $_session;

    /**
     * Constructor.
     * @param RequestSessionInterface $session
     */
    public function __construct($session)
    {
        $this->_session = $session;
        $this->_keys = array_keys($this->_session->data);
    }

    /**
     * Rewinds internal array pointer.
     * This method is required by the interface [[\Iterator]].
     */
    public function rewind()
    {
        $this->_key = reset($this->_keys);
    }

    /**
     * Returns the key of the current array element.
     * This method is required by the interface [[\Iterator]].
     * @return mixed the key of the current array element
     */
    public function key()
    {
        return $this->_key;
    }

    /**
     * Returns the current array element.
     * This method is required by the interface [[\Iterator]].
     * @return mixed the current array element
     */
    public function current()
    {
        return isset($this->_session->data[$this->_key]) ? $this->_session->data[$this->_key] : null;
    }

    /**
     * Moves the internal pointer to the next array element.
     * This method is required by the interface [[\Iterator]].
     */
    public function next()
    {
        do {
            $this->_key = next($this->_keys);
        } while (!isset($this->_session->data[$this->_key]) && $this->_key !== false);
    }

    /**
     * Returns whether there is an element at current position.
     * This method is required by the interface [[\Iterator]].
     * @return bool
     */
    public function valid()
    {
        return $this->_key !== false;
    }
}


<?php

/*
 * This file is part of the Valkyrja framework.
 *
 * (c) Melech Mizrachi
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Valkyrja\Console\Input;

use Valkyrja\Application;
use Valkyrja\Http\Request;
use Valkyrja\Support\Providers\Provides;

/**
 * Class Input.
 *
 * @author Melech Mizrachi
 */
class NativeInput implements Input
{
    use Provides;

    /**
     * The request.
     *
     * @var \Valkyrja\Http\Request
     */
    protected $request;

    /**
     * The request arguments.
     *
     * @var array
     */
    protected $requestArguments;

    /**
     * The arguments.
     *
     * @var array
     */
    protected $arguments = [];

    /**
     * The short options.
     *
     * @var array
     */
    protected $shortOptions = [];

    /**
     * The long options.
     *
     * @var array
     */
    protected $longOptions = [];

    /**
     * Input constructor.
     *
     * @param Request $request The request
     */
    public function __construct(Request $request)
    {
        $this->request = $request;

        $this->parseRequestArguments();
    }

    /**
     * Get the arguments.
     *
     * @return array
     */
    public function getArguments(): array
    {
        return $this->arguments;
    }

    /**
     * Get the short options.
     *
     * @return array
     */
    public function getShortOptions(): array
    {
        return $this->shortOptions;
    }

    /**
     * Get the arguments.
     *
     * @return array
     */
    public function getLongOptions(): array
    {
        return $this->longOptions;
    }

    /**
     * Get the arguments.
     *
     * @return array
     */
    public function getOptions(): array
    {
        return array_merge($this->longOptions, $this->shortOptions);
    }

    /**
     * Get the arguments as a string.
     *
     * @return string
     */
    public function getStringArguments(): string
    {
        $arguments       = $this->getRequestArguments();
        $globalArguments = $this->getGlobalOptionsFlat();

        foreach ($arguments as $key => $argument) {
            if (\in_array($argument, $globalArguments, true)) {
                unset($arguments[$key]);
            }
        }

        return implode(' ', $arguments);
    }

    /**
     * Get the arguments from the request.
     *
     * @return array
     */
    public function getRequestArguments(): array
    {
        if (null !== $this->requestArguments) {
            return $this->requestArguments;
        }

        $arguments = $this->request->server()->get('argv');

        // strip the application name
        array_shift($arguments);

        return $this->requestArguments = $arguments;
    }

    /**
     * Parse request arguments to split by options and arguments.
     *
     * @return void
     */
    protected function parseRequestArguments(): void
    {
        // Iterate through the request arguments
        foreach ($this->getRequestArguments() as $argument) {
            // Split the string on an equal sign
            $exploded = explode('=', $argument);

            $key   = $exploded[0];
            $value = $exploded[1] ?? true;
            $type  = 'arguments';

            // If the key has double dash it is a long option
            if (strpos($key, '--') !== false) {
                $type = 'longOptions';
            } // If the key has a single dash it is a short option
            elseif (strpos($key, '-') !== false) {
                $type = 'shortOptions';
            }

            // If the key is already set
            if (isset($this->{$type}[$key])) {
                // If the key isn't already an array
                if (! \is_array($this->{$type}[$key])) {
                    // Make it an array with the current value
                    $this->{$type}[$key] = [$this->{$type}[$key]];
                }

                // Add the next value to the array
                $this->{$type}[$key][] = $value;

                continue;
            }

            // Set the key value pair
            $this->{$type}[$key] = $value;
        }
    }

    /**
     * Get an argument.
     *
     * @param string $argument The argument
     *
     * @return string
     */
    public function getArgument(string $argument): ? string
    {
        return $this->arguments[$argument] ?? null;
    }

    /**
     * Determine if an argument exists.
     *
     * @param string $argument The argument
     *
     * @return bool
     */
    public function hasArgument(string $argument): bool
    {
        return isset($this->arguments[$argument]);
    }

    /**
     * Get a short option.
     *
     * @param string $option The option
     *
     * @return string
     */
    public function getShortOption(string $option): ? string
    {
        return $this->shortOptions[$option] ?? null;
    }

    /**
     * Determine if a short option exists.
     *
     * @param string $option The short option
     *
     * @return bool
     */
    public function hasShortOption(string $option): bool
    {
        return isset($this->shortOptions[$option]);
    }

    /**
     * Get a long option.
     *
     * @param string $option The option
     *
     * @return string
     */
    public function getLongOption(string $option): ? string
    {
        return $this->longOptions[$option] ?? null;
    }

    /**
     * Determine if a long option exists.
     *
     * @param string $option The option
     *
     * @return bool
     */
    public function hasLongOption(string $option): bool
    {
        return isset($this->longOptions[$option]);
    }

    /**
     * Get an option (short or long).
     *
     * @param string $option The option
     *
     * @return string
     */
    public function getOption(string $option): ? string
    {
        return $this->shortOptions[$option] ?? $this->longOptions[$option] ?? null;
    }

    /**
     * Check if an option exists (long or short).
     *
     * @param string $option The option
     *
     * @return bool
     */
    public function hasOption(string $option): bool
    {
        return $this->hasShortOption($option) || $this->hasLongOption($option);
    }

    /**
     * Get the global options.
     *
     * @return \Valkyrja\Console\Input\Option[]
     */
    public function getGlobalOptions(): array
    {
        return [
            new Option('help', 'The help option for the command', 'h'),
            new Option('quiet', 'Do not output to the console', 'q'),
            new Option('version', 'The version of this application', 'V'),
        ];
    }

    /**
     * Get the global options as a flat array.
     *
     * @return array
     */
    public function getGlobalOptionsFlat(): array
    {
        return [
            '-h',
            '--help',
            '-q',
            '--quite',
            '-V',
            '--version',
        ];
    }

    /**
     * The items provided by this provider.
     *
     * @return array
     */
    public static function provides(): array
    {
        return [
            Input::class,
        ];
    }

    /**
     * Publish the provider.
     *
     * @param Application $app The application
     *
     * @return void
     */
    public static function publish(Application $app): void
    {
        $app->container()->singleton(
            Input::class,
            new static(
                $app->request()
            )
        );
    }
}


<?php

/**
 * Created by Prowect
 * Author: Raffael Kessler
 * Date: 17.10.2015 - 23:30.
 * Copyright Prowect.
 */
namespace Drips\Routing;

use Exception;
use Drips\HTTP\Request;
use Drips\HTTP\Response;
use Drips\Utils\OutputBuffer;

/**
 * Class Router.
 *
 * Diese Klasse dient als Routing-System. Es können URLs (sogenannte Route)
 * registriert werden und eine dazugehörige Funktion. Wird die entsprechende URL
 * aufgerufen, so wird die verknüpfte Funktion ausgeführt.
 */
class Router
{
    /**
     * Beinhaltet alle registrierten Routen, sowie deren Eigenschaften.
     *
     * @var array
     */
    protected $routes = array();

    /**
     * Beinhaltet die aktuelle Route, die vom Router gefunden beziehungsweise
     * ausgeführt wurde.
     *
     * @var string
     */
    protected $current_route;

    /**
     * Beinhaltet die aufgerufene URL.
     *
     * @var string
     */
    protected $request_uri;

    /**
     * Beinhaltet den aktuellen Pfad, unter dem sich dieses Script befindet.
     *
     * @var string
     */
    protected $current_path;

    /**
     * Beinhaltet den virtuellen Root von Drips welcher vom Router bestimmt wurde.
     * Dieser ist ausgehend vom Routing-Script.
     *
     * @var string
     */
    protected $drips_root;

    /**
     * Beinhaltet die aufgerufene URL.
     *
     * @var string
     */
    protected $url;

    /**
     * Beinhaltet die Parameter-Informationen zur entsprechenden Route.
     *
     * @var array
     */
    protected $params = array();

    /**
     * Beinhaltet den eingegangen Request.
     *
     * @var Request
     */
    protected $request;

    /**
     * Beinhaltet die Router-Instanz
     *
     * @var Router
     */
    private static $instance;

    /**
     * Gibt die Router-Instanz zurück (Singleton)
     *
     * @return Router
     */
    public static function getInstance()
    {
        if(static::$instance === null){
            static::$instance = new Router;
        }

        return static::$instance;
    }

    /**
     * Erzeugt eine neue Router-Instanz.
     */
    private function __construct()
    {
        $this->request = Request::getInstance();
        $request_uri = $this->request->server->get('REQUEST_URI');
        $this->current_path = dirname($this->request->server->get('SCRIPT_FILENAME'));
        $this->drips_root = substr($this->current_path, strlen($this->request->server->get('DOCUMENT_ROOT'))).'/';
        if(defined('DRIPS_PUBLIC')){
            $this->drips_root = substr($this->drips_root, 0, strlen($this->drips_root) - strlen('/public'));
        }
        $this->request_uri = substr($request_uri, strlen($this->drips_root));
        if(strlen($this->drips_root) < 1 || $this->drips_root[0] != "/"){
            $this->drips_root = "/".$this->drips_root;
        }
        $parts = explode("#", $this->request_uri);
        $this->request_uri = $parts[0];
        $parts = explode("?", $this->request_uri);
        $this->request_uri = $parts[0];
    }

    private function __clone(){}

    /**
     * Diese Methode wird zum Registrieren neuer Routen verwendet.
     * Die $url kann ein regulärer Ausdruck sein, jedoch ohne Delimiter.
     * Außerdem kann die $url auch Platzhalter mit folgendem Format beinhalten:
     * {placeholder}
     * Optional können auch $options übergeben werden. Diese können das Routing
     * einschränken. Dafür gibt es folgende Möglichkeiten:
     *  - "https" ... bool - wenn TRUE, muss die aufgerufene URL über HTTPS aufgerufen worden sein - Standard: FALSE
     *  - "verb" ... string or array - schränkt die Request-Methode ein, also über welche Request-Methoden die Route erreichbar sein soll. - Standard: alle
     *  - "domain" ... string or array - Beschränkt die Route auf eine oder mehrere bestimmte Domains.
     *
     * Gibt zurück ob die Route erfolgreich hinzugefügt wurde oder nicht. (TRUE/FALSE)
     * Wenn der Name der Route bereits vergeben ist, kann die Route nicht registriert werden!

     * @param string $name     eindeutiger Name der Route
     * @param string $url      Routen-Definition - kann Platzhalter beinhalten
     * @param mixed  $callback Funktion, die aufgerufen wird, sobald die Route ausgeführt wird oder ein Controller (MVC)
     * @param array  $options  optional - ermöglicht Zusatzinformationen, wie z.B.: Einschränkungen für die Routen
     *
     * @return bool
     */
    public function add($name, $url, $callback, array $options = array())
    {
        if (!is_callable($callback) && !class_exists($callback)) {
            throw new Exception("Ungültiges Callback bei Route: $name");
        }

        if (!$this->has($name)) {
            $this->routes[$name] = array('url' => $url, 'callback' => $callback, 'options' => $options);
            if (!isset($this->current_route)) {
                if ($this->match($name)) {
                    $this->current_route = $name;
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Liefert TRUE oder FALSE, je nachdem ob eine Route mit dem angebenen Namen
     * bereits existiert oder nicht.
     *
     * @param string $name Name der Route, die überprüft werden soll
     *
     * @return bool
     */
    public function has($name)
    {
        return array_key_exists($name, $this->routes);
    }

    /**
     * Führt die "gefundene" Route aus.
     * Gibt TRUE/FALSE zurück, je nachdem ob die Route ausgeführt werden konnte
     * oder nicht.
     * Wurde keine Route gefunden, wird eine Error404Exception geworfen.
     *
     * @return bool
     */
    public function route()
    {
        if (isset($this->current_route)) {
            return $this->exec($this->current_route);
        }

        throw new Error404Exception;
    }

    /**
     * Liefert den DocumentRoot des Routers.
     *
     * @return string
     */
    public function getRoot()
    {
        return $this->drips_root;
    }

    /**
     * Führt die Route aus, die unter dem Namen $name registriert ist.
     * Wurde die Route gefunden und ausgeführt wird TRUE zurückgeliefert, andernfalls
     * FALSE.
     *
     * @param string $name Name der Route, die ausgeführt werden soll.
     *
     * @return bool
     */
    protected function exec($name, array $params = array())
    {
        if ($this->has($name)) {
            if (empty($params)) {
                $params = $this->params;
            }
            $callback = $this->routes[$name]['callback'];
            if (is_callable($callback)) {
                $response = new Response();
                $buffer = new OutputBuffer();
                $buffer->start();
                echo call_user_func_array($callback, $params);
                $response->body = $buffer->end();
                $response->send();
            } elseif (class_exists($callback)) {
                $controller = new $callback($params);
            }

            return true;
        }

        return false;
    }

    /**
     * Gibt zurück ob die angegebene Route existiert und ob diese, falls erforderlich
     * auch mit HTTPS aufgerufen wurde.
     *
     * @param string $name Name der Route, die überprüft werden soll.
     *
     * @return bool
     */
    protected function isHTTPS($name)
    {
        if ($this->has($name)) {
            $route = $this->routes[$name];
            if (isset($route['options']['https'])) {
                $https = $route['options']['https'];
                $server_https = $this->request->server->get('HTTPS');
                if ($https === true && (empty($server_https) || $server_https == 'off')) {
                    return false;
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Gibt zurück ob die angegebene Route existiert und ob diese, falls erforderlich
     * auch über die richtige Request-Methode aufgerufen wurde.
     *
     * @param string $name Name der Route, die überprüft werden soll.
     *
     * @return bool
     */
    protected function isValidVerb($name)
    {
        if ($this->has($name)) {
            $route = $this->routes[$name];
            if (isset($route['options']['verb'])) {
                $verbs = $route['options']['verb'];
                $request_method = $this->request->server->get('REQUEST_METHOD');
                if (is_array($verbs) && !in_array(strtoupper($request_method), $verbs)) {
                    return false;
                } elseif (!is_array($verbs) && strtoupper($request_method) != $verbs) {
                    return false;
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Gibt zurück ob die angegebene Route existiert und ob diese, falls erforderlich
     * auch über die richtige Domain aufgerufen wurde.
     *
     * @param string $name Name der Route, die überprüft werden soll.
     *
     * @return bool
     */
    protected function isValidDomain($name)
    {
        if ($this->has($name)) {
            $route = $this->routes[$name];
            if (isset($route['options']['domain'])) {
                $domains = $route['options']['domain'];
                $http_host = $this->request->server('HTTP_HOST');
                if (is_array($domains) && !in_array($http_host, $domains)) {
                    return false;
                } elseif (!is_array($domains) && $http_host != $domains) {
                    return false;
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Gibt zurück ob die Route der aufgerufenen URL entspricht.
     *
     * @param string $name Name der Route, die überprüft werden soll.
     *
     * @return bool
     */
    protected function match($name)
    {
        if ($this->has($name)) {
            $route = $this->routes[$name];
            if (!$this->isHTTPS($name) || !$this->isValidVerb($name) || !$this->isValidDomain($name)) {
                return false;
            }
            $url = $this->findPlaceholders($route);

            return $this->getParams($url);
        }

        return false;
    }

    /**
     * Sucht nach Platzhaltern in der Routen-Definition und ersetzt diese durch
     * reguläre Ausdrücke.
     * Gibt die generierte URL zurück oder false wenn es sich um eine leere URL
     * bzw. um / handelt.
     *
     * @param array $route Routen-Objekt, wie es gespeichert wurde.
     *
     * @return string|false
     */
    protected function findPlaceholders($route)
    {
        $url = trim($route['url'], '/');
        if (empty($url) && trim($this->request_uri, '/') != '') {
            return false;
        }
        $matches = array();
        if (preg_match_all("/\{([\w-]+)\}/", $url, $matches) && isset($matches[1])) {
            foreach ($matches[1] as $match) {
                $replace = "([\w-]+)?";
                if (isset($route['options']['pattern'][$match])) {
                    $replace = $route['options']['pattern'][$match];
                }
                $url = str_replace('{'.$match.'}', $replace, $url);
            }
        }

        return $url;
    }

    /**
     * Speichert die Parameter der übergebenen URL als Array ($this->params)
     * anhand der aufgerufenen URL.
     *
     * @param string $url URL der die Parameter entnommen werden sollen
     *
     * @return bool
     */
    protected function getParams($url)
    {
        $request = trim($this->request_uri, '/');
        if(stripos($url, AUTO_ROUTE) !== false){
            $url = trim(str_replace('[auto]', '', $url), '/');
            if(preg_match("`^$url`", $request)){
                $this->params = explode('/', substr($request, strlen($url)));
                if(count($this->params) > 0 && empty($this->params[0])){
                    array_shift($this->params);
                }

                return true;
            }
        }

        $matches = array();
        $result = preg_match("`^$url$`", $request, $matches);
        if (count($matches) >= 2) {
            array_shift($matches);
            $this->params = $matches;
        }

        return $result;
    }

    /**
     * Liefert alle registrierten Routen zurück.
     *
     * @return array
     */
    public function getRoutes()
    {
        return $this->routes;
    }

    /**
     * Gibt zurück ob bereits Routen registriert wurden.
     *
     * @return bool
     */
    public function hasRoutes()
    {
        return !empty($this->routes);
    }

    /**
     * Generiert einen Link zu einer bestimmten Route.
     *
     * @param $name Name der Route oder URL
     *
     * @return string
     */
    public function link($name, array $params = array())
    {
        if ($this->has($name)) {
            $route = $this->routes[$name];
            $url = $route['url'];
            foreach ($params as $key => $val) {
                $url = str_replace('{'.$key.'}', $val, $url);
            }
            $url = preg_replace("/\{\w+\}/", '', $url);
            $name = ltrim(str_replace(AUTO_ROUTE, '', $url), '/');
        }

        return $this->asset($name);
    }

    /**
     * Führt eine Umleitung auf eine bestimmte Route oder URL durch.
     *
     * @param $name Name der Route oder URL
     * @param array $params Parameter für eine zugehörige Route
     */
    public function redirect($name, array $params = array())
    {
        $url = $this->link($name, $params);
        if ($url === null && filter_var($name, FILTER_VALIDATE_URL)) {
            $url = $name;
        }
        if (headers_sent()) {
            echo "<meta http-equiv='refresh' content='0, URL=$url'>";
        } else {
            header("Location: $url");
            exit();
        }
    }

    /**
     * Erzeugt einen absoluten Pfad für die aufgerufene URL eines bestimmten
     * Assets, beispielsweise einer CSS-Datei oder eines Bildes.
     *
     * @param $name
     *
     * @return string
     */
    public function asset($name)
    {
        return preg_replace('`/{2,}`', '/', $this->drips_root.$name);
    }

    /**
     * Liefert die aktuell gewählte Route zurück oder null, wenn keine Route
     * ausgewählt wurde.
     *
     * @return string
     */
    public function getCurrent()
    {
        return $this->current_route;
    }
}


<?php
/**
 * User: Alex Gusev <alex@flancer64.com>
 */
namespace Praxigento\Bonus\GlobalSales\Lib\Service\Calc;

use Praxigento\BonusBase\Service\Period\Request\GetForDependentCalc as PeriodGetForDependentCalcRequest;
use Praxigento\BonusGlobalSales\Config as Cfg;
use Praxigento\Wallet\Service\Operation\Request\AddToWalletActive as WalletOperationAddToWalletActiveRequest;

/**
 * @SuppressWarnings(PHPMD.CamelCasePropertyName)
 * @SuppressWarnings(PHPMD.CamelCaseMethodName)
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Call
    implements \Praxigento\Bonus\GlobalSales\Lib\Service\ICalc
{
    /** @var  \Praxigento\BonusBase\Service\IPeriod */
    private $callBasePeriod;
    /** @var  \Praxigento\Wallet\Service\IOperation */
    private $callWalletOperation;
    /** @var \Psr\Log\LoggerInterface */
    private $logger;
    /** @var  \Praxigento\Core\Api\App\Repo\Transaction\Manager */
    private $manTrans;
    /** @var  \Praxigento\BonusBase\Repo\Dao\Compress */
    private $repoBonusCompress;
    /** @var \Praxigento\BonusBase\Repo\Service\IModule */
    private $repoBonusService;
    /** @var \Praxigento\BonusBase\Repo\Dao\Type\Calc */
    private $repoBonusTypeCalc;
    /** @var \Praxigento\Bonus\GlobalSales\Lib\Repo\IModule */
    private $repoMod;
    /** @var  Sub\Bonus */
    private $subBonus;
    /** @var Sub\Qualification */
    private $subQualification;

    public function __construct(
        \Praxigento\Core\Api\App\Logger\Main $logger,
        \Praxigento\Core\Api\App\Repo\Transaction\Manager $manTrans,
        \Praxigento\Bonus\GlobalSales\Lib\Repo\IModule $daoMod,
        \Praxigento\BonusBase\Repo\Service\IModule $daoBonusService,
        \Praxigento\BonusBase\Repo\Dao\Compress $daoBonusCompress,
        \Praxigento\BonusBase\Repo\Dao\Type\Calc $daoBonusTypeCalc,
        \Praxigento\BonusBase\Service\IPeriod $callBasePeriod,
        \Praxigento\Wallet\Service\IOperation $callWalletOperation,
        Sub\Bonus $subBonus,
        Sub\Qualification $subQual
    ) {
        $this->logger = $logger;
        $this->manTrans = $manTrans;
        $this->repoMod = $daoMod;
        $this->repoBonusService = $daoBonusService;
        $this->repoBonusCompress = $daoBonusCompress;
        $this->repoBonusTypeCalc = $daoBonusTypeCalc;
        $this->callBasePeriod = $callBasePeriod;
        $this->callWalletOperation = $callWalletOperation;
        $this->subBonus = $subBonus;
        $this->subQualification = $subQual;
    }

    /**
     * @param $updates [$custId=>[$rankId=>$bonus, ...], ...]
     *
     * @return \Praxigento\Wallet\Service\Operation\Response\AddToWalletActive
     */
    private function _createBonusOperation($updates)
    {
        $asCustId = 'asCid';
        $asAmount = 'asAmnt';
        $asRef = 'asRef';
        $transData = [];
        foreach ($updates as $custId => $ranks) {
            foreach ($ranks as $rankId => $amount) {
                $item = [$asCustId => $custId, $asAmount => $amount, $asRef => $rankId];
                $transData[] = $item;
            }
        }
        $req = new WalletOperationAddToWalletActiveRequest();
        $req->setAsCustomerId($asCustId);
        $req->setAsAmount($asAmount);
        $req->setAsRef($asRef);
        $req->setOperationTypeCode(Cfg::CODE_TYPE_OPER_BONUS);
        $req->setTransData($transData);
        $result = $this->callWalletOperation->addToWalletActive($req);
        return $result;
    }

    /**
     * @param Request\Bonus $req
     *
     * @return Response\Bonus
     */
    public function bonus(Request\Bonus $req)
    {
        $result = new Response\Bonus();
        $datePerformed = $req->getDatePerformed();
        $dateApplied = $req->getDateApplied();
        $this->logger->info("'Global Sales Bonus' calculation is started. Performed at: $datePerformed, applied at: $dateApplied.");
        $reqGetPeriod = new PeriodGetForDependentCalcRequest();
        $calcTypeBase = Cfg::CODE_TYPE_CALC_QUALIFICATION;
        $calcType = Cfg::CODE_TYPE_CALC_BONUS;
        $reqGetPeriod->setBaseCalcTypeCode($calcTypeBase);
        $reqGetPeriod->setDependentCalcTypeCode($calcType);
        $respGetPeriod = $this->callBasePeriod->getForDependentCalc($reqGetPeriod);
        if ($respGetPeriod->isSucceed()) {
            $def = $this->manTrans->begin();
            try {
                $periodDataDepend = $respGetPeriod->getDependentPeriodData();
                $calcDataDepend = $respGetPeriod->getDependentCalcData();
                $calcIdDepend = $calcDataDepend->getId();
                $dsBegin = $periodDataDepend->getDstampBegin();
                $dsEnd = $periodDataDepend->getDstampEnd();
                /* collect data to process bonus */
                $calcTypeIdCompress = $this->repoBonusTypeCalc->getIdByCode(Cfg::CODE_TYPE_CALC_COMPRESSION);
                $calcDataCompress = $this->repoBonusService
                    ->getLastCalcForPeriodByDates($calcTypeIdCompress, $dsBegin, $dsEnd);
                $calcIdCompress = $calcDataCompress->getId();
                $params = $this->repoMod->getConfigParams();
                $treeCompressed = $this->repoMod->getCompressedTreeWithQualifications($calcIdCompress);
                $pvTotal = $this->repoMod->getSalesOrdersPvForPeriod($dsBegin, $dsEnd);
                /* calculate bonus */
                $updates = $this->subBonus->calc($treeCompressed, $pvTotal, $params);
                /* create new operation with bonus transactions and save sales log */
                $respAdd = $this->_createBonusOperation($updates);
                $transLog = $respAdd->getTransactionsIds();
                $this->repoMod->saveLogRanks($transLog);
                /* mark calculation as completed and finalize bonus */
                $this->repoBonusService->markCalcComplete($calcIdDepend);
                $this->manTrans->commit($def);
                $result->setPeriodId($periodDataDepend->getId());
                $result->setCalcId($calcIdDepend);
                $result->markSucceed();
            } finally {
                $this->manTrans->end($def);
            }
        }
        $this->logger->info("'Global Sales Bonus' calculation is complete.");
        return $result;
    }

    public function qualification(Request\Qualification $req)
    {
        $result = new Response\Qualification();
        $datePerformed = $req->getDatePerformed();
        $dateApplied = $req->getDateApplied();
        $gvMaxLevels = $req->getGvMaxLevels();
        $msg = "'Qualification for Global Sales' calculation is started. "
            . "Performed at: $datePerformed, applied at: $dateApplied.";
        $this->logger->info($msg);
        $reqGetPeriod = new PeriodGetForDependentCalcRequest();
        $calcTypeBase = Cfg::CODE_TYPE_CALC_COMPRESSION;
        $calcType = Cfg::CODE_TYPE_CALC_QUALIFICATION;
        $reqGetPeriod->setBaseCalcTypeCode($calcTypeBase);
        $reqGetPeriod->setDependentCalcTypeCode($calcType);
        $respGetPeriod = $this->callBasePeriod->getForDependentCalc($reqGetPeriod);
        if ($respGetPeriod->isSucceed()) {
            $def = $this->manTrans->begin();
            try {
                $periodDataDepend = $respGetPeriod->getDependentPeriodData();
                $calcDataDepend = $respGetPeriod->getDependentCalcData();
                $calcIdDepend = $calcDataDepend->getId();
                $calcDataBase = $respGetPeriod->getBaseCalcData();
                $dsBegin = $periodDataDepend->getDstampBegin();
                $dsEnd = $periodDataDepend->getDstampEnd();
                $calcIdBase = $calcDataBase->getId();
                $tree = $this->repoBonusCompress->getTreeByCalcId($calcIdBase);
                $qualData = $this->repoMod->getQualificationData($dsBegin, $dsEnd);
                $cfgParams = $this->repoMod->getConfigParams();
                $updates = $this->subQualification->calcParams($tree, $qualData, $cfgParams, $gvMaxLevels);
                $this->repoMod->saveQualificationParams($updates);
                $this->repoBonusService->markCalcComplete($calcIdDepend);
                $this->manTrans->commit($def);
                $result->setPeriodId($periodDataDepend->getId());
                $result->setCalcId($calcIdDepend);
                $result->markSucceed();
            } finally {
                $this->manTrans->end($def);
            }
        }
        $this->logger->info("'Qualification for Global Sales' calculation is complete.");
        return $result;
    }
}


<?php

/*
 * This file is part of the Valkyrja framework.
 *
 * (c) Melech Mizrachi
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Valkyrja\HttpMessage;

use Valkyrja\HttpMessage\Exceptions\InvalidProtocolVersion;

/**
 * Trait MessageTrait.
 *
 * @author Melech Mizrachi
 */
trait MessageTrait
{
    /**
     * The headers with normalized header names.
     *
     * @var string[][]
     */
    protected $headers = [];

    /**
     * Original header names.
     *
     * @var array
     */
    protected $headerNames = [];

    /**
     * The protocol.
     *
     * @var string
     */
    protected $protocol = '1.1';

    /**
     * The stream.
     *
     * @var \Valkyrja\HttpMessage\Stream
     */
    protected $stream;

    /**
     * Retrieves the HTTP protocol version as a string.
     *
     * The string MUST contain only the HTTP version number (e.g., "1.1",
     * "1.0").
     *
     * @return string HTTP protocol version.
     */
    public function getProtocolVersion(): string
    {
        return $this->protocol;
    }

    /**
     * Return an instance with the specified HTTP protocol version.
     *
     * The version string MUST contain only the HTTP version number (e.g.,
     * "1.1", "1.0").
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new protocol version.
     *
     * @param string $version HTTP protocol version
     *
     * @throws \Valkyrja\HttpMessage\Exceptions\InvalidProtocolVersion
     *
     * @return static
     */
    public function withProtocolVersion(string $version)
    {
        $this->validateProtocolVersion($version);

        $this->protocol = $version;

        return $this;
    }

    /**
     * Retrieves all message header values.
     *
     * The keys represent the header name as it will be sent over the wire, and
     * each value is an array of strings associated with the header.
     *
     *     // Represent the headers as a string
     *     foreach ($message->getHeaders() as $name => $values) {
     *         echo $name . ": " . implode(", ", $values);
     *     }
     *
     *     // Emit headers iteratively:
     *     foreach ($message->getHeaders() as $name => $values) {
     *         foreach ($values as $value) {
     *             header(sprintf('%s: %s', $name, $value), false);
     *         }
     *     }
     *
     * While header names are not case-sensitive, getHeaders() will preserve
     * the exact case in which headers were originally specified.
     *
     * @return string[][] Returns an associative array of the message's
     *                    headers. Each key MUST be a header name, and each
     *                    value MUST be an array of strings for that header.
     */
    public function getHeaders(): array
    {
        return $this->headers;
    }

    /**
     * Checks if a header exists by the given case-insensitive name.
     *
     * @param string $name Case-insensitive header field name.
     *
     * @return bool Returns true if any header names match the given header
     *              name using a case-insensitive string comparison. Returns
     *              false if no matching header name is found in the message.
     */
    public function hasHeader(string $name): bool
    {
        return isset($this->headerNames[strtolower($name)]);
    }

    /**
     * Retrieves a message header value by the given case-insensitive name.
     *
     * This method returns an array of all the header values of the given
     * case-insensitive header name.
     *
     * If the header does not appear in the message, this method MUST return an
     * empty array.
     *
     * @param string $name Case-insensitive header field name.
     *
     * @return string[] An array of string values as provided for the given
     *                  header. If the header does not appear in the message,
     *                  this method MUST return an empty array.
     */
    public function getHeader(string $name): array
    {
        if (! $this->hasHeader($name)) {
            return [];
        }

        $name = $this->headerNames[strtolower($name)];

        return $this->headers[$name];
    }

    /**
     * Retrieves a comma-separated string of the values for a single header.
     *
     * This method returns all of the header values of the given
     * case-insensitive header name as a string concatenated together using
     * a comma.
     *
     * NOTE: Not all header values may be appropriately represented using
     * comma concatenation. For such headers, use getHeader() instead
     * and supply your own delimiter when concatenating.
     *
     * If the header does not appear in the message, this method MUST return
     * an empty string.
     *
     * @param string $name Case-insensitive header field name.
     *
     * @return string A string of values as provided for the given header
     *                concatenated together using a comma. If the header does
     *                not appear in the message, this method MUST return an
     *                empty string.
     */
    public function getHeaderLine(string $name): string
    {
        $value = $this->getHeader($name);

        if (! $value) {
            return '';
        }

        return implode(',', $value);
    }

    /**
     * Return an instance with the provided value replacing the specified
     * header.
     *
     * While header names are case-insensitive, the casing of the header will
     * be preserved by this function, and returned from getHeaders().
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new and/or updated header and value.
     *
     * @param string   $name      Case-insensitive header field name.
     * @param string[] ...$values Header values.
     *
     * @throws \InvalidArgumentException for invalid header names or values.
     *
     * @return static
     */
    public function withHeader(string $name, string ...$values)
    {
        HeaderSecurity::assertValidName($name);

        $normalized = strtolower($name);

        $new = clone $this;

        if ($new->hasHeader($name)) {
            unset($new->headers[$new->headerNames[$normalized]]);
        }

        $values = $this->assertHeaderValues(...$values);

        $new->headerNames[$normalized] = $name;
        $new->headers[$name]           = $values;

        return $new;
    }

    /**
     * Return an instance with the specified header appended with the given
     * value.
     *
     * Existing values for the specified header will be maintained. The new
     * value(s) will be appended to the existing list. If the header did not
     * exist previously, it will be added.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * new header and/or value.
     *
     * @param string   $name      Case-insensitive header field name to add.
     * @param string[] ...$values Header values.
     *
     * @throws \InvalidArgumentException for invalid header names or values.
     *
     * @return static
     */
    public function withAddedHeader(string $name, string ...$values)
    {
        HeaderSecurity::assertValidName($name);

        if (! $this->hasHeader($name)) {
            return $this->withHeader($name);
        }

        $name = $this->headerNames[strtolower($name)];

        $new = clone $this;

        $values = $this->assertHeaderValues(...$values);

        $new->headers[$name] = array_merge($this->headers[$name], $values);

        return $new;
    }

    /**
     * Return an instance without the specified header.
     *
     * Header resolution MUST be done without case-sensitivity.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that removes
     * the named header.
     *
     * @param string $name Case-insensitive header field name to remove.
     *
     * @return static
     */
    public function withoutHeader(string $name)
    {
        if (! $this->hasHeader($name)) {
            return clone $this;
        }

        $normalized = strtolower($name);
        $original   = $this->headerNames[$normalized];
        $new        = clone $this;

        unset($new->headers[$original], $new->headerNames[$normalized]);

        return $new;
    }

    /**
     * Gets the body of the message.
     *
     * @return \Valkyrja\HttpMessage\Stream Returns the body as a stream.
     */
    public function getBody(): Stream
    {
        return $this->stream;
    }

    /**
     * Return an instance with the specified message body.
     *
     * The body MUST be a StreamInterface object.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return a new instance that has the
     * new body stream.
     *
     * @param Stream $body Body.
     *
     * @throws \InvalidArgumentException When the body is not valid.
     *
     * @return static
     */
    public function withBody(Stream $body)
    {
        $new = clone $this;

        $new->stream = $body;

        return $new;
    }

    /**
     * Validate the protocol version.
     *
     * @param string $version
     *
     * @throws \Valkyrja\HttpMessage\Exceptions\InvalidProtocolVersion
     *
     * @return void
     */
    protected function validateProtocolVersion(string $version): void
    {
        // HTTP/1 uses a "<major>.<minor>" numbering scheme to indicate
        // versions of the protocol, while HTTP/2 does not.
        if (! preg_match('#^(1\.[01]|2)$#', $version)) {
            throw new InvalidProtocolVersion(
                sprintf(
                    'Unsupported HTTP protocol version "%s" provided',
                    $version
                )
            );
        }
    }

    /**
     * Set headers.
     *
     * @param array $originalHeaders
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    protected function setHeaders(array $originalHeaders): void
    {
        $headerNames = $headers = [];

        foreach ($originalHeaders as $header => $value) {
            $value = $this->assertHeaderValues($value);

            HeaderSecurity::assertValidName($header);

            $headerNames[strtolower($header)] = $header;
            $headers[$header]                 = $value;
        }

        $this->headerNames = $headerNames;
        $this->headers     = $headers;
    }

    /**
     * Filter header values.
     *
     * @param string[] ...$values Header values
     *
     * @throws \InvalidArgumentException
     *
     * @return string[]
     */
    protected function assertHeaderValues(string ...$values): array
    {
        foreach ($values as $value) {
            HeaderSecurity::assertValid($value);
        }

        return $values;
    }

    /**
     * Inject a header in a headers array.
     *
     * @param string $header   The header to set
     * @param string $value    The value to set
     * @param array  $headers  [optional] The headers
     * @param bool   $override [optional] Whether to override any existing value
     *
     * @return array
     */
    protected function injectHeader(string $header, string $value, array $headers = null, bool $override = false): array
    {
        // The headers
        $headers = $headers ?? [];
        // Normalize the content type header
        $normalized = strtolower($header);
        // The original value for the header (if it exists in the headers array)
        // Defaults to the value passed in
        $originalValue = $value;

        // Iterate through all the headers
        foreach ($headers as $headerIndex => $headerValue) {
            // Normalize the header name and check if it matches the normalized
            // passed in header
            if (strtolower($headerIndex) === $normalized) {
                // Set the original value as this header value
                $originalValue = $headerValue;

                // Unset the header as we want to use the header string that was
                // passed in as the header
                unset($headers[$headerIndex]);
            }
        }

        // Set the header in the headers list
        $headers[$header] = [$override ? $originalValue : $value];

        return $headers;
    }
}


<?php
namespace Gosyl\CommonBundle;

class Constantes {
    const PANEL_DEFAULT = 0;
    const PANEL_PRIMARY = 1;
    const PANEL_SUCCESS = 2;
    const PANEL_INFO = 3;
    const PANEL_WARNING = 4;
    const PANEL_DANGER = 5;

    /**
     * @var array
     */
    public static $aTypePanel = array(
        self::PANEL_DEFAULT => 'panel_default',
        self::PANEL_PRIMARY => 'panel_primary',
        self::PANEL_SUCCESS => 'panel_success',
        self::PANEL_INFO => 'panel_info',
        self::PANEL_WARNING => 'panel_warning',
        self::PANEL_DANGER => 'panel_danger',
    );

	/**
	 * Boîtes de dialogue connexion et inscription
	 */
	public static $aDialogConnexion = array(
			'dialogOptions' => array(
					'options' => array(
							'autoOpen' => array(
									'data' => false,
									'ecrasement' => true,
							),
							'resizable' => array(
									'data' => false,
									'ecrasement' => true,
							),
							'width' => array(
									'data' => "auto",
									'ecrasement' => true,
							),
							'buttons' => array(
									'data' => array(),
									'ecrasement' => true,
							),
					),
					'events' => array(
							'open' => array(
									'data' => array(
											'function' => '{
					                            $(".ui-dialog .ui-dialog-titlebar .ui-dialog-title").css("display", "none");
					    	                    $(".ui-dialog .ui-dialog-titlebar .ui-dialog-title").parent().css("display", "none");
					                        }',
									),
									'ecrasement' => false,
							),
							'close' => array(
									'data' => array(
											'function' => '{
					                            $(".ui-dialog .ui-dialog-titlebar .ui-dialog-title").css("display", "block");
					    	                    $(".ui-dialog .ui-dialog-titlebar .ui-dialog-title").parent().css("display", "block");
					                            $("#dialogConnexion .error").remove();
					                        }',
									),
									'ecrasement' => true,
							),
					),
			),
			'idDialog' => 'dialogConnexion',
	);

	public static $aDialogInscription = array(
			'dialogOptions' => array(
					'options' => array(
							'autoOpen' => array(
									'data' => false,
									'ecrasement' => true,
							),
							'resizable' => array(
									'data' => false,
									'ecrasement' => true,
							),
							'width' => array(
									'data' => "auto",
									'ecrasement' => true,
							),
							'buttons' => array(
									'data' => array(),
									'ecrasement' => true,
							),
					),
					'events' => array(
							'open' => array(
									'data' => array(
											'function' => '{
					                            $(".ui-dialog .ui-dialog-titlebar .ui-dialog-title").css("display", "none");
					    	                    $(".ui-dialog .ui-dialog-titlebar .ui-dialog-title").parent().css("display", "none");
					                    		Gosyl.Inscription.loadDatePicker();
					                    	}',
									),
									'ecrasement' => false,
							),
							'close' => array(
									'data' => array(
											'function' => '{
					                            $(".ui-dialog .ui-dialog-titlebar .ui-dialog-title").css("display", "block");
					    	                    $(".ui-dialog .ui-dialog-titlebar .ui-dialog-title").parent().css("display", "block");
					                            $("#dialogInscription .error").remove();
					                        }',
									),
									'ecrasement' => true,
							),
					),
			),
			'idDialog' => 'dialogInscription',
	);

	/**
	 * Liste des privilèges
	 */
	const IS_AUTHENTICATED_ANONYMOUSLY = 'IS_AUTHENTICATED_ANONYMOUSLY';
	const ROLE_USER = 'ROLE_USER';
	const ROLE_ADMIN = 'ROLE_ADMIN';

	public static $aPrivileges = array(
		//self::IS_AUTHENTICATED_ANONYMOUSLY,
		self::ROLE_USER => 0,
		self::ROLE_ADMIN => 1
	);

	/*-- DataTable Options --*/
	public static $aDataTableLanguage = array(
			'language' => array(
					'processing' => 'Traitement des données...',
					'lengthMenu' => 'Afficher _MENU_ résultats',
					'zeroRecords' => 'Aucun résultat à afficher',
					"emptyTable" =>	 "Pas de résultat pour les critères demandés.",
					"info" =>         "Affichage des résultats _START_ à _END_ sur _TOTAL_ éléments",
					"infoEmpty" =>  "Pas de résultat pour les critères demandés.",
					"infoFiltered" => "(filtré de _MAX_ résultats au total)",
					"infoPostFix" => "",
					"search" => "Rechercher :",
					"url" => "",
					"paginate" => array(
							"first"=>  "Début",
							"previous" => "Précédent",
							"next" => "Suivant",
							"last" => "Fin"
					),
			),
	);

	/**
	 * Debug
	 */
	public static function vardump() {
		if(func_num_args() == 0) {
			throw new \Exception('Aucune variable');
		}

		$aArgs = func_get_args();

		echo '<pre>';

		foreach($aArgs as $arg) {
			var_dump($arg);
		}

		echo '</pre>';
	}
}


<?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_Filter
 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Encrypt.php 24593 2012-01-05 20:35:02Z matthew $
 */

/**
 * @see Zend_Filter_Interface
 */

/**
 * @see Zend_Loader
 */

/**
 * Encrypts a given string
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Filter_Encrypt implements Zend_Filter_Interface
{
    /**
     * Encryption adapter
     */
    protected $_adapter;

    /**
     * Class constructor
     *
     * @param string|array $options (Optional) Options to set, if null mcrypt is used
     */
    public function __construct($options = null)
    {
        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        }

        $this->setAdapter($options);
    }

    /**
     * Returns the name of the set adapter
     *
     * @return string
     */
    public function getAdapter()
    {
        return $this->_adapter->toString();
    }

    /**
     * Sets new encryption options
     *
     * @param  string|array $options (Optional) Encryption options
     * @return Zend_Filter_Encrypt
     */
    public function setAdapter($options = null)
    {
        if (is_string($options)) {
            $adapter = $options;
        } else if (isset($options['adapter'])) {
            $adapter = $options['adapter'];
            unset($options['adapter']);
        } else {
            $adapter = 'Mcrypt';
        }

        if (!is_array($options)) {
            $options = array();
        }

        if (Zend_Loader::isReadable('Zend/Filter/Encrypt/' . ucfirst($adapter). '.php')) {
            $adapter = 'Zend_Filter_Encrypt_' . ucfirst($adapter);
        }

        if (!class_exists($adapter)) {
            Zend_Loader::loadClass($adapter);
        }

        $this->_adapter = new $adapter($options);
        if (!$this->_adapter instanceof Zend_Filter_Encrypt_Interface) {

            throw new Zend_Filter_Exception("Encoding adapter '" . $adapter . "' does not implement Zend_Filter_Encrypt_Interface");
        }

        return $this;
    }

    /**
     * Calls adapter methods
     *
     * @param string       $method  Method to call
     * @param string|array $options Options for this method
     */
    public function __call($method, $options)
    {
        $part = substr($method, 0, 3);
        if ((($part != 'get') and ($part != 'set')) or !method_exists($this->_adapter, $method)) {

            throw new Zend_Filter_Exception("Unknown method '{$method}'");
        }

        return call_user_func_array(array($this->_adapter, $method), $options);
    }

    /**
     * Defined by Zend_Filter_Interface
     *
     * Encrypts the content $value with the defined settings
     *
     * @param  string $value Content to encrypt
     * @return string The encrypted content
     */
    public function filter($value)
    {
        return $this->_adapter->encrypt($value);
    }
}


<?php

namespace EdwinLuijten\Ekko\Broadcast\Broadcasters;

use EdwinLuijten\Ekko\Broadcast\Identity;
use EdwinLuijten\Ekko\Broadcast\StrUtil;
use Predis\ClientInterface;

class RedisBroadcaster extends AbstractBroadcaster implements BroadcasterInterface
{
    /**
     * @var ClientInterface
     */
    private $redis;

    /**
     * RedisBroadcaster constructor.
     * @param ClientInterface $redis
     */
    public function __construct(ClientInterface $redis)
    {
        $this->redis = $redis;
    }

    /**
     * @param Identity $identity
     * @return mixed
     * @throws \Exception
     */
    public function auth(Identity $identity)
    {
        if (StrUtil::startsWith($identity->channel, ['private-', 'presence-']) && empty($identity->identifier)) {
            throw new \Exception('Unauthorized', 403);
        }

        return parent::verifyThatIdentityCanAccessChannel(
            $identity,
            str_replace(['private-', 'presence-'], '', $identity->channel)
        );
    }

    /**
     * @param Identity $identity
     * @param $response
     * @return string
     */
    public function validAuthenticationResponse(Identity $identity, $response)
    {
        if (is_bool($response)) {
            return json_encode($response);
        }

        return json_encode(
            [
                'channel_data' => [
                    'identifier' => $identity->identifier,
                    'identity'   => $response,
                ]
            ]
        );
    }

    /**
     * Broadcast the given event.
     *
     * @param  array $channels
     * @param  string $event
     * @param  array $payload
     * @return void
     */
    public function broadcast(array $channels, $event, array $payload = [])
    {
        $socket  = isset($payload['socket']) ? $payload['socket'] : null;
        $payload = json_encode(['event' => $event, 'data' => $payload, 'socket' => $socket]);

        foreach ($this->formatChannels($channels) as $channel) {
            $this->redis->publish($channel, $payload);
        }
    }
}


<?php
/**
 * Stores cookies and passes them between HTTP requests
 *
 * PHP version 5
 *
 * LICENSE
 *
 * This source file is subject to BSD 3-Clause License that is bundled
 * with this package in the file LICENSE and available at the URL
 * https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE
 *
 * @category  HTTP
 * @package   HTTP_Request2
 * @author    Alexey Borzov <avb@php.net>
 * @copyright 2008-2014 Alexey Borzov <avb@php.net>
 * @license   http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
 * @link      http://pear.php.net/package/HTTP_Request2
 */

/** Class representing a HTTP request message */
require_once 'HTTP/Request2.php';

/**
 * Stores cookies and passes them between HTTP requests
 *
 * @category HTTP
 * @package  HTTP_Request2
 * @author   Alexey Borzov <avb@php.net>
 * @license  http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
 * @version  Release: 2.2.1
 * @link     http://pear.php.net/package/HTTP_Request2
 */
class HTTP_Request2_CookieJar implements Serializable
{
    /**
     * Array of stored cookies
     *
     * The array is indexed by domain, path and cookie name
     *   .example.com
     *     /
     *       some_cookie => cookie data
     *     /subdir
     *       other_cookie => cookie data
     *   .example.org
     *     ...
     *
     * @var array
     */
    protected $cookies = array();

    /**
     * Whether session cookies should be serialized when serializing the jar
     * @var bool
     */
    protected $serializeSession = false;

    /**
     * Whether Public Suffix List should be used for domain matching
     * @var bool
     */
    protected $useList = true;

    /**
     * Array with Public Suffix List data
     * @var  array
     * @link http://publicsuffix.org/
     */
    protected static $psl = array();

    /**
     * Class constructor, sets various options
     *
     * @param bool $serializeSessionCookies Controls serializing session cookies,
     *                                      see {@link serializeSessionCookies()}
     * @param bool $usePublicSuffixList     Controls using Public Suffix List,
     *                                      see {@link usePublicSuffixList()}
     */
    public function __construct(
        $serializeSessionCookies = false, $usePublicSuffixList = true
    ) {
        $this->serializeSessionCookies($serializeSessionCookies);
        $this->usePublicSuffixList($usePublicSuffixList);
    }

    /**
     * Returns current time formatted in ISO-8601 at UTC timezone
     *
     * @return string
     */
    protected function now()
    {
        $dt = new DateTime();
        $dt->setTimezone(new DateTimeZone('UTC'));
        return $dt->format(DateTime::ISO8601);
    }

    /**
     * Checks cookie array for correctness, possibly updating its 'domain', 'path' and 'expires' fields
     *
     * The checks are as follows:
     *   - cookie array should contain 'name' and 'value' fields;
     *   - name and value should not contain disallowed symbols;
     *   - 'expires' should be either empty parseable by DateTime;
     *   - 'domain' and 'path' should be either not empty or an URL where
     *     cookie was set should be provided.
     *   - if $setter is provided, then document at that URL should be allowed
     *     to set a cookie for that 'domain'. If $setter is not provided,
     *     then no domain checks will be made.
     *
     * 'expires' field will be converted to ISO8601 format from COOKIE format,
     * 'domain' and 'path' will be set from setter URL if empty.
     *
     * @param array    $cookie cookie data, as returned by
     *                         {@link HTTP_Request2_Response::getCookies()}
     * @param Net_URL2 $setter URL of the document that sent Set-Cookie header
     *
     * @return   array    Updated cookie array
     * @throws   HTTP_Request2_LogicException
     * @throws   HTTP_Request2_MessageException
     */
    protected function checkAndUpdateFields(array $cookie, Net_URL2 $setter = null)
    {
        if ($missing = array_diff(array('name', 'value'), array_keys($cookie))) {
            throw new HTTP_Request2_LogicException(
                "Cookie array should contain 'name' and 'value' fields",
                HTTP_Request2_Exception::MISSING_VALUE
            );
        }
        if (preg_match(HTTP_Request2::REGEXP_INVALID_COOKIE, $cookie['name'])) {
            throw new HTTP_Request2_LogicException(
                "Invalid cookie name: '{$cookie['name']}'",
                HTTP_Request2_Exception::INVALID_ARGUMENT
            );
        }
        if (preg_match(HTTP_Request2::REGEXP_INVALID_COOKIE, $cookie['value'])) {
            throw new HTTP_Request2_LogicException(
                "Invalid cookie value: '{$cookie['value']}'",
                HTTP_Request2_Exception::INVALID_ARGUMENT
            );
        }
        $cookie += array('domain' => '', 'path' => '', 'expires' => null, 'secure' => false);

        // Need ISO-8601 date @ UTC timezone
        if (!empty($cookie['expires'])
            && !preg_match('/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+0000$/', $cookie['expires'])
        ) {
            try {
                $dt = new DateTime($cookie['expires']);
                $dt->setTimezone(new DateTimeZone('UTC'));
                $cookie['expires'] = $dt->format(DateTime::ISO8601);
            } catch (Exception $e) {
                throw new HTTP_Request2_LogicException($e->getMessage());
            }
        }

        if (empty($cookie['domain']) || empty($cookie['path'])) {
            if (!$setter) {
                throw new HTTP_Request2_LogicException(
                    'Cookie misses domain and/or path component, cookie setter URL needed',
                    HTTP_Request2_Exception::MISSING_VALUE
                );
            }
            if (empty($cookie['domain'])) {
                if ($host = $setter->getHost()) {
                    $cookie['domain'] = $host;
                } else {
                    throw new HTTP_Request2_LogicException(
                        'Setter URL does not contain host part, can\'t set cookie domain',
                        HTTP_Request2_Exception::MISSING_VALUE
                    );
                }
            }
            if (empty($cookie['path'])) {
                $path = $setter->getPath();
                $cookie['path'] = empty($path)? '/': substr($path, 0, strrpos($path, '/') + 1);
            }
        }

        if ($setter && !$this->domainMatch($setter->getHost(), $cookie['domain'])) {
            throw new HTTP_Request2_MessageException(
                "Domain " . $setter->getHost() . " cannot set cookies for "
                . $cookie['domain']
            );
        }

        return $cookie;
    }

    /**
     * Stores a cookie in the jar
     *
     * @param array    $cookie cookie data, as returned by
     *                         {@link HTTP_Request2_Response::getCookies()}
     * @param Net_URL2 $setter URL of the document that sent Set-Cookie header
     *
     * @throws   HTTP_Request2_Exception
     */
    public function store(array $cookie, Net_URL2 $setter = null)
    {
        $cookie = $this->checkAndUpdateFields($cookie, $setter);

        if (strlen($cookie['value'])
            && (is_null($cookie['expires']) || $cookie['expires'] > $this->now())
        ) {
            if (!isset($this->cookies[$cookie['domain']])) {
                $this->cookies[$cookie['domain']] = array();
            }
            if (!isset($this->cookies[$cookie['domain']][$cookie['path']])) {
                $this->cookies[$cookie['domain']][$cookie['path']] = array();
            }
            $this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']] = $cookie;

        } elseif (isset($this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']])) {
            unset($this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']]);
        }
    }

    /**
     * Adds cookies set in HTTP response to the jar
     *
     * @param HTTP_Request2_Response $response HTTP response message
     * @param Net_URL2               $setter   original request URL, needed for
     *                               setting default domain/path
     */
    public function addCookiesFromResponse(HTTP_Request2_Response $response, Net_URL2 $setter)
    {
        foreach ($response->getCookies() as $cookie) {
            $this->store($cookie, $setter);
        }
    }

    /**
     * Returns all cookies matching a given request URL
     *
     * The following checks are made:
     *   - cookie domain should match request host
     *   - cookie path should be a prefix for request path
     *   - 'secure' cookies will only be sent for HTTPS requests
     *
     * @param Net_URL2 $url      Request url
     * @param bool     $asString Whether to return cookies as string for "Cookie: " header
     *
     * @return array|string Matching cookies
     */
    public function getMatching(Net_URL2 $url, $asString = false)
    {
        $host   = $url->getHost();
        $path   = $url->getPath();
        $secure = 0 == strcasecmp($url->getScheme(), 'https');

        $matched = $ret = array();
        foreach (array_keys($this->cookies) as $domain) {
            if ($this->domainMatch($host, $domain)) {
                foreach (array_keys($this->cookies[$domain]) as $cPath) {
                    if (0 === strpos($path, $cPath)) {
                        foreach ($this->cookies[$domain][$cPath] as $name => $cookie) {
                            if (!$cookie['secure'] || $secure) {
                                $matched[$name][strlen($cookie['path'])] = $cookie;
                            }
                        }
                    }
                }
            }
        }
        foreach ($matched as $cookies) {
            krsort($cookies);
            $ret = array_merge($ret, $cookies);
        }
        if (!$asString) {
            return $ret;
        } else {
            $str = '';
            foreach ($ret as $c) {
                $str .= (empty($str)? '': '; ') . $c['name'] . '=' . $c['value'];
            }
            return $str;
        }
    }

    /**
     * Returns all cookies stored in a jar
     *
     * @return array
     */
    public function getAll()
    {
        $cookies = array();
        foreach (array_keys($this->cookies) as $domain) {
            foreach (array_keys($this->cookies[$domain]) as $path) {
                foreach ($this->cookies[$domain][$path] as $name => $cookie) {
                    $cookies[] = $cookie;
                }
            }
        }
        return $cookies;
    }

    /**
     * Sets whether session cookies should be serialized when serializing the jar
     *
     * @param boolean $serialize serialize?
     */
    public function serializeSessionCookies($serialize)
    {
        $this->serializeSession = (bool)$serialize;
    }

    /**
     * Sets whether Public Suffix List should be used for restricting cookie-setting
     *
     * Without PSL {@link domainMatch()} will only prevent setting cookies for
     * top-level domains like '.com' or '.org'. However, it will not prevent
     * setting a cookie for '.co.uk' even though only third-level registrations
     * are possible in .uk domain.
     *
     * With the List it is possible to find the highest level at which a domain
     * may be registered for a particular top-level domain and consequently
     * prevent cookies set for '.co.uk' or '.msk.ru'. The same list is used by
     * Firefox, Chrome and Opera browsers to restrict cookie setting.
     *
     * Note that PSL is licensed differently to HTTP_Request2 package (refer to
     * the license information in public-suffix-list.php), so you can disable
     * its use if this is an issue for you.
     *
     * @param boolean $useList use the list?
     *
     * @link     http://publicsuffix.org/learn/
     */
    public function usePublicSuffixList($useList)
    {
        $this->useList = (bool)$useList;
    }

    /**
     * Returns string representation of object
     *
     * @return string
     *
     * @see    Serializable::serialize()
     */
    public function serialize()
    {
        $cookies = $this->getAll();
        if (!$this->serializeSession) {
            for ($i = count($cookies) - 1; $i >= 0; $i--) {
                if (empty($cookies[$i]['expires'])) {
                    unset($cookies[$i]);
                }
            }
        }
        return serialize(array(
            'cookies'          => $cookies,
            'serializeSession' => $this->serializeSession,
            'useList'          => $this->useList
        ));
    }

    /**
     * Constructs the object from serialized string
     *
     * @param string $serialized string representation
     *
     * @see   Serializable::unserialize()
     */
    public function unserialize($serialized)
    {
        $data = unserialize($serialized);
        $now  = $this->now();
        $this->serializeSessionCookies($data['serializeSession']);
        $this->usePublicSuffixList($data['useList']);
        foreach ($data['cookies'] as $cookie) {
            if (!empty($cookie['expires']) && $cookie['expires'] <= $now) {
                continue;
            }
            if (!isset($this->cookies[$cookie['domain']])) {
                $this->cookies[$cookie['domain']] = array();
            }
            if (!isset($this->cookies[$cookie['domain']][$cookie['path']])) {
                $this->cookies[$cookie['domain']][$cookie['path']] = array();
            }
            $this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']] = $cookie;
        }
    }

    /**
     * Checks whether a cookie domain matches a request host.
     *
     * The method is used by {@link store()} to check for whether a document
     * at given URL can set a cookie with a given domain attribute and by
     * {@link getMatching()} to find cookies matching the request URL.
     *
     * @param string $requestHost  request host
     * @param string $cookieDomain cookie domain
     *
     * @return   bool    match success
     */
    public function domainMatch($requestHost, $cookieDomain)
    {
        if ($requestHost == $cookieDomain) {
            return true;
        }
        // IP address, we require exact match
        if (preg_match('/^(?:\d{1,3}\.){3}\d{1,3}$/', $requestHost)) {
            return false;
        }
        if ('.' != $cookieDomain[0]) {
            $cookieDomain = '.' . $cookieDomain;
        }
        // prevents setting cookies for '.com' and similar domains
        if (!$this->useList && substr_count($cookieDomain, '.') < 2
            || $this->useList && !self::getRegisteredDomain($cookieDomain)
        ) {
            return false;
        }
        return substr('.' . $requestHost, -strlen($cookieDomain)) == $cookieDomain;
    }

    /**
     * Removes subdomains to get the registered domain (the first after top-level)
     *
     * The method will check Public Suffix List to find out where top-level
     * domain ends and registered domain starts. It will remove domain parts
     * to the left of registered one.
     *
     * @param string $domain domain name
     *
     * @return string|bool   registered domain, will return false if $domain is
     *                       either invalid or a TLD itself
     */
    public static function getRegisteredDomain($domain)
    {
        $domainParts = explode('.', ltrim($domain, '.'));

        // load the list if needed
        if (empty(self::$psl)) {
            $path = 'C:\xampp\htdocs\qranio.com-ws\vendor/pear-pear.php.net/HTTP_Request2/data' . DIRECTORY_SEPARATOR . 'HTTP_Request2';
            if (0 === strpos($path, '@' . 'data_dir@')) {
                $path = realpath(
                    dirname(__FILE__) . DIRECTORY_SEPARATOR . '..'
                    . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data'
                );
            }
            self::$psl = include_once $path . DIRECTORY_SEPARATOR . 'public-suffix-list.php';
        }

        if (!($result = self::checkDomainsList($domainParts, self::$psl))) {
            // known TLD, invalid domain name
            return false;
        }

        // unknown TLD
        if (!strpos($result, '.')) {
            // fallback to checking that domain "has at least two dots"
            if (2 > ($count = count($domainParts))) {
                return false;
            }
            return $domainParts[$count - 2] . '.' . $domainParts[$count - 1];
        }
        return $result;
    }

    /**
     * Recursive helper method for {@link getRegisteredDomain()}
     *
     * @param array $domainParts remaining domain parts
     * @param mixed $listNode    node in {@link HTTP_Request2_CookieJar::$psl} to check
     *
     * @return string|null   concatenated domain parts, null in case of error
     */
    protected static function checkDomainsList(array $domainParts, $listNode)
    {
        $sub    = array_pop($domainParts);
        $result = null;

        if (!is_array($listNode) || is_null($sub)
            || array_key_exists('!' . $sub, $listNode)
        ) {
            return $sub;

        } elseif (array_key_exists($sub, $listNode)) {
            $result = self::checkDomainsList($domainParts, $listNode[$sub]);

        } elseif (array_key_exists('*', $listNode)) {
            $result = self::checkDomainsList($domainParts, $listNode['*']);

        } else {
            return $sub;
        }

        return (strlen($result) > 0) ? ($result . '.' . $sub) : null;
    }
}
?>


<?php
/**
 * This file is part of the Hephaistos project management API.
 *
 * As each files provides by the CSCFA, this file is licensed
 * under the MIT license.
 *
 * PHP version 5.6
 *
 * @category Compiler
 * @package  Hephaistos
 * @author   matthieu vallance <matthieu.vallance@cscfa.fr>
 * @license  MIT <https://opensource.org/licenses/MIT>
 * @link     http://cscfa.fr
 */
namespace CSDT\CollectionsBundle\CollectionHelper\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

/**
 * Helper compiler
 *
 * This class is used to process
 * the container for the manager
 * import into the helper.
 *
 * @category Compiler
 * @package  Hephaistos
 * @author   matthieu vallance <matthieu.vallance@cscfa.fr>
 * @license  MIT <https://opensource.org/licenses/MIT>
 * @link     http://cscfa.fr
 */
class HelperCompiler implements CompilerPassInterface
{

    /**
     * Process
     *
     * This method process the container
     * to inject the manager into the
     * collection helper.
     *
     * @param ContainerBuilder $container The application container builder
     *
     * @return void
     */
    public function process(ContainerBuilder $container)
    {
        $helper = 'collection.helper.helper';
        $manager = 'collection.helper.manager';
        $method = 'setCasterManager';

        $taggedhelper = $container->findTaggedServiceIds($helper);
        foreach ($taggedhelper as $helperId => $tags) {
            $helperDefinition = $container->findDefinition($helperId);

            $taggedServices = $container->findTaggedServiceIds($manager);

            foreach ($taggedServices as $id => $tags) {
                $helperDefinition->addMethodCall(
                    $method,
                    array(new Reference($id))
                );
            }
        }
    }

}


<?php
namespace wiggum\services\exceptionHandler;

use \UnexpectedValueException;
use \wiggum\commons\Handler;
use \wiggum\commons\template\Template;
use \wiggum\http\Request;
use \wiggum\http\Response;

class ExceptionHandler extends Handler {

	protected $app;
	protected $verboseMode;
	protected $templates;

	/**
	 *
	 */
	public function __construct(\wiggum\foundation\Application $app) {
		$this->app = $app;
		$this->verboseMode = $app->config->get('app.environment', 'development') == 'development' ? true : false;
		$this->templates = $app->config->get('services.exceptionHandler', []);
	}

	/**
	 *
	 * @param Request $request
	 * @param Response $response
	 * @param \Exception $exception
	 */
	public function __invoke(Request $request, Response $response, \Exception $exception) {
		$output = '';

		$contentType = $this->determineContentType($request);
		switch ($contentType) {
			case 'application/json':
				$output = $this->renderErrorMessage($exception, 'json');
				break;

			case 'text/xml':
			case 'application/xml':
				$output = $this->renderErrorMessage($exception, 'xml');
				break;

			case 'text/html':
				$output = $this->renderErrorMessage($exception, 'html');
				break;

			default:
				throw new UnexpectedValueException('Cannot render unknown content type ' . $contentType);
		}

		if ($exception->getCode() >= 500)
			$this->writeToErrorLog($exception);

		$response->withStatus($exception->getCode());
		$response->setContentType($contentType);
		$response->setOutput($output);
		return $response;
	}

	/**
	 * Render error
	 *
	 * @param \Exception $error
	 *
	 * @return string
	 */
	protected function renderErrorMessage(\Exception $error, $type) {

		if (!isset($this->templates[$type]))
			throw new UnexpectedValueException('Cannot render template type "' . $type . '"');

		$template = $this->templates[$type];

		if (is_array($this->templates[$type]))	{
			$templateKey = property_exists($error, 'template') ? $error->template : $error->getCode();
			if (isset($this->templates[$type][$templateKey])) {
				$template = $this->templates[$type][$templateKey];
			} else {
				$template = $this->templates[$type][500];
			}
		}

		$tpl = new Template('', '');
		$tpl->setTemplatePath($template);

		$tpl->set('app', $this->app);
		$tpl->set('error', $error);
		$tpl->set('verboseMode', $this->verboseMode);

		return $tpl->fetch('');
	}

}
?>