Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add requires_php to the wp plugin list --update=available output #428

Open
dd32 opened this issue Jul 17, 2024 · 5 comments · May be fixed by #440
Open

Add requires_php to the wp plugin list --update=available output #428

dd32 opened this issue Jul 17, 2024 · 5 comments · May be fixed by #440

Comments

@dd32
Copy link

dd32 commented Jul 17, 2024

The following command can be used to list out plugin updates:

wp plugin list --update=available

but it includes plugins which are incompatible with the current site, due to either the requires or requires_php field values.

It would be helpful to be able to add the following fields to the output if supported:

  • requires_php
  • requires
  • tested
  • requires_plugins (plugin dependencies)

The update API appears to only return requires for no-update plugins and not the requires_php/tested/requires_plugins (this can be fixed) but expanding the data would be helpful.

It would additionally be useful to be able to filter plugins based on those fields, such as --update=available --canbeinstalled or something of the sort, for example, if a plugin requires PHP 8 but I'm running PHP 7.4 I don't want it included. I don't know how best to achieve that.

@mrsdizzie
Copy link
Member

I'd like to work on this, but I'm not sure the premise of this issue is true. Does it actually show available updates where the minimum requirements aren't meant? In my experience, the opposite is true and what I want to address:

WordPress / WP CLI shows there are no updates available, but the reality is the plugin has been updated yet the update can't be installed on the site. I'm not sure the best way to reflect that in the wp cli output.

I'm not sure the best way to add requires requires_php etc.. as listed above because WordPress only provides those details for the very latest version of the plugin published upstream. It isn't possible to get them for any other version. Also I'm not really sure how this works for plugins that aren't in the wordpress.org repo

I would like to figure out the best way to display to a user that there is a newer version of the plugin available upstream, but it can't be installed because either the version of PHP or WordPress is too low. Somewhat related to #436 but I want wp plugin list to do its best possible to let a user know if they are running the latest available version of all plugins currently present on the site (as it used to before requirements were introduced).

So it needs a way to show that there is a newer version available upstream, even if there is no update available for this particular site. I suppose it should also then explain why that newer version is not available. What might that look like?

@dd32
Copy link
Author

dd32 commented Dec 19, 2024

I'd like to work on this, but I'm not sure the premise of this issue is true. Does it actually show available updates where the minimum requirements aren't meant? In my experience, the opposite is true and what I want to address:

Yes, it does.

Prior to WordPress/wordpress-develop@b00097b incompatible updates (WP version) were not shown, but since then the API has returned incompatible-with-your-WP. I believe the site will show a notice to that effect.

The requires_php field is never used on the server-side in the API.

I'm not sure the best way to add requires requires_php etc.. as listed above because WordPress only provides those details for the very latest version of the plugin published upstream. It isn't possible to get them for any other version. Also I'm not really sure how this works for plugins that aren't in the wordpress.org repo

This is not an issue; The needed fields are exposed in the API, and probably stored in the core transient.

Example:

curl https://api.wordpress.org/plugins/update-check/1.1/ --data 'plugins={"plugins":{"edit-flow/edit-flow.php":{"Name":"Edit+Flow","Version":"0.9.8"}},"active":["edit-flow/edit-flow.php"]}&translations={}&locale=[]&all=true' | jq
{
  "plugins": {
    "edit-flow/edit-flow.php": {
      "id": "w.org/plugins/edit-flow",
      "slug": "edit-flow",
      "plugin": "edit-flow/edit-flow.php",
      "new_version": "0.9.9",
      "url": "https://wordpress.org/plugins/edit-flow/",
      "package": "https://downloads.wordpress.org/plugin/edit-flow.0.9.9.zip",
      "icons": {
        "default": "https://s.w.org/plugins/geopattern-icon/edit-flow_6a393c.svg"
      },
      "banners": {
        "1x": "https://ps.w.org/edit-flow/assets/banner-772x250.png?rev=487217"
      },
      "banners_rtl": [],
      "requires": "6.0",
      "tested": "6.5.5",
      "requires_php": "8.0",
      "requires_plugins": [],
      "compatibility": [],
      "upgrade_notice": "<p>Bump minimum PHP supported version to 8.0, WordPress minimum supported version to 6.0.</p>"
    }
  },
  "translations": [],
  "no_update": []
}

@mrsdizzie
Copy link
Member

mrsdizzie commented Dec 19, 2024

(sorry for longer response but thanks for encouraging me to look into it deeper)

I'm not able to reproduce wp cli showing me updates for a plugin where the php / wp requirements are not met when I run wp plugin list or wp plugin list --update=available. Do you happen to have a specific version of wp and a plugin to be able to reproduce this behavior?

Looking into what the code actually does, here is what I can say about how it works and why wp cli currently does not show an update available when it doesn't meet wp / php requirements:

As you say, wp cli doesn't call the API directly, it uses the function wp_update_plugins from WordPress core. The response from the API server seems to already check requirements, and if they are not met it puts the upstream plugin details inside of the no_update array. This is then saved to the transient mostly as-is by wp_update_plugins. Here is a slimmed down API call that suggests it is already filtered server side based on requirements:

$ curl 'http://api.wordpress.org/plugins/update-check/1.1/' -X POST -H 'Host: api.wordpress.org' -H 'User-Agent: WordPress/6.4.2; http://macbook.local/' -H 'Accept: */*' -H 'Connection: close' -H 'Content-Type: application/x-www-form-urlencoded' --data-raw 'plugins={
    "plugins": {
        "wp-super-cache/wp-cache.php": {
            "Name": "WP Super Cache",
            "PluginURI": "https://wordpress.org/plugins/wp-super-cache/",
            "Version": "1.9.4",
            "Description": "Very fast caching plugin for WordPress.",
            "Author": "Automattic",
            "AuthorURI": "https://automattic.com/",
            "TextDomain": "wp-super-cache",
            "DomainPath": "",
            "Network": false,
            "RequiresWP": "",
            "RequiresPHP": "",
            "UpdateURI": "",
            "Title": "WP Super Cache",
            "AuthorName": "Automattic"
        }
    },
    "active": []
}&translations=[]&locale=[]&all=true' | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1515    0   803  100   712  11795  10458 --:--:-- --:--:-- --:--:-- 22279
{
  "plugins": [],
  "translations": [],
  "no_update": {
    "wp-super-cache/wp-cache.php": {
      "id": "w.org/plugins/wp-super-cache",
      "slug": "wp-super-cache",
      "plugin": "wp-super-cache/wp-cache.php",
      "new_version": "1.12.4",
      "url": "https://wordpress.org/plugins/wp-super-cache/",
      "package": "http://downloads.wordpress.org/plugin/wp-super-cache.1.12.4.zip",
      "icons": {
        "2x": "https://ps.w.org/wp-super-cache/assets/icon-256x256.png?rev=1095422",
        "1x": "https://ps.w.org/wp-super-cache/assets/icon-128x128.png?rev=1095422"
      },
      "banners": {
        "2x": "https://ps.w.org/wp-super-cache/assets/banner-1544x500.png?rev=1082414",
        "1x": "https://ps.w.org/wp-super-cache/assets/banner-772x250.png?rev=1082414"
      },
      "banners_rtl": [],
      "requires": "6.5",
      "tested": "6.6.2",
      "requires_php": "7.0",
      "requires_plugins": [],
      "compatibility": []
    }
  }
}

wp cli then reads the update_plugins transient that the core function set:

// Force WordPress to check for updates if `--skip-update-check` is not passed.
if ( false === (bool) Utils\get_flag_value( $assoc_args, 'skip-update-check', false ) ) {
call_user_func( $this->upgrade_refresh );
}

protected function get_update_info() {
return get_site_transient( $this->upgrade_transient );
}

However, wp cli only really checks inside the [response] array for the transient to see if there are updates available -- so it never sees any update details within the no_update section:

$update_info = ( isset( $all_update_info->response[ $file ] ) && null !== $all_update_info->response[ $file ] ) ? (array) $all_update_info->response[ $file ] : null;

So you end up with an object like this:

stdClass Object
(
    [last_checked] => 1734626062
    [response] => Array
        (
            [akismet/akismet.php] => stdClass Object
                (
                    [id] => w.org/plugins/akismet
                    [slug] => akismet
                    [plugin] => akismet/akismet.php
                    [new_version] => 5.3.5
                    [url] => https://wordpress.org/plugins/akismet/
                    [package] => https://downloads.wordpress.org/plugin/akismet.5.3.5.zip
                    [icons] => Array
                        (
                            [2x] => https://ps.w.org/akismet/assets/icon-256x256.png?rev=2818463
                            [1x] => https://ps.w.org/akismet/assets/icon-128x128.png?rev=2818463
                        )

                    [banners] => Array
                        (
                            [2x] => https://ps.w.org/akismet/assets/banner-1544x500.png?rev=2900731
                            [1x] => https://ps.w.org/akismet/assets/banner-772x250.png?rev=2900731
                        )

                    [banners_rtl] => Array
                        (
                        )

                    [requires] => 5.8
                    [tested] => 6.7.1
                    [requires_php] => 5.6.20
                    [requires_plugins] => Array
                        (
                        )

                )

        )

    [translations] => Array
        (
        )

    [no_update] => Array
        (
            [hello.php] => stdClass Object
                (
                    [id] => w.org/plugins/hello-dolly
                    [slug] => hello-dolly
                    [plugin] => hello.php
                    [new_version] => 1.7.2
                    [url] => https://wordpress.org/plugins/hello-dolly/
                    [package] => https://downloads.wordpress.org/plugin/hello-dolly.1.7.3.zip
                    [icons] => Array
                        (
                            [2x] => https://ps.w.org/hello-dolly/assets/icon-256x256.jpg?rev=2052855
                            [1x] => https://ps.w.org/hello-dolly/assets/icon-128x128.jpg?rev=2052855
                        )

                    [banners] => Array
                        (
                            [2x] => https://ps.w.org/hello-dolly/assets/banner-1544x500.jpg?rev=2645582
                            [1x] => https://ps.w.org/hello-dolly/assets/banner-772x250.jpg?rev=2052855
                        )

                    [banners_rtl] => Array
                        (
                        )

                    [requires] => 4.6
                )

            [wp-super-cache/wp-cache.php] => stdClass Object
                (
                    [id] => w.org/plugins/wp-super-cache
                    [slug] => wp-super-cache
                    [plugin] => wp-super-cache/wp-cache.php
                    [new_version] => 1.12.4
                    [url] => https://wordpress.org/plugins/wp-super-cache/
                    [package] => https://downloads.wordpress.org/plugin/wp-super-cache.1.12.4.zip
                    [icons] => Array
                        (
                            [2x] => https://ps.w.org/wp-super-cache/assets/icon-256x256.png?rev=1095422
                            [1x] => https://ps.w.org/wp-super-cache/assets/icon-128x128.png?rev=1095422
                        )

                    [banners] => Array
                        (
                            [2x] => https://ps.w.org/wp-super-cache/assets/banner-1544x500.png?rev=1082414
                            [1x] => https://ps.w.org/wp-super-cache/assets/banner-772x250.png?rev=1082414
                        )

                    [banners_rtl] => Array
                        (
                        )

                    [requires] => 6.5
                    [tested] => 6.6.2
                    [requires_php] => 7.0
                    [requires_plugins] => Array
                        (
                        )

                )

        )

    [checked] => Array
        (
            [akismet/akismet.php] => 5.3
            [hello.php] => 1.7.2
            [wp-super-cache/wp-cache.php] => 1.9.4
        )

)

And wp cli output like this:

+----------------+----------+-----------+---------+----------------+-------------+
| name           | status   | update    | version | update_version | auto_update |
+----------------+----------+-----------+---------+----------------+-------------+
| akismet        | inactive | available | 5.3     | 5.3.5          | off         |
| hello          | inactive | none      | 1.7.2   |                | off         |
| wp-super-cache | inactive | none      | 1.9.4   |                | off         |
+----------------+----------+-----------+---------+----------------+-------------+

So wp cli says none for a WP Super Cache update even though there is a newer version of WP Super Cache available upstream. Looking at this output, you would think 1.9.4 is the latest release.

This is where my confusion with the initial issue description in, because it suggests that wp cli is showing these updates as available even though they don't meet requirements. In my example above, it is not showing them specifically because they didn't meet wp / php requirements when the API was called initially via WordPress core.

So I consider the problem to be that it doesn't mention a newer version at all, when it should have a message saying that an update is available but you can't install it. Again, I'd be interested in an example to reproduce the original issue claim that the opposite happens. I could imagine there is some case where the API does not do the check server side and does return an update available -- but I haven't seen that.

So for the problem of wp cli not showing newer releases:

Earlier I said wp cli 'mostly' doesn't look in [no_update] above because it does have some code for looking inside no_update

if ( null === $update_info ) {
// Get info for all plugins that don't have an update.
$plugin_update_info = isset( $all_update_info->no_update[ $file ] ) ? $all_update_info->no_update[ $file ] : null;
// Compare version and update information in plugin list.
if ( null !== $plugin_update_info && version_compare( $details['Version'], $plugin_update_info->new_version, '>' ) ) {
$items[ $file ]['update'] = static::INVALID_VERSION_MESSAGE;
}
}
}

But that seems to be for checking if the local version installed is higher than the listed version (not the other way around) and displaying the version higher than expected message which warns the the local version is newer than the one available from wp.org.

So for the problem of telling a user that a newer version exists but that they can't install it, more code should be added to this section which checks if there is a newer version inside [no_update], and if so will check requires_php and requires with the assumption that one of them won't pass.

Then my question would be, how to we display that to a user? Just a warning in the already existing update_available column that says something like "Newer version available but it requires a higher php|wp"?

The overall problem to fix here is the same regardless: how to update the wp cli interface to communicate various aspects of php/wp requirements and when they affect what a user can do. This also brings up how to display requires_php etc... In the example above, wp cli lists 1.9.4 as the current WP Super Cache version but the wporg api is only going to provide requires_php for the latest version, which is 1.12.4 upstream. So how do we handle showing requires_php for plugins that aren't on the latest version if wporg only provides those details for the latest version? What would a requires_php column look like for the example above?

@mrsdizzie
Copy link
Member

OK I think I understand my confusion. The original issue says:

it includes plugins which are incompatible with the current site, due to either the requires or requires_php field values.

And I said it doesn't, but it is true in the case of requires_php. My example was just being held back because of requires but not requires_php:

The wordpress.org API seems to filter responses based on the provided WordPress version in the headers, but not the PHP version (since WordPress doesn't send that to the wordpress.org API servers). So wp cli will show updates that don't pass requires_php but it won't show updates that don't pass requires. This is because the wordpress.org API has already filtered plugins that don't meet requires into a separate no_update section.

Using the edit-flow example, I can indeed reproduce it offering to install the latest version which requires PHP 8 while using PHP 7.4. I can even see the update offer go away by downgrading WordPress core to a version lower than requires:

$ php -v
PHP 7.4.33 (cli) (built: Oct 16 2024 16:24:05) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

$ wp transient delete --all; wp plugin list
Success: No transients found.
+----------------------------+----------+-----------+----------+----------------+-------------+
| name                       | status   | update    | version  | update_version | auto_update |
+----------------------------+----------+-----------+----------+----------------+-------------+       |
| edit-flow                  | active   | available | 0.9.8    | 0.9.9          | off         |

$ wp core download --version=5.9 --force
Downloading WordPress 5.9 (en_US)...
Success: WordPress downloaded.

$ wp transient delete --all; wp plugin list
Success: No transients found.
+----------------------------+----------+-----------+----------+----------------+-------------+
| name                       | status   | update    | version  | update_version | auto_update |
+----------------------------+----------+-----------+----------+----------------+-------------+
| edit-flow                  | active   | none      | 0.9.8    |                | off         |

So this should be addressed in wp cli in two places:

wp cli needs to manually check the requires_php of any plugin that is listed as having an update available to see if it should really be installed.

wp cli needs to also check that an update hasn't already been filtered into no_update by the API server via WordPress core.

Then in both cases it can show an appropriate message that while there is a new upstream version, that update isn't available because of missing requirements

@mrsdizzie
Copy link
Member

I put up #440 which should fix this issue. I included the specific example in the original report as one of the new test cases

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants