Вход Регистрация
Файл: sngine-v2.8/Script/includes/libs/Embed/Http/Url.php
Строк: 557
<?php

namespace EmbedHttp;

/**
 * Class to split and manipulate urls.
 */
class Url
{
    private 
$info;
    private 
$url;
    private static 
$public_suffix_list;

    
/**
     * Create a new Url instance.
     *
     * @param string $url
     *
     * @return Url
     */
    
public static function create($url)
    {
        return 
Redirects::resolve(new static($url));
    }

    
/**
     * Constructor. Sets the url.
     *
     * @param string $url
     */
    
private function __construct($url)
    {
        
$this->parseUrl($url);
    }

    
/**
     * Returns the url.
     *
     * @return string
     */
    
public function __toString()
    {
        if (
$this->url === null) {
            return 
$this->url $this->buildUrl();
        }

        return 
$this->url;
    }

    
/**
     * Remove the built url on clone.
     */
    
public function __clone()
    {
        
$this->url null;
    }

    
/**
     * Check if the url match with a specific pattern. The patterns only accepts * and ?
     *
     * @param string|array $patterns The pattern or an array with various patterns
     *
     * @return bool
     */
    
public function match($patterns)
    {
        if (!
is_array($patterns)) {
            
$patterns = [$patterns];
        }

        
//Remove scheme and query
        
$long_url preg_replace('|^(w+://)|''', (string) $this);
        
$short_url preg_replace('|(?.*)?$|'''$long_url);

        foreach (
$patterns as $pattern) {
            if (
$pattern[0] === '?') { // ?hello=world => *?hello=world
                
$pattern '*' $pattern;
            }

            
$pattern str_replace('\*''.*'preg_quote($pattern'|'));

            if (
strpos($pattern'?') === false) {
                
$url $short_url;
            } else {
                
$pattern str_replace('\?&''[\?&]'$pattern);
                
$url $long_url;
            }

            if (
preg_match('|^'.$pattern.'$|i'$url)) {
                return 
true;
            }
        }

        return 
false;
    }

    
/**
     * Return the content of the url (for embedded images).
     *
     * @return string The content or null
     */
    
public function getContent()
    {
        return isset(
$this->info['content']) ? $this->info['content'] : null;
    }

    
/**
     * Return the extension of the url (html, php, jpg, etc).
     *
     * @return string The scheme or null
     */
    
public function getExtension()
    {
        return isset(
$this->info['extension']) ? $this->info['extension'] : null;
    }

    
/**
     * Returns a new instance with other relative url.
     *
     * @param string $url
     *
     * @return Url
     */
    
public function createAbsolute($url)
    {
        return 
self::create($this->getAbsolute($url));
    }

    
/**
     * Returns a clone with other extension.
     *
     * @param string $extension
     *
     * @return Url
     */
    
public function withExtension($extension)
    {
        
$clone = clone $this;
        
$clone->info['extension'] = $extension;

        if (empty(
$clone->info['file'])) {
            
$clone->info['file'] = array_pop($clone->info['path']);
        }

        return 
$clone;
    }

    
/**
     * Return the scheme of the url (for example http, https, ftp, etc).
     *
     * @return string The scheme or null
     */
    
public function getScheme()
    {
        return isset(
$this->info['scheme']) ? $this->info['scheme'] : null;
    }

    
/**
     * Returns a clone with other scheme.
     *
     * @param string $scheme
     *
     * @return Url
     */
    
public function withScheme($scheme)
    {
        
$clone = clone $this;
        
$clone->info['scheme'] = $scheme;

        return 
$clone;
    }

    
/**
     * Return the host of the url (for example: google.com).
     *
     * @return string The host or null
     */
    
public function getHost()
    {
        return isset(
$this->info['host']) ? $this->info['host'] : null;
    }

    
/**
     * Returns a clone with other host.
     *
     * @param string $host
     *
     * @return Url
     */
    
public function withHost($host)
    {
        
$clone = clone $this;
        
$clone->info['host'] = $host;

        return 
$clone;
    }

    
/**
     * Return the domain of the url (for example: google).
     *
     * @param bool $first_level True to return the first level domain (.com, .es, etc)
     *
     * @return string
     */
    
public function getDomain($first_level false)
    {
        
$host $this->getHost();

        if (empty(
$host)) {
            return 
'';
        }

        
$host array_reverse(explode('.'$host));

        switch (
count($host)) {
            case 
1:
                return 
$host[0];

            case 
2:
                return 
$first_level ? ($host[1].'.'.$host[0]) : $host[1];

            default:
                
$tld $host[1].'.'.$host[0];
                
$suffixes self::getSuffixes();

                if (
in_array($tld$suffixestrue)) {
                    return 
$first_level $host[2].'.'.$tld $host[2];
                }

                return 
$first_level $host[1].'.'.$host[0] : $host[1];
        }
    }

    
/**
     * Return a specific directory position in the path of the url.
     *
     * @param int $position The position of the directory (0 based index)
     *
     * @return string|null
     */
    
public function getDirectoryPosition($position)
    {
        if (
$position === count($this->info['path'])) {
            return 
urldecode($this->info['file']);
        }

        return isset(
$this->info['path'][$position]) ? urldecode($this->info['path'][$position]) : null;
    }

    
/**
     * Returns a clone with other directory in a specific position.
     *
     * @param int|null $key   The position of the subdirectory (0 based index)
     * @param string   $value The new value
     *
     * @return Url
     */
    
public function withDirectoryPosition($key$value)
    {
        
$clone = clone $this;

        
$pos $clone->info['path'];
        
$hasFile = isset($clone->info['file']);

        if (
$hasFile) {
            
$pos[] = $clone->info['file'];
        }

        
$pos[$key] = $value;

        if (
$hasFile) {
            
$clone->info['file'] = array_pop($pos);
        }

        
$clone->info['path'] = $pos;

        return 
$clone;
    }

    
/**
     * Return all directories.
     *
     * @return string
     */
    
public function getDirectories()
    {
        return !empty(
$this->info['path']) ? '/'.implode('/'$this->info['path']).'/' '/';
    }

    
/**
     * Slice path.
     *
     * @param int      $offset
     * @param int|null $length
     *
     * @return array
     */
    
public function getSlicePath($offset$length null)
    {
        
$array explode('/'$this->getPath());

        if (empty(
$array[0])) {
            
array_shift($array);
        }

        return 
array_slice($array$offset$length);
    }

    
/**
     * Return the url path.
     *
     * @return string
     */
    
public function getPath()
    {
        
$path = !empty($this->info['path']) ? '/'.implode('/'array_map('self::urlEncode'$this->info['path'])).'/' '/';

        if (isset(
$this->info['file'])) {
            
$path .= self::urlEncode($this->info['file']);

            if (isset(
$this->info['extension'])) {
                
$path .= '.'.$this->info['extension'];
            }
        }

        return 
$path;
    }

    
/**
     * Returns a clone with other path.
     *
     * @param string $path
     *
     * @return Url
     */
    
public function withPath($path)
    {
        
$clone = clone $this;

        
$clone->setPath($path);

        return 
$clone;
    }

    
/**
     * Returns a clone with path appended.
     *
     * @param string $path
     *
     * @return Url
     */
    
public function withAddedPath($path)
    {
        
$path $this->getPath().'/'.$path;

        return 
$this->withPath($path);
    }

    
/**
     * Check if the url has a query parameter.
     *
     * @param string $name
     *
     * @return bool
     */
    
public function hasQueryParameter($name)
    {
        return isset(
$this->info['query'][$name]);
    }

    
/**
     * Returns all query parameters.
     *
     * @return array
     */
    
public function getQueryParameters()
    {
        return 
$this->info['query'];
    }

    
/**
     * Returns a query parameter value.
     *
     * @param string $name
     *
     * @return string|null
     */
    
public function getQueryParameter($name)
    {
        return isset(
$this->info['query'][$name]) ? $this->info['query'][$name] : null;
    }

    
/**
     * Returns a clone with a new query parameter.
     *
     * @param string $name  The parameter name
     * @param string $value The parameter value
     *
     * @return Url
     */
    
public function withQueryParameter($name$value)
    {
        
$clone = clone $this;

        
$clone->info['query'][$name] = $value;

        return 
$clone;
    }

    
/**
     * Returns a clone with new query parameters merged.
     *
     * @param array $parameters
     *
     * @return Url
     */
    
public function withAddedQueryParameters(array $parameters)
    {
        
$clone = clone $this;

        
$clone->info['query'] = empty($clone->info['query']) ? $parameters array_replace($clone->info['query'], $parameters);

        return 
$clone;
    }

    
/**
     * Returns a clone with new query parameters.
     *
     * @param array $parameters
     *
     * @return Url
     */
    
public function withQueryParameters(array $parameters)
    {
        
$clone = clone $this;

        
$clone->info['query'] = $parameters;

        return 
$clone;
    }

    
/**
     * Return the url fragment.
     *
     * @return string
     */
    
public function getFragment()
    {
        return isset(
$this->info['fragment']) ? $this->info['fragment'] : null;
    }

    
/**
     * Return ClassName for domain.
     *
     * Domains started with numbers will get N prepended to their class name.
     *
     * @return string
     */
    
public function getClassNameForDomain()
    {
        
$className str_replace(array('-'' '), ''ucwords(strtolower($this->getDomain())));

        if (
is_numeric(mb_substr($className01))) {
            
$className 'N'.$className;
        }

        return 
$className;
    }

    
/**
     * Build the url using the splitted data.
     */
    
protected function buildUrl()
    {
        
$url '';

        if (isset(
$this->info['content'])) {
            return 
'data:'.$this->info['content'];
        }

        if (isset(
$this->info['scheme'])) {
            
$url .= $this->info['scheme'].'://';
        }

        
$user = isset($this->info['user']) ? $this->info['user'] : '';
        
$pass = isset($this->info['pass']) ? ':'.$this->info['pass'] : '';
        if (
$user || $pass) {
            
$url .= $user.$pass.'@';
        }

        if (isset(
$this->info['host'])) {
            
$url .= $this->info['host'];
        }

        if (isset(
$this->info['port'])) {
            
$url .= ':'.$this->info['port'];
        }

        
$url .= $this->getPath();

        if (!empty(
$this->info['query'])) {
            
$url .= '?'.rtrim(http_build_query($this->info['query']), '=');
        }
        if (isset(
$this->info['fragment'])) {
            
$url .= '#'.$this->info['fragment'];
        }

        return 
$url;
    }

    
/**
     * Parse an url and split into different pieces.
     *
     * @param string $url The url to parse
     */
    
protected function parseUrl($url)
    {
        
$this->info self::parse($url);

        if (isset(
$this->info['path'])) {
            
$this->setPath($this->info['path']);
        }

        if (empty(
$this->info['query'])) {
            
$this->info['query'] = [];

            return;
        }

        
// Fix dots and other characters used in query's variables names
        // https://github.com/oscarotero/Embed/issues/101
        
$queryString preg_replace_callback('/(^|(?<=&))[^=[&]+/', function ($key) {
            return 
bin2hex(urldecode($key[0]));
        }, 
$this->info['query']);

        
parse_str($queryString$query);

        
$this->info['query'] = [];

        foreach ((array) 
$query as $key => $value) {
            
$this->info['query'][hex2bin($key)] = $value;
        }
    }

    
/**
     * Return an absolute url based in a relative.
     *
     * @return string
     */
    
public function getAbsolute($url)
    {
        
$url trim($url);

        if (empty(
$url)) {
            return 
'';
        }

        if (
preg_match('|^w+:[^/]|'$url)) {
            return 
$url;
        }

        if (
preg_match('|^w+://|'$url)) {
            return 
self::validUrlOrEmpty($url);
        }

        if (
strpos($url'://') === 0) {
            return 
self::validUrlOrEmpty($this->getScheme().$url);
        }

        if (
strpos($url'//') === 0) {
            return 
self::validUrlOrEmpty($this->getScheme().":$url");
        }

        if (
$url[0] === '/') {
            return 
self::validUrlOrEmpty($this->getScheme().'://'.$this->getHost().$url);
        }

        return 
self::validUrlOrEmpty($this->getScheme().'://'.$this->getHost().$this->getDirectories().$url);
    }

    
/**
     * Parses and adds path and file value.
     *
     * @param string $path
     */
    
private function setPath($path)
    {
        
$this->info['path'] = $this->info['file'] = $this->info['extension'] = $this->info['content'] = null;

        if (
$this->getScheme() === 'data') {
            
$this->info['content'] = $path;

            return;
        }

        
$file substr(strrchr($path'/'), 1);

        if (
strlen($file)) {
            
$path substr($path0, -strlen($file));

            if (
preg_match('/(.*).([w]+)$/'$file$match)) {
                
$this->info['file'] = rawurldecode($match[1]);
                
$this->info['extension'] = $match[2];
            } else {
                
$this->info['file'] = rawurldecode($file);
            }
        }

        
$this->info['path'] = [];

        foreach (
explode('/'$path) as $dir) {
            
$dir rawurldecode($dir);

            if (
$dir !== '') {
                
$this->info['path'][] = $dir;
            }
        }
    }

    private static function 
getSuffixes()
    {
        if (
self::$public_suffix_list === null) {
            
self::$public_suffix_list = (@include __DIR__.'/../resources/public_suffix_list.php') ?: [];
        }

        return 
self::$public_suffix_list;
    }

    
/**
     * UTF-8 compatible parse_url
     * http://php.net/manual/en/function.parse-url.php#114817
     *
     * @param string $url
     *
     * @return string
     */
    
private static function parse($url)
    {
        
$enc_url preg_replace_callback(
            
'%[^:/@?&=#]+%usD',
            function (
$matches) {
                return 
rawurlencode($matches[0]);
            },
            
$url
        
);

        
$parts parse_url($enc_url);

        if (
$parts === false) {
            throw new 
InvalidArgumentException('Malformed URL: ' $url);
        }

        if (!empty(
$parts['scheme']) && !in_array($parts['scheme'], ['http''https''data'])) {
            throw new 
InvalidArgumentException(sprintf('Invalid URL scheme: "%s"'$parts['scheme']));
        }

        foreach (
$parts as $name => $value) {
            
$parts[$name] = rawurldecode($value);
        }
        return 
$parts;
    }

    private static function 
urlEncode($path)
    {
        
// : - used for files
        // @, + and , - used for GoogleMaps adapter url (in view and streetview modes)
        
return str_replace(['%3A','%40','%2C''%2B'], [':','@',',''+'], rawurlencode($path));
    }

    private static function 
validUrlOrEmpty($url)
    {
        return 
parse_url($url) === false '' $url;
    }
}
Онлайн: 0
Реклама