Skip to content

Commit 83cef82

Browse files
The code has been rewritten from scratch
1 parent ec9a67f commit 83cef82

15 files changed

Lines changed: 431 additions & 84 deletions

File tree

src/Groups/Group.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use DragonCode\SizeSorter\Enums\GroupEnum;
88
use Illuminate\Support\Str;
9+
use Illuminate\Support\Stringable;
910

1011
use function implode;
1112

@@ -24,6 +25,16 @@ public static function detect(string $value): bool
2425

2526
public static function normalize(mixed $value, int|string $key): string
2627
{
27-
return implode(static::Delimiter, [static::$group->value, $key, $value]);
28+
return implode(static::Delimiter, [static::$group->value, $key, static::prepare($value)]);
29+
}
30+
31+
public static function value(string $key): Stringable
32+
{
33+
return Str::of($key)->afterLast(static::Delimiter);
34+
}
35+
36+
protected static function prepare(mixed $value): string
37+
{
38+
return $value;
2839
}
2940
}

src/Groups/LetterClothingGroup.php

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,50 +7,61 @@
77
use DragonCode\SizeSorter\Enums\GroupEnum;
88
use Illuminate\Support\Str;
99

10-
use function array_keys;
11-
use function array_values;
12-
use function preg_replace_callback;
13-
use function str_repeat;
10+
use function in_array;
11+
use function preg_match;
12+
use function strlen;
1413

1514
class LetterClothingGroup extends Group
1615
{
1716
protected static GroupEnum $group = GroupEnum::LetterClothingSize;
1817

1918
protected static array|string $pattern = '/^(?\'size\'(([2-9]?[x]{1,9}[sml]{1})|([sml])))(_(?1))?$/';
2019

21-
public static function normalize(mixed $value, int|string $key): string
20+
protected static array $multiplier = [
21+
's' => 100,
22+
'm' => 1000,
23+
'l' => 10000,
24+
];
25+
26+
protected static function prepare(mixed $value): string
27+
{
28+
return Str::of($value)
29+
->explode('_')
30+
->map(static fn (mixed $value) => static::convert($value))
31+
->implode('_');
32+
}
33+
34+
protected static function convert(mixed $value): string
2235
{
23-
if (! static::containsNumber($value)) {
24-
return parent::normalize($value . '0', $key);
36+
if (in_array($value, ['s', 'm', 'l'])) {
37+
return (string) static::multiply($value, 1);
2538
}
2639

27-
$matches = static::match($value);
40+
if (preg_match('/^(x+)?s$/', $value, $matches)) {
41+
$count = isset($matches[1]) ? strlen($matches[1]) : 1;
2842

29-
$value = Str::replace(
30-
array_keys($matches),
31-
array_values($matches),
32-
$value
33-
);
43+
return (string) static::multiply('s', $count);
44+
}
3445

35-
return parent::normalize($value . '1', $key);
36-
}
46+
if (preg_match('/^(\d+)xs$/', $value, $matches)) {
47+
return (string) static::multiply('s', (int) $matches[1], 1);
48+
}
3749

38-
protected static function containsNumber(string $value): bool
39-
{
40-
return Str::isMatch('/\d/', $value);
50+
if (preg_match('/^(x+)l$/', $value, $matches)) {
51+
$count = strlen($matches[1]);
52+
53+
return (string) static::multiply('l', $count);
54+
}
55+
56+
if (preg_match('/^(\d+)xl$/', $value, $matches)) {
57+
return (string) static::multiply('l', (int) $matches[1], 1);
58+
}
59+
60+
return '0';
4161
}
4262

43-
protected static function match(string $value): array
63+
protected static function multiply(string $key, int $count, int $plus = 0): int
4464
{
45-
return Str::of($value)
46-
->matchAll('/\dx/')
47-
->mapWithKeys(static function (string $item) {
48-
$replace = preg_replace_callback('/(\d)x/', function (array $matches) {
49-
return str_repeat('x', (int) $matches[1]);
50-
}, $item);
51-
52-
return [$item => $replace];
53-
})
54-
->all();
65+
return static::$multiplier[$key] * $count + $plus;
5566
}
5667
}

src/Normalizers/KeyNormalizer.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ public static function normalize(mixed $value): string
2626
return (string) $value;
2727
}
2828

29-
return Cache::remember($value, static fn () => Str::of($value)
30-
->replaceMatches('/[\W_\s]+/u', ' ')
31-
->trim()
32-
->slug('_')
33-
->toString()
29+
return Cache::remember(
30+
$value,
31+
static fn () => Str::of($value)
32+
->replaceMatches('/[\W_\s]+/u', ' ')
33+
->trim()
34+
->slug('_')
35+
->toString()
3436
);
3537
}
3638
}

src/Services/Processor.php

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,45 @@
77
use Closure;
88
use DragonCode\SizeSorter\Enums\GroupEnum;
99
use DragonCode\SizeSorter\Groups\Group;
10-
use DragonCode\SizeSorter\Sorters\CharSorter;
1110
use DragonCode\SizeSorter\Support\Map;
1211
use Illuminate\Support\Collection;
1312
use Illuminate\Support\Str;
1413

1514
class Processor
1615
{
16+
public function __construct(
17+
protected Sort $sort = new Sort
18+
) {}
19+
1720
public function run(Collection $items, Closure $column, array $orderBy): Collection
21+
{
22+
$sorted = $this->sortItems($items, $column);
23+
24+
$map = $this->sortGroups($sorted, $orderBy);
25+
26+
return Map::apply($items, $map);
27+
}
28+
29+
protected function sortItems(Collection $items, Closure $column): Collection
1830
{
1931
return $this->map($items, $column)
2032
->groupBy(fn (mixed $value, string $key) => $this->detectGroup($key), true)
21-
->map(fn (Collection $values, int $group) => $values->sortKeysUsing(
22-
$this->sort($group)
23-
))
24-
->dd();
33+
->map(fn (Collection $values, int $group) => $this->sortPerGroup($values, $group));
34+
}
35+
36+
protected function sortGroups(Collection $items, array $orderBy): Collection
37+
{
38+
return Collection::make($orderBy)->map(
39+
fn (GroupEnum $group) => $items->get($group->value)
40+
)->collapseWithKeys();
2541
}
2642

27-
protected function sort(int $group): Closure
43+
protected function sortPerGroup(Collection $items, int $group): Collection
2844
{
2945
return match ($group) {
30-
GroupEnum::LetterClothingSize->value => CharSorter::callback(),
31-
GroupEnum::ClothesAndShoes->value => 2,
32-
GroupEnum::BraSize->value => 3,
33-
GroupEnum::OverallDimensions->value => 4,
34-
GroupEnum::OtherSizes->value => 5,
46+
GroupEnum::LetterClothingSize->value,
47+
GroupEnum::ClothesAndShoes->value => $this->sort->byNumber($items),
48+
default => $this->sort->byAlphabet($items),
3549
};
3650
}
3751

src/Services/Sort.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DragonCode\SizeSorter\Services;
6+
7+
use DragonCode\SizeSorter\Sorters\NumberSorter;
8+
use Illuminate\Support\Collection;
9+
10+
class Sort
11+
{
12+
public function byNumber(Collection $items): Collection
13+
{
14+
return $items->sortKeysUsing(
15+
NumberSorter::callback()
16+
);
17+
}
18+
19+
public function byAlphabet(Collection $items): Collection
20+
{
21+
return $items->sortKeys();
22+
}
23+
}

src/SizeSorter.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
class SizeSorter
1616
{
17-
protected string|Closure $column = 'value';
17+
protected Closure|string $column = 'value';
1818

1919
protected ?iterable $orderBy = null;
2020

@@ -25,10 +25,10 @@ public static function items(iterable $items): static
2525

2626
public function __construct(
2727
protected readonly iterable $items,
28-
protected readonly Processor $processor = new Processor(),
28+
protected readonly Processor $processor = new Processor,
2929
) {}
3030

31-
public function column(string|Closure $name): static
31+
public function column(Closure|string $name): static
3232
{
3333
$this->column = $name;
3434

@@ -37,11 +37,14 @@ public function column(string|Closure $name): static
3737

3838
/**
3939
* @param GroupEnum[]|null $order
40-
*
4140
* @return $this
4241
*/
4342
public function orderBy(?iterable $order): static
4443
{
44+
if (empty($order)) {
45+
return $this;
46+
}
47+
4548
Validator::ensure($order, GroupEnum::class);
4649

4750
$this->orderBy = $order;

src/Sorters/ArrowSorter.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@
44

55
namespace DragonCode\SizeSorter\Sorters;
66

7+
use Closure;
8+
79
class ArrowSorter extends Sorter
810
{
11+
public static function callback(int $arrow = 1): Closure
12+
{
13+
return static function (mixed $a, mixed $b) use ($arrow) {
14+
if ($a === $b) {
15+
return 0;
16+
}
17+
18+
return $a < $b ? -1 * $arrow : $arrow;
19+
};
20+
}
921
}

src/Sorters/CharSorter.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@
44

55
namespace DragonCode\SizeSorter\Sorters;
66

7+
use Closure;
8+
use Illuminate\Support\Str;
9+
710
class CharSorter extends Sorter
811
{
12+
public static function callback(int $arrow = 1): Closure
13+
{
14+
return static function (mixed $a, mixed $b) use ($arrow) {
15+
$arrow = static::contains($a, '_') ? -1 : 1;
16+
17+
return ArrowSorter::callback($arrow)($a, $b);
18+
};
19+
}
20+
21+
protected static function contains(string $haystack, string $needle): bool
22+
{
23+
return Str::contains($haystack, $needle);
24+
}
925
}

src/Sorters/NumberSorter.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,40 @@
44

55
namespace DragonCode\SizeSorter\Sorters;
66

7+
use Closure;
8+
use DragonCode\SizeSorter\Groups\Group;
9+
use Illuminate\Support\Str;
10+
711
class NumberSorter extends Sorter
812
{
13+
public static function callback(int $arrow = 1): Closure
14+
{
15+
return static function (mixed $a, mixed $b) use ($arrow) {
16+
$a = static::extract($a);
17+
$b = static::extract($b);
18+
19+
if ($a[0] !== $b[0]) {
20+
return $a[0] < $b[0] ? -1 * $arrow : $arrow;
21+
}
22+
23+
if (! isset($a[1], $b[1])) {
24+
return 0;
25+
}
26+
27+
if ($a[1] === $b[1]) {
28+
return 0;
29+
}
30+
31+
return $a[1] < $b[1] ? -1 * $arrow : $arrow;
32+
};
33+
}
34+
35+
protected static function extract(int|string $value): array
36+
{
37+
return Str::of($value)
38+
->afterLast(Group::Delimiter)
39+
->explode('_')
40+
->map(static fn (int|string $value) => (int) $value)
41+
->all();
42+
}
943
}

src/Sorters/Sorter.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace DragonCode\SizeSorter\Sorters;
66

7+
use Closure;
8+
79
abstract class Sorter
810
{
11+
abstract public static function callback(int $arrow = 1): Closure;
912
}

0 commit comments

Comments
 (0)