Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
-- remove old email parameter from scheduled tasks
UPDATE `#__scheduler_task`
SET `params` = JSON_REMOVE(`params`, '$.email')
WHERE JSON_CONTAINS_PATH(`params`, 'one', '$.email');

-- add post-installation message for task update notification.
--
-- See https://github.com/joomla/joomla-cms/pull/43182 for details.
--
INSERT INTO `#__postinstall_messages`
(`extension_id`,
`title_key`,
`description_key`,
`action_key`,
`language_extension`,
`language_client_id`,
`type`,
`action_file`,
`action`,
`condition_file`,
`condition_method`,
`version_introduced`,
`enabled`)
SELECT
`extension_id`,
'PLG_TASK_UPDATENOTIFICATION_POSTINSTALL_TITLE',
'PLG_TASK_UPDATENOTIFICATION_POSTINSTALL_DESCRIPTION',
'',
'plg_task_updatenotification',
1,
'message',
'',
'',
'admin://plugins/task/updatenotification/postinstall/updatenotification.php',
'',
'6.1.0',
1
FROM `#__extensions` WHERE `name` = 'files_joomla';
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
-- remove old email parameter from scheduled tasks
UPDATE "#__scheduler_task"
SET "params" = jsonb_set("params", '{email}', '""')
WHERE "params" ? 'email';

-- add post-installation message for task update notification.
--
-- See https://github.com/joomla/joomla-cms/pull/43182 for details.
--
INSERT INTO "#__postinstall_messages"
("extension_id",
"title_key",
"description_key",
"action_key",
"language_extension",
"language_client_id",
"type",
"action_file",
"action",
"condition_file",
"condition_method",
"version_introduced",
"enabled")
SELECT
"extension_id",
'PLG_TASK_UPDATENOTIFICATION_POSTINSTALL_TITLE',
'PLG_TASK_UPDATENOTIFICATION_POSTINSTALL_DESCRIPTION',
'',
'plg_task_updatenotification',
1,
'message',
'',
'',
'admin://plugins/task/updatenotification/postinstall/updatenotification.php',
'',
'6.1.0',
1
FROM "#__extensions" WHERE "name" = 'files_joomla';
8 changes: 7 additions & 1 deletion administrator/language/en-GB/plg_task_updatenotification.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
; Note : All ini files need to be saved as UTF-8

PLG_TASK_UPDATENOTIFICATION="Task - Joomla! Update Notification"
; The following string is deprecated and will be removed with 8.
PLG_TASK_UPDATENOTIFICATION_EMAIL_DESC="A comma separated list of the email addresses which will receive the update notification emails. The addresses in the list MUST belong to existing users of your site who have the Super User privilege. If none of the listed emails belongs to Super Users, or if it's left blank, all Super Users of this site will receive the update notification email."
; The following string is deprecated and will be removed with 8.
PLG_TASK_UPDATENOTIFICATION_EMAIL_LBL="Super User Emails"
PLG_TASK_UPDATENOTIFICATION_EMAILGROUPS_DESC="All users in the selected groups will receive the emails. If no users are found, the emails are sent to all Super Users. Recipients MUST have the Receive System Emails option enabled."
PLG_TASK_UPDATENOTIFICATION_EMAILGROUPS_LBL="Send Email to User Groups"
PLG_TASK_UPDATENOTIFICATION_SEND_TITLE="Joomla! Update Notification"
PLG_TASK_UPDATENOTIFICATION_SEND_DESC="This task periodically checks for the availability of new Joomla! versions. When one is found it will send you an email, reminding you to update. You can customise the email at <a href=\"index.php?option=com_mails&view=templates&filter[extension]=plg_task_updatenotification\">System &rarr; Mail Templates.</a>"
PLG_TASK_UPDATENOTIFICATION_LANGUAGE_OVERRIDE_DESC="Select a language for the update notification emails. Set to Auto to send them in the site language at the time."
Expand All @@ -23,4 +27,6 @@ PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY="This email IS NOT sent by the Joomla! pr
PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT="Joomla! Update available for {SITENAME} – {URL}"
PLG_TASK_UPDATENOTIFICATION_MAIL_MAIL_DESC="Sent to the site administrators when the &quot;Joomla! Update Notification&quot; task plugin detects an update."
PLG_TASK_UPDATENOTIFICATION_MAIL_MAIL_TITLE="Joomla: Update Notification"
PLG_TASK_UPDATENOTIFICATION_XML_DESCRIPTION="This task periodically checks for the availability of new Joomla! versions. When one is found it will send you an email, reminding you to update. You can customise the email at <a href=\"index.php?option=com_mails&view=templates&filter[extension]=plg_task_updatenotification\">System &rarr; Mail Templates.</a>"
PLG_TASK_UPDATENOTIFICATION_POSTINSTALL_DESCRIPTION="<p>The &quot;Joomla! Update Notification&quot; task sends an email to the site administrators when it detects that a new Joomla! version is available. The email is per default sent to all super users of the system.</p><p>It is now possible to send notifications to one or more groups of users, who have the sendEmail permission, also if they are not super users.</p><p>If in your system recipients were defined as a comma separated list of email addresses, this list has been removed with update to version 6.1.</p><p>Please check the plugin's options and adjust them to your needs.</p>"
PLG_TASK_UPDATENOTIFICATION_POSTINSTALL_TITLE="Joomla! Update Notification Recipient Change"
PLG_TASK_UPDATENOTIFICATION_XML_DESCRIPTION="This task periodically checks for the availability of new Joomla! versions. When one is found it will send you an email, reminding you to update. You can customise the email at <a href=\"index.php?option=com_mails&view=templates&filter[extension]=plg_task_updatenotification\">System &rarr; Mail Templates.</a>"
12 changes: 7 additions & 5 deletions plugins/task/updatenotification/forms/sendForm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
<fields name="params">
<fieldset name="task_params">
<field
name="email"
type="text"
label="PLG_TASK_UPDATENOTIFICATION_EMAIL_LBL"
description="PLG_TASK_UPDATENOTIFICATION_EMAIL_DESC"
default=""
name="email_groups"
type="usergrouplist"
label="PLG_TASK_UPDATENOTIFICATION_EMAILGROUPS_LBL"
description="PLG_TASK_UPDATENOTIFICATION_EMAILGROUPS_DESC"
multiple="true"
checksuperusergroup="0"
layout="joomla.form.field.list-fancy-select"
/>
<field
name="language_override"
Expand Down
147 changes: 60 additions & 87 deletions plugins/task/updatenotification/src/Extension/UpdateNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
use Joomla\CMS\Access\Access;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Extension\ExtensionHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Helper\UserGroupsHelper;
use Joomla\CMS\Mail\Exception\MailDisabledException;
use Joomla\CMS\Mail\MailHelper;
use Joomla\CMS\Mail\MailTemplate;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Table\Asset;
use Joomla\CMS\Updater\Updater;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Version;
Expand All @@ -25,8 +27,8 @@
use Joomla\Component\Scheduler\Administrator\Task\Status;
use Joomla\Component\Scheduler\Administrator\Traits\TaskPluginTrait;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Database\ParameterType;
use Joomla\Event\SubscriberInterface;
use Joomla\Utilities\ArrayHelper;
use PHPMailer\PHPMailer\Exception as phpMailerException;

// phpcs:disable PSR1.Files.SideEffects
Expand Down Expand Up @@ -90,11 +92,8 @@ public static function getSubscribedEvents(): array
*/
private function sendNotification(ExecuteTaskEvent $event): int
{
// Load the parameters.
$specificEmail = $event->getArgument('params')->email ?? '';
$forcedLanguage = $event->getArgument('params')->language_override ?? '';

$updateParams = ComponentHelper::getParams('com_joomlaupdate');
$updateParams = ComponentHelper::getParams('com_joomlaupdate');

// Don't send when automated updates are active and working
$registrationState = AutoupdateRegisterState::tryFrom($updateParams->get('autoupdate_status', ''));
Expand Down Expand Up @@ -135,7 +134,6 @@ private function sendNotification(ExecuteTaskEvent $event): int
if (version_compare($update->version, JVERSION, 'le')) {
return Status::OK;
}

// If we're here, we have updates. First, get a link to the Joomla! Update component.
$baseURL = Uri::base();
$baseURL = rtrim($baseURL, '/');
Expand All @@ -158,17 +156,10 @@ private function sendNotification(ExecuteTaskEvent $event): int
$this->getApplication()->triggerEvent('onBuildAdministratorLoginURL', [&$uri]);

// Let's find out the email addresses to notify
$superUsers = [];

if (!empty($specificEmail)) {
$superUsers = $this->getSuperUsers($specificEmail);
}

if (empty($superUsers)) {
$superUsers = $this->getSuperUsers();
}
$emailReceivers = $this->getEmailReceivers();

if (empty($superUsers)) {
if (empty($emailReceivers)) {
// Just in case - at least one super user exists in every Joomla! site
return Status::KNOCKOUT;
}

Expand Down Expand Up @@ -205,11 +196,11 @@ private function sendNotification(ExecuteTaskEvent $event): int
'releasenews' => 'https://www.joomla.org/announcements/release-news/',
];

// Send the emails to the Super Users
foreach ($superUsers as $superUser) {
// Send the emails
foreach ($emailReceivers as $receiver) {
try {
$mailer = new MailTemplate('plg_task_updatenotification.mail', $jLanguage->getTag());
$mailer->addRecipient($superUser->email);
$mailer->addRecipient($receiver->email);
$mailer->addTemplateData($substitutions);
$mailer->send();
} catch (MailDisabledException | phpMailerException $exception) {
Expand All @@ -227,94 +218,76 @@ private function sendNotification(ExecuteTaskEvent $event): int
}

/**
* Returns the Super Users email information. If you provide a comma separated $email list
* we will check that these emails do belong to Super Users and that they have not blocked
* system emails.
* Returns all Email recipients: super users and the users of email receiver groups
*
* @param null|string $email A list of Super Users to email
* @return array The list of email recipients
*
* @return array The list of Super User emails
*
* @since 3.5
* @since __DEPLOY_VERSION__
*/
private function getSuperUsers($email = null)
private function getEmailReceivers(): array
{
$db = $this->getDatabase();
$emails = [];
$emailReceivers = [];

// Convert the email list to an array
if (!empty($email)) {
$temp = explode(',', $email);
// Find groups with core.admin rights (super users)
$superUserGroups = $this->getSuperUserGroups();

foreach ($temp as $entry) {
$emails[] = trim($entry);
}
// Get User group ids from input field, if empty fallback to super user groups
$params = ComponentHelper::getParams('com_joomlaupdate');
$emailGroups = $params->get('email_groups', $superUserGroups);

$emails = array_unique($emails);
if (!\is_array($emailGroups)) {
$emailGroups = ArrayHelper::toInteger(explode(',', $emailGroups));
}

// Get a list of groups which have Super User privileges
$ret = [];
// Make the array unique to avoid multiple queries for the same group
$emailGroups = array_unique($emailGroups);

try {
$table = new Asset($db);
$rootId = $table->getRootId();
$rules = Access::getAssetRules($rootId)->getData();
$rawGroups = $rules['core.admin']->getData();
$groups = [];
// Get the users of all groups in the emailGroups
$usersModel = Factory::getApplication()->bootComponent('com_users')
->getMVCFactory()->createModel('Users', 'Administrator');
$usersModel->setState('filter.state', (int) 0);

if (empty($rawGroups)) {
return $ret;
foreach ($emailGroups as $group) {
// Skip invalid group ids. Group ids are always numeric and > 0
if (!is_numeric($group) || $group < 1) {
continue;
}

foreach ($rawGroups as $g => $enabled) {
if ($enabled) {
$groups[] = $g;
}
$usersModel->setState('filter.group_id', $group);

$usersInGroup = $usersModel->getItems();
if (empty($usersInGroup)) {
continue;
}

if (empty($groups)) {
return $ret;
// Users can be in more than one group. Accept only one entry
foreach ($usersInGroup as $user) {
if (MailHelper::isEmailAddress($user->email) && $user->sendEmail === 1) {
$emailReceivers[$user->id] ??= $user;
}
}
} catch (\Exception $exc) {
return $ret;
}

// Get the user IDs of users belonging to the SA groups
try {
$query = $db->getQuery(true)
->select($db->quoteName('user_id'))
->from($db->quoteName('#__user_usergroup_map'))
->whereIn($db->quoteName('group_id'), $groups);

$db->setQuery($query);
$userIDs = $db->loadColumn(0);
return $emailReceivers;
}

if (empty($userIDs)) {
return $ret;
}
} catch (\Exception $exc) {
return $ret;
}
/**
* Returns all Super Users
*
* @return array The list of super user groups.
*
* @since __DEPLOY_VERSION__
*/
private function getSuperUserGroups(): array
{
$groups = UserGroupsHelper::getInstance()->getAll();
$ret = [];

// Get the user information for the Super Administrator users
try {
$query = $db->getQuery(true)
->select($db->quoteName(['id', 'username', 'email']))
->from($db->quoteName('#__users'))
->whereIn($db->quoteName('id'), $userIDs)
->where($db->quoteName('block') . ' = 0')
->where($db->quoteName('sendEmail') . ' = 1');

if (!empty($emails)) {
$lowerCaseEmails = array_map('strtolower', $emails);
$query->whereIn('LOWER(' . $db->quoteName('email') . ')', $lowerCaseEmails, ParameterType::STRING);
// Find groups with core.admin rights (super users)
foreach ($groups as $group) {
if (Access::checkGroup($group->id, 'core.admin')) {
$ret[] = $group->id;
}

$db->setQuery($query);
$ret = $db->loadObjectList();
} catch (\Exception) {
return $ret;
}

return $ret;
Expand Down
Loading