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