From 32afd76465bf62a0701b9bfca5a0e9aa2a8c3479 Mon Sep 17 00:00:00 2001 From: Nathan Macnamara Date: Thu, 17 Jul 2014 14:25:59 +0100 Subject: [PATCH] Fix issue with dot notation in only/except functions --- src/Parser.php | 171 ++++++++++++++++++++-------------------- tests/ParserPHPTest.php | 7 +- 2 files changed, 91 insertions(+), 87 deletions(-) diff --git a/src/Parser.php b/src/Parser.php index 3781c0b..f693f0c 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -31,7 +31,14 @@ public function only($keys) { $keys = is_array($keys) ? $keys : func_get_args(); - return array_only($this->payload(), $keys) + array_fill_keys($keys, null); + $input = $this->payload(); + + $results = array(); + foreach ($keys as $key) { + $results = array_merge($results, $this->_buildArray(explode('.', $key), $this->get($key))); + } + + return $results; } public function except($keys) @@ -40,8 +47,9 @@ public function except($keys) $results = $this->payload(); - foreach ($keys as $key) array_forget($results, $key); - + foreach ($keys as $key) { + $this->_removeValue($results, $key); + } return $results; } @@ -53,7 +61,7 @@ public function has($key) foreach ($keys as $value) { - if ($this->hasValue($value, $results) === false) + if ($this->_hasValue($value, $results) === false) return false; } return true; @@ -64,63 +72,11 @@ public function get($key = null, $default = null) $results = $this->payload(); if ($this->has($key)) { - return $this->getValue($key, $results); + return $this->_getValue($key, $results); } return $default; } - private function getValue($key, $data) - { - return $this->_RecursiveGetValue(array_reverse(explode('.', $key)), $data); - } - - private function _RecursiveGetValue($route, $data) - { - $key = array_pop($route); - - if (!isset($data[$key])) - return false; - - if (count($route) <= 0) - { - if (is_bool($data[$key])) - return $data[$key]; - - if ($data[$key] === '') - return false; - - return $data[$key]; - } - - return $this->_RecursiveGetValue($route, $data[$key]); - } - - private function hasValue($key, $data) - { - return $this->_RecursiveHasValue(array_reverse(explode('.', $key)), $data); - } - - private function _RecursiveHasValue($route, $data) - { - $key = array_pop($route); - - if (!isset($data[$key])) - return false; - - if (count($route) <= 0) - { - if (is_bool($data[$key])) - return true; - - if ($data[$key] === '') - return false; - - return true; - } - - return $this->_RecursiveHasValue($route, $data[$key]); - } - /** * Alias to the payload function. * @@ -134,13 +90,8 @@ public function all() public function payload($format = false) { if ($format !== false) - { if (isset($this->supported_formats[$format])) - { return $this->{$this->supported_formats[$format]}($this->_payload()); - } - throw new ParserException('Invalid Or Unsupported Format'); - } return $this->{$this->_format()}($this->_payload()); } @@ -227,41 +178,87 @@ public function yaml($string) } return array(); } -} -class ParserException extends Exception {} + /** + * Return a value from the array identified from the key. + * + * @param $key + * @param $data + * @return mixed + */ + private function _getValue($key, $data) + { + $keys = explode('.', $key); + while (count($keys) > 1) + { + $key = array_shift($keys); + + if ( ! isset($data[$key]) || ! is_array($data[$key])) + { + return false; + } + + $data =& $data[$key]; + } + + return ($data[array_shift($keys)]); + } + + /** + * Array contains a value identified from the key, returns bool + * + * @param $key + * @param $data + * @return bool + */ + private function _hasValue($key, $data) + { + $keys = explode('.', $key); + + while (count($keys) > 0) + { + $key = array_shift($keys); + + if (!isset($data[$key])) + return false; + + if (is_bool($data[$key])) + return true; + + if ($data[$key] === '') + return false; + + $data =& $data[$key]; + } + return true; + } -/** - * Helper Functions - * - * http://laravel.com/api/4.2/Illuminate/Http/Request.html - */ -if ( ! function_exists('array_only')) -{ /** - * Get a subset of the items from the given array. + * Build the array structure for value. * - * @param array $array - * @param array $keys - * @return array + * @param $route + * @param null $data + * @return array|null */ - function array_only($array, $keys) + private function _buildArray($route, $data = null) { - return array_intersect_key($array, array_flip((array) $keys)); + $key = array_pop($route); + $data = array($key => $data); + if (count($route) == 0) + { + return $data; + } + return $this->_buildArray($route, $data); } -} -if ( ! function_exists('array_forget')) -{ /** - * Remove an array item from a given array using "dot" notation. + * Remove a value identified from the key * - * @param array $array - * @param string $key - * @return void + * @param $array + * @param $key */ - function array_forget(&$array, $key) + private function _removeValue(&$array, $key) { $keys = explode('.', $key); @@ -279,4 +276,6 @@ function array_forget(&$array, $key) unset($array[array_shift($keys)]); } -} \ No newline at end of file +} + +class ParserException extends Exception {} \ No newline at end of file diff --git a/tests/ParserPHPTest.php b/tests/ParserPHPTest.php index 844ba07..369be03 100644 --- a/tests/ParserPHPTest.php +++ b/tests/ParserPHPTest.php @@ -27,10 +27,15 @@ public function return_value_for_multi_level_key() ->method('_payload') ->will($this->returnValue('{"id": 123, "note": {"headers": {"to": "example@example.com", "from": "example@example.com"}, "body": "Hello World"}}')); - $this->assertEquals('123', $parser->get('id')); $this->assertEquals('Hello World', $parser->get('note.body')); $this->assertEquals('example@example.com', $parser->get('note.headers.to')); + $this->assertTrue($parser->has('note.headers.to')); + + $this->assertEquals(array('id' => 123, 'note' => array('headers' => array('from' => 'example@example.com'), 'body' => 'Hello World')), $parser->except('note.headers.to')); + $this->assertEquals(array('id' => 123, 'note' => array('headers' => array('to' => 'example@example.com', 'from' => 'example@example.com'))), $parser->except('note.body')); + + $this->assertEquals(array('id' => 123, 'status' => null, 'note' => array('body' => 'Hello World')), $parser->only('note.body', 'id', 'status')); } /** @test */