Put every plugin class into its own FOG\Plugins\<Plugin> namespace - #33
Merged
Conversation
Every class/interface/trait-declaring file under a plugin directory (*.class.php, *.hook.php, *.page.php, *.event.php, *.report.php, *.task.php -- 176 files across 15 plugins) now declares `namespace FOG\Plugins\<Ucfirst-plugin-directory-name>;`, mechanically derived from the plugin's directory name with no exceptions. The subdirectory (class/, pages/, hooks/, events/, reports/, tasks/, capone's odd reg-task/) is not part of it, so every class in a plugin shares one flat namespace. Core references stay exactly as they were -- already leading-backslash FQCNs (fogproject ADR 0013 §2/§13) -- and self::getClass() string literals are untouched, since core's FOGBase::qualify() already resolves a plugin short name to its new FQCN. A per-file bare-builtin and cross-plugin-reference sweep found nothing to fix; the source was already clean. Fixed the stale helloworld docblock claiming the class is found by PHP's default spl_autoload lowercasing the filename -- that fallback was removed from core (ADR 0013 §2b) because it let a plugin shadow a core class. It documents Initiator::autoload() and the new namespace instead. tests/oidc-flow-safety.test.php and tests/oidc-provider-safety.test.php require the OIDC plugin's source directly and call OIDC/OIDCManager/ OIDCGroupManager/OIDCUserGrantManager by bare name -- both now qualify those references, matching the FQCN convention everywhere else. Added tests/plugins-are-namespaced.test.php: for every class file under every plugin directory, asserts exactly one namespace declaration, that it matches FOG\Plugins\<Plugin> case-insensitively (a third-party plugin may spell it differently from a strict ucfirst()), and that the file declares no class_alias(). Mutation-verified by copying ldap/class/ldapmanager.class.php aside, removing its namespace line (went red: "declares no namespace"), restoring, setting it to a wrong namespace (went red: "declares namespace 'FOG\Plugins\Oidc', expected 'fog\plugins\ldap'"), then restoring the original file byte-for-byte. Co-Authored-By: Claude <noreply@anthropic.com>
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.
Companion to FOGProject/fogproject#1535, which teaches core to resolve a namespaced plugin class. That PR must merge, release and be pinned first — a plugin declaring
FOG\Plugins\…does not resolve on a core without its autoload arm.What this does
All 176 class-declaring files across 15 plugins now declare:
ldap/→FOG\Plugins\Ldap,helloworld/→FOG\Plugins\Helloworld. Mechanicalucfirst()of the directory name — no lookup table, no exceptions. The subdirectory (class/,pages/,hooks/,events/,reports/,tasks/, capone'sreg-task/) is not part of it: every class in a plugin shares one flat namespace, becauseFOGController::getManager()isqualify(shortName($this) . 'Manager')and a model and its manager have to resolve together.File layout is untouched — the discovery suffixes are how a page, hook, event, report or task is found.
Why the diff is one line per file
\FOG\Base\FOGController), pinned bytests/core-references-are-qualified.test.php. A leading backslash means the same thing inside a namespace, so not one of them changed.catchwas already qualified — 24\Exception, one\TypeError, one\Throwable.self::getClass('X')string literals are untouched (~150 of them). Core'sFOGBase::qualify()resolves a plugin short name to its new FQCN, so they keep working as written.class_alias()is added anywhere — that is the point of the core change.Also in here
helloworld/class/helloworld.class.phphad a stale docblock claiming the class is found by PHP's defaultspl_autoloadlowercasing the filename. That fallback was removed from core (ADR 0013 §2b) because it let a plugin shadow a core class. It now describesInitiator::autoload()and the new namespace.tests/oidc-flow-safety.test.phpandtests/oidc-provider-safety.test.phprequireOIDC plugin source directly and calledOIDC/OIDCManager/OIDCGroupManager/OIDCUserGrantManagerbare. Both now qualify those references — without it, two tests went from green to a fatalClass "OIDC" not found.Gate
tests/plugins-are-namespaced.test.php(new) asserts, for every class file under every plugin directory: exactly onenamespacedeclaration; that it equalsFOG\Plugins\+ the plugin directory, case-insensitively (PHP namespaces are, and a third-party plugin may spell itMyPluginfor directorymyplugin); and that the file declares noclass_alias(). It runs with no fogproject checkout, like its sibling.Mutation-verified, both arms observed red:
Restored by copy, not
git checkout --, and verified byte-identical.Verification
php -l.Still outstanding, and it needs a running server: render every plugin page, install/uninstall a plugin, hit a plugin REST route, run a plugin task through
PluginRunner.