Skip to content

fix(checks): validate each Requires Plugins dependency individually#1391

Open
faisalahammad wants to merge 2 commits into
WordPress:trunkfrom
faisalahammad:fix/1385-multiple-plugin-dependencies
Open

fix(checks): validate each Requires Plugins dependency individually#1391
faisalahammad wants to merge 2 commits into
WordPress:trunkfrom
faisalahammad:fix/1385-multiple-plugin-dependencies

Conversation

@faisalahammad

@faisalahammad faisalahammad commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Plugin Check currently validates the Requires Plugins header as a single comma-separated blob, so a plugin declaring more than one dependency gets one generic "header is not valid" error with no indication of which slug is the problem, or whether the declared dependency actually exists in the WordPress.org plugin directory. This updates Plugin_Header_Fields_Check to validate each declared dependency individually and report its status on its own.
Fixes #1385

Changes

includes/Checker/Checks/Plugin_Repo/Plugin_Header_Fields_Check.php

Before:

if ( ! preg_match( '/^[a-z0-9-]+(?:,\s*[a-z0-9-]+)*$/', $plugin_header['RequiresPlugins'] ) ) {
    // one error for the entire header, doesn't say which slug is bad
}

After:

private function check_requires_plugins_header( Check_Result $result, string $requires_plugins, string $label, string $plugin_main_file ) {
    $slugs = array_map( 'trim', explode( ',', $requires_plugins ) );

    foreach ( $slugs as $slug ) {
        if ( '' === $slug ) {
            continue;
        }

        if ( ! preg_match( '/^[a-z0-9]+(?:-[a-z0-9]+)*$/', $slug ) ) {
            // error naming this specific slug
            continue;
        }

        $this->check_requires_plugins_slug_status( $result, $slug, $plugin_main_file );
    }
}

Each malformed slug is now reported as its own error, naming the slug. Each validly formatted slug is checked against the WordPress.org plugin directory (via https://api.wordpress.org/plugins/info/1.0/{slug}.json, transient-cached for a day): a warning is added if the slug can't be found there (covers both nonexistent and closed/removed plugins, since the directory API returns an error key for both). If the directory API can't be reached, the check skips silently rather than risk a false positive.

Why: Plugin authors declaring multiple dependencies had no way to tell which one was wrong. ernilambar pointed out in review that checking local install/active state isn't this check's job — a plugin_repo category check should validate repo-readiness, i.e. whether the declared slug actually exists in the WordPress.org directory, since a parent plugin missing from the directory means the child plugin can't be published there either. The original approach (checking is_plugin_inactive() against the local scan environment) has been replaced entirely with this directory-existence check.

Testing

Test 1: Multiple invalid slugs are reported individually

  1. Set Requires Plugins: Example Plugin, OtherPlugin in a test plugin's header.
  2. Run Plugin Check against it.
    Result: two separate errors, one naming "Example Plugin" and one naming "OtherPlugin", instead of a single generic message.

Test 2: Valid multi-dependency header passes format validation

  1. Set Requires Plugins: woocommerce, contact-form-7.
  2. Run Plugin Check.
    Result: no plugin_header_invalid_requires_plugins errors.

Test 3: Dependency directory-existence warnings

  1. Set Requires Plugins: plugin-check, hello-dolly, not-a-real-plugin.
  2. Run Plugin Check.
    Result: warning naming not-a-real-plugin as not found in the WordPress.org plugin directory; no warning for plugin-check or hello-dolly (both published there).

Updated PHPUnit tests in tests/phpunit/tests/Checker/Checks/Plugin_Header_Fields_Check_Tests.php (transients are seeded directly in tests rather than mocking the HTTP call, matching the existing convention used for Version_Utils/RequiresWP in the same file/class). Full suite (482 tests) passes, phpcs and phpstan clean.

Open WordPress Playground Preview

- Report a separate error per malformed slug in the Requires Plugins
  header, naming the offending slug, instead of one generic message
  for the whole comma-separated value
- Add a warning per declared dependency that is not installed or not
  active in the environment the check runs in

This gives plugin authors clear, per-dependency feedback when they
declare more than one plugin dependency, instead of a single vague
error covering the entire header.

Fixes WordPress#1385
@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: faisalahammad <faisalahammad@git.wordpress.org>
Co-authored-by: davidperezgar <davidperez@git.wordpress.org>
Co-authored-by: ernilambar <nilambar@git.wordpress.org>
Co-authored-by: tushar-addweb <tusharaddweb@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@davidperezgar

Copy link
Copy Markdown
Member

Thanks for the contribution. I see reasonable.

@ernilambar

Copy link
Copy Markdown
Member

I think PR is following incorrect approach. Checking whether parent plugin is installed/active or not the responsibility of PCP or the actual check it was intended. We should check of that slug is active and published in the WordPress.org directory.
Like if "parent-plugin" is not there in the directory, child plugin will not even published in the directory. This is what the check should be focused.

@faisalahammad

faisalahammad commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback, this makes sense. I agree checking local install/active state is not the right job for a plugin_repo check.

Pushed an update (689a1a1): the check now queries the WordPress.org plugin directory (api.wordpress.org/plugins/info/1.0/{slug}.json, cached in a transient for a day, same pattern the existing Requires at least header validation already uses in this file) and warns only when the declared slug can't be found there. That covers both nonexistent slugs and closed/removed plugins, since the directory API returns an error key for both cases. Local install/active check is removed entirely, nothing left checking runtime state.

If the API is unreachable the check skips silently rather than risk a false positive, same convention as the existing WP-version check.

Check no longer inspects local install/active state, per ernilambar's
review feedback that this isn't the responsibility of a plugin_repo
check. Each declared dependency slug is now looked up against the
WordPress.org plugin directory API instead, warning only when the
slug can't be found there (covers nonexistent and closed plugins).
API calls are transient-cached and fail silently when unreachable.

Refs WordPress#1391
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement: Support checking and reporting multiple dependent plugins

3 participants