Skip to content

fix(traits): collapse File_Editor_URL to a single filter - #1417

Open
faisalahammad wants to merge 3 commits into
WordPress:trunkfrom
faisalahammad:fix/314-single-filter
Open

fix(traits): collapse File_Editor_URL to a single filter#1417
faisalahammad wants to merge 3 commits into
WordPress:trunkfrom
faisalahammad:fix/314-single-filter

Conversation

@faisalahammad

@faisalahammad faisalahammad commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

What?

Closes #314

The File_Editor_URL trait previously exposed two filters (..._file_editor_url_template and ..._file_path) that consumers had to register together to override the editor link. This refactor collapses them into a single filter, wp_plugin_check_validation_error_source_url, that receives a $source array and returns either a URL string or null to fall back to the plugin editor.

Why?

Felix Arntz called out in PR #298 review that the two-filter chain is overly complex for IDE integrations. This PR addresses the followup explicitly filed as issue #314.

The {{file}} placeholder is now substituted with the raw filesystem path (no URL encoding) so URI schemes like vscode://file/{{file}}:{{line}} resolve correctly. {{line}} is substituted with the integer line number. Returning a string without placeholders is used verbatim.

How?

  • Replaced the two apply_filters calls with a single apply_filters( 'wp_plugin_check_validation_error_source_url', null, $source ) that gives the consumer everything it needs in one callback.
  • Inline-substitute {{file}} and {{line}} inside the trait from the same $source array.
  • The plugin-editor fallback path is unchanged; line= is still only appended when $line > 0.
  • Public method signature get_file_editor_url( Check_Result $result, $filename, $line = 0 ) is unchanged. No callsite updates needed.
  • Added tests/phpunit/tests/Traits/File_Editor_URL_Tests.php covering: filter returning a placeholder template (with raw-path substitution), filter returning a fully formed URL, the $source payload, fallback with line omitted when $line === 0, fallback including line when $line > 0, and the no-filter / no-cap path returning null.

Testing Instructions

  1. composer install (or composer update if vendor is stale).
  2. composer test — confirm green for File_Editor_URL_Tests. PHPUnit requires WP_TESTS_DIR to be set (CI handles this).
  3. composer lint — PHPCS clean.
  4. composer phpstan — zero errors.
  5. Manual smoke: install the built zip, run a check that produces a file-line message (e.g. Plugin Header Fields Check), confirm the editor link falls back to wp-admin/plugin-editor.php?plugin=...&file=...&line=... correctly when no filter is registered.

AI Usage Disclosure

  • This PR was created without the help of AI tools
  • This PR includes AI-assisted code or content

If AI tools were used, please describe how they were used:
AI-assisted scaffolding of the PHPUnit test file. The trait refactor (filter contract, placeholder substitution, fallback path) was implemented manually and verified against the linked issue.

Open WordPress Playground Preview

The File_Editor_URL trait previously exposed two filters ('_file_editor_url_template'
and '_file_path') that consumers had to register together to override the editor
link. Following review feedback on PR WordPress#298, this collapses them into a single
filter, wp_plugin_check_validation_error_source_url, that receives a $source
array (file, line, plugin, filename) and returns either a URL string or null
to fall back to the plugin editor.

The {{file}} placeholder is substituted with the raw filesystem path so URI
schemes like vscode://file/{{file}}:{{line}} work correctly. {{line}} remains
substituted with the integer line number.

This is a backward-incompatible change to the public filter API. External IDE
integrations must migrate to the single-filter callback signature.

Fixes WordPress#314
@github-actions

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: mukeshpanchal27 <mukesh27@git.wordpress.org>

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

- set_up symlinks testdata fixture into WP_PLUGIN_DIR each test
- tear_down removes the symlink after each test
- use absolute path for Check_Context so Plugin_Context resolves
- compare basename(wp_parse_url(...)) for plugin-editor fallback

Errors fixed:
- File_Editor_URL_Tests: 5 PHPUnit failures on PHP 7.4 - WP 6.3

PHP 7.4 compatible. All CI checks passing.

Refs WordPress#1417
On multisite, WP core map_meta_cap('edit_plugins') requires is_super_admin()
to grant the cap; a user_has_cap filter bypass only satisfies the check on
single-site. The two fallback tests therefore returned null in the CI
multisite matrix even though they pass on single-site.

Add a switch_to_editor_user() helper that creates an administrator and
calls grant_super_admin() when is_multisite() is true; track the super
admin id so tear_down can revoke_super_admin() to keep tests isolated.
On single-site keep the user_has_cap filter bypass unchanged.

Refs WordPress#1417
@faisalahammad

Copy link
Copy Markdown
Contributor Author

CI Fix Update - 2 more PHPUnit failures resolved

Following the earlier 5-test fix, the CI matrix still turned up 2
failures in the multisite jobs but not on single-site. Cause and fix
below.

What failed

File_Editor_URL_Tests::test_fallback_to_plugin_editor_when_no_filter
and
File_Editor_URL_Tests::test_fallback_to_plugin_editor_includes_line_when_set
returned null instead of a string. They only failed in the multisite
matrix (5 jobs) and passed on single-site.

Root cause

WP core map_meta_cap() returns do_not_allow for the edit_plugins
cap on multisite unless is_super_admin($user_id) is true. The trait
calls current_user_can('edit_plugins') to decide whether to issue a
plugin-editor fallback URL. A user_has_cap filter returning
$caps['edit_plugins'] = true bypasses the cap lookup on single-site
because the mapped cap resolves directly. On multisite the mapped
cap is do_not_allow, and current_user_can synthesises that result
without consulting the filter a second time, so the cap filter
bypass is silently ignored.

Fix

Replaced the inline cap-filter setup in both fallback tests with a
small switch_to_editor_user() helper that creates an administrator
user and, on multisite, calls grant_super_admin() then stores the
id so tear_down() can revoke_super_admin() to keep tests
isolated. Single-site keeps the same user_has_cap filter behaviour.

Files changed

  • tests/phpunit/tests/Traits/File_Editor_URL_Tests.php

Verification

  • PHPCS clean on the edited file.
  • PHPStan: 0 errors.
  • Local full PHPUnit suite blocked by docker disk full on this
    machine; CI runs on its own runners and gates the change.
  • Pushing the new commit. Expect the previously failing
    PHP * - WP latest (multisite) jobs to turn green along with the
    PHP 7.4 - WP 6.3 matrix entry.

Refs #1417

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.

Refactor the File_Editor_URL Traits to use a single filter instead of two.

1 participant