From 7777aea42c919ce59213f8d51df0dfc5189f6384 Mon Sep 17 00:00:00 2001 From: "Matthew J. Sahagian" Date: Fri, 14 Oct 2022 12:12:31 -0700 Subject: [PATCH 1/3] Adding per collection custom delimiter --- src/Dot.php | 27 +++++++++++++++++++++------ tests/DotTest.php | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/Dot.php b/src/Dot.php index 115c340..ab91de0 100644 --- a/src/Dot.php +++ b/src/Dot.php @@ -29,14 +29,25 @@ class Dot implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable */ protected $items = []; + + /** + * The delimiter (alternative to a '.') to be used. + * + * @var string + */ + protected $delimiter = '.'; + + /** * Create a new Dot instance * * @param mixed $items + * @param string $delimiter */ - public function __construct($items = []) + public function __construct($items = [], $delimiter = '.') { $this->items = $this->getArrayItems($items); + $this->delimiter = $delimiter; } /** @@ -104,7 +115,7 @@ public function delete($keys) } $items = &$this->items; - $segments = explode('.', $key); + $segments = explode($this->delimiter, $key); $lastSegment = array_pop($segments); foreach ($segments as $segment) { @@ -148,6 +159,10 @@ public function flatten($delimiter = '.', $items = null, $prepend = '') $items = $this->items; } + if (!func_num_args()) { + $delimiter = $this->delimiter; + } + foreach ($items as $key => $value) { if (is_array($value) && !empty($value)) { $flatten = array_merge( @@ -179,13 +194,13 @@ public function get($key = null, $default = null) return $this->items[$key]; } - if (strpos($key, '.') === false) { + if (strpos($key, $this->delimiter) === false) { return $default; } $items = $this->items; - foreach (explode('.', $key) as $segment) { + foreach (explode($this->delimiter, $key) as $segment) { if (!is_array($items) || !$this->exists($items, $segment)) { return $default; } @@ -234,7 +249,7 @@ public function has($keys) continue; } - foreach (explode('.', $key) as $segment) { + foreach (explode($this->delimiter, $key) as $segment) { if (!is_array($items) || !$this->exists($items, $segment)) { return false; } @@ -446,7 +461,7 @@ public function set($keys, $value = null) $items = &$this->items; - foreach (explode('.', $keys) as $key) { + foreach (explode($this->delimiter, $keys) as $key) { if (!isset($items[$key]) || !is_array($items[$key])) { $items[$key] = []; } diff --git a/tests/DotTest.php b/tests/DotTest.php index f506497..d5a5d6a 100644 --- a/tests/DotTest.php +++ b/tests/DotTest.php @@ -70,6 +70,14 @@ public function testAddKeyValuePair() $this->assertEquals('baz', $dot->get('foo.bar')); } + public function testAddKeyValuePairWithCustomDelimeter() + { + $dot = new Dot([], '/'); + $dot->add('foo/bar', 'baz'); + + $this->assertEquals('baz', $dot->get('foo/bar')); + } + public function testAddValueToExistingKey() { $dot = new Dot(['foo' => 'bar']); @@ -116,6 +124,14 @@ public function testClearKey() $this->assertSame([], $dot->get('foo.bar')); } + public function testClearKeyWithCustomDelimiter() + { + $dot = new Dot(['foo' => ['bar' => 'baz']], '/'); + $dot->clear('foo/bar'); + + $this->assertSame([], $dot->get('foo/bar')); + } + public function testClearNonExistingKey() { $dot = new Dot; @@ -154,6 +170,14 @@ public function testDeleteKey() $this->assertFalse($dot->has('foo.bar')); } + public function testDeleteKeyWithCustomDelimeter() + { + $dot = new Dot(['foo' => ['bar' => 'baz']], '/'); + $dot->delete('foo/bar'); + + $this->assertFalse($dot->has('foo/bar')); + } + public function testDeleteNonExistingKey() { $dot = new Dot(['foo' => 'bar']); @@ -182,15 +206,25 @@ public function testFlatten() $this->assertEquals('xyz', $flatten['foo.abc']); $this->assertEquals('baz', $flatten['foo.bar.0']); } - + public function testFlattenWithCustomDelimiter() { - $dot = new Dot(['foo' => ['abc' => 'xyz', 'bar' => ['baz']]]); + $dot = new Dot(['foo' => ['abc' => 'xyz', 'bar' => ['baz']]], '/'); + $flatten = $dot->flatten(); + $this->assertEquals('xyz', $flatten['foo/abc']); + $this->assertEquals('baz', $flatten['foo/bar/0']); + } + + + public function testFlattenWithDoubleCustomDelimiter() + { + $dot = new Dot(['foo' => ['abc' => 'xyz', 'bar' => ['baz']]], '/'); $flatten = $dot->flatten('_'); $this->assertEquals('xyz', $flatten['foo_abc']); $this->assertEquals('baz', $flatten['foo_bar_0']); } + /* * -------------------------------------------------------------- * Get @@ -532,6 +566,15 @@ public function testSetKeyValuePair() $this->assertEquals('baz', $dot->get('foo.bar')); } + public function testSetKeyValuePairWithCustomDelimiter() + { + $dot = new Dot([], '/'); + $dot->set('foo/bar', 'baz'); + + $this->assertEquals('baz', $dot->get('foo/bar')); + } + + public function testSetArrayOfKeyValuePairs() { $dot = new Dot; From 79daab3cf0cbde030ccd2f15409564cd349d27cc Mon Sep 17 00:00:00 2001 From: "Matthew J. Sahagian" Date: Fri, 14 Oct 2022 13:22:52 -0700 Subject: [PATCH 2/3] Adding delimiter for helper, documentation --- README.md | 9 +++++++++ src/helpers.php | 9 +++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d12ea34..6aed034 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,15 @@ $dot = dot(); $dot = dot($array); ``` +It is possible use an alternative delimiter from the default dot (`.`) with the second constructor parameter. Using an underscore instead: + +```php +$dot = new \Adbar\Dot($array, '_'); + +// With the helper +$dot = dot($array, '_'); +``` + ## Methods Dot has the following methods: diff --git a/src/helpers.php b/src/helpers.php index ffdc826..bebb952 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -11,13 +11,14 @@ if (! function_exists('dot')) { /** - * Create a new Dot object with the given items + * Create a new Dot object with the given items and optional delimiter * - * @param mixed $items + * @param mixed $items + * @param string $delimiter * @return \Adbar\Dot */ - function dot($items) + function dot($items, $delimiter = '.') { - return new Dot($items); + return new Dot($items, $delimiter); } } From c58b2fd4b19661e87a1cd93a7223c97357b74241 Mon Sep 17 00:00:00 2001 From: "Matthew J. Sahagian" Date: Fri, 14 Oct 2022 13:25:18 -0700 Subject: [PATCH 3/3] Prevent empty delimeter (treat empty string as default) --- src/Dot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Dot.php b/src/Dot.php index ab91de0..3cd1c50 100644 --- a/src/Dot.php +++ b/src/Dot.php @@ -47,7 +47,7 @@ class Dot implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable public function __construct($items = [], $delimiter = '.') { $this->items = $this->getArrayItems($items); - $this->delimiter = $delimiter; + $this->delimiter = strlen($delimiter) ? $delimiter : '.'; } /**