#50913 closed task (blessed) (fixed)
PHP 8.0: various compatibility fixes
Reported by: | jrf | Owned by: | SergeyBiryukov |
---|---|---|---|
Milestone: | 5.6 | Priority: | normal |
Severity: | normal | Version: | |
Component: | General | Keywords: | php8 has-patch has-dev-note |
Focuses: | coding-standards | Cc: |
Description (last modified by )
Once #50902 has been merged, a start can be made to apply fixes to WP core to fix the test failures on PHP 8.0.
Rather than opening a new ticket for every single patch, I'm proposing to use this ticket as an "epic", allowing a variety of small patches each fixing a specific failure to be added to and committed against this ticket.
For patches addressing all instances of failures related to one specific PHP 8.0 change across the codebase, separate tickets should still be opened.
For an example of issues/patches with separate tickets, see:
- #50343 PHP 8: Fix deprecation notices for optional function parameters declared before required parameter
- #50833 PHP 8: GD resources are GdImage object instances
- #50897 PHP 8: fix final private methods
When opening a separate ticket, please tag it with the php8
keyword, so these can be easily found using this report: https://core.trac.wordpress.org/query?keywords=~php8
Attachments (3)
Change History (84)
This ticket was mentioned in PR #472 on WordPress/wordpress-develop by jrfnl.
4 years ago
#2
- Keywords has-patch added
The WP native get_comment()
function expects the first argument $comment
to be passed by reference.
The PHP array_map()
function, however, passes by value, not by reference, resulting in a fatal arguments must be passed by reference, value given
error.
The PHP native array_walk()
function _does_ pass by reference. Using this prevents the fatal error on PHP 8 and maintains the existing behaviour on PHP < 8.
This patch fixes 96 errors + 62 failures + 3 warnings of the test failures on PHP 8.
Refs:
- https://developer.wordpress.org/reference/functions/get_comment/
- https://www.php.net/manual/en/function.array-map.php
- https://www.php.net/manual/en/function.array-walk.php
Trac ticket: https://core.trac.wordpress.org/ticket/50913
This ticket was mentioned in PR #473 on WordPress/wordpress-develop by jrfnl.
4 years ago
#3
As per the documentation of call_user_func_array()
, the $param_arr
should be a (numerically) indexed array, not a string-keyed array.
As we can use the spread operator in PHP 5.6+, there isn't really any need to use call_user_func_array()
anyhow, we can call the array_merge()
function directly.
The caveat to this is that the spread operator only works on numerically indexed arrays, so we need to wrap the $sidebars_widgets
variable in a call to array_values()
when using the spread operator.
Using array_values()
in the existing call_user_func_array()
call would also have solved this, but the solution now proposed, has the added benefit of getting rid of the overhead of call_user_func_array()
.
Refs:
- https://www.php.net/manual/en/function.call-user-func-array
- https://www.php.net/manual/en/function.array-merge
- https://www.php.net/manual/en/function.array-values.php
Trac ticket: https://core.trac.wordpress.org/ticket/50913
@
4 years ago
Fix one fatal "ArgumentCountError: array_merge() does not accept unknown named parameters" error. This patch fixes 5 errors in the unit test run on PHP 8.0.
#6
@
4 years ago
Just noting that when testing 50913-1.patch with PHP 8.0 Beta 2 on my install, the "argument must be passed by reference, value given" message is a warning, rather than a fatal error. I guess it might have changed between Beta 1 and Beta 2. The patch does fix the issue though.
This ticket was mentioned in Slack in #core by hellofromtonya. View the logs.
4 years ago
#11
@
4 years ago
[48960] brings the number of unit test failures down from 331 in build 11258.12 to 23 in build 11268.12.
Still a lot of work ahead, though :)
#13
follow-up:
↓ 14
@
4 years ago
@SergeyBiryukov [48961] should be considered a BC-break and will need a dev-note. Chances are there will be a plugin/theme out there which is relying on the reference for non-object passed parameters. While that will realistically only come into play if the variable they passed to get_comment()
would be regarded as "empty", the fact that the variable will now no longer automatically be filled is a BC-break.
#14
in reply to:
↑ 13
@
4 years ago
Replying to jrf:
[48961] should be considered a BC-break and will need a dev-note.
Thanks, adding the tag. Just noted a few other instances of array_map( 'get_comment', ... )
in core and the tests, and thought this could be a more common pattern than relying on the reference for filling an empty variable, so bringing some consistency with get_post()
would make sense.
A brief search shows that some popular plugins do indeed use array_map( 'get_comment', ... )
.
#16
follow-ups:
↓ 17
↓ 18
@
4 years ago
While testing on PHP 8 I found that any page (home or archive) will return 404 as if there were no posts available. The problem appears to be in wp-includes/class-wp-query.php
at line 762
, where the new Saner string to number comparisons makes it so that "" < 0 === true
, so $qv['p'] < 0
is true
since the default for $qv['p']
is string(0)
.
Changing the condition to intval($qv['p']) < 0
fixes the wrong 404s.
Question: should I open a PR against this ticket for such findings as well or is this ticket for more holistic fixes?
#17
in reply to:
↑ 16
@
4 years ago
Replying to andraganescu:
...the new Saner string to number comparisons makes it so that
"" < 0 === true
Ugh, thinking that's going to be another big "back-compat-fail" thing in PHP 8.0 :(
Question: should I open a PR against this ticket for such findings as well or is this ticket for more holistic fixes?
Thinking a PR would be good, at least for "documentation purposes". Then gather all the "findings" and publish them on make/core. I'm sure the PHP team will publish a "Migration guide" at some point but the sooner plugins authors know what to look for when checking their plugins, the better :)
#18
in reply to:
↑ 16
@
4 years ago
Replying to andraganescu:
While testing on PHP 8 I found that any page (home or archive) will return 404 as if there were no posts available. The problem appears to be in
wp-includes/class-wp-query.php
at line762
, where the new Saner string to number comparisons makes it so that"" < 0 === true
, so$qv['p'] < 0
istrue
since the default for$qv['p']
isstring(0)
.
This was already fixed in [48960] (https://core.trac.wordpress.org/ticket/50913#comment:10)
#20
in reply to:
↑ 12
;
follow-up:
↓ 23
@
4 years ago
Replying to SergeyBiryukov:
In 48961:
After this change, and considering @jrf's comment, should we consider updating map_meta_cap
to take this into account, when no arguments are passed and get_comment( $args[0] )
now produces a notice?
-- https://core.trac.wordpress.org/browser/trunk/src/wp-includes/capabilities.php#L389
This ticket was mentioned in Slack in #core by sergey. View the logs.
4 years ago
This ticket was mentioned in Slack in #core by hellofromtonya. View the logs.
4 years ago
#23
in reply to:
↑ 20
;
follow-up:
↓ 24
@
4 years ago
Replying to jeherve:
After this change, and considering @jrf's comment, should we consider updating
map_meta_cap
to take this into account, when no arguments are passed andget_comment( $args[0] )
now produces a notice?
-- https://core.trac.wordpress.org/browser/trunk/src/wp-includes/capabilities.php#L389
Thanks for bringing this up.
If the notice comes from current_user_can( 'edit_comment' )
, that doesn't seem any different from edit_post
and similar checks:
current_user_can( 'delete_post' )
current_user_can( 'edit_post' )
current_user_can( 'read_post' )
current_user_can( 'publish_post' )
These all require a post ID to check, and will cause a PHP notice if the ID is not provided. Performing these checks without passing in a post ID (or a comment ID, in case of edit_comment
) is a developer error, so I think the notice is legitimate, hiding it would only make debugging harder.
See also: #48415, specifically comment:2:ticket:48415.
#24
in reply to:
↑ 23
@
4 years ago
Replying to SergeyBiryukov:
These all require a post ID to check, and will cause a PHP notice if the ID is not provided. Performing these checks without passing in a post ID (or a comment ID, in case of
edit_comment
) is a developer error, so I think the notice is legitimate, hiding it would only make debugging harder.
Found an existing open ticket for this: #44591, let's add a _doing_it_wrong()
notice there.
#27
@
4 years ago
Just noting that [48973] might need to be reverted to address backward compatibility for wpdb::prepare()
instead, see comment:7:ticket:50639 for more details.
#28
@
4 years ago
Looking at the remaining failures, there is one particular issue in the import tests that's outside of WordPress core:
Function libxml_disable_entity_loader() is deprecated
It needs something like [48789] applied to the WordPress Importer plugin.
Looks like that will need a PR to WordPress Importer on GitHub and then a sync to the SVN repo.
If someone is able to help with that, please do :)
#29
@
4 years ago
Looks like that will need a PR to WordPress Importer on GitHub and then a sync to the SVN repo.
If someone is able to help with that, please do :)
@SergeyBiryukov I already opened a PR for the WordPress Importer issue over a month ago: https://github.com/WordPress/wordpress-importer/pull/78
#34
in reply to:
↑ 10
@
4 years ago
Replying to SergeyBiryukov:
In 48960:
Code Modernization: Correct the check for negative post IDs in
WP_Query::parse_query()
to work as expected on PHP 8.
PHP 8 changes the way string to number comparisons are performed: https://wiki.php.net/rfc/string_to_number_comparison
In particular, checking if an empty string is less than zero in PHP 8 evaluates to
true
, notfalse
.
Just noting that I checked other instances of ... < 0
in core to see if any of them involve an empty string, but it doesn't look like they are affected. Most of them already explicitly cast the left part to (int)
, and the rest are unlikely to contain a string either. If someone would like to double-check that, please do :)
This ticket was mentioned in Slack in #core by sergey. View the logs.
4 years ago
#44
follow-up:
↓ 45
@
4 years ago
I'm also going through some issues reported by PHPStan (see https://github.com/WordPress/wordpress-develop/pull/553), mostly in places where we are passing the incorrect type to WP core or PHP's built-in functions.
@SergeyBiryukov what would be the best way to handle this given the amount of changes that are required? I'm doing one commit per affected file which will hopefully make things easier to include it in core.
#45
in reply to:
↑ 44
;
follow-up:
↓ 58
@
4 years ago
Replying to xknown:
I'm also going through some issues reported by PHPStan (see https://github.com/WordPress/wordpress-develop/pull/553), mostly in places where we are passing the incorrect type to WP core or PHP's built-in functions.
That looks great, thanks!
what would be the best way to handle this given the amount of changes that are required? I'm doing one commit per affected file which will hopefully make things easier to include it in core.
That works for me :)
#49
@
4 years ago
Looking at this failure:
1) Tests_Functions::test_wp_check_filetype_and_ext with data set #13 ('/var/www/tests/phpunit/includ...st.csv', 'test.csv', array('csv', 'text/csv', false)) Failed asserting that two arrays are identical. --- Expected +++ Actual @@ @@ Array &0 ( - 'ext' => 'csv' - 'type' => 'text/csv' + 'ext' => false + 'type' => false 'proper_filename' => false ) /var/www/tests/phpunit/tests/functions.php:1210
It's caused by a change in PHP 8: previously the Fileinfo extension returned the text/plain
MIME type for CSV files, and now it returns application/csv
. wp_check_filetype_and_ext()
does not take that new value into account.
Relevant commits and issues upstream:
- fileinfo: Upgrade to libmagic 5.39
- PR/174: petre: The new CSV file identification is returning "application/csv"
- 0000174: CSV files identified as "application/csv" instead of registered "text/csv"
Per the comments in the issue 174 above, the incorrect type is now fixed and text/csv
should be returned instead. However, it's not quite clear when that fix makes it into the PHP project.
Since it's a safe change that should not affect anything else, I think wp_check_filetype_and_ext()
should be updated to also check for application/csv
, same as it currently does for application/rtf
.
This can be reverted later if the correct text/csv
type makes it into the PHP 8 final release.
#58
in reply to:
↑ 45
;
follow-up:
↓ 60
@
4 years ago
Replying to SergeyBiryukov:
Replying to xknown:
I'm also going through some issues reported by PHPStan (see https://github.com/WordPress/wordpress-develop/pull/553), mostly in places where we are passing the incorrect type to WP core or PHP's built-in functions.
That looks great, thanks!
Created a separate ticket for that: #51423, as this one is getting quite large.
This ticket was mentioned in Slack in #core by sergey. View the logs.
4 years ago
#60
in reply to:
↑ 58
@
4 years ago
Replying to SergeyBiryukov:
Created a separate ticket for that: #51423, as this one is getting quite large.
Sounds good, thanks!
#61
follow-up:
↓ 65
@
4 years ago
With all known unit test issues now addressed, WordPress 5.6 aims to support PHP 8 as much as possible.
Just for the record - and I know @SergeyBiryukov is fully aware of this:
The current test suite covers less than 40% of the WordPress Core code, so that still means that over 60% of the WordPress Core code is currently untested again PHP 8.0 and the PHP 8 compatibility status of the code is unknown.
#62
@
4 years ago
I've just gone through some of the more recent changes to PHP 8.0 and noticed this commit which we may need to account for: https://github.com/php/php-src/commit/5cb8b04646ed99c794c45f8c24fc5c3c7c59e320
TL;DR: Looks like support for MySQL < 5.5 is being dropped in PHP 8.0 when not using mysqlnd
.
This doesn't necessarily mean that WP needs to drop support for those older MySQl versions, but it may warrant a safeguard in the installation routine.
I.e. a check that:
=> If on PHP 8 => and the available MySQL version < 5.5. => make sure the `mysqlnd` driver is available. => Otherwise refuse to install
There may be more places where a check would be warranted. Input welcome.
#65
in reply to:
↑ 61
@
4 years ago
Replying to jrf:
The current test suite covers less than 40% of the WordPress Core code, so that still means that over 60% of the WordPress Core code is currently untested again PHP 8.0 and the PHP 8 compatibility status of the code is unknown.
Right. As shared during the recent weekly dev chat, I think the next steps for PHP 8 support would be:
- Updating the Docker image to use the same PHP extensions for PHP 8 that we have on PHP 7.x:
gd
,mbstring
, etc. There is a PR by @desrosj waiting for review: https://github.com/WordPress/wpdev-docker-images/pull/36. If anyone is able to help with that, please do :) - Fixing some function argument type issues reported by PHPStan (a static analyzer): #51423.
- More testing on PHP 8, expanding test coverage, and creating tickets for any issues found. @andraganescu and @desrosj are working on a call for testing to be published later.
#66
follow-up:
↓ 68
@
4 years ago
Wanted to provide a few updates here.
The PHP 8 wpdev Docker image has been updated to be more inline with the ones for other versions of PHP. There are a few exceptions:
- xDebug is not installed. Support for PHP 8.0 is not yet added, though it is planned for version 3.0.
- The Imagick extension is not installed. The main branch of Imagick does support PHP 8. However, an official version has not been released containing those changes. I inquired about when to expect that tagged version.
I also switched the container being used from devilbox
(which was installing PHP 8.0.0-dev) to the latest one from the official PHP account (8.0 RC1). Since PHP 8 is now in the beta/RC stages, they will be creating containers with each release.
I'll make sure to update the PHP 8 image as each new RC is released. Before starting the Docker container to test on PHP 8, make sure to run npm run env:pull
to ensure you have the most up to date version of the container installed.
The call for testing has also been published: https://make.wordpress.org/core/2020/10/06/call-for-testing-php-8-0/.
This ticket was mentioned in Slack in #core by desrosj. View the logs.
4 years ago
#68
in reply to:
↑ 66
@
4 years ago
Replying to desrosj:
xDebug is not installed. Support for PHP 8.0 is not yet added, though it is planned for version 3.0.
Just to follow up on this, Xdebug 3.0.0beta1 with PHP 8 support has been released:
https://xdebug.org/announcements/2020-10-14
#69
@
4 years ago
Hi, a few days ago I posted a comment in the ticket for unit tests regarding a custom version of PHPUnit 7 I've prepared for WooCommerce, linking here for visibility: https://core.trac.wordpress.org/ticket/50902#comment:20
This ticket was mentioned in Slack in #core by sergey. View the logs.
4 years ago
This ticket was mentioned in PR #618 on WordPress/wordpress-develop by jrfnl.
4 years ago
#74
WordPress should not throw any notices.
array_map()
passes by value, while array_walk()
passes by reference.
The use of array_map()
on line 52 within the export_entries()
method will cause a "Warning: PO::export_entry(): Argument #1 ($entry) must be passed by reference, value given" warning on PHP 8.0 because the export_entry()
method is declared to expect the $entry
object to be passed by reference.
Since PHP 5.0, objects are passed by reference by default and this does not have to be declared in the function signature of a method expecting this anymore.
Also, the code within the method doesn't even try to change $entry
and return a value.
So, all in all, the reference in the function declaration is redundant, old-school and should be removed.
While this could be considered a BC-break, I have done a search for use of this method in plugins and reviewed a significant number of the returned results. None of these would run into trouble with the change now made. Rather this change fixes the same issue for a number of plugins also using array_map()
.
All the same, this change should be mentioned in a dev-note as it is a very small and insignificant BC-break.
Search results: https://wpdirectory.net/search/01EMWBEKAM2B6ECSTCTEDAZGQW
Trac ticket: https://core.trac.wordpress.org/ticket/50913
@
4 years ago
Fixes another "argument # must be passed by reference" issue - see the PR for more information and a passing build + see https://3v4l.org/KbpLJ for proof of issue
#77
@
4 years ago
- Resolution set to fixed
- Status changed from reviewing to closed
Let's call this one fixed for 5.6. Please create new tickets for any follow-up issues.
Thanks everyone!
#80
@
4 years ago
- Keywords has-dev-note added; needs-dev-note removed
Dev note published: https://make.wordpress.org/core/2020/11/23/wordpress-and-php-8-0/
Fix one fatal "argument must be passed by reference, value given" error. This single patch fixes 96 errors + 62 failures in the unit test run on PHP 8.0.