Skip to content

Commit a3314cd

Browse files
authored
Merge pull request #28 from colinodell/cleanup
Minor cleanup
2 parents 7c13ae1 + a7437fb commit a3314cd

File tree

8 files changed

+93
-59
lines changed

8 files changed

+93
-59
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ isset($data['name']) === $data->has('name');
121121
unset($data['name']);
122122
```
123123

124+
`/` can also be used as a path delimiter:
125+
126+
```php
127+
$data->set('a/b/c', 'd');
128+
echo $data->get('a/b/c'); // "d"
129+
130+
$data->get('a/b/c') === $data->get('a.b.c'); // true
131+
```
132+
124133
License
125134
-------
126135

src/Data.php

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
/*
46
* This file is a part of dflydev/dot-access-data.
57
*
@@ -45,25 +47,10 @@ public function __construct(array $data = [])
4547
public function append(string $key, $value = null): void
4648
{
4749
$currentValue =& $this->data;
48-
$keyPath = $this->keyToPathArray($key);
49-
50-
if (1 == count($keyPath)) {
51-
if (!isset($currentValue[$key])) {
52-
$currentValue[$key] = [];
53-
}
54-
if (!is_array($currentValue[$key])) {
55-
// Promote this key to an array.
56-
// TODO: Is this really what we want to do?
57-
$currentValue[$key] = [$currentValue[$key]];
58-
}
59-
$currentValue[$key][] = $value;
60-
61-
return;
62-
}
50+
$keyPath = self::keyToPathArray($key);
6351

6452
$endKey = array_pop($keyPath);
65-
for ($i = 0; $i < count($keyPath); $i++) {
66-
$currentKey =& $keyPath[$i];
53+
foreach ($keyPath as $currentKey) {
6754
if (! isset($currentValue[$currentKey])) {
6855
$currentValue[$currentKey] = [];
6956
}
@@ -73,11 +60,13 @@ public function append(string $key, $value = null): void
7360
if (!isset($currentValue[$endKey])) {
7461
$currentValue[$endKey] = [];
7562
}
63+
7664
if (!is_array($currentValue[$endKey])) {
65+
// Promote this key to an array.
66+
// TODO: Is this really what we want to do?
7767
$currentValue[$endKey] = [$currentValue[$endKey]];
7868
}
79-
// Promote this key to an array.
80-
// TODO: Is this really what we want to do?
69+
8170
$currentValue[$endKey][] = $value;
8271
}
8372

@@ -87,22 +76,15 @@ public function append(string $key, $value = null): void
8776
public function set(string $key, $value = null): void
8877
{
8978
$currentValue =& $this->data;
90-
$keyPath = $this->keyToPathArray($key);
91-
92-
if (1 == count($keyPath)) {
93-
$currentValue[$key] = $value;
94-
95-
return;
96-
}
79+
$keyPath = self::keyToPathArray($key);
9780

9881
$endKey = array_pop($keyPath);
99-
for ($i = 0; $i < count($keyPath); $i++) {
100-
$currentKey =& $keyPath[$i];
82+
foreach ($keyPath as $currentKey) {
10183
if (!isset($currentValue[$currentKey])) {
10284
$currentValue[$currentKey] = [];
10385
}
10486
if (!is_array($currentValue[$currentKey])) {
105-
throw new DataException("Key path at $currentKey of $key cannot be indexed into (is not an array)");
87+
throw new DataException(sprintf('Key path "%s" within "%s" cannot be indexed into (is not an array)', $currentKey, self::formatPath($key)));
10688
}
10789
$currentValue =& $currentValue[$currentKey];
10890
}
@@ -115,17 +97,10 @@ public function set(string $key, $value = null): void
11597
public function remove(string $key): void
11698
{
11799
$currentValue =& $this->data;
118-
$keyPath = $this->keyToPathArray($key);
119-
120-
if (1 == count($keyPath)) {
121-
unset($currentValue[$key]);
122-
123-
return;
124-
}
100+
$keyPath = self::keyToPathArray($key);
125101

126102
$endKey = array_pop($keyPath);
127-
for ($i = 0; $i < count($keyPath); $i++) {
128-
$currentKey =& $keyPath[$i];
103+
foreach ($keyPath as $currentKey) {
129104
if (!isset($currentValue[$currentKey])) {
130105
return;
131106
}
@@ -142,10 +117,9 @@ public function remove(string $key): void
142117
public function get(string $key, $default = null)
143118
{
144119
$currentValue = $this->data;
145-
$keyPath = $this->keyToPathArray($key);
120+
$keyPath = self::keyToPathArray($key);
146121

147-
for ($i = 0; $i < count($keyPath); $i++) {
148-
$currentKey = $keyPath[$i];
122+
foreach ($keyPath as $currentKey) {
149123
if (!isset($currentValue[$currentKey])) {
150124
return $default;
151125
}
@@ -166,10 +140,8 @@ public function get(string $key, $default = null)
166140
public function has(string $key): bool
167141
{
168142
$currentValue = &$this->data;
169-
$keyPath = $this->keyToPathArray($key);
170143

171-
for ($i = 0; $i < count($keyPath); $i++) {
172-
$currentKey = $keyPath[$i];
144+
foreach (self::keyToPathArray($key) as $currentKey) {
173145
if (
174146
!is_array($currentValue) ||
175147
!array_key_exists($currentKey, $currentValue)
@@ -194,7 +166,7 @@ public function getData(string $key): DataInterface
194166
return new Data($value);
195167
}
196168

197-
throw new DataException("Value at '$key' could not be represented as a DataInterface");
169+
throw new DataException(sprintf('Value at "%s" could not be represented as a DataInterface', self::formatPath($key)));
198170
}
199171

200172
/**
@@ -258,13 +230,15 @@ public function offsetUnset($key)
258230
}
259231

260232
/**
233+
* @param string $path
234+
*
261235
* @return string[]
262236
*
263237
* @psalm-return non-empty-list<string>
264238
*
265239
* @psalm-pure
266240
*/
267-
protected function keyToPathArray(string $path): array
241+
protected static function keyToPathArray(string $path): array
268242
{
269243
if (\strlen($path) === 0) {
270244
throw new InvalidPathException('Path cannot be an empty string');
@@ -274,4 +248,20 @@ protected function keyToPathArray(string $path): array
274248

275249
return \explode('.', $path);
276250
}
251+
252+
/**
253+
* @param string|string[] $path
254+
*
255+
* @return string
256+
*
257+
* @psalm-pure
258+
*/
259+
protected static function formatPath($path): string
260+
{
261+
if (is_string($path)) {
262+
$path = self::keyToPathArray($path);
263+
}
264+
265+
return implode(' » ', $path);
266+
}
277267
}

src/DataInterface.php

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
/*
46
* This file is a part of dflydev/dot-access-data.
57
*
@@ -19,41 +21,52 @@ interface DataInterface
1921
/**
2022
* Append a value to a key (assumes key refers to an array value)
2123
*
24+
* If the key does not yet exist it will be created.
25+
* If the key references a non-array it's existing contents will be added into a new array before appending the new value.
26+
*
2227
* @param string $key
2328
* @param mixed $value
2429
*
25-
* @throws InvalidPathException if the given path is empty
30+
* @throws InvalidPathException if the given key is empty
2631
*/
2732
public function append(string $key, $value = null): void;
2833

2934
/**
3035
* Set a value for a key
3136
*
37+
* If the key does not yet exist it will be created.
38+
*
3239
* @param string $key
3340
* @param mixed $value
3441
*
35-
* @throws InvalidPathException if the given path is empty
36-
* @throws DataException if the given path does not target an array
42+
* @throws InvalidPathException if the given key is empty
43+
* @throws DataException if the given key does not target an array
3744
*/
3845
public function set(string $key, $value = null): void;
3946

4047
/**
4148
* Remove a key
4249
*
50+
* No exception will be thrown if the key does not exist
51+
*
4352
* @param string $key
4453
*
45-
* @throws InvalidPathException if the given path is empty
54+
* @throws InvalidPathException if the given key is empty
4655
*/
4756
public function remove(string $key): void;
4857

4958
/**
5059
* Get the raw value for a key
5160
*
61+
* If the key does not exist, the provided default value (or null) will be returned instead.
62+
*
5263
* @param string $key
5364
* @param mixed $default
5465
*
5566
* @return mixed
5667
*
68+
* @throws InvalidPathException if the given key is empty
69+
*
5770
* @psalm-mutation-free
5871
*/
5972
public function get(string $key, $default = null);
@@ -65,6 +78,8 @@ public function get(string $key, $default = null);
6578
*
6679
* @return bool
6780
*
81+
* @throws InvalidPathException if the given key is empty
82+
*
6883
* @psalm-mutation-free
6984
*/
7085
public function has(string $key): bool;
@@ -76,7 +91,8 @@ public function has(string $key): bool;
7691
*
7792
* @return DataInterface
7893
*
79-
* @throws DataException if the given path does not reference an array
94+
* @throws InvalidPathException if the given key is empty
95+
* @throws DataException if the given key does not reference an array
8096
*
8197
* @psalm-mutation-free
8298
*/

src/Exception/DataException.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
/*
46
* This file is a part of dflydev/dot-access-data.
57
*

src/Exception/InvalidPathException.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
/*
46
* This file is a part of dflydev/dot-access-data.
57
*

src/Util.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
/*
46
* This file is a part of dflydev/dot-access-data.
57
*

tests/DataTest.php

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
/*
46
* This file is a part of dflydev/dot-access-data.
57
*
@@ -63,6 +65,7 @@ protected function runSampleDataTests(DataInterface $data)
6365
$this->assertEquals($data->get('f/g/h/i', 'default-value-2'), 'default-value-2');
6466

6567
$this->expectException(InvalidPathException::class);
68+
$this->expectExceptionMessage('Path cannot be an empty string');
6669
$data->get('', 'broken');
6770
}
6871

@@ -91,7 +94,7 @@ public function testAppend()
9194
$this->assertEquals(['L'], $data->get('i.k.l'));
9295

9396
$this->expectException(InvalidPathException::class);
94-
97+
$this->expectExceptionMessage('Path cannot be an empty string');
9598
$data->append('', 'broken');
9699
}
97100

@@ -114,7 +117,7 @@ public function testSet()
114117
$this->assertEquals(['e' => ['f' => 'F', 'g' => 'G']], $data->get('d'));
115118

116119
$this->expectException(InvalidPathException::class);
117-
120+
$this->expectExceptionMessage('Path cannot be an empty string');
118121
$data->set('', 'broken');
119122
}
120123

@@ -125,7 +128,7 @@ public function testSetClobberStringInPath()
125128
$data->set('a.b.c', 'Should not be able to write to a.b.c.d.e');
126129

127130
$this->expectException(DataException::class);
128-
131+
$this->expectExceptionMessage('Key path "c" within "a » b » c » d » e" cannot be indexed into (is not an array)');
129132
$data->set('a.b.c.d.e', 'broken');
130133
}
131134

@@ -147,7 +150,7 @@ public function testRemove()
147150
$this->assertEquals('D2', $data->get('b.d.d2'));
148151

149152
$this->expectException(InvalidPathException::class);
150-
153+
$this->expectExceptionMessage('Path cannot be an empty string');
151154
$data->remove('', 'broken');
152155
}
153156

@@ -175,6 +178,7 @@ public function testHas()
175178
}
176179

177180
$this->expectException(InvalidPathException::class);
181+
$this->expectExceptionMessage('Path cannot be an empty string');
178182
$data->has('', 'broken');
179183
}
180184

@@ -189,10 +193,17 @@ public function testGetData()
189193
$data = $wrappedData->getData('wrapped.sampleData');
190194

191195
$this->runSampleDataTests($data);
196+
}
192197

193-
$this->expectException(DataException::class);
198+
public function testGetDataOnNonArrayValue()
199+
{
200+
$data = new Data([
201+
'foo' => 'bar',
202+
]);
194203

195-
$data = $wrappedData->getData('wrapped.sampleData.a');
204+
$this->expectException(DataException::class);
205+
$this->expectExceptionMessage('Value at "foo" could not be represented as a DataInterface');
206+
$data->getData('foo');
196207
}
197208

198209
public function testImport()
@@ -277,7 +288,7 @@ public function testOffsetSet()
277288
$this->assertEquals(['e' => ['f' => 'F', 'g' => 'G']], $data['d']);
278289

279290
$this->expectException(InvalidPathException::class);
280-
291+
$this->expectExceptionMessage('Path cannot be an empty string');
281292
$data->set('', 'broken');
282293
}
283294

@@ -299,7 +310,7 @@ public function testOffsetUnset()
299310
$this->assertEquals('D2', $data['b.d.d2']);
300311

301312
$this->expectException(InvalidPathException::class);
302-
313+
$this->expectExceptionMessage('Path cannot be an empty string');
303314
unset($data['']);
304315
}
305316
}

tests/UtilTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
/*
46
* This file is a part of dflydev/dot-access-data.
57
*

0 commit comments

Comments
 (0)