Elgg  Version master
Plugins.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Database;
4 
6 use Elgg\Config;
7 use Elgg\Context;
8 use Elgg\Database;
22 
29 class Plugins {
30 
31  use Profilable;
32  use Cacheable;
33  use Loggable;
34 
35  const BUNDLED_PLUGINS = [
36  'activity',
37  'blog',
38  'bookmarks',
39  'ckeditor',
40  'custom_index',
41  'dashboard',
42  'developers',
43  'discussions',
44  'externalpages',
45  'file',
46  'friends',
47  'friends_collections',
48  'garbagecollector',
49  'groups',
50  'invitefriends',
51  'likes',
52  'members',
53  'messageboard',
54  'messages',
55  'notifications',
56  'pages',
57  'profile',
58  'reportedcontent',
59  'search',
60  'site_notifications',
61  'system_log',
62  'tagcloud',
63  'thewire',
64  'uservalidationbyemail',
65  'web_services',
66  ];
67 
71  protected ?array $boot_plugins;
72 
73  protected Database $db;
74 
76 
78 
80 
81  protected ViewsService $views;
82 
83  protected Config $config;
84 
86 
87  protected Context $context;
88 
102  public function __construct(
103  BaseCache $cache,
104  Database $db,
105  SessionManagerService $session_manager,
106  EventsService $events,
107  Translator $translator,
108  ViewsService $views,
109  Config $config,
110  SystemMessagesService $system_messages,
112  ) {
113  $this->cache = $cache;
114  $this->db = $db;
115  $this->session_manager = $session_manager;
116  $this->events = $events;
117  $this->translator = $translator;
118  $this->views = $views;
119  $this->config = $config;
120  $this->system_messages = $system_messages;
121 
122  $this->context = $request->getContextStack();
123  }
124 
130  public function getPath(): string {
131  $path = $this->config->plugins_path;
132  if (!$path) {
133  $path = Paths::project() . 'mod/';
134  }
135 
136  return $path;
137  }
138 
147  public function setBootPlugins(array $plugins = null, bool $order_plugins = true): void {
148  if (!is_array($plugins)) {
149  unset($this->boot_plugins);
150  return;
151  }
152 
153  // Always (re)set the boot_plugins. This makes sure that even if you have no plugins active this is known to the system.
154  $this->boot_plugins = [];
155 
156  if ($order_plugins) {
158  }
159 
160  foreach ($plugins as $plugin) {
161  if (!$plugin instanceof \ElggPlugin) {
162  continue;
163  }
164 
165  $plugin_id = $plugin->getID();
166  if (!$plugin_id) {
167  continue;
168  }
169 
170  $plugin->registerLanguages();
171 
172  $this->boot_plugins[$plugin_id] = $plugin;
173  $this->cache->save($plugin_id, $plugin);
174  }
175  }
176 
182  public function clear(): void {
183  $this->cache->clear();
184  }
185 
191  public function invalidate(): void {
192  $this->cache->invalidate();
193  }
194 
203  public function getDirsInDir(string $dir = null): array {
204  if (!$dir) {
205  $dir = $this->getPath();
206  }
207 
208  if (!is_dir($dir)) {
209  return [];
210  }
211 
212  $handle = opendir($dir);
213  if ($handle === false) {
214  return [];
215  }
216 
217  $plugin_dirs = [];
218  while (($plugin_dir = readdir($handle)) !== false) {
219  // must be directory and not begin with a .
220  if (!str_starts_with($plugin_dir, '.') && is_dir($dir . $plugin_dir)) {
221  $plugin_dirs[] = $plugin_dir;
222  }
223  }
224 
225  sort($plugin_dirs);
226 
227  return $plugin_dirs;
228  }
229 
238  public function generateEntities(): bool {
239  $mod_dir = $this->getPath();
240 
241  // ignore access in case this is called with no admin logged in - needed for creating plugins perhaps?
242  $old_ia = $this->session_manager->setIgnoreAccess(true);
243 
244  // show hidden entities so that we can enable them if appropriate
245  $old_access = $this->session_manager->setDisabledEntityVisibility(true);
246 
247  $known_plugins = $this->find('all');
248  if (empty($known_plugins)) {
249  $known_plugins = [];
250  }
251 
252  // keeps track if reindexing is needed
253  $reindex = false;
254 
255  // map paths to indexes
256  $id_map = [];
257  $latest_priority = -1;
258  foreach ($known_plugins as $i => $plugin) {
259  // if the ID is wrong, delete the plugin because we can never load it.
260  $id = $plugin->getID();
261  if (!$id) {
262  $plugin->delete();
263  unset($known_plugins[$i]);
264  continue;
265  }
266 
267  $id_map[$plugin->getID()] = $i;
268  $plugin->cache();
269 
270  // disabled plugins should have no priority, so no need to check if the priority is incorrect
271  if (!$plugin->isEnabled()) {
272  continue;
273  }
274 
275  $current_priority = $plugin->getPriority();
276  if (($current_priority - $latest_priority) > 1) {
277  $reindex = true;
278  }
279 
280  $latest_priority = $current_priority;
281  }
282 
283  $physical_plugins = $this->getDirsInDir($mod_dir);
284  if (empty($physical_plugins)) {
285  $this->session_manager->setIgnoreAccess($old_ia);
286  $this->session_manager->setDisabledEntityVisibility($old_access);
287 
288  return false;
289  }
290 
291  // check real plugins against known ones
292  foreach ($physical_plugins as $plugin_id) {
293  // is this already in the db?
294  if (array_key_exists($plugin_id, $id_map)) {
295  $index = $id_map[$plugin_id];
296  $plugin = $known_plugins[$index];
297  // was this plugin deleted and its entity disabled?
298  if (!$plugin->isEnabled()) {
299  $plugin->enable();
300  try {
301  $plugin->deactivate();
302  } catch (PluginException $e) {
303  // do nothing
304  }
305 
306  $plugin->setPriority('new');
307  }
308 
309  // remove from the list of plugins to disable
310  unset($known_plugins[$index]);
311  } else {
312  // create new plugin
313  // priority is forced to last in save() if not set.
314  $plugin = \ElggPlugin::fromId($plugin_id);
315  $plugin->cache();
316  }
317  }
318 
319  // everything remaining in $known_plugins needs to be disabled
320  // because they are entities, but their dirs were removed.
321  // don't delete the entities because they hold settings.
322  foreach ($known_plugins as $plugin) {
323  if (!$plugin->isEnabled()) {
324  continue;
325  }
326 
327  $reindex = true;
328 
329  if ($plugin->isActive()) {
330  try {
331  $plugin->deactivate();
332  } catch (PluginException $e) {
333  // do nothing
334  }
335  }
336 
337  // remove the priority.
338  $plugin->deleteMetadata(\ElggPlugin::PRIORITY_SETTING_NAME);
339 
340  $plugin->disable();
341  }
342 
343  if ($reindex) {
344  $this->reindexPriorities();
345  }
346 
347  $this->session_manager->setIgnoreAccess($old_ia);
348  $this->session_manager->setDisabledEntityVisibility($old_access);
349 
350  return true;
351  }
352 
360  public function cache(\ElggPlugin $plugin): void {
361  if (!$plugin->getID()) {
362  return;
363  }
364 
365  $this->cache->save($plugin->getID(), $plugin);
366  }
367 
375  public function invalidateCache($plugin_id): void {
376  try {
377  $this->cache->delete($plugin_id);
378  } catch (InvalidArgumentException $ex) {
379  // A plugin must have been deactivated due to missing folder
380  // without proper cleanup
382  }
383  }
384 
392  public function get(string $plugin_id): ?\ElggPlugin {
393  if (empty($plugin_id)) {
394  return null;
395  }
396 
397  $plugin = $this->cache->load($plugin_id);
398  if ($plugin instanceof \ElggPlugin) {
399  return $plugin;
400  }
401 
403  'type' => 'object',
404  'subtype' => 'plugin',
405  'metadata_name_value_pairs' => [
406  'name' => 'title',
407  'value' => $plugin_id,
408  ],
409  'limit' => 1,
410  'distinct' => false,
411  ]);
412 
413  if (empty($plugins)) {
414  return null;
415  }
416 
417  $plugins[0]->cache();
418 
419  return $plugins[0];
420  }
421 
433  public function exists(string $id): bool {
434  return $this->get($id) instanceof \ElggPlugin;
435  }
436 
442  public function getMaxPriority(): int {
443  $qb = Select::fromTable('entities', 'e');
444  $qb->select('MAX(CAST(md.value AS unsigned)) as max')
445  ->join('e', 'metadata', 'md', 'e.guid = md.entity_guid')
446  ->where($qb->compare('md.name', '=', \ElggPlugin::PRIORITY_SETTING_NAME, ELGG_VALUE_STRING))
447  ->andWhere($qb->compare('e.type', '=', 'object', ELGG_VALUE_STRING))
448  ->andWhere($qb->compare('e.subtype', '=', 'plugin', ELGG_VALUE_STRING));
449 
450  $data = $this->db->getDataRow($qb);
451  if (empty($data)) {
452  return 1;
453  }
454 
455  return max(1, (int) $data->max);
456  }
457 
465  public function isActive(string $plugin_id): bool {
466  if (isset($this->boot_plugins) && is_array($this->boot_plugins)) {
467  return array_key_exists($plugin_id, $this->boot_plugins);
468  }
469 
470  $plugin = $this->get($plugin_id);
471  if (!$plugin instanceof \ElggPlugin) {
472  return false;
473  }
474 
475  return $plugin->hasRelationship(1, 'active_plugin');
476  }
477 
487  public function build(): bool {
488  $plugins_path = $this->getPath();
489 
490  // temporary disable all plugins if there is a file called 'disabled' in the plugin dir
491  if (file_exists("{$plugins_path}/disabled")) {
492  if ($this->session_manager->isAdminLoggedIn() && $this->context->contains('admin')) {
493  $this->system_messages->addSuccessMessage($this->translator->translate('plugins:disabled'));
494  }
495 
496  return false;
497  }
498 
499  $this->events->registerHandler('plugins_load', 'system', [$this, 'register']);
500  $this->events->registerHandler('plugins_boot:before', 'system', [$this, 'boot']);
501  $this->events->registerHandler('init', 'system', [$this, 'init']);
502  $this->events->registerHandler('ready', 'system', [$this, 'ready']);
503  $this->events->registerHandler('upgrade', 'system', [$this, 'upgrade']);
504  $this->events->registerHandler('shutdown', 'system', [$this, 'shutdown']);
505 
506  return true;
507  }
508 
515  public function register(): void {
516  $plugins = $this->find('active');
517  if (empty($plugins)) {
518  return;
519  }
520 
521  $this->beginTimer([__METHOD__]);
522 
523  foreach ($plugins as $plugin) {
524  try {
525  $plugin->register();
526  } catch (\Exception $ex) {
527  $this->disable($plugin, $ex);
528  }
529  }
530 
531  $this->endTimer([__METHOD__]);
532  }
533 
539  public function boot(): void {
540  $plugins = $this->find('active');
541  if (empty($plugins)) {
542  return;
543  }
544 
545  $this->beginTimer([__METHOD__]);
546 
547  foreach ($plugins as $plugin) {
548  try {
549  $plugin->boot();
550  } catch (\Exception $ex) {
551  $this->disable($plugin, $ex);
552  }
553  }
554 
555  $this->endTimer([__METHOD__]);
556  }
557 
563  public function init(): void {
564  $plugins = $this->find('active');
565  if (empty($plugins)) {
566  return;
567  }
568 
569  $this->beginTimer([__METHOD__]);
570 
571  foreach ($plugins as $plugin) {
572  try {
573  $plugin->init();
574  } catch (\Exception $ex) {
575  $this->disable($plugin, $ex);
576  }
577  }
578 
579  $this->endTimer([__METHOD__]);
580  }
581 
587  public function ready(): void {
588  $plugins = $this->find('active');
589  if (empty($plugins)) {
590  return;
591  }
592 
593  $this->beginTimer([__METHOD__]);
594 
595  foreach ($plugins as $plugin) {
596  try {
597  $plugin->getBootstrap()->ready();
598  } catch (\Exception $ex) {
599  $this->disable($plugin, $ex);
600  }
601  }
602 
603  $this->endTimer([__METHOD__]);
604  }
605 
611  public function upgrade(): void {
612  $plugins = $this->find('active');
613  if (empty($plugins)) {
614  return;
615  }
616 
617  $this->beginTimer([__METHOD__]);
618 
619  foreach ($plugins as $plugin) {
620  try {
621  $plugin->getBootstrap()->upgrade();
622  } catch (\Exception $ex) {
623  $this->disable($plugin, $ex);
624  }
625  }
626 
627  $this->endTimer([__METHOD__]);
628  }
629 
635  public function shutdown(): void {
636  $plugins = $this->find('active');
637  if (empty($plugins)) {
638  return;
639  }
640 
641  $this->beginTimer([__METHOD__]);
642 
643  foreach ($plugins as $plugin) {
644  try {
645  $plugin->getBootstrap()->shutdown();
646  } catch (\Exception $ex) {
647  $this->disable($plugin, $ex);
648  }
649  }
650 
651  $this->endTimer([__METHOD__]);
652  }
653 
662  protected function disable(\ElggPlugin $plugin, \Exception $previous): void {
663  $this->getLogger()->log(LogLevel::ERROR, $previous, [
664  'context' => [
665  'plugin' => $plugin,
666  ],
667  ]);
668 
669  if (!$this->config->auto_disable_plugins) {
670  return;
671  }
672 
673  try {
674  $id = $plugin->getID();
675  $plugin->deactivate();
676 
677  $msg = $this->translator->translate(
678  'PluginException:CannotStart',
679  [$id, $plugin->guid, $previous->getMessage()]
680  );
681 
682  elgg_add_admin_notice("cannot_start {$id}", $msg);
683  } catch (PluginException $ex) {
684  $this->getLogger()->log(LogLevel::ERROR, $ex, [
685  'context' => [
686  'plugin' => $plugin,
687  ],
688  ]);
689  }
690  }
691 
699  public function find(string $status = 'active'): array {
700  if (!$this->db || !$this->config->installed) {
701  return [];
702  }
703 
704  if ($status === 'active' && isset($this->boot_plugins)) {
705  // boot_plugins is an already ordered list of plugins
706  return array_values($this->boot_plugins);
707  }
708 
709  $volatile_data_name = null;
710  $site_guid = 1;
711 
712  // grab plugins
713  $options = [
714  'type' => 'object',
715  'subtype' => 'plugin',
716  'limit' => false,
717  'order_by' => false,
718  ];
719 
720  switch ($status) {
721  case 'active':
722  $options['relationship'] = 'active_plugin';
723  $options['relationship_guid'] = $site_guid;
724  $options['inverse_relationship'] = true;
725 
726  // shorten callstack
727  $volatile_data_name = 'select:value';
728  $options['select'] = ['n_table.value'];
729  $options['metadata_names'] = [
731  ];
732  break;
733 
734  case 'inactive':
735  $options['wheres'][] = function (QueryBuilder $qb, $main_alias) use ($site_guid) {
736  $subquery = $qb->subquery('entity_relationships', 'active_er');
737  $subquery->select('active_er.guid_one')
738  ->where($qb->compare('active_er.relationship', '=', 'active_plugin', ELGG_VALUE_STRING))
739  ->andWhere($qb->compare('active_er.guid_two', '=', $site_guid, ELGG_VALUE_GUID));
740 
741  return $qb->compare("{$main_alias}.guid", 'NOT IN', $subquery->getSQL());
742  };
743  break;
744 
745  case 'all':
746  default:
747  break;
748  }
749 
750  $old_ia = $this->session_manager->setIgnoreAccess(true);
752  $this->session_manager->setIgnoreAccess($old_ia);
753 
754  $result = $this->orderPluginsByPriority($plugins, $volatile_data_name);
755 
756  if ($status === 'active' && !isset($this->boot_plugins)) {
757  // populate local cache if for some reason this is not set yet
758  $this->setBootPlugins($result, false);
759  }
760 
761  return $result;
762  }
763 
772  protected function orderPluginsByPriority(array $plugins = [], string $volatile_data_name = null): array {
773  $priorities = [];
774  $sorted_plugins = [];
775 
776  foreach ($plugins as $plugin) {
777  $priority = null;
778  if (!empty($volatile_data_name)) {
779  $priority = $plugin->getVolatileData($volatile_data_name);
780  }
781 
782  if (!isset($priority)) {
783  $priority = $plugin->getPriority();
784  }
785 
786  $priorities[$plugin->guid] = (int) $priority;
787  $sorted_plugins[$plugin->guid] = $plugin;
788  }
789 
790  asort($priorities);
791 
792  return array_values(array_replace($priorities, $sorted_plugins));
793  }
794 
807  public function setPriorities(array $order): bool {
809 
810  $plugins = $this->find('any');
811  if (empty($plugins)) {
812  return false;
813  }
814 
815  // reindex to get standard counting. no need to increment by 10.
816  // though we do start with 1
817  $order = array_values($order);
818 
819  /* @var \ElggPlugin[] $missing_plugins */
820  $missing_plugins = [];
821 
822  $priority = 0;
823  foreach ($plugins as $plugin) {
824  if (!$plugin->isEnabled()) {
825  // disabled plugins should not have a priority
826  if ($plugin->getPriority() !== null) {
827  // remove the priority
828  unset($plugin->$name);
829  }
830 
831  continue;
832  }
833 
834  $plugin_id = $plugin->getID();
835 
836  if (!in_array($plugin_id, $order)) {
837  $missing_plugins[] = $plugin;
838  continue;
839  }
840 
841  $priority = array_search($plugin_id, $order) + 1;
842 
843  if (!$plugin->setMetadata($name, $priority)) {
844  return false;
845  }
846  }
847 
848  // set the missing plugins' priorities
849  if (empty($missing_plugins)) {
850  return true;
851  }
852 
853  foreach ($missing_plugins as $plugin) {
854  $priority++;
855  if (!$plugin->setMetadata($name, $priority)) {
856  return false;
857  }
858  }
859 
860  return true;
861  }
862 
868  public function reindexPriorities(): bool {
869  return $this->setPriorities([]);
870  }
871 
880  public function setPriority(\ElggPlugin $plugin, int $priority): int|false {
881  $old_priority = $plugin->getPriority() ?: 1;
882 
884 
885  if (!$plugin->setMetadata($name, $priority)) {
886  return false;
887  }
888 
889  if (!$plugin->guid) {
890  return false;
891  }
892 
893  $qb = Update::table('metadata');
894  $qb->where($qb->compare('name', '=', $name, ELGG_VALUE_STRING))
895  ->andWhere($qb->compare('entity_guid', '!=', $plugin->guid, ELGG_VALUE_INTEGER));
896 
897  if ($priority > $old_priority) {
898  $qb->set('value', 'CAST(value AS UNSIGNED) - 1');
899  $qb->andWhere($qb->between('CAST(value AS UNSIGNED)', $old_priority, $priority, ELGG_VALUE_INTEGER));
900  } else {
901  $qb->set('value', 'CAST(value AS UNSIGNED) + 1');
902  $qb->andWhere($qb->between('CAST(value AS UNSIGNED)', $priority, $old_priority, ELGG_VALUE_INTEGER));
903  }
904 
905  if (!$this->db->updateData($qb)) {
906  return false;
907  }
908 
909  return $priority;
910  }
911 }
isActive(string $plugin_id)
Returns if a plugin is active for a current site.
Definition: Plugins.php:465
trait Profilable
Make an object accept a timer.
Definition: Profilable.php:12
static project()
Get the project root (where composer is installed) path with "/".
Definition: Paths.php:25
getID()
Returns the ID (dir name) of this plugin.
Definition: ElggPlugin.php:138
setMetadata(string $name, $value, string $value_type= '', bool $multiple=false)
Set metadata on this entity.
Definition: ElggEntity.php:370
$plugin
Elgg HTTP request.
Definition: Request.php:17
reindexPriorities()
Reindexes all plugin priorities starting at 1.
Definition: Plugins.php:868
Exception thrown if an argument is not of the expected type.
getMaxPriority()
Returns the highest priority of the plugins.
Definition: Plugins.php:442
if(!$user||!$user->canDelete()) $name
Definition: delete.php:22
static table($table, $alias=null)
{}
Definition: Update.php:13
build()
Registers lifecycle events for all active plugins sorted by their priority.
Definition: Plugins.php:487
The Elgg database.
Definition: Database.php:25
$request
Definition: livesearch.php:11
const ELGG_VALUE_INTEGER
Value types.
Definition: constants.php:111
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special the source code distributed need not include anything that is normally and so on of the operating system on which the executable unless that component itself accompanies the executable If distribution of executable or object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place counts as distribution of the source even though third parties are not compelled to copy the source along with the object code You may not or distribute the Program except as expressly provided under this License Any attempt otherwise to sublicense or distribute the Program is void
Definition: LICENSE.txt:215
Translator $translator
Definition: Plugins.php:79
const ELGG_VALUE_GUID
Definition: constants.php:113
Events service.
Database abstraction query builder.
getDirsInDir(string $dir=null)
Returns a list of plugin directory names from a base directory.
Definition: Plugins.php:203
$plugins
Definition: categories.php:3
boot()
Boot the plugins.
Definition: Plugins.php:539
__construct(BaseCache $cache, Database $db, SessionManagerService $session_manager, EventsService $events, Translator $translator, ViewsService $views, Config $config, SystemMessagesService $system_messages, Request $request)
Constructor.
Definition: Plugins.php:102
invalidate()
Invalidate plugin cache.
Definition: Plugins.php:191
$options
Elgg admin footer.
Definition: footer.php:6
disable(\ElggPlugin $plugin,\Exception $previous)
Disable a plugin upon exception.
Definition: Plugins.php:662
$plugin_id
Remove all user and plugin settings from the give plugin ID.
Definition: remove.php:8
elgg_invalidate_caches()
Invalidate all the registered caches.
Definition: cache.php:183
$path
Definition: details.php:70
if(!$entity instanceof\ElggUser) $data
Definition: attributes.php:13
ViewsService $views
Definition: Plugins.php:81
trait Loggable
Enables adding a logger.
Definition: Loggable.php:14
exists(string $id)
Returns if a plugin exists in the system.
Definition: Plugins.php:433
setBootPlugins(array $plugins=null, bool $order_plugins=true)
Set the list of active plugins according to the boot data cache.
Definition: Plugins.php:147
orderPluginsByPriority(array $plugins=[], string $volatile_data_name=null)
Sorts plugins by priority.
Definition: Plugins.php:772
elgg_get_entities(array $options=[])
Fetches/counts entities or performs a calculation on their properties.
Definition: entities.php:504
ready()
Run plugin ready handlers.
Definition: Plugins.php:587
init()
Initialize plugins.
Definition: Plugins.php:563
generateEntities()
Discovers plugins in the plugins_path setting and creates entities for them if they don&#39;t exist...
Definition: Plugins.php:238
compare($x, $comparison, $y=null, $type=null, $case_sensitive=null)
Build value comparison clause.
Views service.
SystemMessagesService $system_messages
Definition: Plugins.php:85
upgrade()
Run plugin upgrade handlers.
Definition: Plugins.php:611
The Elgg cache base class.
Definition: BaseCache.php:9
clear()
Clear plugin caches.
Definition: Plugins.php:182
invalidateCache($plugin_id)
Remove plugin from cache.
Definition: Plugins.php:375
const PRIORITY_SETTING_NAME
Definition: ElggPlugin.php:18
subquery($table, $alias=null)
Creates a new SelectQueryBuilder for join/where subqueries using the DB connection of the primary Que...
static fromTable($table, $alias=null)
{}
Definition: Select.php:13
getLogger()
Returns logger.
Definition: Loggable.php:37
deactivate()
Deactivates the plugin.
Definition: ElggPlugin.php:648
getContextStack()
Returns context stack.
Definition: Request.php:110
setPriority(\ElggPlugin $plugin, int $priority)
Set plugin priority and adjust the priorities of other plugins.
Definition: Plugins.php:880
const ELGG_VALUE_STRING
Definition: constants.php:112
beginTimer(array $keys)
Start the timer (when enabled)
Definition: Profilable.php:46
System messages service.
getPath()
Get the plugin path for this installation, ending with slash.
Definition: Plugins.php:130
getPriority()
Gets the plugin&#39;s load priority.
Definition: ElggPlugin.php:225
setPriorities(array $order)
Reorder plugins to an order specified by the array.
Definition: Plugins.php:807
elgg_add_admin_notice(string $id, string $message)
Write a persistent message to the admin view.
Definition: admin.php:51
shutdown()
Run plugin shutdown handlers.
Definition: Plugins.php:635
EventsService $events
Definition: Plugins.php:77
$index
Definition: gallery.php:40
Persistent, installation-wide key-value storage.
Definition: Plugins.php:29
static fromId(string $plugin_id, string $path=null)
Load a plugin object from its ID Create a new plugin entity if doesn&#39;t exist.
Definition: ElggPlugin.php:81
cache(\ElggPlugin $plugin)
Cache a reference to this plugin by its ID.
Definition: Plugins.php:360
find(string $status= 'active')
Returns an ordered list of plugins.
Definition: Plugins.php:699
$id
Generic annotation delete action.
Definition: delete.php:6
$qb
Definition: queue.php:11
trait Cacheable
Utility trait for injecting cache.
Definition: Cacheable.php:13
$priority
Manages a global stack of strings for sharing information about the current execution context...
Definition: Context.php:27
SessionManagerService $session_manager
Definition: Plugins.php:75
endTimer(array $keys)
Ends the timer (when enabled)
Definition: Profilable.php:62