Main dispatcher. Looks for patterns from the config.

@param string $uri Current URI
@param array $config Routing configuration

@return string Controller's callback
547951
private static function _mainDispatcher($uri, $config) {
        $uriInfo = self::analizeUri();
        $uri = $uriInfo['uri'];
        $uriItems = explode('/', $uri);
        $attributes = [];

        foreach ($config['routes'] as $routePattern => $className) {
            if (preg_match('#' . $routePattern . '#', $uri)) {
                $class = $className;
                $itemCount = count(explode('/', str_replace('\\/', '/', $routePattern)));

                for ($i = 0; $i < $itemCount; $i++) {
                    unset($uriItems[$i]);
                }
                $attributes = array_values($uriItems);
                break;
            }
        }

        if (!$class) {
            $class = self::_getController($uri, 'App\\');
            $classUri = self::_getControllerBaseUri($class);
            
            if(strpos($uri, $classUri) === 0 && strlen($uri) > strlen($classUri)) {
                $attributesUri = substr($uri, strlen($classUri)+1);
                $attributes = explode('/', $attributesUri);
            }
        }
        
        return [
            'class' => self::fixNamespace($class ? $class : self::_getController($uri, 'App\\')),
            'method' => strtolower($_SERVER['REQUEST_METHOD']),
            'attributes' => $attributes
        ];
    }
730932
public function actionAll( $config = [] ) {

		Url::remember( Yii::$app->request->getUrl(), 'site-members' );

		$siteId = Yii::$app->request->get( 'sid' );

		$dataProvider = $this->modelService->getPageBySiteId( $siteId );

		return $this->render( 'all', [
			'dataProvider' => $dataProvider,
			'siteId' => $siteId
		]);
	}
1326655
private function findRoute(string $uri, string $method): RouteInterface
    {
        $matches = [];
        $route = new NullRoute();

        foreach ($this->routes as $value) {
            $urlMatch = \preg_match('`^'.\preg_replace($this->matchTypes, $this->types, $value->url).'/?$`', $uri, $matches);
            $methodMatch = \strpos($value->method, $method);

            if ($urlMatch && $methodMatch !== false) {
                $route = clone $value;
                $this->routeMatches = $matches;
                break;
            }
        }

        return $route;
    }
459118
public function dispatch(string $httpMethod, string $uri) : array
    {
        $urlPath = rawurldecode(parse_url($uri, PHP_URL_PATH));
        $routeInfo = $this->routeDispatcher->dispatch($httpMethod, $urlPath);
        return $routeInfo;
    }
730889
protected function parseRoutes($uri)
    {
        if (Container::get('config')->get('url_route_annotation')) {
            $finder = new Finder();
            $finder
                ->in(Container::get('config')->get('app_full_path') . '/controllers')
                ->name('*.php');
            $controllerNamespaces = [];
            foreach ($finder as $file) {
                array_push($controllerNamespaces, '\\' . Container::get('config')->get('namespace_prefix') . 'controllers\\' . $file->getBasename('.' . $file->getExtension()));
            }

            foreach ($controllerNamespaces as $namespace) {
                $classReflector = new ReflectionClass($namespace);
                $classAnnotations = new Annotations($classReflector);

                foreach ($classReflector->getMethods() as $methodReflector) {
                    $methodAnnotations = new Annotations($methodReflector);
                    if (!isset($methodAnnotations['route'])) {
                        continue;
                    } else {
                        $routeAnnotations = $methodAnnotations['route'];
                        if (!isset($routeAnnotations['uri'])) {
                            throw new ConfigException('Route annotations error');
                        }

                        $controllerName = $classReflector->getShortName();
                        $actionName = $methodReflector->getName();
                        $route = $controllerName . '/' . $actionName;
                        if (isset($routeAnnotations['params'])) {
                            $route .= '/' . $routeAnnotations['params'];
                        }

                        if (!isset($routeAnnotations['method'])) {
                            $this->routes[$routeAnnotations['uri']] = $route;
                        } else {
                            $this->routes[$routeAnnotations['uri']][$routeAnnotations['method']] = $route;
                        }

                        unset($route);
                    }
                }
            }
        } else {
            $this->routes = Container::get('config')->get('url_route');
        }

        $hostName = Container::get('request')->getHostName();

        if (isset($this->routes[$hostName])) {
            $this->routes = $this->routes[$hostName];
        }

        // Get HTTP verb
        $httpVerb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';

        if (null != $this->routes) {
            foreach ($this->routes as $key => $val) {
                // Check if route format is using HTTP verbs
                if (is_array($val)) {
                    $val = array_change_key_case($val, CASE_LOWER);
                    if (isset($val[$httpVerb])) {
                        $val = $val[$httpVerb];
                    } else {
                        continue;
                    }
                }

                // Does the RegEx match?
                if (preg_match('#^' . $key . '$#', $uri, $matches)) {
                    // Are we using callbacks to process back-references?
                    if (!is_string($val) && is_callable($val)) {
                        // Remove the original string from the matches array.
                        array_shift($matches);

                        // Execute the callback using the values in matches as its parameters.
                        $val = call_user_func_array($val, $matches);
                    } // Are we using the default routing method for back-references?
                    elseif (strpos($val, '$') !== false && strpos($key, '(') !== false) {
                        $val = preg_replace('#^' . $key . '$#', $val, $uri);
                    }

                    return $val;
                }
            }
        }
    }
401729
protected function getRequestConfig(array $config) : array
    {
        if (!empty($this->defaultRequestOptions)) {
            $config = array_replace_recursive($this->defaultRequestOptions, $config);
        }

        return $config;
    }
722372
protected static function addRedirectUriToServiceConfig(array $config)
    {
        if (!empty($config['constructor']) && is_array($config['constructor'])) {
            $key = key($config['constructor']); // Key may be non-numeric

            if (!isset($config['constructor'][$key]['redirectUri'])) {
                $config['constructor'][$key]['redirectUri'] = static::getRedirectUri();
            }
        }

        return $config;
    }
84794
private function getInstanceHelper($config)
    {
        if (is_callable($config)) {
            return $config;
        }
        if (!isset($config['class_name'])) {
            throw new Exception\RuntimeException('Config router convert miss "class_name"');
        }
        $className = $config['class_name'];
        if (!class_exists($className)) {
            throw new Exception\RuntimeException(sprintf('"%s" is not existed', $className));
        }

        /**
         * @todo User can config parameter when create new object
         * @todo User can config call method after creating object
         */
        $object = new $className;

        return $object;
    }
104289
public function createController($config)
    {
        $this->fileService->mkdir($config['_path_controller_'], 0777, true);

        $request = $this->fileService->get($config['template_source'].'/Controller.txt');

        foreach ($config as $key => $value) {
            $request = str_replace($key, $value, $request);
        }

        $request = $this->putIfNotExists($config['_path_controller_'].'/'.$config['_ucCamel_casePlural_'].'Controller.php', $request);

        return $request;
    }
47596
public function parseUrl($url, $config = []) {
		foreach ($this->_hosts as $stub) {
			$match = $this->_matchUrl($url, (array)$stub['url-match']);
			if (!$match) {
				continue;
			}

			$this->_match = $match;

			if (!empty($stub['fetch-match'])) {
				if (!$this->_parseLink($url, $stub['fetch-match'])) {
					return null;
				}
			}

			$stub['match'] = $this->_match;
			$Object = $this->object($stub, $config + $this->config);
			return $Object;
		}
	}
364971
public function init( $config = [ ] )
    {
        if ( isset( $_SERVER[ 'HTTP_USER_AGENT' ] ) )
        {
            $this->userAgent = $_SERVER[ 'HTTP_USER_AGENT' ];
        }
        if ( isset( $_SERVER[ 'SERVER_NAME' ] ) )
        {
            $this->server = $_SERVER[ 'SERVER_NAME' ];
        }
        if ( isset( $_SERVER[ 'SERVER_PORT' ] ) )
        {
            $this->port = $_SERVER[ 'SERVER_PORT' ];
        }
        if ( isset( $_SERVER[ 'REQUEST_METHOD' ] ) )
        {
            $this->method = $_SERVER[ 'REQUEST_METHOD' ];
        }
        if ( isset( $_SERVER[ 'QUERY_STRING' ] ) )
        {
            $this->query = $_SERVER[ 'QUERY_STRING' ];
        }
        if ( isset( $_SERVER[ 'SCRIPT_NAME' ] ) )
        {
            $this->script = $_SERVER[ 'SCRIPT_NAME' ];
        }
        if ( isset( $_SERVER[ 'REQUEST_URI' ] ) )
        {
            $this->requestUri = $_SERVER[ 'REQUEST_URI' ];
        }
        if ( isset( $_SERVER[ 'REQUEST_SCHEME' ] ) )
        {
            $this->scheme = $_SERVER[ 'REQUEST_SCHEME' ];
        }

        $request = str_replace( $_SERVER[ 'SCRIPT_NAME' ], '', $this->requestUri );

        $elements = explode( '/', $request );

        if ( '' === $elements[ 0 ] )
        {
            array_shift( $elements );
        }

        if ( 2 <= count( $elements ) )
        {
            $this->route = $elements[ 0 ] . '/' . $elements[ 1 ];

            array_shift( $elements );
            array_shift( $elements );

            if ( 0 < count( $elements ) )
            {
                $this->params = $elements;
            }
        }
        else if ( 1 === count( $elements ) )
        {
            $this->route = $elements[ 0 ];

            array_shift( $elements );
        }
    }
622126
public function actionAll( $config = [] ) {

		Url::remember( Yii::$app->request->getUrl(), 'groups' );

		return parent::actionAll( $config );
	}
1211413
public function route(array $method, $uri, $callback, $options = [])
    {
        if (is_array($uri)) {
            foreach ($uri as $u) {
                $this->route($method, $u, $callback, $options);

            }
            return $this;
        }
        $options = array_merge(['ajaxOnly' => false, 'continue' => false], (array)$options);

        if ($uri != '/') {
            $uri = $this->removeDuplSlash($uri) . '/';
        }
        // Replace named uri param to regex pattern.
        $pattern = $this->namedParameters($uri);
        $this->currentUri = $pattern;

        if ($options['ajaxOnly'] == false || $options['ajaxOnly'] && $this->req->ajax) {
            // If matched before, skip this.
            if ($this->matched === false) {
                // Prepare.
                $pattern = $this->prepare(
                    str_replace(['/?', '/*'], [$this->pattern['/?'], $this->pattern['/*']], $this->removeDuplSlash($this->group . $pattern))
                );

                // If matched.
                $method = count($method) > 0 ? in_array($this->req->method, $method) : true;
                if ($method && $this->matched($pattern)) {
                    if ($this->isGroup) {
                        $this->prams = array_merge($this->pramsGroup, $this->prams);
                    }

                    $this->req->args = $this->bindArgs($this->prams, $this->matchedArgs);

                    $this->matchedPath = $this->currentUri;
                    $this->routeCallback[] = $callback;

                    if ($options['continue']) {
                        $this->matched = false;
                    }
                }
            }
        }
        $this->_as($this->removeParameters($this->trimSlash($uri)));
        return $this;
    }
1178682
protected function treatRouterConfig(array $config): void
    {
        if (!\array_key_exists('router', $config)) {
            return;
        }

        if (!\is_array($config['router'])) {
            throw new RouterException('Config router has to be an array');
        }

        if (\array_key_exists('middlewares', $config['router'])) {
            if (!\is_array($config['router']['middlewares'])) {
                throw new RouterException('Config router/middlewares has to be an array');
            }

            $this->setGlobalMiddlewares($config['router']['middlewares']);
        }

        if (\array_key_exists('constraints', $config['router'])) {
            if (!\is_array($config['router']['constraints'])) {
                throw new RouterException('Config router/constraints has to be an array');
            }

            $this->setGlobalParametersConstraints($config['router']['constraints']);
        }

        if (\array_key_exists('host', $config['router'])) {
            if (!\is_string($config['router']['host'])) {
                throw new RouterException('Config router/host has to be a string');
            }

            $this->setGlobalHost($config['router']['host']);
        }

        if (\array_key_exists('host_constraints', $config['router'])) {
            if (!\is_array($config['router']['host_constraints'])) {
                throw new RouterException('Config router/host_constraints has to be an array');
            }

            $this->setGlobalHostConstraints($config['router']['host_constraints']);
        }

        if (\array_key_exists('default_404', $config['router'])) {
            $this->setDefault404($config['router']['default_404']);
        }
    }
130344
final protected function getConfigs($config = null)
    {
        if (null !== $config) {
            if (array_key_exists($config, self::$_configs)) {
                return self::$_configs[$config];
            } else {
                return false;
            }
        }

        return self::$_configs;
    }
199160
protected function treatRoutesConfig(array $config): void
    {
        if (!\array_key_exists('routes', $config)) {
            return;
        }

        if (!\is_array($config['routes'])) {
            throw new RouterException('Config routes has to be an array');
        }

        foreach ($config['routes'] as $route) {
            if (!\array_key_exists('methods', $route)) {
                throw new RouterException('Config routes/methods is mandatory');
            }

            if (!\array_key_exists('url', $route)) {
                throw new RouterException('Config routes/url is mandatory');
            }

            if (!\array_key_exists('callback', $route)) {
                throw new RouterException('Config routes/callback is mandatory');
            }

            $newRoute = new Route($route['methods'], $route['url'], $route['callback']);

            if (\array_key_exists('constraints', $route)) {
                $newRoute->setParametersConstraints($route['constraints']);
            }

            if (\array_key_exists('middlewares', $route)) {
                if (!\is_array($route['middlewares'])) {
                    throw new RouterException('Config routes/middlewares has to be an array');
                }

                foreach ($route['middlewares'] as $middleware) {
                    $newRoute->addMiddleware($middleware);
                }
            }

            if (\array_key_exists('name', $route)) {
                if (!\is_string($route['name'])) {
                    throw new RouterException('Config routes/name has to be a string');
                }

                $newRoute->setName($route['name']);
            }

            if (\array_key_exists('host', $route)) {
                if (!\is_string($route['host'])) {
                    throw new RouterException('Config routes/host has to be a string');
                }

                $newRoute->setHost($route['host']);
            }

            if (\array_key_exists('host_constraints', $route)) {
                if (!\is_array($route['host_constraints'])) {
                    throw new RouterException('Config routes/host_constraints has to be an array');
                }

                $newRoute->setHostConstraints($route['host_constraints']);
            }

            if (\array_key_exists('optionals_parameters', $route)) {
                if (!\is_array($route['optionals_parameters'])) {
                    throw new RouterException('Config routes/optionals_parameters has to be an array');
                }

                $newRoute->setOptionalsParameters($route['optionals_parameters']);
            }

            $this->addRoute($newRoute);
        }
    }
177692
public function createApi($config)
    {
        $routesMaster = $config['_path_api_routes_'];

        if (!file_exists($routesMaster)) {
            $this->putIfNotExists($routesMaster, "<?php\n\n");
        }

        $this->fileService->mkdir($config['_path_api_controller_'], 0777, true);

        $routes = $this->fileService->get($config['template_source'].'/ApiRoutes.txt');

        foreach ($config as $key => $value) {
            $routes = str_replace($key, $value, $routes);
        }

        $this->filesystem->append($routesMaster, $routes);

        $request = $this->fileService->get($config['template_source'].'/ApiController.txt');

        foreach ($config as $key => $value) {
            $request = str_replace($key, $value, $request);
        }

        $request = $this->putIfNotExists($config['_path_api_controller_'].'/'.$config['_ucCamel_casePlural_'].'Controller.php', $request);

        return $request;
    }