diff --git a/README.md b/README.md index 370956e57..f3bbe6a04 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ Polyfills are provided for: - the `Date*Exception/Error` classes introduced in PHP 8.3; - the `SQLite3Exception` class introduced in PHP 8.3; - the `mb_ucfirst` and `mb_lcfirst` functions introduced in PHP 8.4; +- the `array_find`, `array_find_key`, `array_any` and `array_all` functions introduced in PHP 8.4; It is strongly recommended to upgrade your PHP version and/or install the missing extensions whenever possible. This polyfill should be used only when there is no diff --git a/src/Php84/Php84.php b/src/Php84/Php84.php index c8a9cf160..9358e0440 100644 --- a/src/Php84/Php84.php +++ b/src/Php84/Php84.php @@ -63,4 +63,48 @@ public static function mb_lcfirst(string $string, ?string $encoding = null): str return $firstChar . mb_substr($string, 1, null, $encoding); } + + public static function array_find(array $array, callable $callback) + { + foreach ($array as $key => $value) { + if ($callback($value, $key)) { + return $value; + } + } + + return null; + } + + public static function array_find_key(array $array, callable $callback) + { + foreach ($array as $key => $value) { + if ($callback($value, $key)) { + return $key; + } + } + + return null; + } + + public static function array_any(array $array, callable $callback): bool + { + foreach ($array as $key => $value) { + if ($callback($value, $key)) { + return true; + } + } + + return false; + } + + public static function array_all(array $array, callable $callback): bool + { + foreach ($array as $key => $value) { + if (!$callback($value, $key)) { + return false; + } + } + + return true; + } } diff --git a/src/Php84/README.md b/src/Php84/README.md index 77d249bed..443e3d1b9 100644 --- a/src/Php84/README.md +++ b/src/Php84/README.md @@ -4,6 +4,7 @@ Symfony Polyfill / Php84 This component provides features added to PHP 8.4 core: - [`mb_ucfirst` and `mb_lcfirst`](https://wiki.php.net/rfc/mb_ucfirst) +- [`array_find`, `array_find_key`, `array_any` and `array_all`](https://wiki.php.net/rfc/array_find) More information can be found in the [main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). diff --git a/src/Php84/bootstrap.php b/src/Php84/bootstrap.php index f73ba3d42..12cf7a7ac 100644 --- a/src/Php84/bootstrap.php +++ b/src/Php84/bootstrap.php @@ -23,3 +23,19 @@ function mb_ucfirst($string, ?string $encoding = null): string { return p\Php84: if (!function_exists('mb_lcfirst')) { function mb_lcfirst($string, ?string $encoding = null): string { return p\Php84::mb_lcfirst($string, $encoding); } } + +if (!function_exists('array_find')) { + function array_find(array $array, callable $callback) { return p\Php84::array_find($array, $callback); } +} + +if (!function_exists('array_find_key')) { + function array_find_key(array $array, callable $callback) { return p\Php84::array_find_key($array, $callback); } +} + +if (!function_exists('array_any')) { + function array_any(array $array, callable $callback): bool { return p\Php84::array_any($array, $callback); } +} + +if (!function_exists('array_all')) { + function array_all(array $array, callable $callback): bool { return p\Php84::array_all($array, $callback); } +} diff --git a/tests/Php84/Php84Test.php b/tests/Php84/Php84Test.php index c66f402df..e37a76ec1 100644 --- a/tests/Php84/Php84Test.php +++ b/tests/Php84/Php84Test.php @@ -30,6 +30,34 @@ public function testMbLcFirst(string $string, string $expected): void { $this->assertSame($expected, mb_lcfirst($string)); } + /** + * @dataProvider arrayFindDataProvider + */ + public function testArrayFind(array $array, callable $callback, $expected): void { + $this->assertSame($expected, array_find($array, $callback)); + } + + /** + * @dataProvider arrayFindKeyDataProvider + */ + public function testArrayFindKey(array $array, callable $callback, $expected): void { + $this->assertSame($expected, array_find_key($array, $callback)); + } + + /** + * @dataProvider arrayAnyDataProvider + */ + public function testArrayAny(array $array, callable $callback, bool $expected): void { + $this->assertSame($expected, array_any($array, $callback)); + } + + /** + * @dataProvider arrayAllDataProvider + */ + public function testArrayAll(array $array, callable $callback, bool $expected): void { + $this->assertSame($expected, array_all($array, $callback)); + } + public static function ucFirstDataProvider(): array { return [ ['', ''], @@ -68,4 +96,78 @@ public static function lcFirstDataProvider(): array { ["ß", "ß"], ]; } + + public static function arrayFindDataProvider(): array { + $callable = function ($value): bool { + return strlen($value) > 2; + }; + + $callableKey = function ($value, $key): bool { + return is_numeric($key); + }; + + return [ + [[], $callable, null], + [['a', 'aa', 'aaa', 'aaaa'], $callable, 'aaa'], + [['a', 'aa'], $callable, null], + [['a' => '1', 'b' => '12', 'c' => '123', 'd' => '1234'], $callable, '123'], + [['a' => '1', 'b' => '12', 'c' => '123', 3 => '1234'], $callableKey, '1234'], + ]; + } + + public static function arrayFindKeyDataProvider(): array { + $callable = function ($value): bool { + return strlen($value) > 2; + }; + + $callableKey = function ($value, $key): bool { + return is_numeric($key); + }; + + return [ + [[], $callable, null], + [['a', 'aa', 'aaa', 'aaaa'], $callable, 2], + [['a', 'aa'], $callable, null], + [['a' => '1', 'b' => '12', 'c' => '123', 'd' => '1234'], $callable, 'c'], + [['a' => '1', 'b' => '12', 'c' => '123', 3 => '1234'], $callableKey, 3], + ]; + } + + public static function arrayAnyDataProvider(): array { + $callable = function ($value): bool { + return strlen($value) > 2; + }; + + $callableKey = function ($value, $key): bool { + return is_numeric($key); + }; + + return [ + [[], $callable, false], + [['a', 'aa', 'aaa', 'aaaa'], $callable, true], + [['a', 'aa'], $callable, false], + [['a' => '1', 'b' => '12', 'c' => '123', 'd' => '1234'], $callable, true], + [['a' => '1', 'b' => '12', 'c' => '123', 3 => '1234'], $callableKey, true], + [['a' => '1', 'b' => '12', 'c' => '123', 'd' => '1234'], $callableKey, false], + ]; + } + + public static function arrayAllDataProvider(): array { + $callable = function ($value): bool { + return strlen($value) > 2; + }; + + $callableKey = function ($value, $key): bool { + return is_numeric($key); + }; + + return [ + [[], $callable, true], + [['a', 'aa', 'aaa', 'aaaa'], $callable, false], + [['aaa', 'aaa'], $callable, true], + [['a' => '1', 'b' => '12', 'c' => '123', 'd' => '1234'], $callable, false], + [['a' => '1', 'b' => '12', 'c' => '123', 'd' => '1234'], $callableKey, false], + [[1 => '1', 2 => '12', 3 => '123', 4 => '1234'], $callableKey, true], + ]; + } }