]> git.mxchange.org Git - friendica.git/blob - src/Core/Hook.php
3053db7a1d429e174b5a3ee702f650b721636e0b
[friendica.git] / src / Core / Hook.php
1 <?php
2 /**
3  * @file src/Core/Hook.php
4  */
5 namespace Friendica\Core;
6
7 use Friendica\App;
8 use Friendica\BaseObject;
9 use Friendica\Database\DBA;
10
11 require_once 'include/dba.php';
12
13 /**
14  * Some functions to handle hooks
15  */
16 class Hook extends BaseObject
17 {
18         /**
19          * Array of registered hooks
20          *
21          * Format:
22          * [
23          *              ["<hook name>"] => [
24          *                      0 => "<hook file>",
25          *                      1 => "<hook function name>"
26          *              ],
27          *              ...
28          * ]
29          *
30          * @var array
31          */
32         private static $hooks = [];
33
34         /**
35          * Load hooks
36          */
37         public static function loadHooks()
38         {
39                 self::$hooks = [];
40                 $stmt = DBA::select('hook', ['hook', 'file', 'function'], [], ['order' => ['priority' => 'desc', 'file']]);
41
42                 while ($hook = DBA::fetch($stmt)) {
43                         if (!array_key_exists($hook['hook'], self::$hooks)) {
44                                 self::$hooks[$hook['hook']] = [];
45                         }
46                         self::$hooks[$hook['hook']][] = [$hook['file'], $hook['function']];
47                 }
48                 DBA::close($stmt);
49         }
50
51         /**
52          * Registers a hook.
53          *
54          * @param string $hook     the name of the hook
55          * @param string $file     the name of the file that hooks into
56          * @param string $function the name of the function that the hook will call
57          * @param int    $priority A priority (defaults to 0)
58          * @return mixed|bool
59          */
60         public static function register($hook, $file, $function, $priority = 0)
61         {
62                 $file = str_replace(self::getApp()->getBasePath() . DIRECTORY_SEPARATOR, '', $file);
63
64                 $condition = ['hook' => $hook, 'file' => $file, 'function' => $function];
65                 if (DBA::exists('hook', $condition)) {
66                         return true;
67                 }
68
69                 $result = DBA::insert('hook', ['hook' => $hook, 'file' => $file, 'function' => $function, 'priority' => $priority]);
70
71                 return $result;
72         }
73
74         /**
75          * Unregisters a hook.
76          *
77          * @param string $hook     the name of the hook
78          * @param string $file     the name of the file that hooks into
79          * @param string $function the name of the function that the hook called
80          * @return boolean
81          */
82         public static function unregister($hook, $file, $function)
83         {
84                 $relative_file = str_replace(self::getApp()->getBasePath() . DIRECTORY_SEPARATOR, '', $file);
85
86                 // This here is only needed for fixing a problem that existed on the develop branch
87                 $condition = ['hook' => $hook, 'file' => $file, 'function' => $function];
88                 DBA::delete('hook', $condition);
89
90                 $condition = ['hook' => $hook, 'file' => $relative_file, 'function' => $function];
91                 $result = DBA::delete('hook', $condition);
92                 return $result;
93         }
94
95         /**
96          * Returns the list of callbacks for a single hook
97          *
98          * @param  string $name
99          * @return array
100          */
101         public static function getByName($name)
102         {
103                 $return = [];
104
105                 if (isset(self::$hooks[$name])) {
106                         $return = self::$hooks[$name];
107                 }
108
109                 return $return;
110         }
111
112         /**
113          * @brief Forks a hook.
114          *
115          * Use this function when you want to fork a hook via the worker.
116          *
117          * @param string       $name of the hook to call
118          * @param string|array $data to transmit to the callback handler
119          */
120         public static function fork($priority, $name, $data = null)
121         {
122                 if (array_key_exists($name, self::$hooks)) {
123                         foreach (self::$hooks[$name] as $hook) {
124                                 Worker::add($priority, 'ForkHook', $name, $hook, $data);
125                         }
126                 }
127         }
128
129         /**
130          * @brief Calls a hook.
131          *
132          * Use this function when you want to be able to allow a hook to manipulate
133          * the provided data.
134          *
135          * @param string       $name  of the hook to call
136          * @param string|array &$data to transmit to the callback handler
137          */
138         public static function callAll($name, &$data = null)
139         {
140                 if (array_key_exists($name, self::$hooks)) {
141                         foreach (self::$hooks[$name] as $hook) {
142                                 self::callSingle(self::getApp(), $name, $hook, $data);
143                         }
144                 }
145         }
146
147         /**
148          * @brief Calls a single hook.
149          *
150          * @param App $a
151          * @param string         $name of the hook to call
152          * @param array          $hook Hook data
153          * @param string|array   &$data to transmit to the callback handler
154          */
155         public static function callSingle(App $a, $name, $hook, &$data = null)
156         {
157                 // Don't run a theme's hook if the user isn't using the theme
158                 if (strpos($hook[0], 'view/theme/') !== false && strpos($hook[0], 'view/theme/' . $a->getCurrentTheme()) === false) {
159                         return;
160                 }
161
162                 @include_once($hook[0]);
163                 if (function_exists($hook[1])) {
164                         $func = $hook[1];
165                         $func($a, $data);
166                 } else {
167                         // remove orphan hooks
168                         $condition = ['hook' => $name, 'file' => $hook[0], 'function' => $hook[1]];
169                         DBA::delete('hook', $condition, ['cascade' => false]);
170                 }
171         }
172
173         /**
174          * check if an app_menu hook exist for addon $name.
175          * Return true if the addon is an app
176          */
177         public static function isAddonApp($name)
178         {
179                 if (array_key_exists('app_menu', self::$hooks)) {
180                         foreach (self::$hooks['app_menu'] as $hook) {
181                                 if ($hook[0] == 'addon/' . $name . '/' . $name . '.php') {
182                                         return true;
183                                 }
184                         }
185                 }
186
187                 return false;
188         }
189 }