-
Notifications
You must be signed in to change notification settings - Fork 2
/
ContentTypeNegotiation.php
135 lines (120 loc) · 4.29 KB
/
ContentTypeNegotiation.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php
declare(strict_types=1);
namespace Cake\Http;
use Psr\Http\Message\RequestInterface;
/**
* Negotiates the prefered content type from what the application
* provides and what the request has in its Accept header.
*/
class ContentTypeNegotiation
{
/**
* Parse Accept* headers with qualifier options.
*
* Only qualifiers will be extracted, any other accept extensions will be
* discarded as they are not frequently used.
*
* @param \Psr\Http\Message\RequestInterface $request The request to get an accept from.
* @return array<string, array<string>> A mapping of preference values => content types
*/
public function parseAccept(RequestInterface $request): array
{
$header = $request->getHeaderLine('Accept');
return $this->parseQualifiers($header);
}
/**
* Parse the Accept-Language header
*
* Only qualifiers will be extracted, other extensions will be ignored
* as they are not frequently used.
*
* @param \Psr\Http\Message\RequestInterface $request The request to get an accept from.
* @return array<string, array<string>> A mapping of preference values => languages
*/
public function parseAcceptLanguage(RequestInterface $request): array
{
$header = $request->getHeaderLine('Accept-Language');
return $this->parseQualifiers($header);
}
/**
* Parse a header value into preference => value mapping
*
* @param string $header The header value to parse
* @return array<string, array<string>>
*/
protected function parseQualifiers(string $header): array
{
return HeaderUtility::parseAccept($header);
}
/**
* Get the most preferred content type from a request.
*
* Parse the Accept header preferences and return the most
* preferred type. If multiple types are tied in preference
* the first type of that preference value will be returned.
*
* You can expect null when the request has no Accept header.
*
* @param \Psr\Http\Message\RequestInterface $request The request to use.
* @param array<string> $choices The supported content type choices.
* @return string|null The prefered type or null if there is no match with choices or if the
* request had no Accept header.
*/
public function preferredType(RequestInterface $request, array $choices = []): ?string
{
$parsed = $this->parseAccept($request);
if (empty($parsed)) {
return null;
}
if (empty($choices)) {
$preferred = array_shift($parsed);
return $preferred[0];
}
foreach ($parsed as $acceptTypes) {
$common = array_intersect($acceptTypes, $choices);
if ($common) {
return array_shift($common);
}
}
return null;
}
/**
* Get the normalized list of accepted languages
*
* Language codes in the request will be normalized to lower case and have
* `_` replaced with `-`.
*
* @param \Psr\Http\Message\RequestInterface $request The request to read headers from.
* @return array<string> A list of language codes that are accepted.
*/
public function acceptedLanguages(RequestInterface $request): array
{
$raw = $this->parseAcceptLanguage($request);
$accept = [];
foreach ($raw as $languages) {
foreach ($languages as &$lang) {
if (strpos($lang, '_')) {
$lang = str_replace('_', '-', $lang);
}
$lang = strtolower($lang);
}
$accept = array_merge($accept, $languages);
}
return $accept;
}
/**
* Check if the request accepts a given language code.
*
* Language codes in the request will be normalized to lower case and have `_` replaced
* with `-`.
*
* @param \Psr\Http\Message\RequestInterface $request The request to read headers from.
* @param string $lang The language code to check.
* @return bool Whether the request accepts $lang
*/
public function acceptLanguage(RequestInterface $request, string $lang): bool
{
$accept = $this->acceptedLanguages($request);
return in_array(strtolower($lang), $accept, true);
}
}