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