Skip to content

Commit 53e0dc0

Browse files
committed
Initial commit
0 parents  commit 53e0dc0

7 files changed

Lines changed: 653 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor/
2+
composer.lock
3+
phpunit.xml

ArrayFinder.php

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
<?php
2+
3+
namespace Shudrum\Component\ArrayFinder;
4+
5+
class ArrayFinder implements
6+
\ArrayAccess,
7+
\Countable,
8+
\Iterator,
9+
\Serializable
10+
{
11+
private $content = [];
12+
private $position = 0;
13+
private $pathSeparator = '.';
14+
15+
/**
16+
* ArrayFinder constructor.
17+
*
18+
* @param array $content Content of the array
19+
*/
20+
public function __construct(array $content = [])
21+
{
22+
$this->content = $content;
23+
}
24+
25+
/**
26+
* {@inheritdoc}
27+
*/
28+
public function offsetExists($offset)
29+
{
30+
return isset($this->content[$offset]);
31+
}
32+
33+
/**
34+
* {@inheritdoc}
35+
*/
36+
public function offsetGet($offset)
37+
{
38+
return $this->get($offset);
39+
}
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
public function offsetSet($offset, $value)
45+
{
46+
if (is_null($offset)) {
47+
$this->content[] = $value;
48+
} else {
49+
$this->content[$offset] = $value;
50+
}
51+
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
public function offsetUnset($offset)
57+
{
58+
$path = explode($this->pathSeparator, $offset);
59+
$pathToUnset = array_pop($path);
60+
61+
$this->callAtPath(implode($this->pathSeparator, $path), function(&$offset) use (&$pathToUnset) {
62+
unset($offset[$pathToUnset]);
63+
});
64+
}
65+
66+
/**
67+
* {@inheritdoc}
68+
*/
69+
public function count()
70+
{
71+
return count($this->content);
72+
}
73+
74+
/**
75+
* {@inheritdoc}
76+
*/
77+
public function current()
78+
{
79+
$keys = array_keys($this->content);
80+
return $this->content[$keys[$this->position]];
81+
}
82+
83+
/**
84+
* {@inheritdoc}
85+
*/
86+
public function next()
87+
{
88+
++$this->position;
89+
}
90+
91+
/**
92+
* {@inheritdoc}
93+
*/
94+
public function key()
95+
{
96+
$keys = array_keys($this->content);
97+
return $keys[$this->position];
98+
}
99+
100+
/**
101+
* {@inheritdoc}
102+
*/
103+
public function valid()
104+
{
105+
$keys = array_keys($this->content);
106+
return isset($keys[$this->position]);
107+
}
108+
109+
/**
110+
* {@inheritdoc}
111+
*/
112+
public function rewind()
113+
{
114+
$this->position = 0;
115+
}
116+
117+
/**
118+
* {@inheritdoc}
119+
*/
120+
public function serialize() {
121+
return serialize($this->content);
122+
}
123+
124+
/**
125+
* {@inheritdoc}
126+
*/
127+
public function unserialize($content) {
128+
$this->content = unserialize($content);
129+
}
130+
131+
/**
132+
* Change the path separator of the array wrapper.
133+
*
134+
* By default, the separator is: .
135+
*
136+
* @param string $separator Separator to set.
137+
*
138+
* @return ArrayFinder Current instance.
139+
*/
140+
public function changeSeparator($separator)
141+
{
142+
$this->pathSeparator = $separator;
143+
return $this;
144+
}
145+
146+
/**
147+
* Return a value from the array corresponding to the path.
148+
*
149+
* ex:
150+
* $a = ['a' => ['b' => 'yeah']];
151+
* echo $this->get('a.b'); // yeah
152+
*
153+
* @param string|int|null $path Path to the value. If null, return all the content.
154+
*
155+
* @return mixed|null Value on the array corresponding to the path, null if the key does not exist.
156+
*/
157+
public function get($path = null)
158+
{
159+
if ($path === null) {
160+
return $this->content;
161+
}
162+
163+
$value = null;
164+
$this->callAtPath($path, function(&$offset) use (&$value) {
165+
$value = $offset;
166+
});
167+
168+
return $value;
169+
}
170+
171+
/**
172+
* Insert a value to the array at the specified path.
173+
*
174+
* ex:
175+
* $this->set('a.b', 'yeah); // ['a' => ['b' => 'yeah']]
176+
*
177+
* @param string $path Path where the values will be insered.
178+
* @param mixed $value Value ti insert.
179+
*
180+
* @return ArrayFinder Current instance.
181+
*/
182+
public function set($path, $value)
183+
{
184+
$this->callAtPath($path, function(&$offset) use ($value) {
185+
$offset = $value;
186+
}, true);
187+
188+
return $this;
189+
}
190+
191+
private function callAtPath($path, callable $callback, $createPath = false, &$currentOffset = null)
192+
{
193+
if ($currentOffset === null) {
194+
$currentOffset = &$this->content;
195+
196+
if (is_string($path) && $path == '') {
197+
$callback($currentOffset);
198+
return;
199+
}
200+
}
201+
202+
$explodedPath = explode($this->pathSeparator, $path);
203+
$nextPath = array_shift($explodedPath);
204+
205+
if (!isset($currentOffset[$nextPath])) {
206+
if ($createPath) {
207+
$currentOffset[$nextPath] = [];
208+
} else {
209+
return;
210+
}
211+
}
212+
213+
if (count($explodedPath) > 0) {
214+
$this->callAtPath(
215+
implode($this->pathSeparator, $explodedPath),
216+
$callback,
217+
$createPath,
218+
$currentOffset[$nextPath]
219+
);
220+
} else {
221+
$callback($currentOffset[$nextPath]);
222+
}
223+
}
224+
}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2015 Julien Martin
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#ArrayFinder Component
2+
3+
The ArrayFinder component allow you to manage large nested arrays with ease.
4+
5+
Here is a simple example that shows how to easily get a value from an array:
6+
7+
```php
8+
use Shudrum\Component\ArrayFinder\ArrayFinder;
9+
10+
$arrayFinder = new ArrayFinder([
11+
'level_1' => [
12+
'level_2' => [
13+
'level_3' => 'value',
14+
],
15+
],
16+
]);
17+
18+
$myValue = $arrayFinder->get('level_1.level_2.level_3');
19+
// OR
20+
$myValue = $arrayFinder['level_1.level_2.level_3'];
21+
```
22+
23+
##Documentation
24+
25+
###Methods
26+
27+
####get($path)
28+
29+
You can get a value following a path separated by a '.'.
30+
31+
```php
32+
use Shudrum\Component\ArrayFinder\ArrayFinder;
33+
34+
$arrayFinder = new ArrayFinder([
35+
'a' => [
36+
'b' => [
37+
'c' => 'value1',
38+
],
39+
'value2',
40+
],
41+
'value3',
42+
]);
43+
44+
$myValue = $arrayFinder->get('a.b.c'); // value1
45+
$myValue = $arrayFinder->get('a.0'); // value2
46+
$myValue = $arrayFinder->get(0); // value3
47+
```
48+
49+
If the path is `null`, all the content will be returned.
50+
51+
####set($path, $value)
52+
53+
You can add a value to a specific path separated by a '.'. If the nested arrays does not exists, it will be created.
54+
55+
```php
56+
use Shudrum\Component\ArrayFinder\ArrayFinder;
57+
58+
$arrayFinder = new ArrayFinder();
59+
$arrayFinder->set('a.b', 'value');
60+
61+
$arrayFinder->get(); // ['a' => ['b' => 'value]]
62+
```
63+
64+
####changeSeparator($separator)
65+
66+
If the default separator (.) does not fit to your needs, you can call this method to change it.
67+
68+
```php
69+
use Shudrum\Component\ArrayFinder\ArrayFinder;
70+
71+
$arrayFinder = new ArrayFinder([…]);
72+
73+
$myValue = $arrayFinder->changeSeparator('/');
74+
$myValue = $arrayFinder->get('a/b/c');
75+
```
76+
77+
###Implementations
78+
79+
The ArrayFinder component implements some usefull interfaces:
80+
81+
####ArrayAccess
82+
83+
You can use this object like an array:
84+
85+
```php
86+
use Shudrum\Component\ArrayFinder\ArrayFinder;
87+
88+
$arrayFinder = new ArrayFinder([…]);
89+
90+
$value = $arrayFinder['a.b'];
91+
$arrayFinder['a.b.c'] = 'value';
92+
unset($arrayFinder['a.b']);
93+
```
94+
95+
####Countable
96+
97+
You can use count on this object:
98+
99+
```php
100+
use Shudrum\Component\ArrayFinder\ArrayFinder;
101+
102+
$arrayFinder = new ArrayFinder([…]);
103+
104+
count($arrayFinder);
105+
count($arrayFinder['a.b']);
106+
```
107+
108+
####Iterator
109+
110+
You can iterate on this object:
111+
112+
```php
113+
use Shudrum\Component\ArrayFinder\ArrayFinder;
114+
115+
$arrayFinder = new ArrayFinder([…]);
116+
117+
foreach ($arrayFinder as $key => $value) {
118+
// …
119+
}
120+
```
121+
122+
####Serializable
123+
124+
You can easily serialize / unserialize this object.
125+
126+
##Resources
127+
128+
You can run the unit tests with the following command:
129+
130+
$ cd path/to/Shudrum/Component/ArrayFinder/
131+
$ composer install
132+
$ phpunit

0 commit comments

Comments
 (0)