JoomlaPolska / jezyk-J4

Język polski dla Joomla 4
GNU General Public License v2.0
3 stars 5 forks source link

[5] add2scheduler-privacyconsents #414

Closed joomlapl-bot closed 5 months ago

joomlapl-bot commented 1 year ago

PR w związku ze zmianą oryginału https://github.com/joomla/joomla-cms/pull/40553 Poniżej zmiany w oryginale:

Click to expand the diff! ```diff diff --git a/administrator/components/com_admin/script.php b/administrator/components/com_admin/script.php index 1eefc688d162..768a04aa6df0 100644 --- a/administrator/components/com_admin/script.php +++ b/administrator/components/com_admin/script.php @@ -2346,11 +2346,86 @@ public function postflight($action, $installer) return false; } + if (!$this->migratePrivacyconsentConfiguration()) { + return false; + } + $this->setGuidedToursUid(); return true; } + /** + * Migrate privacyconsents system plugin configuration + * + * @return boolean True on success + * + * @since 5.0.0 + */ + private function migratePrivacyconsentConfiguration(): bool + { + $db = Factory::getDbo(); + + try { + // Get the PrivacyConsent system plugin's parameters + $row = $db->setQuery( + $db->getQuery(true) + ->select($db->quotename('enabled'), $db->quoteName('params')) + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) + ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) + ->where($db->quoteName('element') . ' = ' . $db->quote('privacyconsent')) + )->loadObject(); + } catch (Exception $e) { + echo Text::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '
'; + + return false; + } + + // If not existing or disbled there is nothing to migrate + if (!$row || !$row->enabled) { + return true; + } + + $params = new Registry($row->params); + + // If consent expiration was disbled there is nothing to migrate + if (!$params->get('enabled', 0)) { + return true; + } + + /** @var SchedulerComponent $component */ + $component = Factory::getApplication()->bootComponent('com_scheduler'); + + /** @var TaskModel $model */ + $model = $component->getMVCFactory()->createModel('Task', 'Administrator', ['ignore_request' => true]); + $task = [ + 'title' => 'PrivacyConsent', + 'type' => 'privacy.consent', + 'execution_rules' => [ + 'rule-type' => 'interval-days', + 'interval-days' => $params->get('cachetimeout', 30), + 'exec-time' => gmdate('H:i', $params->get('lastrun', time())), + 'exec-day' => gmdate('d'), + ], + 'state' => 1, + 'params' => [ + 'consentexpiration' => $params->get('consentexpiration', 360), + 'remind' => $params->get('remind', 30), + ], + ]; + + try { + $model->save($task); + } catch (Exception $e) { + echo Text::sprintf('JLIB_DATABASE_ERROR_FUNCTION_FAILED', $e->getCode(), $e->getMessage()) . '
'; + + return false; + } + + return true; + } + /** * Migrate TinyMCE editor plugin configuration * diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-02.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-02.sql index 5552693d22c2..27c020cd2fb5 100644 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-02.sql +++ b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-02.sql @@ -1,9 +1,12 @@ INSERT INTO `#__extensions` (`name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES +('plg_task_privacyconsent', 'plugin', 'privacyconsent', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), ('plg_task_rotatelogs', 'plugin', 'rotatelogs', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), ('plg_task_updatenotification', 'plugin', 'updatenotification', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0); INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subject`, `body`, `htmlbody`, `attachments`, `params`) VALUES +('plg_task_privacyconsent.request.reminder', 'plg_task_privacyconsent', '', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_BODY', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), ('plg_task_updatenotification.mail', 'plg_task_updatenotification', '', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url","link","releasenews"]}'); -DELETE FROM `#__mail_templates` WHERE `template_id` = 'plg_system_updatenotification.mail'; +DELETE FROM `#__mail_templates` WHERE `template_id` IN ('plg_system_privacyconsent.request.reminder', 'plg_system_updatenotification.mail'); + DELETE FROM `#__postinstall_messages` WHERE `condition_file` = 'site://plugins/system/updatenotification/postinstall/updatecachetime.php'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-02.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-02.sql index fc99290a3d62..931f4acb15b6 100644 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-02.sql +++ b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-02.sql @@ -1,9 +1,12 @@ INSERT INTO "#__extensions" ("name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "checked_out", "checked_out_time", "ordering", "state") VALUES +('plg_task_privacyconsent', 'plugin', 'privacyconsent', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), ('plg_task_rotatelogs', 'plugin', 'rotatelogs', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), ('plg_task_updatenotification', 'plugin', 'updatenotification', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0); INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subject", "body", "htmlbody", "attachments", "params") VALUES +('plg_task_privacyconsent.request.reminder', 'plg_task_privacyconsent', '', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_BODY', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), ('plg_task_updatenotification.mail', 'plg_task_updatenotification', '', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url","link","releasenews"]}'); -DELETE FROM "#__mail_templates" WHERE "template_id" = 'plg_system_updatenotification.mail'; +DELETE FROM "#__mail_templates" WHERE "template_id" IN ('plg_system_privacyconsent.request.reminder', 'plg_system_updatenotification.mail'); + DELETE FROM "#__postinstall_messages" WHERE "condition_file" = 'site://plugins/system/updatenotification/postinstall/updatecachetime.php'; diff --git a/administrator/language/en-GB/plg_system_privacyconsent.ini b/administrator/language/en-GB/plg_system_privacyconsent.ini index 30ef0294554d..2abb7a81a4ec 100644 --- a/administrator/language/en-GB/plg_system_privacyconsent.ini +++ b/administrator/language/en-GB/plg_system_privacyconsent.ini @@ -5,18 +5,11 @@ PLG_SYSTEM_PRIVACYCONSENT="System - Privacy Consent" PLG_SYSTEM_PRIVACYCONSENT_BODY="

The user consented to storing their user information using the IP address %s

The user agent string of the user's browser was:
%s

This information was automatically recorded when the user submitted their details on the website and checked the confirm box

" -PLG_SYSTEM_PRIVACYCONSENT_CACHETIMEOUT_DESC="How often the check is performed." -PLG_SYSTEM_PRIVACYCONSENT_CACHETIMEOUT_LABEL="Periodic check (days)" PLG_SYSTEM_PRIVACYCONSENT_CONSENT="User {username} consented to the privacy policy." -PLG_SYSTEM_PRIVACYCONSENT_CONSENTEXPIRATION_DESC="Number of days after which the privacy consent shall expire." -PLG_SYSTEM_PRIVACYCONSENT_CONSENTEXPIRATION_LABEL="Expiration" PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_BODY="Your Privacy Consent given at {URL} will expire in few days, you can renew the privacy consent for this website.\n\nIn order to do this, you can complete one of the following tasks:\n\n1. Visit the following URL: {TOKENURL}\n\n2. Copy your token from this email, visit the referenced URL, and paste your token into the form.\nURL: {FORMURL}\nToken: {TOKEN}\n\nPlease note that this token is only valid for this account." PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT="Privacy Consent at {SITENAME}" -PLG_SYSTEM_PRIVACYCONSENT_EXPIRATION_FIELDSET_LABEL="Expiration" PLG_SYSTEM_PRIVACYCONSENT_FIELD_ARTICLE_DESC="Select the article from the list or create a new one." PLG_SYSTEM_PRIVACYCONSENT_FIELD_ARTICLE_LABEL="Privacy Article" -PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_DESC="When enabled it performs checks for consent expiration." -PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_LABEL="Enable" PLG_SYSTEM_PRIVACYCONSENT_FIELD_ERROR="Agreement to the site's Privacy Policy is required." PLG_SYSTEM_PRIVACYCONSENT_FIELD_LABEL="Privacy Policy" PLG_SYSTEM_PRIVACYCONSENT_FIELD_MENU_ITEM_LABEL="Privacy Menu Item" @@ -36,7 +29,16 @@ PLG_SYSTEM_PRIVACYCONSENT_OPTION_DO_NOT_AGREE="I do not agree" PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_DEFAULT="Please confirm that you consent to this website storing your information by agreeing to the privacy policy." PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_DESC="Custom message to be displayed on redirect. If left blank then the default message will be used." PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_LABEL="Redirect Message" -PLG_SYSTEM_PRIVACYCONSENT_REMINDBEFORE_DESC="Number of days to send a reminder before the expiration of the privacy consent." -PLG_SYSTEM_PRIVACYCONSENT_REMINDBEFORE_LABEL="Remind" PLG_SYSTEM_PRIVACYCONSENT_SUBJECT="Privacy Policy" PLG_SYSTEM_PRIVACYCONSENT_XML_DESCRIPTION="Basic plugin to request user's consent to the site's privacy policy. Existing users who have not consented yet will be redirected on login to update their profile." + +; All the following strings are deprecated and will be removed with 6.0 +PLG_SYSTEM_PRIVACYCONSENT_CACHETIMEOUT_DESC="How often the check is performed." +PLG_SYSTEM_PRIVACYCONSENT_CACHETIMEOUT_LABEL="Periodic check (days)" +PLG_SYSTEM_PRIVACYCONSENT_CONSENTEXPIRATION_DESC="Number of days after which the privacy consent shall expire." +PLG_SYSTEM_PRIVACYCONSENT_CONSENTEXPIRATION_LABEL="Expiration" +PLG_SYSTEM_PRIVACYCONSENT_EXPIRATION_FIELDSET_LABEL="Expiration" +PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_DESC="When enabled it performs checks for consent expiration." +PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_LABEL="Enable" +PLG_SYSTEM_PRIVACYCONSENT_REMINDBEFORE_DESC="Number of days to send a reminder before the expiration of the privacy consent." +PLG_SYSTEM_PRIVACYCONSENT_REMINDBEFORE_LABEL="Remind" diff --git a/administrator/language/en-GB/plg_task_privacyconsent.ini b/administrator/language/en-GB/plg_task_privacyconsent.ini new file mode 100644 index 000000000000..5baf97d04fae --- /dev/null +++ b/administrator/language/en-GB/plg_task_privacyconsent.ini @@ -0,0 +1,47 @@ +; Joomla! Project +; (C) 2023 Open Source Matters, Inc. +; License GNU General Public License version 2 or later; see LICENSE.txt +; Note : All ini files need to be saved as UTF-8 + +PLG_TASK_PRIVACYCONSENT="Task - Privacy Consents" +PLG_TASK_PRIVACYCONSENT_CONSENTEXPIRATIONDAYS_DESC="Number of days after which the privacy consent shall expire." +PLG_TASK_PRIVACYCONSENT_CONSENTEXPIRATIONDAYS_LABEL="Expiration" +PLG_TASK_PRIVACYCONSENT_INVALIDATE_TITLE ="Expiration of privacy consents" +PLG_TASK_PRIVACYCONSENT_INVALIDATE_DESC ="Manage the expiration of privacy consents" +PLG_TASK_PRIVACYCONSENT_REMIND_DESC="Manage the remind of expiration of privacy consents" +PLG_TASK_PRIVACYCONSENT_REMIND_TITLE="Remind" +PLG_TASK_PRIVACYCONSENT_BODY="

The user consented to storing their user information using the IP address %s

The user agent string of the user's browser was:
%s

This information was automatically recorded when the user submitted their details on the website and checked the confirm box

" +PLG_TASK_PRIVACYCONSENT_CACHETIMEOUT_DESC="How often the check is performed." +PLG_TASK_PRIVACYCONSENT_CACHETIMEOUT_LABEL="Periodic check (days)" +PLG_TASK_PRIVACYCONSENT_CONSENT="User {username} consented to the privacy policy." + +PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_BODY="Your Privacy Consent given at {URL} will expire in few days, you can renew the privacy consent for this website.\n\nIn order to do this, you can complete one of the following tasks:\n\n1. Visit the following URL: {TOKENURL}\n\n2. Copy your token from this email, visit the referenced URL, and paste your token into the form.\nURL: {FORMURL}\nToken: {TOKEN}\n\nPlease note that this token is only valid for this account." +PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT="Privacy Consent at {SITENAME}" +PLG_TASK_PRIVACYCONSENT_EXPIRATION_FIELDSET_LABEL="Expiration" +PLG_TASK_PRIVACYCONSENT_FIELD_ARTICLE_DESC="Select the article from the list or create a new one." +PLG_TASK_PRIVACYCONSENT_FIELD_ARTICLE_LABEL="Privacy Article" +PLG_TASK_PRIVACYCONSENT_FIELD_ENABLED_DESC="When enabled it performs checks for consent expiration." +PLG_TASK_PRIVACYCONSENT_FIELD_ENABLED_LABEL="Enable" +PLG_TASK_PRIVACYCONSENT_FIELD_ERROR="Agreement to the site's Privacy Policy is required." +PLG_TASK_PRIVACYCONSENT_FIELD_LABEL="Privacy Policy" +PLG_TASK_PRIVACYCONSENT_FIELD_MENU_ITEM_LABEL="Privacy Menu Item" +PLG_TASK_PRIVACYCONSENT_FIELD_TYPE_ARTICLE="Article" +PLG_TASK_PRIVACYCONSENT_FIELD_TYPE_LABEL="Privacy Type" +PLG_TASK_PRIVACYCONSENT_FIELD_TYPE_MENU_ITEM="Menu Item" +PLG_TASK_PRIVACYCONSENT_LABEL="Website Privacy" +PLG_TASK_PRIVACYCONSENT_MAIL_REQUEST_REMINDER_DESC="Reminder to renew the privacy consent for this website." +PLG_TASK_PRIVACYCONSENT_MAIL_REQUEST_REMINDER_TITLE="System - Privacy Consent: Renew Consent" +PLG_TASK_PRIVACYCONSENT_NOTE_FIELD_DEFAULT="By signing up to this website and agreeing to the Privacy Policy you agree to this website storing your information." +PLG_TASK_PRIVACYCONSENT_NOTE_FIELD_DESC="A summary of the site's privacy policy. If left blank then the default message will be used." +PLG_TASK_PRIVACYCONSENT_NOTE_FIELD_LABEL="Short Privacy Policy" +PLG_TASK_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_MESSAGE="Privacy consent has expired for %1$s." +PLG_TASK_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_SUBJECT="Privacy Consent Expired" +PLG_TASK_PRIVACYCONSENT_OPTION_AGREE="I agree" +PLG_TASK_PRIVACYCONSENT_OPTION_DO_NOT_AGREE="I do not agree" +PLG_TASK_PRIVACYCONSENT_REDIRECT_MESSAGE_DEFAULT="Please confirm that you consent to this website storing your information by agreeing to the privacy policy." +PLG_TASK_PRIVACYCONSENT_REDIRECT_MESSAGE_DESC="Custom message to be displayed on redirect. If left blank then the default message will be used." +PLG_TASK_PRIVACYCONSENT_REDIRECT_MESSAGE_LABEL="Redirect Message" +PLG_TASK_PRIVACYCONSENT_REMINDBEFORE_DESC="Number of days to send a reminder before the expiration of the privacy consent." +PLG_TASK_PRIVACYCONSENT_REMINDBEFORE_LABEL="Remind" +PLG_TASK_PRIVACYCONSENT_SUBJECT="Privacy Policy" +PLG_TASK_PRIVACYCONSENT_XML_DESCRIPTION="Task for remind expired consents and delete expired consents" diff --git a/administrator/language/en-GB/plg_task_privacyconsent.sys.ini b/administrator/language/en-GB/plg_task_privacyconsent.sys.ini new file mode 100644 index 000000000000..4893e9d29203 --- /dev/null +++ b/administrator/language/en-GB/plg_task_privacyconsent.sys.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2023 Open Source Matters, Inc. +; License GNU General Public License version 2 or later; see LICENSE.txt +; Note : All ini files need to be saved as UTF-8 + +PLG_TASK_PRIVACYCONSENT="Task - Privacy Consents" +PLG_TASK_PRIVACYCONSENT_XML_DESCRIPTION="Task for remind expired consents and delete expired consents." diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql index d5ed86c6dd52..0c0b6a33700a 100644 --- a/installation/sql/mysql/base.sql +++ b/installation/sql/mysql/base.sql @@ -366,9 +366,10 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'plg_task_checkfiles', 'plugin', 'checkfiles', 'task', 0, 1, 1, 0, 1, '', '{}', '', 1, 0), (0, 'plg_task_globalcheckin', 'plugin', 'globalcheckin', 'task', 0, 1, 1, 0, 0, '', '{}', '', 2, 0), (0, 'plg_task_requests', 'plugin', 'requests', 'task', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), -(0, 'plg_task_rotatelogs', 'plugin', 'rotatelogs', 'task', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), -(0, 'plg_task_sitestatus', 'plugin', 'sitestatus', 'task', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), -(0, 'plg_task_updatenotification', 'plugin', 'updatenotification', 'task', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), +(0, 'plg_task_privacyconsent', 'plugin', 'privacyconsent', 'task', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), +(0, 'plg_task_rotatelogs', 'plugin', 'rotatelogs', 'task', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), +(0, 'plg_task_sitestatus', 'plugin', 'sitestatus', 'task', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), +(0, 'plg_task_updatenotification', 'plugin', 'updatenotification', 'task', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), (0, 'plg_multifactorauth_totp', 'plugin', 'totp', 'multifactorauth', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_multifactorauth_yubikey', 'plugin', 'yubikey', 'multifactorauth', 0, 1, 1, 0, 1, '', '', '', 2, 0), (0, 'plg_multifactorauth_webauthn', 'plugin', 'webauthn', 'multifactorauth', 0, 1, 1, 0, 1, '', '', '', 3, 0), diff --git a/installation/sql/mysql/supports.sql b/installation/sql/mysql/supports.sql index f7252db7465a..2829bad359b0 100644 --- a/installation/sql/mysql/supports.sql +++ b/installation/sql/mysql/supports.sql @@ -431,7 +431,7 @@ INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subjec ('com_users.registration.admin.new_notification', 'com_users', '', 'COM_USERS_EMAIL_ACCOUNT_DETAILS', 'COM_USERS_EMAIL_REGISTERED_NOTIFICATION_TO_ADMIN_BODY', '', '', '{"tags":["name","sitename","siteurl","username"]}'), ('com_users.registration.user.admin_activated', 'com_users', '', 'COM_USERS_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_SUBJECT', 'COM_USERS_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_BODY', '', '', '{"tags":["name","sitename","siteurl","username"]}'), ('com_users.registration.admin.verification_request', 'com_users', '', 'COM_USERS_EMAIL_ACTIVATE_WITH_ADMIN_ACTIVATION_SUBJECT', 'COM_USERS_EMAIL_ACTIVATE_WITH_ADMIN_ACTIVATION_BODY', '', '', '{"tags":["name","sitename","email","username","activate"]}'), -('plg_system_privacyconsent.request.reminder', 'plg_system_privacyconsent', '', 'PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT', 'PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_BODY', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), +('plg_task_privacyconsent.request.reminder', 'plg_task_privacyconsent', '', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_BODY', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), ('com_messages.new_message', 'com_messages', '', 'COM_MESSAGES_NEW_MESSAGE', 'COM_MESSAGES_NEW_MESSAGE_BODY', '', '', '{"tags":["subject","message","fromname","sitename","siteurl","fromemail","toname","toemail"]}'), ('plg_system_tasknotification.failure_mail', 'plg_system_tasknotification', '', 'PLG_SYSTEM_TASK_NOTIFICATION_FAILURE_MAIL_SUBJECT', 'PLG_SYSTEM_TASK_NOTIFICATION_FAILURE_MAIL_BODY', '', '', '{"tags": ["task_id", "task_title", "exit_code", "exec_data_time", "task_output"]}'), ('plg_system_tasknotification.fatal_recovery_mail', 'plg_system_tasknotification', '', 'PLG_SYSTEM_TASK_NOTIFICATION_FATAL_MAIL_SUBJECT', 'PLG_SYSTEM_TASK_NOTIFICATION_FATAL_MAIL_BODY', '', '', '{"tags": ["task_id", "task_title"]}'), diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql index 58314488cbde..883ad28bf8ff 100644 --- a/installation/sql/postgresql/base.sql +++ b/installation/sql/postgresql/base.sql @@ -372,9 +372,10 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'plg_task_checkfiles', 'plugin', 'checkfiles', 'task', 0, 1, 1, 0, 1, '', '{}', '', 1, 0), (0, 'plg_task_globalcheckin', 'plugin', 'globalcheckin', 'task', 0, 1, 1, 0, 0, '', '{}', '', 2, 0), (0, 'plg_task_requests', 'plugin', 'requests', 'task', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), -(0, 'plg_task_rotatelogs', 'plugin', 'rotatelogs', 'task', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), -(0, 'plg_task_sitestatus', 'plugin', 'sitestatus', 'task', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), -(0, 'plg_task_updatenotification', 'plugin', 'updatenotification', 'task', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), +(0, 'plg_task_privacyconsent', 'plugin', 'privacyconsent', 'task', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), +(0, 'plg_task_rotatelogs', 'plugin', 'rotatelogs', 'task', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), +(0, 'plg_task_sitestatus', 'plugin', 'sitestatus', 'task', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), +(0, 'plg_task_updatenotification', 'plugin', 'updatenotification', 'task', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), (0, 'plg_multifactorauth_totp', 'plugin', 'totp', 'multifactorauth', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_multifactorauth_yubikey', 'plugin', 'yubikey', 'multifactorauth', 0, 1, 1, 0, 1, '', '', '', 2, 0), (0, 'plg_multifactorauth_webauthn', 'plugin', 'webauthn', 'multifactorauth', 0, 1, 1, 0, 1, '', '', '', 3, 0), diff --git a/installation/sql/postgresql/supports.sql b/installation/sql/postgresql/supports.sql index 1ad64316c3c2..fb6571f6f951 100644 --- a/installation/sql/postgresql/supports.sql +++ b/installation/sql/postgresql/supports.sql @@ -442,7 +442,7 @@ INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subjec ('com_users.registration.admin.new_notification', 'com_users', '', 'COM_USERS_EMAIL_ACCOUNT_DETAILS', 'COM_USERS_EMAIL_REGISTERED_NOTIFICATION_TO_ADMIN_BODY', '', '', '{"tags":["name","sitename","siteurl","username"]}'), ('com_users.registration.user.admin_activated', 'com_users', '', 'COM_USERS_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_SUBJECT', 'COM_USERS_EMAIL_ACTIVATED_BY_ADMIN_ACTIVATION_BODY', '', '', '{"tags":["name","sitename","siteurl","username"]}'), ('com_users.registration.admin.verification_request', 'com_users', '', 'COM_USERS_EMAIL_ACTIVATE_WITH_ADMIN_ACTIVATION_SUBJECT', 'COM_USERS_EMAIL_ACTIVATE_WITH_ADMIN_ACTIVATION_BODY', '', '', '{"tags":["name","sitename","email","username","activate"]}'), -('plg_system_privacyconsent.request.reminder', 'plg_system_privacyconsent', '', 'PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT', 'PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_BODY', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), +('plg_task_privacyconsent.request.reminder', 'plg_task_privacyconsent', '', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_BODY', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), ('com_messages.new_message', 'com_messages', '', 'COM_MESSAGES_NEW_MESSAGE', 'COM_MESSAGES_NEW_MESSAGE_BODY', '', '', '{"tags":["subject","message","fromname","sitename","siteurl","fromemail","toname","toemail"]}'), ('plg_system_tasknotification.failure_mail', 'plg_system_tasknotification', '', 'PLG_SYSTEM_TASK_NOTIFICATION_FAILURE_MAIL_SUBJECT', 'PLG_SYSTEM_TASK_NOTIFICATION_FAILURE_MAIL_BODY', '', '', '{"tags": ["task_id", "task_title", "exit_code", "exec_data_time", "task_output"]}'), ('plg_system_tasknotification.fatal_recovery_mail', 'plg_system_tasknotification', '', 'PLG_SYSTEM_TASK_NOTIFICATION_FATAL_MAIL_SUBJECT', 'PLG_SYSTEM_TASK_NOTIFICATION_FATAL_MAIL_BODY', '', '', '{"tags": ["task_id", "task_title"]}'), diff --git a/libraries/src/Extension/ExtensionHelper.php b/libraries/src/Extension/ExtensionHelper.php index e52390c4cb9a..bde784432c9d 100644 --- a/libraries/src/Extension/ExtensionHelper.php +++ b/libraries/src/Extension/ExtensionHelper.php @@ -319,6 +319,7 @@ class ExtensionHelper // Core plugin extensions - task scheduler ['plugin', 'checkfiles', 'task', 0], ['plugin', 'globalcheckin', 'task', 0], + ['plugin', 'privacyconsent', 'task', 0], ['plugin', 'requests', 'task', 0], ['plugin', 'rotatelogs', 'task', 0], ['plugin', 'sitestatus', 'task', 0], diff --git a/plugins/system/privacyconsent/privacyconsent.xml b/plugins/system/privacyconsent/privacyconsent.xml index 9f7d31f02082..6c47d949ef51 100644 --- a/plugins/system/privacyconsent/privacyconsent.xml +++ b/plugins/system/privacyconsent/privacyconsent.xml @@ -78,65 +78,6 @@ filter="html" /> -
- - - - - - - - -
diff --git a/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php b/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php index 3376b260f548..639aa20cff5a 100644 --- a/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php +++ b/plugins/system/privacyconsent/src/Extension/PrivacyConsent.php @@ -10,28 +10,18 @@ namespace Joomla\Plugin\System\PrivacyConsent\Extension; -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; use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Text; -use Joomla\CMS\Mail\Exception\MailDisabledException; -use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Router\Route; -use Joomla\CMS\Uri\Uri; -use Joomla\CMS\User\UserFactoryAwareTrait; -use Joomla\CMS\User\UserHelper; use Joomla\Component\Actionlogs\Administrator\Model\ActionlogModel; -use Joomla\Component\Messages\Administrator\Model\MessageModel; use Joomla\Database\DatabaseAwareTrait; -use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; use Joomla\Utilities\ArrayHelper; -use PHPMailer\PHPMailer\Exception as phpmailerException; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -450,252 +440,4 @@ private function getPrivacyItemId() return $itemId; } - - /** - * The privacy consent expiration check code is triggered after the page has fully rendered. - * - * @return void - * - * @since 3.9.0 - */ - public function onAfterRender() - { - if (!$this->params->get('enabled', 0)) { - return; - } - - $cacheTimeout = (int) $this->params->get('cachetimeout', 30); - $cacheTimeout = 24 * 3600 * $cacheTimeout; - - // Do we need to run? Compare the last run timestamp stored in the plugin's options with the current - // timestamp. If the difference is greater than the cache timeout we shall not execute again. - $now = time(); - $last = (int) $this->params->get('lastrun', 0); - - if ((abs($now - $last) < $cacheTimeout)) { - return; - } - - // Update last run status - $this->params->set('lastrun', $now); - - $paramsJson = $this->params->toString('JSON'); - $db = $this->getDatabase(); - $query = $db->getQuery(true) - ->update($db->quoteName('#__extensions')) - ->set($db->quoteName('params') . ' = :params') - ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) - ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) - ->where($db->quoteName('element') . ' = ' . $db->quote('privacyconsent')) - ->bind(':params', $paramsJson); - - try { - // Lock the tables to prevent multiple plugin executions causing a race condition - $db->lockTable('#__extensions'); - } catch (\Exception $e) { - // If we can't lock the tables it's too risky to continue execution - return; - } - - try { - // Update the plugin parameters - $result = $db->setQuery($query)->execute(); - $this->clearCacheGroups(['com_plugins'], [0, 1]); - } catch (\Exception $exc) { - // If we failed to execute - $db->unlockTables(); - $result = false; - } - - try { - // Unlock the tables after writing - $db->unlockTables(); - } catch (\Exception $e) { - // If we can't lock the tables assume we have somehow failed - $result = false; - } - - // Stop on failure - if (!$result) { - return; - } - - // Delete the expired privacy consents - $this->invalidateExpiredConsents(); - - // Remind for privacy consents near to expire - $this->remindExpiringConsents(); - } - - /** - * Method to send the remind for privacy consents renew - * - * @return integer - * - * @since 3.9.0 - */ - private function remindExpiringConsents() - { - // Load the parameters. - $expire = (int) $this->params->get('consentexpiration', 365); - $remind = (int) $this->params->get('remind', 30); - $now = Factory::getDate()->toSql(); - $period = '-' . ($expire - $remind); - $db = $this->getDatabase(); - $query = $db->getQuery(true); - - $query->select($db->quoteName(['r.id', 'r.user_id', 'u.email'])) - ->from($db->quoteName('#__privacy_consents', 'r')) - ->join('LEFT', $db->quoteName('#__users', 'u'), $db->quoteName('u.id') . ' = ' . $db->quoteName('r.user_id')) - ->where($db->quoteName('subject') . ' = ' . $db->quote('PLG_SYSTEM_PRIVACYCONSENT_SUBJECT')) - ->where($db->quoteName('remind') . ' = 0') - ->where($query->dateAdd($db->quote($now), $period, 'DAY') . ' > ' . $db->quoteName('created')); - - try { - $users = $db->setQuery($query)->loadObjectList(); - } catch (ExecutionFailureException $exception) { - return false; - } - - $app = $this->getApplication(); - $linkMode = $app->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE; - - foreach ($users as $user) { - $token = ApplicationHelper::getHash(UserHelper::genRandomPassword()); - $hashedToken = UserHelper::hashPassword($token); - - // The mail - try { - $templateData = [ - 'sitename' => $app->get('sitename'), - 'url' => Uri::root(), - 'tokenurl' => Route::link('site', 'index.php?option=com_privacy&view=remind&remind_token=' . $token, false, $linkMode, true), - 'formurl' => Route::link('site', 'index.php?option=com_privacy&view=remind', false, $linkMode, true), - 'token' => $token, - ]; - - $mailer = new MailTemplate('plg_system_privacyconsent.request.reminder', $app->getLanguage()->getTag()); - $mailer->addTemplateData($templateData); - $mailer->addRecipient($user->email); - - $mailResult = $mailer->send(); - - if ($mailResult === false) { - return false; - } - - $userId = (int) $user->id; - - // Update the privacy_consents item to not send the reminder again - $query->clear() - ->update($db->quoteName('#__privacy_consents')) - ->set($db->quoteName('remind') . ' = 1') - ->set($db->quoteName('token') . ' = :token') - ->where($db->quoteName('id') . ' = :userid') - ->bind(':token', $hashedToken) - ->bind(':userid', $userId, ParameterType::INTEGER); - $db->setQuery($query); - - try { - $db->execute(); - } catch (\RuntimeException $e) { - return false; - } - } catch (MailDisabledException | phpmailerException $exception) { - return false; - } - } - } - - /** - * Method to delete the expired privacy consents - * - * @return boolean - * - * @since 3.9.0 - */ - private function invalidateExpiredConsents() - { - // Load the parameters. - $expire = (int) $this->params->get('consentexpiration', 365); - $now = Factory::getDate()->toSql(); - $period = '-' . $expire; - $db = $this->getDatabase(); - $query = $db->getQuery(true); - - $query->select($db->quoteName(['id', 'user_id'])) - ->from($db->quoteName('#__privacy_consents')) - ->where($query->dateAdd($db->quote($now), $period, 'DAY') . ' > ' . $db->quoteName('created')) - ->where($db->quoteName('subject') . ' = ' . $db->quote('PLG_SYSTEM_PRIVACYCONSENT_SUBJECT')) - ->where($db->quoteName('state') . ' = 1'); - - $db->setQuery($query); - - try { - $users = $db->loadObjectList(); - } catch (\RuntimeException $e) { - return false; - } - - // Do not process further if no expired consents found - if (empty($users)) { - return true; - } - - // Push a notification to the site's super users - /** @var MessageModel $messageModel */ - $messageModel = $this->getApplication()->bootComponent('com_messages')->getMVCFactory()->createModel('Message', 'Administrator'); - - foreach ($users as $user) { - $userId = (int) $user->id; - $query = $db->getQuery(true) - ->update($db->quoteName('#__privacy_consents')) - ->set($db->quoteName('state') . ' = 0') - ->where($db->quoteName('id') . ' = :userid') - ->bind(':userid', $userId, ParameterType::INTEGER); - $db->setQuery($query); - - try { - $db->execute(); - } catch (\RuntimeException $e) { - return false; - } - - $messageModel->notifySuperUsers( - $this->getApplication()->getLanguage()->_('PLG_SYSTEM_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_SUBJECT'), - Text::sprintf('PLG_SYSTEM_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_MESSAGE', $this->getUserFactory()->loadUserById($user->user_id)->username) - ); - } - - return true; - } - /** - * Clears cache groups. We use it to clear the plugins cache after we update the last run timestamp. - * - * @param array $clearGroups The cache groups to clean - * @param array $cacheClients The cache clients (site, admin) to clean - * - * @return void - * - * @since 3.9.0 - */ - private function clearCacheGroups(array $clearGroups, array $cacheClients = [0, 1]) - { - foreach ($clearGroups as $group) { - foreach ($cacheClients as $client_id) { - try { - $options = [ - 'defaultgroup' => $group, - 'cachebase' => $client_id ? JPATH_ADMINISTRATOR . '/cache' : - $this->getApplication()->get('cache_path', JPATH_SITE . '/cache'), - ]; - - $cache = Cache::getInstance('callback', $options); - $cache->clean(); - } catch (\Exception $e) { - // Ignore it - } - } - } - } } diff --git a/plugins/task/privacyconsent/forms/privacyconsentForm.xml b/plugins/task/privacyconsent/forms/privacyconsentForm.xml new file mode 100644 index 000000000000..dd6f12b71ff6 --- /dev/null +++ b/plugins/task/privacyconsent/forms/privacyconsentForm.xml @@ -0,0 +1,31 @@ + +
+ +
+ + +
+
+
diff --git a/plugins/task/privacyconsent/privacyconsent.xml b/plugins/task/privacyconsent/privacyconsent.xml new file mode 100644 index 000000000000..c47fd75c4747 --- /dev/null +++ b/plugins/task/privacyconsent/privacyconsent.xml @@ -0,0 +1,22 @@ + + + plg_task_privacyconsent + Joomla! Project + 2023-07 + (C) 2023 Open Source Matters, Inc. + GNU General Public License version 2 or later; see LICENSE.txt + admin@joomla.org + www.joomla.org + 5.0.0 + PLG_TASK_PRIVACYCONSENT_XML_DESCRIPTION + Joomla\Plugin\Task\PrivacyConsent + + forms + services + src + + + language/en-GB/plg_task_privacyconsent.ini + language/en-GB/plg_task_privacyconsent.sys.ini + + diff --git a/plugins/task/privacyconsent/services/provider.php b/plugins/task/privacyconsent/services/provider.php new file mode 100644 index 000000000000..4bd20fa1c74c --- /dev/null +++ b/plugins/task/privacyconsent/services/provider.php @@ -0,0 +1,50 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Extension\PluginInterface; +use Joomla\CMS\Factory; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\User\UserFactoryInterface; +use Joomla\Database\DatabaseInterface; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherInterface; +use Joomla\Plugin\Task\PrivacyConsent\Extension\PrivacyConsent; + +return new class () implements ServiceProviderInterface { + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function register(Container $container) + { + $container->set( + PluginInterface::class, + function (Container $container) { + $plugin = new PrivacyConsent( + $container->get(DispatcherInterface::class), + (array) PluginHelper::getPlugin('task', 'privacyconsent') + ); + $plugin->setApplication(Factory::getApplication()); + $plugin->setDatabase($container->get(DatabaseInterface::class)); + $plugin->setUserFactory($container->get(UserFactoryInterface::class)); + + return $plugin; + } + ); + } +}; diff --git a/plugins/task/privacyconsent/src/Extension/PrivacyConsent.php b/plugins/task/privacyconsent/src/Extension/PrivacyConsent.php new file mode 100644 index 000000000000..d79a595e4ee8 --- /dev/null +++ b/plugins/task/privacyconsent/src/Extension/PrivacyConsent.php @@ -0,0 +1,261 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Plugin\Task\PrivacyConsent\Extension; + +use Joomla\CMS\Application\ApplicationHelper; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Mail\Exception\MailDisabledException; +use Joomla\CMS\Mail\MailTemplate; +use Joomla\CMS\Plugin\CMSPlugin; +use Joomla\CMS\Router\Route; +use Joomla\CMS\Uri\Uri; +use Joomla\CMS\User\UserFactoryAwareTrait; +use Joomla\CMS\User\UserHelper; +use Joomla\Component\Scheduler\Administrator\Event\ExecuteTaskEvent; +use Joomla\Component\Scheduler\Administrator\Task\Status; +use Joomla\Component\Scheduler\Administrator\Task\Task; +use Joomla\Component\Scheduler\Administrator\Traits\TaskPluginTrait; +use Joomla\Database\DatabaseAwareTrait; +use Joomla\Database\ParameterType; +use Joomla\Event\SubscriberInterface; +use PHPMailer\PHPMailer\Exception as phpmailerException; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * A task plugin. Offers 2 task routines Invalidate Expired Consents and Remind Expired Consents + * {@see ExecuteTaskEvent}. + * + * @since __DEPLOY_VERSION__ + */ +final class PrivacyConsent extends CMSPlugin implements SubscriberInterface +{ + use DatabaseAwareTrait; + use TaskPluginTrait; + use UserFactoryAwareTrait; + + /** + * @var string[] + * @since __DEPLOY_VERSION__ + */ + private const TASKS_MAP = [ + 'privacy.consent' => [ + 'langConstPrefix' => 'PLG_TASK_PRIVACYCONSENT_INVALIDATE', + 'method' => 'privacyConsents', + 'form' => 'privacyconsentForm', + ], + ]; + + /** + * @var boolean + * + * @since __DEPLOY_VERSION__ + */ + protected $autoloadLanguage = true; + + /** + * @inheritDoc + * + * @return string[] + * + * @since __DEPLOY_VERSION__ + */ + public static function getSubscribedEvents(): array + { + return [ + 'onTaskOptionsList' => 'advertiseRoutines', + 'onExecuteTask' => 'standardRoutineHandler', + 'onContentPrepareForm' => 'enhanceTaskItemForm', + ]; + } + + /** + * Method to send the remind for privacy consents renew. + * + * @param ExecuteTaskEvent $event The `onExecuteTask` event. + * + * @return integer The routine exit code. + * + * @since __DEPLOY_VERSION__ + * @throws \Exception + */ + private function privacyConsents(ExecuteTaskEvent $event): int + { + // Load the parameters. + $expire = (int) $event->getArgument('params')->consentexpiration ?? 365; + $remind = (int) $event->getArgument('params')->remind ?? 30; + + if ( + $this->invalidateExpiredConsents($expire) === Status::OK + && $this->remindExpiringConsents($expire, $remind) === Status::OK + ) { + return Status::OK; + } + + return Status::KNOCKOUT; + } + + /** + * Method to send the remind for privacy consents renew. + * + * @param integer $expire + * @param integer $remind + * + * @return integer The routine exit code. + * + * @since __DEPLOY_VERSION__ + * @throws \Exception + */ + private function remindExpiringConsents($expire, $remind): int + { + $now = Factory::getDate()->toSql(); + $period = '-' . ($expire - $remind); + $db = $this->getDatabase(); + $query = $db->getQuery(true); + + $query->select($db->quoteName(['r.id', 'r.user_id', 'u.email'])) + ->from($db->quoteName('#__privacy_consents', 'r')) + ->join('LEFT', $db->quoteName('#__users', 'u'), $db->quoteName('u.id') . ' = ' . $db->quoteName('r.user_id')) + ->where($db->quoteName('subject') . ' = ' . $db->quote('PLG_TASK_PRIVACYCONSENT_SUBJECT')) + ->where($db->quoteName('remind') . ' = 0') + ->where($query->dateAdd($db->quote($now), $period, 'DAY') . ' > ' . $db->quoteName('created')); + + try { + $users = $db->setQuery($query)->loadObjectList(); + } catch (\RuntimeException $exception) { + return Status::KNOCKOUT; + } + + // Do not process further if no expired consents found + if (empty($users)) { + return Status::OK; + } + + $app = $this->getApplication(); + $linkMode = $app->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE; + + foreach ($users as $user) { + $token = ApplicationHelper::getHash(UserHelper::genRandomPassword()); + $hashedToken = UserHelper::hashPassword($token); + + // The mail + try { + $templateData = [ + 'sitename' => $app->get('sitename'), + 'url' => Uri::root(), + 'tokenurl' => Route::link('site', 'index.php?option=com_privacy&view=remind&remind_token=' . $token, false, $linkMode, true), + 'formurl' => Route::link('site', 'index.php?option=com_privacy&view=remind', false, $linkMode, true), + 'token' => $token, + ]; + + $mailer = new MailTemplate('plg_task_privacyconsent.request.reminder', $app->getLanguage()->getTag()); + $mailer->addTemplateData($templateData); + $mailer->addRecipient($user->email); + + $mailResult = $mailer->send(); + + if ($mailResult === false) { + return Status::KNOCKOUT; + } + + $userId = (int) $user->id; + + // Update the privacy_consents item to not send the reminder again + $query->clear() + ->update($db->quoteName('#__privacy_consents')) + ->set($db->quoteName('remind') . ' = 1') + ->set($db->quoteName('token') . ' = :token') + ->where($db->quoteName('id') . ' = :userid') + ->bind(':token', $hashedToken) + ->bind(':userid', $userId, ParameterType::INTEGER); + $db->setQuery($query); + + try { + $db->execute(); + } catch (\RuntimeException $e) { + return Status::KNOCKOUT; + } + } catch (MailDisabledException | phpmailerException $exception) { + return Status::KNOCKOUT; + } + } + $this->logTask('Remind end'); + + return Status::OK; + } + + /** + * Method to delete the expired privacy consents. + * + * @param integer $expire + * + * @return integer The routine exit code. + * + * @since __DEPLOY_VERSION__ + * @throws \Exception + */ + private function invalidateExpiredConsents($expire): int + { + $now = Factory::getDate()->toSql(); + $period = '-' . $expire; + $db = $this->getDatabase(); + $query = $db->getQuery(true); + + $query->select($db->quoteName(['id', 'user_id'])) + ->from($db->quoteName('#__privacy_consents')) + ->where($query->dateAdd($db->quote($now), $period, 'DAY') . ' > ' . $db->quoteName('created')) + ->where($db->quoteName('subject') . ' = ' . $db->quote('PLG_TASK_PRIVACYCONSENT_SUBJECT')) + ->where($db->quoteName('state') . ' = 1'); + + $db->setQuery($query); + + try { + $users = $db->loadObjectList(); + } catch (\RuntimeException $e) { + return Status::KNOCKOUT; + } + + // Do not process further if no expired consents found + if (empty($users)) { + return Status::OK; + } + + // Push a notification to the site's super users + /** @var MessageModel $messageModel */ + $messageModel = $this->getApplication()->bootComponent('com_messages')->getMVCFactory()->createModel('Message', 'Administrator'); + + foreach ($users as $user) { + $userId = (int) $user->id; + $query = $db->getQuery(true) + ->update($db->quoteName('#__privacy_consents')) + ->set($db->quoteName('state') . ' = 0') + ->where($db->quoteName('id') . ' = :userid') + ->bind(':userid', $userId, ParameterType::INTEGER); + $db->setQuery($query); + + try { + $db->execute(); + } catch (\RuntimeException $e) { + return Status::KNOCKOUT; + } + + $messageModel->notifySuperUsers( + Text::_('PLG_TASK_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_SUBJECT'), + Text::sprintf('PLG_TASK_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_MESSAGE', $this->getUserFactory()->loadUserById($user->user_id)->username) + ); + } + + return Status::OK; + } +} ```