Skip to content

Commit 5ac2244

Browse files
committed
refactor(EventList): simplify sorting logic with a dedicated comparator
1 parent 1ad2788 commit 5ac2244

File tree

1 file changed

+52
-11
lines changed

1 file changed

+52
-11
lines changed

src/EventsList.php

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
declare(strict_types=1);
23

34
namespace om;
45

@@ -23,12 +24,7 @@ public function getArrayCopy(): array {
2324
* Return sorted EventList (the newest dates are first)
2425
*/
2526
public function sorted(): EventsList {
26-
$this->uasort(static function ($a, $b): int {
27-
if ($a['DTSTART'] === $b['DTSTART']) {
28-
return 0;
29-
}
30-
return ($a['DTSTART'] < $b['DTSTART']) ? -1 : 1;
31-
});
27+
$this->uasort($this->comparator(true));
3228

3329
return $this;
3430
}
@@ -37,14 +33,59 @@ public function sorted(): EventsList {
3733
* Return reversed sorted EventList (the oldest dates are first)
3834
*/
3935
public function reversed(): EventsList {
40-
$this->uasort(static function ($a, $b): int {
41-
if ($a['DTSTART'] === $b['DTSTART']) {
36+
$this->uasort($this->comparator(false));
37+
38+
return $this;
39+
}
40+
41+
/**
42+
* Return a comparator callable for DTSTART values.
43+
* @param bool $ascending When true, sorts ascending (older first) like the original implementation; false inverts order.
44+
*/
45+
private function comparator(bool $ascending): callable {
46+
return function ($a, $b) use ($ascending): int {
47+
$ad = $a['DTSTART'] ?? null;
48+
$bd = $b['DTSTART'] ?? null;
49+
50+
// both equal (including both null)
51+
if ($ad === $bd) {
4252
return 0;
4353
}
44-
return ($a['DTSTART'] > $b['DTSTART']) ? -1 : 1;
45-
});
4654

47-
return $this;
55+
// decide ordering for nulls: nulls sort last
56+
if ($ad === null) {
57+
return 1;
58+
}
59+
if ($bd === null) {
60+
return -1;
61+
}
62+
63+
$at = $this->dtTimestamp($ad);
64+
$bt = $this->dtTimestamp($bd);
65+
66+
if ($at === $bt) {
67+
return 0;
68+
}
69+
70+
if ($ascending) {
71+
return ($at < $bt) ? -1 : 1;
72+
}
73+
return ($at > $bt) ? -1 : 1;
74+
};
75+
}
76+
77+
/**
78+
* Normalize a DTSTART value to an integer timestamp for stable comparisons.
79+
*/
80+
private function dtTimestamp(mixed $value): int {
81+
if ($value instanceof \DateTimeInterface) {
82+
return $value->getTimestamp();
83+
}
84+
if (is_int($value) || is_float($value) || is_numeric($value)) {
85+
return (int) $value;
86+
}
87+
$ts = strtotime((string) $value);
88+
return $ts === false ? 0 : $ts;
4889
}
4990

5091
}

0 commit comments

Comments
 (0)