Add route.

@param string[] $methods Array of HTTP methods
@param string   $pattern The route pattern
@param callable $handler The route callable

@throws InvalidArgumentException if the route pattern isn't a string

@return RouteInterface
974637
public function map($methods, $pattern, $handler)
    {
        if (!is_string($pattern)) {
            throw new InvalidArgumentException('Route pattern must be a string');
        }

        // Prepend parent group pattern(s)
        if ($this->routeGroups) {
            $pattern = $this->processGroups().$pattern;
        }

        // Add route
        $route = new Route($methods, $pattern, $handler, $this->routeGroups);
        $this->routes[] = $route;

        return $route;
    }
1086782
public function addMethod($method)
    {
        if (!is_string($method)) {
            throw new InvalidArgumentException(
                sprintf(
                    'Unsupported HTTP method; must be a string, received %s',
                    (is_object($method) ? get_class($method) : gettype($method))
                )
            );
        }

        // According to RFC, methods are defined in uppercase (See RFC 7231)
        $method = strtoupper($method);

        $validHttpMethods = [
            'CONNECT',
            'DELETE',
            'GET',
            'HEAD',
            'OPTIONS',
            'PATCH',
            'POST',
            'PUT',
            'TRACE',
        ];

        if (!in_array($method, $validHttpMethods)) {
            throw new InvalidArgumentException(sprintf(
                'Unsupported HTTP method; must be one of "%s", received "%s"',
                implode('","', $validHttpMethods),
                $method
            ));
        }

        $this->methods[] = $method;

        return $this;
    }
1008075
public function map($method, $path, $handler)
    {
        $path = sprintf('/%s', ltrim($path, '/'));

        $route = (new Route)->setMethods((array) $method)
        ->setPath($path)->setCallable($handler);

        $this->routes[$path] = $route;

        return $route;
    }
1080854
public function get($path, callable $handler): RouterInterface
    {
        $ruler = $this->createRuler('GET', $path);
        return $this->addRuler($ruler, $handler);
    }
24821
public Router all(@NotNull final String pattern, @NotNull final Middleware... handler) {
        get(pattern, handler);
        put(pattern, handler);
        post(pattern, handler);
        delete(pattern, handler);
        options(pattern, handler);
        head(pattern, handler);
        trace(pattern, handler);
        connect(pattern, handler);
        patch(pattern, handler);
        return this;
    }
575338
public Router connect(@NotNull final String pattern, @NotNull final IMiddleware... handlers) {
        addPattern("CONNECT", pattern, handlers, connectBindings);
        return this;
    }
968171
public function add($method, $pattern, $callback, array $params = [])
    {
        $pattern = '/' . trim($pattern, '/');

        $pattern = rtrim($this->prefix . $pattern, '/');
        $pattern = $pattern ?: '/' . $pattern;

        if (!is_array($method)) {
            $method = [$method];
        }

        $before = $this->getParam($params, 'before');
        $after  = $this->getParam($params, 'after');
        $name   = $this->getParam($params, 'name');

        $before = $before ? explode('|', $params['before']) : [];
        $after  = $after ? explode('|', $params['after']) : [];

        $this->storeRoute($method, [
            'pattern'  => $pattern,
            'name'     => $name,
            'callback' => $callback,
            'before'   => array_merge($this->before, $before),
            'after'    => array_merge($this->after, $after),
            'args'     => [],
        ]);

        return $this;
    }
349268
public function pattern(string $parameter, string $pattern) : RouteBuilder
    {
        foreach ($this->routes as $route) {
            $route->tokens([
                $parameter => $pattern,
            ]);
        }
        return $this;
    }
1141498
public function route(
        string $method,
        string $pattern,
        callable $callback,
        int $priority = 0
    ): RouterInterface {
        //hard requirement
        if (!is_callable($callback)) {
            throw HttpException::forInvalidRouteCallback();
        }

        if (strtoupper($method) === 'ALL') {
            $method = '[a-zA-Z0-9]+';
        }

        //find and organize all the dynamic parameters
        preg_match_all('#(\:[a-zA-Z0-9\-_]+)|(\*\*)|(\*)#s', $pattern, $matches);

        $keys = array();
        if (isset($matches[0]) && is_array($matches[0])) {
            $keys = $matches[0];
        }

        //replace the :variable-_name01
        $regex = preg_replace('#(\:[a-zA-Z0-9\-_]+)#s', '*', $pattern);

        //replace the stars
        //* -> ([^/]+)
        $regex = str_replace('*', '([^/]+)', $regex);
        //** -> ([^/]+)([^/]+) -> (.*)
        $regex = str_replace('([^/]+)([^/]+)', '(.*)', $regex);

        //now form the event pattern
        $event = '#^' . $method . '\s' . $regex . '/*$#is';

        //we need the handler for later
        $handler = $this->getEventHandler();

        $handler->on(
            $event,
            function (
                RequestInterface $request,
                ...$args
            ) use (
                $handler,
                $callback,
                $pattern,
                $keys
            ) {
                $route = $handler->getMeta();
                $variables = array();
                $parameters = array();

                //sanitize the variables
                foreach ($route['variables'] as $i => $variable) {
                    //if it's a * variable
                    if (!isset($keys[$i]) || strpos($keys[$i], '*') === 0) {
                        //it's a variable
                        if (strpos($variable, '/') === false) {
                            $variables[] = $variable;
                            continue;
                        }

                        $variables = array_merge($variables, explode('/', $variable));
                        continue;
                    }

                    //if it's a :parameter
                    if (isset($keys[$i])) {
                        $key = substr($keys[$i], 1);
                        $parameters[$key] = $variable;
                    }
                }

                $request
                    ->setStage($parameters)
                    ->setRoute(array(
                        'event' => $route['event'],
                        'variables' => $variables,
                        'parameters' => $parameters
                    ));

                return call_user_func($callback, $request, ...$args);
            },
            $priority
        );

        return $this;
    }
521889
public function route(Route $route, $handler) 
	{
		if (!is_callable($handler)) {
			throw new Exception('Route handler must be callable.');
		}

		$this->currentContext->addRoute($route, $handler);
		return $this;
	}
282140
public function query($method, $pattern, $callback)
    {
        $route = new Route($pattern, $callback, $method);
        $this['router']->addRoute($route);

        return $route;
    }
1369502
public function create(
        string $method,
        string $definition,
        RequestHandlerInterface $handler,
        ?string $name,
        $data
    ): Route {
        if (!Method::isValid($method)) {
            throw InvalidRoute::invalidMethod($method);
        }

        $path = $this->parser->parse($definition, $this->types);

        return new Route($method, $path, $handler, $name, $data);
    }
978476
public function post($path, callable $handler): RouterInterface
    {
        $ruler = $this->createRuler('POST', $path);
        return $this->addRuler($ruler, $handler);
    }
810424
public function get($pattern, $handler, array $requirements = [], array $defaults = [])
    {
        $this->addRoute('GET', $pattern, $handler, $requirements, $defaults);
    }
974150
public function addMethod($method)
    {
        // Capitalise method
        $method = strtoupper($method);

        if (!in_array($method, self::$availableMethods)) {
            throw new InvalidArgumentException(sprintf('Invalid method for route with path "%s". Method must be one of: ' . implode(', ', self::$availableMethods) . '. Got "%s" instead.', $this->getPath(), $method));
        }

        if (!in_array($method, $this->methods)) {
            $this->methods[] = $method;
        }

        // Add HEAD method if GET has been allowed for this Route
        if ($method == 'GET') {
            $this->addMethod('HEAD');
        }

        return $this;
    }
275236
public function resolveGroup($pattern, $route = null)
    {
        foreach($this->groupHandlers as $handler)
        {
            if(!$handler->validate($pattern, $route))
                continue;

            return $handler->resolve($this, $pattern, $route);
        }

        foreach($this->defaultGroupHandlers as $handler)
        {
            if(!$handler->validate($pattern, $route))
                continue;

            return $handler->resolve($this, $pattern, $route);
        }

        throw new InvalidArgumentException('Unable to resolve the routing group pattern');
    }
284498
public function map(array $methods, string $pattern, $callable): MethodsInterface
    {
        $this->container('router')->map($methods, $pattern, $callable);
        return $this;
    }