Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Plugin groups and events

The group of a plugin determines when Joomla loads it and which events it usually handles. The content plugin from the previous lesson works only where content is output or saved. Other tasks need another group — the file structure stays the same.

Groups

GroupFolderPurpose
contentplugins/contentPreparing, saving and deleting content
systemplugins/systemStages of handling any request
userplugins/userLogin, logout, registration, saving a user
authenticationplugins/authenticationWays of checking a name and password
editors-xtdplugins/editors-xtdButtons below the editor
webservicesplugins/webservicesAPI routes
consoleplugins/consoleConsole commands
taskplugins/taskScheduler tasks

A system plugin

Plugins of the system group are loaded on every request — on the site and in the panel. Create a second plugin modelled on the first:

plugins/system/hello/
├── hello.xml
├── services/provider.php
└── src/Extension/Hello.php

In the manifest replace group="content" with group="system", the name with plg_system_hello, the namespace with My\Plugin\System\Hello. In the provider use PluginHelper::getPlugin('system', 'hello') and the new class. The class itself:

// plugins/system/hello/src/Extension/Hello.php
namespace My\Plugin\System\Hello\Extension;
 
defined('_JEXEC') or die;
 
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\Event;
use Joomla\Event\SubscriberInterface;
 
final class Hello extends CMSPlugin implements SubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            'onAfterInitialise' => 'addHeader',
        ];
    }
 
    public function addHeader(Event $event): void
    {
        $this->getApplication()->setHeader('X-Frame-Options', 'SAMEORIGIN', true);
    }
}

Install the plugin through Discover and enable it. Open the browser developer tools, the Network tab: the response headers of every page now include X-Frame-Options.

Request events

System events come in this order:

EventWhen it happens
onAfterInitialiseJoomla is loaded, the request is not parsed yet
onAfterRouteThe component and the page are determined
onAfterDispatchThe component has run, the content is ready
onBeforeRenderBefore the template assembles the page
onBeforeCompileHeadBefore the head tags are output — the last chance to add styles and scripts
onAfterRenderThe page is ready and its whole text can be changed

To run code on the site only, check the client: $this->getApplication()->isClient('site').

A user plugin

The plugin plugins/user/hello with the namespace My\Plugin\User\Hello is created the same way. It greets a user after login:

// plugins/user/hello/src/Extension/Hello.php
public static function getSubscribedEvents(): array
{
    return [
        'onUserAfterLogin' => 'greet',
    ];
}
 
public function greet(Event $event): void
{
    $options = $event->getArgument('options');
 
    $this->getApplication()->enqueueMessage('Welcome back, ' . $options['user']->name . '!');
}

The event carries an options array that holds the user who logged in. enqueueMessage() queues a message — it appears at the top of the next page. Log in on the site: "Welcome back, Anna!" is shown above the content.

Content and user events

EventWhen it happens
onContentPrepareText is being prepared for output
onContentBeforeSave, onContentAfterSaveBefore and after a record is saved
onContentAfterDeleteAfter a record is deleted
onContentPrepareFormA form is prepared — fields can be added to it
onUserAfterLogin, onUserLogoutLogin and logout
onUserBeforeSave, onUserAfterSaveBefore and after a user is saved

Ready examples are in the core folders: plugins/content, plugins/system, plugins/user.

Common mistake

Heavy work — database queries or calls to an external service — is put into a system plugin without any conditions. Such code runs on every request, including the control panel and the API. Check the client and the address first, and only then do the work.

Thanks for reading!

Donate to the site — we work hard for you.