diff --git a/administrator/components/com_privacy/src/Model/CapabilitiesModel.php b/administrator/components/com_privacy/src/Model/CapabilitiesModel.php index dc5d8d00f3d85..3da2ba74452d8 100644 --- a/administrator/components/com_privacy/src/Model/CapabilitiesModel.php +++ b/administrator/components/com_privacy/src/Model/CapabilitiesModel.php @@ -11,6 +11,7 @@ namespace Joomla\Component\Privacy\Administrator\Model; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Privacy\CollectCapabilitiesEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\BaseModel; @@ -70,13 +71,18 @@ public function getCapabilities() * This is in addition to plugin groups which are imported before this method is triggered, generally this is the system group. */ - PluginHelper::importPlugin('authentication'); - PluginHelper::importPlugin('captcha'); - PluginHelper::importPlugin('installer'); - PluginHelper::importPlugin('privacy'); - PluginHelper::importPlugin('user'); + $dispatcher = $app->getDispatcher(); - $pluginResults = $app->triggerEvent('onPrivacyCollectAdminCapabilities'); + PluginHelper::importPlugin('authentication', null, true, $dispatcher); + PluginHelper::importPlugin('captcha', null, true, $dispatcher); + PluginHelper::importPlugin('installer', null, true, $dispatcher); + PluginHelper::importPlugin('privacy', null, true, $dispatcher); + PluginHelper::importPlugin('user', null, true, $dispatcher); + + $pluginResults = $dispatcher->dispatch( + 'onPrivacyCollectAdminCapabilities', + new CollectCapabilitiesEvent('onPrivacyCollectAdminCapabilities') + )->getArgument('result', []); // We are going to "cheat" here and include this component's capabilities without using a plugin $extensionCapabilities = [ diff --git a/administrator/components/com_privacy/src/Model/ExportModel.php b/administrator/components/com_privacy/src/Model/ExportModel.php index 6e20ef540bb2a..8ae502d1d713b 100644 --- a/administrator/components/com_privacy/src/Model/ExportModel.php +++ b/administrator/components/com_privacy/src/Model/ExportModel.php @@ -11,6 +11,7 @@ namespace Joomla\Component\Privacy\Administrator\Model; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Privacy\ExportRequestEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Language; use Joomla\CMS\Language\Text; @@ -97,9 +98,14 @@ public function collectDataForExportRequest($id = null) // Log the export $this->logExport($table); - PluginHelper::importPlugin('privacy'); + $dispatcher = $this->getDispatcher(); - $pluginResults = Factory::getApplication()->triggerEvent('onPrivacyExportRequest', [$table, $user]); + PluginHelper::importPlugin('privacy', null, true, $dispatcher); + + $pluginResults = $dispatcher->dispatch('onPrivacyExportRequest', new ExportRequestEvent('onPrivacyExportRequest', [ + 'subject' => $table, + 'user' => $user, + ]))->getArgument('result', []); $domains = []; diff --git a/administrator/components/com_privacy/src/Model/RemoveModel.php b/administrator/components/com_privacy/src/Model/RemoveModel.php index 027277d5e8e77..864e79a840455 100644 --- a/administrator/components/com_privacy/src/Model/RemoveModel.php +++ b/administrator/components/com_privacy/src/Model/RemoveModel.php @@ -11,6 +11,8 @@ namespace Joomla\Component\Privacy\Administrator\Model; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Privacy\CanRemoveDataEvent; +use Joomla\CMS\Event\Privacy\RemoveDataEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\BaseDatabaseModel; @@ -89,12 +91,16 @@ public function removeDataForRequest($id = null) $user = $userId ? $this->getUserFactory()->loadUserById($userId) : null; - $canRemove = true; + $canRemove = true; + $dispatcher = $this->getDispatcher(); - PluginHelper::importPlugin('privacy'); + PluginHelper::importPlugin('privacy', null, true, $dispatcher); /** @var Status[] $pluginResults */ - $pluginResults = Factory::getApplication()->triggerEvent('onPrivacyCanRemoveData', [$table, $user]); + $pluginResults = $dispatcher->dispatch('onPrivacyCanRemoveData', new CanRemoveDataEvent('onPrivacyCanRemoveData', [ + 'subject' => $table, + 'user' => $user, + ]))->getArgument('result', []); foreach ($pluginResults as $status) { if (!$status->canRemove) { @@ -113,7 +119,10 @@ public function removeDataForRequest($id = null) // Log the removal $this->logRemove($table); - Factory::getApplication()->triggerEvent('onPrivacyRemoveData', [$table, $user]); + $dispatcher->dispatch('onPrivacyRemoveData', new RemoveDataEvent('onPrivacyRemoveData', [ + 'subject' => $table, + 'user' => $user, + ])); return true; } diff --git a/administrator/modules/mod_privacy_status/src/Helper/PrivacyStatusHelper.php b/administrator/modules/mod_privacy_status/src/Helper/PrivacyStatusHelper.php index 91def613d9efa..dca3f93a2e706 100644 --- a/administrator/modules/mod_privacy_status/src/Helper/PrivacyStatusHelper.php +++ b/administrator/modules/mod_privacy_status/src/Helper/PrivacyStatusHelper.php @@ -11,9 +11,11 @@ namespace Joomla\Module\PrivacyStatus\Administrator\Helper; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Privacy\CheckPrivacyPolicyPublishedEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\Proxy\ArrayProxy; use Joomla\CMS\Router\Route; // phpcs:disable PSR1.Files.SideEffects @@ -36,7 +38,8 @@ class PrivacyStatusHelper */ public static function getPrivacyPolicyInfo() { - $policy = [ + $dispatcher = Factory::getApplication()->getDispatcher(); + $policy = [ 'published' => false, 'articlePublished' => false, 'editLink' => '', @@ -46,10 +49,15 @@ public static function getPrivacyPolicyInfo() * Prior to 3.9.0 it was common for a plugin such as the User - Profile plugin to define a privacy policy or * terms of service article, therefore we will also import the user plugin group to process this event. */ - PluginHelper::importPlugin('privacy'); - PluginHelper::importPlugin('user'); - - Factory::getApplication()->triggerEvent('onPrivacyCheckPrivacyPolicyPublished', [&$policy]); + PluginHelper::importPlugin('privacy', null, true, $dispatcher); + PluginHelper::importPlugin('user', null, true, $dispatcher); + + $dispatcher->dispatch( + 'onPrivacyCheckPrivacyPolicyPublished', + new CheckPrivacyPolicyPublishedEvent('onPrivacyCheckPrivacyPolicyPublished', [ + 'subject' => new ArrayProxy($policy), + ]) + ); return $policy; } diff --git a/libraries/src/Event/CoreEventAware.php b/libraries/src/Event/CoreEventAware.php index 3cb34e6f9e85b..1d389bf3c9c03 100644 --- a/libraries/src/Event/CoreEventAware.php +++ b/libraries/src/Event/CoreEventAware.php @@ -175,6 +175,12 @@ trait CoreEventAware 'onBuildIndex' => Finder\BuildIndexEvent::class, 'onStartIndex' => Finder\StartIndexEvent::class, 'onFinderGarbageCollection' => Finder\GarbageCollectionEvent::class, + // Privacy + 'onPrivacyCollectAdminCapabilities' => Privacy\CollectCapabilitiesEvent::class, + 'onPrivacyCheckPrivacyPolicyPublished' => Privacy\CheckPrivacyPolicyPublishedEvent::class, + 'onPrivacyExportRequest' => Privacy\ExportRequestEvent::class, + 'onPrivacyCanRemoveData' => Privacy\CanRemoveDataEvent::class, + 'onPrivacyRemoveData' => Privacy\RemoveDataEvent::class, ]; /** diff --git a/libraries/src/Event/Privacy/CanRemoveDataEvent.php b/libraries/src/Event/Privacy/CanRemoveDataEvent.php new file mode 100644 index 0000000000000..3af54a25a0133 --- /dev/null +++ b/libraries/src/Event/Privacy/CanRemoveDataEvent.php @@ -0,0 +1,135 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Event\Privacy; + +use Joomla\CMS\Event\Result\ResultAware; +use Joomla\CMS\Event\Result\ResultAwareInterface; +use Joomla\CMS\User\User; +use Joomla\Component\Privacy\Administrator\Removal\Status; +use Joomla\Component\Privacy\Administrator\Table\RequestTable; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Class for Privacy events. + * Example: + * new CanRemoveDataEvent('onEventName', ['subject' => $requestTable, 'user' => $user]); + * + * @since __DEPLOY_VERSION__ + */ +class CanRemoveDataEvent extends PrivacyEvent implements ResultAwareInterface +{ + use ResultAware; + + /** + * The argument names, in order expected by legacy plugins. + * + * @var array + * + * @since __DEPLOY_VERSION__ + * @deprecated 5.0 will be removed in 6.0 + */ + protected $legacyArgumentsOrder = ['subject', 'user']; + + /** + * Constructor. + * + * @param string $name The event name. + * @param array $arguments The event arguments. + * + * @throws \BadMethodCallException + * + * @since __DEPLOY_VERSION__ + */ + public function __construct($name, array $arguments = []) + { + parent::__construct($name, $arguments); + + if (!\array_key_exists('subject', $this->arguments)) { + throw new \BadMethodCallException("Argument 'subject' of event {$name} is required but has not been provided"); + } + + if (!\array_key_exists('user', $this->arguments)) { + throw new \BadMethodCallException("Argument 'user' of event {$name} is required but has not been provided"); + } + } + + /** + * Setter for the subject argument. + * + * @param RequestTable $value The value to set + * + * @return RequestTable + * + * @since __DEPLOY_VERSION__ + */ + protected function setSubject(RequestTable $value): RequestTable + { + return $value; + } + + /** + * Setter for the user argument. + * + * @param ?User $value The value to set + * + * @return ?User + * + * @since __DEPLOY_VERSION__ + */ + protected function setUser(?User $value): ?User + { + return $value; + } + + /** + * Checks the type of the data being appended to the result argument. + * + * @param mixed $data The data to type check + * + * @return void + * @throws \InvalidArgumentException + * + * @internal + * @since __DEPLOY_VERSION__ + */ + public function typeCheckResult($data): void + { + if (!$data instanceof Status) { + throw new \InvalidArgumentException(sprintf('Event %s only accepts Joomla\Component\Privacy\Administrator\Removal\Status results.', \get_class($this))); + } + } + + /** + * Getter for the request. + * + * @return RequestTable + * + * @since __DEPLOY_VERSION__ + */ + public function getRequest(): RequestTable + { + return $this->arguments['subject']; + } + + /** + * Getter for the user. + * + * @return ?User + * + * @since __DEPLOY_VERSION__ + */ + public function getUser(): ?User + { + return $this->arguments['user']; + } +} diff --git a/libraries/src/Event/Privacy/CheckPrivacyPolicyPublishedEvent.php b/libraries/src/Event/Privacy/CheckPrivacyPolicyPublishedEvent.php new file mode 100644 index 0000000000000..982e132510108 --- /dev/null +++ b/libraries/src/Event/Privacy/CheckPrivacyPolicyPublishedEvent.php @@ -0,0 +1,79 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Event\Privacy; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Class for Privacy events. + * Example: + * new CheckPrivacyPolicyPublishedEvent('onEventName', ['subject' => $policyInfo]); + * + * @since __DEPLOY_VERSION__ + */ +class CheckPrivacyPolicyPublishedEvent extends PrivacyEvent +{ + /** + * The argument names, in order expected by legacy plugins. + * + * @var array + * + * @since __DEPLOY_VERSION__ + * @deprecated 5.0 will be removed in 6.0 + */ + protected $legacyArgumentsOrder = ['subject']; + + /** + * Constructor. + * + * @param string $name The event name. + * @param array $arguments The event arguments. + * + * @throws \BadMethodCallException + * + * @since __DEPLOY_VERSION__ + */ + public function __construct($name, array $arguments = []) + { + parent::__construct($name, $arguments); + + if (!\array_key_exists('subject', $this->arguments)) { + throw new \BadMethodCallException("Argument 'subject' of event {$name} is required but has not been provided"); + } + } + + /** + * Setter for the subject argument. + * + * @param array|\ArrayAccess $value The value to set + * + * @return array|\ArrayAccess + * + * @since __DEPLOY_VERSION__ + */ + protected function setSubject(array|\ArrayAccess $value): array|\ArrayAccess + { + return $value; + } + + /** + * Getter for the policy check. + * + * @return array|\ArrayAccess + * + * @since __DEPLOY_VERSION__ + */ + public function getPolicyInfo(): array|\ArrayAccess + { + return $this->arguments['subject']; + } +} diff --git a/libraries/src/Event/Privacy/CollectCapabilitiesEvent.php b/libraries/src/Event/Privacy/CollectCapabilitiesEvent.php new file mode 100644 index 0000000000000..4421ea6788356 --- /dev/null +++ b/libraries/src/Event/Privacy/CollectCapabilitiesEvent.php @@ -0,0 +1,31 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Event\Privacy; + +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 Privacy events. + * Example: + * new CollectCapabilitiesEvent('onEventName'); + * + * @since __DEPLOY_VERSION__ + */ +class CollectCapabilitiesEvent extends PrivacyEvent implements ResultAwareInterface +{ + use ResultAware; + use ResultTypeArrayAware; +} diff --git a/libraries/src/Event/Privacy/ExportRequestEvent.php b/libraries/src/Event/Privacy/ExportRequestEvent.php new file mode 100644 index 0000000000000..88887a1aeddae --- /dev/null +++ b/libraries/src/Event/Privacy/ExportRequestEvent.php @@ -0,0 +1,147 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Event\Privacy; + +use Joomla\CMS\Event\Result\ResultAware; +use Joomla\CMS\Event\Result\ResultAwareInterface; +use Joomla\CMS\User\User; +use Joomla\Component\Privacy\Administrator\Export\Domain; +use Joomla\Component\Privacy\Administrator\Table\RequestTable; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Class for Privacy events. + * Example: + * new ExportRequestEvent('onEventName', ['subject' => $requestTable, 'user' => $user]); + * + * @since __DEPLOY_VERSION__ + */ +class ExportRequestEvent extends PrivacyEvent implements ResultAwareInterface +{ + use ResultAware; + + /** + * The argument names, in order expected by legacy plugins. + * + * @var array + * + * @since __DEPLOY_VERSION__ + * @deprecated 5.0 will be removed in 6.0 + */ + protected $legacyArgumentsOrder = ['subject', 'user']; + + /** + * Constructor. + * + * @param string $name The event name. + * @param array $arguments The event arguments. + * + * @throws \BadMethodCallException + * + * @since __DEPLOY_VERSION__ + */ + public function __construct($name, array $arguments = []) + { + parent::__construct($name, $arguments); + + if (!\array_key_exists('subject', $this->arguments)) { + throw new \BadMethodCallException("Argument 'subject' of event {$name} is required but has not been provided"); + } + + if (!\array_key_exists('user', $this->arguments)) { + throw new \BadMethodCallException("Argument 'user' of event {$name} is required but has not been provided"); + } + } + + /** + * Setter for the subject argument. + * + * @param RequestTable $value The value to set + * + * @return RequestTable + * + * @since __DEPLOY_VERSION__ + */ + protected function setSubject(RequestTable $value): RequestTable + { + return $value; + } + + /** + * Setter for the user argument. + * + * @param ?User $value The value to set + * + * @return ?User + * + * @since __DEPLOY_VERSION__ + */ + protected function setUser(?User $value): ?User + { + return $value; + } + + /** + * Getter for the request. + * + * @return RequestTable + * + * @since __DEPLOY_VERSION__ + */ + public function getRequest(): RequestTable + { + return $this->arguments['subject']; + } + + /** + * Getter for the user. + * + * @return ?User + * + * @since __DEPLOY_VERSION__ + */ + public function getUser(): ?User + { + return $this->arguments['user']; + } + + /** + * Checks the type of the data being appended to the result argument. + * + * @param mixed $data The data to type check + * + * @return void + * @throws \InvalidArgumentException + * + * @internal + * @since __DEPLOY_VERSION__ + */ + public function typeCheckResult($data): void + { + if (!is_array($data)) { + throw new \InvalidArgumentException(sprintf('Event %s only accepts Array results.', \get_class($this))); + } + + // Validate items in array + foreach ($data as $item) { + if (!$item instanceof Domain) { + throw new \InvalidArgumentException( + sprintf( + 'Event %s only accepts Joomla\Component\Privacy\Administrator\Export\Domain in result array.', + \get_class($this) + ) + ); + } + } + } +} diff --git a/libraries/src/Event/Privacy/PrivacyEvent.php b/libraries/src/Event/Privacy/PrivacyEvent.php new file mode 100644 index 0000000000000..ffef84b775aee --- /dev/null +++ b/libraries/src/Event/Privacy/PrivacyEvent.php @@ -0,0 +1,57 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Event\Privacy; + +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 Privacy events + * + * @since __DEPLOY_VERSION__ + */ +abstract class PrivacyEvent extends AbstractImmutableEvent +{ + use ReshapeArgumentsAware; + + /** + * The argument names, in order expected by legacy plugins. + * + * @var array + * + * @since __DEPLOY_VERSION__ + * @deprecated 5.0 will be removed in 6.0 + */ + protected $legacyArgumentsOrder = []; + + /** + * 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); + } +} diff --git a/libraries/src/Event/Privacy/RemoveDataEvent.php b/libraries/src/Event/Privacy/RemoveDataEvent.php new file mode 100644 index 0000000000000..9476f9e905bec --- /dev/null +++ b/libraries/src/Event/Privacy/RemoveDataEvent.php @@ -0,0 +1,112 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Event\Privacy; + +use Joomla\CMS\User\User; +use Joomla\Component\Privacy\Administrator\Table\RequestTable; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Class for Privacy events. + * Example: + * new RemoveDataEvent('onEventName', ['subject' => $requestTable, 'user' => $user]); + * + * @since __DEPLOY_VERSION__ + */ +class RemoveDataEvent extends PrivacyEvent +{ + /** + * The argument names, in order expected by legacy plugins. + * + * @var array + * + * @since __DEPLOY_VERSION__ + * @deprecated 5.0 will be removed in 6.0 + */ + protected $legacyArgumentsOrder = ['subject', 'user']; + + /** + * Constructor. + * + * @param string $name The event name. + * @param array $arguments The event arguments. + * + * @throws \BadMethodCallException + * + * @since __DEPLOY_VERSION__ + */ + public function __construct($name, array $arguments = []) + { + parent::__construct($name, $arguments); + + if (!\array_key_exists('subject', $this->arguments)) { + throw new \BadMethodCallException("Argument 'subject' of event {$name} is required but has not been provided"); + } + + if (!\array_key_exists('user', $this->arguments)) { + throw new \BadMethodCallException("Argument 'user' of event {$name} is required but has not been provided"); + } + } + + /** + * Setter for the subject argument. + * + * @param RequestTable $value The value to set + * + * @return RequestTable + * + * @since __DEPLOY_VERSION__ + */ + protected function setSubject(RequestTable $value): RequestTable + { + return $value; + } + + /** + * Setter for the user argument. + * + * @param ?User $value The value to set + * + * @return ?User + * + * @since __DEPLOY_VERSION__ + */ + protected function setUser(?User $value): ?User + { + return $value; + } + + /** + * Getter for the request. + * + * @return RequestTable + * + * @since __DEPLOY_VERSION__ + */ + public function getRequest(): RequestTable + { + return $this->arguments['subject']; + } + + /** + * Getter for the user. + * + * @return ?User + * + * @since __DEPLOY_VERSION__ + */ + public function getUser(): ?User + { + return $this->arguments['user']; + } +} diff --git a/plugins/captcha/recaptcha_invisible/src/Extension/InvisibleReCaptcha.php b/plugins/captcha/recaptcha_invisible/src/Extension/InvisibleReCaptcha.php index 59358eb90b72c..e4694822e07f6 100644 --- a/plugins/captcha/recaptcha_invisible/src/Extension/InvisibleReCaptcha.php +++ b/plugins/captcha/recaptcha_invisible/src/Extension/InvisibleReCaptcha.php @@ -11,9 +11,9 @@ namespace Joomla\Plugin\Captcha\InvisibleReCaptcha\Extension; use Joomla\CMS\Event\Captcha\CaptchaSetupEvent; +use Joomla\CMS\Event\Privacy\CollectCapabilitiesEvent; use Joomla\CMS\Language\Text; use Joomla\CMS\Plugin\CMSPlugin; -use Joomla\Event\Event; use Joomla\Event\SubscriberInterface; use Joomla\Plugin\Captcha\InvisibleReCaptcha\Provider\InvisibleReCaptchaProvider; @@ -61,24 +61,18 @@ public function onCaptchaSetup(CaptchaSetupEvent $event) /** * Reports the privacy related capabilities for this plugin to site administrators. * - * @TODO: The event should be changed to what the Privacy component provide. - * - * @param Event $event + * @param CollectCapabilitiesEvent $event * * @since 3.9.0 */ - public function onPrivacyCollectAdminCapabilities(Event $event) + public function onPrivacyCollectAdminCapabilities(CollectCapabilitiesEvent $event) { $this->loadLanguage(); - $result = $event['result'] ?? []; - - $result[] = [ + $event->addResult([ Text::_('PLG_CAPTCHA_RECAPTCHA_INVISIBLE') => [ Text::_('PLG_RECAPTCHA_INVISIBLE_PRIVACY_CAPABILITY_IP_ADDRESS'), ], - ]; - - $event['result'] = $result; + ]); } } diff --git a/plugins/privacy/actionlogs/src/Extension/Actionlogs.php b/plugins/privacy/actionlogs/src/Extension/Actionlogs.php index bd5e8c046a5e6..454f63f1e5727 100644 --- a/plugins/privacy/actionlogs/src/Extension/Actionlogs.php +++ b/plugins/privacy/actionlogs/src/Extension/Actionlogs.php @@ -10,11 +10,11 @@ namespace Joomla\Plugin\Privacy\Actionlogs\Extension; -use Joomla\CMS\User\User; +use Joomla\CMS\Event\Privacy\ExportRequestEvent; use Joomla\Component\Actionlogs\Administrator\Helper\ActionlogsHelper; use Joomla\Component\Privacy\Administrator\Plugin\PrivacyPlugin; -use Joomla\Component\Privacy\Administrator\Table\RequestTable; use Joomla\Database\ParameterType; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -25,22 +25,38 @@ * * @since 3.9.0 */ -final class Actionlogs extends PrivacyPlugin +final class Actionlogs extends PrivacyPlugin implements SubscriberInterface { + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onPrivacyExportRequest' => 'onPrivacyExportRequest', + ]; + } + /** * Processes an export request for Joomla core actionlog data * - * @param RequestTable $request The request record being processed - * @param User $user The user account associated with this request if available + * @param ExportRequestEvent $event The request event * - * @return \Joomla\Component\Privacy\Administrator\Export\Domain[] + * @return void * * @since 3.9.0 */ - public function onPrivacyExportRequest(RequestTable $request, User $user = null) + public function onPrivacyExportRequest(ExportRequestEvent $event) { + $user = $event->getUser(); + + // RequestTable $request, User $user = null if (!$user) { - return []; + return; } $domain = $this->createDomain('user_action_logs', 'joomla_user_action_logs_data'); @@ -59,7 +75,7 @@ public function onPrivacyExportRequest(RequestTable $request, User $user = null) $data = $db->loadObjectList(); if (!count($data)) { - return []; + return; } $data = ActionlogsHelper::getCsvData($data); @@ -75,6 +91,6 @@ public function onPrivacyExportRequest(RequestTable $request, User $user = null) $domain->addItem($this->createItemFromArray($item)); } - return [$domain]; + $event->addResult([$domain]); } } diff --git a/plugins/privacy/user/src/Extension/UserPlugin.php b/plugins/privacy/user/src/Extension/UserPlugin.php index 7d42c4c0e7cc1..701b175abe106 100644 --- a/plugins/privacy/user/src/Extension/UserPlugin.php +++ b/plugins/privacy/user/src/Extension/UserPlugin.php @@ -10,14 +10,17 @@ namespace Joomla\Plugin\Privacy\User\Extension; +use Joomla\CMS\Event\Privacy\CanRemoveDataEvent; +use Joomla\CMS\Event\Privacy\ExportRequestEvent; +use Joomla\CMS\Event\Privacy\RemoveDataEvent; use Joomla\CMS\Language\Text; use Joomla\CMS\Table\User as TableUser; use Joomla\CMS\User\User; use Joomla\CMS\User\UserHelper; use Joomla\Component\Privacy\Administrator\Plugin\PrivacyPlugin; use Joomla\Component\Privacy\Administrator\Removal\Status; -use Joomla\Component\Privacy\Administrator\Table\RequestTable; use Joomla\Database\ParameterType; +use Joomla\Event\SubscriberInterface; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects @@ -29,26 +32,43 @@ * * @since 3.9.0 */ -final class UserPlugin extends PrivacyPlugin +final class UserPlugin extends PrivacyPlugin implements SubscriberInterface { + /** + * Returns an array of events this subscriber will listen to. + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onPrivacyCanRemoveData' => 'onPrivacyCanRemoveData', + 'onPrivacyRemoveData' => 'onPrivacyRemoveData', + 'onPrivacyExportRequest' => 'onPrivacyExportRequest', + ]; + } + /** * Performs validation to determine if the data associated with a remove information request can be processed * * This event will not allow a super user account to be removed * - * @param RequestTable $request The request record being processed - * @param User $user The user account associated with this request if available + * @param CanRemoveDataEvent $event The request event * - * @return Status + * @return void * * @since 3.9.0 */ - public function onPrivacyCanRemoveData(RequestTable $request, User $user = null) + public function onPrivacyCanRemoveData(CanRemoveDataEvent $event) { + $user = $event->getUser(); $status = new Status(); if (!$user) { - return $status; + $event->addResult($status); + return; } if ($user->authorise('core.admin')) { @@ -56,7 +76,7 @@ public function onPrivacyCanRemoveData(RequestTable $request, User $user = null) $status->reason = Text::_('PLG_PRIVACY_USER_ERROR_CANNOT_REMOVE_SUPER_USER'); } - return $status; + $event->addResult($status); } /** @@ -69,17 +89,18 @@ public function onPrivacyCanRemoveData(RequestTable $request, User $user = null) * - #__user_profiles * - User custom fields * - * @param RequestTable $request The request record being processed - * @param User $user The user account associated with this request if available + * @param ExportRequestEvent $event The request event * - * @return \Joomla\Component\Privacy\Administrator\Export\Domain[] + * @return void * * @since 3.9.0 */ - public function onPrivacyExportRequest(RequestTable $request, User $user = null) + public function onPrivacyExportRequest(ExportRequestEvent $event) { + $user = $event->getUser(); + if (!$user) { - return []; + return; } /** @var TableUser $userTable */ @@ -92,7 +113,7 @@ public function onPrivacyExportRequest(RequestTable $request, User $user = null) $domains[] = $this->createProfileDomain($userTable); $domains[] = $this->createCustomFieldsDomain('com_users.user', [$userTable]); - return $domains; + $event->addResult($domains); } /** @@ -100,15 +121,16 @@ public function onPrivacyExportRequest(RequestTable $request, User $user = null) * * This event will pseudoanonymise the user account * - * @param RequestTable $request The request record being processed - * @param User $user The user account associated with this request if available + * @param RemoveDataEvent $event The remove data event * * @return void * * @since 3.9.0 */ - public function onPrivacyRemoveData(RequestTable $request, User $user = null) + public function onPrivacyRemoveData(RemoveDataEvent $event) { + $user = $event->getUser(); + // This plugin only processes data for registered user accounts if (!$user) { return; diff --git a/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php b/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php index dee9174cc86c1..3376b260f548c 100644 --- a/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php +++ b/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php @@ -12,6 +12,7 @@ use Joomla\CMS\Application\ApplicationHelper; use Joomla\CMS\Cache\Cache; +use Joomla\CMS\Event\Privacy\CheckPrivacyPolicyPublishedEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Form\FormHelper; @@ -312,14 +313,17 @@ public function onAfterRoute() /** * Event to specify whether a privacy policy has been published. * - * @param array &$policy The privacy policy status data, passed by reference, with keys "published", "editLink" and "articlePublished". + * @param CheckPrivacyPolicyPublishedEvent $event The privacy policy status event. * * @return void * * @since 3.9.0 */ - public function onPrivacyCheckPrivacyPolicyPublished(&$policy) + public function onPrivacyCheckPrivacyPolicyPublished(CheckPrivacyPolicyPublishedEvent $event) { + // Data, with keys "published", "editLink" and "articlePublished". + $policy = $event->getPolicyInfo(); + // If another plugin has already indicated a policy is published, we won't change anything here if ($policy['published']) { return; diff --git a/tests/Unit/Plugin/Captcha/InvisibleRecaptcha/Extension/InvisibleRecaptchaPluginTest.php b/tests/Unit/Plugin/Captcha/InvisibleRecaptcha/Extension/InvisibleRecaptchaPluginTest.php index a93e5e26d7e9a..c834f0981f531 100644 --- a/tests/Unit/Plugin/Captcha/InvisibleRecaptcha/Extension/InvisibleRecaptchaPluginTest.php +++ b/tests/Unit/Plugin/Captcha/InvisibleRecaptcha/Extension/InvisibleRecaptchaPluginTest.php @@ -14,6 +14,7 @@ use Joomla\CMS\Captcha\CaptchaRegistry; use Joomla\CMS\Document\HtmlDocument; use Joomla\CMS\Event\Captcha\CaptchaSetupEvent; +use Joomla\CMS\Event\Privacy\CollectCapabilitiesEvent; use Joomla\CMS\Form\Field\CaptchaField; use Joomla\CMS\Language\Language; use Joomla\Event\Dispatcher; @@ -281,8 +282,7 @@ public function testPrivacy() $plugin = new InvisibleReCaptcha($dispatcher, ['name' => 'test', 'params' => []]); $plugin->setApplication($app); - // @TODO: The event should be changed to what the Privacy component provide. - $event = new \Joomla\Event\Event('onPrivacyCollectAdminCapabilities', ['result' => []]); + $event = new CollectCapabilitiesEvent('onPrivacyCollectAdminCapabilities'); $plugin->onPrivacyCollectAdminCapabilities($event); $this->assertNotEmpty($event['result']);