Make WordPress Core

Opened 17 months ago

Closed 13 months ago

Last modified 8 months ago

#54730 closed task (blessed) (fixed)

PHP 8.x: various compatibility fixes for WordPress 6.0

Reported by: hellofromtonya's profile hellofromTonya Owned by:
Milestone: 6.0 Priority: normal
Severity: normal Version:
Component: General Keywords: php8 php81 has-patch has-unit-tests
Focuses: coding-standards Cc:

Description

Previously:

This ticket will be used 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 version (such as PHP 8.0, 8.1, or 8.2) change across the codebase, separate tickets should still be opened.

For an example of issues/patches with separate tickets, see:

  • #53299 PHP 8.1: Update is_serialized function to accept Enums
  • #53465 PHP 8.1.: the default value of the flags parameter for htmlentities() et all needs to be explicitly set

When opening a separate ticket, please tag it with the appropriate PHP version keyword so that these tickets can be easily found:

Attachments (1)

53635-09-script-translations.patch (2.0 KB) - added by Chouby 16 months ago.

Download all attachments as: .zip

Change History (25)

This ticket was mentioned in PR #1801 on WordPress/wordpress-develop by anomiex.


17 months ago
#1

  • Keywords has-patch added

This fixes a "Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated" warning on PHP 8.1.

PHP has started requiring that built-in method arguments that are not explicitly declared as nullable may no longer be passed null. In this case it seems to make more sense to avoid calling WordPress's own email_exists() function with null, as that method is declared as taking only strings and a null email is never going to exist anyway.

Trac ticket: https://core.trac.wordpress.org/ticket/54730

hellofromtonya commented on PR #1801:


17 months ago
#2

I see that you've closed https://core.trac.wordpress.org/ticket/53635 without addressing the issue this PR fixes. What's the way forward now?

@anomiex Trac ticket https://core.trac.wordpress.org/ticket/54730 is now open for continuing PHP 8.x compatibility fixes during the 6.0 cycle. I updated the description in this PR to point at the new ticket.

This ticket was mentioned in PR #1556 on WordPress/wordpress-develop by jrfnl.


17 months ago
#3

  • Keywords has-unit-tests added

Fixes strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated notices on PHP 8.1.

Impact: 38 of the pre-existing tests are affected by this issue.

Note: trac ticket link below not added yet on purpose while this ticket is still WIP.

Trac ticket: https://core.trac.wordpress.org/ticket/54730

Update: Though this is WIP, adding the new 6.0 ticket to ensure this PR moves forward in the 6.0 cycle.

This ticket was mentioned in PR #1658 on WordPress/wordpress-develop by jrfnl.


17 months ago
#4

Potential fix for the below issue, but the fix _may_ have unforeseen side-effects. Needs second opinion from someone with detailed domain knowledge of the XMLRPC functionality.

Tests_XMLRPC_mw_newPost::test_post_thumbnail
strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated

path/to/src/wp-includes/class-wp-xmlrpc-server.php:5681
path/to/src/wp-includes/src/wp-includes/class-wp-xmlrpc-server.php:5606
path/to/tests/phpunit/tests/xmlrpc/mw/newPost.php:147

Trac ticket: https://core.trac.wordpress.org/ticket/54730

Update: Changed the Trac ticket to the 6.0 one.

#5 @hellofromTonya
17 months ago

Dropping [51968] as a reminder of ongoing architectural decisions needed to resolve remaining known deprecation notices

This changeset ignores (on purpose) "null to nullable" deprecations for select tests. Why? Here are the details:

Adds an expectation for PHP 8.1 "passing null to non-nullable" deprecation notice to select tests where the deprecation is generated by one of the functions in the wp-includes/formatting.php file, either via a filter hook callback or by a direct call.

Instead of haphazardly fixing these issues exposed by the tests, a more structural and all-encompassing solution for input validation should be architected and implemented as otherwise, we'll keep running into similar issues time and again with each new PHP version.

To discourage people from "fixing" these issues now anyway, this commit "hides" nearly all of these issues from the test runs.

Once a more structural solution is designed, these tests and the underlying functions causing the deprecation notices should be revisited and the structural solution put in place.

This ticket was mentioned in PR #2133 on WordPress/wordpress-develop by hellofromtonya.


17 months ago
#6

The PHP native trim() function expects to be passed a string and it is not a nullable parameter. Passing null to it will result in a trim(): Passing null to parameter #1 ($string) of type string is deprecated notice on PHP 8.1.

In the WP_User::get_data_by() static method, the value given is expected to be int or string. However no input validation was done for fields other than the id field.

This PR adds input validation for the field $value to ensure it is a scalar type and if no, bails out returning false. Why is_scalar()? For backwards-compatible, the native behavior of trim() is retained as it coerces non-string scalar types into a string.

Trac ticket: https://core.trac.wordpress.org/ticket/54730

References:

#7 @costdev
17 months ago

Related ticket: #54826

#8 @SergeyBiryukov
17 months ago

In 52585:

Upgrade/Install: Check if the disk_free_space() function exists before calling it.

In PHP 8+, @ no longer suppresses fatal errors:

The @ operator will no longer silence fatal errors (E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR, E_PARSE).

Reference: PHP 8: Backward Incompatible Changes.

disk_free_space() may be disabled by hosts, which will throw a fatal error on a call to undefined function.

This change prevents the fatal error, and falls back to false when disk_free_space() is unavailable.

Follow-up to [25540], [25774], [25776], [25831], [25869].

Props costdev, jrf, swb1192, SergeyBiryukov.
Fixes #54826. See #54730.

#9 @JavierCasares
17 months ago

If helps, I set up the "wpsabot" account for PHP 8.1 + MariaDB 10.6 (latest versions for everything)

Errors be like: https://make.wordpress.org/hosting/test-results/r52620/wpsabot-r52620/

I'm no expert doing tests, but if I can help, please, ask :)

#10 @Chouby
16 months ago

As #53635 was closed, I tentatively re-propose 53635-09-script-translations.patch to avoid notices in untrailingslashit() due to the default value of the script translations path being null instead of an empty string.
Also it's worth noticing that the doc blocks don't document null as an accepted value for the path.

anomiex commented on PR #1801:


16 months ago
#11

Looks like #2133 will fix this too, by making the called functions no longer object to being passed null. If that gets merged, this can be closed.

hellofromtonya commented on PR #1801:


16 months ago
#12

Looks like https://github.com/WordPress/wordpress-develop/pull/2133 will fix this too, by making the called functions no longer object to being passed null. If that gets merged, this can be closed.

Once #2133 gets merged, then yes, it will resolve this PR's deprecation notice without further changes. Plus #2133 resolves the issue at the lower level, i.e. where the deprecation notice is triggered. I think overall this PR can be closed in favor of #2133.

Note: There's an improvement opportunity, though out of scope for the purpose of this PR:

  • Guard email_exists() to invoke get_user_by() only when a string type is passed to email_exists(), i.e. providing a teeny tiny micro-optimization when a non-string is passed. (This tweak deserves a separate PR and tests.)

This ticket was mentioned in PR #2359 on WordPress/wordpress-develop by d-claassen.


15 months ago
#13

This makes sure that wp_mail will not run into a PHP 8.1 null to non-nullable deprecation error when network_home_url returns an invalid url. I focussed on keeping the old implementation 100% intact to ensure that any functions hooked into the wp_mail_from filter and relying a potentially invalid from address won't be affected.

Trac ticket: https://core.trac.wordpress.org/ticket/54730

#14 @dennisatyoast
15 months ago

I've created a PR to prevent an 8.1 null to non-nullable deprecation in wp_mail. I've already discussed this fix with @jrf.

SergeyBiryukov commented on PR #2359:


15 months ago
#15

Thanks for the PR!

Just a minor note that closures like this:

add_filter(
	'network_home_url',
	function( $url ) {
		return '';
	}
);

can be simplified by using __return_empty_string() as a callback:

add_filter( 'network_home_url', '__return_empty_string' );

It has the same effect but looks a bit cleaner. I can adjust this on commit.

#16 @SergeyBiryukov
15 months ago

In 52799:

Code Modernization: Check the return type of wp_parse_url() in wp_mail().

As per the PHP manual:

If the component parameter is omitted, an associative array is returned.
If the component parameter is specified, parse_url() returns a string (or an int, in the case of PHP_URL_PORT) instead of an array. If the requested component doesn't exist within the given URL, null will be returned.

Reference: PHP Manual: parse_url(): Return Values

In PHP 8.1, if the home URL does not have a "host" component, it would lead to a substr(): Passing null to parameter #1 ($string) of type string is deprecated notice.

Changing the logic around and adding validation for the return type value of wp_parse_url() prevents that.

Follow-up to [48601], [51606], [51622], [51626], [51629], [51630].

Props dennisatyoast, jrf.
See #54730.

#18 follow-up: @SergeyBiryukov
15 months ago

Looking at [48601], it seems that some other functions need the same fix as in [52799], since they were all changed to use wp_parse_url( network_home_url(), PHP_URL_HOST ):

  • wpmu_signup_blog_notification()
  • wpmu_signup_user_notification()
  • wpmu_welcome_notification()
  • wpmu_welcome_user_notification()
  • wp_notify_postauthor()

#19 in reply to: ↑ 18 @jrf
15 months ago

Replying to SergeyBiryukov:

Looking at [48601], it seems that some other functions need the same fix as in [52799], since they were all changed to use wp_parse_url( network_home_url(), PHP_URL_HOST ):

  • wpmu_signup_blog_notification()
  • wpmu_signup_user_notification()
  • wpmu_welcome_notification()
  • wpmu_welcome_user_notification()
  • wp_notify_postauthor()

Yes, I started reviewing all uses of [wp_]parse_url() a while back, but there are a LOT of them, so I didn't manage to finish that yet.

I can provide a list of what still needs reviewing with a lot of things filtered out already if it helps.

#20 @SergeyBiryukov
15 months ago

In 52800:

Tests: Rename the $success variable to $result in the wp_mail() test for an empty home URL.

The previously name could be a bit confusing if the function is expected to fail.

Follow-up to [52799].

See #54730.

This ticket was mentioned in Slack in #core by costdev. View the logs.


13 months ago

#22 @hellofromTonya
13 months ago

  • Resolution set to fixed
  • Status changed from new to closed

6.0's last beta is happening now and RC1 is tomorrow. I opened #55656 to continue PHP 8.x cross-compatibility work during the next cycle. I'll close this ticket.

Thank you everyone for your contributions!

SergeyBiryukov commented on PR #1658:


8 months ago
#23

Thanks for the PR! I believe this was superseded by #3187.

jrfnl commented on PR #1658:


8 months ago
#24

I believe this was superseded by #3187.

Correct. Thanks for getting the improved version merged!

Note: See TracTickets for help on using tickets.