1 | <?php |
||||
2 | |||||
3 | use Elgg\Application; |
||||
4 | use Elgg\Includer; |
||||
5 | |||||
6 | /** |
||||
7 | * Stores site-side plugin settings as private data. |
||||
8 | * |
||||
9 | * This class is currently a stub, allowing a plugin to |
||||
10 | * save settings in an object's private settings for each site. |
||||
11 | */ |
||||
12 | class ElggPlugin extends ElggObject { |
||||
13 | |||||
14 | /** |
||||
15 | * @var ElggPluginPackage |
||||
16 | */ |
||||
17 | protected $package; |
||||
18 | |||||
19 | /** |
||||
20 | * @var ElggPluginManifest |
||||
21 | */ |
||||
22 | protected $manifest; |
||||
23 | |||||
24 | /** |
||||
25 | * @var string |
||||
26 | */ |
||||
27 | protected $path; |
||||
28 | |||||
29 | /** |
||||
30 | * Data from static config file. null if not yet read. |
||||
31 | * |
||||
32 | * @var array|null |
||||
33 | */ |
||||
34 | protected $static_config; |
||||
35 | |||||
36 | /** |
||||
37 | * @var string |
||||
38 | */ |
||||
39 | protected $errorMsg = ''; |
||||
40 | |||||
41 | /** |
||||
42 | * @var bool |
||||
43 | */ |
||||
44 | protected $activated; |
||||
45 | |||||
46 | /** |
||||
47 | * {@inheritdoc} |
||||
48 | */ |
||||
49 | 374 | protected function initializeAttributes() { |
|||
50 | 374 | parent::initializeAttributes(); |
|||
51 | |||||
52 | 374 | $this->attributes['subtype'] = "plugin"; |
|||
53 | 374 | } |
|||
54 | |||||
55 | /** |
||||
56 | * Load a plugin object from its ID |
||||
57 | * Create a new plugin entity if doesn't exist |
||||
58 | * |
||||
59 | * @param string $plugin_id Plugin ID |
||||
60 | * @param string $path Path, defaults to /mod |
||||
61 | * |
||||
62 | * @return ElggPlugin |
||||
63 | * @throws PluginException |
||||
64 | */ |
||||
65 | 356 | public static function fromId($plugin_id, $path = null) { |
|||
66 | 356 | if (empty($plugin_id)) { |
|||
67 | 1 | throw new InvalidArgumentException('Plugin ID must be set'); |
|||
68 | } |
||||
69 | |||||
70 | 355 | $plugin = elgg_get_plugin_from_id($plugin_id); |
|||
71 | |||||
72 | 355 | if (!$plugin) { |
|||
73 | 8 | $ia = _elgg_services()->session->setIgnoreAccess(true); |
|||
74 | 8 | $plugin = new ElggPlugin(); |
|||
75 | 8 | $plugin->title = $plugin_id; |
|||
76 | 8 | $plugin->save(); |
|||
77 | |||||
78 | 8 | _elgg_services()->session->setIgnoreAccess($ia); |
|||
79 | } |
||||
80 | |||||
81 | 355 | if (!$path) { |
|||
82 | 337 | $path = elgg_get_plugins_path(); |
|||
83 | } |
||||
84 | |||||
85 | 355 | $path = rtrim($path, '/'); |
|||
86 | 355 | $plugin->setPath($path . '/' . $plugin_id); |
|||
87 | |||||
88 | 355 | return $plugin; |
|||
89 | } |
||||
90 | |||||
91 | /** |
||||
92 | * {@inheritdoc} |
||||
93 | */ |
||||
94 | 10 | public function save() { |
|||
95 | |||||
96 | 10 | $site = elgg_get_site_entity(); |
|||
97 | |||||
98 | 10 | $this->attributes['owner_guid'] = $site->guid; |
|||
99 | 10 | $this->attributes['container_guid'] = $site->guid; |
|||
100 | 10 | $this->attributes['access_id'] = ACCESS_PUBLIC; |
|||
101 | |||||
102 | 10 | $new = !$this->guid; |
|||
103 | 10 | $priority = null; |
|||
104 | 10 | if ($new) { |
|||
105 | 10 | $name = _elgg_services()->plugins->namespacePrivateSetting('internal', 'priority'); |
|||
106 | 10 | $priority = elgg_extract($name, $this->temp_private_settings, 'new'); |
|||
107 | 2 | } elseif ($this->getPriority() === null) { |
|||
108 | $priority = 'last'; |
||||
109 | } |
||||
110 | |||||
111 | 10 | if ($priority) { |
|||
112 | 10 | $this->setPriority($priority); |
|||
113 | } |
||||
114 | |||||
115 | 10 | return parent::save(); |
|||
116 | } |
||||
117 | |||||
118 | /** |
||||
119 | * Returns the ID (dir name) of this plugin |
||||
120 | * |
||||
121 | * @return string |
||||
122 | */ |
||||
123 | 408 | public function getID() { |
|||
124 | 408 | return $this->title; |
|||
125 | } |
||||
126 | |||||
127 | /** |
||||
128 | * Returns the manifest's name if available, otherwise the ID. |
||||
129 | * |
||||
130 | * @return string |
||||
131 | * @since 3.0 |
||||
132 | */ |
||||
133 | 2 | public function getDisplayName() { |
|||
134 | 2 | $manifest = $this->getManifest(); |
|||
135 | 2 | if ($manifest) { |
|||
136 | 1 | return $manifest->getName(); |
|||
137 | } |
||||
138 | |||||
139 | 1 | return $this->getID(); |
|||
140 | } |
||||
141 | |||||
142 | /** |
||||
143 | * Set path |
||||
144 | * |
||||
145 | * @param string $path Path to plugin directory |
||||
146 | * |
||||
147 | * @return void |
||||
148 | * @access private |
||||
149 | */ |
||||
150 | 396 | public function setPath($path) { |
|||
151 | 396 | $this->path = \Elgg\Project\Paths::sanitize($path, true); |
|||
152 | 396 | } |
|||
153 | |||||
154 | /** |
||||
155 | * Returns the plugin's full path with trailing slash. |
||||
156 | * |
||||
157 | * @return string |
||||
158 | */ |
||||
159 | 394 | public function getPath() { |
|||
160 | 394 | if (isset($this->path)) { |
|||
161 | 392 | return $this->path; |
|||
162 | } |
||||
163 | |||||
164 | 54 | $this->setPath(elgg_get_plugins_path() . $this->getID()); |
|||
165 | 54 | return $this->path; |
|||
166 | } |
||||
167 | |||||
168 | /** |
||||
169 | * Returns the plugin's languages directory full path with trailing slash. |
||||
170 | * Returns false if directory does not exist |
||||
171 | * |
||||
172 | * @return string|false |
||||
173 | */ |
||||
174 | 206 | public function getLanguagesPath() { |
|||
175 | 206 | $languages_path = $this->getPath() . 'languages/'; |
|||
176 | 206 | if (!is_dir($languages_path)) { |
|||
177 | 58 | return false; |
|||
178 | } |
||||
179 | |||||
180 | 196 | return $languages_path; |
|||
181 | } |
||||
182 | |||||
183 | /** |
||||
184 | * Get a value from the plugins's static config file. |
||||
185 | * |
||||
186 | * @note If the system cache is on, Elgg APIs should not call this on every request. |
||||
187 | * |
||||
188 | * @param string $key Config key |
||||
189 | * @param mixed $default Value returned if missing |
||||
190 | * |
||||
191 | * @return mixed |
||||
192 | * @access private |
||||
193 | * @internal For Elgg internal use only |
||||
194 | */ |
||||
195 | 200 | public function getStaticConfig($key, $default = null) { |
|||
196 | 200 | if ($this->static_config === null) { |
|||
197 | 194 | $this->static_config = []; |
|||
198 | |||||
199 | try { |
||||
200 | 194 | if ($this->canReadFile(ElggPluginPackage::STATIC_CONFIG_FILENAME)) { |
|||
201 | 194 | $this->static_config = $this->includeFile(ElggPluginPackage::STATIC_CONFIG_FILENAME); |
|||
202 | } |
||||
203 | } catch (PluginException $ex) { |
||||
204 | elgg_log($ex, \Psr\Log\LogLevel::ERROR); |
||||
205 | } |
||||
206 | } |
||||
207 | |||||
208 | 200 | if (isset($this->static_config[$key])) { |
|||
209 | 190 | return $this->static_config[$key]; |
|||
210 | } else { |
||||
211 | 199 | return $default; |
|||
212 | } |
||||
213 | } |
||||
214 | |||||
215 | /** |
||||
216 | * Returns an array of available markdown files for this plugin |
||||
217 | * |
||||
218 | * @return array |
||||
219 | */ |
||||
220 | 1 | public function getAvailableTextFiles() { |
|||
221 | 1 | $filenames = $this->getPackage()->getTextFilenames(); |
|||
222 | |||||
223 | 1 | $files = []; |
|||
224 | 1 | foreach ($filenames as $filename) { |
|||
225 | 1 | if ($this->canReadFile($filename)) { |
|||
226 | 1 | $files[$filename] = "{$this->getPath()}{$filename}"; |
|||
227 | } |
||||
228 | } |
||||
229 | |||||
230 | 1 | return $files; |
|||
231 | } |
||||
232 | |||||
233 | // Load Priority |
||||
234 | |||||
235 | /** |
||||
236 | * Gets the plugin's load priority. |
||||
237 | * |
||||
238 | * @return int|null |
||||
239 | */ |
||||
240 | 15 | public function getPriority() { |
|||
241 | 15 | $name = _elgg_services()->plugins->namespacePrivateSetting('internal', 'priority'); |
|||
242 | |||||
243 | 15 | $priority = $this->getPrivateSetting($name); |
|||
244 | 15 | if (isset($priority)) { |
|||
245 | 8 | return (int) $priority; |
|||
246 | } |
||||
247 | |||||
248 | 11 | return null; |
|||
249 | } |
||||
250 | |||||
251 | /** |
||||
252 | * Sets the priority of the plugin |
||||
253 | * Returns the new priority or false on error |
||||
254 | * |
||||
255 | * @param mixed $priority The priority to set |
||||
256 | * One of +1, -1, first, last, or a number. |
||||
257 | * If given a number, this will displace all plugins at that number |
||||
258 | * and set their priorities +1 |
||||
259 | * |
||||
260 | * @return int|false |
||||
261 | * @throws DatabaseException |
||||
262 | */ |
||||
263 | 10 | public function setPriority($priority) { |
|||
264 | 10 | $priority = $this->normalizePriority($priority); |
|||
265 | |||||
266 | 10 | return _elgg_services()->plugins->setPriority($this, $priority); |
|||
267 | } |
||||
268 | |||||
269 | /** |
||||
270 | * Normalize and validate new priority |
||||
271 | * |
||||
272 | * @param mixed $priority Priority to normalize |
||||
273 | * |
||||
274 | * @return int |
||||
275 | * @access private |
||||
276 | */ |
||||
277 | 10 | public function normalizePriority($priority) { |
|||
278 | // if no priority assume a priority of 1 |
||||
279 | 10 | $old_priority = $this->getPriority(); |
|||
280 | 10 | $old_priority = $old_priority ? : 1; |
|||
281 | 10 | $max_priority = _elgg_get_max_plugin_priority() ? : 1; |
|||
282 | |||||
283 | // can't use switch here because it's not strict and php evaluates +1 == 1 |
||||
284 | 10 | if ($priority === '+1') { |
|||
285 | 1 | $priority = $old_priority + 1; |
|||
286 | 10 | } else if ($priority === '-1') { |
|||
287 | 1 | $priority = $old_priority - 1; |
|||
288 | 10 | } else if ($priority === 'first') { |
|||
289 | 1 | $priority = 1; |
|||
290 | 10 | } else if ($priority === 'last') { |
|||
291 | 1 | $priority = $max_priority; |
|||
292 | 10 | } else if ($priority === 'new') { |
|||
293 | 10 | $max_priority++; |
|||
294 | 10 | $priority = $max_priority; |
|||
295 | } |
||||
296 | |||||
297 | 10 | return min($max_priority, max(1, (int) $priority)); |
|||
298 | } |
||||
299 | |||||
300 | // Plugin settings |
||||
301 | |||||
302 | /** |
||||
303 | * Returns a plugin setting |
||||
304 | * |
||||
305 | * @param string $name The setting name |
||||
306 | * @param mixed $default The default value to return if none is set |
||||
307 | * |
||||
308 | * @return mixed |
||||
309 | */ |
||||
310 | 4 | public function getSetting($name, $default = null) { |
|||
311 | 4 | $values = $this->getAllSettings(); |
|||
312 | 4 | return elgg_extract($name, $values, $default); |
|||
313 | } |
||||
314 | |||||
315 | /** |
||||
316 | * Returns an array of all settings saved for this plugin. |
||||
317 | * |
||||
318 | * @note Unlike user settings, plugin settings are not namespaced. |
||||
319 | * |
||||
320 | * @return array An array of key/value pairs. |
||||
321 | */ |
||||
322 | 41 | public function getAllSettings() { |
|||
323 | |||||
324 | try { |
||||
325 | 41 | $defaults = []; |
|||
326 | 41 | if ($this->isActive()) { |
|||
327 | // only load settings from static config for active plugins to prevent issues |
||||
328 | // with internal plugin references ie. classes and language keys |
||||
329 | 36 | $defaults = $this->getStaticConfig('settings', []); |
|||
330 | } |
||||
331 | |||||
332 | 41 | if (!$this->guid) { |
|||
333 | 1 | $settings = $this->temp_private_settings; |
|||
334 | } else { |
||||
335 | 40 | $settings = _elgg_services()->plugins->getAllSettings($this); |
|||
336 | } |
||||
337 | |||||
338 | 41 | return array_merge($defaults, $settings); |
|||
339 | } catch (DatabaseException $ex) { |
||||
340 | return []; |
||||
341 | } |
||||
342 | } |
||||
343 | |||||
344 | /** |
||||
345 | * Set a plugin setting for the plugin |
||||
346 | * |
||||
347 | * @param string $name The name to set |
||||
348 | * @param string $value The value to set |
||||
349 | * |
||||
350 | * @return bool |
||||
351 | */ |
||||
352 | 8 | public function setSetting($name, $value) { |
|||
353 | |||||
354 | 8 | $value = _elgg_services()->hooks->trigger('setting', 'plugin', [ |
|||
355 | 8 | 'plugin_id' => $this->getID(), |
|||
356 | 8 | 'plugin' => $this, |
|||
357 | 8 | 'name' => $name, |
|||
358 | 8 | 'value' => $value, |
|||
359 | 8 | ], $value); |
|||
360 | |||||
361 | 8 | if (is_array($value)) { |
|||
362 | 1 | elgg_log('Plugin settings cannot store arrays.', 'ERROR'); |
|||
363 | |||||
364 | 1 | return false; |
|||
365 | } |
||||
366 | |||||
367 | 8 | return $this->setPrivateSetting($name, $value); |
|||
368 | } |
||||
369 | |||||
370 | /** |
||||
371 | * Removes a plugin setting name and value |
||||
372 | * |
||||
373 | * @param string $name The setting name to remove |
||||
374 | * |
||||
375 | * @return bool |
||||
376 | */ |
||||
377 | 2 | public function unsetSetting($name) { |
|||
378 | 2 | return $this->removePrivateSetting($name); |
|||
379 | } |
||||
380 | |||||
381 | /** |
||||
382 | * Removes all settings for this plugin |
||||
383 | * @return bool |
||||
384 | */ |
||||
385 | 1 | public function unsetAllSettings() { |
|||
386 | 1 | $settings = $this->getAllSettings(); |
|||
387 | |||||
388 | 1 | foreach ($settings as $name => $value) { |
|||
389 | 1 | if (strpos($name, 'elgg:internal:') === 0) { |
|||
390 | 1 | continue; |
|||
391 | } |
||||
392 | 1 | $this->unsetSetting($name); |
|||
393 | } |
||||
394 | |||||
395 | 1 | return true; |
|||
396 | } |
||||
397 | |||||
398 | |||||
399 | // User settings |
||||
400 | |||||
401 | /** |
||||
402 | * Returns a user's setting for this plugin |
||||
403 | * |
||||
404 | * @param string $name The setting name |
||||
405 | * @param int $user_guid The user GUID |
||||
406 | * @param mixed $default The default value to return if none is set |
||||
407 | * |
||||
408 | * @return mixed The setting string value, the default value or false if there is no user |
||||
409 | * @throws DatabaseException |
||||
410 | */ |
||||
411 | 1 | public function getUserSetting($name, $user_guid = 0, $default = null) { |
|||
412 | 1 | $values = $this->getAllUserSettings($user_guid); |
|||
413 | 1 | if ($values === false) { |
|||
414 | return false; |
||||
415 | } |
||||
416 | |||||
417 | 1 | return elgg_extract($name, $values, $default); |
|||
418 | } |
||||
419 | |||||
420 | /** |
||||
421 | * Returns an array of all user settings saved for this plugin for the user. |
||||
422 | * |
||||
423 | * @note Plugin settings are saved with a prefix. This removes that prefix. |
||||
424 | * |
||||
425 | * @param int $user_guid The user GUID. Defaults to logged in. |
||||
426 | * |
||||
427 | * @return array An array of key/value pairs |
||||
428 | * @throws DatabaseException |
||||
429 | */ |
||||
430 | 1 | public function getAllUserSettings($user_guid = 0) { |
|||
431 | |||||
432 | 1 | $user = _elgg_services()->entityTable->getUserForPermissionsCheck($user_guid); |
|||
433 | 1 | if (!$user instanceof ElggUser) { |
|||
434 | return []; |
||||
435 | } |
||||
436 | |||||
437 | 1 | $defaults = $this->getStaticConfig('user_settings', []); |
|||
438 | |||||
439 | 1 | $settings = _elgg_services()->plugins->getAllUserSettings($this, $user); |
|||
440 | |||||
441 | 1 | return array_merge($defaults, $settings); |
|||
442 | } |
||||
443 | |||||
444 | /** |
||||
445 | * Sets a user setting for a plugin |
||||
446 | * |
||||
447 | * @param string $name The setting name |
||||
448 | * @param string $value The setting value |
||||
449 | * @param int $user_guid The user GUID |
||||
450 | * |
||||
451 | * @return mixed The new setting ID or false |
||||
452 | */ |
||||
453 | 1 | public function setUserSetting($name, $value, $user_guid = 0) { |
|||
454 | 1 | $user = _elgg_services()->entityTable->getUserForPermissionsCheck($user_guid); |
|||
455 | 1 | if (!$user instanceof ElggUser) { |
|||
456 | return false; |
||||
457 | } |
||||
458 | |||||
459 | 1 | $value = _elgg_services()->hooks->trigger('usersetting', 'plugin', [ |
|||
460 | 1 | 'user' => $user, |
|||
461 | 1 | 'plugin' => $this, |
|||
462 | 1 | 'plugin_id' => $this->getID(), |
|||
463 | 1 | 'name' => $name, |
|||
464 | 1 | 'value' => $value |
|||
465 | 1 | ], $value); |
|||
466 | |||||
467 | 1 | if (is_array($value)) { |
|||
468 | 1 | elgg_log('Plugin user settings cannot store arrays.', 'ERROR'); |
|||
469 | |||||
470 | 1 | return false; |
|||
471 | } |
||||
472 | |||||
473 | 1 | $name = _elgg_services()->plugins->namespacePrivateSetting('user_setting', $name, $this->getID()); |
|||
474 | |||||
475 | 1 | return $user->setPrivateSetting($name, $value); |
|||
476 | } |
||||
477 | |||||
478 | /** |
||||
479 | * Removes a user setting name and value. |
||||
480 | * |
||||
481 | * @param string $name The user setting name |
||||
482 | * @param int $user_guid The user GUID |
||||
483 | * |
||||
484 | * @return bool |
||||
485 | */ |
||||
486 | 1 | public function unsetUserSetting($name, $user_guid = 0) { |
|||
487 | 1 | $user = _elgg_services()->entityTable->getUserForPermissionsCheck($user_guid); |
|||
488 | |||||
489 | 1 | if (!$user instanceof ElggUser) { |
|||
490 | return false; |
||||
491 | } |
||||
492 | |||||
493 | 1 | $name = _elgg_services()->plugins->namespacePrivateSetting('user_setting', $name, $this->getID()); |
|||
494 | |||||
495 | 1 | return $user->removePrivateSetting($name); |
|||
496 | } |
||||
497 | |||||
498 | /** |
||||
499 | * Removes all plugin settings for a given user |
||||
500 | * |
||||
501 | * @param int $user_guid The user GUID to remove user settings. |
||||
502 | * |
||||
503 | * @return bool |
||||
504 | * @throws DatabaseException |
||||
505 | */ |
||||
506 | 1 | public function unsetAllUserSettings($user_guid = 0) { |
|||
507 | 1 | $user = _elgg_services()->entityTable->getUserForPermissionsCheck($user_guid); |
|||
508 | |||||
509 | 1 | if (!$user instanceof ElggUser) { |
|||
510 | return false; |
||||
511 | } |
||||
512 | |||||
513 | 1 | $settings = $this->getAllUserSettings($user_guid); |
|||
514 | |||||
515 | 1 | foreach ($settings as $name => $value) { |
|||
516 | 1 | $name = _elgg_services()->plugins->namespacePrivateSetting('user_setting', $name, $this->getID()); |
|||
517 | 1 | $user->removePrivateSetting($name); |
|||
518 | } |
||||
519 | |||||
520 | 1 | return true; |
|||
521 | } |
||||
522 | |||||
523 | /** |
||||
524 | * Returns if the plugin is complete, meaning has all required files |
||||
525 | * and Elgg can read them and they make sense. |
||||
526 | * |
||||
527 | * @return bool |
||||
528 | */ |
||||
529 | 1 | public function isValid() { |
|||
530 | 1 | if (!$this->getID()) { |
|||
531 | $this->errorMsg = elgg_echo('ElggPlugin:MissingID', [$this->guid]); |
||||
532 | |||||
533 | return false; |
||||
534 | } |
||||
535 | |||||
536 | 1 | if (!$this->getPackage() instanceof ElggPluginPackage) { |
|||
537 | $this->errorMsg = elgg_echo('ElggPlugin:NoPluginPackagePackage', [ |
||||
538 | $this->getID(), |
||||
539 | $this->guid |
||||
540 | ]); |
||||
541 | |||||
542 | return false; |
||||
543 | } |
||||
544 | |||||
545 | 1 | if (!$this->getPackage()->isValid()) { |
|||
546 | $this->errorMsg = $this->getPackage()->getError(); |
||||
547 | |||||
548 | return false; |
||||
549 | } |
||||
550 | |||||
551 | 1 | return true; |
|||
552 | } |
||||
553 | |||||
554 | /** |
||||
555 | * Is this plugin active? |
||||
556 | * |
||||
557 | * @return bool |
||||
558 | */ |
||||
559 | 93 | public function isActive() { |
|||
560 | 93 | if (isset($this->activated)) { |
|||
561 | 54 | return $this->activated; |
|||
562 | } |
||||
563 | |||||
564 | 59 | $this->activated = elgg_is_active_plugin($this->getID()); |
|||
565 | 59 | return $this->activated; |
|||
566 | } |
||||
567 | |||||
568 | /** |
||||
569 | * Checks if this plugin can be activated on the current |
||||
570 | * Elgg installation. |
||||
571 | * |
||||
572 | * @return bool |
||||
573 | */ |
||||
574 | 15 | public function canActivate() { |
|||
575 | 15 | if ($this->isActive()) { |
|||
576 | return false; |
||||
577 | } |
||||
578 | |||||
579 | 15 | if ($this->getPackage()) { |
|||
580 | 15 | $result = $this->getPackage()->isValid() && $this->getPackage()->checkDependencies(); |
|||
581 | 15 | if (!$result) { |
|||
582 | $this->errorMsg = $this->getPackage()->getError(); |
||||
583 | } |
||||
584 | |||||
585 | 15 | return $result; |
|||
586 | } |
||||
587 | |||||
588 | return false; |
||||
589 | } |
||||
590 | |||||
591 | |||||
592 | // activating and deactivating |
||||
593 | |||||
594 | /** |
||||
595 | * Actives the plugin for the current site. |
||||
596 | * |
||||
597 | * @return bool |
||||
598 | * @throws InvalidParameterException |
||||
599 | * @throws PluginException |
||||
600 | */ |
||||
601 | 15 | public function activate() { |
|||
602 | 15 | if ($this->isActive()) { |
|||
603 | return false; |
||||
604 | } |
||||
605 | |||||
606 | 15 | if (!$this->canActivate()) { |
|||
607 | return false; |
||||
608 | } |
||||
609 | |||||
610 | // Check this before setting status because the file could potentially throw |
||||
611 | 15 | if (!$this->isStaticConfigValid()) { |
|||
612 | return false; |
||||
613 | } |
||||
614 | |||||
615 | 15 | if (!$this->setStatus(true)) { |
|||
616 | return false; |
||||
617 | } |
||||
618 | |||||
619 | // perform tasks and emit events |
||||
620 | // emit an event. returning false will make this not be activated. |
||||
621 | // we need to do this after it's been fully activated |
||||
622 | // or the deactivate will be confused. |
||||
623 | $params = [ |
||||
624 | 15 | 'plugin_id' => $this->getID(), |
|||
625 | 15 | 'plugin_entity' => $this, |
|||
626 | ]; |
||||
627 | |||||
628 | 15 | $return = _elgg_services()->events->trigger('activate', 'plugin', $params); |
|||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||
629 | |||||
630 | // if there are any on_enable functions, start the plugin now and run them |
||||
631 | // Note: this will not run re-run the init hooks! |
||||
632 | 15 | if ($return) { |
|||
633 | try { |
||||
634 | 15 | _elgg_services()->events->trigger('cache:flush', 'system'); |
|||
635 | |||||
636 | 15 | $this->register(); |
|||
637 | |||||
638 | // directly load languages to have them available during runtime |
||||
639 | 15 | $this->loadLanguages(); |
|||
640 | |||||
641 | 15 | $setup = $this->boot(); |
|||
642 | 15 | if ($setup instanceof Closure) { |
|||
643 | 7 | $setup(); |
|||
644 | } |
||||
645 | |||||
646 | 15 | $this->getBootstrap()->activate(); |
|||
647 | |||||
648 | 15 | if ($this->canReadFile('activate.php')) { |
|||
649 | $return = $this->includeFile('activate.php'); |
||||
650 | } |
||||
651 | |||||
652 | 15 | $this->init(); |
|||
653 | } catch (PluginException $ex) { |
||||
654 | elgg_log($ex, \Psr\Log\LogLevel::ERROR); |
||||
655 | |||||
656 | $return = false; |
||||
657 | } |
||||
658 | } |
||||
659 | |||||
660 | 15 | if ($return === false) { |
|||
661 | $this->deactivate(); |
||||
662 | } else { |
||||
663 | 15 | elgg_delete_admin_notice("cannot_start {$this->getID()}"); |
|||
664 | |||||
665 | 15 | _elgg_services()->events->trigger('cache:flush', 'system'); |
|||
666 | 15 | _elgg_services()->logger->notice("Plugin {$this->getID()} has been activated"); |
|||
667 | } |
||||
668 | |||||
669 | 15 | return $return; |
|||
670 | } |
||||
671 | |||||
672 | /** |
||||
673 | * Checks if this plugin can be deactivated on the current |
||||
674 | * Elgg installation. Validates that this plugin has no |
||||
675 | * active dependants. |
||||
676 | * |
||||
677 | * @return bool |
||||
678 | */ |
||||
679 | 7 | public function canDeactivate() { |
|||
680 | 7 | if (!$this->isActive()) { |
|||
681 | return false; |
||||
682 | } |
||||
683 | |||||
684 | 7 | $dependents = []; |
|||
685 | |||||
686 | 7 | $active_plugins = elgg_get_plugins(); |
|||
687 | |||||
688 | 7 | foreach ($active_plugins as $plugin) { |
|||
689 | 6 | $manifest = $plugin->getManifest(); |
|||
690 | 6 | if (!$manifest) { |
|||
691 | 2 | continue; |
|||
692 | } |
||||
693 | 6 | $requires = $manifest->getRequires(); |
|||
694 | |||||
695 | 6 | foreach ($requires as $required) { |
|||
696 | 6 | if ($required['type'] == 'plugin' && $required['name'] == $this->getID()) { |
|||
697 | // there are active dependents |
||||
698 | 6 | $dependents[$manifest->getPluginID()] = $plugin; |
|||
699 | } |
||||
700 | } |
||||
701 | } |
||||
702 | |||||
703 | 7 | if (!empty($dependents)) { |
|||
704 | $list = array_map(function (\ElggPlugin $plugin) { |
||||
705 | $css_id = preg_replace('/[^a-z0-9-]/i', '-', $plugin->getManifest()->getID()); |
||||
706 | |||||
707 | return elgg_view('output/url', [ |
||||
708 | 'text' => $plugin->getDisplayName(), |
||||
709 | 'href' => "#$css_id", |
||||
710 | ]); |
||||
711 | }, $dependents); |
||||
712 | $name = $this->getDisplayName(); |
||||
713 | $list = implode(', ', $list); |
||||
714 | $this->errorMsg = elgg_echo('ElggPlugin:Dependencies:ActiveDependent', [$name, $list]); |
||||
715 | |||||
716 | return false; |
||||
717 | } |
||||
718 | |||||
719 | 7 | return true; |
|||
720 | } |
||||
721 | |||||
722 | /** |
||||
723 | * Deactivates the plugin. |
||||
724 | * |
||||
725 | * @return bool |
||||
726 | * @throws PluginException |
||||
727 | */ |
||||
728 | 8 | public function deactivate() { |
|||
729 | 8 | if (!$this->isActive()) { |
|||
730 | 3 | return false; |
|||
731 | } |
||||
732 | |||||
733 | 7 | if (!$this->canDeactivate()) { |
|||
734 | return false; |
||||
735 | } |
||||
736 | |||||
737 | // emit an event. returning false will cause this to not be deactivated. |
||||
738 | $params = [ |
||||
739 | 7 | 'plugin_id' => $this->getID(), |
|||
740 | 7 | 'plugin_entity' => $this, |
|||
741 | ]; |
||||
742 | |||||
743 | 7 | $return = _elgg_services()->events->trigger('deactivate', 'plugin', $params); |
|||
0 ignored issues
–
show
$params of type array<string,ElggPlugin|string> is incompatible with the type string expected by parameter $object of Elgg\EventsService::trigger() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
744 | 7 | if ($return === false) { |
|||
745 | return false; |
||||
746 | } |
||||
747 | |||||
748 | 7 | $this->getBootstrap()->deactivate(); |
|||
749 | |||||
750 | // run any deactivate code |
||||
751 | 7 | if ($this->canReadFile('deactivate.php')) { |
|||
752 | // allows you to prevent disabling a plugin by returning false in a deactivate.php file |
||||
753 | if ($this->includeFile('deactivate.php') === false) { |
||||
754 | return false; |
||||
755 | } |
||||
756 | } |
||||
757 | |||||
758 | 7 | $this->deactivateEntities(); |
|||
759 | |||||
760 | 7 | _elgg_services()->events->trigger('cache:flush', 'system'); |
|||
761 | |||||
762 | 7 | _elgg_services()->logger->notice("Plugin {$this->getID()} has been deactivated"); |
|||
763 | |||||
764 | 7 | return $this->setStatus(false); |
|||
765 | } |
||||
766 | |||||
767 | /** |
||||
768 | * Bootstrap object |
||||
769 | * @return \Elgg\PluginBootstrapInterface |
||||
770 | * @throws PluginException |
||||
771 | * @access private |
||||
772 | * @internal |
||||
773 | */ |
||||
774 | 197 | public function getBootstrap() { |
|||
775 | 197 | $bootstrap = $this->getStaticConfig('bootstrap'); |
|||
776 | 197 | if ($bootstrap) { |
|||
777 | 40 | if (!is_subclass_of($bootstrap, \Elgg\PluginBootstrapInterface::class)) { |
|||
778 | throw PluginException::factory( |
||||
779 | 'InvalidBootstrap', |
||||
780 | $this, |
||||
781 | elgg_echo('LogicException:InterfaceNotImplemented', [ |
||||
782 | $bootstrap, |
||||
783 | \Elgg\PluginBootstrapInterface::class |
||||
784 | ]) |
||||
785 | ); |
||||
786 | } |
||||
787 | |||||
788 | 40 | return new $bootstrap($this, _elgg_services()->dic); |
|||
789 | } |
||||
790 | |||||
791 | 193 | return new \Elgg\DefaultPluginBootstrap($this, _elgg_services()->dic); |
|||
792 | } |
||||
793 | |||||
794 | /** |
||||
795 | * Register plugin classes and require composer autoloader |
||||
796 | * |
||||
797 | * @return void |
||||
798 | * @throws PluginException |
||||
799 | * @access private |
||||
800 | * @internal |
||||
801 | */ |
||||
802 | 204 | public function autoload() { |
|||
803 | 204 | $this->registerClasses(); |
|||
804 | |||||
805 | 204 | $autoload_file = 'vendor/autoload.php'; |
|||
806 | 204 | if (!$this->canReadFile($autoload_file)) { |
|||
807 | 204 | return; |
|||
808 | } |
||||
809 | |||||
810 | $autoloader = Application::requireSetupFileOnce("{$this->getPath()}{$autoload_file}"); |
||||
811 | |||||
812 | if (!$autoloader instanceof \Composer\Autoload\ClassLoader) { |
||||
813 | return; |
||||
814 | } |
||||
815 | |||||
816 | $autoloader->unregister(); |
||||
817 | |||||
818 | // plugins should be appended, composer defaults to prepend |
||||
819 | $autoloader->register(false); |
||||
820 | } |
||||
821 | |||||
822 | /** |
||||
823 | * Autoload plugin classes and vendor libraries |
||||
824 | * Register plugin-specific entity classes and execute bootstrapped load scripts |
||||
825 | * Register languages and views |
||||
826 | * |
||||
827 | * @return void |
||||
828 | * @throws PluginException |
||||
829 | * @access private |
||||
830 | * @internal |
||||
831 | */ |
||||
832 | 194 | public function register() { |
|||
833 | 194 | $this->autoload(); |
|||
834 | |||||
835 | 194 | $this->activateEntities(); |
|||
836 | 194 | $this->registerLanguages(); |
|||
837 | 194 | $this->registerViews(); |
|||
838 | |||||
839 | 194 | $this->getBootstrap()->load(); |
|||
840 | 194 | } |
|||
841 | |||||
842 | /** |
||||
843 | * Boot the plugin |
||||
844 | * |
||||
845 | * @throws PluginException |
||||
846 | * @return \Closure|null |
||||
847 | * @access private |
||||
848 | * @internal |
||||
849 | */ |
||||
850 | 194 | public function boot() { |
|||
851 | 194 | $result = null; |
|||
852 | 194 | if ($this->canReadFile('start.php')) { |
|||
853 | 185 | $result = Application::requireSetupFileOnce("{$this->getPath()}start.php"); |
|||
854 | } |
||||
855 | |||||
856 | 194 | $this->getBootstrap()->boot(); |
|||
857 | |||||
858 | 194 | return $result; |
|||
859 | } |
||||
860 | |||||
861 | /** |
||||
862 | * Init the plugin |
||||
863 | * @return void |
||||
864 | * @throws InvalidParameterException |
||||
865 | * @throws PluginException |
||||
866 | * @access private |
||||
867 | * @internal |
||||
868 | */ |
||||
869 | 194 | public function init() { |
|||
870 | 194 | $this->registerRoutes(); |
|||
871 | 194 | $this->registerActions(); |
|||
872 | 194 | $this->registerEntities(); |
|||
873 | 194 | $this->registerWidgets(); |
|||
874 | |||||
875 | 194 | $this->getBootstrap()->init(); |
|||
876 | 194 | } |
|||
877 | |||||
878 | /** |
||||
879 | * Includes one of the plugins files |
||||
880 | * |
||||
881 | * @param string $filename The name of the file |
||||
882 | * |
||||
883 | * @throws PluginException |
||||
884 | * @return mixed The return value of the included file (or 1 if there is none) |
||||
885 | */ |
||||
886 | 189 | protected function includeFile($filename) { |
|||
887 | 189 | $filepath = "{$this->getPath()}{$filename}"; |
|||
888 | |||||
889 | 189 | if (!$this->canReadFile($filename)) { |
|||
890 | $msg = elgg_echo( |
||||
891 | 'ElggPlugin:Exception:CannotIncludeFile', |
||||
892 | [$filename, $this->getID(), $this->guid, $this->getPath()] |
||||
893 | ); |
||||
894 | |||||
895 | throw PluginException::factory('CannotIncludeFile', $this, $msg); |
||||
896 | } |
||||
897 | |||||
898 | try { |
||||
899 | 189 | $ret = Application::requireSetupFileOnce($filepath); |
|||
900 | } catch (Exception $e) { |
||||
901 | $msg = elgg_echo( |
||||
902 | 'ElggPlugin:Exception:IncludeFileThrew', |
||||
903 | [$filename, $this->getID(), $this->guid, $this->getPath()] |
||||
904 | ); |
||||
905 | |||||
906 | throw PluginException::factory('IncludeFileThrew', $this, $msg, $e); |
||||
907 | } |
||||
908 | |||||
909 | 189 | return $ret; |
|||
910 | } |
||||
911 | |||||
912 | /** |
||||
913 | * Checks whether a plugin file with the given name exists |
||||
914 | * |
||||
915 | * @param string $filename The name of the file |
||||
916 | * |
||||
917 | * @return bool |
||||
918 | */ |
||||
919 | 208 | protected function canReadFile($filename) { |
|||
920 | 208 | $path = "{$this->getPath()}{$filename}"; |
|||
921 | |||||
922 | 208 | return is_file($path) && is_readable($path); |
|||
923 | } |
||||
924 | |||||
925 | /** |
||||
926 | * If a static config file is present, is it a serializable array? |
||||
927 | * |
||||
928 | * @return bool |
||||
929 | * @throws PluginException |
||||
930 | */ |
||||
931 | 15 | private function isStaticConfigValid() { |
|||
932 | 15 | if (!$this->canReadFile(ElggPluginPackage::STATIC_CONFIG_FILENAME)) { |
|||
933 | 5 | return true; |
|||
934 | } |
||||
935 | |||||
936 | 10 | ob_start(); |
|||
937 | 10 | $value = $this->includeFile(ElggPluginPackage::STATIC_CONFIG_FILENAME); |
|||
938 | 10 | if (ob_get_clean() !== '') { |
|||
939 | $this->errorMsg = elgg_echo('ElggPlugin:activate:ConfigSentOutput'); |
||||
940 | |||||
941 | return false; |
||||
942 | } |
||||
943 | |||||
944 | // make sure can serialize |
||||
945 | 10 | $value = @unserialize(serialize($value)); |
|||
946 | 10 | if (!is_array($value)) { |
|||
947 | $this->errorMsg = elgg_echo('ElggPlugin:activate:BadConfigFormat'); |
||||
948 | |||||
949 | return false; |
||||
950 | } |
||||
951 | |||||
952 | 10 | return true; |
|||
953 | } |
||||
954 | |||||
955 | /** |
||||
956 | * Registers the plugin's views |
||||
957 | * |
||||
958 | * @throws PluginException |
||||
959 | * @return void |
||||
960 | */ |
||||
961 | 194 | protected function registerViews() { |
|||
962 | 194 | if (_elgg_config()->system_cache_loaded) { |
|||
963 | 32 | return; |
|||
964 | } |
||||
965 | |||||
966 | 166 | $views = _elgg_services()->views; |
|||
967 | |||||
968 | // Declared views first |
||||
969 | 166 | $file = "{$this->getPath()}views.php"; |
|||
970 | 166 | if (is_file($file)) { |
|||
971 | $spec = Includer::includeFile($file); |
||||
972 | if (is_array($spec)) { |
||||
973 | $views->mergeViewsSpec($spec); |
||||
974 | } |
||||
975 | } |
||||
976 | |||||
977 | 166 | $spec = $this->getStaticConfig('views'); |
|||
978 | 166 | if ($spec) { |
|||
979 | 9 | $views->mergeViewsSpec($spec); |
|||
980 | } |
||||
981 | |||||
982 | // Allow /views directory files to override |
||||
983 | 166 | if (!$views->registerPluginViews($this->getPath(), $failed_dir)) { |
|||
984 | $key = 'ElggPlugin:Exception:CannotRegisterViews'; |
||||
985 | $args = [$this->getID(), $this->guid, $failed_dir]; |
||||
986 | $msg = elgg_echo($key, $args); |
||||
987 | |||||
988 | throw PluginException::factory('CannotRegisterViews', $this, $msg); |
||||
989 | } |
||||
990 | 166 | } |
|||
991 | |||||
992 | /** |
||||
993 | * Registers the plugin's entities |
||||
994 | * |
||||
995 | * @return void |
||||
996 | */ |
||||
997 | 194 | protected function registerEntities() { |
|||
998 | |||||
999 | 194 | $spec = (array) $this->getStaticConfig('entities', []); |
|||
1000 | 194 | if (empty($spec)) { |
|||
1001 | 87 | return; |
|||
1002 | } |
||||
1003 | |||||
1004 | 141 | foreach ($spec as $entity) { |
|||
1005 | 141 | if (isset($entity['type'], $entity['subtype'], $entity['searchable']) && $entity['searchable']) { |
|||
1006 | 141 | elgg_register_entity_type($entity['type'], $entity['subtype']); |
|||
1007 | } |
||||
1008 | } |
||||
1009 | 141 | } |
|||
1010 | |||||
1011 | /** |
||||
1012 | * Registers the plugin's actions provided in the plugin config file |
||||
1013 | * |
||||
1014 | * @return void |
||||
1015 | */ |
||||
1016 | 194 | protected function registerActions() { |
|||
1017 | 194 | self::addActionsFromStaticConfig($this->getStaticConfig('actions', []), $this->getPath()); |
|||
1018 | 194 | } |
|||
1019 | |||||
1020 | /** |
||||
1021 | * Register a plugin's actions provided in the config file |
||||
1022 | * |
||||
1023 | * @todo move to a static config service |
||||
1024 | * |
||||
1025 | * @param array $spec 'actions' section of static config |
||||
1026 | * @param string $root_path Plugin path |
||||
1027 | * |
||||
1028 | * @return void |
||||
1029 | * @access private |
||||
1030 | * @internal |
||||
1031 | */ |
||||
1032 | 194 | public static function addActionsFromStaticConfig(array $spec, $root_path) { |
|||
1033 | 194 | $actions = _elgg_services()->actions; |
|||
1034 | 194 | $root_path = rtrim($root_path, '/\\'); |
|||
1035 | |||||
1036 | 194 | foreach ($spec as $action => $action_spec) { |
|||
1037 | 168 | if (!is_array($action_spec)) { |
|||
1038 | continue; |
||||
1039 | } |
||||
1040 | |||||
1041 | 168 | $access = elgg_extract('access', $action_spec, 'logged_in'); |
|||
1042 | 168 | $handler = elgg_extract('controller', $action_spec); |
|||
1043 | 168 | if (!$handler) { |
|||
1044 | 168 | $handler = elgg_extract('filename', $action_spec); |
|||
1045 | 168 | if (!$handler) { |
|||
1046 | 168 | $handler = "$root_path/actions/{$action}.php"; |
|||
1047 | } |
||||
1048 | } |
||||
1049 | |||||
1050 | 168 | $actions->register($action, $handler, $access); |
|||
1051 | } |
||||
1052 | 194 | } |
|||
1053 | |||||
1054 | /** |
||||
1055 | * Registers the plugin's routes provided in the plugin config file |
||||
1056 | * |
||||
1057 | * @return void |
||||
1058 | * @throws InvalidParameterException |
||||
1059 | */ |
||||
1060 | 194 | protected function registerRoutes() { |
|||
1061 | 194 | $routes = _elgg_services()->routes; |
|||
1062 | |||||
1063 | 194 | $spec = (array) $this->getStaticConfig('routes', []); |
|||
1064 | |||||
1065 | 194 | foreach ($spec as $name => $route_spec) { |
|||
1066 | 170 | if (!is_array($route_spec)) { |
|||
1067 | continue; |
||||
1068 | } |
||||
1069 | |||||
1070 | 170 | $routes->register($name, $route_spec); |
|||
1071 | } |
||||
1072 | 194 | } |
|||
1073 | |||||
1074 | /** |
||||
1075 | * Registers the plugin's widgets provided in the plugin config file |
||||
1076 | * |
||||
1077 | * @return void |
||||
1078 | * @throws \InvalidParameterException |
||||
1079 | */ |
||||
1080 | 194 | protected function registerWidgets() { |
|||
1081 | 194 | $widgets = _elgg_services()->widgets; |
|||
1082 | |||||
1083 | 194 | $spec = (array) $this->getStaticConfig('widgets', []); |
|||
1084 | 194 | foreach ($spec as $widget_id => $widget_definition) { |
|||
1085 | 135 | if (!is_array($widget_definition)) { |
|||
1086 | continue; |
||||
1087 | } |
||||
1088 | 135 | if (!isset($widget_definition['id'])) { |
|||
1089 | 135 | $widget_definition['id'] = $widget_id; |
|||
1090 | } |
||||
1091 | |||||
1092 | 135 | $definition = \Elgg\WidgetDefinition::factory($widget_definition); |
|||
1093 | |||||
1094 | 135 | $widgets->registerType($definition); |
|||
1095 | } |
||||
1096 | 194 | } |
|||
1097 | |||||
1098 | /** |
||||
1099 | * Registers the plugin's languages |
||||
1100 | * |
||||
1101 | * Makes the language paths available to the system. Commonly used during boot of engine. |
||||
1102 | * |
||||
1103 | * @return void |
||||
1104 | */ |
||||
1105 | 206 | public function registerLanguages() { |
|||
1106 | 206 | $languages_path = $this->getLanguagesPath(); |
|||
1107 | 206 | if (empty($languages_path)) { |
|||
1108 | 58 | return; |
|||
1109 | } |
||||
1110 | |||||
1111 | 196 | _elgg_services()->translator->registerLanguagePath($languages_path); |
|||
1112 | 196 | } |
|||
1113 | |||||
1114 | /** |
||||
1115 | * Loads the plugin's translations |
||||
1116 | * |
||||
1117 | * Directly loads the translations for this plugin into available translations. |
||||
1118 | * |
||||
1119 | * Use when on runtime activating a plugin. |
||||
1120 | * |
||||
1121 | * @return void |
||||
1122 | */ |
||||
1123 | 15 | protected function loadLanguages() { |
|||
1124 | 15 | $languages_path = $this->getLanguagesPath(); |
|||
1125 | 15 | if (empty($languages_path)) { |
|||
1126 | 10 | return; |
|||
1127 | } |
||||
1128 | |||||
1129 | 5 | _elgg_services()->translator->registerTranslations($languages_path); |
|||
1130 | 5 | } |
|||
1131 | |||||
1132 | /** |
||||
1133 | * Registers the plugin's classes |
||||
1134 | * |
||||
1135 | * @return void |
||||
1136 | */ |
||||
1137 | 204 | protected function registerClasses() { |
|||
1138 | 204 | $classes_path = "{$this->getPath()}classes"; |
|||
1139 | |||||
1140 | 204 | _elgg_services()->autoloadManager->addClasses($classes_path); |
|||
1141 | 204 | } |
|||
1142 | |||||
1143 | /** |
||||
1144 | * Activates the plugin's entities |
||||
1145 | * |
||||
1146 | * @return void |
||||
1147 | */ |
||||
1148 | 194 | protected function activateEntities() { |
|||
1149 | 194 | $spec = (array) $this->getStaticConfig('entities', []); |
|||
1150 | 194 | if (empty($spec)) { |
|||
1151 | 87 | return; |
|||
1152 | } |
||||
1153 | |||||
1154 | 141 | foreach ($spec as $entity) { |
|||
1155 | 141 | if (isset($entity['type'], $entity['subtype'], $entity['class'])) { |
|||
1156 | 141 | elgg_set_entity_class($entity['type'], $entity['subtype'], $entity['class']); |
|||
1157 | } |
||||
1158 | } |
||||
1159 | 141 | } |
|||
1160 | |||||
1161 | /** |
||||
1162 | * Deactivates the plugin's entities |
||||
1163 | * |
||||
1164 | * @return void |
||||
1165 | */ |
||||
1166 | 7 | protected function deactivateEntities() { |
|||
1167 | 7 | $spec = (array) $this->getStaticConfig('entities', []); |
|||
1168 | 7 | if (empty($spec)) { |
|||
1169 | 7 | return; |
|||
1170 | } |
||||
1171 | |||||
1172 | foreach ($spec as $entity) { |
||||
1173 | if (isset($entity['type'], $entity['subtype'], $entity['class'])) { |
||||
1174 | elgg_set_entity_class($entity['type'], $entity['subtype']); |
||||
1175 | } |
||||
1176 | } |
||||
1177 | } |
||||
1178 | |||||
1179 | /** |
||||
1180 | * Get an attribute, metadata or private setting value |
||||
1181 | * |
||||
1182 | * @param string $name Name of the attribute or private setting |
||||
1183 | * |
||||
1184 | * @return mixed |
||||
1185 | * @throws DatabaseException |
||||
1186 | */ |
||||
1187 | 410 | public function __get($name) { |
|||
1188 | // See if its in our base attribute |
||||
1189 | 410 | if (array_key_exists($name, $this->attributes)) { |
|||
1190 | 410 | return $this->attributes[$name]; |
|||
1191 | } |
||||
1192 | |||||
1193 | // object title and description are stored as metadata |
||||
1194 | 408 | if (in_array($name, ['title', 'description'])) { |
|||
1195 | 408 | return parent::__get($name); |
|||
1196 | } |
||||
1197 | |||||
1198 | 7 | $result = $this->getPrivateSetting($name); |
|||
1199 | 7 | if ($result !== null) { |
|||
1200 | 5 | return $result; |
|||
1201 | } |
||||
1202 | |||||
1203 | 6 | $defaults = $this->getStaticConfig('settings', []); |
|||
1204 | |||||
1205 | 6 | return elgg_extract($name, $defaults, $result); |
|||
1206 | } |
||||
1207 | |||||
1208 | /** |
||||
1209 | * Set a value as attribute, metadata or private setting. |
||||
1210 | * |
||||
1211 | * Metadata applies to title and description. |
||||
1212 | * |
||||
1213 | * @param string $name Name of the attribute or private_setting |
||||
1214 | * @param mixed $value Value to be set |
||||
1215 | * |
||||
1216 | * @return void |
||||
1217 | */ |
||||
1218 | 348 | public function __set($name, $value) { |
|||
1219 | 348 | if (array_key_exists($name, $this->attributes)) { |
|||
1220 | // Check that we're not trying to change the guid! |
||||
1221 | 1 | if ((array_key_exists('guid', $this->attributes)) && ($name == 'guid')) { |
|||
1222 | return; |
||||
1223 | } |
||||
1224 | |||||
1225 | 1 | $this->attributes[$name] = $value; |
|||
1226 | |||||
1227 | 1 | return; |
|||
1228 | } |
||||
1229 | |||||
1230 | // object title and description are stored as metadata |
||||
1231 | 348 | if (in_array($name, ['title', 'description'])) { |
|||
1232 | 348 | parent::__set($name, $value); |
|||
1233 | |||||
1234 | 348 | return; |
|||
1235 | } |
||||
1236 | |||||
1237 | // to make sure we trigger the correct hooks |
||||
1238 | 6 | $this->setSetting($name, $value); |
|||
1239 | 6 | } |
|||
1240 | |||||
1241 | /** |
||||
1242 | * Sets the plugin to active or inactive. |
||||
1243 | * |
||||
1244 | * @param bool $active Set to active or inactive |
||||
1245 | * |
||||
1246 | * @return bool |
||||
1247 | */ |
||||
1248 | 16 | private function setStatus($active) { |
|||
1249 | 16 | if (!$this->guid) { |
|||
1250 | return false; |
||||
1251 | } |
||||
1252 | |||||
1253 | 16 | $site = elgg_get_site_entity(); |
|||
1254 | 16 | if ($active) { |
|||
1255 | 15 | $result = add_entity_relationship($this->guid, 'active_plugin', $site->guid); |
|||
1256 | } else { |
||||
1257 | 7 | $result = remove_entity_relationship($this->guid, 'active_plugin', $site->guid); |
|||
1258 | } |
||||
1259 | |||||
1260 | 16 | if ($result) { |
|||
1261 | 16 | $this->activated = $active; |
|||
1262 | } |
||||
1263 | |||||
1264 | 16 | $this->invalidateCache(); |
|||
1265 | |||||
1266 | 16 | return $result; |
|||
1267 | } |
||||
1268 | |||||
1269 | /** |
||||
1270 | * Returns the last error message registered. |
||||
1271 | * |
||||
1272 | * @return string|null |
||||
1273 | */ |
||||
1274 | public function getError() { |
||||
1275 | return $this->errorMsg; |
||||
1276 | } |
||||
1277 | |||||
1278 | /** |
||||
1279 | * Returns this plugin's \ElggPluginManifest object |
||||
1280 | * |
||||
1281 | * @return ElggPluginManifest|null |
||||
1282 | */ |
||||
1283 | 343 | public function getManifest() { |
|||
1284 | 343 | if ($this->manifest instanceof ElggPluginManifest) { |
|||
1285 | 16 | return $this->manifest; |
|||
1286 | } |
||||
1287 | |||||
1288 | try { |
||||
1289 | 338 | $package = $this->getPackage(); |
|||
1290 | 338 | if (!$package) { |
|||
1291 | 6 | throw PluginException::factory('InvalidPackage', $this); |
|||
1292 | } |
||||
1293 | |||||
1294 | 335 | $this->manifest = $package->getManifest(); |
|||
1295 | |||||
1296 | 335 | return $this->manifest; |
|||
1297 | 6 | } catch (PluginException $e) { |
|||
1298 | 6 | _elgg_services()->logger->warning("Failed to load manifest for plugin $this->guid. " . $e->getMessage()); |
|||
1299 | 6 | $this->errorMsg = $e->getMessage(); |
|||
1300 | |||||
1301 | 6 | elgg_log($e, \Psr\Log\LogLevel::ERROR); |
|||
1302 | } |
||||
1303 | 6 | } |
|||
1304 | |||||
1305 | /** |
||||
1306 | * Returns this plugin's \ElggPluginPackage object |
||||
1307 | * |
||||
1308 | * @return ElggPluginPackage|null |
||||
1309 | */ |
||||
1310 | 343 | public function getPackage() { |
|||
1311 | 343 | if ($this->package instanceof ElggPluginPackage) { |
|||
1312 | 16 | return $this->package; |
|||
1313 | } |
||||
1314 | |||||
1315 | try { |
||||
1316 | 343 | $this->package = new ElggPluginPackage($this->getPath(), false); |
|||
1317 | |||||
1318 | 341 | return $this->package; |
|||
1319 | 6 | } catch (Exception $e) { |
|||
1320 | 6 | _elgg_services()->logger->warning("Failed to load package for $this->guid. " . $e->getMessage()); |
|||
1321 | 6 | $this->errorMsg = $e->getMessage(); |
|||
1322 | |||||
1323 | 6 | elgg_log($e, \Psr\Log\LogLevel::ERROR); |
|||
1324 | } |
||||
1325 | 6 | } |
|||
1326 | |||||
1327 | /** |
||||
1328 | * {@inheritdoc} |
||||
1329 | */ |
||||
1330 | 373 | public function isCacheable() { |
|||
1331 | 373 | return true; |
|||
1332 | } |
||||
1333 | |||||
1334 | /** |
||||
1335 | * {@inheritdoc} |
||||
1336 | */ |
||||
1337 | 373 | public function cache($persist = true) { |
|||
1338 | 373 | _elgg_services()->plugins->cache($this); |
|||
1339 | |||||
1340 | 373 | parent::cache($persist); |
|||
1341 | 373 | } |
|||
1342 | |||||
1343 | /** |
||||
1344 | * {@inheritdoc} |
||||
1345 | */ |
||||
1346 | 353 | public function invalidateCache() { |
|||
1347 | |||||
1348 | 353 | _elgg_services()->boot->invalidateCache(); |
|||
1349 | 353 | _elgg_services()->plugins->invalidateCache($this->getID()); |
|||
1350 | |||||
1351 | 353 | parent::invalidateCache(); |
|||
1352 | 353 | } |
|||
1353 | } |
||||
1354 |