Final Class Yiisoft\Http\HeaderValueHelper
| Inheritance | Yiisoft\Http\HeaderValueHelper |
|---|
HeaderValueHelper parses the header value parameters.
Public Methods
| Method | Description | Defined By |
|---|---|---|
| getParameters() | Explodes a header value parameters (eg. q=2;version=6) | Yiisoft\Http\HeaderValueHelper |
| getSortedAcceptTypes() | Returns a list of sorted content types from the accept header values. | Yiisoft\Http\HeaderValueHelper |
| getSortedValueAndParameters() | Returns a header value as "q" factor sorted list. | Yiisoft\Http\HeaderValueHelper |
| getValueAndParameters() | Explodes a header value to value and parameters (eg. text/html;q=2;version=6) | Yiisoft\Http\HeaderValueHelper |
Constants
| Constant | Value | Description | Defined By |
|---|---|---|---|
| PATTERN_ATTRIBUTE | self::PATTERN_TOKEN | Yiisoft\Http\HeaderValueHelper | |
| PATTERN_QUOTED_STRING | '(?:"(?:(?:\\\.)+|[^\"]+)*")' | Yiisoft\Http\HeaderValueHelper | |
| PATTERN_TOKEN | '(?:(?:[^()<>@,;:\"\/[\]?={} \t\x7f]|[\x00-\x1f])+)' | Yiisoft\Http\HeaderValueHelper | |
| PATTERN_VALUE | '(?:' . self::PATTERN_QUOTED_STRING . '|' . self::PATTERN_TOKEN . ')' | Yiisoft\Http\HeaderValueHelper |
Method Details
Explodes a header value parameters (eg. q=2;version=6)
| public static string[] getParameters ( string $headerValueParameters, boolean $lowerCaseParameter = true, boolean $lowerCaseParameterValue = true ) | ||
| $headerValueParameters | string |
Header value parameters. |
| $lowerCaseParameter | boolean |
Whether should cast header parameter name to lowercase. |
| $lowerCaseParameterValue | boolean |
Whether should cast header parameter value to lowercase. |
| return | string[] |
Key-value are the parameters. |
|---|---|---|
public static function getParameters(
string $headerValueParameters,
bool $lowerCaseParameter = true,
bool $lowerCaseParameterValue = true
): array {
$headerValueParameters = trim($headerValueParameters);
if ($headerValueParameters === '') {
return [];
}
if (rtrim($headerValueParameters, ';') !== $headerValueParameters) {
throw new InvalidArgumentException('Cannot end with a semicolon.');
}
$output = [];
do {
/**
* @var string $headerValueParameters We use valid regular expression, so `preg_replace()` always returns string.
*/
$headerValueParameters = preg_replace_callback(
'/^[ \t]*(?<parameter>' . self::PATTERN_ATTRIBUTE . ')[ \t]*=[ \t]*(?<value>' . self::PATTERN_VALUE . ')[ \t]*(?:;|$)/u',
static function (array $matches) use (&$output, $lowerCaseParameter, $lowerCaseParameterValue): string {
$value = $matches['value'];
if (mb_strpos($matches['value'], '"') === 0) {
/**
* Unescape + Remove first and last quote
*
* @var string $value We use valid regular expression, so `preg_replace()` always returns string.
*/
$value = preg_replace('/\\\\(.)/u', '$1', mb_substr($value, 1, -1));
}
$key = $lowerCaseParameter ? mb_strtolower($matches['parameter']) : $matches['parameter'];
if (isset($output[$key])) {
// The first is the winner.
return '';
}
/** @psalm-suppress MixedArrayAssignment False-positive error */
$output[$key] = $lowerCaseParameterValue ? mb_strtolower($value) : $value;
return '';
},
$headerValueParameters,
1,
$count
);
if ($count !== 1) {
throw new InvalidArgumentException('Invalid input: ' . $headerValueParameters);
}
} while ($headerValueParameters !== '');
/** @var array<string,string> $output */
return $output;
}
Returns a list of sorted content types from the accept header values.
| public static string[] getSortedAcceptTypes ( string|string[] $values ) | ||
| $values | string|string[] |
Header value as a comma-separated string or already exploded string array. |
| return | string[] |
Sorted accept types. Note: According to RFC 7231, special parameters (except the q factor) are added to the type, which are always appended by a semicolon and sorted by string. |
|---|---|---|
public static function getSortedAcceptTypes($values): array
{
$output = self::getSortedValueAndParameters($values);
usort($output, static function (array $a, array $b) {
/**
* @psalm-var QFactorHeader $a
* @psalm-var QFactorHeader $b
*/
if ($a['q'] !== $b['q']) {
// The higher q value wins
return $a['q'] > $b['q'] ? -1 : 1;
}
/** @var string $typeA */
$typeA = reset($a);
/** @var string $typeB */
$typeB = reset($b);
if (strpos($typeA, '*') === false && strpos($typeB, '*') === false) {
$countA = count($a);
$countB = count($b);
if ($countA === $countB) {
// They are equivalent for the same parameter number
return 0;
}
// No wildcard character, higher parameter number wins
return $countA > $countB ? -1 : 1;
}
$endWildcardA = substr($typeA, -1, 1) === '*';
$endWildcardB = substr($typeB, -1, 1) === '*';
if (($endWildcardA && !$endWildcardB) || (!$endWildcardA && $endWildcardB)) {
// The wildcard ends is the loser.
return $endWildcardA ? 1 : -1;
}
// The wildcard starts is the loser.
return strpos($typeA, '*') === 0 ? 1 : -1;
});
foreach ($output as $key => $value) {
$type = array_shift($value);
unset($value['q']);
if (count($value) === 0) {
$output[$key] = $type;
continue;
}
foreach ($value as $k => $v) {
$value[$k] = $k . '=' . $v;
}
// Parameters are sorted for easier use of parameter variations.
asort($value, SORT_STRING);
$output[$key] = $type . ';' . implode(';', $value);
}
/** @var string[] $output */
return $output;
}
Returns a header value as "q" factor sorted list.
See also getValueAndParameters().
| public static array[] getSortedValueAndParameters ( string|string[] $values, boolean $lowerCaseValue = true, boolean $lowerCaseParameter = true, boolean $lowerCaseParameterValue = true ) | ||
| $values | string|string[] |
Header value as a comma-separated string or already exploded string array. |
| $lowerCaseValue | boolean |
Whether should cast header value to lowercase. |
| $lowerCaseParameter | boolean |
Whether should cast header parameter name to lowercase. |
| $lowerCaseParameterValue | boolean |
Whether should cast header parameter value to lowercase. |
| return | array[] |
The q factor sorted list. |
|---|---|---|
public static function getSortedValueAndParameters(
$values,
bool $lowerCaseValue = true,
bool $lowerCaseParameter = true,
bool $lowerCaseParameterValue = true
): array {
/** @var mixed $values Don't trust to annotations. */
if (!is_array($values) && !is_string($values)) {
throw new InvalidArgumentException('Values are neither array nor string.');
}
$list = [];
foreach ((array) $values as $headerValue) {
if (!is_string($headerValue)) {
throw new InvalidArgumentException('Values must be array of strings.');
}
/** @psalm-suppress InvalidOperand Presume that `preg_split` never returns false here. */
$list = [...$list, ...preg_split('/\s*,\s*/', trim($headerValue), -1, PREG_SPLIT_NO_EMPTY)];
}
/** @var string[] $list */
if (count($list) === 0) {
return [];
}
$output = [];
foreach ($list as $value) {
$parse = self::getValueAndParameters(
$value,
$lowerCaseValue,
$lowerCaseParameter,
$lowerCaseParameterValue
);
// case-insensitive "q" parameter
$q = $parse['q'] ?? $parse['Q'] ?? 1.0;
// min 0.000 max 1.000, max 3 digits, without digits allowed
if (is_string($q) && preg_match('/^(?:0(?:\.\d{1,3})?|1(?:\.0{1,3})?)$/', $q) === 0) {
throw new InvalidArgumentException('Invalid q factor.');
}
$parse['q'] = (float) $q;
unset($parse['Q']);
$output[] = $parse;
}
usort(
$output,
static function (array $a, array $b) {
return $b['q'] <=> $a['q'];
}
);
return $output;
}
Explodes a header value to value and parameters (eg. text/html;q=2;version=6)
| public static string[] getValueAndParameters ( string $headerValue, boolean $lowerCaseValue = true, boolean $lowerCaseParameter = true, boolean $lowerCaseParameterValue = true ) | ||
| $headerValue | string |
Header value. |
| $lowerCaseValue | boolean |
Whether should cast header value to lowercase. |
| $lowerCaseParameter | boolean |
Whether should cast header parameter name to lowercase. |
| $lowerCaseParameterValue | boolean |
Whether should cast header parameter value to lowercase. |
| return | string[] |
First element is the value, and key-value are the parameters. |
|---|---|---|
public static function getValueAndParameters(
string $headerValue,
bool $lowerCaseValue = true,
bool $lowerCaseParameter = true,
bool $lowerCaseParameterValue = true
): array {
$headerValue = trim($headerValue);
if ($headerValue === '') {
return [];
}
$parts = explode(';', $headerValue, 2);
$output = [$lowerCaseValue ? strtolower($parts[0]) : $parts[0]];
if (count($parts) === 1) {
return $output;
}
/** @psalm-var array{0:string,1:string} $parts */
return $output + self::getParameters($parts[1], $lowerCaseParameter, $lowerCaseParameterValue);
}
Signup or Login in order to comment.