Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
30 / 30
17.14% covered (danger)
17.14%
12 / 70
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
Hook
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
30 / 30
17.14% covered (danger)
17.14%
12 / 70
100.00% covered (success)
100.00%
5 / 5
271.86
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
8 / 8
66.67% covered (warning)
66.67%
4 / 6
100.00% covered (success)
100.00%
1 / 1
4.59
 remove
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 replace
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
17 / 17
6.67% covered (danger)
6.67%
4 / 60
100.00% covered (success)
100.00%
1 / 1
74.86
 rebind
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 inject
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3namespace GorillaClaw;
4
5class Hook
6{
7    public $function_key;
8    public $callback;
9    public $hook_name;
10    public $priority;
11    public $that;
12    public $original_callback;
13    
14    /**
15     * __construct
16     *
17     * @param  mixed $hook_name
18     * @param  mixed $callback
19     * @param  mixed $priority
20     * @param  mixed $function_key
21     * @return void
22     */
23    
24    function __construct($hook_name, $callback, $priority, $function_key)
25    {
26        global $wp_filter;
27
28        $this->function_key = $function_key;
29        $this->callback = $callback;
30        $this->hook_name = $hook_name;
31        $this->priority = $priority;
32        $this->that = null;
33        $this->original_callback = isset($wp_filter[$this->hook_name]) ? $wp_filter[$this->hook_name]->callbacks[$this->priority][$this->function_key]['function'] : false;
34
35        if (is_array($callback['function'])) {
36            if (is_object($callback['function'][0])) { 
37                $this->that = &$callback['function'][0];
38            } else {
39                $this->that = $callback['function'][0];
40            }
41        }
42    }
43    
44    /**
45     * Remove and un-hook the handler
46     *
47     * @return bool `true` on success
48     */
49    
50    public function remove(): bool
51    {
52        return remove_filter($this->hook_name, $this->callback['function'], $this->priority);
53    }
54    
55    /**
56     * replace
57     *
58     * @param  mixed $callback
59     * @return bool 
60     */
61    
62    public function replace(callable $callback): bool
63    {
64        global $wp_filter;
65        if (
66            isset($wp_filter[$this->hook_name]) &&
67            isset($wp_filter[$this->hook_name]->callbacks[$this->priority]) &&
68            isset($wp_filter[$this->hook_name]->callbacks[$this->priority][$this->function_key])
69        ) {
70
71            if (!is_null($this->that) && is_object($this->that)) {
72                // $this rebinding
73                $wp_filter[$this->hook_name]->callbacks[$this->priority][$this->function_key]['function'] = (new HookProxy($callback, $this->that))->__cb;
74                $this->callback['function'] = [&$this->that, $callback];
75            } elseif (!is_null($this->that) && is_string($this->that)) {
76                // Static binding
77                $wp_filter[$this->hook_name]->callbacks[$this->priority][$this->function_key]['function'] = $callback;
78                $this->callback['function'] =  $callback;
79            } elseif (is_null($this->that)) {
80                // No rescoping or binding
81                $wp_filter[$this->hook_name]->callbacks[$this->priority][$this->function_key]['function'] = $callback;
82                $this->callback['function'] = $callback;
83            } 
84            
85            return true;
86        }
87
88        return false;
89    }
90        
91    /**
92     * rebind
93     *
94     * @param  mixed $hook_name
95     * @param  mixed $callback
96     * @param  mixed $priority
97     * @param  mixed $accepted_args
98     * @return void
99     */
100
101    public function rebind(string $hook_name, callable $callback, int $priority = 10, $accepted_args = 1) {
102        if(is_null($this->that)) {
103            throw new \ErrorException('Cannot rebind from a non-object hook');
104        }
105
106        add_filter($hook_name, (new HookProxy($callback, $this->that))->__cb, $priority, $accepted_args);
107    }
108
109    public function inject($before, $after = false) {
110        $original_callback = &$this->original_callback;
111
112        $this->replace(function(...$args) use ($before, $after, $original_callback) {
113            if($before) {
114                if(_is_callable_object($original_callback)) {
115                    $args[0] = (new HookProxy($before, $original_callback[0]))->__cb(...$args); 
116                } else {
117                    $args[0] = $before(...$args);
118                }
119            }
120                    
121            $args[0] = call_user_func_array($original_callback, $args);
122            
123            if($after) {
124                if(_is_callable_object($original_callback)) {
125                    $args[0] = (new HookProxy($after, $original_callback[0]))->__cb(...$args); 
126                } else {
127                    $args[0] = $after(...$args);
128                }
129            }
130
131            return $args[0];
132        });
133    }
134}