From 695cd019c76bd5b918c0a3241a806f23f2b3a8e0 Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Tue, 13 Sep 2022 15:56:28 +0000 Subject: [PATCH] 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 --- src/wp-includes/class.wp-scripts.php | 9 +++++++-- tests/phpunit/tests/dependencies/scripts.php | 18 +++++------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/wp-includes/class.wp-scripts.php b/src/wp-includes/class.wp-scripts.php index 649f086d60..f20964ead4 100644 --- a/src/wp-includes/class.wp-scripts.php +++ b/src/wp-includes/class.wp-scripts.php @@ -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; } diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index e799247352..9a85ee34f0 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -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' ), ); }