Skip to content

Commit 514da39

Browse files
committed
Added another flag to check method and improved documentation
1 parent 3145bd9 commit 514da39

File tree

3 files changed

+125
-41
lines changed

3 files changed

+125
-41
lines changed

src/Arr.php

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,17 @@ class Arr
9595
*/
9696
const FIND_RETURN_ALL = 'all';
9797

98+
/**
99+
* <p>In case <b>condition</b> is callable check if it result is exactly <tt>true</tt></p>
100+
* <p>If <b>condition</b> is not callable, then check if array element is equal to it both by value and type</p>
101+
*/
102+
const CHECK_STRICT = 1;
103+
104+
/**
105+
* Check will return <tt>true</tt> on first array element that match specified <b>condition</b>
106+
*/
107+
const CHECK_SOME = 2;
108+
98109
private const AUTO_INDEX_KEY = '[]';
99110
private const KEY_SEPARATOR = '.';
100111

@@ -326,47 +337,25 @@ public static function unpack(array $array, int $mode = self::UNPACK_ALL): array
326337
return self::_unpack($array, $mode);
327338
}
328339

329-
private static function _unpack(array $array, int $mode = self::UNPACK_ALL, array $keys = []): array
330-
{
331-
$result = [];
332-
333-
foreach ($array as $key => $value) {
334-
335-
if (is_array($value) && !(
336-
// Check if value IS NOT a subject for preserve mode
337-
!self::isNested($value) && // Preserve mode only work for highest depth elements
338-
(
339-
($mode === self::UNPACK_PRESERVE_LIST_ARRAY && !self::isAssoc($value, true)) ||
340-
($mode === self::UNPACK_PRESERVE_ASSOC_ARRAY && self::isAssoc($value, true)) ||
341-
$mode === self::UNPACK_PRESERVE_ARRAY
342-
)
343-
)) {
344-
$keys[] = $key;
345-
$result += self::_unpack($value, $mode, $keys);
346-
array_pop($keys);
347-
} else {
348-
$result[implode(self::KEY_SEPARATOR, array_merge($keys, [$key]))] = $value;
349-
}
350-
}
351-
352-
return $result;
353-
}
354-
355-
/*--------------------------------------------------------------------------------------*\
356-
| Validation |
357-
| ****************************************************************************** |
358-
| Flexible check method and various specific checks |
359-
\*--------------------------------------------------------------------------------------*/
360-
361340
/**
362341
* Check if every element of an array meets specified condition
363342
*
364343
* @param array $array
365-
* @param mixed|callable $condition Can be either single value to compare every array value to or callable (which takes value as first argument and key as second) that performs check
366-
* @param bool $strict In case $condition is callable check if it result is exactly <code>true</code> otherwise if it is equal both by value and type to supplied $condition
344+
* @param mixed|callable $condition <p>Either callable performing check or a value which every array element will be compared to.</p>
345+
* <p><b>Callable</b> is supplied with either only element value or pair of element value and key. Arguments amount depends on <b>callable</b> definition and is dynamically resolved using reflection (defaults to 2 - value and key)</p>
346+
* @param int $flag <p>[optional]</p>
347+
* <p>Determines how <b>condition</b> is processed (see Arr::CHECK_* constants for more info)</p>
348+
* <ul>
349+
* <li><b>CHECK_STRICT</b> - compare using <b>condition</b> by both value and type</li>
350+
* <li><b>CHECK_SOME</b> - return <tt>true</tt> if any of array elements meet specified <b>condition</b></li>
351+
* </ul>
367352
* @return bool
353+
* @see Arr::CHECK_STRICT
354+
* @see Arr::CHECK_SOME
355+
* @see ReflectionMethod::getNumberOfParameters()
356+
* @see ReflectionFunction::getNumberOfParameters()
368357
*/
369-
public static function check(array $array, $condition, bool $strict = false): bool
358+
public static function check(array $array, $condition, int $flag = 0): bool
370359
{
371360
if (is_callable($condition)) {
372361
try {
@@ -385,24 +374,71 @@ public static function check(array $array, $condition, bool $strict = false): bo
385374
}
386375
}
387376

377+
$checkStrict = $flag & self::CHECK_STRICT;
378+
$checkSome = $flag & self::CHECK_SOME;
379+
388380
foreach ($array as $key => $value) {
389381
if (is_callable($condition)) {
390382
/** @var int $paramsCount */
391383
$result = $paramsCount == 1 ? call_user_func($condition, $value) : call_user_func($condition, $value, $key);
392384

393-
if ($strict ? $result !== true : !$result) {
394-
return false;
385+
if ($checkStrict ? $result === true : $result) {
386+
if ($checkSome) {
387+
return true;
388+
}
389+
} else {
390+
if (!$checkSome) {
391+
return false;
392+
}
395393
}
396394
} else {
397-
if ($strict ? $value !== $condition : $value != $condition) {
398-
return false;
395+
if ($checkStrict ? $value === $condition : $value == $condition) {
396+
if ($checkSome) {
397+
return true;
398+
}
399+
} else {
400+
if (!$checkSome) {
401+
return false;
402+
}
399403
}
400404
}
401405
}
402406

403-
return true;
407+
return $checkSome ? false : true;
404408
}
405409

410+
private static function _unpack(array $array, int $mode = self::UNPACK_ALL, array $keys = []): array
411+
{
412+
$result = [];
413+
414+
foreach ($array as $key => $value) {
415+
416+
if (is_array($value) && !(
417+
// Check if value IS NOT a subject for preserve mode
418+
!self::isNested($value) && // Preserve mode only work for highest depth elements
419+
(
420+
($mode === self::UNPACK_PRESERVE_LIST_ARRAY && !self::isAssoc($value, true)) ||
421+
($mode === self::UNPACK_PRESERVE_ASSOC_ARRAY && self::isAssoc($value, true)) ||
422+
$mode === self::UNPACK_PRESERVE_ARRAY
423+
)
424+
)) {
425+
$keys[] = $key;
426+
$result += self::_unpack($value, $mode, $keys);
427+
array_pop($keys);
428+
} else {
429+
$result[implode(self::KEY_SEPARATOR, array_merge($keys, [$key]))] = $value;
430+
}
431+
}
432+
433+
return $result;
434+
}
435+
436+
/*--------------------------------------------------------------------------------------*\
437+
| Validation |
438+
| ****************************************************************************** |
439+
| Flexible check method and various specific checks |
440+
\*--------------------------------------------------------------------------------------*/
441+
406442
/**
407443
* Recursively check if all of array values match empty condition
408444
*

src/ArrObj.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
*
3333
* ---------------------------------------------------------------------------------
3434
*
35-
* @method bool check(mixed|callable $condition, bool $strict = false)
35+
* @method bool check(mixed|callable $condition, int $flag = 0)
3636
* @see Arr::check()
3737
*
3838
* @method bool isEmpty()

test/Arr/ArrTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ public function testCheck($class)
376376
{
377377
$array1 = ['test', 'test', 'test'];
378378
$array2 = [1, 1, 1];
379+
$array3 = [false, 0, true, 1, '2', 'three'];
379380

380381
$testClass = new TestCheckMethod();
381382

@@ -392,33 +393,80 @@ public function testCheck($class)
392393

393394
$this->assertFalse($this->callMethod([$class, 'check'], $array1, [$testClass, 'testOneArg']));
394395
$this->assertFalse($this->callMethod([$class, 'check'], $array1, [$testClass, 'testOneArg'], true));
396+
$this->assertFalse($this->callMethod([$class, 'check'], $array1, [$testClass, 'testOneArg'], Arr::CHECK_STRICT));
395397

396398
$this->assertTrue($this->callMethod([$class, 'check'], $array2, [$testClass, 'testOneArg']));
397399
$this->assertTrue($this->callMethod([$class, 'check'], $array2, [$testClass, 'testOneArg'], true));
400+
$this->assertTrue($this->callMethod([$class, 'check'], $array2, [$testClass, 'testOneArg'], Arr::CHECK_STRICT));
398401

399402
$this->assertTrue($this->callMethod([$class, 'check'], $array1, [$testClass, 'testTwoArg']));
400403
$this->assertTrue($this->callMethod([$class, 'check'], $array1, [$testClass, 'testTwoArg'], true));
404+
$this->assertTrue($this->callMethod([$class, 'check'], $array1, [$testClass, 'testTwoArg'], Arr::CHECK_STRICT));
401405

402406
$this->assertTrue($this->callMethod([$class, 'check'], $array2, [$testClass, 'testTwoArg']));
403407
$this->assertTrue($this->callMethod([$class, 'check'], $array2, [$testClass, 'testTwoArg'], true));
408+
$this->assertTrue($this->callMethod([$class, 'check'], $array2, [$testClass, 'testTwoArg'], Arr::CHECK_STRICT));
404409

405410
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 'TestCheckMethod::testStaticOneArg'));
406411
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 'TestCheckMethod::testStaticTwoArg'));
407412

413+
414+
408415
$this->assertTrue($this->callMethod([$class, 'check'], $array1, 'test', false));
416+
$this->assertTrue($this->callMethod([$class, 'check'], $array1, 'test', 0));
417+
$this->assertTrue($this->callMethod([$class, 'check'], $array1, 'test', Arr::CHECK_SOME));
418+
409419
$this->assertTrue($this->callMethod([$class, 'check'], $array1, 'test', true));
420+
$this->assertTrue($this->callMethod([$class, 'check'], $array1, 'test', Arr::CHECK_STRICT));
421+
$this->assertTrue($this->callMethod([$class, 'check'], $array1, 'test', Arr::CHECK_STRICT | Arr::CHECK_SOME));
422+
410423
$this->assertFalse($this->callMethod([$class, 'check'], $array1, 'test1', false));
424+
$this->assertFalse($this->callMethod([$class, 'check'], $array1, 'test1', 0));
425+
$this->assertFalse($this->callMethod([$class, 'check'], $array1, 'test1', Arr::CHECK_SOME));
426+
411427
$this->assertFalse($this->callMethod([$class, 'check'], $array1, 'test1', true));
428+
$this->assertFalse($this->callMethod([$class, 'check'], $array1, 'test1', Arr::CHECK_STRICT));
429+
$this->assertFalse($this->callMethod([$class, 'check'], $array1, 'test1', Arr::CHECK_STRICT | Arr::CHECK_SOME));
430+
431+
412432

413433
$this->assertTrue($this->callMethod([$class, 'check'], $array2, '1', false));
434+
$this->assertTrue($this->callMethod([$class, 'check'], $array2, '1', 0));
435+
$this->assertTrue($this->callMethod([$class, 'check'], $array2, '1', Arr::CHECK_SOME));
436+
414437
$this->assertFalse($this->callMethod([$class, 'check'], $array2, '1', true));
438+
$this->assertFalse($this->callMethod([$class, 'check'], $array2, '1', Arr::CHECK_STRICT));
439+
$this->assertFalse($this->callMethod([$class, 'check'], $array2, '1', Arr::CHECK_STRICT | Arr::CHECK_SOME));
440+
415441
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 1, false));
442+
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 1, 0));
443+
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 1, Arr::CHECK_SOME));
444+
416445
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 1, true));
446+
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 1, Arr::CHECK_STRICT));
447+
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 1, Arr::CHECK_STRICT | Arr::CHECK_SOME));
448+
449+
450+
$this->assertFalse($this->callMethod([$class, 'check'], $array3, '1'));
451+
$this->assertTrue($this->callMethod([$class, 'check'], $array3, '1', Arr::CHECK_SOME));
452+
$this->assertFalse($this->callMethod([$class, 'check'], $array3, '1', Arr::CHECK_STRICT | Arr::CHECK_SOME));
453+
454+
$this->assertFalse($this->callMethod([$class, 'check'], $array3, 1));
455+
$this->assertTrue($this->callMethod([$class, 'check'], $array3, 1, Arr::CHECK_SOME));
456+
$this->assertTrue($this->callMethod([$class, 'check'], $array3, 1, Arr::CHECK_STRICT | Arr::CHECK_SOME));
457+
417458

418459
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 'is_int'));
419460
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 'is_int', true));
461+
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 'is_int', Arr::CHECK_STRICT));
462+
$this->assertTrue($this->callMethod([$class, 'check'], $array2, 'is_int', Arr::CHECK_STRICT | Arr::CHECK_SOME));
463+
420464
$this->assertFalse($this->callMethod([$class, 'check'], $array2, 'is_string'));
421465
$this->assertFalse($this->callMethod([$class, 'check'], $array2, 'is_string', true));
466+
$this->assertFalse($this->callMethod([$class, 'check'], $array2, 'is_string', Arr::CHECK_STRICT));
467+
$this->assertFalse($this->callMethod([$class, 'check'], $array2, 'is_string', Arr::CHECK_STRICT | Arr::CHECK_SOME));
468+
469+
422470

423471
$this->assertFalse($this->callMethod([$class, 'check'], $array1, ['test']));
424472
$this->assertFalse($this->callMethod([$class, 'check'], $array2, [1]));

0 commit comments

Comments
 (0)