Initial Commit
This commit is contained in:
178
dependencies/league/uri-interfaces/KeyValuePair/Converter.php
vendored
Normal file
178
dependencies/league/uri-interfaces/KeyValuePair/Converter.php
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* League.Uri (https://uri.thephpleague.com)
|
||||
*
|
||||
* (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
declare (strict_types=1);
|
||||
namespace WP_Ultimo\Dependencies\League\Uri\KeyValuePair;
|
||||
|
||||
use WP_Ultimo\Dependencies\League\Uri\Contracts\UriComponentInterface;
|
||||
use WP_Ultimo\Dependencies\League\Uri\Exceptions\SyntaxError;
|
||||
use Stringable;
|
||||
use function array_combine;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function is_float;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
use function json_encode;
|
||||
use function preg_match;
|
||||
use function str_replace;
|
||||
use const JSON_PRESERVE_ZERO_FRACTION;
|
||||
use const PHP_QUERY_RFC1738;
|
||||
use const PHP_QUERY_RFC3986;
|
||||
final class Converter
|
||||
{
|
||||
private const REGEXP_INVALID_CHARS = '/[\\x00-\\x1f\\x7f]/';
|
||||
/** @var non-empty-string */
|
||||
private readonly string $separator;
|
||||
/**
|
||||
* @param array<string> $fromRfc3986 contains all the RFC3986 encoded characters to be converted
|
||||
* @param array<string> $toEncoding contains all the expected encoded characters
|
||||
*/
|
||||
private function __construct(string $separator, private readonly array $fromRfc3986 = [], private readonly array $toEncoding = [])
|
||||
{
|
||||
if ('' === $separator) {
|
||||
throw new SyntaxError('The separator character must be a non empty string.');
|
||||
}
|
||||
$this->separator = $separator;
|
||||
}
|
||||
/**
|
||||
* @param non-empty-string $separator
|
||||
*/
|
||||
public static function new(string $separator) : self
|
||||
{
|
||||
return new self($separator);
|
||||
}
|
||||
/**
|
||||
* @param non-empty-string $separator
|
||||
*/
|
||||
public static function fromRFC3986(string $separator = '&') : self
|
||||
{
|
||||
return self::new($separator);
|
||||
}
|
||||
/**
|
||||
* @param non-empty-string $separator
|
||||
*/
|
||||
public static function fromRFC1738(string $separator = '&') : self
|
||||
{
|
||||
return self::new($separator)->withEncodingMap(['%20' => '+']);
|
||||
}
|
||||
/**
|
||||
* @param non-empty-string $separator
|
||||
*
|
||||
* @see https://url.spec.whatwg.org/#application/x-www-form-urlencoded
|
||||
*/
|
||||
public static function fromFormData(string $separator = '&') : self
|
||||
{
|
||||
return self::new($separator)->withEncodingMap(['%20' => '+', '%2A' => '*']);
|
||||
}
|
||||
public static function fromEncodingType(int $encType) : self
|
||||
{
|
||||
return match ($encType) {
|
||||
PHP_QUERY_RFC3986 => self::fromRFC3986(),
|
||||
PHP_QUERY_RFC1738 => self::fromRFC1738(),
|
||||
default => throw new SyntaxError('Unknown or Unsupported encoding.'),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @return non-empty-string
|
||||
*/
|
||||
public function separator() : string
|
||||
{
|
||||
return $this->separator;
|
||||
}
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function encodingMap() : array
|
||||
{
|
||||
return array_combine($this->fromRfc3986, $this->toEncoding);
|
||||
}
|
||||
/**
|
||||
* @return array<non-empty-list<string|null>>
|
||||
*/
|
||||
public function toPairs(Stringable|string|int|float|bool|null $value) : array
|
||||
{
|
||||
$value = match (\true) {
|
||||
$value instanceof UriComponentInterface => $value->value(),
|
||||
$value instanceof Stringable, is_int($value) => (string) $value,
|
||||
\false === $value => '0',
|
||||
\true === $value => '1',
|
||||
default => $value,
|
||||
};
|
||||
if (null === $value) {
|
||||
return [];
|
||||
}
|
||||
$value = match (1) {
|
||||
preg_match(self::REGEXP_INVALID_CHARS, (string) $value) => throw new SyntaxError('Invalid query string: `' . $value . '`.'),
|
||||
default => str_replace($this->toEncoding, $this->fromRfc3986, (string) $value),
|
||||
};
|
||||
return \array_map(fn(string $pair): array => explode('=', $pair, 2) + [1 => null], explode($this->separator, $value));
|
||||
}
|
||||
private static function vString(Stringable|string|bool|int|float|null $value) : ?string
|
||||
{
|
||||
return match (\true) {
|
||||
$value => '1',
|
||||
\false === $value => '0',
|
||||
null === $value => null,
|
||||
is_float($value) => (string) json_encode($value, JSON_PRESERVE_ZERO_FRACTION),
|
||||
default => (string) $value,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @param iterable<array{0:string|null, 1:Stringable|string|bool|int|float|null}> $pairs
|
||||
*/
|
||||
public function toValue(iterable $pairs) : ?string
|
||||
{
|
||||
$filteredPairs = [];
|
||||
foreach ($pairs as $pair) {
|
||||
$filteredPairs[] = match (\true) {
|
||||
!is_string($pair[0]) => throw new SyntaxError('the pair key MUST be a string;, `' . \gettype($pair[0]) . '` given.'),
|
||||
null === $pair[1] => self::vString($pair[0]),
|
||||
default => self::vString($pair[0]) . '=' . self::vString($pair[1]),
|
||||
};
|
||||
}
|
||||
return match ([]) {
|
||||
$filteredPairs => null,
|
||||
default => str_replace($this->fromRfc3986, $this->toEncoding, implode($this->separator, $filteredPairs)),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @param non-empty-string $separator
|
||||
*/
|
||||
public function withSeparator(string $separator) : self
|
||||
{
|
||||
return match ($this->separator) {
|
||||
$separator => $this,
|
||||
default => new self($separator, $this->fromRfc3986, $this->toEncoding),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Sets the conversion map.
|
||||
*
|
||||
* Each key from the iterable structure represents the RFC3986 encoded characters as string,
|
||||
* while each value represents the expected output encoded characters
|
||||
*/
|
||||
public function withEncodingMap(iterable $encodingMap) : self
|
||||
{
|
||||
$fromRfc3986 = [];
|
||||
$toEncoding = [];
|
||||
foreach ($encodingMap as $from => $to) {
|
||||
[$fromRfc3986[], $toEncoding[]] = match (\true) {
|
||||
!is_string($from) => throw new SyntaxError('The encoding output must be a string; `' . \gettype($from) . '` given.'),
|
||||
$to instanceof Stringable, is_string($to) => [$from, (string) $to],
|
||||
default => throw new SyntaxError('The encoding output must be a string; `' . \gettype($to) . '` given.'),
|
||||
};
|
||||
}
|
||||
return match (\true) {
|
||||
$fromRfc3986 !== $this->fromRfc3986, $toEncoding !== $this->toEncoding => new self($this->separator, $fromRfc3986, $toEncoding),
|
||||
default => $this,
|
||||
};
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user