diff --git a/plugins/user/contactcreator/src/Extension/ContactCreator.php b/plugins/user/contactcreator/src/Extension/ContactCreator.php index 87e0ac4e015ad..c45396b7be8a1 100644 --- a/plugins/user/contactcreator/src/Extension/ContactCreator.php +++ b/plugins/user/contactcreator/src/Extension/ContactCreator.php @@ -10,8 +10,10 @@ namespace Joomla\Plugin\User\ContactCreator\Extension; +use Joomla\CMS\Event\User\AfterSaveEvent; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\Component\Contact\Administrator\Table\ContactTable; +use Joomla\Event\SubscriberInterface; use Joomla\String\StringHelper; // phpcs:disable PSR1.Files.SideEffects @@ -25,24 +27,39 @@ * * @since 1.6 */ -final class ContactCreator extends CMSPlugin +final class ContactCreator 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 [ + 'onUserAfterSave' => 'onUserAfterSave', + ]; + } + /** * Utility method to act on a user after it has been saved. * * This method creates a contact for the saved user * - * @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 AfterSaveEvent $event The event instance. * * @return void * * @since 1.6 */ - public function onUserAfterSave($user, $isnew, $success, $msg): void + public function onUserAfterSave(AfterSaveEvent $event): void { + $user = $event->getUser(); + $isnew = $event->getIsNew(); + $success = $event->getSavingResult(); + // If the user wasn't stored we don't resync if (!$success) { return; diff --git a/plugins/user/joomla/src/Extension/Joomla.php b/plugins/user/joomla/src/Extension/Joomla.php index d9dd5cccc01c6..1b6d144bfecf4 100644 --- a/plugins/user/joomla/src/Extension/Joomla.php +++ b/plugins/user/joomla/src/Extension/Joomla.php @@ -11,6 +11,12 @@ namespace Joomla\Plugin\User\Joomla\Extension; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Model\PrepareFormEvent; +use Joomla\CMS\Event\User\AfterDeleteEvent; +use Joomla\CMS\Event\User\AfterLoginEvent; +use Joomla\CMS\Event\User\AfterSaveEvent; +use Joomla\CMS\Event\User\LoginEvent; +use Joomla\CMS\Event\User\LogoutEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\LanguageFactoryInterface; use Joomla\CMS\Log\Log; @@ -23,6 +29,7 @@ use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; +use Joomla\Event\SubscriberInterface; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects @@ -34,23 +41,44 @@ * * @since 1.5 */ -final class Joomla extends CMSPlugin +final class Joomla extends CMSPlugin implements SubscriberInterface { use DatabaseAwareTrait; use UserFactoryAwareTrait; + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onContentPrepareForm' => 'onContentPrepareForm', + 'onUserAfterDelete' => 'onUserAfterDelete', + 'onUserAfterSave' => 'onUserAfterSave', + 'onUserLogin' => 'onUserLogin', + 'onUserLogout' => 'onUserLogout', + 'onUserAfterLogin' => 'onUserAfterLogin', + ]; + } + /** * Set as required the passwords fields when mail to user is set to No * - * @param \Joomla\CMS\Form\Form $form The form to be altered. - * @param mixed $data The associated data for the form. + * @param PrepareFormEvent $event The event instance. * - * @return boolean + * @return void * * @since 4.0.0 */ - public function onContentPrepareForm($form, $data) + public function onContentPrepareForm(PrepareFormEvent $event) { + $form = $event->getForm(); + $data = $event->getData(); + // Check we are manipulating a valid user form before modifying it. $name = $form->getName(); @@ -71,8 +99,6 @@ public function onContentPrepareForm($form, $data) $form->setFieldAttribute('password2', 'required', 'true'); } } - - return true; } /** @@ -80,16 +106,17 @@ public function onContentPrepareForm($form, $data) * * 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 AfterDeleteEvent $event The event instance. * * @return void * * @since 1.6 */ - public function onUserAfterDelete($user, $success, $msg): void + public function onUserAfterDelete(AfterDeleteEvent $event): void { + $user = $event->getUser(); + $success = $event->getDeletingResult(); + if (!$success) { return; } @@ -147,17 +174,17 @@ public function onUserAfterDelete($user, $success, $msg): void * * This method sends a registration email to new users created in the backend. * - * @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 AfterSaveEvent $event The event instance. * * @return void * * @since 1.6 */ - public function onUserAfterSave($user, $isnew, $success, $msg): void + public function onUserAfterSave(AfterSaveEvent $event): void { + $user = $event->getUser(); + $isnew = $event->getIsNew(); + $mail_to_user = $this->params->get('mail_to_user', 1); if (!$isnew || !$mail_to_user) { @@ -249,27 +276,30 @@ public function onUserAfterSave($user, $isnew, $success, $msg): void /** * This method should handle any login logic and report back to the subject * - * @param array $user Holds the user data - * @param array $options Array holding options (remember, autoregister, group) + * @param LoginEvent $event The event instance. * - * @return boolean True on success + * @return void * * @since 1.5 */ - public function onUserLogin($user, $options = []) + public function onUserLogin(LoginEvent $event) { + $user = $event->getAuthenticationResponse(); + $options = $event->getOptions(); $instance = $this->getUser($user, $options); // If getUser returned an error, then pass it back. if ($instance instanceof \Exception) { - return false; + $event->addResult(false); + return; } // If the user is blocked, redirect with an error if ($instance->block == 1) { $this->getApplication()->enqueueMessage($this->getApplication()->getLanguage()->_('JERROR_NOLOGIN_BLOCKED'), 'warning'); + $event->addResult(false); - return false; + return; } // Authorise the user based on the group information @@ -282,8 +312,9 @@ public function onUserLogin($user, $options = []) if (!$result) { $this->getApplication()->enqueueMessage($this->getApplication()->getLanguage()->_('JERROR_LOGIN_DENIED'), 'warning'); + $event->addResult(false); - return false; + return; } // Mark the user as logged in @@ -337,22 +368,22 @@ public function onUserLogin($user, $options = []) true ); } - - return true; } /** * This method should 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 True on success + * @return void * * @since 1.5 */ - public function onUserLogout($user, $options = []) + public function onUserLogout(LogoutEvent $event) { + $user = $event->getParameters(); + $options = $event->getOptions(); + $my = $this->getApplication()->getIdentity(); $session = Factory::getSession(); @@ -360,7 +391,7 @@ public function onUserLogout($user, $options = []) // Make sure we're a valid user first if ($user['id'] === 0 && !$my->get('tmp_user')) { - return true; + return; } $sharedSessions = $this->getApplication()->get('shared_session', '0'); @@ -386,8 +417,6 @@ public function onUserLogout($user, $options = []) if ($this->getApplication()->isClient('site')) { $this->getApplication()->getInput()->cookie->set('joomla_user_state', '', 1, $this->getApplication()->get('cookie_path', '/'), $this->getApplication()->get('cookie_domain', '')); } - - return true; } /** @@ -399,18 +428,18 @@ public function onUserLogout($user, $options = []) * logging in, something which would cause the Captive page to appear in the frontend and redirect you to the public * frontend homepage after successfully passing the Two Step verification process. * - * @param array $options Passed by Joomla. user: a User object; responseType: string, authentication response type. + * @param AfterLoginEvent $event The event instance. * * @return void * @since 4.2.0 */ - public function onUserAfterLogin(array $options): void + public function onUserAfterLogin(AfterLoginEvent $event): void { if (!($this->getApplication()->isClient('administrator')) && !($this->getApplication()->isClient('site'))) { return; } - $this->disableMfaOnSilentLogin($options); + $this->disableMfaOnSilentLogin($event->getOptions()); } /** diff --git a/plugins/user/profile/src/Extension/Profile.php b/plugins/user/profile/src/Extension/Profile.php index 9f68cf0b4defd..75b79cfdc2dae 100644 --- a/plugins/user/profile/src/Extension/Profile.php +++ b/plugins/user/profile/src/Extension/Profile.php @@ -11,7 +11,11 @@ namespace Joomla\Plugin\User\Profile\Extension; use Joomla\CMS\Date\Date; -use Joomla\CMS\Form\Form; +use Joomla\CMS\Event\Model\PrepareDataEvent; +use Joomla\CMS\Event\Model\PrepareFormEvent; +use Joomla\CMS\Event\User\AfterDeleteEvent; +use Joomla\CMS\Event\User\AfterSaveEvent; +use Joomla\CMS\Event\User\BeforeSaveEvent; use Joomla\CMS\Form\FormHelper; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; @@ -19,6 +23,7 @@ use Joomla\CMS\String\PunycodeHelper; use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; +use Joomla\Event\SubscriberInterface; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects @@ -30,7 +35,7 @@ * * @since 1.6 */ -final class Profile extends CMSPlugin +final class Profile extends CMSPlugin implements SubscriberInterface { use DatabaseAwareTrait; @@ -43,21 +48,41 @@ final class Profile extends CMSPlugin */ private $date = ''; + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onContentPrepareData' => 'onContentPrepareData', + 'onContentPrepareForm' => 'onContentPrepareForm', + 'onUserBeforeSave' => 'onUserBeforeSave', + 'onUserAfterSave' => 'onUserAfterSave', + 'onUserAfterDelete' => 'onUserAfterDelete', + ]; + } + /** * Runs on content preparation * - * @param string $context The context for the data - * @param object $data An object containing the data for the form. + * @param PrepareDataEvent $event The event instance. * - * @return boolean + * @return void * * @since 1.6 */ - public function onContentPrepareData($context, $data) + public function onContentPrepareData(PrepareDataEvent $event) { + $context = $event->getContext(); + $data = $event->getData(); + // Check we are manipulating a valid form. if (!\in_array($context, ['com_users.profile', 'com_users.user', 'com_users.registration'])) { - return true; + return; } // Load plugin language files @@ -114,8 +139,6 @@ public function onContentPrepareData($context, $data) HTMLHelper::register('users.dob', [__CLASS__, 'dob']); } } - - return true; } /** @@ -192,20 +215,20 @@ public static function tos($value) /** * 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 PrepareFormEvent $event The event instance. * - * @return boolean + * @return void * * @since 1.6 */ - public function onContentPrepareForm(Form $form, $data) + public function onContentPrepareForm(PrepareFormEvent $event) { + $form = $event->getForm(); // Check we are manipulating a valid form. $name = $form->getName(); if (!\in_array($name, ['com_users.user', 'com_users.profile', 'com_users.registration'])) { - return true; + return; } // Load plugin language files @@ -281,24 +304,22 @@ public function onContentPrepareForm(Form $form, $data) if (!\count($remainingfields)) { $form->removeGroup('profile'); } - - 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 BeforeSaveEvent $event The event instance. * - * @return boolean + * @return void * * @since 3.1 * @throws \InvalidArgumentException on invalid date. */ - public function onUserBeforeSave($user, $isnew, $data) + public function onUserBeforeSave(BeforeSaveEvent $event) { + $data = $event->getData(); + // Load plugin language files $this->loadLanguage(); @@ -327,22 +348,19 @@ public function onUserBeforeSave($user, $isnew, $data) if ($task === 'register' && $tosEnabled && $option === 'com_users' && !$data['profile']['tos']) { throw new \InvalidArgumentException($this->getApplication()->getLanguage()->_('PLG_USER_PROFILE_FIELD_TOS_DESC_SITE')); } - - return true; } /** * Saves user profile data * - * @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 AfterSaveEvent $event The event instance. * * @return void */ - public function onUserAfterSave($data, $isNew, $result, $error): void + public function onUserAfterSave(AfterSaveEvent $event): void { + $data = $event->getUser(); + $result = $event->getSavingResult(); $userId = ArrayHelper::getValue($data, 'id', 0, 'int'); if ($userId && $result && isset($data['profile']) && \count($data['profile'])) { @@ -415,14 +433,15 @@ 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 AfterDeleteEvent $event The event instance. * * @return void */ - public function onUserAfterDelete($user, $success, $msg): void + public function onUserAfterDelete(AfterDeleteEvent $event): void { + $user = $event->getUser(); + $success = $event->getDeletingResult(); + if (!$success) { return; } diff --git a/plugins/user/terms/src/Extension/Terms.php b/plugins/user/terms/src/Extension/Terms.php index 98b7f8ea280ec..0995d2a8093f0 100644 --- a/plugins/user/terms/src/Extension/Terms.php +++ b/plugins/user/terms/src/Extension/Terms.php @@ -10,10 +10,13 @@ namespace Joomla\Plugin\User\Terms\Extension; -use Joomla\CMS\Form\Form; +use Joomla\CMS\Event\Model\PrepareFormEvent; +use Joomla\CMS\Event\User\AfterSaveEvent; +use Joomla\CMS\Event\User\BeforeSaveEvent; use Joomla\CMS\Form\FormHelper; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\Component\Actionlogs\Administrator\Model\ActionlogModel; +use Joomla\Event\SubscriberInterface; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects @@ -25,25 +28,42 @@ * * @since 3.9.0 */ -final class Terms extends CMSPlugin +final class Terms 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 [ + 'onContentPrepareForm' => 'onContentPrepareForm', + 'onUserBeforeSave' => 'onUserBeforeSave', + 'onUserAfterSave' => 'onUserAfterSave', + ]; + } + /** * Adds additional fields to the user registration form * - * @param Form $form The form to be altered. - * @param mixed $data The associated data for the form. + * @param PrepareFormEvent $event The event instance. * - * @return boolean + * @return void * * @since 3.9.0 */ - public function onContentPrepareForm(Form $form, $data) + public function onContentPrepareForm(PrepareFormEvent $event) { + $form = $event->getForm(); + // Check we are manipulating a valid form - we only display this on user registration form. $name = $form->getName(); if (!\in_array($name, ['com_users.registration'])) { - return true; + return; } // Load plugin language files @@ -67,27 +87,27 @@ public function onContentPrepareForm(Form $form, $data) /** * 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 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(BeforeSaveEvent $event) { + $user = $event->getUser(); + // // Only check for front-end user registration if ($this->getApplication()->isClient('administrator')) { - return true; + return; } $userId = ArrayHelper::getValue($user, 'id', 0, 'int'); // User already registered, no need to check it further if ($userId > 0) { - return true; + return; } // Load plugin language files @@ -102,24 +122,23 @@ public function onUserBeforeSave($user, $isNew, $data) if ($option == 'com_users' && \in_array($task, ['registration.register']) && empty($form['terms']['terms'])) { throw new \InvalidArgumentException($this->getApplication()->getLanguage()->_('PLG_USER_TERMS_FIELD_ERROR')); } - - return true; } /** * Saves user profile data * - * @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 AfterSaveEvent $event The event instance. * * @return void * * @since 3.9.0 */ - public function onUserAfterSave($data, $isNew, $result, $error): void + public function onUserAfterSave(AfterSaveEvent $event): void { + $data = $event->getUser(); + $isNew = $event->getIsNew(); + $result = $event->getSavingResult(); + if (!$isNew || !$result) { return; } diff --git a/plugins/user/token/src/Extension/Token.php b/plugins/user/token/src/Extension/Token.php index 3bd8a06dff386..b04a2e8262ea8 100644 --- a/plugins/user/token/src/Extension/Token.php +++ b/plugins/user/token/src/Extension/Token.php @@ -11,12 +11,17 @@ namespace Joomla\Plugin\User\Token\Extension; use Joomla\CMS\Crypt\Crypt; +use Joomla\CMS\Event\Model\PrepareDataEvent; +use Joomla\CMS\Event\Model\PrepareFormEvent; +use Joomla\CMS\Event\User\AfterDeleteEvent; +use Joomla\CMS\Event\User\AfterSaveEvent; use Joomla\CMS\Form\Form; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\User\UserFactoryAwareTrait; use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; +use Joomla\Event\SubscriberInterface; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects @@ -28,7 +33,7 @@ * * @since 3.9.0 */ -final class Token extends CMSPlugin +final class Token extends CMSPlugin implements SubscriberInterface { use DatabaseAwareTrait; use UserFactoryAwareTrait; @@ -60,37 +65,56 @@ final class Token extends CMSPlugin */ private $tokenLength = 32; + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onContentPrepareData' => 'onContentPrepareData', + 'onContentPrepareForm' => 'onContentPrepareForm', + 'onUserAfterSave' => 'onUserAfterSave', + 'onUserAfterDelete' => 'onUserAfterDelete', + ]; + } + /** * Inject the Joomla token management panel's data into the User Profile. * * This method is called whenever Joomla is preparing the data for an XML form for display. * - * @param string $context Form context, passed by Joomla - * @param mixed $data Form data + * @param PrepareDataEvent $event The event instance. * - * @return boolean + * @return void * @since 4.0.0 */ - public function onContentPrepareData(string $context, &$data): bool + public function onContentPrepareData(PrepareDataEvent $event): void { // Only do something if the api-authentication plugin with the same name is published if (!PluginHelper::isEnabled('api-authentication', $this->_name)) { - return true; + return; } + $context = $event->getContext(); + $data = $event->getData(); + // Check we are manipulating a valid form. if (!\in_array($context, $this->allowedContexts)) { - return true; + return; } // $data must be an object if (!\is_object($data)) { - return true; + return; } // We expect the numeric user ID in $data->id if (!isset($data->id)) { - return true; + return; } // Get the user ID @@ -98,11 +122,11 @@ public function onContentPrepareData(string $context, &$data): bool // Make sure we have a positive integer user ID if ($userId <= 0) { - return true; + return; } if (!$this->isInAllowedUserGroup($userId)) { - return true; + return; } // Load plugin language files @@ -162,31 +186,31 @@ public function onContentPrepareData(string $context, &$data): bool $data->{$this->profileKeyPrefix} = $pluginData; } - - return true; } /** * Runs whenever Joomla is preparing a form object. * - * @param Form $form The form to be altered. - * @param mixed $data The associated data for the form. + * @param PrepareFormEvent $event The event instance. * - * @return boolean + * @return void * * @throws \Exception When $form is not a valid form object * @since 4.0.0 */ - public function onContentPrepareForm(Form $form, $data): bool + public function onContentPrepareForm(PrepareFormEvent $event): void { // Only do something if the api-authentication plugin with the same name is published if (!PluginHelper::isEnabled('api-authentication', $this->_name)) { - return true; + return; } + $form = $event->getForm(); + $data = $event->getData(); + // Check we are manipulating a valid form. if (!\in_array($form->getName(), $this->allowedContexts)) { - return true; + return; } // If we are on the save command, no data is passed to $data variable, we need to get it directly from request @@ -204,7 +228,7 @@ public function onContentPrepareForm(Form $form, $data): bool $userId = (\is_object($data) && isset($data->id)) ? $data->id : 0; if (!empty($userId) && !$this->isInAllowedUserGroup($userId)) { - return true; + return; } // Load plugin language files @@ -243,23 +267,22 @@ public function onContentPrepareForm(Form $form, $data): bool if (($form->getName() === 'com_users.profile') && ($this->getApplication()->getInput()->get('layout') !== 'edit')) { $form->removeField('reset', 'joomlatoken'); } - - return true; } /** * Save the Joomla token in the user profile field * - * @param mixed $data The incoming form data - * @param bool $isNew Is this a new user? - * @param bool $result Has Joomla successfully saved the user? - * @param ?string $error Error string + * @param AfterSaveEvent $event The event instance. * * @return void * @since 4.0.0 */ - public function onUserAfterSave($data, bool $isNew, bool $result, ?string $error): void + public function onUserAfterSave(AfterSaveEvent $event): void { + $data = $event->getUser(); + $isNew = $event->getIsNew(); + $result = $event->getSavingResult(); + if (!\is_array($data)) { return; } @@ -371,17 +394,18 @@ public function onUserAfterSave($data, bool $isNew, bool $result, ?string $error * * This event is called after the 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 AfterDeleteEvent $event The event instance. * * @return void * * @throws \Exception * @since 4.0.0 */ - public function onUserAfterDelete(array $user, bool $success, string $msg): void + public function onUserAfterDelete(AfterDeleteEvent $event): void { + $user = $event->getUser(); + $success = $event->getDeletingResult(); + if (!$success) { return; }