Code Modernization: Fix autovivification from false to array in WP_Scripts::localize().

This function was previously already problematic as it does not do proper input validation, and it has already received tweaks related to PHP 8.0 in [50408] / #52534, which also introduced a `_doing_it_wrong()` notice and added tests.

The short of it is:
* The function expects to receive an `array` for the `$l10n` parameter;
* ...but silently supported the parameter being passed as a `string`;
* ...and would expect PHP to gracefully handle everything else or throw appropriate warnings/errors.

In the previous fix, a `_doing_it_wrong()` notice was added for any non-array inputs. The function would also cause a PHP native "Cannot use a scalar value as an array" warning (PHP < 8.0) or error (PHP 8.0+) for all scalar values, except `false`.

PHP 8.1 deprecated autovivification from `false` to `array`, so now `false` starts throwing an "Automatic conversion of false to array is deprecated" notice.

By rights, the function should just throw an exception when a non-array/string input is received, but that would be a backward compatibility break.

So the current change will maintain the previous behavior, but will prevent both the "Cannot use a scalar value as an array" warning/error as well as the "Automatic conversion of false to array" deprecation notice for invalid inputs.

Invalid inputs ''will'' still receive a `_doing_it_wrong()` notice, which is the reason this fix is considered acceptable.

Includes:
* Adding a test passing an empty array.
* Adding a test to the data provider for a `null` input to make sure that the function will not throw a PHP 8.1 "passing null to non-nullable" notice.

This solves the following PHP 8.1 test error:
{{{
Tests_Dependencies_Scripts::test_wp_localize_script_data_formats with data set #8 (false, '[""]')
Automatic conversion of false to array is deprecated

/var/www/src/wp-includes/class.wp-scripts.php:514
/var/www/src/wp-includes/functions.wp-scripts.php:221
/var/www/tests/phpunit/tests/dependencies/scripts.php:1447
/var/www/vendor/bin/phpunit:123
}}}

Reference: [https://www.php.net/manual/en/migration81.deprecated.php#migration81.deprecated.core.autovivification-false PHP Manual: PHP 8.1 Deprecations: Autovivification from false].

Follow-up to [7970], [18464], [18490], [19217], [50408].

Props jrf, costdev.
See #55656.

git-svn-id: https://develop.svn.wordpress.org/trunk@54142 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Sergey Biryukov
2022-09-13 15:56:28 +00:00
parent b886ab6595
commit 695cd019c7
2 changed files with 12 additions and 15 deletions

View File

@@ -501,12 +501,17 @@ class WP_Scripts extends WP_Dependencies {
),
'5.7.0'
);
if ( false === $l10n ) {
// This should really not be needed, but is necessary for backward compatibility.
$l10n = array( $l10n );
}
}
if ( is_string( $l10n ) ) {
$l10n = html_entity_decode( $l10n, ENT_QUOTES, 'UTF-8' );
} else {
foreach ( (array) $l10n as $key => $value ) {
} elseif ( is_array( $l10n ) ) {
foreach ( $l10n as $key => $value ) {
if ( ! is_scalar( $value ) ) {
continue;
}

View File

@@ -1428,17 +1428,8 @@ JS;
*
* @param mixed $l10n_data Localization data passed to wp_localize_script().
* @param string $expected Expected transformation of localization data.
* @param string $warning Optional. Whether a PHP native warning/error is expected. Default false.
*/
public function test_wp_localize_script_data_formats( $l10n_data, $expected, $warning = false ) {
if ( $warning ) {
if ( PHP_VERSION_ID < 80000 ) {
$this->expectWarning();
} else {
$this->expectError();
}
}
public function test_wp_localize_script_data_formats( $l10n_data, $expected ) {
if ( ! is_array( $l10n_data ) ) {
$this->setExpectedIncorrectUsage( 'WP_Scripts::localize' );
}
@@ -1460,7 +1451,6 @@ JS;
*
* @type mixed $l10n_data Localization data passed to wp_localize_script().
* @type string $expected Expected transformation of localization data.
* @type string $warning Optional. Whether a PHP native warning/error is expected.
* }
*/
public function data_wp_localize_script_data_formats() {
@@ -1471,14 +1461,16 @@ JS;
array( array( 'foo' => array( 'bar' => 'foobar' ) ), '{"foo":{"bar":"foobar"}}' ),
array( array( 'foo' => 6.6 ), '{"foo":"6.6"}' ),
array( array( 'foo' => 6 ), '{"foo":"6"}' ),
array( array(), '[]' ),
// Unofficially supported format.
array( 'string', '"string"' ),
// Unsupported formats.
array( 1.5, '1.5', true ),
array( 1, '1', true ),
array( 1.5, '1.5' ),
array( 1, '1' ),
array( false, '[""]' ),
array( null, 'null' ),
);
}