Parses URI parts from a URL (or a URI/query/fragment only).

@since 140417 Initial release.

@throws \Exception If unable to parse.

@return array|null

@see parseUriParts()
parseUriParts()
547956
protected function mustParseUriParts() // Arguments are NOT listed here.
    {
        if (is_null($parts = call_user_func_array([$this, 'parseUriParts'], func_get_args()))) {
            throw new \Exception(sprintf('Unable to parse: `%1$s`.', (string) func_get_arg(0)));
        }
        return $parts;
    }
235920
public function parse($uri)
	{
		// Initialise variables
		$retval = false;

		// Set the original URI to fall back on
		$this->uri = $uri;

		// Parse the URI and populate the object fields.  If URI is parsed properly,
		// set method return value to true.
		if ($parts = parse_url($uri))
		{
			$retval = true;
		}

		// We need to replace &amp; with & for parse_str to work right...
		if (isset($parts['query']) && strpos($parts['query'], '&amp;'))
		{
			$parts['query'] = str_replace('&amp;', '&', $parts['query']);
		}

		$data = array('scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment');
		foreach ($data as $part)
		{
			$this->$part = isset($parts[$part]) ? $parts[$part] : null;
		}

		// Parse the query
		if (isset($parts['query']))
		{
			parse_str($parts['query'], $this->vars);
		}

		return $retval;
	}
696380
public function parseURI(string $uri) : array
    {
        if ($uri == '') {
            throw new \InvalidArgumentException(
                "URI Could not be empty"
            );
        }

        $parsedUri = parse_url($uri);
        if ($parsedUri === false) {
            throw new \InvalidArgumentException("Unable to parse URI: $uri");
        }

        $defaultParsedUri = [
            'user'  => null,
            'pass'  => null,
            'scheme'=> '',
            'host'  => '',
            'port'  => null,
            'path'  => '',
            'query' => '',
            'fragment' => '',
        ];

        return array_merge($defaultParsedUri, $parsedUri);
    }
1298930
public function parse()
    {
        if ($this->isParsed || $this->uriPattern === null || $this->uriPattern === '') {
            return;
        }
        $this->routeParts = [];
        $currentRoutePartIsOptional = false;
        if (substr($this->uriPattern, -1) === '/') {
            throw new InvalidUriPatternException('The URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" ends with a slash, which is not allowed. You can put the trailing slash in brackets to make it optional.', 1234782997);
        }
        if ($this->uriPattern[0] === '/') {
            throw new InvalidUriPatternException('The URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" starts with a slash, which is not allowed.', 1234782983);
        }

        $matches = [];
        preg_match_all(self::PATTERN_EXTRACTROUTEPARTS, $this->uriPattern, $matches, PREG_SET_ORDER);

        /** @var $lastRoutePart RoutePartInterface */
        $lastRoutePart = null;
        foreach ($matches as $match) {
            $routePartType = empty($match['dynamic']) ? self::ROUTEPART_TYPE_STATIC : self::ROUTEPART_TYPE_DYNAMIC;
            $routePartName = $match['content'];
            if (!empty($match['optionalStart'])) {
                if ($lastRoutePart !== null && $lastRoutePart->isOptional()) {
                    throw new InvalidUriPatternException('the URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" contains successive optional Route sections, which is not allowed.', 1234562050);
                }
                $currentRoutePartIsOptional = true;
            }
            $routePart = null;
            switch ($routePartType) {
                case self::ROUTEPART_TYPE_DYNAMIC:
                    if ($lastRoutePart instanceof DynamicRoutePartInterface) {
                        throw new InvalidUriPatternException('the URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" contains successive Dynamic Route Parts, which is not allowed.', 1218446975);
                    }
                    if (isset($this->routePartsConfiguration[$routePartName]['handler'])) {
                        $routePart = $this->objectManager->get($this->routePartsConfiguration[$routePartName]['handler']);
                        if (!$routePart instanceof DynamicRoutePartInterface) {
                            throw new InvalidRoutePartHandlerException(sprintf('routePart handlers must implement "%s" in route "%s"', DynamicRoutePartInterface::class, $this->getName()), 1218480972);
                        }
                    } elseif (isset($this->routePartsConfiguration[$routePartName]['objectType'])) {
                        $routePart = new IdentityRoutePart();
                        $routePart->setObjectType($this->routePartsConfiguration[$routePartName]['objectType']);
                        if (isset($this->routePartsConfiguration[$routePartName]['uriPattern'])) {
                            $routePart->setUriPattern($this->routePartsConfiguration[$routePartName]['uriPattern']);
                        }
                    } else {
                        $routePart = new DynamicRoutePart();
                    }
                    $routePartDefaultValue = ObjectAccess::getPropertyPath($this->defaults, $routePartName);
                    if ($routePartDefaultValue !== null) {
                        $routePart->setDefaultValue($routePartDefaultValue);
                    }
                    break;
                case self::ROUTEPART_TYPE_STATIC:
                    $routePart = new StaticRoutePart();
                    if ($lastRoutePart !== null && $lastRoutePart instanceof DynamicRoutePartInterface) {
                        /** @var DynamicRoutePartInterface $lastRoutePart */
                        $lastRoutePart->setSplitString($routePartName);
                    }
            }
            $routePart->setName($routePartName);
            if ($currentRoutePartIsOptional) {
                $routePart->setOptional(true);
                if ($routePart instanceof DynamicRoutePartInterface && !$routePart->hasDefaultValue()) {
                    throw new InvalidRouteSetupException(sprintf('There is no default value specified for the optional route part "{%s}" of route "%s", but all dynamic optional route parts need a default.', $routePartName, $this->getName()), 1477140679);
                }
            }
            $routePart->setLowerCase($this->lowerCase);
            if (isset($this->routePartsConfiguration[$routePartName]['options'])) {
                $routePart->setOptions($this->routePartsConfiguration[$routePartName]['options']);
            }
            if (isset($this->routePartsConfiguration[$routePartName]['toLowerCase'])) {
                $routePart->setLowerCase($this->routePartsConfiguration[$routePartName]['toLowerCase']);
            }

            $this->routeParts[] = $routePart;
            if (!empty($match['optionalEnd'])) {
                if (!$currentRoutePartIsOptional) {
                    throw new InvalidUriPatternException('The URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" contains an unopened optional section.', 1234564495);
                }
                $currentRoutePartIsOptional = false;
            }
            $lastRoutePart = $routePart;
        }
        if ($currentRoutePartIsOptional) {
            throw new InvalidUriPatternException('The URI pattern "' . $this->uriPattern . '" of route "' . $this->getName() . '" contains an unterminated optional section.', 1234563922);
        }
        $this->isParsed = true;
    }
36621
public function parseUrl($url) : array
    {
        $url = (string) $url;

        $parsedUrl = $this->doParseUrl($url);

        if ($parsedUrl === []) {
            throw new InvalidArgumentException(sprintf('Invalid url %s', $url));
        }

        $parsedUrl = array_merge(self::$defaultParts, $parsedUrl);

        if (isset($parsedUrl['host'])) {
            $parsedUrl['canonical'] = implode('.', array_reverse(explode('.', $parsedUrl['host']))) . ($parsedUrl['path'] ?? '') . (isset($parsedUrl['query']) ? '?' . $parsedUrl['query'] : '');

            $parsedUrl['resource'] = $parsedUrl['path'] ?? '';

            if (isset($parsedUrl['query'])) {
                $parsedUrl['resource'] .= '?' . $parsedUrl['query'];
            }
        }

        return $parsedUrl;
    }
1101679
public function parse($uri)
	{
		// Create the URI object
		$uri = $this->createUri($uri);

		$this->bind($uri->getQuery(true));

		// Process the parsed variables based on custom defined rules
		foreach ($this->rules['parse'] as $rule)
		{
			if ($rule($uri))
			{
				break;
			}
		}

		$vars = array_merge($uri->getQuery(true), $this->vars());

		$this->bind($vars);

		return $this->vars();
	}
526310
protected function getURIElements()
    {
        if (isset($this->uriElements)) {
            return $this->uriElements;
        } elseif (!isset($this->request)) {
            return array();
        }

        $elements = array_slice(
            explode('/', $this->request->pathinfo),
            1,
            $this->elementNumber
        );

        // If one of the elements is empty, we do not match.
        foreach ($elements as $element) {
            if ($element === '') {
                throw new LogicException('One of the URI elements was empty');
            }
        }

        if (count($elements) !== $this->elementNumber) {
            throw new LogicException('The number of provided elements to consider is different than the number of elements found in the URI');
        }

        return $this->uriElements = $elements;
    }
186002
public function parse()
    {
        if (!is_file($this->file)) {
            throw new \Exception(sprintf(
                'Template "%s" file doesn\'t exist!', $this->file
            ));
        }

        $fp = fopen($this->file, 'r');

        $lineCount       = 0;
        $nextToken       = '';
        $block           = '';
        $currentValue    = '';
        $stringComposing = false;
        $skipMultilineComment = false;

        while (($line = fgets($fp)) !== false) {
            $lineCount++;

            if ($stringComposing) {
                if (substr(ltrim($line), 0, 3) === '>>>') {
                    $this->blocks[$block][$name] = trim($value);
                    //$block = '';
                    $value = '';
                    $stringComposing = false;
                } else {
                    // $line = trim($line);
//                     if (substr($value, -1) != '>' && ! empty($line)) {
//                         $line = " " . $line;
//                     }

                    //$value .= substr($value, -1) == '>' ? trim($line) : " " . trim($line);
                    $value .= $line;
                }

                continue;
            }

            $line = trim($line);

            if (substr($line, 0, 1) === '#' || $line === '' || substr($line, 0, 2) === '//') {
                continue; // skip single comments or empty lines
            } elseif (substr($line, 0, 2) === '/*') { // start multiline comment
                if (strpos($line, '*/') === false) {
                    $skipMultilineComment = true; // activate multiline comments skipping
                } else {
                    continue; // just skip this line, it has the form: /* ... */
                }
            } elseif (strpos($line, '*/') !== false) { // end multiline comment
                $skipMultilineComment = false;
                continue; // just skip the end multiline comment
            }

            if ($skipMultilineComment) {
                continue; //skip multiline comments segment
            }

            $kwPattern = '^@(?<keyword>\w+)';

            if (! preg_match('/'.$kwPattern.'.*/', $line, $matches)) {
                throw new \Exception(sprintf(
                    'Parse Error: Unknow keyword, lines must starts with a valid keyword, near: %s, on line %s',
                    $line, $lineCount
                ));
            }
            //var_dump($matches);
            $keyword = $matches['keyword'];

            switch ($keyword) {
                case Parser::T_DEF:
                    $pattern = '/'.$kwPattern.'\s+(?<type>[\w]+)\s+(?<name>[\w.]+)\s+(?<value>.+)/';

                    if (!preg_match($pattern, $line, $matches)) {
                        throw new \Exception(sprintf(
                            "Syntax Error: near: '%s', on line %s.\n" .
                            "Syntax should be: @def <type> <name> <value>",
                            $line, $lineCount
                        ));
                    }

                    $keyword = $matches['keyword'];
                    $type    = $matches['type'];
                    $name    = $matches['name'];
                    $value   = $matches['value'];

                    $tmp     = explode('.', $name);
                    $defName = $tmp[0];
                    $defProp = isset($tmp[1]) ? $tmp[1] : '';

                    switch ($type) {
                        case Parser::T_GLOBAL:
                        case Parser::T_ITERATOR:
                        case Parser::T_SETCONF:
                            if (substr($value, 0, 1) == '"' && substr($value, -1) == '"') {
                                $value = trim($value, '"');
                            } elseif (substr($value, 0, 1) == "'" && substr($value, -1) == "'") {
                                $value = trim($value, "'");
                            }

                            if ($value === '\n' || $value === '\r\n') {
                                $value = "\n";
                            }

                            $value = self::castValue($value);

                            if (empty($defProp)) {
                                $this->defs[$type][$defName] = $value;
                            } else {
                                $this->defs[$type][$defName][$defProp] = $value;
                            }
                            break;
                        default:
                            throw new \Exception(sprintf(
                                'Parse Error: unknow definition type: "%s" on line %s.', $type, $lineCount
                            ));
                    }
                    break;
                case Parser::T_BLOCK:
                    $pattern = '/'.$kwPattern.'\s+(?<block>[\w]+)/';

                    if (!preg_match($pattern, $line, $matches)) {
                        throw new Exception(sprintf(
                            "Parse Error: Syntax error near: %s, on line %s.\n." .
                            "Syntax should be: @def <type> <name> <value>",
                            substr($line, 0, 20).'...', $lineCount
                        ));
                    }
                    //var_dump($matches);

                    $block = $matches['block'];

                    if (!empty($nextToken)) {
                        throw new \Exception(sprintf(
                            'Parse Error: expected: @"%s", given: @"%s"', $nextToken, Parser::T_BLOCK
                        ));
                    }

                    $nextToken = Parser::T_END;
                    break;
                case Parser::T_END:
                    if (empty($nextToken)) {
                        throw new \Exception(sprintf(
                            'Parse Error: close keyword: @"%s" given, but any block was started.', Parser::T_BLOCK
                        ));
                    }

                    if ($nextToken !== Parser::T_END) {
                        throw new \Exception(sprintf(
                            'Parse Error: expected: @"%s", given: @"%s"', $nextToken, Parser::T_END
                        ));
                    }

                    $nextToken = '';
                    break;
                case Parser::T_VAR:
                    $pattern = '/'.$kwPattern.'\s+(?<name>[\w]+)\s+(?<value>.+)/';

                    if (!preg_match($pattern, $line, $matches)) {
                        throw new Exception(sprintf(
                            "Parse Error: Syntax error near: %s, on line %s.\n." .
                            "Syntax should be: @var <name> <value>\n or \n" .
                            "@var <name> <<<\nsome large string\nmultiline...\n>>>\n\n",
                            substr($line, 0, 20).'...', $lineCount
                        ));
                    }
                    //print_r($matches);
                    $keyword = $matches['keyword'];
                    $name    = $matches['name'];
                    $value   = $matches['value'];

                    if (substr($value, 0, 3) === '<<<' && $value !== '<<<') {
                        throw new \Exception(sprintf(
                            "Syntax Error: multiline string must starts on new line after open braces <<<\n" .
                            "near: '%s', on line %s", $line, $lineCount
                        ));
                    }

                    if (substr($value, 0, 1) == '"' && substr($value, -1) == '"') {
                        $value = trim($value, '"');
                    } elseif (substr($value, 0, 1) == "'" && substr($value, -1) == "'") {
                        $value = trim($value, "'");
                    }

                    if ($value !== '<<<') {
                        $this->blocks[$block][$name] = self::castValue($value);
                    } else {
                        $value = '';
                        $stringComposing = true;
                    }
                    break;
                default:
                    throw new \Exception(sprintf(
                        'Parse Error: Unknown definition type: %s, on line %s', $type, $lineCount
                    ));
            }

        }

        if ($stringComposing) {
            throw new \Exception(sprintf(
                "Parse Error: Multiline string closing braces are missing '>>>',\nfor @block: '%s', @var: '%s' " .
                "until end of file.", $block, $name
            ));
        }
    }
836103
private function getUri()
    {
        if (empty($this->uri) && ($this->uri !== false)) {
            $this->uri = $_SERVER['REQUEST_URI'];

            // Remove the parameters from the URI.
            $paramsStart = strpos($this->uri, '?');
            if ($paramsStart !== false) {
                $this->uri = substr($this->uri, 0, $paramsStart);
            }
        }

        return $this->uri;
    }
617372
public function parse($uri)
    {
        preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);

        $components = array();
        if (5 < count($match)) {
            $components =  array(
                'scheme'    => $match[2],
                'authority' => $match[4],
                'path'      => $match[5]
            );
        }
        if (7 < count($match)) {
            $components['query'] = $match[7];
        }
        if (9 < count($match)) {
            $components['fragment'] = $match[9];
        }

        return $components;
    }
836006
private function parsePathParts(Request $request)
    {
        if (empty($this->apiUrlPath)) {
            throw new \Exception(self::ERROR_NO_API_BASE_PATH);
        }

        // Resolving not knowing whether the base contains a domain.
        $base = explode('/', $this->apiUrlPath);
        $path = explode('/', $request->getPathInfo());

        return array_values(array_diff($path, $base));
    }
920000
public static function parse(string $uri): URI
    {
        if ($uri == '') {
            return new static();
        }

        $parts = parse_url($uri);
        if ($parts === false) {
            throw new \InvalidArgumentException(sprintf('Cannot parse malformed uri "%s".', $uri));
        }

        if (!isset($parts['scheme'])) {
            throw new \InvalidArgumentException(sprintf('Missing scheme in uri "%s".', $uri));
        }

        if (count($parts) == 1 && isset($parts['scheme'])) {
            throw new \InvalidArgumentException(sprintf('Missing hierarchical segment in uri "%s".', $uri));
        }

        $defaults = [
            'scheme' => '',
            'host' => '',
            'user' => '',
            'pass' => '',
            'port' => null,
            'path' => '',
            'query' => '',
            'fragment' => '',
        ];

        $parts = array_merge($defaults, $parts);

        return new static(
            $parts['scheme'],
            $parts['host'],
            $parts['path'],
            $parts['query'],
            $parts['fragment'],
            $parts['user'],
            $parts['pass'],
            $parts['port']
        );
    }
612865
protected function getURIsegments($uri, $segmentCount)
    {
        if( $uri === NULL)
        {
            $uri = URI::active();
        }

        
        return explode('/' , rtrim(Datatype::divide($uri, '/', 0, $segmentCount), '/'));
    }
1008756
public function parse($url)
    {
        foreach ($this->map as $pattern) {
            $pattern = $this->compile($pattern);
            if (preg_match($pattern, $url, $match)) {
                // remove numeric keys
                foreach ($match as $key => $value) {
                    if (is_numeric($key)) {
                        unset($match[$key]);
                    }
                }

                return $match;
            }
        }

        throw new Exceptions\InvalidArgumentException("URL '$url' did not match any route.");
    }
456616
public function getParts()
    {
        $query = (string) $this->query;

        return array(
            'scheme' => $this->scheme,
            'user' => $this->username,
            'pass' => $this->password,
            'host' => $this->host,
            'port' => $this->port,
            'path' => $this->getPath(),
            'query' => $query !== '' ? $query : null,
            'fragment' => $this->fragment,
        );
    }
1072944
protected function mustUnparseUrl() // Arguments are NOT listed here.
    {
        if (($unparsed = call_user_func_array([$this, 'unparseUrl'], func_get_args())) === '') {
            throw new \Exception(sprintf('Unable to unparse: `%1$s`.', print_r(func_get_arg(0), true)));
        }
        return $unparsed;
    }
386362
public function parseRequest(Message\Uri $uri = null)
    {
        $this->uri = is_null($uri) ? server_request()->getUri() : $uri;
        $uriSegments = $this->uri->getSegments()->getParts();
        $uriString = $this->uri->getSegments()->getString();

        if (count($uriSegments)) {
            if (strpos(end($uriSegments), '.json') !== false) {
                output()->setContentType('application/json');
                $endSegment = str_replace('.json', '', end($uriSegments));
                array_pop($uriSegments);
                array_push($uriSegments, $endSegment);
                $this->uri = $this->uri->withSegments(new Message\Uri\Segments($uriSegments));
                $uriString = $this->uri->getSegments()->getString();
            } elseif (strpos(end($uriSegments), '.xml') !== false) {
                output()->setContentType('application/xml');
                $endSegment = str_replace('.xml', '', end($uriSegments));
                array_pop($uriSegments);
                array_push($uriSegments, $endSegment);
                $this->uri = $this->uri->withSegments(new Message\Uri\Segments($uriSegments));
                $uriString = $this->uri->getSegments()->getString();
            }
        } else {
            $uriPath = urldecode(
                parse_url($_SERVER[ 'REQUEST_URI' ], PHP_URL_PATH)
            );

            $uriPathParts = explode('public/', $uriPath);
            $uriPath = end($uriPathParts);

            if ($uriPath !== '/') {
                $uriString = $uriPath;
                $uriSegments = array_filter(explode('/', $uriString));

                $this->uri = $this->uri->withSegments(new Message\Uri\Segments($uriSegments));
                $uriString = $this->uri->getSegments()->getString();
            }
        }

        // Try to translate from uri string
        if (false !== ($action = $this->addresses->getTranslation($uriString))) {
            if ( ! $action->isValidHttpMethod(server_request()->getMethod()) && ! $action->isAnyHttpMethod()) {
                output()->sendError(405);
            } else {
                if (false !== ($parseSegments = $action->getParseUriString($uriString))) {
                    $uriSegments = $parseSegments;
                } else {
                    $uriSegments = [];
                }

                $this->uri = $this->uri->withSegments(new Message\Uri\Segments($uriSegments));

                $this->parseAction($action, $uriSegments);

                if (services()->has('controller')) {
                    return true;
                }
            }
        }

        // Try to get route from controller & page
        if ($uriTotalSegments = count($uriSegments)) {
            $namespaces = [
                'App\Controllers\\',
                'App\Http\Controllers\\',
                'O2System\Reactor\Http\Controllers\\',
            ];

            for ($i = 0; $i <= $uriTotalSegments; $i++) {
                $uriRoutedSegments = array_slice($uriSegments, 0, ($uriTotalSegments - $i));

                foreach ($namespaces as $namespace) {

                    $controllerClassName = $namespace . implode('\\',
                            array_map('studlycase', $uriRoutedSegments));

                    if (class_exists($controllerClassName)) {
                        $uriSegments = array_diff($uriSegments, $uriRoutedSegments);
                        $this->setController(new Router\DataStructures\Controller($controllerClassName),
                            $uriSegments);
                        break;
                    }
                }

                // break the loop if the controller has been set
                if (services()->has('controller')) {
                    return true;
                    break;
                }
            }
        }

        // Let's the app do the rest when there is no controller found
        // the app should redirect to PAGE 404
    }