Skip to content

Commit e66a3fd

Browse files
Merge pull request #562 from robbiejackson/redo-plugin-methods-for-v6
replacement of joomla 4 and 5 changes page
2 parents 2e4cbbd + 7cefd14 commit e66a3fd

37 files changed

+1342
-1242
lines changed
-3.9 KB
Binary file not shown.
-16.7 KB
Binary file not shown.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
title: Advanced Features
3+
sidebar_position: 4
4+
---
5+
6+
Plugin Advanced Features
7+
========================
8+
9+
## Priority of Events
10+
11+
Often there will be several plugins listening for the same event.
12+
13+
The order in which these plugins' handler functions are called is by default controlled by the order the plugins are read in from the database,
14+
and this is determined by the order of the plugins set by the administrator in the Manage / Plugins page on the back-end.
15+
16+
You can change the priority of your plugin's handler function on a per-event basis.
17+
To do this, specify the priority in your response to `getSubscribedEvents` an array of `[<handler function>, <priority>]`
18+
19+
```php
20+
public static function getSubscribedEvents(): array
21+
{
22+
return [
23+
'onContentPrepare' => ['myContentPrepareMethod', \Joomla\Event\Priority::HIGH],
24+
'onContentAfterTitle' => ['myContentAfterTitleMethod', \Joomla\Event\Priority::MIN],
25+
];
26+
}
27+
```
28+
29+
See the other values available in libraries/vendor/joomla/event/src/Priority.php.
30+
Use with caution though, as this will override any priority which the site administrator may want to set through ordering the plugins.
31+
32+
## Stop Event Propagation
33+
34+
To stop the propagation of an event to other plugins you can call
35+
36+
```php
37+
$event->stopPropagation();
38+
```

docs/building-extensions/plugins/basic-content-plugin.md

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,25 @@ In addition, the plugin demonstrates the use of:
1919
- language constants - both in the manifest file and in the plugin code
2020
- returning a value from a plugin method - through the use of the `onContentAfterTitle` event. The plugin code adds some text after the article title.
2121

22-
You can test this plugin on both Joomla 4 and Joomla 5 instances, to see the differences in obtaining the parameters and returning the result (as described in [Joomla 4 and 5 changes](joomla-4-and-5-changes.md)).
22+
The diagram below lists the plugin files to write, or you can download the plugin
23+
from the Joomla Manual Examples repository [shortcodes plugin](https://github.com/joomla/manual-examples/tree/main/plugin-example-shortcode).
2324

24-
![Shortcodes plugin files](_assets/shortcodes.jpg "Shortcodes plugin files")
25-
26-
The diagram shows the plugin files to write, or you can download a zip file of the plugin from [shortcodes plugin download](_assets/plg_shortcodes.zip).
25+
```
26+
plg_shortcodes
27+
├─── language
28+
│ └─── en-GB
29+
│ ├─── plg_content_shortcodes.ini
30+
│ └─── plg_content_shortcodes.sys.ini
31+
├─── services
32+
│ └─── provider.php
33+
├─── src
34+
│ └─── Extension
35+
│ └─── Shortcode.php
36+
└─── shortcodes.xml
37+
```
2738

2839
## Manifest File
29-
For general information on manifest files see [Manifest Files](https://docs.joomla.org/Manifest_files).
40+
For general information on manifest files see [Manifest Files](../install-update/installation/manifest.md).
3041

3142
```xml title="plg_shortcodes/shortcodes.xml"
3243
<?xml version="1.0" encoding="utf-8"?>
@@ -36,7 +47,7 @@ For general information on manifest files see [Manifest Files](https://docs.joom
3647
<description>PLG_CONTENT_SHORTCODES_DESCRIPTION</description>
3748
<author>Me</author>
3849
<creationDate>Today</creationDate>
39-
<copyright>(C) 2024 Open Source Matters, Inc.</copyright>
50+
<copyright>(C) 2025 Open Source Matters, Inc.</copyright>
4051
<license>GNU General Public License version 2 or later</license>
4152
<namespace path="src">My\Plugin\Content\Shortcodes</namespace>
4253
<files>
@@ -58,7 +69,7 @@ Joomla is quite particular when it comes to plugin manifest files, and it's easy
5869
<extension method="upgrade" type="plugin" group="content">
5970
```
6071

61-
Previous sections described plugin types as 'content', 'system', etc but here the `type` is "plugin" (as it's the type of the extension) and the `group` refers to the plugin type.
72+
Here the `type` is "plugin" (as it's the type of the extension) and the `group` refers to the plugin type.
6273

6374
### Language constants
6475

@@ -156,7 +167,7 @@ This is pretty much boilerplate code for obtaining your plugin from the Dependen
156167
use My\Plugin\Content\Shortcodes\Extension\Shortcode;
157168
```
158169

159-
Ensure that this aligns with your `<namespace>` in the manifest file and your `namespace` statement and class name in the Extension class file. .
170+
Ensure that this aligns with your `<namespace>` in the manifest file and your `namespace` statement and class name in the Extension class file.
160171

161172
```php
162173
$config = (array) PluginHelper::getPlugin('content', 'shortcodes');
@@ -172,16 +183,7 @@ Ensure that this matches your class in your `src/Extension` directory.
172183

173184
### Extension Class
174185
This is the main code of the plugin. Hopefully the comments in the code explain what is going on.
175-
176-
As explained in [Joomla 4 and 5 changes](./joomla-4-and-5-changes.md), code which triggers the Events can use a `GenericEvent` or a concrete Event, eg `ContentPrepareEvent`. In both these cases you can get the arguments using
177-
178-
```php
179-
[$context, $article, $params, $page] = array_values($event->getArguments());
180-
```
181-
182-
but you have to check in your code how to return the result.
183-
184-
Using this approach means that you don't need to change your plugin code if the code which is triggering the event changes from using a generic Event class to a concrete event class.
186+
For further details see the page on [Plugin Methods and Arguments](./methods-and-arguments.md).
185187

186188
```php title="plg_shortcodes/src/Extension/Shortcode.php"
187189
<?php
@@ -191,11 +193,10 @@ namespace My\Plugin\Content\Shortcodes\Extension;
191193
defined('_JEXEC') or die;
192194

193195
use Joomla\CMS\Plugin\CMSPlugin;
194-
use Joomla\Event\Event;
196+
use Joomla\CMS\Event\Content\ContentPrepareEvent;
197+
use Joomla\CMS\Event\Content\AfterTitleEvent;
195198
use Joomla\Event\SubscriberInterface;
196-
use Joomla\CMS\Factory;
197199
use Joomla\CMS\Language\Text;
198-
use Joomla\CMS\Event\Result\ResultAwareInterface;
199200

200201
class Shortcode extends CMSPlugin implements SubscriberInterface
201202
{
@@ -208,29 +209,33 @@ class Shortcode extends CMSPlugin implements SubscriberInterface
208209
}
209210

210211
// this will be called whenever the onContentPrepare event is triggered
211-
public function replaceShortcodes(Event $event)
212+
public function replaceShortcodes(ContentPrepareEvent $event): void
212213
{
213214
/* This function processes the text of an article being presented on the site.
214215
* It replaces any text of the form "{configname}" (where configname is the name
215216
* of a config parameter in configuration.php) with the value of the parameter.
216-
*
217-
* This is similar to shortcodes functionality within wordpress
218217
*/
219-
220-
// The line below restricts the functionality to the site (ie not on api)
218+
219+
// We used setApplication on our plugin instance inside services/provider.php to set the Application instance
220+
// Now we can retrieve it here using getApplication.
221+
// getApplication and setApplication are inherited from CMSPlugin
222+
$app = $this->getApplication();
223+
224+
// The line below restricts the functionality to the front-end site (ie not admin/api/console job)
221225
// You may not want this, so you need to consider this in your own plugins
222-
if (!$this->getApplication()->isClient('site')) {
226+
if (!$app->isClient('site')) {
223227
return;
224228
}
225-
226-
// use this format to get the arguments for both Joomla 4 and Joomla 5
227-
// In Joomla 4 a generic Event is passed
228-
// In Joomla 5 a concrete ContentPrepareEvent is passed
229-
[$context, $article, $params, $page] = array_values($event->getArguments());
229+
230+
// Find out if this event relates to an article or something else (eg contact, user)
231+
$context = $event->getContext();
230232
if ($context !== "com_content.article" && $context !== "com_content.featured") return;
231233

234+
// If we've reached here then it's an article - get the 'text' property
235+
$article = $event->getItem();
232236
$text = $article->text; // text of the article
233-
$config = Factory::getApplication()->getConfig()->toArray(); // config params as an array
237+
238+
$config = $app->getConfig()->toArray(); // config params as an array
234239
// (we can't do a foreach over the config params as a Registry because they're protected)
235240

236241
// the following is just code to replace {configname} with the parameter value
@@ -269,22 +274,22 @@ class Shortcode extends CMSPlugin implements SubscriberInterface
269274
$article->text = $text;
270275
}
271276

272-
public function addShortcodeSubtitle(Event $event)
277+
public function addShortcodeSubtitle(AfterTitleEvent $event): void
273278
{
274-
if (!$this->getApplication()->isClient('site')) {
275-
return;
276-
}
277-
[$context, $article, $params, $page] = array_values($event->getArguments());
278-
if ($context !== "com_content.article" && $context !== "com_content.featured") return;
279-
280-
$eventType = method_exists($event, 'getContext') ? "concrete event class" : "generic event class";
279+
/* This function adds a subtitle to a page on the site front end:
280+
* "Processed for shortcodes" - if the page is an article
281+
* "Not processed for shortcodes" - if the page is a contact, etc.
282+
*/
283+
284+
if (!$this->getApplication()->isClient('site')) return;
281285

282-
if ($event instanceof ResultAwareInterface) {
283-
$event->addResult("{$eventType} via addResult");
286+
$context = $event->getContext();
287+
$this->loadLanguage();
288+
if ($context === "com_content.article" || $context === "com_content.featured")
289+
{
290+
$event->addResult(Text::_('PLG_CONTENT_SHORTCODES_PROCESSED'));
284291
} else {
285-
$result = $event->getArgument('result') ?? [];
286-
$result[] = "{$eventType} via setArgument";
287-
$event->setArgument('result', $result);
292+
$event->addResult(Text::_('PLG_CONTENT_SHORTCODES_NOT_PROCESSED'));
288293
}
289294
}
290295
}
@@ -302,6 +307,8 @@ Language constants which are used in the plugin code:
302307

303308
```php title="plg_shortcodes/language/en-GB/plg_content_shortcodes.ini"
304309
PLG_CONTENT_SHORTCODES_NO_MATCH="Error: no match for shortcode found"
310+
PLG_CONTENT_SHORTCODES_PROCESSED="Processed for shortcodes"
311+
PLG_CONTENT_SHORTCODES_NOT_PROCESSED="Not processed for shortcodes"
305312
```
306313

307314
## Installation
@@ -313,4 +320,6 @@ On my Joomla instance {sitename} the default editor is {editor}.
313320
```
314321
Then navigate to a Joomla site menuitem which displays this article, either as a single article or as one of the featured articles.
315322

316-
The code should work on both Joomla 4 and Joomla 5, and should also display after the article title information about the type of event class used, and how the value is returned.
323+
Include a non-existent configuration parameter in your shortcode to display the error text.
324+
325+
Also compare the subtitle shown for a page displaying an article with a page displaying a contact.

docs/building-extensions/plugins/how-plugins-work.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
title: How Plugins Work
33
sidebar_position: 1
44
---
5+
6+
How Plugins Work
7+
================
8+
9+
## Overview
10+
511
![Plugins Overview](_assets/plugin-overview.jpg "Plugins Overview")
612

713
The diagram shows how Joomla plugins work.
@@ -20,6 +26,8 @@ The process of involving the plugins comprises 2 steps:
2026
1. Import all plugins of a given type
2127
2. Trigger an event
2228

29+
## Importing a Plugin
30+
2331
Importing a plugin type is implemented by the code:
2432
```php
2533
PluginHelper::importPlugin($pluginType, …);
@@ -36,12 +44,16 @@ Importing a plugin type involves:
3644

3745
Splitting the plugins by plugin type in this way makes Joomla more performant - it doesn't need to process plugins which aren't going to be interested in the event which will be triggered next.
3846

47+
## Triggering an Event
48+
3949
The second step is triggering an event via a call to the event dispatcher. Joomla looks through its store of `Listeners` to determine which plugins have subscribed to that event type. It then calls the associated method of the subscribing plugin, and passes the event data to it, often allowing that data to be modified by the plugin code.
4050

4151
Each plugin which has subscribed to that event is called in turn (based on a priority scheme), and any results returned by the plugins are collated into an array associated with the event.
4252

4353
As an example, after Joomla is initialised system plugins are imported and the event `onAfterInitialise` is triggered. The "Remember Me" plugin (in plugins/system/remember) receives notification of this, and can log in a user who has previously checked the "Remember Me" checkbox on the login form.
4454

55+
## Subsequent Events
56+
4557
Once a plugin has been imported and its subscriptions logged in the `Listeners` data store, then it continues to receive notifications for all the events it has subscribed to. For example, consider the following scenario:
4658
- system plugins are imported, and the `onAfterInitialise` event is triggered
4759
- some time later content plugins are imported, and the `onContentPrepare` event is triggered.
@@ -50,6 +62,8 @@ The system plugins imported in the first step can subscribe to the `onContentPre
5062

5163
You should also be aware that unlike components and modules, there aren't different site plugins and administrator plugins. The plugins which you install are run for all the different contexts - site, administrator and API applications - so it's a good idea to in your plugins to check the application context.
5264

65+
## Sequence Diagram
66+
5367
For those who wish a more detailed picture of how plugins work, see the sequence diagram below.
5468

5569
```mermaid

0 commit comments

Comments
 (0)