Skip to content
42 changes: 42 additions & 0 deletions src/wp-includes/compat.php
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,48 @@ function array_all( array $array, callable $callback ): bool { // phpcs:ignore U
}
}

if ( ! function_exists( 'array_first' ) ) {
/**
* Polyfill for `array_first()` function added in PHP 8.5.
*
* Returns the first element of an array.
*
* @since 6.9.0
*
* @param array $array The array to get the first element from.
* @return mixed|null The first element of the array, or null if the array is empty.
*/
function array_first( array $array ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound
if ( empty( $array ) ) {
return null;
}

foreach ( $array as $value ) {
return $value;
}
}
}

if ( ! function_exists( 'array_last' ) ) {
/**
* Polyfill for `array_last()` function added in PHP 8.5.
*
* Returns the last element of an array.
*
* @since 6.9.0
*
* @param array $array The array to get the last element from.
* @return mixed|null The last element of the array, or null if the array is empty.
*/
function array_last( array $array ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound
if ( empty( $array ) ) {
return null;
}

return $array[ array_key_last( $array ) ];
}
}

// IMAGETYPE_AVIF constant is only defined in PHP 8.x or later.
if ( ! defined( 'IMAGETYPE_AVIF' ) ) {
define( 'IMAGETYPE_AVIF', 19 );
Expand Down
95 changes: 95 additions & 0 deletions tests/phpunit/tests/compat/arrayFirst.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

/**
* @group compat
*
* @covers ::array_first
*/
class Tests_Compat_arrayFirst extends WP_UnitTestCase {

/**
* @ticket 63853
*
* Test that array_first() is always available (either from PHP or WP).
*/
public function test_array_first_availability(): void {
$this->assertTrue( function_exists( 'array_first' ) );
}

/**
* @ticket 63853
*
* @dataProvider data_array_first
*
* @param mixed $expected The value extracted from the given array.
* @param array $arr The array to get the first value from.
*/
public function test_array_first( $expected, $arr ): void {
$this->assertSame( $expected, array_first( $arr ) );
}


/**
* Data provider.
*
* @return array[]
*/
public function data_array_first(): array {
$obj = new \stdClass();
return array(
'string values' => array(
'expected' => 'a',
'arr' => array( 'a', 'b', 'c' ),
),
'associative array' => array(
'expected' => 10,
'arr' => array(
'foo' => 10,
'bar' => 20,
),
),
'empty array' => array(
'expected' => null,
'arr' => array(),
),
'single element array' => array(
'expected' => 42,
'arr' => array( 42 ),
),
'null values' => array(
'expected' => null,
'arr' => array( null, 'b', 'c' ),
),
'objects' => array(
'expected' => $obj,
'arr' => array(
$obj,
1,
2,
),
),
'boolean values' => array(
'expected' => false,
'arr' => array( false, true, 1, 2, 3 ),
),
);
}

/**
* Test that array_first() returns the pointer is not the first element.
*
* @ticket 63853
*/
public function test_array_first_with_end_pointer() {
$arr = array(
'key1' => 'val1',
'key2' => 'val2',
);
// change the pointer to the last element
end( $arr );

$val = array_first( $arr );
$this->assertSame( 'val2', current( $arr ) );
$this->assertSame( 'val1', $val );
}
}
84 changes: 84 additions & 0 deletions tests/phpunit/tests/compat/arrayLast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

/**
* @group compat
*
* @covers ::array_last
*/
class Tests_Compat_arrayLast extends WP_UnitTestCase {

/**
* @ticket 63853
*
* Test that array_last() is always available (either from PHP or WP).
*/
public function test_array_last_availability(): void {
$this->assertTrue( function_exists( 'array_last' ) );
}

/**
* @ticket 63853
*
* @dataProvider data_array_last
*
* @param mixed $expected The expected last value.
* @param array $arr The array to get the last value from.
*/
public function test_array_last( $expected, $arr ): void {
$this->assertSame( $expected, array_last( $arr ) );
}

/**
* Data provider for array_last().
*
* @return array[]
*/
public function data_array_last(): array {
$obj = new \stdClass();
return array(
'string values' => array(
'expected' => 'c',
'arr' => array( 'a', 'b', 'c' ),
),
'associative array' => array(
'expected' => 20,
'arr' => array(
'foo' => 10,
'bar' => 20,
),
),
'empty array' => array(
'expected' => null,
'arr' => array(),
),
'single element array' => array(
'expected' => 42,
'arr' => array( 42 ),
),
'null values' => array(
'expected' => null,
'arr' => array( 'a', 'b', null ),
),
'objects' => array(
'expected' => $obj,
'arr' => array(
1,
2,
$obj,
),
),
'boolean values' => array(
'expected' => false,
'arr' => array( true, false ),
),
'null values in between' => array(
'expected' => 'c',
'arr' => array( 'a', null, 'b', 'c' ),
),
'empty string values' => array(
'expected' => '',
'arr' => array( 'a', 'b', '' ),
),
);
}
}
Loading