Hooks Service
The hooks service is first-of-all a single-handler service and second-of-all a runnable and resettable object. It's a service designed to work with WordPress actions and filters (commonly referred to as hooks). Basically the service provides the following public methods:
add_action
- registers an action with the handlerremove_action
- removes an action registered with the handlerremove_all_actions
- removes all actions registered with the handleradd_filter
- registers a filter with the handlerremove_filter
- remove a filter registered with the handlerremove_all_filters
- removes all filters registered with the handler
All of these methods are just wrappers against the registered handler. Any handler implementing the
HooksHandlerInterface
can be registered with the hooks service, but you may also decide to simply use the default handler instantiated if no handler is passed on in the constructor. The default handler is an instance of the DefaultHooksHandler
inspired by the loader defined in the WordPress Plugin Boilerplate by DevinVinson.The intention is to only register the hooks with the WordPress system if the plugin was successfully initialized. If an error occurred, we don't want any half-hooks being called.
The default handler maintains all of the registered hooks in protected arrays and calls WordPress' own
add_action
and add_filter
functions on its own run
action.The handler's
run
and reset
methods are automatically called when the hooks service's respective methods are called.This approach arguably has its downsides. For example, you can't use any of your own hooks during plugin initialization (because that's when you're supposed to call
run
on the service). If you want to bypass this, there are 2 options available:- 1.Just don't use the service. We think the advantages outweigh the disadvantages, but that's for you to decide.
- 2.Write your own custom handler implementing the
HooksHandlerInterface
interface and have it call the WP API directly.
There are 3 traits available for working with the hooks service.
First there is the
HooksServiceAwareTrait
and the corresponding HooksServiceAwareInterface
. Basically this allows you to call upon the hooks service instance from anywhere within the object. Technically, you can also use more than one service in your plugin and register different ones with different objects.<?php
namespace DeepWebSolutions\Plugins\MyPlugin;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksService;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksServiceAwareInterface ;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksServiceAwareTrait;
defined( 'ABSPATH' ) || exit;
class MyClass implements HooksServiceAwareInterface {
use HooksServiceAwareTrait;
public function register_my_hooks() {
$hooks_service = $this->get_hooks_service();
$hooks_service->add_filter( 'dws_myplugin_filter', $this, 'filter_value' );
}
public function filter_value( $value_to_filter ) {
// ...modify 'value_to_filter'
return $value_to_filter;
}
}
$hooks_service = new HooksService( $plugin_instance, $logging_service_instance );
$my_class = new MyClass();
$my_class->set_hooks_service( $hooks_service );
$my_class->register_my_hooks();
$hooks_service->run();
The second method involves injecting the hooks service from outside the instance. This behavior is modelled by the
HooksServiceRegisterInterface
interface and the HooksServiceRegisterTrait
.<?php
namespace DeepWebSolutions\Plugins\MyPlugin;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksService;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksServiceRegisterInterface;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksServiceRegisterTrait;
defined( 'ABSPATH' ) || exit;
class MyClass implements HooksServiceRegisterInterface {
use HooksServiceRegisterTrait;
public function register_hooks( HooksService $hooks_service ) {
$hooks_service->add_filter( $this->get_hook_tag( 'dws_myplugin_filter' ), $this, 'filter_value' );
}
public function filter_value( $value_to_filter ) {
// ...modify 'value_to_filter'
return $value_to_filter;
}
}
$hooks_service = new HooksService( $plugin_instance, $logging_service_instance );
$my_class = new MyClass();
$my_class->register_hooks( $hooks_service );
$hooks_service->run();
The recommended way, however, is to use the
SetupHooksTrait
action trait. It's an action extension trait for automagically calling the aforementioned register_hooks
methods upon the setup
action. If attempts to obtain an instance of the HooksService
either from the object itself (if it implements the HooksServiceAwareInterface
interface) or from a dependency injection container.There is also an accompanying
InitializeHooksServiceTrait
action trait. This one attempts to set the hooks service on the instance by first querying its parent and lastly the dependency injection container for an instance.Putting it all together, your code could look something like this:
<?php
namespace DeepWebSolutions\Plugins\MyPlugin;
use DeepWebSolutions\Framework\Foundations\Actions\InitializableInterface;
use DeepWebSolutions\Framework\Foundations\Actions\Initializable\InitializableTrait;
use DeepWebSolutions\Framework\Foundations\Actions\SetupableInterface;
use DeepWebSolutions\Framework\Foundations\Actions\Setupable\SetupableTrait;
use DeepWebSolutions\Framework\Foundations\Utilities\DependencyInjection\ContainerAwareInterface;
use DeepWebSolutions\Framework\Foundations\Utilities\DependencyInjection\ContainerAwareTrait;
use DeepWebSolutions\Framework\Utilities\Actions\Initializable\InitializeHooksServiceTrait;
use DeepWebSolutions\Framework\Utilities\Actions\Setupable\SetupHooksTrait;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksService;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksServiceRegisterInterface;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksServiceRegisterTrait;
defined( 'ABSPATH' ) || exit;
class MyClass implements ContainerAwareInterface, InitializableInterface, SetupableInterface {
use ContainerAwareTrait;
use InitializeHooksServiceTrait;
use InitializableTrait;
use SetupableTrait;
use SetupHooksTrait;
public function register_hooks( HooksService $hooks_service ) {
// register your hooks in here...
}
}
$my_class = new MyClass();
$my_class->set_container( $my_dependency_injection_container );
$my_class->initialize(); // the hooks service will be set on the instance from the DI container
$my_class->setup(); // the 'register_hooks' method will be automagically called
If the number of imported interfaces and traits in the example above is scarring you, you can find some comfort in the fact that this is an extreme example built from scratch! Normally you would create pre-built abstract objects that implement most of these features and simply extend them. That's basically what our Core Module does!
Last modified 2yr ago