]> git.mxchange.org Git - friendica.git/blob - src/Core/Addon.php
Merge pull request #6460 from annando/relaying
[friendica.git] / src / Core / Addon.php
1 <?php
2 /**
3  * @file src/Core/Addon.php
4  */
5 namespace Friendica\Core;
6
7 use Friendica\App;
8 use Friendica\BaseObject;
9 use Friendica\Core\Logger;
10 use Friendica\Database\DBA;
11
12 /**
13  * Some functions to handle addons
14  */
15 class Addon extends BaseObject
16 {
17         /**
18          * List of the names of enabled addons
19          *
20          * @var array
21          */
22         private static $addons = [];
23
24         /**
25          * @brief Synchronize addons:
26          *
27          * system.addon contains a comma-separated list of names
28          * of addons which are used on this system.
29          * Go through the database list of already installed addons, and if we have
30          * an entry, but it isn't in the config list, call the uninstall procedure
31          * and mark it uninstalled in the database (for now we'll remove it).
32          * Then go through the config list and if we have a addon that isn't installed,
33          * call the install procedure and add it to the database.
34          *
35          */
36         public static function loadAddons()
37         {
38                 $installed_addons = [];
39
40                 $r = DBA::select('addon', [], ['installed' => 1]);
41                 if (DBA::isResult($r)) {
42                         $installed_addons = DBA::toArray($r);
43                 }
44
45                 $addons = Config::get('system', 'addon');
46                 $addons_arr = [];
47
48                 if ($addons) {
49                         $addons_arr = explode(',', str_replace(' ', '', $addons));
50                 }
51
52                 self::$addons = $addons_arr;
53
54                 $installed_arr = [];
55
56                 foreach ($installed_addons as $addon) {
57                         if (!self::isEnabled($addon['name'])) {
58                                 self::uninstall($addon['name']);
59                         } else {
60                                 $installed_arr[] = $addon['name'];
61                         }
62                 }
63
64                 foreach (self::$addons as $p) {
65                         if (!in_array($p, $installed_arr)) {
66                                 self::install($p);
67                         }
68                 }
69         }
70
71         /**
72          * @brief uninstalls an addon.
73          *
74          * @param string $addon name of the addon
75          * @return boolean
76          */
77         public static function uninstall($addon)
78         {
79                 Logger::log("Addons: uninstalling " . $addon);
80                 DBA::delete('addon', ['name' => $addon]);
81
82                 @include_once('addon/' . $addon . '/' . $addon . '.php');
83                 if (function_exists($addon . '_uninstall')) {
84                         $func = $addon . '_uninstall';
85                         $func();
86                 }
87
88                 unset(self::$addons[array_search($addon, self::$addons)]);
89         }
90
91         /**
92          * @brief installs an addon.
93          *
94          * @param string $addon name of the addon
95          * @return bool
96          */
97         public static function install($addon)
98         {
99                 // silently fail if addon was removed
100
101                 if (!file_exists('addon/' . $addon . '/' . $addon . '.php')) {
102                         return false;
103                 }
104                 Logger::log("Addons: installing " . $addon);
105                 $t = @filemtime('addon/' . $addon . '/' . $addon . '.php');
106                 @include_once('addon/' . $addon . '/' . $addon . '.php');
107                 if (function_exists($addon . '_install')) {
108                         $func = $addon . '_install';
109                         $func();
110
111                         $addon_admin = (function_exists($addon . "_addon_admin") ? 1 : 0);
112
113                         DBA::insert('addon', ['name' => $addon, 'installed' => true,
114                                 'timestamp' => $t, 'plugin_admin' => $addon_admin]);
115
116                         // we can add the following with the previous SQL
117                         // once most site tables have been updated.
118                         // This way the system won't fall over dead during the update.
119
120                         if (file_exists('addon/' . $addon . '/.hidden')) {
121                                 DBA::update('addon', ['hidden' => true], ['name' => $addon]);
122                         }
123
124                         if (!self::isEnabled($addon)) {
125                                 self::$addons[] = $addon;
126                         }
127                         return true;
128                 } else {
129                         Logger::log("Addons: FAILED installing " . $addon);
130                         return false;
131                 }
132         }
133
134         /**
135          * reload all updated addons
136          */
137         public static function reload()
138         {
139                 $addons = Config::get('system', 'addon');
140                 if (strlen($addons)) {
141                         $r = DBA::select('addon', [], ['installed' => 1]);
142                         if (DBA::isResult($r)) {
143                                 $installed = DBA::toArray($r);
144                         } else {
145                                 $installed = [];
146                         }
147
148                         $addon_list = explode(',', $addons);
149
150                         if (count($addon_list)) {
151                                 foreach ($addon_list as $addon) {
152                                         $addon = trim($addon);
153                                         $fname = 'addon/' . $addon . '/' . $addon . '.php';
154
155                                         if (file_exists($fname)) {
156                                                 $t = @filemtime($fname);
157                                                 foreach ($installed as $i) {
158                                                         if (($i['name'] == $addon) && ($i['timestamp'] != $t)) {
159                                                                 Logger::log('Reloading addon: ' . $i['name']);
160                                                                 @include_once($fname);
161
162                                                                 if (function_exists($addon . '_uninstall')) {
163                                                                         $func = $addon . '_uninstall';
164                                                                         $func();
165                                                                 }
166                                                                 if (function_exists($addon . '_install')) {
167                                                                         $func = $addon . '_install';
168                                                                         $func();
169                                                                 }
170                                                                 DBA::update('addon', ['timestamp' => $t], ['id' => $i['id']]);
171                                                         }
172                                                 }
173                                         }
174                                 }
175                         }
176                 }
177         }
178
179         /**
180          * @brief Parse addon comment in search of addon infos.
181          *
182          * like
183          * \code
184          *   * Name: addon
185          *   * Description: An addon which plugs in
186          * . * Version: 1.2.3
187          *   * Author: John <profile url>
188          *   * Author: Jane <email>
189          *   * Maintainer: Jess <email>
190          *   *
191          *   *\endcode
192          * @param string $addon the name of the addon
193          * @return array with the addon information
194          */
195         public static function getInfo($addon)
196         {
197                 $a = self::getApp();
198
199                 $info = [
200                         'name' => $addon,
201                         'description' => "",
202                         'author' => [],
203                         'maintainer' => [],
204                         'version' => "",
205                         'status' => ""
206                 ];
207
208                 if (!is_file("addon/$addon/$addon.php")) {
209                         return $info;
210                 }
211
212                 $stamp1 = microtime(true);
213                 $f = file_get_contents("addon/$addon/$addon.php");
214                 $a->saveTimestamp($stamp1, "file");
215
216                 $r = preg_match("|/\*.*\*/|msU", $f, $m);
217
218                 if ($r) {
219                         $ll = explode("\n", $m[0]);
220                         foreach ($ll as $l) {
221                                 $l = trim($l, "\t\n\r */");
222                                 if ($l != "") {
223                                         $addon_info = array_map("trim", explode(":", $l, 2));
224                                         if (count($addon_info) < 2) {
225                                                 continue;
226                                         }
227
228                                         list($type, $v) = $addon_info;
229                                         $type = strtolower($type);
230                                         if ($type == "author" || $type == "maintainer") {
231                                                 $r = preg_match("|([^<]+)<([^>]+)>|", $v, $m);
232                                                 if ($r) {
233                                                         $info[$type][] = ['name' => $m[1], 'link' => $m[2]];
234                                                 } else {
235                                                         $info[$type][] = ['name' => $v];
236                                                 }
237                                         } else {
238                                                 if (array_key_exists($type, $info)) {
239                                                         $info[$type] = $v;
240                                                 }
241                                         }
242                                 }
243                         }
244                 }
245                 return $info;
246         }
247
248         /**
249          * Checks if the provided addon is enabled
250          *
251          * @param string $addon
252          * @return boolean
253          */
254         public static function isEnabled($addon)
255         {
256                 return in_array($addon, self::$addons);
257         }
258
259         /**
260          * Returns a list of the enabled addon names
261          *
262          * @return array
263          */
264         public static function getEnabledList()
265         {
266                 return self::$addons;
267         }
268
269         /**
270          * Saves the current enabled addon list in the system.addon config key
271          *
272          * @return boolean
273          */
274         public static function saveEnabledList()
275         {
276                 return Config::set("system", "addon", implode(", ", self::$addons));
277         }
278
279         /**
280          * Returns the list of non-hidden enabled addon names
281          *
282          * @return array
283          */
284         public static function getVisibleList()
285         {
286                 $visible_addons = [];
287                 $stmt = DBA::select('addon', ['name'], ['hidden' => false, 'installed' => true]);
288                 if (DBA::isResult($stmt)) {
289                         foreach (DBA::toArray($stmt) as $addon) {
290                                 $visible_addons[] = $addon['name'];
291                         }
292                 }
293
294                 return $visible_addons;
295         }
296
297         /**
298          * Shim of Hook::register left for backward compatibility purpose.
299          *
300          * @see Hook::register
301          * @deprecated since version 2018.12
302          * @param string $hook     the name of the hook
303          * @param string $file     the name of the file that hooks into
304          * @param string $function the name of the function that the hook will call
305          * @param int    $priority A priority (defaults to 0)
306          * @return mixed|bool
307          */
308         public static function registerHook($hook, $file, $function, $priority = 0)
309         {
310                 return Hook::register($hook, $file, $function, $priority);
311         }
312
313         /**
314          * Shim of Hook::unregister left for backward compatibility purpose.
315          *
316          * @see Hook::unregister
317          * @deprecated since version 2018.12
318          * @param string $hook     the name of the hook
319          * @param string $file     the name of the file that hooks into
320          * @param string $function the name of the function that the hook called
321          * @return boolean
322          */
323         public static function unregisterHook($hook, $file, $function)
324         {
325                 return Hook::unregister($hook, $file, $function);
326         }
327
328         /**
329          * Shim of Hook::callAll left for backward-compatibility purpose.
330          *
331          * @see Hook::callAll
332          * @deprecated since version 2018.12
333          * @param string       $name  of the hook to call
334          * @param string|array &$data to transmit to the callback handler
335          */
336         public static function callHooks($name, &$data = null)
337         {
338                 Hook::callAll($name, $data);
339         }
340 }