Skip to content

Commit 57a2a69

Browse files
committed
Made BaseArray class. Added OneOffArray.
1 parent 17f25c5 commit 57a2a69

File tree

6 files changed

+181
-28
lines changed

6 files changed

+181
-28
lines changed

README.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Table of Contents
1111
- [4. offsetUnset](#composite-key-array-offset-unset)
1212
* [XPath Key Array](#xpath-key-array)
1313
* [Dotted Key Array](#dotted-key-array)
14+
* [One-off Array](#one-off-array)
1415

1516
<a name="composite-key-array"></a>
1617

@@ -176,4 +177,13 @@ Compared to `CompositeKeyArray`, `XPathKeyArray` has some limitations:
176177
Compared to `CompositeKeyArray`, `DottedKeyArray` has some limitations:
177178

178179
1. You cannot use keys with `.` in them.
179-
2. You cannot use `null` as key.
180+
2. You cannot use `null` as key.
181+
182+
<a name="one-off-array"></a>
183+
184+
## One-off Array
185+
186+
Sometimes you want to get value from an array by key and `unset` this key after that. The `OneOffArray` class helps you with this.
187+
188+
Again this class can be used in combination with `CompositeKeyArray` or its descendents: `XPathKeyArray` or `DottedKeyArray`.
189+
Actually, it can be used in combination with any object that implemets `ArrayAccess`.

src/BaseArray.php

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
namespace Sevavietl\Arrays;
4+
5+
class BaseArray implements \ArrayAccess
6+
{
7+
protected $container;
8+
protected $undefinedOffsetAction;
9+
10+
public function __construct($array = [])
11+
{
12+
$this->container = $array;
13+
14+
$this->validateContainerArrayOrArrayAccessObject();
15+
16+
$this->setUndefinedOffsetAction(function ($array, $offset) {
17+
$offset = json_encode($offset);
18+
19+
throw new UndefinedOffsetException(
20+
"Undefined offset $offset."
21+
);
22+
});
23+
}
24+
25+
protected function validateContainerArrayOrArrayAccessObject()
26+
{
27+
if (is_array($this->container)) {
28+
return;
29+
}
30+
31+
if (
32+
is_object($this->container)
33+
&& $this->container instanceof \ArrayAccess
34+
) {
35+
return;
36+
}
37+
38+
throw new \InvalidArgumentException;
39+
}
40+
41+
public function setUndefinedOffsetAction(callable $callback)
42+
{
43+
$this->undefinedOffsetAction = $callback;
44+
45+
return $this;
46+
}
47+
48+
public function offsetExists($offset) {
49+
return isset($this->container[$offset]);
50+
}
51+
52+
public function offsetGet($offset) {
53+
if (isset($this->container[$offset])) {
54+
return $this->container[$offset];
55+
}
56+
57+
return $this->undefinedOffsetAction($this->container, $offset);
58+
}
59+
60+
public function offsetSet($offset, $value) {
61+
if (is_null($offset)) {
62+
$this->container[] = $value;
63+
} else {
64+
$this->container[$offset] = $value;
65+
}
66+
}
67+
68+
public function offsetUnset($offset) {
69+
unset($this->container[$offset]);
70+
}
71+
}

src/CompositeKeyArray.php

+7-27
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,14 @@
22

33
namespace Sevavietl\Arrays;
44

5-
class CompositeKeyArray implements \ArrayAccess
5+
class CompositeKeyArray extends BaseArray
66
{
7-
protected $array;
7+
protected $container;
88
protected $undefinedOffsetAction;
99

10-
public function __construct(array $array = [])
11-
{
12-
$this->array = $array;
13-
14-
$this->undefinedOffsetAction = function ($array, $offset) {
15-
$offset = json_encode($offset);
16-
17-
throw new UndefinedOffsetException(
18-
"Undefined offset $offset."
19-
);
20-
};
21-
}
22-
23-
public function setUndefinedOffsetAction(Callable $undefinedOffsetAction)
24-
{
25-
$this->undefinedOffsetAction = $undefinedOffsetAction;
26-
27-
return $this;
28-
}
29-
3010
public function toArray()
3111
{
32-
return $this->array;
12+
return $this->container;
3313
}
3414

3515
protected $offsets;
@@ -39,7 +19,7 @@ public function offsetExists($offset)
3919
$this->setOffsets($offset);
4020

4121
return $this->walkThroughOffsets(
42-
$this->array,
22+
$this->container,
4323
function ($array, $offset) {
4424
return isset($array[$offset]);
4525
},
@@ -54,7 +34,7 @@ public function offsetGet($offset)
5434
$this->setOffsets($offset);
5535

5636
return $this->walkThroughOffsets(
57-
$this->array,
37+
$this->container,
5838
function ($array, $offset) {
5939
return $array[$offset];
6040
},
@@ -96,7 +76,7 @@ public function offsetSet($offset, $value)
9676
};
9777

9878
return $this->walkThroughOffsets(
99-
$this->array,
79+
$this->container,
10080
$baseCaseAction,
10181
$offsetNotExistsAction
10282
);
@@ -107,7 +87,7 @@ public function offsetUnset($offset)
10787
$this->setOffsets($offset);
10888

10989
return $this->walkThroughOffsets(
110-
$this->array,
90+
$this->container,
11191
function (&$array, $offset) {
11292
unset($array[$offset]);
11393
},

src/OneOffArray.php

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Sevavietl\Arrays;
4+
5+
class OneOffArray extends BaseArray
6+
{
7+
public function offsetGet($offset)
8+
{
9+
$value = $this->container[$offset];
10+
unset($this->container[$offset]);
11+
12+
return $value;
13+
}
14+
}

tests/unit/BaseArrayTest.php

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Sevavietl\Arrays\Tests\Unit;
4+
5+
use Sevavietl\Arrays\BaseArray;
6+
7+
class BaseArrayTest extends \TestCase
8+
{
9+
/**
10+
* @dataProvider instantiationDataProvider
11+
*/
12+
public function testInstantiation($argument)
13+
{
14+
new BaseArray($argument);
15+
}
16+
17+
public function instantiationDataProvider()
18+
{
19+
return [
20+
[[1, 2, 3]],
21+
[new \ArrayObject],
22+
];
23+
}
24+
25+
/**
26+
* @dataProvider instantiationThrowsExceptionDataProvider
27+
*
28+
* @expectedException InvalidArgumentException
29+
*/
30+
public function testInstantiationThrowsException($argument)
31+
{
32+
new BaseArray($argument);
33+
}
34+
35+
public function instantiationThrowsExceptionDataProvider()
36+
{
37+
return [
38+
[1],
39+
['foo'],
40+
[new \StdClass],
41+
];
42+
}
43+
}

tests/unit/OneOffArrayTest.php

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Sevavietl\Arrays\Tests\Unit;
4+
5+
use Sevavietl\Arrays\OneOffArray;
6+
use Sevavietl\Arrays\CompositeKeyArray;
7+
8+
class OneOffArrayTest extends \TestCase
9+
{
10+
/**
11+
* @dataProvider arrayDataProviderForGetTesting
12+
*/
13+
public function testOffsetGet($array, $offset, $value)
14+
{
15+
$array = new OneOffArray($array);
16+
17+
$this->assertEquals(
18+
$value,
19+
$array[$offset]
20+
);
21+
22+
$this->assertFalse(isset($array[$offset]));
23+
}
24+
25+
public function arrayDataProviderForGetTesting()
26+
{
27+
return [
28+
[[1], 0, 1],
29+
[new CompositeKeyArray([1 => [2 => 3]]), ['1', '2'], 3],
30+
31+
[['foo' => 'bar'], 'foo', 'bar'],
32+
[new CompositeKeyArray(['foo' => ['bar' => 'baz']]), ['foo', 'bar'], 'baz'],
33+
];
34+
}
35+
}

0 commit comments

Comments
 (0)