]> git.mxchange.org Git - friendica.git/blob - src/Core/Addon.php
af1d71ac4ec3445ca8e0b9098c00b0394b6d9634
[friendica.git] / src / Core / Addon.php
1 <?php\r
2 /**\r
3  * @file src/Core/Addon.php\r
4  */\r
5 namespace Friendica\Core;\r
6 \r
7 use Friendica\Core\Config;\r
8 use Friendica\Database\DBM;\r
9 \r
10 use dba;\r
11 \r
12 require_once 'include/dba.php';\r
13 \r
14 /**\r
15  * Some functions to handle addons\r
16  */\r
17 class Addon\r
18 {\r
19         /**\r
20          * @brief uninstalls an addon.\r
21          *\r
22          * @param string $addon name of the addon\r
23          * @return boolean\r
24          */\r
25         public static function uninstall($addon)\r
26         {\r
27                 logger("Addons: uninstalling " . $addon);\r
28                 dba::delete('addon', ['name' => $addon]);\r
29 \r
30                 @include_once('addon/' . $addon . '/' . $addon . '.php');\r
31                 if (function_exists($addon . '_uninstall')) {\r
32                         $func = $addon . '_uninstall';\r
33                         $func();\r
34                 }\r
35         }\r
36 \r
37         /**\r
38          * @brief installs an addon.\r
39          *\r
40          * @param string $addon name of the addon\r
41          * @return bool\r
42          */\r
43         public static function install($addon)\r
44         {\r
45                 // silently fail if addon was removed\r
46 \r
47                 if (!file_exists('addon/' . $addon . '/' . $addon . '.php')) {\r
48                         return false;\r
49                 }\r
50                 logger("Addons: installing " . $addon);\r
51                 $t = @filemtime('addon/' . $addon . '/' . $addon . '.php');\r
52                 @include_once('addon/' . $addon . '/' . $addon . '.php');\r
53                 if (function_exists($addon . '_install')) {\r
54                         $func = $addon . '_install';\r
55                         $func();\r
56 \r
57                         $addon_admin = (function_exists($addon."_addon_admin") ? 1 : 0);\r
58 \r
59                         dba::insert('addon', ['name' => $addon, 'installed' => true,\r
60                                                 'timestamp' => $t, 'plugin_admin' => $addon_admin]);\r
61 \r
62                         // we can add the following with the previous SQL\r
63                         // once most site tables have been updated.\r
64                         // This way the system won't fall over dead during the update.\r
65 \r
66                         if (file_exists('addon/' . $addon . '/.hidden')) {\r
67                                 dba::update('addon', ['hidden' => true], ['name' => $addon]);\r
68                         }\r
69                         return true;\r
70                 } else {\r
71                         logger("Addons: FAILED installing " . $addon);\r
72                         return false;\r
73                 }\r
74         }\r
75 \r
76         /**\r
77          * reload all updated addons\r
78          */\r
79         public static function reload()\r
80         {\r
81                 $addons = Config::get('system', 'addon');\r
82                 if (strlen($addons)) {\r
83                         $r = dba::select('addon', [], ['installed' => 1]);\r
84                         if (DBM::is_result($r)) {\r
85                                 $installed = dba::inArray($r);\r
86                         } else {\r
87                                 $installed = [];\r
88                         }\r
89 \r
90                         $addon_list = explode(',', $addons);\r
91 \r
92                         if (count($addon_list)) {\r
93                                 foreach ($addon_list as $addon) {\r
94                                         $addon = trim($addon);\r
95                                         $fname = 'addon/' . $addon . '/' . $addon . '.php';\r
96 \r
97                                         if (file_exists($fname)) {\r
98                                                 $t = @filemtime($fname);\r
99                                                 foreach ($installed as $i) {\r
100                                                         if (($i['name'] == $addon) && ($i['timestamp'] != $t)) {\r
101                                                                 logger('Reloading addon: ' . $i['name']);\r
102                                                                 @include_once($fname);\r
103 \r
104                                                                 if (function_exists($addon . '_uninstall')) {\r
105                                                                         $func = $addon . '_uninstall';\r
106                                                                         $func();\r
107                                                                 }\r
108                                                                 if (function_exists($addon . '_install')) {\r
109                                                                         $func = $addon . '_install';\r
110                                                                         $func();\r
111                                                                 }\r
112                                                                 dba::update('addon', ['timestamp' => $t], ['id' => $i['id']]);\r
113                                                         }\r
114                                                 }\r
115                                         }\r
116                                 }\r
117                         }\r
118                 }\r
119         }\r
120 \r
121         /**\r
122          * @brief check if addon is enabled\r
123          *\r
124          * @param string $addon\r
125          * @return boolean\r
126          */\r
127         public static function isEnabled($addon)\r
128         {\r
129                 return dba::exists('addon', ['installed' => true, 'name' => $addon]);\r
130         }\r
131 \r
132 \r
133         /**\r
134          * @brief registers a hook.\r
135          *\r
136          * @param string $hook the name of the hook\r
137          * @param string $file the name of the file that hooks into\r
138          * @param string $function the name of the function that the hook will call\r
139          * @param int $priority A priority (defaults to 0)\r
140          * @return mixed|bool\r
141          */\r
142         public static function registerHook($hook, $file, $function, $priority = 0)\r
143         {\r
144                 $condition = ['hook' => $hook, 'file' => $file, 'function' => $function];\r
145                 $exists = dba::exists('hook', $condition);\r
146                 if ($exists) {\r
147                         return true;\r
148                 }\r
149 \r
150                 $r = dba::insert('hook', ['hook' => $hook, 'file' => $file, 'function' => $function, 'priority' => $priority]);\r
151 \r
152                 return $r;\r
153         }\r
154 \r
155         /**\r
156          * @brief unregisters a hook.\r
157          *\r
158          * @param string $hook the name of the hook\r
159          * @param string $file the name of the file that hooks into\r
160          * @param string $function the name of the function that the hook called\r
161          * @return array\r
162          */\r
163         public static function unregisterHook($hook, $file, $function)\r
164         {\r
165                 $condition = ['hook' => $hook, 'file' => $file, 'function' => $function];\r
166                 $r = dba::delete('hook', $condition);\r
167                 return $r;\r
168         }\r
169 \r
170         /**\r
171          * Load hooks\r
172          */\r
173         public static function loadHooks()\r
174         {\r
175                 $a = get_app();\r
176                 $a->hooks = [];\r
177                 $r = dba::select('hook', ['hook', 'file', 'function'], [], ['order' => ['priority' => 'desc', 'file']]);\r
178 \r
179                 while ($rr = dba::fetch($r)) {\r
180                         if (! array_key_exists($rr['hook'], $a->hooks)) {\r
181                                 $a->hooks[$rr['hook']] = [];\r
182                         }\r
183                         $a->hooks[$rr['hook']][] = [$rr['file'],$rr['function']];\r
184                 }\r
185                 dba::close($r);\r
186         }\r
187 \r
188         /**\r
189          * @brief Calls a hook.\r
190          *\r
191          * Use this function when you want to be able to allow a hook to manipulate\r
192          * the provided data.\r
193          *\r
194          * @param string $name of the hook to call\r
195          * @param string|array &$data to transmit to the callback handler\r
196          */\r
197         public static function callHooks($name, &$data = null)\r
198         {\r
199                 $a = get_app();\r
200 \r
201                 if (is_array($a->hooks) && array_key_exists($name, $a->hooks)) {\r
202                         foreach ($a->hooks[$name] as $hook) {\r
203                                 self::callSingleHook($a, $name, $hook, $data);\r
204                         }\r
205                 }\r
206         }\r
207 \r
208         /**\r
209          * @brief Calls a single hook.\r
210          *\r
211          * @param string $name of the hook to call\r
212          * @param array $hook Hook data\r
213          * @param string|array &$data to transmit to the callback handler\r
214          */\r
215         public static function callSingleHook($a, $name, $hook, &$data = null)\r
216         {\r
217                 // Don't run a theme's hook if the user isn't using the theme\r
218                 if (strpos($hook[0], 'view/theme/') !== false && strpos($hook[0], 'view/theme/'.current_theme()) === false) {\r
219                         return;\r
220                 }\r
221 \r
222                 @include_once($hook[0]);\r
223                 if (function_exists($hook[1])) {\r
224                         $func = $hook[1];\r
225                         $func($a, $data);\r
226                 } else {\r
227                         // remove orphan hooks\r
228                         $condition = ['hook' => $name, 'file' => $hook[0], 'function' => $hook[1]];\r
229                         dba::delete('hook', $condition);\r
230                 }\r
231         }\r
232 \r
233         /**\r
234          * check if an app_menu hook exist for addon $name.\r
235          * Return true if the addon is an app\r
236          */\r
237         public static function isApp($name)\r
238         {\r
239                 $a = get_app();\r
240 \r
241                 if (is_array($a->hooks) && (array_key_exists('app_menu', $a->hooks))) {\r
242                         foreach ($a->hooks['app_menu'] as $hook) {\r
243                                 if ($hook[0] == 'addon/'.$name.'/'.$name.'.php') {\r
244                                         return true;\r
245                                 }\r
246                         }\r
247                 }\r
248 \r
249                 return false;\r
250         }\r
251 \r
252         /**\r
253          * @brief Parse addon comment in search of addon infos.\r
254          *\r
255          * like\r
256          * \code\r
257          *   * Name: addon\r
258          *   * Description: An addon which plugs in\r
259          * . * Version: 1.2.3\r
260          *   * Author: John <profile url>\r
261          *   * Author: Jane <email>\r
262          *   * Maintainer: Jess <email>\r
263          *   *\r
264          *   *\endcode\r
265          * @param string $addon the name of the addon\r
266          * @return array with the addon information\r
267          */\r
268         public static function getInfo($addon)\r
269         {\r
270                 $a = get_app();\r
271 \r
272                 $info = [\r
273                         'name' => $addon,\r
274                         'description' => "",\r
275                         'author' => [],\r
276                         'maintainer' => [],\r
277                         'version' => "",\r
278                         'status' => ""\r
279                 ];\r
280 \r
281                 if (!is_file("addon/$addon/$addon.php")) {\r
282                         return $info;\r
283                 }\r
284 \r
285                 $stamp1 = microtime(true);\r
286                 $f = file_get_contents("addon/$addon/$addon.php");\r
287                 $a->save_timestamp($stamp1, "file");\r
288 \r
289                 $r = preg_match("|/\*.*\*/|msU", $f, $m);\r
290 \r
291                 if ($r) {\r
292                         $ll = explode("\n", $m[0]);\r
293                         foreach ($ll as $l) {\r
294                                 $l = trim($l, "\t\n\r */");\r
295                                 if ($l != "") {\r
296                                         list($type, $v) = array_map("trim", explode(":", $l, 2));\r
297                                         $type = strtolower($type);\r
298                                         if ($type == "author" || $type == "maintainer") {\r
299                                                 $r = preg_match("|([^<]+)<([^>]+)>|", $v, $m);\r
300                                                 if ($r) {\r
301                                                         $info[$type][] = ['name' => $m[1], 'link' => $m[2]];\r
302                                                 } else {\r
303                                                         $info[$type][] = ['name' => $v];\r
304                                                 }\r
305                                         } else {\r
306                                                 if (array_key_exists($type, $info)) {\r
307                                                         $info[$type] = $v;\r
308                                                 }\r
309                                         }\r
310                                 }\r
311                         }\r
312                 }\r
313                 return $info;\r
314         }\r
315 }\r