Skip to content

Commit b9cf8df

Browse files
committed
Upgrade to latest Symfony HttpFoundation tag. Closes #1865.
1 parent 92f602e commit b9cf8df

28 files changed

+1154
-219
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpFoundation;
13+
14+
/**
15+
* Represents an Accept-* header.
16+
*
17+
* An accept header is compound with a list of items,
18+
* sorted by descending quality.
19+
*
20+
* @author Jean-François Simon <contact@jfsimon.fr>
21+
*/
22+
class AcceptHeader
23+
{
24+
/**
25+
* @var AcceptHeaderItem[]
26+
*/
27+
private $items = array();
28+
29+
/**
30+
* @var bool
31+
*/
32+
private $sorted = true;
33+
34+
/**
35+
* Constructor.
36+
*
37+
* @param AcceptHeaderItem[] $items
38+
*/
39+
public function __construct(array $items)
40+
{
41+
foreach ($items as $item) {
42+
$this->add($item);
43+
}
44+
}
45+
46+
/**
47+
* Builds an AcceptHeader instance from a string.
48+
*
49+
* @param string $headerValue
50+
*
51+
* @return AcceptHeader
52+
*/
53+
public static function fromString($headerValue)
54+
{
55+
$index = 0;
56+
57+
return new self(array_map(function ($itemValue) use (&$index) {
58+
$item = AcceptHeaderItem::fromString($itemValue);
59+
$item->setIndex($index++);
60+
61+
return $item;
62+
}, preg_split('/\s*(?:,*("[^"]+"),*|,*(\'[^\']+\'),*|,+)\s*/', $headerValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)));
63+
}
64+
65+
/**
66+
* Returns header value's string representation.
67+
*
68+
* @return string
69+
*/
70+
public function __toString()
71+
{
72+
return implode(',', $this->items);
73+
}
74+
75+
/**
76+
* Tests if header has given value.
77+
*
78+
* @param string $value
79+
*
80+
* @return Boolean
81+
*/
82+
public function has($value)
83+
{
84+
return isset($this->items[$value]);
85+
}
86+
87+
/**
88+
* Returns given value's item, if exists.
89+
*
90+
* @param string $value
91+
*
92+
* @return AcceptHeaderItem|null
93+
*/
94+
public function get($value)
95+
{
96+
return isset($this->items[$value]) ? $this->items[$value] : null;
97+
}
98+
99+
/**
100+
* Adds an item.
101+
*
102+
* @param AcceptHeaderItem $item
103+
*
104+
* @return AcceptHeader
105+
*/
106+
public function add(AcceptHeaderItem $item)
107+
{
108+
$this->items[$item->getValue()] = $item;
109+
$this->sorted = false;
110+
111+
return $this;
112+
}
113+
114+
/**
115+
* Returns all items.
116+
*
117+
* @return AcceptHeaderItem[]
118+
*/
119+
public function all()
120+
{
121+
$this->sort();
122+
123+
return $this->items;
124+
}
125+
126+
/**
127+
* Filters items on their value using given regex.
128+
*
129+
* @param string $pattern
130+
*
131+
* @return AcceptHeader
132+
*/
133+
public function filter($pattern)
134+
{
135+
return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) {
136+
return preg_match($pattern, $item->getValue());
137+
}));
138+
}
139+
140+
/**
141+
* Returns first item.
142+
*
143+
* @return AcceptHeaderItem|null
144+
*/
145+
public function first()
146+
{
147+
$this->sort();
148+
149+
return !empty($this->items) ? reset($this->items) : null;
150+
}
151+
152+
/**
153+
* Sorts items by descending quality
154+
*/
155+
private function sort()
156+
{
157+
if (!$this->sorted) {
158+
uasort($this->items, function ($a, $b) {
159+
$qA = $a->getQuality();
160+
$qB = $b->getQuality();
161+
162+
if ($qA === $qB) {
163+
return $a->getIndex() > $b->getIndex() ? 1 : -1;
164+
}
165+
166+
return $qA > $qB ? -1 : 1;
167+
});
168+
169+
$this->sorted = true;
170+
}
171+
}
172+
}
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpFoundation;
13+
14+
/**
15+
* Represents an Accept-* header item.
16+
*
17+
* @author Jean-François Simon <contact@jfsimon.fr>
18+
*/
19+
class AcceptHeaderItem
20+
{
21+
/**
22+
* @var string
23+
*/
24+
private $value;
25+
26+
/**
27+
* @var float
28+
*/
29+
private $quality = 1.0;
30+
31+
/**
32+
* @var int
33+
*/
34+
private $index = 0;
35+
36+
/**
37+
* @var array
38+
*/
39+
private $attributes = array();
40+
41+
/**
42+
* Constructor.
43+
*
44+
* @param string $value
45+
* @param array $attributes
46+
*/
47+
public function __construct($value, array $attributes = array())
48+
{
49+
$this->value = $value;
50+
foreach ($attributes as $name => $value) {
51+
$this->setAttribute($name, $value);
52+
}
53+
}
54+
55+
/**
56+
* Builds an AcceptHeaderInstance instance from a string.
57+
*
58+
* @param string $itemValue
59+
*
60+
* @return AcceptHeaderItem
61+
*/
62+
public static function fromString($itemValue)
63+
{
64+
$bits = preg_split('/\s*(?:;*("[^"]+");*|;*(\'[^\']+\');*|;+)\s*/', $itemValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
65+
$value = array_shift($bits);
66+
$attributes = array();
67+
68+
$lastNullAttribute = null;
69+
foreach ($bits as $bit) {
70+
if (($start = substr($bit, 0, 1)) === ($end = substr($bit, -1)) && ($start === '"' || $start === '\'')) {
71+
$attributes[$lastNullAttribute] = substr($bit, 1, -1);
72+
} elseif ('=' === $end) {
73+
$lastNullAttribute = $bit = substr($bit, 0, -1);
74+
$attributes[$bit] = null;
75+
} else {
76+
$parts = explode('=', $bit);
77+
$attributes[$parts[0]] = isset($parts[1]) && strlen($parts[1]) > 0 ? $parts[1] : '';
78+
}
79+
}
80+
81+
return new self(($start = substr($value, 0, 1)) === ($end = substr($value, -1)) && ($start === '"' || $start === '\'') ? substr($value, 1, -1) : $value, $attributes);
82+
}
83+
84+
/**
85+
* Returns header value's string representation.
86+
*
87+
* @return string
88+
*/
89+
public function __toString()
90+
{
91+
$string = $this->value.($this->quality < 1 ? ';q='.$this->quality : '');
92+
if (count($this->attributes) > 0) {
93+
$string .= ';'.implode(';', array_map(function($name, $value) {
94+
return sprintf(preg_match('/[,;=]/', $value) ? '%s="%s"' : '%s=%s', $name, $value);
95+
}, array_keys($this->attributes), $this->attributes));
96+
}
97+
98+
return $string;
99+
}
100+
101+
/**
102+
* Set the item value.
103+
*
104+
* @param string $value
105+
*
106+
* @return AcceptHeaderItem
107+
*/
108+
public function setValue($value)
109+
{
110+
$this->value = $value;
111+
112+
return $this;
113+
}
114+
115+
/**
116+
* Returns the item value.
117+
*
118+
* @return string
119+
*/
120+
public function getValue()
121+
{
122+
return $this->value;
123+
}
124+
125+
/**
126+
* Set the item quality.
127+
*
128+
* @param float $quality
129+
*
130+
* @return AcceptHeaderItem
131+
*/
132+
public function setQuality($quality)
133+
{
134+
$this->quality = $quality;
135+
136+
return $this;
137+
}
138+
139+
/**
140+
* Returns the item quality.
141+
*
142+
* @return float
143+
*/
144+
public function getQuality()
145+
{
146+
return $this->quality;
147+
}
148+
149+
/**
150+
* Set the item index.
151+
*
152+
* @param int $index
153+
*
154+
* @return AcceptHeaderItem
155+
*/
156+
public function setIndex($index)
157+
{
158+
$this->index = $index;
159+
160+
return $this;
161+
}
162+
163+
/**
164+
* Returns the item index.
165+
*
166+
* @return int
167+
*/
168+
public function getIndex()
169+
{
170+
return $this->index;
171+
}
172+
173+
/**
174+
* Tests if an attribute exists.
175+
*
176+
* @param string $name
177+
*
178+
* @return Boolean
179+
*/
180+
public function hasAttribute($name)
181+
{
182+
return isset($this->attributes[$name]);
183+
}
184+
185+
/**
186+
* Returns an attribute by its name.
187+
*
188+
* @param string $name
189+
* @param mixed $default
190+
*
191+
* @return mixed
192+
*/
193+
public function getAttribute($name, $default = null)
194+
{
195+
return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
196+
}
197+
198+
/**
199+
* Returns all attributes.
200+
*
201+
* @return array
202+
*/
203+
public function getAttributes()
204+
{
205+
return $this->attributes;
206+
}
207+
208+
/**
209+
* Set an attribute.
210+
*
211+
* @param string $name
212+
* @param string $value
213+
*
214+
* @return AcceptHeaderItem
215+
*/
216+
public function setAttribute($name, $value)
217+
{
218+
if ('q' === $name) {
219+
$this->quality = (float) $value;
220+
} else {
221+
$this->attributes[$name] = (string) $value;
222+
}
223+
224+
return $this;
225+
}
226+
}

0 commit comments

Comments
 (0)