-
Notifications
You must be signed in to change notification settings - Fork 9
/
Hook.php
138 lines (122 loc) · 3.47 KB
/
Hook.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?php
namespace luya;
use luya\base\HookEvent;
use yii\base\BaseObject;
/**
* Simple Hooking mechanism.
*
* Attaching callables or object methods to the Hook mechnism in your controller, block or elsewhere. Read more in the guide [[concept-hooks.md]].
*
* A simple string output behavior:
*
* ```php
* Hook::on('fooBar', function() {
* return 'Hello World';
* });
* ```
*
* In order to trigger the hook output somewher in your layout file use:
*
* ```php
* echo Hook::string('fooBar');
* ```
*
* In order to generate iteration output.
*
* ```php
* Hook::on('fooBarArray', function($hook) {
* $hook[] = 'Hello';
* $hook[] = 'World';
* });
* ```
*
* The array would print:
*
* ```php
* $array = Hook::iterate('fooBarArray'); // Array ( 0 => 'Hello', 1 => 'World')
* ```
*
* @author Basil Suter <[email protected]>
* @since 1.0.0
*/
class Hook extends BaseObject
{
private static $_hooks = [];
/**
* Register a hook listener.
*
* Define the name of the type of listener.
*
* @param string $name The name of the hook.
* @param callable|array $value An array with `[$object, 'method']` or a callable function `function($hook) {}`.
* @param boolean $prepend Whether to prepend the item to the start or as by default to the end of the stack.
*/
public static function on($name, $value, $prepend = false)
{
$object = new HookEvent(['handler' => $value]);
if ($prepend) {
array_unshift(static::$_hooks[$name], $object);
} else {
static::$_hooks[$name][] = $object;
}
}
/**
* Trigger the hooks and returns the {{luya\base\HookEvent}} objects.
*
* @param string $name The hook name.
* @return array An array with {{luya\base\HookEvent}} objects.
* @throws Exception
*/
protected static function trigger($name)
{
if (isset(static::$_hooks[$name])) {
$events = [];
foreach (static::$_hooks[$name] as $hookEvent) {
if ($hookEvent->isHandled) {
continue;
}
if (is_array($hookEvent->handler)) {
$hookEvent->output = call_user_func_array($hookEvent->handler, [$hookEvent]);
} elseif (is_callable($hookEvent->handler)) {
$hookEvent->output = call_user_func($hookEvent->handler, $hookEvent);
} else {
throw new Exception("The provided hook event handler is not valid.");
}
$hookEvent->isHandled = true;
if ($hookEvent->isValid) {
$events[] = $hookEvent;
}
}
return $events;
}
return [];
}
/**
* Get the string output of the hooks.
*
* @param string $name The name of the hook to trigger.
* @return string
*/
public static function string($name)
{
$buffer = [];
foreach (self::trigger($name) as $hook) {
$buffer[] = $hook->output;
}
return implode("", $buffer);
}
/**
* Get the array output of iteration hooks.
*
* @param string $name The name of the hook to trigger.
* @return array
*/
public static function iterate($name)
{
$buffer = [];
foreach (self::trigger($name) as $hook) {
$buffer = array_merge($buffer, $hook->getIterations());
}
return $buffer;
}
}