Skip to content
This repository has been archived by the owner on Sep 21, 2024. It is now read-only.
/ wp-hook Public archive

🪝 WordPress hook with OOP flavor

License

Notifications You must be signed in to change notification settings

syntatis/wp-hook

Repository files navigation

🪝 wp-hook

Packagist Dependency Version wp codecov

Caution

This package is now part of Codex.

A class wrapper designed to use WordPress hooks with object-oriented programming (OOP), inspired by the WordPress Plugin Boilerplate. This class helps you stay organized and maintain structure when managing hooks in your WordPress plugin or theme.

Installation

Install the package via Composer:

composer require syntatis/wp-hook

Usage

Create a new instance of the Registry class and register your hooks:

use Syntatis\WPHook\Registry;

$registry = new Registry();
$registry->addAction('init', 'initialise');
$registry->addFilter('the_content', 'content', 100);
$registry->addAction('add_option', 'option', 100, 2);

Using PHP Attributes

If your theme or plugin runs on PHP 8.0 or later, you can leverage PHP Attributes to define hooks directly within your classes:

use Syntatis\WPHook\Action;
use Syntatis\WPHook\Filter;
use Syntatis\WPHook\Registry;

#[Action(name: "wp")]
class HelloWorld
{
    #[Action(name: "init")]
    public function initialise(): void
    {
        echo 'initialise';
    }

    #[Filter(name: "the_content", priority: 100)]
    public function content(string $content): string
    {
        return $content . "\ncontent";
    }

    #[Action(name: "the_content", priority: 100, acceptedArgs: 2)]
    public function option(string $optionName, mixed $value): void
    {
        echo $optionName . $value;
    }

    public function __invoke(): void
    {
        echo 'wp';
    }
}

$registry = new Registry();
$registry->parse(new HelloWorld());

Note

Attributes will only be applied to non-abstract public methods that are not PHP native methods or any methods that begin with __ like __constructor, __clone, and __callStatic. If you add the Attributes at the class level, the class should implement the __invoke method, as shown in the above example.

Removing Hook

You can also remove a hook similarly to how you would with the native WordPress functions:

$registry = new Registry();
$registry->addAction('init', 'initialise');
$registry->addFilter('the_content', 'content', 100);

// ...later in the code...
$registry->removeAction('init', 'initialise');
$registry->removeFilter('the_content', 'content', 100);

It is also possible to remove all hooks at once:

$registry = new Registry();
$registry->addAction('init', 'initialise');
$registry->addFilter('the_content', 'content', 100);

// ...later in the code...
$registry->removeAll();

It is possible to attach hook with method from an object instance, a static method, or a closure:

use Syntatis\WPHook\Registry;

$helloWorld = new HelloWorld();
$anonymous = fn () => 'Hello, World!';

$registry = new Registry();
$registry->addFilter('the_content', [$helloWorld, 'content'], 100);
$registry->addAction('init', $anonymous);

However, this makes it rather tricky to remove the hook later on the code since you need to pass the same object instance or the same reference to the anonymous function to the removeAction and removeFilter methods, which is not always possible.

To circumvent this, you can pass id to the addAction and addFilter methods, and refer the id using @ symbol when removing the hook. For example:

use Syntatis\WPHook\Registry;

$helloWorld = new HelloWorld();
$anonymous = fn () => 'Hello, World!';

$registry = new Registry();
$registry->addFilter('the_content', [$helloWorld, 'content'], 100, 1, ['id' => 'the-content-hello-world']);
$registry->addAction('init', $anonymous, 10, 1, ['id' => 'init-hello-world']);

// ...much later in the code...

$registry->removeAction('init', '@init-hello-world', 10);
$registry->removeFilter('the_content', '@the-content-hello-world', 100);

Important

The ID must be all lowercase and use words separated by -, ., or _. It should not have any uppercase letters, spaces, or special characters. You can use a slash (/) to define the namespace, like acme/hello-world, to avoid conflicts with other plugins or themes. Please note that the ID added within the registry must be unique. If you're trying to add the same ID twice, it will throw an exception.

References