Skip to content

Commit 7fc5fdf

Browse files
authored
[6.0] Upmerges - 2025-08-31
Merge pull request #46016 from Bodge-IT/upmerges/2025-08-31
2 parents 203ba0c + 88d9881 commit 7fc5fdf

File tree

8 files changed

+100
-97
lines changed

8 files changed

+100
-97
lines changed

administrator/components/com_content/forms/article.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
translateformat="true"
168168
showtime="true"
169169
filter="user_utc"
170+
showon="featured:1"
170171
/>
171172

172173
<field
@@ -176,6 +177,7 @@
176177
translateformat="true"
177178
showtime="true"
178179
filter="user_utc"
180+
showon="featured:1"
179181
/>
180182

181183
<field

administrator/components/com_joomlaupdate/config.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,5 +121,15 @@
121121
class="alert alert-info w-100"
122122
showon="updatesource!:default[OR]minimum_stability!:4"
123123
/>
124+
<field
125+
name="automated_updates_email_groups"
126+
type="usergrouplist"
127+
label="COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_UPDATE_EMAIL_LABEL"
128+
description="COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_UPDATE_EMAIL_DESCRIPTION"
129+
checksuperusergroup="0"
130+
multiple="true"
131+
layout="joomla.form.field.list-fancy-select"
132+
showon="updatesource:default[AND]minimum_stability:4[AND]autoupdate:1"
133+
/>
124134
</fieldset>
125135
</config>

administrator/components/com_joomlaupdate/src/Model/NotificationModel.php

Lines changed: 63 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
use Joomla\CMS\Access\Access;
1414
use Joomla\CMS\Component\ComponentHelper;
1515
use Joomla\CMS\Factory;
16+
use Joomla\CMS\Helper\UserGroupsHelper;
1617
use Joomla\CMS\Mail\MailHelper;
1718
use Joomla\CMS\Mail\MailTemplate;
1819
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
19-
use Joomla\CMS\Table\Asset;
2020
use Joomla\CMS\Uri\Uri;
2121
use Joomla\CMS\Version;
22-
use Joomla\Database\ParameterType;
2322
use Joomla\Registry\Registry;
23+
use Joomla\Utilities\ArrayHelper;
2424

2525
// phpcs:disable PSR1.Files.SideEffects
2626
\defined('_JEXEC') or die;
@@ -49,11 +49,26 @@ public function sendNotification($type, $oldVersion, $newVersion): void
4949
{
5050
$params = ComponentHelper::getParams('com_joomlaupdate');
5151

52-
// Send a notification to all super users
53-
$superUsers = $this->getSuperUsers();
52+
// Superusergroups as fallback
53+
$superUserGroups = $this->getSuperUserGroups();
5454

55-
if (empty($superUsers)) {
56-
throw new \RuntimeException();
55+
if (!\is_array($superUserGroups)) {
56+
$emailGroups = ArrayHelper::toInteger(explode(',', $superUserGroups));
57+
}
58+
59+
// User groups from input field
60+
$emailGroups = $params->get('automated_updates_email_groups', $superUserGroups, 'array');
61+
62+
if (!\is_array($emailGroups)) {
63+
$emailGroups = ArrayHelper::toInteger(explode(',', $emailGroups));
64+
}
65+
66+
// Get all users in these groups who can receive emails
67+
$emailReceivers = $this->getEmailReceivers($emailGroups);
68+
69+
// If no email receivers are found, we use superusergroups as fallback
70+
if (empty($emailReceivers)) {
71+
$emailReceivers = $this->getEmailReceivers($superUserGroups);
5772
}
5873

5974
$app = Factory::getApplication();
@@ -67,110 +82,77 @@ public function sendNotification($type, $oldVersion, $newVersion): void
6782
'url' => Uri::root(),
6883
];
6984

70-
// Send the emails to the Super Users
71-
foreach ($superUsers as $superUser) {
72-
$params = new Registry($superUser->params);
85+
// Send emails to all receivers
86+
foreach ($emailReceivers as $receiver) {
87+
$params = new Registry($receiver->params);
7388
$jLanguage->load('com_joomlaupdate', JPATH_ADMINISTRATOR, 'en-GB', true, true);
7489
$jLanguage->load('com_joomlaupdate', JPATH_ADMINISTRATOR, $params->get('admin_language', null), true, true);
7590

7691
$mailer = new MailTemplate('com_joomlaupdate.update.' . $type, $jLanguage->getTag());
77-
$mailer->addRecipient($superUser->email);
92+
$mailer->addRecipient($receiver->email);
7893
$mailer->addTemplateData($substitutions);
7994
$mailer->send();
8095
}
8196
}
8297

8398
/**
84-
* Returns the Super Users email information. If you provide a comma separated $email list
85-
* we will check that these emails do belong to Super Users and that they have not blocked
86-
* system emails.
99+
* Returns the email information of receivers. Receiver can be any user who is not disabled.
87100
*
88-
* @param null|string $email A list of Super Users to email
101+
* @param array $emailGroups A list of usergroups to email
89102
*
90-
* @return array The list of Super User emails
103+
* @return array The list of email receivers. Can be empty if no users are found.
91104
*
92105
* @since 5.4.0
93106
*/
94-
private function getSuperUsers($email = null): array
107+
private function getEmailReceivers($emailGroups): array
95108
{
96-
$db = $this->getDatabase();
97-
$emails = [];
98-
99-
// Convert the email list to an array
100-
if (!empty($email)) {
101-
$temp = explode(',', $email);
102-
103-
foreach ($temp as $entry) {
104-
if (!MailHelper::isEmailAddress(trim($entry))) {
105-
continue;
106-
}
107-
108-
$emails[] = trim($entry);
109-
}
110-
111-
$emails = array_unique($emails);
109+
if (empty($emailGroups)) {
110+
return [];
112111
}
113112

114-
// Get a list of groups which have Super User privileges
115-
$ret = [];
113+
$emailReceivers = [];
116114

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

123-
if (empty($rawGroups)) {
124-
return $ret;
125-
}
120+
foreach ($emailGroups as $group) {
121+
$usersModel->setState('filter.group_id', $group);
126122

127-
foreach ($rawGroups as $g => $enabled) {
128-
if ($enabled) {
129-
$groups[] = $g;
130-
}
123+
$usersInGroup = $usersModel->getItems();
124+
if (empty($usersInGroup)) {
125+
continue;
131126
}
132127

133-
if (empty($groups)) {
134-
return $ret;
128+
// Users can be in more than one group. Accept only one entry
129+
foreach ($usersInGroup as $user) {
130+
if (MailHelper::isEmailAddress($user->email) && $user->sendEmail === 1) {
131+
$emailReceivers[$user->id] ??= $user;
132+
}
135133
}
136-
} catch (\Exception $exc) {
137-
return $ret;
138134
}
139135

140-
// Get the user IDs of users belonging to the SA groups
141-
try {
142-
$query = $db->getQuery(true)
143-
->select($db->quoteName('user_id'))
144-
->from($db->quoteName('#__user_usergroup_map'))
145-
->whereIn($db->quoteName('group_id'), $groups);
146-
147-
$db->setQuery($query);
148-
$userIDs = $db->loadColumn(0);
136+
return $emailReceivers;
137+
}
149138

150-
if (empty($userIDs)) {
151-
return $ret;
152-
}
153-
} catch (\Exception $exc) {
154-
return $ret;
155-
}
139+
/**
140+
* Returns all Super Users
141+
*
142+
* @return array The list of super user groups.
143+
*
144+
* @since 5.4.0
145+
*/
146+
private function getSuperUserGroups(): array
147+
{
148+
$groups = UserGroupsHelper::getInstance()->getAll();
149+
$ret = [];
156150

157-
// Get the user information for the Super Administrator users
158-
try {
159-
$query = $db->getQuery(true)
160-
->select($db->quoteName(['id', 'username', 'email', 'params']))
161-
->from($db->quoteName('#__users'))
162-
->whereIn($db->quoteName('id'), $userIDs)
163-
->where($db->quoteName('block') . ' = 0')
164-
->where($db->quoteName('sendEmail') . ' = 1');
165-
166-
if (!empty($emails)) {
167-
$lowerCaseEmails = array_map('strtolower', $emails);
168-
$query->whereIn('LOWER(' . $db->quoteName('email') . ')', $lowerCaseEmails, ParameterType::STRING);
151+
// Find groups with core.admin rights (super users)
152+
foreach ($groups as $group) {
153+
if (Access::checkGroup($group->id, 'core.admin')) {
154+
$ret[] = $group->id;
169155
}
170-
171-
$ret = $db->setQuery($query)->loadObjectList();
172-
} catch (\Exception) {
173-
return $ret;
174156
}
175157

176158
return $ret;

administrator/language/en-GB/com_config.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ COM_CONFIG_FIELD_GZIP_COMPRESSION_LABEL="Gzip Page Compression"
9898
COM_CONFIG_FIELD_HTMLBODY_LABEL="HTML Body"
9999
COM_CONFIG_FIELD_LOADBALANCER_ENABLE_DESC="If your site is behind a load balancer or reverse proxy, enable this setting so that IP addresses and other configurations within Joomla automatically take this into account."
100100
COM_CONFIG_FIELD_LOADBALANCER_ENABLE_LABEL="Behind Load Balancer"
101-
COM_CONFIG_FIELD_LOG_CATEGORIES_DESC="A comma separated list of log categories to include or exclude. Common log categories include but are not limited to: database, databasequery, database-error, deprecated and jerror. If empty, custom logging is disabled."
101+
COM_CONFIG_FIELD_LOG_CATEGORIES_DESC="A comma separated list of log categories to include or exclude. If empty, custom logging is disabled."
102102
COM_CONFIG_FIELD_LOG_CATEGORIES_LABEL="Log Categories"
103103
COM_CONFIG_FIELD_LOG_CATEGORY_MODE_EXCLUDE="Exclude"
104104
COM_CONFIG_FIELD_LOG_CATEGORY_MODE_INCLUDE="Include"

administrator/language/en-GB/com_joomlaupdate.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_DISABLED_LABEL="<span class=\"fa-fw me
1616
COM_JOOMLAUPDATE_CONFIG_AUTOMATED_UPDATES_LABEL="Automated Updates"
1717
COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_DESC="Automatically update Joomla to the latest version when it is available."
1818
COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_LABEL="Automated Update"
19+
COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_UPDATE_EMAIL_DESCRIPTION="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."
20+
COM_JOOMLAUPDATE_CONFIG_AUTOUPDATE_UPDATE_EMAIL_LABEL="Send Email to User Groups"
1921
COM_JOOMLAUPDATE_CONFIG_BACKUPCHECK_DESC="Shows the checkbox to confirm you have taken a backup and you're ready to update in the final step before the update is actually applied."
2022
COM_JOOMLAUPDATE_CONFIG_BACKUPCHECK_LABEL="Confirm Backup Checkbox"
2123
COM_JOOMLAUPDATE_CONFIG_CUSTOMURL_LABEL="Custom URL"

build/media_source/com_associations/js/associations-edit.es6.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Joomla = window.Joomla || {};
2323
};
2424

2525
Joomla.showAssociationMessage = () => {
26-
const associations = document.getElementById('associations');
26+
const associations = document.getElementById('fieldset-associations');
2727

2828
if (associations) {
2929
const html = document.createElement('joomla-alert');

libraries/src/Versioning/VersionableModelTrait.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,16 @@ public function loadHistory(int $historyId)
115115
return false;
116116
}
117117

118-
$rowArray['checked_out'] = $this->getCurrentUser()->id;
119-
$rowArray['checked_out_time'] = (new Date())->toSql();
118+
$table = $this->getTable();
119+
120+
// We set checked_out to the current user
121+
if ($table->hasField('checked_out')) {
122+
$rowArray[$table->getColumnAlias('checked_out')] = $this->getCurrentUser()->id;
123+
}
124+
125+
if ($table->hasField('checked_out_time')) {
126+
$rowArray[$table->getColumnAlias('checked_out_time')] = (new Date())->toSql();
127+
}
120128

121129
// Fix null ordering when restoring history
122130
if (\array_key_exists('ordering', $rowArray) && $rowArray['ordering'] === null) {

plugins/editors-xtd/image/src/Extension/Image.php

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -165,25 +165,24 @@ public function onDisplay($name, $asset, $author)
165165
}
166166

167167
Text::script('JCLOSE');
168-
Text::script('PLG_IMAGE_BUTTON_INSERT');
169-
Text::script('JFIELD_MEDIA_LAZY_LABEL');
170-
Text::script('JFIELD_MEDIA_ALT_LABEL');
171-
Text::script('JFIELD_MEDIA_ALT_CHECK_LABEL');
172168
Text::script('JFIELD_MEDIA_ALT_CHECK_DESC_LABEL');
169+
Text::script('JFIELD_MEDIA_ALT_CHECK_LABEL');
170+
Text::script('JFIELD_MEDIA_ALT_LABEL');
173171
Text::script('JFIELD_MEDIA_CLASS_LABEL');
174-
Text::script('JFIELD_MEDIA_FIGURE_CLASS_LABEL');
175-
Text::script('JFIELD_MEDIA_FIGURE_CAPTION_LABEL');
176-
Text::script('JFIELD_MEDIA_LAZY_LABEL');
177-
Text::script('JFIELD_MEDIA_SUMMARY_LABEL');
178-
Text::script('JFIELD_MEDIA_EMBED_CHECK_DESC_LABEL');
179172
Text::script('JFIELD_MEDIA_DOWNLOAD_CHECK_DESC_LABEL');
180173
Text::script('JFIELD_MEDIA_DOWNLOAD_CHECK_LABEL');
174+
Text::script('JFIELD_MEDIA_DOWNLOAD_FILE');
175+
Text::script('JFIELD_MEDIA_EMBED_CHECK_DESC_LABEL');
181176
Text::script('JFIELD_MEDIA_EMBED_CHECK_LABEL');
182-
Text::script('JFIELD_MEDIA_WIDTH_LABEL');
183-
Text::script('JFIELD_MEDIA_TITLE_LABEL');
177+
Text::script('JFIELD_MEDIA_FIGURE_CAPTION_LABEL');
178+
Text::script('JFIELD_MEDIA_FIGURE_CLASS_LABEL');
184179
Text::script('JFIELD_MEDIA_HEIGHT_LABEL');
180+
Text::script('JFIELD_MEDIA_LAZY_LABEL');
181+
Text::script('JFIELD_MEDIA_SUMMARY_LABEL');
182+
Text::script('JFIELD_MEDIA_TITLE_LABEL');
185183
Text::script('JFIELD_MEDIA_UNSUPPORTED');
186-
Text::script('JFIELD_MEDIA_DOWNLOAD_FILE');
184+
Text::script('JFIELD_MEDIA_WIDTH_LABEL');
185+
Text::script('PLG_IMAGE_BUTTON_INSERT');
187186

188187
$link = 'index.php?option=com_media&view=media&tmpl=component&e_name=' . $name . '&asset=' . $asset . '&mediatypes=0,1,2,3' . '&author=' . $author;
189188

0 commit comments

Comments
 (0)