Make WordPress Core

Opened 8 months ago

Closed 6 months ago

#59198 closed defect (bug) (fixed)

Bulk actions "Update" ignores Minimum PHP Version Requirement

Reported by: salcode's profile salcode Owned by: costdev's profile costdev
Milestone: 6.3.2 Priority: normal
Severity: critical Version:
Component: Upgrade/Install Keywords: fixed-major
Focuses: Cc:

Description

Background

As described in the Plugin Handbook Header Fields, a plugin can include the Requires PHP header which is

The minimum required PHP version.

WordPress prevents a user from installing a new plugin if the minimum required PHP version is not met and prevents updating a plugin to a newer version, if that newer version requires a PHP version higher than the server is running.

Bug

Using the Bulk actions Update action updates the plugin while ignoring the minimum PHP required version.

Reproduction Steps

WP CLI is useful in reproducing this issue.

I'm also using the plugin https://wordpress.org/plugins/spatie-ray, which requires at these specific versions, which have different PHP minimum requirements.

Plugin VersionPHP Minimum Version
1.4.0 7.3
1.7.4 8.0
  1. On a WordPress 6.3 install running PHP 7.3 (or 7.4) with WP CLI setup
  2. Run the following from the command line to install the plugin at a version compatible with PHP 7.3
    wp plugin install spatie-ray --version=1.4.0
    
  3. Go to /wp-admin/plugins.php and you'll see a message indicating the plugin can not be updated

    There is a new version of Spatie Ray available, but it does not work with your version of PHP. View version 1.7.5 details or learn more about updating PHP.

  4. Check the checkbox in front of the plugin name "Spatie Ray"
  5. From the Bulk actions select box, choose Update
  6. Click the Apply button next to the Bulk actions select box

Expected Behavior

The plugin fails to update because the minimum PHP version requirement is not met.

Actual Behavior

The plugin successfully updates.

Notes

This issue was originally raised as a WP CLI issue, but the root cause appears to be here in WordPress core.

Attachments (6)

59198-plugin-prevent-install.png (142.5 KB) - added by salcode 8 months ago.
The WordPress UI indicating a plugin can not be installed due to the PHP minimum version requirement.
59198-plugin-prevent-update.png (149.8 KB) - added by salcode 8 months ago.
The WordPress UI indicating a plugin can not be updated due to the PHP minimum version requirement.
59198-choosing-plugin-bulk-update.png (249.6 KB) - added by salcode 8 months ago.
Choosing the WordPress plugin bulk update option.
59198-success-despite-php-version.png (117.2 KB) - added by salcode 8 months ago.
Successful update of the plugin despite the minimum PHP version not being met.
plugin-row.png (131.6 KB) - added by afragen 8 months ago.
Plugin row, WP 6.3, PHP 7.4.30
crashed-wp-after-updating-plugin.png (305.4 KB) - added by salcode 8 months ago.
Fatal error displayed after updating to a version of the plugin that requires PHP 8.0, while running PHP 7.3

Download all attachments as: .zip

Change History (38)

@salcode
8 months ago

The WordPress UI indicating a plugin can not be installed due to the PHP minimum version requirement.

@salcode
8 months ago

The WordPress UI indicating a plugin can not be updated due to the PHP minimum version requirement.

@salcode
8 months ago

Choosing the WordPress plugin bulk update option.

@salcode
8 months ago

Successful update of the plugin despite the minimum PHP version not being met.

This ticket was mentioned in PR #5087 on WordPress/wordpress-develop by salcode.


8 months ago
#1

  • Keywords has-patch added

Apply check_package() on bulk plugin update via the "upgrader_source_selection" filter.

This applies the same PHP minimum version checks
on bulk plugin update that are applied on a
single plugin update.

#2 @afragen
8 months ago

Probably best to apply a fix directly and not via a filter.

I’ll try for a closer look tomorrow. Good pick up.

#3 @mukesh27
8 months ago

  • Version 6.3 deleted

Thanks @salcode for the ticket and PR.

The filter approach use in install method.

#4 @afragen
8 months ago

@salcode it would seem a similar patch is required for class-theme-upgrader.php too.

#5 @afragen
8 months ago

In digging into this I see a discrepancy between your images and what I see on an fresh local installation WP 6.3, PHP 7.4.30

@afragen
8 months ago

Plugin row, WP 6.3, PHP 7.4.30

#6 @afragen
8 months ago

The checkbox is removed from https://github.com/WordPress/wordpress-develop/blob/7f38f687c4e45a2a28b214024c50cf145edeae0e/src/wp-admin/includes/class-wp-plugins-list-table.php#L992

Given this I'm not sure how you arrived at your situation with a checkbox present.

#7 @salcode
8 months ago

@afragen Thanks for looking at this and for the feedback.

I suspect you are seeing that screen because you were already on spatie-ray version 1.7.4 before changing your PHP version to 7.4.30.

So the version of the plugin you already have installed (1.7.4) already requires PHP 8.0, which your install does not meet, which causes

  1. The first message "This plugin does not work with your version of PHP." and
  2. disables the checkbox you called out in src/wp-admin/includes/class-wp-plugins-list-table.php on line 992*

If you run the following commands to delete the plugin and re-install it at a version that is compatible with PHP 7.4, you should be able to recreate the original issue for this ticket.

npm run env:cli -- wp plugin delete spatie-ray

npm run env:cli -- wp plugin install spatie-ray --version=1.4.0

*Note: It seems strange that the checkbox is disabled for updating the plugin based on the PHP version of the currently installed plugin (not the version available to update to). I suspect this may need its own ticket.


it would seem a similar patch is required for class-theme-upgrader.php too.

My vote would be to handle the fix in class-theme-upgrader.php as a separate ticket with a separate set of testing steps as validating this fix is tricky enough 😀.

@salcode
8 months ago

Fatal error displayed after updating to a version of the plugin that requires PHP 8.0, while running PHP 7.3

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


8 months ago

#9 @johnbillion
8 months ago

  • Focuses php-compatibility added
  • Keywords needs-testing added
  • Milestone changed from Awaiting Review to 6.4
  • Severity changed from normal to critical

#10 @costdev
8 months ago

  • Focuses php-compatibility removed
  • Keywords changes-requested added

I agree with @afragen that we should handle this directly rather than use a filter. ::install() covers paths that include local file installations, so a filter is more appropriate here.

However, using the filter in ::bulk_upgrade() means downloading and unpacking a package before finding out whether it's supported.

We should be able to save on time, diskspace, memory and cleanup operations like so:

  • $r should already contain requires and requires_php properties.
    • Need to confirm whether these are always set, and whether there's a default value that should also be accounted for.
  • We can pass these values to is_wp_version_compatible() and is_php_version_compatible() respectively.
  • If either isn't compatible, we can set $result to a WP_Error object.

Pseudo:

if not compatible with WP
    result = new WP_Error about WP version
elseif not compatible with php
    result = new WP_Error about PHP version
else
    result = $this->run( ... )



Removing the php-compatibility focus as this pertains to Core's compatibility with PHP versions rather than Core's handling of plugins with PHP version constraints.

Note the description of the focus:

Relating to PHP forward and backwards compatibility. A phpNN keyword identifies the PHP version that introduced the incompatibility

This ticket was mentioned in PR #5116 on WordPress/wordpress-develop by @costdev.


8 months ago
#11

Previously, bulk upgrades did not verify that a plugin package was compatible with the site's WordPress version or the server's PHP version. This could lead to incompatible updates being installed, causing various compatibility issues and errors.

This change implements the following checks:

  • If available, the API response's requires and requires_php values are checked for compatibility. This saves time, diskspace, memory and file operations by failing the upgrade before the package is downloaded and unpacked.
  • If the API check passes, the downloaded and unpacked package is verified using Plugin_Upgrader::check_package() to ensure a plugin file is present, and the plugin's "RequiresWP" and "RequiresPHP" headers are compatible, if present. This ensures that an API/Plugin headers mismatch does not cause an incompatible plugin to be installed.

@afragen commented on PR #5116:


8 months ago
#12

Tested locally and works.

#13 @costdev
8 months ago

  • Keywords changes-requested removed

PR 5116 implements both API response pre-checks as well as ::check_package(). Reasoning is detailed in the PR's description.

Props to @afragen for co-investigation and co-testing.

#14 @salcode
8 months ago

I want to explicitly call out this ticket was originally opened based on this WP CLI GitHub issue and @costdev's patch corrects this WP CLI behavior, as well.

Warning: The PHP version on your server is 7.3.33, however the new plugin version requires 8.0.
+------------+-------------+-------------+--------+
| name       | old_version | new_version | status |
+------------+-------------+-------------+--------+
| spatie-ray | 1.4.0       | 1.7.5       | Error  |
+------------+-------------+-------------+--------+
Error: No plugins updated (1 failed)

Thank you both for your work on this!

#15 @costdev
8 months ago

  • Keywords has-testing-info added

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


8 months ago

#17 @costdev
8 months ago

  • Owner set to costdev
  • Status changed from new to assigned

#18 @iammehedi1
7 months ago

Test Report

This report validates that the indicated patch fixed the issue

Patch tested: https://github.com/WordPress/wordpress-develop/pull/5116

Environment

  • OS: Windows 11 Pro (22H2)
  • Web Server: nginx/1.25.1
  • PHP: 7.4.33
  • WordPress: 6.4-alpha-56267-src
  • Browser: Chrome Version 116.0.5845.98 (Official Build) (64-bit)
  • Theme: Twenty Twenty-Three

Prior to Applying the Patch

  • Error message while updating the plugin: https://i.ibb.co/3Fss4Rb/image.png
  • It eventually updates and leads to fatal error: https://i.ibb.co/8g7zgFf/image.png

After Applying The Patch

  • ✅ 'Update failed' error message comes up while bulk Update - which is correct: https://i.ibb.co/YRmqSf8/image.png

Plugins Used

  • Spatie Ray -Version 1.4.0

#19 @zunaid321
7 months ago

Test Report

This report validates that the indicated patch addresses the issue.

Patch tested: https://github.com/WordPress/wordpress-develop/pull/5116

Environment

  • OS: Windows 11 (22H2)
  • Web Server: nginx/1.25.1
  • PHP: 7.4.33
  • WordPress: 6.4-alpha-56267-src
  • Browser: Chrome Version 113.0.5672.126 (Official Build) (64-bit)
  • Theme: Twenty Twenty-Three
  • Plugins Used: Spatie Ray - v1.4.0

Before Applying The Patch

  • Followed the instructions of @salcode
  • ❌ Fatal error comes up after the plugin is updated in bulk

After Applying The Patch

  • Followed the same instructions.
  • ✅ The folllowing message comes up after the update is initiated in bulk:
  • 'Update failed: The PHP version on your server is 7.4.33, however the new plugin version requires 8.0.'

Supplemental Artifacts

Before the plugin is updated: https://i.imgur.com/w0ueGQs.png

Fatal error shows up after the plugin is updated: https://i.imgur.com/CBIlSrR.png

After the patch is applied, the message shows up: https://i.imgur.com/DFR7oLu.png

Last edited 7 months ago by zunaid321 (previous) (diff)

#20 @costdev
7 months ago

  • Keywords needs-testing removed

PR 5116 has 4 confirmed tests, removing needs-testing.

@johnbillion @azaozz I'm happy to commit this one, but as I wrote the PR, would one of you have time to give it a final review? 🙂

#21 @johnbillion
7 months ago

  • Keywords commit added

#22 @costdev
7 months ago

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

In 56525:

Upgrade/Install: Check plugin compatibility during bulk upgrades.

Previously, bulk upgrades did not verify that a plugin package was compatible with the site's WordPress version or the server's PHP version. This could lead to incompatible updates being installed, causing various compatibility issues and errors.

This change implements the following checks:

  • If available, the API response's requires and requires_php values are checked for compatibility. This saves time, diskspace, memory and file operations by failing the upgrade before the package is downloaded and unpacked.
  • If the API check passes, the downloaded and unpacked package is verified using Plugin_Upgrader::check_package() to ensure a plugin file is present, and the plugin's "RequiresWP" and "RequiresPHP" headers are compatible, if present. This ensures that a mismatch between the API response and the plugin file's headers does not cause an incompatible plugin to be installed.

Props salcode, afragen, mukesh27, iammehedi1, zunaid321, johnbillion, SergeyBiryukov, costdev.
Fixes #59198.

@costdev commented on PR #5116:


7 months ago
#23

Committed in 56525.

#24 @johnbillion
7 months ago

@costdev Do you think this warrants backporting to older branches? As more and more plugins increase their minimum supported PHP version it could help prevent bricking sites on older branches.

#25 @costdev
7 months ago

@johnbillion Certainly in terms of making the older branches more resilient, this could be beneficial to include in the next security/maintenance release. However I'm not sure what the criteria is for non-security backports.

Note that:

  • Plugin_Upgrader::bulk_upgrade() was introduced in 2.8
  • Plugin_Upgrader::check_package() was introduced in 3.3
  • is_wp_version_compatible() and is_php_version_compatible() were introduced in 5.2, so something like these should be used for earlier versions:
// WordPress.
version_compare( explode( '-', $GLOBALS['wp_version'] )[0], $required, '>=' );

// PHP.
version_compare( PHP_VERSION, $required, '>=' )

#26 @johnbillion
7 months ago

  • Keywords fixed-major added; has-patch has-testing-info commit removed
  • Resolution fixed deleted
  • Status changed from closed to reopened

Let's reopen this for discussion about backporting.

#27 @nicolefurlan
6 months ago

With 6.4 RC1 ~2 weeks away, let's keep this discussion going so that we can get any backporting changes in, if we think that is possible and important. (cc component maintainers @costdev and @afragen)

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


6 months ago

#29 @costdev
6 months ago

  • Milestone changed from 6.4 to 6.3.2

#30 @audrasjb
6 months ago

I think it would indeed be nice to backport it to previous releases.
I will backport to 6.3 right now, but for older branches, we'll probably need to adapt the changeset/resolve conflicts with other branches. Probably better to create the changesets ahead of the release.

#31 @joemcgill
6 months ago

I think including this change in the current major release (6.3) makes sense. Adding more resiliency to the upgrade process for previous versions seems like a separate discussion to me.

#32 @audrasjb
6 months ago

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

In 56787:

Upgrade/Install: Check plugin compatibility during bulk upgrades.

Previously, bulk upgrades did not verify that a plugin package was compatible with the site's WordPress version or the server's PHP version. This could lead to
incompatible updates being installed, causing various compatibility issues and errors.

This change implements the following checks:

  • If available, the API response's requires and requires_php values are checked for compatibility. This saves time, diskspace, memory and file operations by

failing the upgrade before the package is downloaded and unpacked.

  • If the API check passes, the downloaded and unpacked package is verified using Plugin_Upgrader::check_package() to ensure a plugin file is present, and the

plugin's "RequiresWP" and "RequiresPHP" headers are compatible, if present. This ensures that a mismatch between the API response and the plugin file's headers does
not cause an incompatible plugin to be installed.

Props salcode, afragen, mukesh27, iammehedi1, zunaid321, johnbillion, SergeyBiryukov, costdev, nicolefurlan, audrasjb, nicolefurlan.
Merges [56525] to the 6.3 branch.
Fixes #59198.

--

_M 6.3
M 6.3/src/wp-admin/includes/class-plugin-upgrader.php

Note: See TracTickets for help on using tickets.