Skip to content

Commit e48a736

Browse files
author
coa
committed
3 new methods added and tested & castColumns tested
1 parent 791e7a7 commit e48a736

26 files changed

Lines changed: 682 additions & 64 deletions

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
.idea
22
/vendor/
3-
index.php
3+
/index.php

README.md

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@ and you're ready to go.
2626
Usage examples
2727
==============================
2828
For additional help, look at the tests, additional input scenarios are tested.
29+
addConfigRow
30+
------------------------------
31+
Method is intended to remove need for configuration files that need to be parsed into php arrays, since that carries significant performance
32+
penalties. It combines readability of ini file with speed of having configurations defined directly on php level.
33+
First parameter represents configuration array, second parameter represents a numerical array (in case of associative array, exception
34+
is thrown) of nested keys of the new configuration row. Third parameter represents the value that is being mapped.
35+
property, that is being added. Method returns configuration with the new row added, or throws exception if the same combination of
36+
keys has already been used.
37+
```
38+
SimpleArrayLibrary::addConfigRow(array('foo' => array('baz' => 1)), array('foo', 'bar'), 2); // array('foo' => array('baz' => 1, 'bar' => 2))
39+
$config = array();
40+
$config = SimpleArrayLibrary::addConfigRow($config, array('foo', 'bar'), new stdClass());
41+
$config = SimpleArrayLibrary::addConfigRow($config, array('foo', 'baz'), 1);
42+
$config = SimpleArrayLibrary::addConfigRow($config, array('foo', 3), array(1, 2));
43+
// $config = array('foo' => array('bar' => stdClass(), 'baz' => 1, 3 => array(1, 2)))
44+
$config = SimpleArrayLibrary::addConfigRow($config, array('foo', 3), false); // exception because of repeated array('foo', 3) path
45+
```
2946
allElementsEqual
3047
------------------------------
3148
Checks whether all elements of the array are equal and optionally if they are all equal to specified value.
@@ -35,6 +52,19 @@ SimpleArrayLibrary::allElementsEqual(array(1, 2)); // false
3552
SimpleArrayLibrary::allElementsEqual(array(1, 1), 1); // true
3653
SimpleArrayLibrary::allElementsEqual(array(1, 1), 2); // false
3754
```
55+
castColumns
56+
------------------------------
57+
Attempts to cast specified columns of all rows of the two dimensional array to specified type. Allowed types are represented by
58+
constants: TYPE_INT, TYPE_STRING, TYPE_FLOAT, TYPE_BOOL, TYPE_ARRAY, TYPE_OBJECT. Any other type will cause exception to be thrown.
59+
User should know how type casting works in PHP as this method provides no protection from possible casting errors.
60+
61+
Third parameter must be a boolean, otherwise exception is thrown. If third parameter is set to true, columns defined as keys in the
62+
second parameter have to be present, otherwise exception is thrown.
63+
```
64+
SimpleArrayLibrary::castColumns(array(array('a' => '2')), array('a' => SimpleArrayLibrary::TYPE_INT)); // array(array('a' => 2))
65+
SimpleArrayLibrary::castColumns(array(array()), array('a' => SimpleArrayLibrary::TYPE_INT), false); // array(array())
66+
SimpleArrayLibrary::castColumns(array(array('a' => '1'), array('b' => 'foo')), array('a' => SimpleArrayLibrary::TYPE_INT), false); // array(array('a' => 1), array('b' => 'foo'))
67+
```
3868
countMaxDepth
3969
------------------------------
4070
Count maximum depth of the array (number of nested sub-arrays) recursively.
@@ -156,6 +186,20 @@ SimpleArrayLibrary::haveEqualValues(array('a' => 1), array(1)); // true
156186
SimpleArrayLibrary::haveEqualValues(array(), array()); // true
157187
SimpleArrayLibrary::haveEqualValues(array(1), array(2)); // false
158188
```
189+
insertSubArray
190+
------------------------------
191+
Inserts the sub-array into the array in the place to which sub-array's keys point to
192+
193+
Third and forth parameters must be booleans, otherwise exception is thrown. If third parameter is set to true, insertion will overwrite
194+
existing value inside the array, pointed to the sub-array's keys, if any. If third parameter is set to true, forth parameter is not used.
195+
If forth parameter is set to true nad third parameter is set to false, existing value will be left unchanged, but if both third and
196+
forth parameters were set to false and sub-array keys point to already existing value, exception will be thrown
197+
```
198+
SimpleArrayLibrary::insertSubArray(array('foo' => 1), array('bar' => 2)); // array('foo' => 1, 'bar' => 2)
199+
SimpleArrayLibrary::insertSubArray(array('foo' => 1), array('foo' => 2), true, false); // array('foo' => 2)
200+
SimpleArrayLibrary::insertSubArray(array('foo' => 1), array('foo' => 2), false, true); // array('foo' => 1)
201+
SimpleArrayLibrary::insertSubArray(array('foo' => 1), array('foo' => 2), false, false); // exception
202+
```
159203
isAssociative
160204
------------------------------
161205
Checks whether array has any associative keys.
@@ -174,16 +218,16 @@ SimpleArrayLibrary::isSubArray(array(2, 1), array(2)); // true
174218
SimpleArrayLibrary::isSubArray(array('a' => 1, 'b' => array(1)), array('c' => 1)); // false
175219
SimpleArrayLibrary::isSubArray(array('a' => 1, 'b' => array(1)), array('a' => 2)); // false
176220
```
177-
castColumns
221+
setColumn
178222
------------------------------
179-
Attempts to cast specified columns in all rows of the two dimensional array to specified type. Allowed types are represented by
180-
constants: TYPE_INT, TYPE_STRING, TYPE_FLOAT, TYPE_BOOL, TYPE_ARRAY, TYPE_OBJECT. Any other type will cause exception to be thrown.
181-
User should know how type casting works in PHP as this method provides no protection from possible casting errors.
223+
Sets values to columns of the multi-dimensional array (is meant for two-dimensional arrays in particular, will work for three or more
224+
dimension, but will only change elements on the second level) to the specified value
182225

183-
Third parameter must be a boolean, otherwise exception is thrown. If third parameter is set to true, columns defined as keys in the
184-
second parameter have to be present, otherwise exception is thrown.
226+
Forth and fifth parameters must be booleans, otherwise exception is thrown. If forth parameter is set to true, column will be added to
227+
the rows in which it's missing. If fifth parameter is set to true, value of the column will be overwritten in rows in which it already
228+
exists
185229
```
186-
SimpleArrayLibrary::castColumns(array(array('a' => '2')), array('a' => SimpleArrayLibrary::TYPE_INT)); // array(array('a' => 2))
187-
SimpleArrayLibrary::castColumns(array(array()), array('a' => SimpleArrayLibrary::TYPE_INT), false); // array(array())
188-
SimpleArrayLibrary::castColumns(array(array('a' => '1'), array('b' => 'foo')), array('a' => SimpleArrayLibrary::TYPE_INT), false); // array(array('a' => 1), array('b' => 'foo'))
230+
SimpleArrayLibrary::setColumn(array(array('foo' => 2), array()), 'foo', 1); // array(array('foo' => 1), array('foo' => 1))
231+
SimpleArrayLibrary::setColumn(array(array('foo' => 2), array()), 'foo', 1, false, false); // array(array('foo' => 2), array())
232+
SimpleArrayLibrary::setColumn(array(array('foo' => 2), array()), 'foo', 1, true, false); // array(array('foo' => 2), array('foo' => 1))
189233
```

src/SimpleArrayLibrary.php

Lines changed: 138 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@
77

88
class SimpleArrayLibrary
99
{
10+
/**
11+
* @param array $config
12+
* @param array $keys
13+
* @param mixed $value
14+
*
15+
* @return array
16+
*/
17+
public static function addConfigRow(array $config, array $keys, $value)
18+
{
19+
// validation
20+
if (self::isAssociative($keys)) {
21+
throw new UnexpectedValueException('Array of config keys must be numeric');
22+
}
23+
24+
$row = $value;
25+
for ($i = count($keys) - 1; $i >= 0; $i--) {
26+
$row = [$keys[$i] => $row];
27+
}
28+
$config = self::insertSubArray($config, $row);
29+
30+
return $config;
31+
}
32+
1033
/**
1134
* Checks if all elements of the array have same value
1235
*
@@ -35,6 +58,63 @@ public static function allElementsEqual(array $array, $value = null)
3558
return $return;
3659
}
3760

61+
const TYPE_INT = 'int';
62+
const TYPE_STRING = 'string';
63+
const TYPE_FLOAT = 'float';
64+
const TYPE_BOOL = 'bool';
65+
const TYPE_ARRAY = 'array';
66+
const TYPE_OBJECT = 'object';
67+
68+
/**
69+
* @param array $matrix
70+
* @param array $castMap
71+
* @param bool $allKeysMustBePresent
72+
*
73+
* @return array
74+
*/
75+
public static function castColumns(array $matrix, array $castMap, $allKeysMustBePresent = true)
76+
{
77+
if (!is_bool($allKeysMustBePresent)) {
78+
throw new InvalidArgumentException('Third parameter must be a boolean');
79+
}
80+
if (self::countMinDepth($matrix) < 2) {
81+
throw new UnexpectedValueException('Can not cast columns on one dimensional array');
82+
}
83+
84+
foreach ($matrix as $key => $row) {
85+
foreach ($castMap as $column => $type) {
86+
if (isset($row[$column]) || array_key_exists($column, $row)) {
87+
switch ($type) {
88+
case self::TYPE_INT:
89+
$matrix[$key][$column] = (int)$row[$column];
90+
break;
91+
case self::TYPE_STRING:
92+
$matrix[$key][$column] = (string)$row[$column];
93+
break;
94+
case self::TYPE_FLOAT:
95+
$matrix[$key][$column] = (float)$row[$column];
96+
break;
97+
case self::TYPE_BOOL:
98+
$matrix[$key][$column] = (bool)$row[$column];
99+
break;
100+
case self::TYPE_ARRAY:
101+
$matrix[$key][$column] = (array)$row[$column];
102+
break;
103+
case self::TYPE_OBJECT:
104+
$matrix[$key][$column] = (object)$row[$column];
105+
break;
106+
default:
107+
throw new UnexpectedValueException('Invalid type: ' . $type);
108+
}
109+
} elseif ($allKeysMustBePresent) {
110+
throw new UnexpectedValueException('Column: ' . $column . ' missing in row: ' . $key);
111+
}
112+
}
113+
}
114+
115+
return $matrix;
116+
}
117+
38118
/**
39119
* Counts maximum array depth
40120
*
@@ -221,6 +301,43 @@ public static function haveEqualValues($array1, $array2)
221301
return self::hasAllValues($array1, $array2) && self::hasAllValues($array2, $array1) ? true : false;
222302
}
223303

304+
/**
305+
* @param mixed $array
306+
* @param mixed $subArray
307+
* @param bool $overwrite
308+
* @param bool $ignoreIfExists
309+
*
310+
* @return array
311+
*/
312+
public static function insertSubArray($array, $subArray, $overwrite = false, $ignoreIfExists = false)
313+
{
314+
// validate
315+
if (!is_bool($overwrite)) {
316+
throw new InvalidArgumentException('Overwrite indicator must be a boolean');
317+
}
318+
if (!is_bool($ignoreIfExists)) {
319+
throw new InvalidArgumentException('Ignore if exists indicator must be a boolean');
320+
}
321+
322+
if (!is_array($subArray) || !is_array($array)) {
323+
// $subArray[$key] is leaf of the array
324+
if ($overwrite) {
325+
$array = $subArray;
326+
} elseif (!$ignoreIfExists) {
327+
throw new UnexpectedValueException('Sub-array already exists');
328+
}
329+
} else {
330+
$key = key($subArray);
331+
if (isset($array[$key]) || array_key_exists($key, $array)) {
332+
$array[$key] = self::insertSubArray($array[$key], $subArray[$key], $overwrite, $ignoreIfExists);
333+
} else {
334+
$array[$key] = $subArray[$key];
335+
}
336+
}
337+
338+
return $array;
339+
}
340+
224341
/**
225342
* Checks whether array is associative or numeric
226343
*
@@ -266,54 +383,36 @@ public static function isSubArray(array $array, array $subArray, $strictComparis
266383
return $return;
267384
}
268385

269-
const TYPE_INT = 'int';
270-
const TYPE_STRING = 'string';
271-
const TYPE_FLOAT = 'float';
272-
const TYPE_BOOL = 'bool';
273-
const TYPE_ARRAY = 'array';
274-
const TYPE_OBJECT = 'object';
275-
276386
/**
277387
* @param array $matrix
278-
* @param array $castMap
279-
* @param bool $allKeysMustBePresent
388+
* @param mixed $column
389+
* @param mixed $value
390+
* @param bool $insertIfMissing
391+
* @param bool $overwrite
280392
*
281393
* @return array
282394
*/
283-
public static function castColumns(array $matrix, array $castMap, $allKeysMustBePresent = true)
395+
public static function setColumn(array $matrix, $column, $value, $insertIfMissing = true, $overwrite = true)
284396
{
285-
if (!is_bool($allKeysMustBePresent)) {
286-
throw new InvalidArgumentException('Strict parameter must be a boolean');
397+
// validate input
398+
if (self::countMinDepth($matrix) < 2) {
399+
throw new UnexpectedValueException('Can not set columns on one dimensional array');
400+
}
401+
if (!is_scalar($column)) {
402+
throw new InvalidArgumentException('Invalid column');
403+
}
404+
if (!is_bool($insertIfMissing)) {
405+
throw new InvalidArgumentException('Insert if missing indicator must be a boolean');
406+
}
407+
if (!is_bool($overwrite)) {
408+
throw new InvalidArgumentException('Overwrite indicator must be a boolean');
287409
}
288410

289411
foreach ($matrix as $key => $row) {
290-
foreach ($castMap as $column => $type) {
291-
if (isset($row[$column]) || array_key_exists($column, $row)) {
292-
switch ($type) {
293-
case self::TYPE_INT:
294-
$matrix[$key][$column] = (int)$row[$column];
295-
break;
296-
case self::TYPE_STRING:
297-
$matrix[$key][$column] = (string)$row[$column];
298-
break;
299-
case self::TYPE_FLOAT:
300-
$matrix[$key][$column] = (float)$row[$column];
301-
break;
302-
case self::TYPE_BOOL:
303-
$matrix[$key][$column] = (bool)$row[$column];
304-
break;
305-
case self::TYPE_ARRAY:
306-
$matrix[$key][$column] = (array)$row[$column];
307-
break;
308-
case self::TYPE_OBJECT:
309-
$matrix[$key][$column] = (object)$row[$column];
310-
break;
311-
default:
312-
throw new UnexpectedValueException('Invalid type: ' . $type);
313-
}
314-
} elseif ($allKeysMustBePresent) {
315-
throw new UnexpectedValueException('Column: ' . $column . ' missing in row: ' . $key);
316-
}
412+
if (isset($row[$column]) || array_key_exists($column, $row)) {
413+
$matrix[$key][$column] = ($overwrite ? $value : $matrix[$key][$column]);
414+
} elseif ($insertIfMissing) {
415+
$matrix[$key][$column] = $value;
317416
}
318417
}
319418

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
use SimpleArrayLibrary\SimpleArrayLibrary;
4+
5+
class AddConfigRowTest extends PHPUnit_Framework_TestCase
6+
{
7+
/**
8+
* @return void
9+
*/
10+
public function test_function()
11+
{
12+
// invoke logic & test
13+
$this->assertEquals(
14+
array('foo' => array(
15+
'baz' => 1,
16+
'bar' => 2
17+
)),
18+
SimpleArrayLibrary::addConfigRow(
19+
array('foo' => array('baz' => 1)),
20+
array('foo', 'bar'),
21+
2
22+
)
23+
);
24+
}
25+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
use SimpleArrayLibrary\SimpleArrayLibrary;
4+
5+
class AddConfigRowXTest extends PHPUnit_Framework_TestCase
6+
{
7+
/**
8+
* @return void
9+
*/
10+
public function test_function()
11+
{
12+
// prepare
13+
$this->setExpectedException('UnexpectedValueException', 'Array of config keys must be numeric');
14+
15+
// invoke logic & test
16+
SimpleArrayLibrary::addConfigRow([], ['z' => 1], 1);
17+
}
18+
19+
/**
20+
* @return array
21+
*/
22+
public function getData()
23+
{
24+
return array(
25+
// #0 invalid keys array
26+
array(
27+
array(
28+
'config' => array(),
29+
'keys' => array('foo' => 1),
30+
'value' => 1,
31+
'exception' => 'UnexpectedValueException',
32+
'errorMessage' => 'Array of config keys must be numeric'
33+
)
34+
),
35+
// #1 row already exists in the config
36+
array(
37+
array(
38+
'config' => array('foo' => 1),
39+
'keys' => array('foo' => 2),
40+
'value' => false,
41+
'exception' => 'UnexpectedValueException',
42+
'errorMessage' => 'Sub-array already exists'
43+
)
44+
)
45+
);
46+
}
47+
}

test/SimpleArrayLibrary/AllElementsEqualTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
use \SimpleArrayLibrary\SimpleArrayLibrary;
3+
use SimpleArrayLibrary\SimpleArrayLibrary;
44

55
class AllElementsEqualTest extends PHPUnit_Framework_TestCase
66
{

0 commit comments

Comments
 (0)