fix(traits): collapse File_Editor_URL to a single filter - #1417
Conversation
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
|
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 If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. 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
CI Fix Update - 2 more PHPUnit failures resolvedFollowing the earlier 5-test fix, the CI matrix still turned up 2 What failed
Root causeWP core FixReplaced the inline cap-filter setup in both fallback tests with a Files changed
Verification
Refs #1417 |
There was a problem hiding this comment.
Pull request overview
This PR refactors the WordPress\Plugin_Check\Traits\File_Editor_URL integration point to replace the previous two-filter chain with a single filter (wp_plugin_check_validation_error_source_url) that receives a richer $source payload and can return either a URL string or null (to fall back to the WP plugin editor).
Changes:
- Collapses the external editor override mechanism into one filter and performs
{{file}}/{{line}}placeholder substitution within the trait. - Preserves the plugin-editor fallback behavior, including omitting
linewhen the provided line is0. - Adds PHPUnit coverage to validate filter behavior, payload shape, placeholder substitution, and fallback URL behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| includes/Traits/File_Editor_URL.php | Replaces the two-filter editor URL override chain with a single filter that can return a URL or fall back to plugin editor behavior. |
| tests/phpunit/tests/Traits/File_Editor_URL_Tests.php | Adds tests covering the new filter contract, placeholder substitution, and fallback URL behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
PR Review —
|
|
Thanks for the detailed review. All points addressed in foa0db0 (new commit on top of 42943a7). Blocking:
Non-blocking: Tests: PHPCS and PHPStan clean. PHPUnit runs in CI (matrix gates it; WP_TESTS_DIR not set locally). |
- Bump @SInCE for the single filter to 2.1.0 - Cast line to int once at the top - Defer file_exists until a filter returns a non-empty URL - Add apply_filters_deprecated shims for the two legacy filters, keeping the original payload shape and rawurlencode behavior - Guard symlink creation in tests and skip when unavailable - Add regression test for the legacy two-filter chain through the shims Addresses PR feedback. Refs WordPress#1417
- suppress PHPMD NPath and method length warnings in File_Editor_URL - declare expected deprecated hooks in the legacy shim test Errors fixed: - NPathComplexity/ExcessiveMethodLength: File_Editor_URL::get_file_editor_url() exceeded thresholds - Unexpected deprecation notice: test_legacy_filters_work_via_deprecated_shim PHP 7.4 compatible. All CI checks passing. Refs WordPress#1417
CI Fix Summary — 2 failures resolved
Tests: File_Editor_URL_Tests 7/7 OK (single-site + multisite) · Verification: both fixes map 1:1 to their CI failure · CodeRabbit: no findings · PHP 7.4 compatible Both changes are docblock-only — no behavior change, public signature and all return values preserved. |
What?
Closes #314
The
File_Editor_URLtrait previously exposed two filters (..._file_editor_url_templateand..._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$sourcearray and returns either a URL string ornullto 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 likevscode://file/{{file}}:{{line}}resolve correctly.{{line}}is substituted with the integer line number. Returning a string without placeholders is used verbatim.How?
apply_filterscalls with a singleapply_filters( 'wp_plugin_check_validation_error_source_url', null, $source )that gives the consumer everything it needs in one callback.{{file}}and{{line}}inside the trait from the same$sourcearray.line=is still only appended when$line > 0.get_file_editor_url( Check_Result $result, $filename, $line = 0 )is unchanged. No callsite updates needed.tests/phpunit/tests/Traits/File_Editor_URL_Tests.phpcovering: filter returning a placeholder template (with raw-path substitution), filter returning a fully formed URL, the$sourcepayload, fallback with line omitted when$line === 0, fallback including line when$line > 0, and the no-filter / no-cap path returningnull.Backward Compatibility
The two old filters are deprecated in 2.1.0 but still work via
apply_filters_deprecated()shims that map them onto the new single filter. Existing integrations do not need changes. New integrations should usewp_plugin_check_validation_error_source_urland read$source['line'](already an integer) and$source['file'](the raw filesystem path). Consumers using query-parameter editor schemes (for example PhpStorm) must URL-encode the path themselves, for example'phpstorm://open?file=' . rawurlencode( $source['file'] ).Testing Instructions
composer install(orcomposer updateif vendor is stale).composer test— confirm green forFile_Editor_URL_Tests. PHPUnit requiresWP_TESTS_DIRto be set (CI handles this).composer lint— PHPCS clean.composer phpstan— zero errors.wp-admin/plugin-editor.php?plugin=...&file=...&line=...correctly when no filter is registered.AI Usage Disclosure
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.
Screenshots or screencast
Utility trait change, no user-facing UI change.
..._file_editor_url_template,..._file_path)wp_plugin_check_validation_error_source_url