Completed
Push — master ( 53b99e...05e097 )
by Basil
03:48
created

Hook::trigger()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 8.5066
c 0
b 0
f 0
cc 7
nc 8
nop 1
1
<?php
2
3
namespace luya;
4
5
use luya\base\HookEvent;
6
use yii\base\BaseObject;
7
8
/**
9
 * Simple Hooking mechanism.
10
 *
11
 * Attaching callables or object methods to the Hook mechnism in your controller, block or elsewhere. Read more in the guide [[concept-hooks.md]].
12
 *
13
 * A simple string output behavior:
14
 *
15
 * ```php
16
 * Hook::on('fooBar', function() {
17
 *     return 'Hello World';
18
 * });
19
 * ```
20
 *
21
 * In order to trigger the hook output somewher in your layout file use:
22
 *
23
 * ```php
24
 * echo Hook::string('fooBar');
25
 * ```
26
 *
27
 * In order to generate iteration output.
28
 *
29
 * ```php
30
 * Hook::on('fooBarArray', function($hook) {
31
 *     $hook[] = 'Hello';
32
 *     $hook[] = 'World';
33
 * });
34
 * ```
35
 *
36
 * The array would print:
37
 *
38
 * ```php
39
 * $array = Hook::iterate('fooBarArray'); // Array ( 0 => 'Hello', 1 => 'World')
40
 * ```
41
 *
42
 * @author Basil Suter <[email protected]>
43
 * @since 1.0.0
44
 */
45
class Hook extends BaseObject
46
{
47
    private static $_hooks = [];
48
49
    /**
50
     * Register a hook listener.
51
     *
52
     * Define the name of the type of listener.
53
     *
54
     * @param string $name The name of the hook.
55
     * @param callable|array $value An array with `[$object, 'method']` or a callable function `function($hook) {}`.
56
     * @param boolean $prepend Whether to prepend the item to the start or as by default to the end of the stack.
57
     */
58
    public static function on($name, $value, $prepend = false)
59
    {
60
        $object = new HookEvent(['handler' => $value]);
61
        
62
        if ($prepend) {
63
            array_unshift(static::$_hooks[$name], $object);
0 ignored issues
show
Bug introduced by
Since $_hooks is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $_hooks to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
64
        } else {
65
            static::$_hooks[$name][] = $object;
0 ignored issues
show
Bug introduced by
Since $_hooks is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $_hooks to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
66
        }
67
    }
68
69
    /**
70
     * Trigger the hooks and returns the {{luya\base\HookEvent}} objects.
71
     *
72
     * @param string $name The hook name.
73
     * @return array An array with {{luya\base\HookEvent}} objects.
74
     * @throws Exception
75
     */
76
    protected static function trigger($name)
77
    {
78
        if (isset(static::$_hooks[$name])) {
0 ignored issues
show
Bug introduced by
Since $_hooks is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $_hooks to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
79
            $events = [];
80
            
81
            foreach (static::$_hooks[$name] as $hookEvent) {
0 ignored issues
show
Bug introduced by
Since $_hooks is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $_hooks to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
82
                if ($hookEvent->isHandled) {
83
                    continue;
84
                }
85
                
86
                if (is_array($hookEvent->handler)) {
87
                    $hookEvent->output = call_user_func_array($hookEvent->handler, [$hookEvent]);
88
                } elseif (is_callable($hookEvent->handler)) {
89
                    $hookEvent->output = call_user_func($hookEvent->handler, $hookEvent);
90
                } else {
91
                    throw new Exception("The provided hook event handler is not valid.");
92
                }
93
                
94
                $hookEvent->isHandled = true;
95
                
96
                if ($hookEvent->isValid) {
97
                    $events[] = $hookEvent;
98
                }
99
            }
100
101
            return $events;
102
        }
103
104
        return [];
105
    }
106
    
107
    /**
108
     * Get the string output of the hooks.
109
     *
110
     * @param string $name The name of the hook to trigger.
111
     * @return string
112
     */
113
    public static function string($name)
114
    {
115
        $buffer = [];
116
        foreach (self::trigger($name) as $hook) {
117
            $buffer[] = $hook->output;
118
        }
119
        
120
        return implode("", $buffer);
121
    }
122
    
123
    /**
124
     * Get the array output of iteration hooks.
125
     *
126
     * @param string $name The name of the hook to trigger.
127
     * @return array
128
     */
129
    public static function iterate($name)
130
    {
131
        $buffer = [];
132
        foreach (self::trigger($name) as $hook) {
133
            $buffer = array_merge($buffer, $hook->getIterations());
134
        }
135
        
136
        return $buffer;
137
    }
138
}
139