Apply parse_url parts to a URI.

@param $parts array of parse_url parts to apply.

@throws \InvalidArgumentException
551532
private function applyParts(array $parts = [])
    {
        $this->scheme = array_key_exists('scheme', $parts) ? $this->filterScheme($parts['scheme']) : null;
        $this->userInfo = array_key_exists('user', $parts) ? $parts['user'] : null;
        $this->host = array_key_exists('host', $parts) ? $parts['host'] : null;
        $this->port = array_key_exists('port', $parts) ? $this->filterPort($this->getScheme(), $this->getHost(), $parts['port']) : null;
        $this->path = array_key_exists('path', $parts) ? $this->filterPath($parts['path']) : null;
        $this->query = array_key_exists('query', $parts) ? $this->filterQueryAndFragment($parts['query']) : null;
        $this->fragment = array_key_exists('fragment', $parts) ? $this->filterQueryAndFragment($parts['fragment']) : null;
        $this->userInfo .= array_key_exists('pass', $parts) ? ':' . $parts['pass'] : null;
    }
1134796
private static function explodePath($parts)
    {
        if (!is_array($parts)) {
            $parts = explode(self::$delimiter, $parts);
        }

        return $parts;
    }
1332698
protected function buildUrl( $parts )
	{
		$url	= new ADT_StringBuffer();
		if( isset( $parts['user'] ) && isset( $parts['pass'] ) && $parts['user'] )
			$url->append( $parts['user'].":".$parts['pass']."@" );
		if( substr( $parts['path'], 0, 1 ) != "/" )
			$parts['path']	= "/".$parts['path'];
		$host	= $parts['host'].( !empty( $parts['port'] ) ? ":".$parts['port'] : "" );
		$url->append( $host.$parts['path'] );
		if( isset( $parts['query'] ) )
			$url->append( "?".$parts['query'] );
		$url	= str_replace( "//", "/", $url->toString() );
		$url	= $parts['scheme']."://".$url;
		return $url;
	}
1244503
private function validateUrl( $urlParts ) {
        if ( !is_array( $urlParts ) ) {
            throw new \InvalidArgumentException( 'Invalid serverUrl has been provided' );
        }

        if ( !isset( $urlParts["scheme"] ) ) {
            throw new \InvalidArgumentException( 'serverUrl has been provided without a valid scheme (http:// or https://)' );
        }

        if ( !isset( $urlParts["host"] ) ) {
            throw new \InvalidArgumentException( 'Invalid serverUrl has been provided' );
        }
    }
1124719
private function parseUri($uri)
    {
        $parts = parse_url($uri);

        if (false === $parts) {
            throw new \InvalidArgumentException(
                'The source URI string appears to be malformed'
            );
        }

        $this->scheme    = isset($parts['scheme'])   ? $this->filterScheme($parts['scheme']) : '';
        $this->userInfo  = isset($parts['user'])     ? $parts['user']     : '';
        $this->host      = isset($parts['host'])     ? $parts['host']     : '';
        $this->port      = isset($parts['port'])     ? $parts['port']     : null;
        $this->path      = isset($parts['path'])     ? $this->filterPath($parts['path']) : '';
        $this->query     = isset($parts['query'])    ? $this->filterQuery($parts['query']) : '';
        $this->fragment  = isset($parts['fragment']) ? $this->filterFragment($parts['fragment']) : '';

        if (isset($parts['pass'])) {
            $this->userInfo .= ':' . $parts['pass'];
        }
    }
1305502
protected function buildChangesPath(string ...$parts)
    {
        return static::buildPath('repositories', $this->username, $this->repo, 'issues', $this->issue, 'changes', ...$parts);
    }
177573
protected function buildStepsPath(string ...$parts)
    {
        return static::buildPath('repositories', $this->username, $this->repo, 'pipelines', $this->pipeline, 'steps', ...$parts);
    }
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;
    }
653947
protected function _buildStringFromParsed(array $parts, $params = [])
    {
        if ($params instanceof \Traversable)
            $params = StdTravers::of($params)->toArray();

        if (! is_array($params) )
            throw new \InvalidArgumentException(sprintf(
                'Parameters must be an array or Traversable; given: (%s).'
                , \Poirot\Std\flatten($params)
            ));


        // regard to recursive function call
        $isOptional = false;
        $args = func_get_args();
        if ($args && isset($args[2]))
            $isOptional = $args[2];

        # Check For Presented Values in Optional Segment
        // consider this "/[@:username{{\w+}}][-:userid{{\w+}}]"
        // if username not presented as params injected then first part include @ as literal
        // not rendered.
        // optional part only render when all parameter is present
        if ($isOptional) {
            foreach ($parts as $parsed) {
                if (! isset($parsed['_parameter_']) )
                    continue;

                ## need parameter
                $neededParameterName = $parsed['_parameter_'];
                if (! (isset($params[$neededParameterName]) && $params[$neededParameterName] !== '') )
                    return '';
            }
        }


        $return    = '';
        // [0 => ['_literal_' => 'localhost'], 1=>['_optional' => ..] ..]
        foreach ($parts as $parsed) {
            $definition_name  = key($parsed);
            $definition_value = $parsed[$definition_name];
            // $parsed can also have extra parsed data options
            // _parameter_ String(3) => tld \
            // tld String(4)         => .com
            switch ($definition_name)
            {
                case '_literal_':
                    $return .= $definition_value;
                    break;

                case '_parameter_':
                    if (! isset($params[$definition_value]) ) {
                        if ($isOptional)  return '';

                        throw new \InvalidArgumentException(sprintf(
                            'Missing parameter (%s).'
                            , $definition_value
                        ));
                    }

                    if (! \Poirot\Std\isStringify($params[$definition_value]) )
                        throw new \Exception(sprintf(
                            'Parameter %s is not stringify; given: (%s).'
                            , $definition_value
                            , \Poirot\Std\flatten($params[$definition_value])
                        ));

                    $return .= $params[$definition_value];
                    break;

                case '_optional_':
                    $optionalPart = $this->_buildStringFromParsed($definition_value, $params, true);
                    if ($optionalPart !== '')
                        $return .= $optionalPart;

                    break;
            }
        }

        return $return;
    }
114511
private function applyParts(array $parts)
    {
        $this->scheme = isset($parts['scheme'])
            ? $this->filterScheme($parts['scheme'])
            : '';
        $this->userInfo = isset($parts['user']) ? $parts['user'] : '';
        $this->host = isset($parts['host']) ? $parts['host'] : '';
        $this->port = !empty($parts['port'])
            ? $this->filterPort($this->scheme, $this->host, $parts['port'])
            : null;
        $this->path = isset($parts['path'])
            ? $this->filterPath($parts['path'])
            : '';
        $this->query = isset($parts['query'])
            ? $this->filterQueryAndFragment($parts['query'])
            : '';
        $this->fragment = isset($parts['fragment'])
            ? $this->filterQueryAndFragment($parts['fragment'])
            : '';
        if (isset($parts['pass'])) {
            $this->userInfo .= ':' . $parts['pass'];
        }
    }
200283
static function buildUrl($parts)
    {
        $parts = new ArrayObject($parts);

        ###################
        ### PARSE PARTS ###
        ###################

        // scheme
        $scheme = $parts->key('scheme', '', true);

        // host
        $host = $parts->key('host', '', true);

        // port
        $port = $parts->key('port', '', true);

        // path
        $path = $parts->key('path', '', true);

        // parse query string
        $query = '';
        if($parts->keyExists('query')) {
            if(self::isString($parts->key('query'))) {
                parse_str($parts->key('query'), $queryData);
            } else {
                $queryData = $parts->key('query');
            }

            if(self::isArray($queryData)) {
                $query = $queryData;
            }
        }


        ###################
        ### BUILD URL   ###
        ###################
        $url = '';

        // scheme
        if($scheme && $scheme != '') {
            $url .= $scheme . '://';
        }

        // host
        if($host && $host != '') {
            $url .= $host;
        }

        // port
        if($port != '') {
            $url .= ':' . $port;
        }

        // path
        if($path != '') {
            $url .= $path;
        }

        // query
        if(self::isArray($query)) {
            $query = http_build_query($query);
            if($query != "") {
                $url .= '?' . $query;
            }
        }

        try {
            return new UrlObject($url);
        } catch (\Exception $e) {
            throw new UrlObjectException($e->getMessage());
        }
    }
251880
protected function buildAttachmentsPath(string ...$parts)
    {
        return static::buildPath('repositories', $this->username, $this->repo, 'issues', $this->issue, 'attachments', ...$parts);
    }
1165845
public function setParts(array $parts)
    {
        $this->parts = array();

        foreach($parts as $part) {
            $this->add($part);
        }
        return $this;
    }
814864
private function parseUri($uri)
    {
        $components = parse_url($uri);

        if (!$components) {
            throw new InvalidValueException('Invalid URI.');
        }

        $this->scheme   = isset($components['scheme'])   ? $this->filterScheme($components['scheme']) : '';
        $this->host     = isset($components['host'])     ? $components['host'] : '';
        $this->port     = isset($components['port'])     ? $this->filterPort($components['port']) : 0;
        $this->user     = isset($components['user'])     ? decode($components['user']) : '';
        $this->password = isset($components['pass'])     ? decode($components['pass']) : '';
        $this->path     = isset($components['path'])     ? $this->parsePath($components['path']) : '';
        $this->query    = isset($components['query'])    ? $this->parseQuery($components['query']) : [];
        $this->fragment = isset($components['fragment']) ? $this->parseFragment($components['fragment']) : '';
    }
549373
protected function buildPath(array $parts, array $params, $optional = false) {
        $path = '';
        foreach ($parts as $part) {
            switch ($part[0]) {
                case 'literal':
                    $path .= $part[1];
                    break;
                case 'parameter':
                    if (!isset($params[$part[1]])) {
                        if (!$optional) {
                            throw new Exception(
                                __('Missing parameter "{name}"', [
                                    'name' => $path[1]
                                ])
                            );
                        }
                        return '';
                    }
                    $path .= rawurlencode($params[$part[1]]);
                    break;
                case 'optional':
                    $segment = $this->buildPath($part[1], $params, true);
                    if ($segment !== '') {
                        $path .= $segment;
                    }
                    break;
            }
        }
        return $path;
    }
994422
protected function marshalInstance(array $parts)
    {
        $this->scheme = array_key_exists('scheme', $parts)
            ? $this->marshalScheme($parts['scheme'])
            : ''
        ;

        $this->userInfo = $parts['user'] ?? null;

        if ( array_key_exists('pass', $parts) ) {
            $this->userInfo .= ':'.$parts['pass'];
        }

        $this->host = array_key_exists('host', $parts)
            ? $this->marshalHost($parts['host'])
            : $this->host
        ;

        $this->port = array_key_exists('port', $parts)
            ? $this->marshalPort($parts['port'])
            : null
        ;

        $this->path = array_key_exists('path', $parts)
            ? $this->marshalPath($parts['path'])
            : '/'
        ;

        $this->query = array_key_exists('query', $parts)
            ? $this->marshalQueryAndFragment($parts['query'])
            : null
        ;

        $this->fragment = array_key_exists('fragment', $parts)
            ? $this->marshalQueryAndFragment($parts['fragment'])
            : null
        ;

        if ( empty($this->scheme) && ! array_key_exists('host', $parts) && ! array_key_exists('port', $parts) ) {
            $this->scheme = 'http';
        }

        $this->calibratePort();
    }
450810
public static function set(array &$array, $parts, $item)
    {
        if (!self::isArray($array)) {
            throw new \InvalidArgumentException('ArrayUtils::getByPath expects an array or an ArrayAccess object.');
        }
        foreach (self::explodePath($parts) as $k) {
            if ($k === null || $k === '') {
                $k = count($array);
            }
            if (!static::arrayHasKey($array, $k)) {
                $array[$k] = [];
            }
            $array = & $array[$k];
        }
        $array = $item;
    }