Skip to content

Commit 94dfc1b

Browse files
committed
Add unified sortUsing() method to collections
Simplifies controller sorting logic by introducing a unified sortUsing(method, order) method. Existing sorting methods now delegate to this new method. No breaking changes.
1 parent 985c36e commit 94dfc1b

File tree

6 files changed

+178
-95
lines changed

6 files changed

+178
-95
lines changed

src/Http/Controllers/FilesController.php

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,7 @@ public function index(Request $request)
1818
$sortingMethod = config('log-viewer.defaults.file_sorting_method', SortingMethod::ModifiedTime);
1919
$direction = $this->validateDirection($request->query('direction'));
2020

21-
if ($sortingMethod === SortingMethod::ModifiedTime) {
22-
if ($direction === SortingOrder::Ascending) {
23-
$files = $files->sortByEarliestFirst();
24-
} else {
25-
$files = $files->sortByLatestFirst();
26-
}
27-
28-
} else {
29-
if ($direction === SortingOrder::Ascending) {
30-
$files = $files->sortAlphabeticallyAsc();
31-
} else {
32-
$files = $files->sortAlphabeticallyDesc();
33-
}
34-
}
21+
$files->sortUsing($sortingMethod, $direction);
3522

3623
return LogFileResource::collection($files);
3724
}

src/Http/Controllers/FoldersController.php

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,37 +23,9 @@ public function index(Request $request)
2323
$fileSortingMethod = config('log-viewer.defaults.file_sorting_method', SortingMethod::ModifiedTime);
2424
$fileSortingOrder = $this->validateDirection($request->query('direction'));
2525

26-
if ($sortingMethod === SortingMethod::Alphabetical) {
27-
if ($sortingOrder === SortingOrder::Ascending) {
28-
$folders = $folders->sortAlphabeticallyAsc();
29-
} else {
30-
$folders = $folders->sortAlphabeticallyDesc();
31-
}
32-
} else { // ModifiedTime
33-
if ($fileSortingOrder === SortingOrder::Ascending) {
34-
$folders = $folders->sortByEarliestFirst();
35-
} else {
36-
$folders = $folders->sortByLatestFirst();
37-
}
38-
}
26+
$folders->sortUsing($sortingMethod, $sortingOrder);
3927

40-
// Sort files within folders after sorting folders
41-
$folders->each(function ($folder) use ($fileSortingMethod, $fileSortingOrder) {
42-
if ($fileSortingMethod === SortingMethod::ModifiedTime) {
43-
if ($fileSortingOrder === SortingOrder::Ascending) {
44-
$folder->files()->sortByEarliestFirst();
45-
} else {
46-
$folder->files()->sortByLatestFirst();
47-
}
48-
49-
} else {
50-
if ($fileSortingOrder === SortingOrder::Ascending) {
51-
$folder->files()->sortAlphabeticallyAsc();
52-
} else {
53-
$folder->files()->sortAlphabeticallyDesc();
54-
}
55-
}
56-
});
28+
$folders->each(fn ($folder) => $folder->files()->sortUsing($fileSortingMethod, $fileSortingOrder));
5729

5830
return LogFolderResource::collection($folders->values());
5931
}

src/LogFileCollection.php

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,56 @@
33
namespace Opcodes\LogViewer;
44

55
use Illuminate\Support\Collection;
6+
use Opcodes\LogViewer\Enums\SortingMethod;
7+
use Opcodes\LogViewer\Enums\SortingOrder;
68
use Opcodes\LogViewer\Readers\MultipleLogReader;
79

810
/**
911
* @var LogFile[] $items
1012
*/
1113
class LogFileCollection extends Collection
1214
{
13-
public function sortByEarliestFirst(): self
15+
public function sortUsing(string $method, string $order): self
1416
{
15-
$this->items = $this->sortBy(function (LogFile $file) {
16-
return $file->earliestTimestamp().($file->name ?? '');
17-
}, SORT_NATURAL)->values()->all();
17+
if ($method === SortingMethod::ModifiedTime) {
18+
if ($order === SortingOrder::Ascending) {
19+
$this->items = $this->sortBy(function (LogFile $file) {
20+
return $file->earliestTimestamp().($file->name ?? '');
21+
}, SORT_NATURAL)->values()->all();
22+
} else {
23+
$this->items = $this->sortByDesc(function (LogFile $file) {
24+
return $file->latestTimestamp().($file->name ?? '');
25+
}, SORT_NATURAL)->values()->all();
26+
}
27+
} else {
28+
if ($order === SortingOrder::Ascending) {
29+
$this->items = $this->sortBy('name')->values()->all();
30+
} else {
31+
$this->items = $this->sortByDesc('name')->values()->all();
32+
}
33+
}
1834

1935
return $this;
2036
}
2137

22-
public function sortByLatestFirst(): self
38+
public function sortByEarliestFirst(): self
2339
{
24-
$this->items = $this->sortByDesc(function (LogFile $file) {
25-
return $file->latestTimestamp().($file->name ?? '');
26-
}, SORT_NATURAL)->values()->all();
40+
return $this->sortUsing(SortingMethod::ModifiedTime, SortingOrder::Ascending);
41+
}
2742

28-
return $this;
43+
public function sortByLatestFirst(): self
44+
{
45+
return $this->sortUsing(SortingMethod::ModifiedTime, SortingOrder::Descending);
2946
}
3047

3148
public function sortAlphabeticallyAsc(): self
3249
{
33-
$this->items = $this->sortBy('name')->values()->all();
34-
35-
return $this;
50+
return $this->sortUsing(SortingMethod::Alphabetical, SortingOrder::Ascending);
3651
}
3752

3853
public function sortAlphabeticallyDesc(): self
3954
{
40-
$this->items = $this->sortByDesc('name')->values()->all();
41-
42-
return $this;
55+
return $this->sortUsing(SortingMethod::Alphabetical, SortingOrder::Descending);
4356
}
4457

4558
public function latest(): ?LogFile

src/LogFolderCollection.php

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,40 @@
33
namespace Opcodes\LogViewer;
44

55
use Illuminate\Support\Collection;
6+
use Opcodes\LogViewer\Enums\SortingMethod;
7+
use Opcodes\LogViewer\Enums\SortingOrder;
68

79
class LogFolderCollection extends Collection
810
{
11+
public function sortUsing(string $method, string $order): self
12+
{
13+
if ($method === SortingMethod::ModifiedTime) {
14+
if ($order === SortingOrder::Ascending) {
15+
$this->items = $this->sortBy->earliestTimestamp()->values()->all();
16+
} else {
17+
$this->items = $this->sortByDesc->latestTimestamp()->values()->all();
18+
}
19+
} else {
20+
$this->items = collect($this->items)
21+
->sort(function (LogFolder $a, LogFolder $b) use ($order) {
22+
if ($a->isRoot() && ! $b->isRoot()) {
23+
return -1;
24+
}
25+
if (! $a->isRoot() && $b->isRoot()) {
26+
return 1;
27+
}
28+
29+
return $order === SortingOrder::Ascending
30+
? strcmp($a->cleanPath(), $b->cleanPath())
31+
: strcmp($b->cleanPath(), $a->cleanPath());
32+
})
33+
->values()
34+
->all();
35+
}
36+
37+
return $this;
38+
}
39+
940
public static function fromFiles($files = []): LogFolderCollection
1041
{
1142
return new LogFolderCollection(
@@ -18,16 +49,12 @@ public static function fromFiles($files = []): LogFolderCollection
1849

1950
public function sortByEarliestFirst(): self
2051
{
21-
$this->items = $this->sortBy->earliestTimestamp()->values()->all();
22-
23-
return $this;
52+
return $this->sortUsing(SortingMethod::ModifiedTime, SortingOrder::Ascending);
2453
}
2554

2655
public function sortByLatestFirst(): self
2756
{
28-
$this->items = $this->sortByDesc->latestTimestamp()->values()->all();
29-
30-
return $this;
57+
return $this->sortUsing(SortingMethod::ModifiedTime, SortingOrder::Descending);
3158
}
3259

3360
public function sortByEarliestFirstIncludingFiles(): self
@@ -48,39 +75,11 @@ public function sortByLatestFirstIncludingFiles(): self
4875

4976
public function sortAlphabeticallyAsc(): self
5077
{
51-
$this->items = collect($this->items)
52-
->sort(function (LogFolder $a, LogFolder $b) {
53-
if ($a->isRoot() && ! $b->isRoot()) {
54-
return -1;
55-
}
56-
if (! $a->isRoot() && $b->isRoot()) {
57-
return 1;
58-
}
59-
60-
return strcmp($a->cleanPath(), $b->cleanPath());
61-
})
62-
->values()
63-
->all();
64-
65-
return $this;
78+
return $this->sortUsing(SortingMethod::Alphabetical, SortingOrder::Ascending);
6679
}
6780

6881
public function sortAlphabeticallyDesc(): self
6982
{
70-
$this->items = collect($this->items)
71-
->sort(function (LogFolder $a, LogFolder $b) {
72-
if ($a->isRoot() && ! $b->isRoot()) {
73-
return -1;
74-
}
75-
if (! $a->isRoot() && $b->isRoot()) {
76-
return 1;
77-
}
78-
79-
return strcmp($b->cleanPath(), $a->cleanPath());
80-
})
81-
->values()
82-
->all();
83-
84-
return $this;
83+
return $this->sortUsing(SortingMethod::Alphabetical, SortingOrder::Descending);
8584
}
8685
}

tests/Unit/LogFileCollectionTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
use Opcodes\LogViewer\Enums\SortingMethod;
4+
use Opcodes\LogViewer\Enums\SortingOrder;
35
use Opcodes\LogViewer\Facades\LogViewer;
46
use Opcodes\LogViewer\LogFile;
57
use Opcodes\LogViewer\LogFileCollection;
@@ -64,3 +66,55 @@
6466

6567
expect($logFile)->toBe($secondFile);
6668
});
69+
70+
test('LogFileCollection can sort by ModifiedTime ascending using sortUsing method', function () {
71+
$firstFile = Mockery::mock(new LogFile('test.log'))
72+
->allows(['earliestTimestamp' => now()->subDay()->timestamp, 'name' => 'test.log']);
73+
$secondFile = Mockery::mock(new LogFile('test2.log'))
74+
->allows(['earliestTimestamp' => now()->subDays(2)->timestamp, 'name' => 'test2.log']);
75+
$collection = new LogFileCollection([$firstFile, $secondFile]);
76+
77+
$collection->sortUsing(SortingMethod::ModifiedTime, SortingOrder::Ascending);
78+
79+
expect($collection[0])->toBe($secondFile)
80+
->and($collection[1])->toBe($firstFile);
81+
});
82+
83+
test('LogFileCollection can sort by ModifiedTime descending using sortUsing method', function () {
84+
$firstFile = Mockery::mock(new LogFile('test.log'))
85+
->allows(['latestTimestamp' => now()->subDays(2)->timestamp, 'name' => 'test.log']);
86+
$secondFile = Mockery::mock(new LogFile('test2.log'))
87+
->allows(['latestTimestamp' => now()->subDay()->timestamp, 'name' => 'test2.log']);
88+
$collection = new LogFileCollection([$firstFile, $secondFile]);
89+
90+
$collection->sortUsing(SortingMethod::ModifiedTime, SortingOrder::Descending);
91+
92+
expect($collection[0])->toBe($secondFile)
93+
->and($collection[1])->toBe($firstFile);
94+
});
95+
96+
test('LogFileCollection can sort alphabetically ascending using sortUsing method', function () {
97+
$fileA = new LogFile('a.log');
98+
$fileB = new LogFile('b.log');
99+
$fileC = new LogFile('c.log');
100+
$collection = new LogFileCollection([$fileC, $fileA, $fileB]);
101+
102+
$collection->sortUsing(SortingMethod::Alphabetical, SortingOrder::Ascending);
103+
104+
expect($collection[0])->toBe($fileA)
105+
->and($collection[1])->toBe($fileB)
106+
->and($collection[2])->toBe($fileC);
107+
});
108+
109+
test('LogFileCollection can sort alphabetically descending using sortUsing method', function () {
110+
$fileA = new LogFile('a.log');
111+
$fileB = new LogFile('b.log');
112+
$fileC = new LogFile('c.log');
113+
$collection = new LogFileCollection([$fileA, $fileC, $fileB]);
114+
115+
$collection->sortUsing(SortingMethod::Alphabetical, SortingOrder::Descending);
116+
117+
expect($collection[0])->toBe($fileC)
118+
->and($collection[1])->toBe($fileB)
119+
->and($collection[2])->toBe($fileA);
120+
});

tests/Unit/LogFolderCollectionTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
use Opcodes\LogViewer\Enums\SortingMethod;
4+
use Opcodes\LogViewer\Enums\SortingOrder;
35
use Opcodes\LogViewer\Facades\LogViewer;
46
use Opcodes\LogViewer\LogFile;
57
use Opcodes\LogViewer\LogFileCollection;
@@ -151,3 +153,59 @@
151153
->and($collection[2])->toBe($bFolder)
152154
->and($collection[3])->toBe($aFolder);
153155
});
156+
157+
test('LogFolderCollection can sort by ModifiedTime ascending using sortUsing method', function () {
158+
$firstFolder = Mockery::mock(new LogFolder('folder', []))
159+
->allows(['earliestTimestamp' => now()->subDay()->timestamp]);
160+
$secondFolder = Mockery::mock(new LogFolder('folder2', []))
161+
->allows(['earliestTimestamp' => now()->subDays(2)->timestamp]);
162+
$collection = new LogFolderCollection([$firstFolder, $secondFolder]);
163+
164+
$collection->sortUsing(SortingMethod::ModifiedTime, SortingOrder::Ascending);
165+
166+
expect($collection[0])->toBe($secondFolder)
167+
->and($collection[1])->toBe($firstFolder);
168+
});
169+
170+
test('LogFolderCollection can sort by ModifiedTime descending using sortUsing method', function () {
171+
$firstFolder = Mockery::mock(new LogFolder('folder', []))
172+
->allows(['latestTimestamp' => now()->subDays(2)->timestamp]);
173+
$secondFolder = Mockery::mock(new LogFolder('folder2', []))
174+
->allows(['latestTimestamp' => now()->subDay()->timestamp]);
175+
$collection = new LogFolderCollection([$firstFolder, $secondFolder]);
176+
177+
$collection->sortUsing(SortingMethod::ModifiedTime, SortingOrder::Descending);
178+
179+
expect($collection[0])->toBe($secondFolder)
180+
->and($collection[1])->toBe($firstFolder);
181+
});
182+
183+
test('LogFolderCollection can sort alphabetically ascending using sortUsing method, with root always on top', function () {
184+
$rootFolder = Mockery::mock(new LogFolder('', []))->allows(['isRoot' => true, 'cleanPath' => LogFolder::rootPrefix()]);
185+
$bFolder = Mockery::mock(new LogFolder('b', []))->allows(['isRoot' => false, 'cleanPath' => 'b']);
186+
$aFolder = Mockery::mock(new LogFolder('a', []))->allows(['isRoot' => false, 'cleanPath' => 'a']);
187+
$zFolder = Mockery::mock(new LogFolder('z', []))->allows(['isRoot' => false, 'cleanPath' => 'z']);
188+
$collection = new LogFolderCollection([$zFolder, $rootFolder, $bFolder, $aFolder]);
189+
190+
$collection->sortUsing(SortingMethod::Alphabetical, SortingOrder::Ascending);
191+
192+
expect($collection[0])->toBe($rootFolder)
193+
->and($collection[1])->toBe($aFolder)
194+
->and($collection[2])->toBe($bFolder)
195+
->and($collection[3])->toBe($zFolder);
196+
});
197+
198+
test('LogFolderCollection can sort alphabetically descending using sortUsing method, with root always on top', function () {
199+
$rootFolder = Mockery::mock(new LogFolder('', []))->allows(['isRoot' => true, 'cleanPath' => LogFolder::rootPrefix()]);
200+
$bFolder = Mockery::mock(new LogFolder('b', []))->allows(['isRoot' => false, 'cleanPath' => 'b']);
201+
$aFolder = Mockery::mock(new LogFolder('a', []))->allows(['isRoot' => false, 'cleanPath' => 'a']);
202+
$zFolder = Mockery::mock(new LogFolder('z', []))->allows(['isRoot' => false, 'cleanPath' => 'z']);
203+
$collection = new LogFolderCollection([$aFolder, $zFolder, $rootFolder, $bFolder]);
204+
205+
$collection->sortUsing(SortingMethod::Alphabetical, SortingOrder::Descending);
206+
207+
expect($collection[0])->toBe($rootFolder)
208+
->and($collection[1])->toBe($zFolder)
209+
->and($collection[2])->toBe($bFolder)
210+
->and($collection[3])->toBe($aFolder);
211+
});

0 commit comments

Comments
 (0)