Problem
In T219684 dependencies were added to ApiQueryBlocks and the class became aware of the container.
Solution
ApiQueryBlocks should have its dependencies injected into it.
Problem
In T219684 dependencies were added to ApiQueryBlocks and the class became aware of the container.
Solution
ApiQueryBlocks should have its dependencies injected into it.
Status | Subtype | Assigned | Task | ||
---|---|---|---|---|---|
Open | None | T259960 Inject services into API modules and special pages | |||
Resolved | None | T221722 ApiQueryBlocks should not be aware of the container | |||
Resolved | dmaza | T219684 BlockRestriction should be a service instead of a singleton | |||
Resolved | Mainframe98 | T222388 Create a mechanism for SpecialPages and API modules to have dependencies injected into them |
This task seems like a good idea in itself, but it assumes we have all the DI infrastructure already in the API which I'm not entirely sure actually exists (yeah, Technical-Debt). So a prerequisite might be to verify that what's already in the API is sufficient for the sort of DI that you're wanting to do here. I'll give an overview of what that is, then we can discuss if there seems to be anything missing.
The "service wiring" for creating API modules is handled by the ApiModuleManager class. The wiring configuration itself is done by PHP arrays: keys are the module names (e.g. the "block" in "action=block"), while values vary depending on how the module is to be instantiated:
For API modules in core, the array is stored in a private static array in the "parent" module, e.g. https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/master/includes/api/ApiMain.php#89 for action=block. Extensions have two mechanisms they can use: either adding values to configuration globals such as $wgAPIModules, or using a hook such as 'ApiMain::moduleManager'. Each "parent" module would have its own global and hook.
So, that's the overview. If you have questions or want more details or clarifications, feel free to ask. Unfortunately I may not be able to reply right away, but I'll do my best.
@Anomie what about doing something like this?
https://gerrit.wikimedia.org/r/c/mediawiki/core/+/494497/21/includes/api/ApiMain.php
I don't really like the fact that we have part of the array statically defined and another part included inside the constructor, it makes it even harder for people to find where the definition of a module lives. What would you say to moving the closures to static factory methods of their classes, so the "wiring" for these modules could still be in the self::$Modules initializer?
Sounds good to me. Maybe the classes could implement an interface with a create() method that also passes in an instance of the container? That way they don't have to (again) rely on the global container?