title sort via accent-stripped dashed slug (fixes names, keeps numbers) (v1.9.1)

This commit is contained in:
2026-07-13 14:38:31 -03:00
parent f9a7637e44
commit 8be9442cb7
3 changed files with 42 additions and 6 deletions

View File

@@ -112,9 +112,16 @@ class OrganonSortHelper extends Base
}
/**
* Number-aware title sort (strnatcasecmp, so "Task 2" precedes "Task 10"), then write positions.
* Mirrors the native reorder scope (all tasks in the column+swimlane, no status filter). Core's
* TaskReorderModel::reorderTasks is protected, so the 3-line position write is replicated here.
* Title sort, then write positions. Mirrors the native reorder scope (all tasks in the
* column+swimlane, no status filter). Core's TaskReorderModel::reorderTasks is protected, so the
* 3-line position write is replicated here.
*
* Each title is reduced to a comparison slug -- lowercased, accent-stripped, spaces -> dashes --
* then compared with strnatcasecmp. The dash is deliberate: strnatcasecmp SKIPS whitespace, so a
* plain space would make "Luiz Eduardo" sort after "Luiza..." (it would compare "LuizEduardo" vs
* "Luiza..."); a dash is not whitespace, so the separator is honoured, while strnatcasecmp still
* groups digit runs ("Task 2" < "Task 10"). The result is case-insensitive, accent-insensitive,
* whitespace-correct and number-aware.
*/
private function reorderByTitle($project_id, $swimlane_id, $column_id, $direction)
{
@@ -125,8 +132,13 @@ class OrganonSortHelper extends Base
->eq('column_id', $column_id)
->findAll();
foreach ($rows as &$row) {
$row['sortkey'] = str_replace(' ', '-', $this->stripAccents(mb_strtolower((string) $row['title'], 'UTF-8')));
}
unset($row);
usort($rows, function ($a, $b) use ($direction) {
$cmp = strnatcasecmp((string) $a['title'], (string) $b['title']);
$cmp = strnatcasecmp($a['sortkey'], $b['sortkey']);
return $direction === 'desc' ? -$cmp : $cmp;
});
@@ -137,4 +149,28 @@ class OrganonSortHelper extends Base
$position++;
}
}
/**
* Flatten a string for sorting: strip accents to their base letter so accented names sort by that
* base (Avila near A, not after Z). Uses ext-intl Normalizer when available (deterministic and
* locale-independent), falling back to iconv //TRANSLIT (locale-dependent), then the raw string
* (still sorts, just accent-naive). Case is already lowered by the caller.
*
* @param string $s
* @return string
*/
private function stripAccents($s)
{
if (class_exists('Normalizer')) {
$decomposed = \Normalizer::normalize($s, \Normalizer::FORM_D);
if ($decomposed !== false) {
return preg_replace('/\p{Mn}/u', '', $decomposed);
}
}
$translit = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s);
return $translit !== false ? $translit : $s;
}
}

View File

@@ -162,7 +162,7 @@ class Plugin extends Base
public function getPluginVersion()
{
return '1.9.0';
return '1.9.1';
}
public function getPluginHomepage()

View File

@@ -1 +1 @@
OrganonTweaks v1.9.0
OrganonTweaks v1.9.1