Skip to content

Commit bda2a93

Browse files
authored
[6.0] Upmerges - 2025-11-11
Merge pull request joomla#46437 from Bodge-IT/upmerges/2025-11-11
2 parents 2d70f80 + c6b74e3 commit bda2a93

File tree

23 files changed

+269
-50
lines changed

23 files changed

+269
-50
lines changed

administrator/components/com_finder/src/Indexer/Indexer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ public function index($item, $format = 'html')
370370
} else {
371371
// Update the link.
372372
$entry->link_id = $linkId;
373-
$db->updateObject('#__finder_links', $entry, 'link_id');
373+
$db->updateObject('#__finder_links', $entry, 'link_id', true);
374374
}
375375

376376
// Set up the variables we will need during processing.

administrator/components/com_finder/src/Model/FilterModel.php

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
namespace Joomla\Component\Finder\Administrator\Model;
1212

1313
use Joomla\CMS\Factory;
14+
use Joomla\CMS\Filter\OutputFilter;
1415
use Joomla\CMS\Form\Form;
1516
use Joomla\CMS\MVC\Model\AdminModel;
1617
use Joomla\Component\Finder\Administrator\Table\FilterTable;
18+
use Joomla\String\StringHelper;
1719

1820
// phpcs:disable PSR1.Files.SideEffects
1921
\defined('_JEXEC') or die;
@@ -149,4 +151,137 @@ public function getTotal()
149151

150152
return $db->setQuery($query)->loadResult();
151153
}
154+
155+
/**
156+
* Method to save the form data.
157+
*
158+
* Overrides the parent to correctly handle the 'save2copy' task for Finder filters.
159+
*
160+
* @param array $data The form data.
161+
*
162+
* @return boolean True on success, false on failure.
163+
*
164+
* @since __DEPLOY_VERSION__
165+
*/
166+
public function save($data)
167+
{
168+
$app = Factory::getApplication();
169+
$task = $app->getInput()->get('task', '', 'cmd');
170+
171+
if ($task === 'save2copy') {
172+
$data['filter_id'] = 0;
173+
174+
$title = trim((string) ($data['title'] ?? ''));
175+
$alias = trim((string) ($data['alias'] ?? ''));
176+
177+
if ($alias === '') {
178+
$alias = OutputFilter::stringURLSafe($title);
179+
}
180+
181+
// Generate unique title + alias
182+
list($title, $alias) = $this->generateNewTitleAndAlias($title, $alias);
183+
184+
$data['title'] = $title;
185+
$data['alias'] = $alias;
186+
}
187+
188+
return parent::save($data);
189+
}
190+
191+
/**
192+
* Generate a new unique title and alias for a copied filter.
193+
* Follows the same logic as Joomla's core content models.
194+
*
195+
* @param string $title The original title.
196+
* @param string $alias The original alias.
197+
*
198+
* @return array Array with [newTitle, newAlias].
199+
*
200+
* @since __DEPLOY_VERSION__
201+
*/
202+
protected function generateNewTitleAndAlias(string $title, string $alias): array
203+
{
204+
$db = $this->getDatabase();
205+
206+
if (preg_match('/^(.*?)(?:\s\((\d+)\))?$/', $title, $matches)) {
207+
$baseTitle = trim($matches[1]);
208+
} else {
209+
$baseTitle = trim($title);
210+
}
211+
212+
$baseAlias = trim($alias ?: OutputFilter::stringURLSafe($title));
213+
214+
$likeTitle = $db->quote($db->escape($baseTitle, true) . '%', false);
215+
216+
$query = $db->getQuery(true)
217+
->select($db->quoteName('title'))
218+
->from($db->quoteName('#__finder_filters'))
219+
->where($db->quoteName('title') . ' LIKE ' . $likeTitle);
220+
221+
$existingTitles = $db->setQuery($query)->loadColumn();
222+
223+
$maxNum = 0;
224+
foreach ($existingTitles as $existing) {
225+
if (preg_match('/^\Q' . $baseTitle . '\E(?:\s\((\d+)\))?$/', $existing, $matches)) {
226+
$num = isset($matches[1]) ? (int) $matches[1] : 1;
227+
if ($num > $maxNum) {
228+
$maxNum = $num;
229+
}
230+
}
231+
}
232+
233+
$nextNum = $maxNum + 1;
234+
235+
$newTitle = $baseTitle;
236+
if ($nextNum > 1) {
237+
$newTitle .= ' (' . $nextNum . ')';
238+
}
239+
240+
// Build a unique alias
241+
$newAlias = $this->getUniqueAlias($baseAlias);
242+
243+
return [$newTitle, $newAlias];
244+
}
245+
246+
/**
247+
* Ensure a unique alias in the table by incrementing with dash style.
248+
*
249+
*
250+
* @param string $base The starting alias (already URL-safe).
251+
*
252+
* @return string A unique alias.
253+
*
254+
* @since __DEPLOY_VERSION__
255+
*/
256+
protected function getUniqueAlias(string $base): string
257+
{
258+
$alias = $base !== '' ? $base : OutputFilter::stringURLSafe(uniqid('filter-', true));
259+
260+
while ($this->aliasExists($alias)) {
261+
$alias = StringHelper::increment($alias, 'dash');
262+
}
263+
264+
return $alias;
265+
}
266+
267+
/**
268+
* Check whether an alias exists in the table.
269+
*
270+
* @param string $alias The alias to test.
271+
*
272+
* @return boolean True if it exists, false otherwise.
273+
*
274+
* @since __DEPLOY_VERSION__
275+
*/
276+
protected function aliasExists(string $alias): bool
277+
{
278+
$db = $this->getDatabase();
279+
$query = $db->getQuery(true)
280+
->select('COUNT(*)')
281+
->from($db->quoteName('#__finder_filters'))
282+
->where($db->quoteName('alias') . ' = :alias')
283+
->bind(':alias', $alias);
284+
285+
return (int) $db->setQuery($query)->loadResult() > 0;
286+
}
152287
}

administrator/components/com_finder/tmpl/filters/default.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@
5959
<th scope="col">
6060
<?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
6161
</th>
62+
<th scope="col">
63+
<?php echo HTMLHelper::_('searchtools.sort', 'JALIAS', 'a.alias', $listDirn, $listOrder); ?>
64+
</th>
6265
<th scope="col" class="w-10 d-none d-md-table-cell">
6366
<?php echo HTMLHelper::_('searchtools.sort', 'COM_FINDER_HEADING_CREATED_BY', 'a.created_by_alias', $listDirn, $listOrder); ?>
6467
</th>
@@ -103,6 +106,9 @@
103106
<?php echo $escapedTitle; ?>
104107
<?php endif; ?>
105108
</th>
109+
<td class="d-none d-md-table-cell">
110+
<?php echo $item->alias; ?>
111+
</td>
106112
<td class="d-none d-md-table-cell">
107113
<?php echo $item->created_by_alias ?: $item->user_name; ?>
108114
</td>

administrator/components/com_media/src/Controller/ApiController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,10 @@ private function sendResponse($data = null, int $responseCode = 200)
308308
$this->app->setHeader('Content-Type', 'application/json');
309309

310310
// Set the status code for the response
311-
http_response_code($responseCode);
311+
$this->app->setHeader('status', $responseCode);
312+
313+
// Send headers before sending the data
314+
$this->app->sendHeaders();
312315

313316
// Send the data
314317
echo new JsonResponse($data);

administrator/components/com_users/src/Dispatcher/Dispatcher.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?php
22

33
/**
4-
* @package Joomla.Administrator
5-
* @subpackage com_users
4+
* @package Joomla.Administrator
5+
* @subpackage com_users
66
*
77
* @copyright (C) 2021 Open Source Matters, Inc. <https://www.joomla.org>
8-
* @license GNU General Public License version 2 or later; see LICENSE.txt
8+
* @license GNU General Public License version 2 or later; see LICENSE.txt
99
*/
1010

1111
namespace Joomla\Component\Users\Administrator\Dispatcher;

administrator/components/com_users/src/Helper/Mfa.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?php
22

33
/**
4-
* @package Joomla.Administrator
5-
* @subpackage com_users
4+
* @package Joomla.Administrator
5+
* @subpackage com_users
66
*
7-
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
8-
* @license GNU General Public License version 2 or later; see LICENSE.txt
7+
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
8+
* @license GNU General Public License version 2 or later; see LICENSE.txt
99
*/
1010

1111
namespace Joomla\Component\Users\Administrator\Helper;

administrator/modules/mod_logged/src/Dispatcher/Dispatcher.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
/**
2525
* Dispatcher class for mod_logged
2626
*
27-
* @since __DEPLOY_VERSION_
27+
* @since 5.4.0
2828
*/
2929
class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareInterface
3030
{
@@ -35,7 +35,7 @@ class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareI
3535
*
3636
* @return void
3737
*
38-
* @since __DEPLOY_VERSION_
38+
* @since 5.4.0
3939
*/
4040
public function dispatch()
4141
{
@@ -81,7 +81,7 @@ public function dispatch()
8181
*
8282
* @return array
8383
*
84-
* @since __DEPLOY_VERSION_
84+
* @since 5.4.0
8585
*/
8686
protected function getLayoutData()
8787
{

administrator/templates/atum/error_full.php

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,18 @@
8989
$themeModeAttr = $themeModes[$userColorScheme];
9090
} else {
9191
// Check parameters first (User and Template), then look if we have detected the OS color scheme (if it set to 'os')
92-
$colorScheme = $app->getIdentity()->getParam('colorScheme', $colorScheme);
92+
$colorScheme = $app->getIdentity()?->getParam('colorScheme', $colorScheme) ?? 'os';
9393
$osColorScheme = $colorScheme === 'os' ? $app->getInput()->cookie->get('osColorScheme', '') : '';
9494
$themeModeAttr = ($themeModes[$colorScheme] ?? '') . ($themeModes[$osColorScheme] ?? '');
9595
}
9696
}
9797

98-
// @see administrator/templates/atum/html/layouts/status.php
99-
$statusModules = LayoutHelper::render('status', ['modules' => 'status']);
98+
// The module renderer will not work properly due to incomplete Application initialisation
99+
$renderModules = $app->getIdentity() && $app->getLanguage();
100+
101+
// @see administrator/templates/atum/html/layouts/status.php
102+
$statusModules = $renderModules ? LayoutHelper::render('status', ['modules' => 'status']) : '';
103+
100104
?>
101105
<!DOCTYPE html>
102106
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>"<?php echo $themeModeAttr; ?>>
@@ -122,9 +126,13 @@
122126
<?php echo HTMLHelper::_('image', $logoBrandSmall, $logoBrandSmallAlt, ['class' => 'logo-collapsed', 'loading' => 'eager', 'decoding' => 'async'], false, 0); ?>
123127
</div>
124128
</div>
125-
<jdoc:include type="modules" name="title" />
129+
<?php if ($renderModules) : ?>
130+
<jdoc:include type="modules" name="title" />
131+
<?php endif; ?>
126132
</div>
127-
<?php echo $statusModules; ?>
133+
<?php if ($renderModules) : ?>
134+
<?php echo $statusModules; ?>
135+
<?php endif; ?>
128136
</header>
129137

130138
<div id="wrapper" class="d-flex wrapper<?php echo $hiddenMenu ? '0' : ''; ?>">
@@ -137,14 +145,18 @@
137145
<div id="container-collapse" class="container-collapse"></div>
138146
<div class="row">
139147
<div class="col-md-12">
140-
<jdoc:include type="modules" name="toolbar" style="none" />
148+
<?php if ($renderModules) : ?>
149+
<jdoc:include type="modules" name="toolbar" style="none" />
150+
<?php endif; ?>
141151
</div>
142152
</div>
143153
</div>
144154
<?php endif; ?>
145155
<section id="content" class="content">
146156
<jdoc:include type="message" />
147-
<jdoc:include type="modules" name="top" style="html5" />
157+
<?php if ($renderModules) : ?>
158+
<jdoc:include type="modules" name="top" style="html5" />
159+
<?php endif; ?>
148160
<div class="row">
149161
<div class="col-md-12">
150162
<h1><?php echo Text::_('JERROR_AN_ERROR_HAS_OCCURRED'); ?></h1>
@@ -179,14 +191,14 @@
179191
</p>
180192
</div>
181193

182-
<?php if ($this->countModules('bottom')) : ?>
194+
<?php if ($renderModules && $this->countModules('bottom')) : ?>
183195
<jdoc:include type="modules" name="bottom" style="html5" />
184196
<?php endif; ?>
185197
</div>
186198
</section>
187199
</div>
188200

189-
<?php if (!$hiddenMenu) : ?>
201+
<?php if ($renderModules && !$hiddenMenu) : ?>
190202
<button class="navbar-toggler toggler-burger collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebar-wrapper" aria-controls="sidebar-wrapper" aria-expanded="false" aria-label="<?php echo Text::_('JTOGGLE_SIDEBAR_MENU'); ?>">
191203
<span class="navbar-toggler-icon"></span>
192204
</button>
@@ -204,6 +216,8 @@
204216
</div>
205217
<?php endif; ?>
206218
</div>
207-
<jdoc:include type="modules" name="debug" style="none" />
219+
<?php if ($renderModules) : ?>
220+
<jdoc:include type="modules" name="debug" style="none" />
221+
<?php endif; ?>
208222
</body>
209223
</html>

administrator/templates/atum/error_login.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,17 @@
9393
$themeModeAttr = $themeModes[$userLastMode];
9494
} else {
9595
// Check parameters first (User and Template), then look if we have detected the OS color scheme (if it set to 'os')
96-
$colorScheme = $app->getIdentity()->getParam('colorScheme', $colorScheme);
96+
$colorScheme = $app->getIdentity()?->getParam('colorScheme', $colorScheme) ?? 'os';
9797
$lastMode = $colorScheme === 'os' ? $app->getInput()->cookie->get('osColorScheme', '') : '';
9898
$themeModeAttr = ($colorScheme === 'os' ? $themeModes['os'] : '') . ($themeModes[$lastMode] ?? '');
9999
}
100100
}
101101

102+
// The module renderer will not work properly due to incomplete Application initialisation
103+
$renderModules = $app->getIdentity() && $app->getLanguage();
104+
102105
// @see administrator/templates/atum/html/layouts/status.php
103-
$statusModules = LayoutHelper::render('status', ['modules' => 'status']);
106+
$statusModules = $renderModules ? LayoutHelper::render('status', ['modules' => 'status']) : '';
104107
?>
105108
<!DOCTYPE html>
106109
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>"<?php echo $themeModeAttr; ?>>
@@ -126,7 +129,9 @@
126129
<?php echo HTMLHelper::_('image', $logoBrandSmall, $logoBrandSmallAlt, ['class' => 'logo-collapsed', 'loading' => 'eager', 'decoding' => 'async'], false, 0); ?>
127130
</div>
128131
</div>
129-
<jdoc:include type="modules" name="title" />
132+
<?php if ($renderModules) : ?>
133+
<jdoc:include type="modules" name="title" />
134+
<?php endif; ?>
130135
</div>
131136
<?php echo $statusModules; ?>
132137
</header>
@@ -178,10 +183,14 @@
178183
<a href="<?php echo Uri::root(); ?>"><?php echo Text::_('TPL_ATUM_LOGIN_SIDEBAR_VIEW_WEBSITE'); ?></a>
179184
</div>
180185
<div id="sidebar">
181-
<jdoc:include type="modules" name="sidebar" style="body" />
186+
<?php if ($renderModules) : ?>
187+
<jdoc:include type="modules" name="sidebar" style="body" />
188+
<?php endif; ?>
182189
</div>
183190
</div>
184191
</div>
185-
<jdoc:include type="modules" name="debug" style="none" />
192+
<?php if ($renderModules) : ?>
193+
<jdoc:include type="modules" name="debug" style="none" />
194+
<?php endif; ?>
186195
</body>
187196
</html>

components/com_contact/src/Model/ContactModel.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,10 @@ protected function buildContactExtendedData($contact)
364364
$contact->articles = null;
365365
}
366366

367+
if (empty($contact->user_id)) {
368+
return;
369+
}
370+
367371
// Get the profile information for the linked user
368372
$userModel = $this->bootComponent('com_users')->getMVCFactory()
369373
->createModel('User', 'Administrator', ['ignore_request' => true]);

0 commit comments

Comments
 (0)