Skip to main content

Actions and hooks

When building large applications with multiple modules and plugins installed, it might get hard to customize or hook into existing functionalities.

Qore provides actions and hooks to make it easier to customize certain features.

Definitions

Action

An action is a simple class that can be executed. For example, you can have an action that retrieves all issues from Gitlab.

Hooks

Hooks are also simple classes that can be executed before (pre hooks) or after (post hooks) actions.

Hooks can also be executed before or after other hooks.

For example, you could have a hook that logs something before or after you do an action.

Return values

When actions run, they may optionally return something.

In your post-hooks, you can use these return values, and even modify it.

Getting started

Let's start by creating an action that retrieves issues from Gitlab:

use Qore\System\Action\Action;

class RetrieveIssuesAction extends Action
{
public function identifier(): string
{
return 'gitlab.retrieve.issues';
}

public function run(): array
{
return [
[
'id' => 'issue1',
],
[
'id' => 'issue2'
]
];
}
}

The identifier is used later to run your action.

info

You can have multiple actions with the same identifier. The last registered action will always override the other actions.

Registering your action

You can register your action anywhere:

actions()->add(new RetrieveIssuesAction);

Running your action

You can run your action now:

$results = run('gitlab.retrieve.issues');
dd($results); // Array of issues

Hooks

Let's say we want to log something before and after the action is called.

We can define create a pre-hook:

class BeforeIssuesRetrievedHook extends ActionHook
{
public function identifier(): string
{
return 'gitlab.retrieve.issues.before';
}

public function run()
{
logger('Before issues are retrieved');
}
}

And a post-hook:

class AfterIssuesRetrievedHook extends ActionHook
{
public function identifier(): string
{
return 'gitlab.retrieve.issues.after';
}

public function run()
{
logger('After issues are retrieved');
}
}

Adding the hooks

You can add your hooks anywhere after the action has been registered:

actions()->add(new RetrieveIssuesAction);
actions()->before('gitlab.retrieve.issues', BeforeIssuesRetrievedHook::class);
actions()->after('gitlab.retrieve.issues', AfterIssuesRetrievedHook::class);

$results = run('gitlab.retrieve.issues');
dd($results);

There should now be 2 new entries in your laravel.log.

Return values

If we take the previous example, you may notice that the $results is actually null now.

This is because our AfterIssuesRetrievedHook does not return anything.

We can use the return value from the previously called action (or hook):

class AfterIssuesRetrievedHook extends ActionHook
{
// The modified return value from the last hook
private $modifiedValue;

// The original return value from the action
private $originalValue;

public function __construct($modifiedValue, $originalValue)
{
$this->modifiedValue = $modifiedValue;
$this->originalValue = $originalValue;
}

public function identifier(): string
{
return 'gitlab.retrieve.issues.after';
}

public function run()
{
logger('After issues are retrieved');

return array_merge($this->originalValue, [
[
'id' => 'custom issue'
]
]);
}
}

Our $results is actually the modified value now.

Arguments

Providing arguments

Sometimes you need to provide additional arguments when running your actions:

$results = run('gitlab.retrieve.issues', ['my custom arg' => true]);

In your action you can retrieve these arguments:

class FillMenuAction extends Action
{
public function identifier(): string
{
return 'dev.fill_menu';
}

public function run(): array
{
dd($this->args);
}
}

In your post-hook you will also retrieve the modified and original values:

class AfterIssuesRetrievedHook extends ActionHook
{
public function __construct($modifiedValue, $originalValue)
{
$this->modifiedValue = $modifiedValue;
$this->originalValue = $originalValue;
}

public function run(): array
{
dd($this->args);
}
}
info

Pre-hooks will not have the $modifiedValue and $originalValue arguments

Retrieving more action information

Your hooks may modify the return value of the initial action, however sometimes you need the initial value back.

You can retrieve full information by providing true as the third parameter:

$results = run('gitlab.retrieve.issues', 'some argument', true);
dd($results);

//
array:3 [
"original" => array:2 []
"modified" => array:3 []
"arguments" => "some argument"
]