Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
100.00% |
21 / 21 |
|
100.00% |
2 / 2 |
CRAP | |
100.00% |
1 / 1 |
| Sort | |
100.00% |
21 / 21 |
|
100.00% |
2 / 2 |
13 | |
100.00% |
1 / 1 |
| __construct | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
8 | |||
| order | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
5 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Cosray\Collection; |
| 6 | |
| 7 | use Cosray\Exception\RuntimeException; |
| 8 | use Cosray\Finder\Order; |
| 9 | use Cosray\Finder\SortField; |
| 10 | |
| 11 | final readonly class Sort |
| 12 | { |
| 13 | /** @var non-empty-list<SortField> */ |
| 14 | public array $fields; |
| 15 | public string $direction; |
| 16 | |
| 17 | /** |
| 18 | * @param non-empty-list<string|SortField>|null $fields |
| 19 | * @param bool $default Whether the listing starts in this order |
| 20 | */ |
| 21 | public function __construct( |
| 22 | public string $key, |
| 23 | ?array $fields = null, |
| 24 | string $direction = 'asc', |
| 25 | public bool $default = false, |
| 26 | ) { |
| 27 | if (preg_match('/^[a-zA-Z][a-zA-Z0-9_-]*$/D', $key) !== 1) { |
| 28 | throw new RuntimeException("Invalid collection sort key '{$key}'"); |
| 29 | } |
| 30 | $fields ??= [$key]; |
| 31 | if ($fields === [] || !array_is_list($fields)) { |
| 32 | throw new RuntimeException("Sort '{$key}' needs a non-empty list of fields"); |
| 33 | } |
| 34 | $resolved = []; |
| 35 | foreach ($fields as $field) { |
| 36 | if (!is_string($field) && !$field instanceof SortField) { |
| 37 | throw new RuntimeException("Unsupported field in sort '{$key}'"); |
| 38 | } |
| 39 | $resolved[] = is_string($field) ? SortField::text($field) : $field; |
| 40 | } |
| 41 | $this->fields = $resolved; |
| 42 | $this->direction = new Order($resolved[0], $direction)->direction; |
| 43 | } |
| 44 | |
| 45 | /** @return non-empty-list<Order> */ |
| 46 | public function order(string $direction = ''): array |
| 47 | { |
| 48 | $direction = $direction === '' ? $this->direction : $direction; |
| 49 | $order = []; |
| 50 | $unique = false; |
| 51 | foreach ($this->fields as $field) { |
| 52 | $order[] = new Order($field, $direction); |
| 53 | $unique = $unique || in_array($field->name, ['uid', 'id'], true); |
| 54 | } |
| 55 | if (!$unique) { |
| 56 | $order[] = new Order('uid'); |
| 57 | } |
| 58 | return $order; |
| 59 | } |
| 60 | } |