Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
0a5e220
resolve alias conflicts when duplicating filters
travisrisner Sep 11, 2025
2171c28
resolve codestyle errors
travisrisner Sep 11, 2025
95a2471
Merge branch 'joomla:5.3-dev' into 5.3-search-filter-copy-bug
travisrisner Sep 12, 2025
8d08537
Merge branch '5.3-dev' into 5.3-search-filter-copy-bug
travisrisner Sep 16, 2025
38af09e
Merge branch '5.3-dev' into 5.3-search-filter-copy-bug
richard67 Sep 18, 2025
60deaec
convert query to prepared statement
travisrisner Sep 18, 2025
ed98e28
remove unnecessary items
travisrisner Sep 18, 2025
25c447a
Merge branch '5.3-dev' into 5.3-search-filter-copy-bug
richard67 Sep 27, 2025
587a640
Merge branch 'joomla:5.3-dev' into 5.3-search-filter-copy-bug
travisrisner Oct 10, 2025
2a19b3e
increment filter title as well
travisrisner Oct 10, 2025
62a693a
Merge branch '5.4-dev' into 5.3-search-filter-copy-bug
richard67 Oct 15, 2025
196ef08
Merge branch 'joomla:5.4-dev' into 5.3-search-filter-copy-bug
travisrisner Oct 17, 2025
e35e259
add alias to list view
travisrisner Oct 17, 2025
c6dcbe2
cs
travisrisner Oct 17, 2025
7093f24
Update administrator/components/com_finder/src/Model/FilterModel.php
travisrisner Oct 17, 2025
7a4917d
Update administrator/components/com_finder/src/Model/FilterModel.php
travisrisner Oct 17, 2025
bc8a30e
Update administrator/components/com_finder/src/Model/FilterModel.php
travisrisner Oct 17, 2025
7bf3608
Update administrator/components/com_finder/src/Model/FilterModel.php
travisrisner Oct 17, 2025
0ee7369
Merge branch '5.4-dev' into 5.3-search-filter-copy-bug
muhme Nov 6, 2025
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
135 changes: 135 additions & 0 deletions administrator/components/com_finder/src/Model/FilterModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
namespace Joomla\Component\Finder\Administrator\Model;

use Joomla\CMS\Factory;
use Joomla\CMS\Filter\OutputFilter;
use Joomla\CMS\Form\Form;
use Joomla\CMS\MVC\Model\AdminModel;
use Joomla\Component\Finder\Administrator\Table\FilterTable;
use Joomla\String\StringHelper;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
Expand Down Expand Up @@ -151,4 +153,137 @@ public function getTotal()

return $db->setQuery($query)->loadResult();
}

/**
* Method to save the form data.
*
* Overrides the parent to correctly handle the 'save2copy' task for Finder filters.
*
* @param array $data The form data.
*
* @return boolean True on success, false on failure.
*
* @since __DEPLOY_VERSION__
*/
public function save($data)
{
$app = Factory::getApplication();
$task = $app->getInput()->get('task', '', 'cmd');

if ($task === 'save2copy') {
$data['filter_id'] = 0;

$title = trim((string) ($data['title'] ?? ''));
$alias = trim((string) ($data['alias'] ?? ''));

if ($alias === '') {
$alias = OutputFilter::stringURLSafe($title);
}

// Generate unique title + alias
list($title, $alias) = $this->generateNewTitleAndAlias($title, $alias);

$data['title'] = $title;
$data['alias'] = $alias;
}

return parent::save($data);
}

/**
* Generate a new unique title and alias for a copied filter.
* Follows the same logic as Joomla's core content models.
*
* @param string $title The original title.
* @param string $alias The original alias.
*
* @return array Array with [newTitle, newAlias].
*
* @since __DEPLOY_VERSION__
*/
protected function generateNewTitleAndAlias(string $title, string $alias): array
{
$db = $this->getDatabase();

if (preg_match('/^(.*?)(?:\s\((\d+)\))?$/', $title, $matches)) {
$baseTitle = trim($matches[1]);
} else {
$baseTitle = trim($title);
}

$baseAlias = trim($alias ?: OutputFilter::stringURLSafe($title));

$likeTitle = $db->quote($db->escape($baseTitle, true) . '%', false);

$query = $db->getQuery(true)
->select($db->quoteName('title'))
->from($db->quoteName('#__finder_filters'))
->where($db->quoteName('title') . ' LIKE ' . $likeTitle);

$existingTitles = $db->setQuery($query)->loadColumn();

$maxNum = 0;
foreach ($existingTitles as $existing) {
if (preg_match('/^\Q' . $baseTitle . '\E(?:\s\((\d+)\))?$/', $existing, $matches)) {
$num = isset($matches[1]) ? (int) $matches[1] : 1;
if ($num > $maxNum) {
$maxNum = $num;
}
}
}

$nextNum = $maxNum + 1;

$newTitle = $baseTitle;
if ($nextNum > 1) {
$newTitle .= ' (' . $nextNum . ')';
}

// Build a unique alias
$newAlias = $this->getUniqueAlias($baseAlias);

return [$newTitle, $newAlias];
}

/**
* Ensure a unique alias in the table by incrementing with dash style.
*
*
* @param string $base The starting alias (already URL-safe).
*
* @return string A unique alias.
*
* @since __DEPLOY_VERSION__
*/
protected function getUniqueAlias(string $base): string
{
$alias = $base !== '' ? $base : OutputFilter::stringURLSafe(uniqid('filter-', true));

while ($this->aliasExists($alias)) {
$alias = StringHelper::increment($alias, 'dash');
}

return $alias;
}

/**
* Check whether an alias exists in the table.
*
* @param string $alias The alias to test.
*
* @return boolean True if it exists, false otherwise.
*
* @since __DEPLOY_VERSION__
*/
protected function aliasExists(string $alias): bool
{
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select('COUNT(*)')
->from($db->quoteName('#__finder_filters'))
->where($db->quoteName('alias') . ' = :alias')
->bind(':alias', $alias);

return (int) $db->setQuery($query)->loadResult() > 0;
}
}
6 changes: 6 additions & 0 deletions administrator/components/com_finder/tmpl/filters/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
<th scope="col">
<?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
</th>
<th scope="col">
<?php echo HTMLHelper::_('searchtools.sort', 'JALIAS', 'a.alias', $listDirn, $listOrder); ?>
</th>
<th scope="col" class="w-10 d-none d-md-table-cell">
<?php echo HTMLHelper::_('searchtools.sort', 'COM_FINDER_HEADING_CREATED_BY', 'a.created_by_alias', $listDirn, $listOrder); ?>
</th>
Expand Down Expand Up @@ -103,6 +106,9 @@
<?php echo $escapedTitle; ?>
<?php endif; ?>
</th>
<td class="d-none d-md-table-cell">
<?php echo $item->alias; ?>
</td>
<td class="d-none d-md-table-cell">
<?php echo $item->created_by_alias ?: $item->user_name; ?>
</td>
Expand Down