diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index b28ed81f2c716..c2da29dfee1b8 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -12,6 +12,8 @@ use Joomla\CMS\Authentication\Authentication; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Extension\AfterJoomlaUpdateEvent; +use Joomla\CMS\Event\Extension\BeforeJoomlaUpdateEvent; use Joomla\CMS\Extension\ExtensionHelper; use Joomla\CMS\Factory; use Joomla\CMS\Filesystem\File as FileCMS; @@ -576,7 +578,7 @@ public function createUpdateFile($basename = null): bool $app = Factory::getApplication(); // Trigger event before joomla update. - $app->triggerEvent('onJoomlaBeforeUpdate'); + $app->getDispatcher()->dispatch('onJoomlaBeforeUpdate', new BeforeJoomlaUpdateEvent('onJoomlaBeforeUpdate')); // Get the absolute path to site's root. $siteroot = JPATH_SITE; @@ -882,7 +884,8 @@ public function cleanUp() $app = Factory::getApplication(); // Trigger event after joomla update. - $app->triggerEvent('onJoomlaAfterUpdate'); + // @TODO: The event dispatched twice, here and at the end of current method. One of it should be removed. + $app->getDispatcher()->dispatch('onJoomlaAfterUpdate', new AfterJoomlaUpdateEvent('onJoomlaAfterUpdate')); // Remove the update package. $tempdir = $app->get('tmp_path'); @@ -909,7 +912,9 @@ public function cleanUp() $oldVersion = $app->getUserState('com_joomlaupdate.oldversion'); // Trigger event after joomla update. - $app->triggerEvent('onJoomlaAfterUpdate', [$oldVersion]); + $app->getDispatcher()->dispatch('onJoomlaAfterUpdate', new AfterJoomlaUpdateEvent('onJoomlaAfterUpdate', [ + 'oldVersion' => $oldVersion ?: '', + ])); $app->setUserState('com_joomlaupdate.oldversion', null); try { diff --git a/libraries/src/Event/CoreEventAware.php b/libraries/src/Event/CoreEventAware.php index f72cafcbbfbc8..9f593fe1b5b45 100644 --- a/libraries/src/Event/CoreEventAware.php +++ b/libraries/src/Event/CoreEventAware.php @@ -149,6 +149,8 @@ trait CoreEventAware 'onExtensionAfterSave' => Model\AfterSaveEvent::class, 'onExtensionAfterDelete' => Model\AfterDeleteEvent::class, 'onExtensionChangeState' => Model\BeforeChangeStateEvent::class, + 'onJoomlaBeforeUpdate' => Extension\BeforeJoomlaUpdateEvent::class, + 'onJoomlaAfterUpdate' => Extension\AfterJoomlaUpdateEvent::class, // Installer 'onInstallerAddInstallationTab' => Installer\AddInstallationTabEvent::class, 'onInstallerBeforeInstallation' => Installer\BeforeInstallationEvent::class, diff --git a/libraries/src/Event/Extension/AbstractJoomlaUpdateEvent.php b/libraries/src/Event/Extension/AbstractJoomlaUpdateEvent.php new file mode 100644 index 0000000000000..dd63377a7cd2b --- /dev/null +++ b/libraries/src/Event/Extension/AbstractJoomlaUpdateEvent.php @@ -0,0 +1,55 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Event\Extension; + +use Joomla\CMS\Event\AbstractImmutableEvent; +use Joomla\CMS\Event\ReshapeArgumentsAware; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Base class for Joomla Update events + * + * @since __DEPLOY_VERSION__ + */ +abstract class AbstractJoomlaUpdateEvent extends AbstractImmutableEvent +{ + use ReshapeArgumentsAware; + + /** + * The argument names, in order expected by legacy plugins. + * + * @var array + * + * @since __DEPLOY_VERSION__ + * @deprecated __DEPLOY_VERSION__ will be removed in 6.0 + */ + protected $legacyArgumentsOrder = []; + + /** + * Constructor. + * + * @param string $name The event name. + * @param array $arguments The event arguments. + * + * @since __DEPLOY_VERSION__ + */ + public function __construct($name, array $arguments = []) + { + // Reshape the arguments array to preserve b/c with legacy listeners + if ($this->legacyArgumentsOrder) { + $arguments = $this->reshapeArguments($arguments, $this->legacyArgumentsOrder); + } + + parent::__construct($name, $arguments); + } +} diff --git a/libraries/src/Event/Extension/AfterJoomlaUpdateEvent.php b/libraries/src/Event/Extension/AfterJoomlaUpdateEvent.php new file mode 100644 index 0000000000000..46672bbec59de --- /dev/null +++ b/libraries/src/Event/Extension/AfterJoomlaUpdateEvent.php @@ -0,0 +1,58 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Event\Extension; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Class for Joomla Update events + * + * @since __DEPLOY_VERSION__ + */ +class AfterJoomlaUpdateEvent extends AbstractJoomlaUpdateEvent +{ + /** + * The argument names, in order expected by legacy plugins. + * + * @var array + * + * @since __DEPLOY_VERSION__ + * @deprecated __DEPLOY_VERSION__ will be removed in 6.0 + */ + protected $legacyArgumentsOrder = ['oldVersion']; + + /** + * Pre-setter for the oldVersion argument. + * + * @param ?string $value The value to set + * + * @return string + * + * @since __DEPLOY_VERSION__ + */ + protected function onSetOldVersion(?string $value): string + { + return $value ?? ''; + } + + /** + * Getter for the oldVersion. + * + * @return string + * + * @since __DEPLOY_VERSION__ + */ + public function getOldVersion(): string + { + return $this->arguments['oldVersion'] ?? ''; + } +} diff --git a/libraries/src/Event/Extension/BeforeJoomlaUpdateEvent.php b/libraries/src/Event/Extension/BeforeJoomlaUpdateEvent.php new file mode 100644 index 0000000000000..635cee88ebc26 --- /dev/null +++ b/libraries/src/Event/Extension/BeforeJoomlaUpdateEvent.php @@ -0,0 +1,23 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Event\Extension; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Class for Joomla Update events + * + * @since __DEPLOY_VERSION__ + */ +class BeforeJoomlaUpdateEvent extends AbstractJoomlaUpdateEvent +{ +} diff --git a/plugins/extension/finder/src/Extension/Finder.php b/plugins/extension/finder/src/Extension/Finder.php index 2934ad9fd8aed..16ef01c32cfb2 100644 --- a/plugins/extension/finder/src/Extension/Finder.php +++ b/plugins/extension/finder/src/Extension/Finder.php @@ -10,11 +10,15 @@ namespace Joomla\Plugin\Extension\Finder\Extension; -use Joomla\CMS\Installer\Installer; +use Joomla\CMS\Event\Extension\AbstractExtensionEvent; +use Joomla\CMS\Event\Extension\AfterInstallEvent; +use Joomla\CMS\Event\Extension\AfterUninstallEvent; +use Joomla\CMS\Event\Extension\AfterUpdateEvent; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\Component\Finder\Administrator\Indexer\Helper; use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; +use Joomla\Event\SubscriberInterface; use Joomla\String\StringHelper; // phpcs:disable PSR1.Files.SideEffects @@ -26,22 +30,39 @@ * * @since 4.0.0 */ -final class Finder extends CMSPlugin +final class Finder extends CMSPlugin implements SubscriberInterface { use DatabaseAwareTrait; + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onExtensionAfterInstall' => 'onExtensionAfterInstall', + 'onExtensionAfterUpdate' => 'onExtensionAfterUpdate', + 'onExtensionAfterUninstall' => 'onExtensionAfterUninstall', + ]; + } + /** * Add common words to finder after language got installed * - * @param Installer $installer Installer object - * @param integer $eid Extension Identifier + * @param AfterInstallEvent $event Event instance. * * @return void * * @since 4.0.0 */ - public function onExtensionAfterInstall($installer, $eid) + public function onExtensionAfterInstall(AbstractExtensionEvent $event): void { + $eid = $event->getEid(); + if (!$eid) { return; } @@ -68,31 +89,32 @@ public function onExtensionAfterInstall($installer, $eid) /** * Add common words to finder after language got updated * - * @param Installer $installer Installer object - * @param integer $eid Extension identifier + * @param AfterUpdateEvent $event Event instance. * * @return void * * @since 4.0.0 */ - public function onExtensionAfterUpdate($installer, $eid) + public function onExtensionAfterUpdate(AfterUpdateEvent $event): void { - $this->onExtensionAfterInstall($installer, $eid); + $this->onExtensionAfterInstall($event); } /** * Remove common words to finder after language got uninstalled * - * @param Installer $installer Installer instance - * @param integer $eid Extension id - * @param boolean $removed Installation result + * @param AfterUninstallEvent $event Event instance. * * @return void * * @since 4.0.0 */ - public function onExtensionAfterUninstall($installer, $eid, $removed) + public function onExtensionAfterUninstall(AfterUninstallEvent $event): void { + $installer = $event->getInstaller(); + $eid = $event->getEid(); + $removed = $event->getRemoved(); + // Check that the language was successfully uninstalled. if ($eid && $removed && $installer->extension->type === 'language') { $this->removeCommonWords($installer->extension); diff --git a/plugins/extension/joomla/src/Extension/Joomla.php b/plugins/extension/joomla/src/Extension/Joomla.php index 46c49c0f7af1d..b98e8f8c8e875 100644 --- a/plugins/extension/joomla/src/Extension/Joomla.php +++ b/plugins/extension/joomla/src/Extension/Joomla.php @@ -10,11 +10,15 @@ namespace Joomla\Plugin\Extension\Joomla\Extension; +use Joomla\CMS\Event\Extension\AfterInstallEvent; +use Joomla\CMS\Event\Extension\AfterUninstallEvent; +use Joomla\CMS\Event\Extension\AfterUpdateEvent; use Joomla\CMS\Installer\Installer; use Joomla\CMS\Language\Text; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -25,7 +29,7 @@ * * @since 1.6 */ -final class Joomla extends CMSPlugin +final class Joomla extends CMSPlugin implements SubscriberInterface { use DatabaseAwareTrait; @@ -52,6 +56,22 @@ final class Joomla extends CMSPlugin */ protected $autoloadLanguage = true; + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onExtensionAfterInstall' => 'onExtensionAfterInstall', + 'onExtensionAfterUpdate' => 'onExtensionAfterUpdate', + 'onExtensionAfterUninstall' => 'onExtensionAfterUninstall', + ]; + } + /** * Adds an update site to the table if it doesn't exist. * @@ -138,17 +158,18 @@ private function addUpdateSite($name, $type, $location, $enabled, $extraQuery = /** * Handle post extension install update sites * - * @param Installer $installer Installer object - * @param integer $eid Extension Identifier + * @param AfterInstallEvent $event Event instance. * * @return void * * @since 1.6 */ - public function onExtensionAfterInstall($installer, $eid) + public function onExtensionAfterInstall(AfterInstallEvent $event): void { + $eid = $event->getEid(); + if ($eid) { - $this->installer = $installer; + $this->installer = $event->getInstaller(); $this->eid = (int) $eid; // After an install we only need to do update sites @@ -159,16 +180,17 @@ public function onExtensionAfterInstall($installer, $eid) /** * Handle extension uninstall * - * @param Installer $installer Installer instance - * @param integer $eid Extension id - * @param boolean $removed Installation result + * @param AfterUninstallEvent $event Event instance. * * @return void * * @since 1.6 */ - public function onExtensionAfterUninstall($installer, $eid, $removed) + public function onExtensionAfterUninstall(AfterUninstallEvent $event): void { + $eid = $event->getEid(); + $removed = $event->getRemoved(); + // If we have a valid extension ID and the extension was successfully uninstalled wipe out any // update sites for it if ($eid && $removed) { @@ -240,17 +262,18 @@ public function onExtensionAfterUninstall($installer, $eid, $removed) /** * After update of an extension * - * @param Installer $installer Installer object - * @param integer $eid Extension identifier + * @param AfterUpdateEvent $event Event instance. * * @return void * * @since 1.6 */ - public function onExtensionAfterUpdate($installer, $eid) + public function onExtensionAfterUpdate(AfterUpdateEvent $event): void { + $eid = $event->getEid(); + if ($eid) { - $this->installer = $installer; + $this->installer = $event->getInstaller(); $this->eid = (int) $eid; // Handle any update sites diff --git a/plugins/extension/namespacemap/src/Extension/NamespaceMap.php b/plugins/extension/namespacemap/src/Extension/NamespaceMap.php index 4dc2fb80c864f..c5e60266ad6c7 100644 --- a/plugins/extension/namespacemap/src/Extension/NamespaceMap.php +++ b/plugins/extension/namespacemap/src/Extension/NamespaceMap.php @@ -10,9 +10,12 @@ namespace Joomla\Plugin\Extension\NamespaceMap\Extension; -use Joomla\CMS\Installer\Installer; +use Joomla\CMS\Event\Extension\AfterInstallEvent; +use Joomla\CMS\Event\Extension\AfterUninstallEvent; +use Joomla\CMS\Event\Extension\AfterUpdateEvent; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\Event\DispatcherInterface; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -23,7 +26,7 @@ * * @since 4.0.0 */ -final class NamespaceMap extends CMSPlugin +final class NamespaceMap extends CMSPlugin implements SubscriberInterface { /** * The namespace map file creator @@ -50,20 +53,35 @@ public function __construct(DispatcherInterface $dispatcher, \JNamespacePsr4Map parent::__construct($dispatcher, $config); } + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onExtensionAfterInstall' => 'onExtensionAfterInstall', + 'onExtensionAfterUpdate' => 'onExtensionAfterUpdate', + 'onExtensionAfterUninstall' => 'onExtensionAfterUninstall', + ]; + } + /** * Update / Create map on extension install * - * @param Installer $installer Installer instance - * @param integer $eid Extension id + * @param AfterInstallEvent $event Event instance. * * @return void * * @since 4.0.0 */ - public function onExtensionAfterInstall($installer, $eid) + public function onExtensionAfterInstall(AfterInstallEvent $event): void { // Check that we have a valid extension - if ($eid) { + if ($event->getEid()) { // Update / Create new map $this->fileCreator->create(); } @@ -72,18 +90,16 @@ public function onExtensionAfterInstall($installer, $eid) /** * Update / Create map on extension uninstall * - * @param Installer $installer Installer instance - * @param integer $eid Extension id - * @param boolean $removed Installation result + * @param AfterUninstallEvent $event Event instance. * * @return void * * @since 4.0.0 */ - public function onExtensionAfterUninstall($installer, $eid, $removed) + public function onExtensionAfterUninstall(AfterUninstallEvent $event): void { // Check that we have a valid extension and that it has been removed - if ($eid && $removed) { + if ($event->getEid() && $event->getRemoved()) { // Update / Create new map $this->fileCreator->create(); } @@ -92,17 +108,16 @@ public function onExtensionAfterUninstall($installer, $eid, $removed) /** * Update map on extension update * - * @param Installer $installer Installer instance - * @param integer $eid Extension id + * @param AfterUpdateEvent $event Event instance. * * @return void * * @since 4.0.0 */ - public function onExtensionAfterUpdate($installer, $eid) + public function onExtensionAfterUpdate(AfterUpdateEvent $event): void { // Check that we have a valid extension - if ($eid) { + if ($event->getEid()) { // Update / Create new map $this->fileCreator->create(); } diff --git a/plugins/installer/override/src/Extension/Override.php b/plugins/installer/override/src/Extension/Override.php index af8a35ce45527..e2a10231d58d1 100644 --- a/plugins/installer/override/src/Extension/Override.php +++ b/plugins/installer/override/src/Extension/Override.php @@ -15,6 +15,7 @@ use Joomla\CMS\Plugin\CMSPlugin; use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -25,7 +26,7 @@ * * @since 4.0.0 */ -final class Override extends CMSPlugin +final class Override extends CMSPlugin implements SubscriberInterface { use DatabaseAwareTrait; @@ -38,6 +39,25 @@ final class Override extends CMSPlugin */ protected $autoloadLanguage = true; + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onExtensionBeforeUpdate' => 'onExtensionBeforeUpdate', + 'onExtensionAfterUpdate' => 'onExtensionAfterUpdate', + 'onJoomlaBeforeUpdate' => 'onJoomlaBeforeUpdate', + 'onJoomlaAfterUpdate' => 'onJoomlaAfterUpdate', + 'onInstallerBeforeInstaller' => 'onInstallerBeforeInstaller', + 'onInstallerAfterInstaller' => 'onInstallerAfterInstaller', + ]; + } + /** * Method to get com_templates model instance. *