Add Iterator to HeaderCollection

This commit is contained in:
PJ Dietz 2015-03-22 13:03:59 -04:00
parent 2575bc743e
commit b6df67afd0
2 changed files with 129 additions and 1 deletions

View File

@ -2,7 +2,10 @@
namespace WellRESTed\Message;
class HeaderCollection implements \ArrayAccess
use ArrayAccess;
use Iterator;
class HeaderCollection implements ArrayAccess, Iterator
{
/**
* @var array
@ -18,12 +21,25 @@ class HeaderCollection implements \ArrayAccess
*/
private $values;
/**
* @var string[]
*
* List arrary of lowercase header names.
*/
private $keys;
/** @var int */
private $position = 0;
public function __construct()
{
$this->keys = [];
$this->fields = [];
$this->values = [];
}
// ArrayAccess -----------------------------------------------------------------------------------------------------
/**
* @param string $offset
* @return bool
@ -49,7 +65,16 @@ class HeaderCollection implements \ArrayAccess
public function offsetSet($offset, $value)
{
$normalized = strtolower($offset);
// Add the normalized key to the list of keys, if not already set.
if (!in_array($normalized, $this->keys)) {
$this->keys[] = $normalized;
}
// Add or update the preserved case key.
$this->fields[$normalized] = $offset;
// Store the value.
if (isset($this->values[$normalized])) {
$this->values[$normalized][] = $value;
} else {
@ -65,5 +90,37 @@ class HeaderCollection implements \ArrayAccess
$normalized = strtolower($offset);
unset($this->fields[$normalized]);
unset($this->values[$normalized]);
// Remove and renormalize the list of keys.
if (($key = array_search($normalized, $this->keys)) !== false) {
unset($this->keys[$key]);
$this->keys = array_values($this->keys);
}
}
// Iterator --------------------------------------------------------------------------------------------------------
public function current()
{
return $this->values[$this->keys[$this->position]];
}
public function next()
{
++$this->position;
}
public function key()
{
return $this->fields[$this->keys[$this->position]];
}
public function valid()
{
return isset($this->keys[$this->position]);
}
public function rewind()
{
$this->position = 0;
}
}

View File

@ -88,4 +88,75 @@ class HeaderCollectionTest extends \PHPUnit_Framework_TestCase
$this->assertTrue(isset($collection["set-cookie"]));
$this->assertFalse(isset($clone["set-cookie"]));
}
/**
* @covers WellRESTed\Message\HeaderCollection::current
* @covers WellRESTed\Message\HeaderCollection::next
* @covers WellRESTed\Message\HeaderCollection::key
* @covers WellRESTed\Message\HeaderCollection::valid
* @covers WellRESTed\Message\HeaderCollection::rewind
* @uses WellRESTed\Message\HeaderCollection::__construct
* @uses WellRESTed\Message\HeaderCollection::offsetSet
* @uses WellRESTed\Message\HeaderCollection::offsetExists
* @uses WellRESTed\Message\HeaderCollection::offsetUnset
*/
public function testIteratesWithOriginalKeys()
{
$collection = new HeaderCollection();
$collection["Content-length"] = "100";
$collection["Set-Cookie"] = "cat=Molly";
$collection["Set-Cookie"] = "dog=Bear";
$collection["Content-type"] = "application/json";
unset($collection["Content-length"]);
$headers = [];
foreach ($collection as $key => $values) {
$headers[] = $key;
}
$expected = ["Content-type", "Set-Cookie"];
$this->assertEquals(0, count(array_diff($expected, $headers)));
$this->assertEquals(0, count(array_diff($headers, $expected)));
}
/**
* @covers WellRESTed\Message\HeaderCollection::current
* @covers WellRESTed\Message\HeaderCollection::next
* @covers WellRESTed\Message\HeaderCollection::key
* @covers WellRESTed\Message\HeaderCollection::valid
* @covers WellRESTed\Message\HeaderCollection::rewind
* @uses WellRESTed\Message\HeaderCollection::__construct
* @uses WellRESTed\Message\HeaderCollection::offsetSet
* @uses WellRESTed\Message\HeaderCollection::offsetExists
* @uses WellRESTed\Message\HeaderCollection::offsetUnset
*/
public function testIteratesWithOriginalKeysAndValues()
{
$collection = new HeaderCollection();
$collection["Content-length"] = "100";
$collection["Set-Cookie"] = "cat=Molly";
$collection["Set-Cookie"] = "dog=Bear";
$collection["Content-type"] = "application/json";
unset($collection["Content-length"]);
$headers = [];
foreach ($collection as $key => $values) {
foreach ($values as $value) {
if (isset($headers[$key])) {
$headers[$key][] = $value;
} else {
$headers[$key] = [$value];
}
}
}
$expected = [
"Set-Cookie" => ["cat=Molly", "dog=Bear"],
"Content-type" => ["application/json"]
];
$this->assertEquals($expected, $headers);
}
}