11: Loader boot and load path - #11
Open
nikolaystrikhar wants to merge 4 commits into
Open
Conversation
This was referenced Aug 3, 2026
…path file_exists() was the gate before require_once, but it is true for a directory and for a file with no read permission, and require_once fatals on both. A deploy that loses a read bit would have taken the site down from the one function whose contract is that it never fatals. is_file() and is_readable() now. is_already_loaded() moves ahead of are_dependencies_met(). The dependency check calls an arbitrary host callable and was running first, so with the standalone active a host whose check happened to fail would queue "requirements are not met" for a plugin the admin can watch running. The defined() check is the cheapest gate and the one carrying the whole re-declaration guarantee. A missing bundled file reports through _doing_it_wrong() rather than the notice queue. Queueing a dependency notice renders the host's own dependency_notice_message, so a broken build would have told the site owner to upgrade a dependency that was fine. WordPress draws the same line. boot() detects that plugins_loaded has already passed priority 2 and loads inline. Adding an action at a passed priority is accepted and never fires, so a host who drops the ', 0' from the documented bootstrap got a site where nothing loaded at all, with no warning. load_all() and render_notices() report a missing hook prefix instead of throwing out of a core action, where it would have been a total outage over a bootstrap mistake. Tests: the fake-registrar test passed with the instanceof guard deleted, so it now binds a registrar returning mixed junk; adds the require_once dedupe case, the unreadable and directory cases, and the late-boot cases. The boot tests rewind did_action( 'plugins_loaded' ), which the harness has already fired before any test can run.
Booting from plugins_loaded at priority 2 wired the load hook into the priority bucket the dispatch was already iterating, which WP_Hook never reaches, and the exclusive comparison meant nothing was reported either. Nothing loaded and the site looked healthy. Also document that a bundled file included from a method does not get the global scope wp-settings.php gives a plugin.
nikolaystrikhar
force-pushed
the
10-notices-queue
branch
from
August 6, 2026 14:22
2f976f3 to
a8e8860
Compare
nikolaystrikhar
force-pushed
the
11-loader-load-path
branch
from
August 6, 2026 14:22
7d4435a to
4d1c627
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
Loader::boot(),load_all(), the load path's five gates, and theshould_loadfilter — the code deciding whether torequire_oncea bundled plugin.Stacked on #10.
file_exists()was the gate beforerequire_once. It returns true for a directory and for an unreadable file, both of which fatal. Nowis_file()plusis_readable().boot()called too late loaded nothing, silently. A hook added at a priority the running dispatch has passed is accepted and never fires. The guard is now inclusive of the load priority and loads inline.Config_Exceptionescaped a core action;load_all()andrender_notices()now report and return.is_already_loaded()must run beforeare_dependencies_met(), which calls an arbitrary host callable and could blame dependencies for a visibly running plugin.$varis function-local. No wrapper can fix that; the README says so.Verify:
slic run unit— 155 tests, 241 assertions.--env multisitegreen, 1 deliberate skip.composer test:analysis→[OK] No errors.Not covered: a parse error in a sub-plugin still fatals, deliberately.