public static function parseUrl($url): Url
    {
        $parts = parse_url($url);
        
        if (false === $parts || false === Arrays::hasElement($parts, 'host') || false === Arrays::hasElement($parts, 'scheme')) {
            throw new InvalidUrlException('The URL {url} does not contain necessary parts', array('url' => $url));
        }
        
        $address = $parts['host'];
        $scheme = $parts['scheme'];
        $query = (isset($parts['query']) ? $parts['query'] : '');
        $port = 0;
        $path = "/";
        
        if (isset($parts['port'])) {
            $port = intval($parts['port']);
        }
        
        if ($port == 0) {
            $port = self::getPortByScheme($scheme);
        }
        
        if (isset($parts['path'])) {
            $path = $parts['path'];
        }
        
        return new Url($address, $port, $path, $scheme, $query);
    }