From b6df67afd0a4ea81dfd1c3a2eb5c818661c2f007 Mon Sep 17 00:00:00 2001 From: PJ Dietz Date: Sun, 22 Mar 2015 13:03:59 -0400 Subject: [PATCH] Add Iterator to HeaderCollection --- src/Message/HeaderCollection.php | 59 ++++++++++++++- .../unit/Message/HeaderCollectionTest.php | 71 +++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/src/Message/HeaderCollection.php b/src/Message/HeaderCollection.php index 6fefd38..6a58843 100644 --- a/src/Message/HeaderCollection.php +++ b/src/Message/HeaderCollection.php @@ -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; } } diff --git a/test/tests/unit/Message/HeaderCollectionTest.php b/test/tests/unit/Message/HeaderCollectionTest.php index f8899c9..8094558 100644 --- a/test/tests/unit/Message/HeaderCollectionTest.php +++ b/test/tests/unit/Message/HeaderCollectionTest.php @@ -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); + } }