123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- <?php
- declare(strict_types=1);
- namespace Enqueue\Dsn;
- class Dsn
- {
- /**
- * @var string
- */
- private $scheme;
- /**
- * @var string
- */
- private $schemeProtocol;
- /**
- * @var string[]
- */
- private $schemeExtensions;
- /**
- * @var string|null
- */
- private $user;
- /**
- * @var string|null
- */
- private $password;
- /**
- * @var string|null
- */
- private $host;
- /**
- * @var int|null
- */
- private $port;
- /**
- * @var string|null
- */
- private $path;
- /**
- * @var string|null
- */
- private $queryString;
- /**
- * @var QueryBag
- */
- private $queryBag;
- public function __construct(
- string $scheme,
- string $schemeProtocol,
- array $schemeExtensions,
- ?string $user,
- ?string $password,
- ?string $host,
- ?int $port,
- ?string $path,
- ?string $queryString,
- array $query
- ) {
- $this->scheme = $scheme;
- $this->schemeProtocol = $schemeProtocol;
- $this->schemeExtensions = $schemeExtensions;
- $this->user = $user;
- $this->password = $password;
- $this->host = $host;
- $this->port = $port;
- $this->path = $path;
- $this->queryString = $queryString;
- $this->queryBag = new QueryBag($query);
- }
- public function getScheme(): string
- {
- return $this->scheme;
- }
- public function getSchemeProtocol(): string
- {
- return $this->schemeProtocol;
- }
- public function getSchemeExtensions(): array
- {
- return $this->schemeExtensions;
- }
- public function hasSchemeExtension(string $extension): bool
- {
- return in_array($extension, $this->schemeExtensions, true);
- }
- public function getUser(): ?string
- {
- return $this->user;
- }
- public function getPassword(): ?string
- {
- return $this->password;
- }
- public function getHost(): ?string
- {
- return $this->host;
- }
- public function getPort(): ?int
- {
- return $this->port;
- }
- public function getPath(): ?string
- {
- return $this->path;
- }
- public function getQueryString(): ?string
- {
- return $this->queryString;
- }
- public function getQueryBag(): QueryBag
- {
- return $this->queryBag;
- }
- public function getQuery(): array
- {
- return $this->queryBag->toArray();
- }
- public function getString(string $name, string $default = null): ?string
- {
- return $this->queryBag->getString($name, $default);
- }
- public function getDecimal(string $name, int $default = null): ?int
- {
- return $this->queryBag->getDecimal($name, $default);
- }
- public function getOctal(string $name, int $default = null): ?int
- {
- return $this->queryBag->getOctal($name, $default);
- }
- public function getFloat(string $name, float $default = null): ?float
- {
- return $this->queryBag->getFloat($name, $default);
- }
- public function getBool(string $name, bool $default = null): ?bool
- {
- return $this->queryBag->getBool($name, $default);
- }
- public function getArray(string $name, array $default = []): QueryBag
- {
- return $this->queryBag->getArray($name, $default);
- }
- public function toArray()
- {
- return [
- 'scheme' => $this->scheme,
- 'schemeProtocol' => $this->schemeProtocol,
- 'schemeExtensions' => $this->schemeExtensions,
- 'user' => $this->user,
- 'password' => $this->password,
- 'host' => $this->host,
- 'port' => $this->port,
- 'path' => $this->path,
- 'queryString' => $this->queryString,
- 'query' => $this->queryBag->toArray(),
- ];
- }
- public static function parseFirst(string $dsn): ?self
- {
- return self::parse($dsn)[0];
- }
- /**
- * @param string $dsn
- *
- * @return Dsn[]
- */
- public static function parse(string $dsn): array
- {
- if (false === strpos($dsn, ':')) {
- throw new \LogicException(sprintf('The DSN is invalid. It does not have scheme separator ":".'));
- }
- list($scheme, $dsnWithoutScheme) = explode(':', $dsn, 2);
- $scheme = strtolower($scheme);
- if (false == preg_match('/^[a-z\d+-.]*$/', $scheme)) {
- throw new \LogicException('The DSN is invalid. Scheme contains illegal symbols.');
- }
- $schemeParts = explode('+', $scheme);
- $schemeProtocol = $schemeParts[0];
- unset($schemeParts[0]);
- $schemeExtensions = array_values($schemeParts);
- $user = parse_url($dsn, PHP_URL_USER) ?: null;
- if (is_string($user)) {
- $user = rawurldecode($user);
- }
- $password = parse_url($dsn, PHP_URL_PASS) ?: null;
- if (is_string($password)) {
- $password = rawurldecode($password);
- }
- $path = parse_url($dsn, PHP_URL_PATH) ?: null;
- if ($path) {
- $path = rawurldecode($path);
- }
- $query = [];
- $queryString = parse_url($dsn, PHP_URL_QUERY) ?: null;
- if (is_string($queryString)) {
- $query = self::httpParseQuery($queryString, '&', PHP_QUERY_RFC3986);
- }
- $hostsPorts = '';
- if (0 === strpos($dsnWithoutScheme, '//')) {
- $dsnWithoutScheme = substr($dsnWithoutScheme, 2);
- $dsnWithoutUserPassword = explode('@', $dsnWithoutScheme, 2);
- $dsnWithoutUserPassword = 2 === count($dsnWithoutUserPassword) ?
- $dsnWithoutUserPassword[1] :
- $dsnWithoutUserPassword[0]
- ;
- list($hostsPorts) = explode('#', $dsnWithoutUserPassword, 2);
- list($hostsPorts) = explode('?', $hostsPorts, 2);
- list($hostsPorts) = explode('/', $hostsPorts, 2);
- }
- if (empty($hostsPorts)) {
- return [
- new self(
- $scheme,
- $schemeProtocol,
- $schemeExtensions,
- null,
- null,
- null,
- null,
- $path,
- $queryString,
- $query
- ),
- ];
- }
- $dsns = [];
- $hostParts = explode(',', $hostsPorts);
- foreach ($hostParts as $key => $hostPart) {
- unset($hostParts[$key]);
- $parts = explode(':', $hostPart, 2);
- $host = $parts[0];
- $port = null;
- if (isset($parts[1])) {
- $port = (int) $parts[1];
- }
- $dsns[] = new self(
- $scheme,
- $schemeProtocol,
- $schemeExtensions,
- $user,
- $password,
- $host,
- $port,
- $path,
- $queryString,
- $query
- );
- }
- return $dsns;
- }
- /**
- * based on http://php.net/manual/en/function.parse-str.php#119484 with some slight modifications.
- */
- private static function httpParseQuery(string $queryString, string $argSeparator = '&', int $decType = PHP_QUERY_RFC1738): array
- {
- $result = [];
- $parts = explode($argSeparator, $queryString);
- foreach ($parts as $part) {
- list($paramName, $paramValue) = explode('=', $part, 2);
- switch ($decType) {
- case PHP_QUERY_RFC3986:
- $paramName = rawurldecode($paramName);
- $paramValue = rawurldecode($paramValue);
- break;
- case PHP_QUERY_RFC1738:
- default:
- $paramName = urldecode($paramName);
- $paramValue = urldecode($paramValue);
- break;
- }
- if (preg_match_all('/\[([^\]]*)\]/m', $paramName, $matches)) {
- $paramName = substr($paramName, 0, strpos($paramName, '['));
- $keys = array_merge([$paramName], $matches[1]);
- } else {
- $keys = [$paramName];
- }
- $target = &$result;
- foreach ($keys as $index) {
- if ('' === $index) {
- if (is_array($target)) {
- $intKeys = array_filter(array_keys($target), 'is_int');
- $index = count($intKeys) ? max($intKeys) + 1 : 0;
- } else {
- $target = [$target];
- $index = 1;
- }
- } elseif (isset($target[$index]) && !is_array($target[$index])) {
- $target[$index] = [$target[$index]];
- }
- $target = &$target[$index];
- }
- if (is_array($target)) {
- $target[] = $paramValue;
- } else {
- $target = $paramValue;
- }
- }
- return $result;
- }
- }
|