From b21d748b410fe49551c01e933bdbbddd672afa9a Mon Sep 17 00:00:00 2001 From: Tonya Mork Date: Mon, 8 Nov 2021 13:50:35 +0000 Subject: [PATCH] General: Introduce polyfills for `array_key_first()` and `array_key_last()` added in PHP 7.3.0. PHP 7.3.0 introduced two new functions: `array_key_first()` and `array_key_last()`. These two functions return the first and last key of each array respectively, without affecting the internal state of the array. The polyfills make these two functions available for use in Core on PHP versions less than 7.3.0. Ref: * PHP RFC https://wiki.php.net/rfc/array_key_first_last * PHP manual `array_key_first()` https://www.php.net/manual/en/function.array-key-first.php * PHP manual `array_key_last()` https://www.php.net/manual/en/function.array-key-last.php Props desrosj, pbearne, costdev, hellofromTonya, ayeshrajans, manzoorwanijk, audrasjb, sergeybiryukov. Fixes #45055. git-svn-id: https://develop.svn.wordpress.org/trunk@52038 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/compat.php | 42 ++++++++++ tests/phpunit/tests/compat/arrayKeyFirst.php | 76 ++++++++++++++++++ tests/phpunit/tests/compat/arrayKeyLast.php | 81 ++++++++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 tests/phpunit/tests/compat/arrayKeyFirst.php create mode 100644 tests/phpunit/tests/compat/arrayKeyLast.php diff --git a/src/wp-includes/compat.php b/src/wp-includes/compat.php index b95275455c..2a8664c065 100644 --- a/src/wp-includes/compat.php +++ b/src/wp-includes/compat.php @@ -375,6 +375,48 @@ if ( ! function_exists( 'is_iterable' ) ) { } } +if ( ! function_exists( 'array_key_first' ) ) { + /** + * Polyfill for array_key_first() function added in PHP 7.3. + * + * Get the first key of the given array without affecting + * the internal array pointer. + * + * @since 5.9.0 + * + * @param array $arr An array. + * @return string|int|null The first key of array if the array + * is not empty; `null` otherwise. + */ + function array_key_first( array $arr ) { + foreach ( $arr as $key => $value ) { + return $key; + } + } +} + +if ( ! function_exists( 'array_key_last' ) ) { + /** + * Polyfill for `array_key_last()` function added in PHP 7.3. + * + * Get the last key of the given array without affecting the + * internal array pointer. + * + * @since 5.9.0 + * + * @param array $arr An array. + * @return string|int|null The last key of array if the array + *. is not empty; `null` otherwise. + */ + function array_key_last( array $arr ) { + if ( empty( $arr ) ) { + return null; + } + end( $arr ); + return key( $arr ); + } +} + // IMAGETYPE_WEBP constant is only defined in PHP 7.1 or later. if ( ! defined( 'IMAGETYPE_WEBP' ) ) { define( 'IMAGETYPE_WEBP', 18 ); diff --git a/tests/phpunit/tests/compat/arrayKeyFirst.php b/tests/phpunit/tests/compat/arrayKeyFirst.php new file mode 100644 index 0000000000..613845aba0 --- /dev/null +++ b/tests/phpunit/tests/compat/arrayKeyFirst.php @@ -0,0 +1,76 @@ +assertTrue( function_exists( 'array_key_first' ) ); + } + + /** + * @dataProvider data_array_key_first + * + * @ticket 45055 + * + * @param bool $expected The value of the key extracted to extracted from given array. + * @param array $arr The array to get first key from. + */ + public function test_array_key_first( $expected, $arr ) { + if ( ! function_exists( 'array_key_first' ) ) { + $this->markTestSkipped( 'array_key_first() is not available.' ); + } else { + $this->assertSame( + $expected, + array_key_first( $arr ) + ); + } + + } + + /** + * Data provider. + * + * @return array[] + */ + public function data_array_key_first() { + return array( + 'string key' => array( + 'expected' => 'key1', + 'arr' => array( + 'key1' => 'val1', + 'key2' => 'val2', + ), + ), + 'int key' => array( + 'expected' => 99, + 'arr' => array( + 99 => 'val1', + 1 => 'val2', + ), + ), + 'no key' => array( + 'expected' => 0, + 'arr' => array( 'val1', 'val2' ), + ), + 'multi array' => array( + 'expected' => 99, + 'arr' => array( + 99 => array( 22 => 'val1' ), + 1 => 'val2', + ), + ), + 'empty array' => array( + 'expected' => null, + 'arr' => array(), + ), + ); + } +} diff --git a/tests/phpunit/tests/compat/arrayKeyLast.php b/tests/phpunit/tests/compat/arrayKeyLast.php new file mode 100644 index 0000000000..77510c8320 --- /dev/null +++ b/tests/phpunit/tests/compat/arrayKeyLast.php @@ -0,0 +1,81 @@ +assertTrue( function_exists( 'array_key_last' ) ); + } + + /** + * @dataProvider data_array_key_last + * + * @ticket 45055 + * + * @param bool $expected The value of the key extracted to extracted from given array. + * @param array $arr The array to get last key from. + */ + public function test_array_key_last( $expected, $arr ) { + if ( ! function_exists( 'array_key_last' ) ) { + $this->markTestSkipped( 'array_key_last() is not available.' ); + } else { + $this->assertSame( $expected, array_key_last( $arr ) ); + } + } + + /** + * Data provider for test_array_key_last(). + * + * @return array + */ + public function data_array_key_last() { + return array( + 'string key' => array( + 'expected' => 'key2', + 'arr' => array( + 'key1' => 'val1', + 'key2' => 'val2', + ), + ), + 'int key' => array( + 'expected' => 1, + 'arr' => array( + 99 => 'val1', + 1 => 'val2', + ), + ), + 'no key' => array( + 'expected' => 1, + 'arr' => array( 'val1', 'val2' ), + ), + 'multi array' => array( + 'expected' => 1, + 'arr' => array( + 99 => array( 22 => 'val1' ), + 1 => 'val2', + ), + ), + 'mixed keys' => array( + 'expected' => 1, + 'arr' => array( + 'val1', + 'key2' => 'val2', + 'val3', + ), + ), + 'empty array' => array( + 'expected' => null, + 'arr' => array(), + ), + ); + } +}