diff --git a/libraries/src/Event/CoreEventAware.php b/libraries/src/Event/CoreEventAware.php index b3507b111bf44..ce55048350968 100644 --- a/libraries/src/Event/CoreEventAware.php +++ b/libraries/src/Event/CoreEventAware.php @@ -90,6 +90,8 @@ trait CoreEventAware 'onSchemaPrepareData' => Plugin\System\Schemaorg\PrepareDataEvent::class, 'onSchemaPrepareForm' => Plugin\System\Schemaorg\PrepareFormEvent::class, 'onSchemaPrepareSave' => Plugin\System\Schemaorg\PrepareSaveEvent::class, + // Plugin: Stats + 'onGetStatsData' => Plugin\System\Stats\GetStatsDataEvent::class, // Content 'onContentPrepare' => Content\ContentPrepareEvent::class, 'onContentAfterTitle' => Content\AfterTitleEvent::class, diff --git a/libraries/src/Event/Plugin/System/Stats/GetStatsDataEvent.php b/libraries/src/Event/Plugin/System/Stats/GetStatsDataEvent.php new file mode 100644 index 0000000000000..1b897777dc332 --- /dev/null +++ b/libraries/src/Event/Plugin/System/Stats/GetStatsDataEvent.php @@ -0,0 +1,94 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Event\Plugin\System\Stats; + +use Joomla\CMS\Event\AbstractImmutableEvent; +use Joomla\CMS\Event\ReshapeArgumentsAware; +use Joomla\CMS\Event\Result\ResultAware; +use Joomla\CMS\Event\Result\ResultAwareInterface; +use Joomla\CMS\Event\Result\ResultTypeArrayAware; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Class for Stats plugin. + * Example: + * new GetStatsDataEvent('onEventName', ['context' => 'com_example.example']); + * + * @since __DEPLOY_VERSION__ + */ +class GetStatsDataEvent extends AbstractImmutableEvent implements ResultAwareInterface +{ + use ReshapeArgumentsAware; + use ResultAware; + use ResultTypeArrayAware; + + /** + * 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 = ['context']; + + /** + * Constructor. + * + * @param string $name The event name. + * @param array $arguments The event arguments. + * + * @throws \BadMethodCallException + * + * @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); + + if (!\array_key_exists('context', $this->arguments)) { + throw new \BadMethodCallException("Argument 'context' of event {$name} is required but has not been provided"); + } + } + + /** + * Setter for the context argument. + * + * @param string $value The value to set + * + * @return string + * + * @since __DEPLOY_VERSION__ + */ + protected function onSetContext(string $value): string + { + return $value; + } + + /** + * Getter for the context argument. + * + * @return string + * + * @since __DEPLOY_VERSION__ + */ + public function getContext(): string + { + return $this->arguments['context']; + } +} diff --git a/plugins/system/accessibility/src/Extension/Accessibility.php b/plugins/system/accessibility/src/Extension/Accessibility.php index e951c9166a97b..7b3b2f6e4c377 100644 --- a/plugins/system/accessibility/src/Extension/Accessibility.php +++ b/plugins/system/accessibility/src/Extension/Accessibility.php @@ -10,7 +10,9 @@ namespace Joomla\Plugin\System\Accessibility\Extension; +use Joomla\CMS\Event\Application\BeforeCompileHeadEvent; use Joomla\CMS\Plugin\CMSPlugin; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -21,32 +23,49 @@ * * @since 4.0.0 */ -final class Accessibility extends CMSPlugin +final class Accessibility extends CMSPlugin implements SubscriberInterface { + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onBeforeCompileHead' => 'onBeforeCompileHead', + ]; + } + /** * Add the javascript for the accessibility menu * + * @param BeforeCompileHeadEvent $event The event object + * * @return void * * @since 4.0.0 */ - public function onBeforeCompileHead() + public function onBeforeCompileHead(BeforeCompileHeadEvent $event): void { $section = $this->params->get('section', 'administrator'); + $app = $event->getApplication(); - if ($section !== 'both' && $this->getApplication()->isClient($section) !== true) { + if ($section !== 'both' && $app->isClient($section) !== true) { return; } // Get the document object. - $document = $this->getApplication()->getDocument(); + $document = $event->getDocument(); if ($document->getType() !== 'html') { return; } // Are we in a modal? - if ($this->getApplication()->getInput()->get('tmpl', '', 'cmd') === 'component') { + if ($app->getInput()->get('tmpl', '', 'cmd') === 'component') { return; } @@ -54,10 +73,10 @@ public function onBeforeCompileHead() $this->loadLanguage(); // Determine if it is an LTR or RTL language - $direction = $this->getApplication()->getLanguage()->isRtl() ? 'right' : 'left'; + $direction = $app->getLanguage()->isRtl() ? 'right' : 'left'; // Detect the current active language - $lang = $this->getApplication()->getLanguage()->getTag(); + $lang = $app->getLanguage()->getTag(); /** * Add strings for translations in Javascript. @@ -67,20 +86,20 @@ public function onBeforeCompileHead() 'accessibility-options', [ 'labels' => [ - 'menuTitle' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_MENU_TITLE'), - 'increaseText' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_INCREASE_TEXT'), - 'decreaseText' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_DECREASE_TEXT'), - 'increaseTextSpacing' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_INCREASE_SPACING'), - 'decreaseTextSpacing' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_DECREASE_SPACING'), - 'invertColors' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_INVERT_COLORS'), - 'grayHues' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_GREY'), - 'underlineLinks' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_UNDERLINE'), - 'bigCursor' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_CURSOR'), - 'readingGuide' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_READING'), - 'textToSpeech' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_TTS'), - 'speechToText' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_STT'), - 'resetTitle' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_RESET'), - 'closeTitle' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_CLOSE'), + 'menuTitle' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_MENU_TITLE'), + 'increaseText' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_INCREASE_TEXT'), + 'decreaseText' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_DECREASE_TEXT'), + 'increaseTextSpacing' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_INCREASE_SPACING'), + 'decreaseTextSpacing' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_DECREASE_SPACING'), + 'invertColors' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_INVERT_COLORS'), + 'grayHues' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_GREY'), + 'underlineLinks' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_UNDERLINE'), + 'bigCursor' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_CURSOR'), + 'readingGuide' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_READING'), + 'textToSpeech' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_TTS'), + 'speechToText' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_STT'), + 'resetTitle' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_RESET'), + 'closeTitle' => $app->getLanguage()->_('PLG_SYSTEM_ACCESSIBILITY_CLOSE'), ], 'icon' => [ 'position' => [ diff --git a/plugins/system/actionlogs/src/Extension/ActionLogs.php b/plugins/system/actionlogs/src/Extension/ActionLogs.php index 5f4129451519a..2b1e9f1bd0999 100644 --- a/plugins/system/actionlogs/src/Extension/ActionLogs.php +++ b/plugins/system/actionlogs/src/Extension/ActionLogs.php @@ -11,6 +11,9 @@ namespace Joomla\Plugin\System\ActionLogs\Extension; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Application\AfterInitialiseEvent; +use Joomla\CMS\Event\Model; +use Joomla\CMS\Event\User; use Joomla\CMS\Form\Form; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; @@ -21,7 +24,8 @@ use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; -use Joomla\Event\DispatcherInterface; +use Joomla\Event\Priority; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -32,41 +36,60 @@ * * @since 3.9.0 */ -final class ActionLogs extends CMSPlugin +final class ActionLogs extends CMSPlugin implements SubscriberInterface { use DatabaseAwareTrait; use UserFactoryAwareTrait; /** - * Constructor. + * Returns an array of events this subscriber will listen to. * - * @param DispatcherInterface $dispatcher The dispatcher - * @param array $config An optional associative array of configuration settings + * @return array * - * @since 3.9.0 + * @since __DEPLOY_VERSION__ */ - public function __construct(DispatcherInterface $dispatcher, array $config) + public static function getSubscribedEvents(): array { - parent::__construct($dispatcher, $config); + return [ + 'onAfterInitialise' => ['onAfterInitialise', Priority::ABOVE_NORMAL], + 'onContentPrepareForm' => 'onContentPrepareForm', + 'onContentPrepareData' => 'onContentPrepareData', + 'onUserAfterSave' => 'onUserAfterSave', + 'onUserAfterDelete' => 'onUserAfterDelete', + 'onExtensionAfterSave' => 'onExtensionAfterSave', + ]; + } + /** + * After initialise listener. + * + * @param AfterInitialiseEvent $event The event instance. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function onAfterInitialise(AfterInitialiseEvent $event): void + { // Import actionlog plugin group so that these plugins will be triggered for events - PluginHelper::importPlugin('actionlog'); + PluginHelper::importPlugin('actionlog', null, true, $event->getApplication()->getDispatcher()); } /** * Adds additional fields to the user editing form for logs e-mail notifications * - * @param Form $form The form to be altered. - * @param mixed $data The associated data for the form. + * @param Model\PrepareFormEvent $event The event instance. * - * @return boolean + * @return void * * @since 3.9.0 * * @throws \Exception */ - public function onContentPrepareForm(Form $form, $data) + public function onContentPrepareForm(Model\PrepareFormEvent $event): void { + $form = $event->getForm(); + $data = $event->getData(); $formName = $form->getName(); $allowedFormNames = [ @@ -75,7 +98,7 @@ public function onContentPrepareForm(Form $form, $data) ]; if (!\in_array($formName, $allowedFormNames, true)) { - return true; + return; } /** @@ -85,7 +108,7 @@ public function onContentPrepareForm(Form $form, $data) $user = $this->getApplication()->getIdentity(); if (!$user || !$user->authorise('core.admin')) { - return true; + return; } // Load plugin language files. @@ -103,7 +126,7 @@ public function onContentPrepareForm(Form $form, $data) } if (empty($data->id) || !$this->getUserFactory()->loadUserById($data->id)->authorise('core.admin')) { - return true; + return; } Form::addFormPath(JPATH_PLUGINS . '/' . $this->_type . '/' . $this->_name . '/forms'); @@ -111,40 +134,41 @@ public function onContentPrepareForm(Form $form, $data) if ((!PluginHelper::isEnabled('actionlog', 'joomla')) && ($this->getApplication()->isClient('administrator'))) { $form->loadFile('information', false); - return true; + return; } if (!PluginHelper::isEnabled('actionlog', 'joomla')) { - return true; + return; } $form->loadFile('actionlogs', false); - - return true; } /** * Runs on content preparation * - * @param string $context The context for the data - * @param object $data An object containing the data for the form. + * @param Model\PrepareDataEvent $event The event instance. * - * @return boolean + * @return void * * @since 3.9.0 */ - public function onContentPrepareData($context, $data) + public function onContentPrepareData(Model\PrepareDataEvent $event): void { + $context = $event->getContext(); + if (!\in_array($context, ['com_users.profile', 'com_users.user'])) { - return true; + return; } + $data = $event->getData(); + if (\is_array($data)) { $data = (object) $data; } if (empty($data->id) || !$this->getUserFactory()->loadUserById($data->id)->authorise('core.admin')) { - return true; + return; } $db = $this->getDatabase(); @@ -159,11 +183,11 @@ public function onContentPrepareData($context, $data) try { $values = $db->setQuery($query)->loadObject(); } catch (ExecutionFailureException $e) { - return false; + return; } if (!$values) { - return true; + return; } // Load plugin language files. @@ -185,28 +209,25 @@ public function onContentPrepareData($context, $data) if (!HTMLHelper::isRegistered('users.actionlogsExcludeSelf')) { HTMLHelper::register('users.actionlogsExcludeSelf', [__CLASS__, 'renderActionlogsExcludeSelf']); } - - return true; } /** * Utility method to act on a user after it has been saved. * - * @param array $user Holds the new user data. - * @param boolean $isNew True if a new user is stored. - * @param boolean $success True if user was successfully stored in the database. - * @param string $msg Message. + * @param User\AfterSaveEvent $event The event instance. * * @return void * * @since 3.9.0 */ - public function onUserAfterSave($user, $isNew, $success, $msg): void + public function onUserAfterSave(User\AfterSaveEvent $event): void { - if (!$success) { + if (!$event->getSavingResult()) { return; } + $user = $event->getUser(); + // Clear access rights in case user groups were changed. $userObject = $this->getUserFactory()->loadUserById($user['id']); $userObject->clearAccessRights(); @@ -292,20 +313,19 @@ public function onUserAfterSave($user, $isNew, $success, $msg): void * * Method is called after user data is deleted from the database * - * @param array $user Holds the user data - * @param boolean $success True if user was successfully stored in the database - * @param string $msg Message + * @param User\AfterDeleteEvent $event The event instance. * * @return void * * @since 3.9.0 */ - public function onUserAfterDelete($user, $success, $msg): void + public function onUserAfterDelete(User\AfterDeleteEvent $event): void { - if (!$success) { + if (!$event->getDeletingResult()) { return; } + $user = $event->getUser(); $db = $this->getDatabase(); $userid = (int) $user['id']; @@ -375,19 +395,20 @@ public static function renderActionlogsExtensions($extensions) } /** - * On Saving extensions logging method + * On Saving extensions logging method. * Method is called when an extension is being saved * - * @param string $context The extension - * @param \Joomla\CMS\Table\Table $table DataBase Table object - * @param boolean $isNew If the extension is new or not + * @param Model\AfterSaveEvent $event The event instance. * * @return void * * @since 5.1.0 */ - public function onExtensionAfterSave($context, $table, $isNew): void + public function onExtensionAfterSave(Model\AfterSaveEvent $event): void { + $context = $event->getContext(); + $table = $event->getItem(); + if ($context !== 'com_config.component' || $table->name !== 'com_actionlogs') { return; } diff --git a/plugins/system/fields/src/Extension/Fields.php b/plugins/system/fields/src/Extension/Fields.php index d8d31434f4e5b..8926dc06b9b15 100644 --- a/plugins/system/fields/src/Extension/Fields.php +++ b/plugins/system/fields/src/Extension/Fields.php @@ -12,10 +12,12 @@ use Joomla\CMS\Event\Content; use Joomla\CMS\Event\Model; +use Joomla\CMS\Event\User; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\User\UserFactoryAwareTrait; use Joomla\Component\Fields\Administrator\Helper\FieldsHelper; +use Joomla\Event\SubscriberInterface; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects @@ -27,10 +29,33 @@ * * @since 3.7 */ -final class Fields extends CMSPlugin +final class Fields extends CMSPlugin implements SubscriberInterface { use UserFactoryAwareTrait; + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onContentNormaliseRequestData' => 'onContentNormaliseRequestData', + 'onContentPrepare' => 'onContentPrepare', + 'onContentPrepareForm' => 'onContentPrepareForm', + 'onContentAfterSave' => 'onContentAfterSave', + 'onContentAfterDelete' => 'onContentAfterDelete', + 'onUserAfterSave' => 'onUserAfterSave', + 'onUserAfterDelete' => 'onUserAfterDelete', + 'onContentAfterTitle' => 'onContentAfterTitle', + 'onContentBeforeDisplay' => 'onContentBeforeDisplay', + 'onContentAfterDisplay' => 'onContentAfterDisplay', + ]; + } + /** * Normalizes the request data. * @@ -80,17 +105,18 @@ public function onContentNormaliseRequestData(Model\NormaliseRequestDataEvent $e /** * The save event. * - * @param string $context The context - * @param \Joomla\CMS\Table\Table $item The table - * @param boolean $isNew Is new item - * @param array $data The validated data + * @param Model\AfterSaveEvent $event The event object * * @return void * * @since 3.7.0 */ - public function onContentAfterSave($context, $item, $isNew, $data = []): void + public function onContentAfterSave(Model\AfterSaveEvent $event): void { + $context = $event->getContext(); + $item = $event->getItem(); + $data = $event->getData(); + // Check if data is an array and the item has an id if (!\is_array($data) || empty($item->id) || empty($data['com_fields'])) { return; @@ -155,17 +181,17 @@ public function onContentAfterSave($context, $item, $isNew, $data = []): void /** * The save event. * - * @param array $userData The date - * @param boolean $isNew Is new - * @param boolean $success Is success - * @param string $msg The message + * @param User\AfterSaveEvent $event The event object * * @return void * * @since 3.7.0 */ - public function onUserAfterSave($userData, $isNew, $success, $msg): void + public function onUserAfterSave(User\AfterSaveEvent $event): void { + $userData = $event->getUser(); + $success = $event->getSavingResult(); + // It is not possible to manipulate the user during save events // Check if data is valid or we are in a recursion if (!$userData['id'] || !$success) { @@ -182,21 +208,29 @@ public function onUserAfterSave($userData, $isNew, $success, $msg): void } // Trigger the events with a real user - $this->onContentAfterSave('com_users.user', $user, false, $userData); + $contentEvent = new Model\AfterSaveEvent('onContentAfterSave', [ + 'context' => 'com_users.user', + 'subject' => $user, + 'isNew' => false, + 'data' => $userData, + ]); + $this->onContentAfterSave($contentEvent); } /** * The delete event. * - * @param string $context The context - * @param \stdClass $item The item + * @param Model\AfterDeleteEvent $event The event object * * @return void * * @since 3.7.0 */ - public function onContentAfterDelete($context, $item): void + public function onContentAfterDelete(Model\AfterDeleteEvent $event): void { + $context = $event->getContext(); + $item = $event->getItem(); + // Set correct context for category if ($context === 'com_categories.category') { $context = $item->extension . '.categories'; @@ -219,20 +253,23 @@ public function onContentAfterDelete($context, $item): void /** * The user delete event. * - * @param array $user The context - * @param boolean $success Is success - * @param string $msg The message + * @param User\AfterDeleteEvent $event The event object * * @return void * * @since 3.7.0 */ - public function onUserAfterDelete($user, $success, $msg): void + public function onUserAfterDelete(User\AfterDeleteEvent $event): void { + $user = $event->getUser(); $item = new \stdClass(); $item->id = $user['id']; - $this->onContentAfterDelete('com_users.user', $item); + $contentEvent = new Model\AfterDeleteEvent('onContentAfterDelete', [ + 'context' => 'com_users.user', + 'subject' => $item, + ]); + $this->onContentAfterDelete($contentEvent); } /** diff --git a/plugins/system/highlight/services/provider.php b/plugins/system/highlight/services/provider.php index a13d7073782ac..ac91d9227ee46 100644 --- a/plugins/system/highlight/services/provider.php +++ b/plugins/system/highlight/services/provider.php @@ -11,7 +11,6 @@ \defined('_JEXEC') or die; use Joomla\CMS\Extension\PluginInterface; -use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; @@ -37,7 +36,6 @@ function (Container $container) { $container->get(DispatcherInterface::class), (array) PluginHelper::getPlugin('system', 'highlight') ); - $plugin->setApplication(Factory::getApplication()); return $plugin; } diff --git a/plugins/system/highlight/src/Extension/Highlight.php b/plugins/system/highlight/src/Extension/Highlight.php index 52fcb230d6599..4b515d55e7400 100644 --- a/plugins/system/highlight/src/Extension/Highlight.php +++ b/plugins/system/highlight/src/Extension/Highlight.php @@ -11,10 +11,12 @@ namespace Joomla\Plugin\System\Highlight\Extension; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Application\AfterDispatchEvent; +use Joomla\CMS\Event\Finder\ResultEvent; use Joomla\CMS\Filter\InputFilter; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Uri\Uri; -use Joomla\Component\Finder\Administrator\Indexer\Result; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -25,8 +27,23 @@ * * @since 2.5 */ -final class Highlight extends CMSPlugin +final class Highlight extends CMSPlugin implements SubscriberInterface { + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onAfterDispatch' => 'onAfterDispatch', + 'onFinderResult' => 'onFinderResult', + ]; + } + /** * Method to catch the onAfterDispatch event. * @@ -34,19 +51,21 @@ final class Highlight extends CMSPlugin * The highlighting is done with JavaScript so we just * need to check a few parameters and the JHtml behavior will do the rest. * + * @param AfterDispatchEvent $event The event object + * * @return void * * @since 2.5 */ - public function onAfterDispatch() + public function onAfterDispatch(AfterDispatchEvent $event): void { // Check that we are in the site application. - if (!$this->getApplication()->isClient('site')) { + if (!$event->getApplication()->isClient('site')) { return; } // Set the variables. - $input = $this->getApplication()->getInput(); + $input = $event->getApplication()->getInput(); $extension = $input->get('option', '', 'cmd'); // Check if the highlighter is enabled. @@ -55,7 +74,7 @@ public function onAfterDispatch() } // Check if the highlighter should be activated in this environment. - if ($input->get('tmpl', '', 'cmd') === 'component' || $this->getApplication()->getDocument()->getType() !== 'html') { + if ($input->get('tmpl', '', 'cmd') === 'component' || $event->getApplication()->getDocument()->getType() !== 'html') { return; } @@ -78,7 +97,7 @@ public function onAfterDispatch() } /** @var \Joomla\CMS\Document\HtmlDocument $doc */ - $doc = $this->getApplication()->getDocument(); + $doc = $event->getApplication()->getDocument(); // Activate the highlighter. if (!empty($cleanTerms)) { @@ -101,14 +120,13 @@ public function onAfterDispatch() /** * Method to catch the onFinderResult event. * - * @param Result $item The search result - * @param object $query The search query of this result + * @param ResultEvent $event The event object * * @return void * * @since 4.0.0 */ - public function onFinderResult($item, $query) + public function onFinderResult(ResultEvent $event): void { static $params; @@ -116,6 +134,9 @@ public function onFinderResult($item, $query) $params = ComponentHelper::getParams('com_finder'); } + $item = $event->getItem(); + $query = $event->getQuery(); + // Get the route with highlighting information. if ( !empty($query->highlight) diff --git a/plugins/system/jooa11y/src/Extension/Jooa11y.php b/plugins/system/jooa11y/src/Extension/Jooa11y.php index 86ba87ec91ae8..ae6a969850ff3 100644 --- a/plugins/system/jooa11y/src/Extension/Jooa11y.php +++ b/plugins/system/jooa11y/src/Extension/Jooa11y.php @@ -10,6 +10,8 @@ namespace Joomla\Plugin\System\Jooa11y\Extension; +use Joomla\CMS\Event\Application\AfterRouteEvent; +use Joomla\CMS\Event\Application\BeforeCompileHeadEvent; use Joomla\CMS\Event\PageCache\SetCachingEvent; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\CMSPlugin; @@ -81,14 +83,20 @@ private function isAuthorisedDisplayChecker(): bool /** * Init the checker. * + * @param AfterRouteEvent $event The event object + * * @return void * * @since 4.1.0 */ - public function initJooa11y() + public function initJooa11y(AfterRouteEvent $event) { + if (!$event->getApplication()->isClient('site')) { + return; + } + // Check if we are in a preview modal or the plugin has enforced loading - $showJooa11y = $this->getApplication() + $showJooa11y = $event->getApplication() ->getInput() ->get('jooa11y', $this->params->get('showAlways', 0)); @@ -112,17 +120,19 @@ static function (SetCachingEvent $event) { /** * Add the checker. * + * @param BeforeCompileHeadEvent $event The event object + * * @return void * * @since __DEPLOY_VERSION__ */ - public function addJooa11y() + public function addJooa11y(BeforeCompileHeadEvent $event) { // Load translations $this->loadLanguage(); // Detect the current active language - $getLang = $this->getApplication() + $getLang = $event->getApplication() ->getLanguage() ->getTag(); @@ -177,7 +187,7 @@ public function addJooa11y() // Get the document object /** @var \Joomla\CMS\Document\HtmlDocument $document */ - $document = $this->getApplication()->getDocument(); + $document = $event->getDocument(); // Get plugin options from xml $getOptions = [ diff --git a/plugins/system/languagecode/services/provider.php b/plugins/system/languagecode/services/provider.php index 4c9dc596d73a6..a021326433d89 100644 --- a/plugins/system/languagecode/services/provider.php +++ b/plugins/system/languagecode/services/provider.php @@ -11,7 +11,6 @@ \defined('_JEXEC') or die; use Joomla\CMS\Extension\PluginInterface; -use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; @@ -37,7 +36,6 @@ function (Container $container) { $container->get(DispatcherInterface::class), (array) PluginHelper::getPlugin('system', 'languagecode') ); - $plugin->setApplication(Factory::getApplication()); return $plugin; } diff --git a/plugins/system/languagecode/src/Extension/LanguageCode.php b/plugins/system/languagecode/src/Extension/LanguageCode.php index c5a6560f48063..e3ecf6a69ec75 100644 --- a/plugins/system/languagecode/src/Extension/LanguageCode.php +++ b/plugins/system/languagecode/src/Extension/LanguageCode.php @@ -10,10 +10,12 @@ namespace Joomla\Plugin\System\LanguageCode\Extension; -use Joomla\CMS\Form\Form; +use Joomla\CMS\Event\Application\AfterRenderEvent; +use Joomla\CMS\Event\Model\PrepareFormEvent; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Plugin\CMSPlugin; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -24,24 +26,43 @@ * * @since 2.5 */ -final class LanguageCode extends CMSPlugin +final class LanguageCode extends CMSPlugin implements SubscriberInterface { + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onAfterRender' => 'onAfterRender', + 'onContentPrepareForm' => 'onContentPrepareForm', + ]; + } + /** * Plugin that changes the language code used in the tag. * + * @param AfterRenderEvent $event The event instance. + * * @return void * * @since 2.5 */ - public function onAfterRender() + public function onAfterRender(AfterRenderEvent $event): void { + $app = $event->getApplication(); + // Use this plugin only in site application. - if ($this->getApplication()->isClient('site')) { + if ($app->isClient('site')) { // Get the response body. - $body = $this->getApplication()->getBody(); + $body = $app->getBody(); // Get the current language code. - $code = $this->getApplication()->getDocument()->getLanguage(); + $code = $app->getDocument()->getLanguage(); // Get the new code. $new_code = $this->params->get($code); @@ -97,25 +118,26 @@ public function onAfterRender() } } - $this->getApplication()->setBody(preg_replace($patterns, $replace, $body)); + $app->setBody(preg_replace($patterns, $replace, $body)); } } /** * Prepare form. * - * @param Form $form The form to be altered. - * @param mixed $data The associated data for the form. + * @param PrepareFormEvent $event The event object * - * @return boolean + * @return void * * @since 2.5 */ - public function onContentPrepareForm(Form $form, $data) + public function onContentPrepareForm(PrepareFormEvent $event): void { + $form = $event->getForm(); + // Check we are manipulating the languagecode plugin. if ($form->getName() !== 'com_plugins.plugin' || !$form->getField('languagecodeplugin', 'params')) { - return true; + return; } // Get site languages. @@ -145,7 +167,5 @@ public function onContentPrepareForm(Form $form, $data) '); } } - - return true; } } diff --git a/plugins/system/log/services/provider.php b/plugins/system/log/services/provider.php index d355f0484da14..669bd216596b4 100644 --- a/plugins/system/log/services/provider.php +++ b/plugins/system/log/services/provider.php @@ -11,7 +11,6 @@ \defined('_JEXEC') or die; use Joomla\CMS\Extension\PluginInterface; -use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; @@ -37,7 +36,6 @@ function (Container $container) { $container->get(DispatcherInterface::class), (array) PluginHelper::getPlugin('system', 'log') ); - $plugin->setApplication(Factory::getApplication()); return $plugin; } diff --git a/plugins/system/log/src/Extension/Log.php b/plugins/system/log/src/Extension/Log.php index b0d16a75a6ed6..748ca8d51bb09 100644 --- a/plugins/system/log/src/Extension/Log.php +++ b/plugins/system/log/src/Extension/Log.php @@ -11,8 +11,10 @@ namespace Joomla\Plugin\System\Log\Extension; use Joomla\CMS\Authentication\Authentication; +use Joomla\CMS\Event\User\LoginFailureEvent; use Joomla\CMS\Log\Log as Logger; use Joomla\CMS\Plugin\CMSPlugin; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -23,19 +25,34 @@ * * @since 1.5 */ -final class Log extends CMSPlugin +final class Log extends CMSPlugin implements SubscriberInterface { + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onUserLoginFailure' => 'onUserLoginFailure', + ]; + } + /** * Called if user fails to be logged in. * - * @param array $response Array of response data. + * @param LoginFailureEvent $event The event instance. * * @return void * * @since 1.5 */ - public function onUserLoginFailure($response) + public function onUserLoginFailure(LoginFailureEvent $event): void { + $response = $event->getAuthenticationResponse(); $errorlog = []; switch ($response['status']) { diff --git a/plugins/system/logout/src/Extension/Logout.php b/plugins/system/logout/src/Extension/Logout.php index 10751fecefedd..046b5288c41ed 100644 --- a/plugins/system/logout/src/Extension/Logout.php +++ b/plugins/system/logout/src/Extension/Logout.php @@ -12,8 +12,10 @@ use Joomla\CMS\Application\ApplicationHelper; use Joomla\CMS\Application\CMSApplicationInterface; +use Joomla\CMS\Event\User\LogoutEvent; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\Event\DispatcherInterface; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -24,7 +26,7 @@ * * @since 1.6 */ -final class Logout extends CMSPlugin +final class Logout extends CMSPlugin implements SubscriberInterface { /** * @param DispatcherInterface $dispatcher The object to observe -- event dispatcher. @@ -58,17 +60,30 @@ public function __construct(DispatcherInterface $dispatcher, array $config, CMSA } } + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onUserLogout' => 'onUserLogout', + ]; + } + /** * Method to handle any logout logic and report back to the subject. * - * @param array $user Holds the user data. - * @param array $options Array holding options (client, ...). + * @param LogoutEvent $event The event instance. * - * @return boolean Always returns true. + * @return void * * @since 1.6 */ - public function onUserLogout($user, $options = []) + public function onUserLogout(LogoutEvent $event): void { if ($this->getApplication()->isClient('site')) { // Create the cookie. @@ -82,7 +97,5 @@ public function onUserLogout($user, $options = []) true ); } - - return true; } } diff --git a/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php b/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php index 5fe442701b753..af11e84e8f031 100644 --- a/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php +++ b/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php @@ -10,9 +10,11 @@ namespace Joomla\Plugin\System\PrivacyConsent\Extension; +use Joomla\CMS\Event\Application\AfterRouteEvent; +use Joomla\CMS\Event\Model; use Joomla\CMS\Event\Privacy\CheckPrivacyPolicyPublishedEvent; +use Joomla\CMS\Event\User; use Joomla\CMS\Factory; -use Joomla\CMS\Form\Form; use Joomla\CMS\Form\FormHelper; use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Text; @@ -21,6 +23,7 @@ use Joomla\Component\Actionlogs\Administrator\Model\ActionlogModel; use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; +use Joomla\Event\SubscriberInterface; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects @@ -32,27 +35,48 @@ * * @since 3.9.0 */ -final class PrivacyConsent extends CMSPlugin +final class PrivacyConsent 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 [ + 'onContentPrepareForm' => 'onContentPrepareForm', + 'onUserBeforeSave' => 'onUserBeforeSave', + 'onUserAfterSave' => 'onUserAfterSave', + 'onUserAfterDelete' => 'onUserAfterDelete', + 'onAfterRoute' => 'onAfterRoute', + 'onPrivacyCheckPrivacyPolicyPublished' => 'onPrivacyCheckPrivacyPolicyPublished', + ]; + } + /** * Adds additional fields to the user editing form * - * @param Form $form The form to be altered. - * @param mixed $data The associated data for the form. + * @param Model\PrepareFormEvent $event The event instance. * - * @return boolean + * @return void * * @since 3.9.0 */ - public function onContentPrepareForm(Form $form, $data) + public function onContentPrepareForm(Model\PrepareFormEvent $event): void { + $form = $event->getForm(); + $data = $event->getData(); + // Check we are manipulating a valid form - we only display this on user registration form and user profile form. $name = $form->getName(); if (!\in_array($name, ['com_users.profile', 'com_users.registration'])) { - return true; + return; } // Load plugin language files @@ -63,7 +87,7 @@ public function onContentPrepareForm(Form $form, $data) $userId = $data->id ?? 0; if ($userId > 0 && $this->isUserConsented($userId)) { - return true; + return; } } @@ -79,29 +103,26 @@ public function onContentPrepareForm(Form $form, $data) // Push the privacy article ID into the privacy field. $form->setFieldAttribute('privacy', $privacyType, $privacyId, 'privacyconsent'); $form->setFieldAttribute('privacy', 'note', $privacynote, 'privacyconsent'); - - return true; } /** * Method is called before user data is stored in the database * - * @param array $user Holds the old user data. - * @param boolean $isNew True if a new user is stored. - * @param array $data Holds the new user data. + * @param User\BeforeSaveEvent $event The event instance. * - * @return boolean + * @return void * * @since 3.9.0 * @throws \InvalidArgumentException on missing required data. */ - public function onUserBeforeSave($user, $isNew, $data) + public function onUserBeforeSave(User\BeforeSaveEvent $event): void { // // Only check for front-end user creation/update profile if ($this->getApplication()->isClient('administrator')) { - return true; + return; } + $user = $event->getUser(); $userId = ArrayHelper::getValue($user, 'id', 0, 'int'); // Load plugin language files @@ -109,7 +130,7 @@ public function onUserBeforeSave($user, $isNew, $data) // User already consented before, no need to check it further if ($userId > 0 && $this->isUserConsented($userId)) { - return true; + return; } // Check that the privacy is checked if required ie only in registration from frontend. @@ -124,23 +145,18 @@ public function onUserBeforeSave($user, $isNew, $data) ) { throw new \InvalidArgumentException($this->getApplication()->getLanguage()->_('PLG_SYSTEM_PRIVACYCONSENT_FIELD_ERROR')); } - - return true; } /** * Saves user privacy confirmation * - * @param array $data entered user data - * @param boolean $isNew true if this is a new user - * @param boolean $result true if saving the user worked - * @param string $error error message + * @param User\AfterSaveEvent $event The event instance. * * @return void * * @since 3.9.0 */ - public function onUserAfterSave($data, $isNew, $result, $error): void + public function onUserAfterSave(User\AfterSaveEvent $event): void { // Only create an entry on front-end user creation/update profile if ($this->getApplication()->isClient('administrator')) { @@ -148,6 +164,7 @@ public function onUserAfterSave($data, $isNew, $result, $error): void } // Get the user's ID + $data = $event->getUser(); $userId = ArrayHelper::getValue($data, 'id', 0, 'int'); // If user already consented before, no need to check it further @@ -210,20 +227,19 @@ public function onUserAfterSave($data, $isNew, $result, $error): void * * Method is called after user data is deleted from the database * - * @param array $user Holds the user data - * @param boolean $success True if user was successfully stored in the database - * @param string $msg Message + * @param User\AfterDeleteEvent $event The event instance. * * @return void * * @since 3.9.0 */ - public function onUserAfterDelete($user, $success, $msg): void + public function onUserAfterDelete(User\AfterDeleteEvent $event): void { - if (!$success) { + if (!$event->getDeletingResult()) { return; } + $user = $event->getUser(); $userId = ArrayHelper::getValue($user, 'id', 0, 'int'); if ($userId) { @@ -241,18 +257,21 @@ public function onUserAfterDelete($user, $success, $msg): void * If logged in users haven't agreed to privacy consent, redirect them to profile edit page, ask them to agree to * privacy consent before allowing access to any other pages * + * @param AfterRouteEvent $event The event instance. + * * @return void * * @since 3.9.0 */ - public function onAfterRoute() + public function onAfterRoute(AfterRouteEvent $event): void { // Run this in frontend only if (!$this->getApplication()->isClient('site')) { return; } - $userId = $this->getApplication()->getIdentity()->id; + $app = $this->getApplication(); + $userId = $app->getIdentity()->id; // Check to see whether user already consented, if not, redirect to user profile page if ($userId > 0) { @@ -264,7 +283,7 @@ public function onAfterRoute() return; } - $input = $this->getApplication()->getInput(); + $input = $app->getInput(); $option = $input->getCmd('option'); $task = $input->get('task', ''); $view = $input->getString('view', ''); @@ -297,9 +316,9 @@ public function onAfterRoute() } // Redirect to com_users profile edit - $this->getApplication()->enqueueMessage($this->getRedirectMessage(), 'notice'); + $app->enqueueMessage($this->getRedirectMessage(), 'notice'); $link = 'index.php?option=com_users&view=profile&layout=edit'; - $this->getApplication()->redirect(Route::_($link, false)); + $app->redirect(Route::_($link, false)); } } diff --git a/plugins/system/remember/src/Extension/Remember.php b/plugins/system/remember/src/Extension/Remember.php index 3956f750b9104..e7c92409bd20e 100644 --- a/plugins/system/remember/src/Extension/Remember.php +++ b/plugins/system/remember/src/Extension/Remember.php @@ -10,11 +10,15 @@ namespace Joomla\Plugin\System\Remember\Extension; +use Joomla\CMS\Event\Application\AfterInitialiseEvent; +use Joomla\CMS\Event\User\BeforeSaveEvent; +use Joomla\CMS\Event\User\LogoutEvent; use Joomla\CMS\Log\Log; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\User\UserHelper; use Joomla\Database\DatabaseAwareTrait; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -25,34 +29,54 @@ * * @since 1.5 */ -final class Remember extends CMSPlugin +final class Remember 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 [ + 'onAfterInitialise' => 'onAfterInitialise', + 'onUserLogout' => 'onUserLogout', + 'onUserBeforeSave' => 'onUserBeforeSave', + ]; + } + /** * Remember me method to run onAfterInitialise * Only purpose is to initialise the login authentication process if a cookie is present * + * @param AfterInitialiseEvent $event The event instance. + * * @return void * * @since 1.5 * * @throws \InvalidArgumentException */ - public function onAfterInitialise() + public function onAfterInitialise(AfterInitialiseEvent $event): void { // No remember me for admin. if (!$this->getApplication()->isClient('site')) { return; } + $app = $this->getApplication(); + // Check for a cookie if user is not logged in - if ($this->getApplication()->getIdentity()->guest) { + if ($app->getIdentity()->guest) { $cookieName = 'joomla_remember_me_' . UserHelper::getShortHashedUserAgent(); // Check for the cookie - if ($this->getApplication()->getInput()->cookie->get($cookieName)) { - $this->getApplication()->login(['username' => ''], ['silent' => true]); + if ($app->getInput()->cookie->get($cookieName)) { + $app->login(['username' => ''], ['silent' => true]); } } } @@ -60,16 +84,15 @@ public function onAfterInitialise() /** * Imports the authentication plugin on user logout to make sure that the cookie is destroyed. * - * @param array $user Holds the user data. - * @param array $options Array holding options (remember, autoregister, group). + * @param LogoutEvent $event The event instance. * - * @return boolean + * @return void */ - public function onUserLogout($user, $options) + public function onUserLogout(LogoutEvent $event): void { // No remember me for admin if (!$this->getApplication()->isClient('site')) { - return true; + return; } $cookieName = 'joomla_remember_me_' . UserHelper::getShortHashedUserAgent(); @@ -79,32 +102,32 @@ public function onUserLogout($user, $options) // Make sure authentication group is loaded to process onUserAfterLogout event PluginHelper::importPlugin('authentication'); } - - return true; } /** * Method is called before user data is stored in the database * Invalidate all existing remember-me cookies after a password change * - * @param array $user Holds the old user data. - * @param boolean $isnew True if a new user is stored. - * @param array $data Holds the new user data. + * @param BeforeSaveEvent $event The event instance. * * @return boolean * * @since 3.8.6 */ - public function onUserBeforeSave($user, $isnew, $data) + public function onUserBeforeSave(BeforeSaveEvent $event): void { + $user = $event->getUser(); + $isnew = $event->getIsNew(); + $data = $event->getData(); + // Irrelevant on new users if ($isnew) { - return true; + return; } // Irrelevant, because password was not changed by user if (empty($data['password_clear'])) { - return true; + return; } // But now, we need to do something - Delete all tokens for this user! @@ -124,7 +147,5 @@ public function onUserBeforeSave($user, $isnew, $data) 'security' ); } - - return true; } } diff --git a/plugins/system/skipto/services/provider.php b/plugins/system/skipto/services/provider.php index 274dcebf053e4..84efa5e700f97 100644 --- a/plugins/system/skipto/services/provider.php +++ b/plugins/system/skipto/services/provider.php @@ -11,7 +11,6 @@ \defined('_JEXEC') or die; use Joomla\CMS\Extension\PluginInterface; -use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; @@ -37,7 +36,6 @@ function (Container $container) { $container->get(DispatcherInterface::class), (array) PluginHelper::getPlugin('system', 'skipto') ); - $plugin->setApplication(Factory::getApplication()); return $plugin; } diff --git a/plugins/system/skipto/src/Extension/Skipto.php b/plugins/system/skipto/src/Extension/Skipto.php index a36f038f08458..9d1d1ecfb994d 100644 --- a/plugins/system/skipto/src/Extension/Skipto.php +++ b/plugins/system/skipto/src/Extension/Skipto.php @@ -10,7 +10,9 @@ namespace Joomla\Plugin\System\Skipto\Extension; +use Joomla\CMS\Event\Application\AfterDispatchEvent; use Joomla\CMS\Plugin\CMSPlugin; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -21,32 +23,49 @@ * * @since 4.0.0 */ -final class Skipto extends CMSPlugin +final class Skipto extends CMSPlugin implements SubscriberInterface { + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onAfterDispatch' => 'onAfterDispatch', + ]; + } + /** * Add the skipto navigation menu. * + * @param AfterDispatchEvent $event The event instance. + * * @return void * * @since 4.0.0 */ - public function onAfterDispatch() + public function onAfterDispatch(AfterDispatchEvent $event): void { $section = $this->params->get('section', 'administrator'); + $app = $event->getApplication(); - if ($section !== 'both' && $this->getApplication()->isClient($section) !== true) { + if ($section !== 'both' && $app->isClient($section) !== true) { return; } // Get the document object. - $document = $this->getApplication()->getDocument(); + $document = $app->getDocument(); if ($document->getType() !== 'html') { return; } // Are we in a modal? - if ($this->getApplication()->getInput()->get('tmpl', '', 'cmd') === 'component') { + if ($app->getInput()->get('tmpl', '', 'cmd') === 'component') { return; } @@ -68,24 +87,24 @@ public function onAfterDispatch() 'displayOption' => 'popup', // Button labels and messages - 'buttonLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_TITLE'), - 'buttonTooltipAccesskey' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_ACCESS_KEY'), + 'buttonLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_TITLE'), + 'buttonTooltipAccesskey' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_ACCESS_KEY'), // Menu labels and messages - 'landmarkGroupLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK'), - 'headingGroupLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_HEADING'), - 'mofnGroupLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_HEADING_MOFN'), - 'headingLevelLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_HEADING_LEVEL'), - 'mainLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_MAIN'), - 'searchLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_SEARCH'), - 'navLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_NAV'), - 'regionLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_REGION'), - 'asideLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_ASIDE'), - 'footerLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_FOOTER'), - 'headerLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_HEADER'), - 'formLabel' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_FORM'), - 'msgNoLandmarksFound' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_NONE'), - 'msgNoHeadingsFound' => $this->getApplication()->getLanguage()->_('PLG_SYSTEM_SKIPTO_HEADING_NONE'), + 'landmarkGroupLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK'), + 'headingGroupLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_HEADING'), + 'mofnGroupLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_HEADING_MOFN'), + 'headingLevelLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_HEADING_LEVEL'), + 'mainLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_MAIN'), + 'searchLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_SEARCH'), + 'navLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_NAV'), + 'regionLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_REGION'), + 'asideLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_ASIDE'), + 'footerLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_FOOTER'), + 'headerLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_HEADER'), + 'formLabel' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_FORM'), + 'msgNoLandmarksFound' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_LANDMARK_NONE'), + 'msgNoHeadingsFound' => $app->getLanguage()->_('PLG_SYSTEM_SKIPTO_HEADING_NONE'), // Selectors for landmark and headings sections 'headings' => 'h1, h2, h3', diff --git a/plugins/system/stats/src/Extension/Stats.php b/plugins/system/stats/src/Extension/Stats.php index 13f6cb16248d7..94cb2b35ee6d9 100644 --- a/plugins/system/stats/src/Extension/Stats.php +++ b/plugins/system/stats/src/Extension/Stats.php @@ -11,12 +11,17 @@ namespace Joomla\Plugin\System\Stats\Extension; use Joomla\CMS\Cache\Cache; +use Joomla\CMS\Event\Application\AfterDispatchEvent; +use Joomla\CMS\Event\Application\AfterInitialiseEvent; +use Joomla\CMS\Event\Plugin\AjaxEvent; +use Joomla\CMS\Event\Plugin\System\Stats\GetStatsDataEvent; use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Layout\FileLayout; use Joomla\CMS\Log\Log; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\User\UserHelper; use Joomla\Database\DatabaseAwareTrait; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -31,7 +36,7 @@ * * @since 3.5 */ -final class Stats extends CMSPlugin +final class Stats extends CMSPlugin implements SubscriberInterface { use DatabaseAwareTrait; @@ -71,14 +76,35 @@ final class Stats extends CMSPlugin */ protected $uniqueId; + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onAfterInitialise' => 'onAfterInitialise', + 'onAfterDispatch' => 'onAfterDispatch', + 'onAjaxSendAlways' => 'onAjaxSendAlways', + 'onAjaxSendNever' => 'onAjaxSendNever', + 'onAjaxSendStats' => 'onAjaxSendStats', + 'onGetStatsData' => 'onGetStatsData', + ]; + } + /** * Listener for the `onAfterInitialise` event * + * @param AfterInitialiseEvent $event The event instance. + * * @return void * * @since 3.5 */ - public function onAfterInitialise() + public function onAfterInitialise(AfterInitialiseEvent $event): void { if (!$this->getApplication()->isClient('administrator') || !$this->isAllowedUser()) { return; @@ -103,11 +129,13 @@ public function onAfterInitialise() /** * Listener for the `onAfterDispatch` event * + * @param AfterDispatchEvent $event The event instance. + * * @return void * * @since 4.0.0 */ - public function onAfterDispatch() + public function onAfterDispatch(AfterDispatchEvent $event): void { if (!$this->getApplication()->isClient('administrator') || !$this->isAllowedUser()) { return; @@ -136,6 +164,8 @@ public function onAfterDispatch() /** * User selected to always send data * + * @param AjaxEvent $event The event instance. + * * @return void * * @since 3.5 @@ -143,7 +173,7 @@ public function onAfterDispatch() * @throws \Exception If user is not allowed. * @throws \RuntimeException If there is an error saving the params or sending the data. */ - public function onAjaxSendAlways() + public function onAjaxSendAlways(AjaxEvent $event): void { if (!$this->isAllowedUser() || !$this->isAjaxRequest()) { throw new \Exception($this->getApplication()->getLanguage()->_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); @@ -155,12 +185,14 @@ public function onAjaxSendAlways() throw new \RuntimeException('Unable to save plugin settings', 500); } - echo json_encode(['sent' => (int) $this->sendStats()]); + $event->updateEventResult(json_encode(['sent' => (int) $this->sendStats()])); } /** * User selected to never send data. * + * @param AjaxEvent $event The event instance. + * * @return void * * @since 3.5 @@ -168,7 +200,7 @@ public function onAjaxSendAlways() * @throws \Exception If user is not allowed. * @throws \RuntimeException If there is an error saving the params. */ - public function onAjaxSendNever() + public function onAjaxSendNever(AjaxEvent $event): void { if (!$this->isAllowedUser() || !$this->isAjaxRequest()) { throw new \Exception($this->getApplication()->getLanguage()->_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); @@ -184,13 +216,15 @@ public function onAjaxSendNever() throw new \RuntimeException('Unable to disable the statistics plugin', 500); } - echo json_encode(['sent' => 0]); + $event->updateEventResult(json_encode(['sent' => 0])); } /** * Send the stats to the server. * On first load | on demand mode it will show a message asking users to select mode. * + * @param AjaxEvent $event The event instance. + * * @return void * * @since 3.5 @@ -198,7 +232,7 @@ public function onAjaxSendNever() * @throws \Exception If user is not allowed. * @throws \RuntimeException If there is an error saving the params, disabling the plugin or sending the data. */ - public function onAjaxSendStats() + public function onAjaxSendStats(AjaxEvent $event): void { if (!$this->isAllowedUser() || !$this->isAjaxRequest()) { throw new \Exception($this->getApplication()->getLanguage()->_('JGLOBAL_AUTH_ACCESS_DENIED'), 403); @@ -211,7 +245,7 @@ public function onAjaxSendStats() 'html' => $this->getRenderer('message')->render($this->getLayoutData()), ]; - echo json_encode($data); + $event->updateEventResult(json_encode($data)); return; } @@ -220,21 +254,21 @@ public function onAjaxSendStats() throw new \RuntimeException('Unable to save plugin settings', 500); } - echo json_encode(['sent' => (int) $this->sendStats()]); + $event->updateEventResult(json_encode(['sent' => (int) $this->sendStats()])); } /** * Get the data through events * - * @param string $context Context where this will be called from + * @param GetStatsDataEvent $event The event instance. * - * @return array + * @return void * * @since 3.5 */ - public function onGetStatsData($context) + public function onGetStatsData(GetStatsDataEvent $event): void { - return $this->getStatsData(); + $event->addResult($this->getStatsData()); } /** diff --git a/plugins/system/stats/src/Field/DataField.php b/plugins/system/stats/src/Field/DataField.php index 76db862824ba9..4709986b7cb16 100644 --- a/plugins/system/stats/src/Field/DataField.php +++ b/plugins/system/stats/src/Field/DataField.php @@ -10,6 +10,7 @@ namespace Joomla\Plugin\System\Stats\Field; +use Joomla\CMS\Event\Plugin\System\Stats\GetStatsDataEvent; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; @@ -53,7 +54,10 @@ protected function getLayoutData() PluginHelper::importPlugin('system', 'stats'); - $result = Factory::getApplication()->triggerEvent('onGetStatsData', ['stats.field.data']); + $result = Factory::getApplication()->getDispatcher()->dispatch( + 'onGetStatsData', + new GetStatsDataEvent('onGetStatsData', ['context' => 'stats.field.data']) + )->getArgument('result', []); $data['statsData'] = $result ? reset($result) : [];