Joomla! is organising a Pizza, Bugs & Fun (PBF) event for fixing issues in Joomla! 5 on August 26th, 2023. We will be there and we have some updates for people who will be participating in the event.
New development releases for Joomla! 5
Joomla! 5 has been progressing with leaps and bounds over the last month. Being a new major version it brings some pretty deep and very much necessary changes in how plugin events —calling and handling— work. Unfortunately, this means that our releases from early August 2023 do not work on the current development release of Joomla! 5.
Over the last two days we've been working tirelessly to address the major changes in Joomla! 5 and make versions of our software which work on it. Since this code has only undergone rudimentary testing, we make them as Developer Releases.
Do not install these versions on production sites. These are development versions, only meant to be used on development and testing Joomla! 5 sites during the Pizza, Bugs & Fun event of August 26th, 2023.
- Akeeba Backup 9.7.0 Core — Development Release for PBF
- Akeeba Backup 9.7.0 Professional — Development Release for PBF
- Admin Tools 7.4.0 Core — Development Release for PBF
- Admin Tools 7.4.0 Professional — Development Release for PBF
- Akeeba Ticket System 5.3.0 Core — Development Release for PBF
- Akeeba Ticket System 5.3.0 Professional — Development Release for PBF
Kindly note that the Professional editions of the development releases are only available to subscribers of the corresponding product. The Core editions can be downloaded by everyone.
So, what changed in Joomla 5?
TL;DR: Joomla! 5 completes the transition of plugin events to Event objects. This will cause a few problems, but it's (presumably) the last of the absolutely necessary Big Changes to the Joomla! extensions development paradigm which will carry Joomla! forward the next 18 years of its life. These changes were coming for the last decade. They were gradually deployed, this being the last part that breaks backwards compatibility, to avoid have a massive number of big changes in a single major version. The good news is that with these changes Joomla! will become faster and more robust. If you wonder why's that, and you are fond of chocolate, keep reading.
All plugin events in Joomla! 1.0 through 3.10, and most plugin events in Joomla! 4, were generic. They did not have a normative method signature. While this allowed developers to write plugins very easily, it was both slow and caused a lot of problems.
In Joomla 1.0 through 3.10 there was no way to communicate, let alone enforce, the number, name, and type of parameters to each named plugin event — whether firing (running) or handling them. Each developer was left to its own devices. Even the core code in Joomla itself had inconsistencies, especially for event names which are used in a multitude of places, for a plethora of use cases. The number of sites I've seen breaking because a developer misunderstood how onContentPrepare
is meant to work (and I've done that mistake myself, too)… Joomla! 4 changed how events work by introducing Event objects. Event objects can be generic or concrete.
This is already reaching a level of abstraction most people can't grasp, so let's use an analogy. Forrest Gump's mom said that life's a box of chocolates. Hm, I think I can work with that!
In Joomla! 1.0 through 3.10 a plugin event was just a name and a bunch of random data in an array; much like trying to hold a bunch of assorted chocolate bites in your hand to take them to your grandma. Throughout the journey on foot and by bus they will melt, warp, some will get lost, and they will get absolutely gross by the time you reach maw-maw.
With an event object you have a rudimentary container to put your chocolates in. This is better! The chocolate won't melt. However, is it really a good way to transport chocolate? You'll definitely drop something on the way, and other, um, stuff might land on it. Not the best way to get chocolate to grandma, either.
Concrete events are like having a purpose built, fitted container. Everything has its place! You know how many chocolate bites you have, what they look like, and where they fit. If you were to, uh, misplace some it would be pretty evident (and not by the chocolate smudged on your face). Why, this is a great way to transport chocolate!
Now, here's the thing. If someone hands you a bunch of chocolate you can of course grab it with your hands; they're right there (for most of us; apologies to people with disabilities, I am already strained to find a good analogy here). If you were told no, you absolutely cannot use your hands you would have to find a bowl or other suitable container. A bit harder, but it can be done, especially if the person telling you so also hands you the bowl.
This was the approach followed with Joomla 4. It told you that events should no longer be handled the Neanderthal way of yore ("don't use your hands!"), but it would also automatically upgrade your primitive event firing and handling to events ("here, use a bowl"). In most cases it would not even offer you a concrete event object ("no, you can't have a tray for this chocolate; just use the freakin' bowl, will ya?!").
Going to the next step is much harder. In our chocolate analogy, you'd be given the vacuum-formed plastic tray to put your chocolates in, but you'd need to also provide your own box or other wrapping to safely transport them. And what happens if you made the chocolate yourself and it doesn't fit in those premade slots?
This is essentially what happened with Joomla! 5. All core Joomla! events are now using concrete objects ("don't use a bowl; use this plastic tray!").
For developers handling the events it means that they no longer receive a bowl of chocolate. They get a vacuum-formed plastic tray in a box. If your code was just trying to empty the bowl of chocolate into another bowl it fails; the plastic tray is in a box, duh! To put it into code, this code worked in Joomla! 4:
[$foo, $bar] = $event->getArguments();
but it no longer works in Joomla! 5 because the chocolate (getArguments) is in a box. We have to open the box:
[$foo, $bar] = array_values($event->getArguments());
Of course, once we stop needing to support Joomla! 4 and its bowl of chocolate (generic events) we can write this far more elegantly:
$foo = $event->getFoo();
$bar = $event->getBar();
Instead of trying to empty the tray of chocolate to a bowl and sort it out before eating it (how dumb!) we can just, you know, pick the chocolate shape we want from the nicely sorted box of chocolates — which I assume is how y'all eat your chocolate bites.
For developers calling the events it means that we can no longer write code cowboy-style:
$event = new GenericEvent('onFooBar', [$foo, $bar]);
$this->getApplication()->getDispatcher()->dispatch($event->getName(), $event);
Trying to do that crashes Joomla! if onFooBar is one of the events with a concrete event object. Joomla! expects to be handed over a tray of chocolates and we have it a bowl; it dropped it, it broke, and nobody gets to eat the chocolate. (In more technical terms, Joomla's event handlers have an event argument which is typed to the concrete event's class; by sending an event object of a different type we trigger a PHP type error, which is why I'm saying that Joomla! expected a tray of chocolate and we gave it a bowl).
There are ways around it, of course, and it's part of the code I had contributed to Joomla! back in 2021.
And why this won't affect old-school extensions (oh, the irony!)
The most ironic part of the changes made in Joomla! 5 is that the only extensions which break are those which were written as native Joomla! 4 extensions.
Plugins which were still using the antediluvian pattern of methods with arbitrary arguments (as opposed to real event handlers) will work just fine. I had contributed code to Joomla! in 2015 and 2021 which does that.
Plugins which were handling real events get their butt handed to them because $event->getArguments()
returns a string-indexed array for concrete events, when it was an integer-indexed array for generic events. You can solve that problem by wrapping this call with array_values()
. The code I contributed in 2021 (\Joomla\CMS\Event\CoreEventAware
) makes sure to keep the same order of parameters as the older generic events used in Joomla! 4. Yes, I foresaw this problem in 2021 — it was also how I made sure that old-school plugins would still work when events become concrete.
Those who are still firing events like Neanderthals, using $this->getApplication()->triggerEvent('onFoobar', [$foo, $bar]);
will have no problem. I had contributed code in 2015 which translates that to real events, and more code in 2021 which magically finds the correct core concrete event class for the event name you provided. The only event where this will fail is onContentCleanCache
due to an omission — if you are brave enough to make it through here, please fix it during this Pizza, Bugs & Fun event! It's just one line to be added to \Joomla\CMS\Event\CoreEventAware
.
Frankly, the solution I am using (e.g. \Akeeba\Component\AkeebaBackup\Administrator\Mixin\RunPluginsTrait
in Akeeba Backup) is over-engineered. I was trying to come up with a universal solution which will allow me to convert my custom plugin events to concrete, and log the use of non-concrete events, and work with Joomla! 4 and 5, and make it possible to get a great deal into migrating to concrete core Joomla! events before dropping Joomla! 4 support, and make it possible to remove that solution in favor of concrete events once I drop Joomla 4 support. Yes, it's code written in 2023 to deal with problems I will need to solve in 2025. For most people, the ideal solution is using my solution from 2015 (improved in 2021) that's already in the core: $this->getApplication()->triggerEvent('onFoobar', [$foo, $bar]);
. Once you decide to drop Joomla 4 support, or if you are insane enough to try and support Joomla 4, 5 and 6 in the same code base, you can probably fork the \Joomla\CMS\Application\EventAware
trait.
I'm not a developer. Should I be worried?
No, not really.
While there is a modicum of backwards incompatible changes between Joomla! 4 and Joomla! 5 any half-competent developer can work around it. Even a rather novice developer can figure it upon reading the more technical information in this article.
I'm a developer. Should I be worried?
Not at all.
Please do read my code. I have bumped —or, rather, head-on collided— with the same problems challenging you now and I figured it out. If you have questions, you can contact me and ask me. I will try my best to help you, time permitting. I may no longer be able to contribute to the Joomla! core, but I'm still around to help other people.