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

Commit

Permalink
Refactor hook registration (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
tfirdaus authored Jul 29, 2024
1 parent 4c3d88d commit c749a44
Show file tree
Hide file tree
Showing 11 changed files with 555 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/wp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
strategy:
fail-fast: true
matrix:
php: ['7.4', '8.0', '8.1', '8.2', '8.3']
php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
wp: ['6.*', '5.*']

services:
Expand Down
57 changes: 51 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ $registry = new Registry();
$registry->addAction('init', 'initialise');
$registry->addFilter('the_content', 'content', 100);
$registry->addAction('add_option', 'option', 100, 2);
$registry->register();
```

### Using PHP Attributes
Expand Down Expand Up @@ -72,27 +71,73 @@ class HelloWorld

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

> [!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.
### Deregistering Hooks
### Removing Hook

You can also deregister hooks, which will remove all the actions and filters that have been registered in the `Hook` instance:
You can also remove a hook similarly to how you would with the native WordPress functions:

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

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

It is also possible to remove all hooks at once:

```php
$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:

```php
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:

```php
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

- [WordPress Plugin Boilerplate](https://wppb.me/)
Expand Down
17 changes: 17 additions & 0 deletions app/Exceptions/RefExistsException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Syntatis\WPHook\Exceptions;

use Exception;

use function sprintf;

class RefExistsException extends Exception
{
public function __construct(string $ref)
{
parent::__construct(sprintf('Reference "%s" already exists on the registry.', $ref));
}
}
17 changes: 17 additions & 0 deletions app/Exceptions/RefNotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Syntatis\WPHook\Exceptions;

use Exception;

use function sprintf;

class RefNotFoundException extends Exception
{
public function __construct(string $ref)
{
parent::__construct(sprintf('Reference "%s" not found on the registry.', $ref));
}
}
19 changes: 17 additions & 2 deletions app/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,24 @@ class Filter

protected int $acceptedArgs;

/** @phpstan-param non-empty-string $name */
/** @var array<string, mixed> */
protected array $options;

/**
* @param array<string, mixed> $options
*
* @phpstan-param non-empty-string $name
*/
public function __construct(
string $name,
int $priority = 10,
int $acceptedArgs = 1
int $acceptedArgs = 1,
array $options = []
) {
$this->name = $name;
$this->priority = $priority;
$this->acceptedArgs = $acceptedArgs;
$this->options = $options;
}

public function getName(): string
Expand All @@ -45,4 +54,10 @@ public function getAcceptedArgs(): int
{
return $this->acceptedArgs;
}

/** @return array<string,mixed> */
public function getOptions(): array
{
return $this->options;
}
}
Loading

0 comments on commit c749a44

Please sign in to comment.