title sort via accent-stripped dashed slug (fixes names, keeps numbers) (v1.9.1)
This commit is contained in:
@@ -112,9 +112,16 @@ class OrganonSortHelper extends Base
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number-aware title sort (strnatcasecmp, so "Task 2" precedes "Task 10"), then write positions.
|
* Title sort, then write positions. Mirrors the native reorder scope (all tasks in the
|
||||||
* Mirrors the native reorder scope (all tasks in the column+swimlane, no status filter). Core's
|
* column+swimlane, no status filter). Core's TaskReorderModel::reorderTasks is protected, so the
|
||||||
* TaskReorderModel::reorderTasks is protected, so the 3-line position write is replicated here.
|
* 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)
|
private function reorderByTitle($project_id, $swimlane_id, $column_id, $direction)
|
||||||
{
|
{
|
||||||
@@ -125,8 +132,13 @@ class OrganonSortHelper extends Base
|
|||||||
->eq('column_id', $column_id)
|
->eq('column_id', $column_id)
|
||||||
->findAll();
|
->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) {
|
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;
|
return $direction === 'desc' ? -$cmp : $cmp;
|
||||||
});
|
});
|
||||||
@@ -137,4 +149,28 @@ class OrganonSortHelper extends Base
|
|||||||
$position++;
|
$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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ class Plugin extends Base
|
|||||||
|
|
||||||
public function getPluginVersion()
|
public function getPluginVersion()
|
||||||
{
|
{
|
||||||
return '1.9.0';
|
return '1.9.1';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPluginHomepage()
|
public function getPluginHomepage()
|
||||||
|
|||||||
Reference in New Issue
Block a user