Hooks::run() was soft-deprecated in Nikki Nikkhoui's HookContainer patch, merged on April 17. [1] And my patch to remove almost all instances of it in MediaWiki Core was finally merged over the weekend. [2] That means that everyone writing core code now needs to learn how to use the new hook system.
HookContainer is a new service which replaces the functionality which was previously in static methods in the Hooks class. HookContainer contains a generic run() method which runs a specified hook, analogous to Hooks::run(). However, unlike Hooks::run(), you generally should not use HookContainer::run() directly. Instead, you call a proxy method in a hook runner class.
Hook runner classes give hooks machine-readable parameter names and types.
How to call a hook ------------------
In MediaWiki Core, there are two hook runner classes: HookRunner and ApiHookRunner. ApiHookRunner is used in the Action API, and HookRunner is used everywhere else.
How you get an instance of HookRunner depends on where you are:
* In classes that use dependency injection, a HookContainer object is passed in as a constructor parameter. Then the class creates a local HookRunner instance:
$this->hookRunner = new HookRunner( $hookContainer );
* In big hierarchies like SpecialPage, there are always getHookRunner() and getHookContainer() methods which you can use.
* Some classes use the ProtectedHookAccessor trait, which provides getHookRunner() and getHookContainer() methods that get their HookContainer from the global service locator. You can also call MediaWikiServices::getHookContainer() in your own code, if dependency injection is not feasible.
* There is a convenience method for static code called Hooks::runner(), which returns a HookRunner instance using the global HookContainer.
* Extensions should generally not use HookRunner, since the available hooks may change without deprecation. Instead, extensions should have their own HookRunner class which calls HookContainer::run().
Once you have a HookRunner object, you call the hook by simply calling the relevant method.
How to add a hook -----------------
* Create an interface for the hook. The interface name is always the hook name with "Hook" appended. The interface should contain a single method, which is the hook name with a prefix of "on". So for example, for a hook called MovePage, there will be an interface called MovePageHook with a method called onMovePage(). The interface will typically be in a "Hook" subnamespace relative to the caller namespace.
* Add an "implements" clause to HookRunner.
* Implement the method in HookRunner.
Note that the name of the interface is currently not enforced by CI. Alphabetical sorting of interface names and method names in HookRunner is also not enforced. Please be careful to follow existing conventions.
How to deprecate a hook -----------------------
Hooks were previously deprecated by passing options to Hook::run(). They are now deprecated globally by adding the hook to an array in the DeprecatedHooks class.
Using the new system in extensions ----------------------------------
Extensions should create their own HookRunner classes and use them to call hooks. HookContainer::run() should be used instead of Hooks::run().
As for handling hooks, I think it's too early for a mass migration of extensions to the new registration system as described in the RFC.[3] Extension authors who are keen to pilot the new system can give it a go. Make sure you add Nikki and me as reviewers.
More information about the new system can be found in docs/Hooks.md [4]. The patch to add it should soon be merged.
[1] https://gerrit.wikimedia.org/r/c/mediawiki/core/+/571297 [2] https://gerrit.wikimedia.org/r/c/mediawiki/core/+/581225 [3] https://phabricator.wikimedia.org/T240307 [4] https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/323ac073d38ec30a97b73b4a25999079b3a125d3/docs/Hooks.md
-- Tim Starling
On Mon, Jun 1, 2020 at 1:44 AM Tim Starling tstarling@wikimedia.org wrote:
Hooks::run() was soft-deprecated in Nikki Nikkhoui's HookContainer patch, merged on April 17. [1] And my patch to remove almost all instances of it in MediaWiki Core was finally merged over the weekend. [2] That means that everyone writing core code now needs to learn how to use the new hook system.
HookContainer is a new service which replaces the functionality which was previously in static methods in the Hooks class. HookContainer contains a generic run() method which runs a specified hook, analogous to Hooks::run(). However, unlike Hooks::run(), you generally should not use HookContainer::run() directly. Instead, you call a proxy method in a hook runner class.
Hook runner classes give hooks machine-readable parameter names and types.
This sounds really cool. Does this mean can read the parameter names and types without deep learning;-)
How to call a hook
In MediaWiki Core, there are two hook runner classes: HookRunner and ApiHookRunner. ApiHookRunner is used in the Action API, and HookRunner is used everywhere else.
How you get an instance of HookRunner depends on where you are:
- In classes that use dependency injection, a HookContainer object is
passed in as a constructor parameter. Then the class creates a local HookRunner instance:
$this->hookRunner = new HookRunner( $hookContainer );
- In big hierarchies like SpecialPage, there are always
getHookRunner() and getHookContainer() methods which you can use.
- Some classes use the ProtectedHookAccessor trait, which provides
getHookRunner() and getHookContainer() methods that get their HookContainer from the global service locator. You can also call MediaWikiServices::getHookContainer() in your own code, if dependency injection is not feasible.
- There is a convenience method for static code called
Hooks::runner(), which returns a HookRunner instance using the global HookContainer.
- Extensions should generally not use HookRunner, since the available
hooks may change without deprecation. Instead, extensions should have their own HookRunner class which calls HookContainer::run().
Once you have a HookRunner object, you call the hook by simply calling the relevant method.
How to add a hook
- Create an interface for the hook. The interface name is always the
hook name with "Hook" appended. The interface should contain a single method, which is the hook name with a prefix of "on". So for example, for a hook called MovePage, there will be an interface called MovePageHook with a method called onMovePage(). The interface will typically be in a "Hook" subnamespace relative to the caller namespace.
Add an "implements" clause to HookRunner.
Implement the method in HookRunner.
Note that the name of the interface is currently not enforced by CI. Alphabetical sorting of interface names and method names in HookRunner is also not enforced. Please be careful to follow existing conventions.
How to deprecate a hook
Hooks were previously deprecated by passing options to Hook::run(). They are now deprecated globally by adding the hook to an array in the DeprecatedHooks class.
Using the new system in extensions
Extensions should create their own HookRunner classes and use them to call hooks. HookContainer::run() should be used instead of Hooks::run().
As for handling hooks, I think it's too early for a mass migration of extensions to the new registration system as described in the RFC.[3] Extension authors who are keen to pilot the new system can give it a go. Make sure you add Nikki and me as reviewers.
More information about the new system can be found in docs/Hooks.md [4]. The patch to add it should soon be merged.
[1] https://gerrit.wikimedia.org/r/c/mediawiki/core/+/571297 [2] https://gerrit.wikimedia.org/r/c/mediawiki/core/+/581225 [3] https://phabricator.wikimedia.org/T240307 [4] https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+/323ac073d38ec30a97b73b4a25999079b3a125d3/docs/Hooks.md
-- Tim Starling
Wikitech-l mailing list Wikitech-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikitech-l
On 2/6/20 4:27 am, Physikerwelt wrote:
Hook runner classes give hooks machine-readable parameter names and types.
This sounds really cool. Does this mean can read the parameter names and types without deep learning;-)
Yes. A large number of hook call sites initially failed Phan static analysis type checks. Sometimes the documentation was at fault, sometimes the call sites were at fault. Now that the migration patch has been merged, Phan will enforce the correct types going forward.
-- Tim Starling
wikitech-l@lists.wikimedia.org