* @since 1.0.0 */ private array $query = []; /** * Uri query. * * @var string * @since 1.0.0 */ private string $queryString; /** * Uri fragment. * * @var string * @since 1.0.0 */ public string $fragment; /** * Uri fragments. * * @var array * @since 1.0.0 */ public array $fragments = []; /** * Uri base. * * @var string * @since 1.0.0 */ private string $base; /** * Constructor. * * @param string $uri Root path for subdirectory * * @since 1.0.0 */ public function __construct(string $uri) { $this->set($uri); } /** * {@inheritdoc} */ public function set(string $uri) : void { $this->uri = $uri; $url = \parse_url($this->uri); if ($url === false) { $this->scheme = ''; $this->host = ''; $this->port = 80; $this->user = ''; $this->pass = ''; $this->path = ''; $this->queryString = ''; $this->query = []; $this->pathElements = []; $this->fragment = ''; $this->base = ''; return; } $this->scheme = $url['scheme'] ?? ''; $this->host = $url['host'] ?? ''; $this->port = $url['port'] ?? 80; $this->user = $url['user'] ?? ''; $this->pass = $url['pass'] ?? ''; $this->path = $url['path'] ?? ''; if (StringUtils::endsWith($this->path, '.php')) { $path = \substr($this->path, 0, -4); if ($path === false) { throw new \Exception(); // @codeCoverageIgnore } $this->path = $path; } $this->pathElements = \explode('/', \trim($this->path, '/')); $path = \array_slice($this->pathElements, $this->pathOffset); $this->offsetPath = '/' . \implode('/', $path); $this->queryString = $url['query'] ?? ''; if (!empty($this->queryString)) { \parse_str($this->queryString, $this->query); } $this->query = \array_change_key_case($this->query, \CASE_LOWER); $this->fragment = $url['fragment'] ?? ''; $this->fragments = \explode('&', $url['fragment'] ?? ''); $this->base = $this->scheme . '://' . $this->host . ($this->port !== 80 ? ':' . $this->port : '') . $this->rootPath; } /** * Get current uri. * * @return string Returns the current uri * * @since 1.0.0 * @codeCoverageIgnore */ public static function getCurrent() : string { /** @noinspection PhpUndefinedConstantInspection */ return ((!empty($_SERVER['HTTPS'] ?? '') && ($_SERVER['HTTPS'] ?? '') !== 'off') || (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https') || (($_SERVER['HTTP_X_FORWARDED_SSL'] ?? '') === 'on') ? 'https' : 'http') . '://' . ($_SERVER['HTTP_HOST'] ?? ''). ($_SERVER['REQUEST_URI'] ?? ''); } /** * Create uri from current url * * @return HttpUri Returns the current uri * * @since 1.0.0 * @codeCoverageIgnore */ public static function fromCurrent() : self { return new self(self::getCurrent()); } /** * {@inheritdoc} */ public static function isValid(string $uri) : bool { return (bool) \filter_var($uri, \FILTER_VALIDATE_URL); } /** * {@inheritdoc} */ public function getRootPath() : string { return $this->rootPath; } /** * {@inheritdoc} */ public function setRootPath(string $root) : void { $this->rootPath = \rtrim($root, '/'); $this->base = $this->scheme . '://' . $this->host . ($this->port !== 80 ? ':' . $this->port : '') . $this->rootPath; } /** * {@inheritdoc} */ public function setPathOffset(int $offset = 0) : void { $this->pathOffset = $offset; $path = \array_slice($this->pathElements, $this->pathOffset); $this->offsetPath = '/' . \implode('/', $path); } /** * Return the subdomain of a host * * @return string * * @since 1.0.0 */ public function getSubdomain() : string { $host = \explode('.', $this->host); $length = \count($host) - 2; if ($length < 1) { return ''; } return \implode('.', \array_slice($host, 0, $length)); } /** * {@inheritdoc} */ public function getPath(int $offset = 0) : string { return $this->path; } /** * {@inheritdoc} */ public function setPath(string $path) : void { $this->path = $path; $this->pathElements = \explode('/', \ltrim($this->path, '/')); $path = \array_slice($this->pathElements, $this->pathOffset); $this->offsetPath = '/' . \implode('/', $path); } /** * Get path offset. * * @return int * * @since 1.0.0 */ public function getPathOffset() : int { return $this->pathOffset; } /** * {@inheritdoc} */ public function getRoute(bool $ignoreOffset = false) : string { $path = $ignoreOffset ? $this->path : $this->offsetPath; $query = $this->getQuery(); return $path . (!empty($query) ? '?' . $this->getQuery() : ''); } /** * {@inheritdoc} */ public function getQuery(string $key = null) : string { if ($key !== null) { $key = \strtolower($key); return $this->query[$key] ?? ''; } return $this->queryString; } /** * {@inheritdoc} */ public function getPathElement(int $pos = 0) : string { return $this->pathElements[$pos + $this->pathOffset] ?? ''; } /** * {@inheritdoc} */ public function getPathElements() : array { return $this->pathElements; } /** * {@inheritdoc} */ public function getQueryArray() : array { return $this->query; } /** * {@inheritdoc} */ public function getBase() : string { return $this->base; } /** * {@inheritdoc} */ public function __toString() { return $this->uri; } /** * {@inheritdoc} */ public function getAuthority() : string { return ($this->user !== '' ? $this->user . '@' : '') . $this->host . ($this->port !== 0 ? ':' . $this->port : ''); } /** * {@inheritdoc} */ public function getUserInfo() : string { return $this->user . (!empty($this->pass) ? ':' . $this->pass : ''); } }