[wp-trac] [WordPress Trac] #52534: PHP 8: wp_localize_script() throws a warning if third parameter is a string.

WordPress Trac noreply at wordpress.org
Tue Feb 16 14:46:17 UTC 2021


#52534: PHP 8: wp_localize_script() throws a warning if third parameter is a
string.
-------------------------------------------+------------------------------
 Reporter:  peterwilsoncc                  |       Owner:  (none)
     Type:  defect (bug)                   |      Status:  new
 Priority:  normal                         |   Milestone:  Awaiting Review
Component:  Script Loader                  |     Version:
 Severity:  normal                         |  Resolution:
 Keywords:  php8 has-patch has-unit-tests  |     Focuses:
-------------------------------------------+------------------------------

Comment (by jrf):

 @peterwilsoncc I had a quick look, but to be honest, that warning seems
 100% correct behaviour and warranted.

 Both the documentation of
 [https://developer.wordpress.org/reference/functions/wp_localize_script/
 `wp_localize_script()`] as well as the docs for
 [https://developer.wordpress.org/reference/classes/wp_scripts/localize/
 `WP_Scripts::localize()`] state explicitly that the third parameter is
 (should be) an array, either single or multi-dimensional.

 In other words, passing a `string` as the `$l10n` parameter is a
 programmer error and unsupported behaviour, even though WP is "tolerant"
 of this by doing an `(array) $l10n` in the `foreach()` in
 `WP_Scripts::localize()`.

 Warnings like this exist for good reason: to warn programmers about errors
 they make before those errors can make it into production. They should not
 be avoided.

 If anything, the tolerance for passing the third parameter as a string
 should be removed and replaced by a ''doing it wrong'' warning, but that
 would break BC...

 So, as the warning is kind of obscure, let's look at what the ''actual''
 problem is.
 The problem is in this code snippet - `src/wp-includes/class.wp-
 scripts.php` - line 487 - 493:
 {{{#!php
 <?php
 foreach ( (array) $l10n as $key => $value ) {
         if ( ! is_scalar( $value ) ) {
                 continue;
         }

         $l10n[ $key ] = html_entity_decode( (string) $value, ENT_QUOTES,
 'UTF-8' );
 }
 }}}

 What is happening is that `foreach()` operates on a copy of the array and
 that ''copy'' is the one which is cast to array here: `foreach ( (array)
 $l10n as $key => $value )`.
 But then on line 492, `$l10n[ $key ] = html_entity_decode(...)`, an
 assignment is made to the ''original'' parameter, which is still a string,
 which is the bit which causes the failure.

 The simple solution to this would be to just cast the `$l10n` parameter to
 array ahead of the foreach.
 {{{#!php
 <?php
 $$l10n = (array) $l10n;
 foreach ( $l10n as $key => $value ) {
         if ( ! is_scalar( $value ) ) {
                 continue;
         }

         $l10n[ $key ] = html_entity_decode( (string) $value, ENT_QUOTES,
 'UTF-8' );
 }
 }}}


 Adding any extra code to add support for passing the parameter in an
 unsupported variable type, should IMO be avoided.

 I mean, seriously, this is going down a road where WP would accept any
 parameter type instead of the documented one and will try to make do with
 it by casting and juggling and doing all sorts of magic tricks, which is a
 never-ending road to incredible torture and pain, quite apart from the
 runtime impact all this type of "overhead" code would have...

 P.S.: Very happy to see the tests, though I'd love it if the `string` test
 could be changed to a hard failure... 😇

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/52534#comment:4>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list