Skip to content

Commit f1e721f

Browse files
committed
sorting folder alphabetically
1 parent 726afaa commit f1e721f

File tree

8 files changed

+171
-4
lines changed

8 files changed

+171
-4
lines changed

config/log-viewer.php

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

3+
use Opcodes\LogViewer\Enums\Theme;
4+
use Opcodes\LogViewer\Enums\FolderSortingMethod;
5+
use Opcodes\LogViewer\Enums\SortingOrder;
6+
37
return [
48

59
/*
@@ -241,4 +245,23 @@
241245
*/
242246

243247
'per_page_options' => [10, 25, 50, 100, 250, 500],
248+
249+
'defaults' => [
250+
251+
// Must be one of the above `per_page_options` values
252+
'per_page' => 10,
253+
254+
// Other options: `Alphabetical`, `ModifiedTime`
255+
'folder_sorting_method' => FolderSortingMethod::Alphabetical,
256+
257+
// Other options: `Ascending`, `Descending`
258+
'folder_sorting_order' => SortingOrder::Descending,
259+
260+
// Other options: `System`, `Light`, `Dark`
261+
'theme' => Theme::System,
262+
263+
// Whether to enable `shorter_stack_traces` by default
264+
'shorter_stack_traces' => true,
265+
266+
]
244267
];

src/Enums/FolderSortingMethod.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Opcodes\LogViewer\Enums;
4+
5+
enum FolderSortingMethod: string
6+
{
7+
case Alphabetical = 'alphabetical';
8+
case ModifiedTime = 'modified-time';
9+
}

src/Enums/SortingOrder.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Opcodes\LogViewer\Enums;
4+
5+
enum SortingOrder: string
6+
{
7+
case Ascending = 'asc';
8+
case Descending = 'desc';
9+
}

src/Enums/Theme.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Opcodes\LogViewer\Enums;
4+
5+
enum Theme: string
6+
{
7+
case System = 'system';
8+
case Light = 'light';
9+
case Dark = 'dark';
10+
}

src/Http/Controllers/FoldersController.php

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use Illuminate\Http\Request;
66
use Illuminate\Support\Facades\Gate;
77
use Illuminate\Support\Facades\URL;
8+
use Opcodes\LogViewer\Enums\FolderSortingMethod;
9+
use Opcodes\LogViewer\Enums\SortingOrder;
810
use Opcodes\LogViewer\Facades\LogViewer;
911
use Opcodes\LogViewer\Http\Resources\LogFolderResource;
1012
use Opcodes\LogViewer\LogFile;
@@ -15,10 +17,32 @@ public function index(Request $request)
1517
{
1618
$folders = LogViewer::getFilesGroupedByFolder();
1719

18-
if ($request->query('direction', 'desc') === 'asc') {
19-
$folders = $folders->sortByEarliestFirstIncludingFiles();
20-
} else {
21-
$folders = $folders->sortByLatestFirstIncludingFiles();
20+
$sortingMethod = config('log-viewer.defaults.folder_sorting_method', FolderSortingMethod::ModifiedTime);
21+
$sortingOrder = config('log-viewer.defaults.folder_sorting_order', SortingOrder::Descending);
22+
23+
$fileSortingOrder = $request->query('direction', 'desc');
24+
25+
if ($sortingMethod === FolderSortingMethod::Alphabetical) {
26+
if ($sortingOrder === SortingOrder::Ascending) {
27+
$folders = $folders->sortAlphabeticallyAsc();
28+
} else {
29+
$folders = $folders->sortAlphabeticallyDesc();
30+
}
31+
32+
// Still sort files inside folders by direction param
33+
$folders->each(function ($folder) use ($fileSortingOrder) {
34+
if ($fileSortingOrder === 'asc') {
35+
$folder->files()->sortByEarliestFirst();
36+
} else {
37+
$folder->files()->sortByLatestFirst();
38+
}
39+
});
40+
} else { // ModifiedTime
41+
if ($fileSortingOrder === 'asc') {
42+
$folders = $folders->sortByEarliestFirstIncludingFiles();
43+
} else {
44+
$folders = $folders->sortByLatestFirstIncludingFiles();
45+
}
2246
}
2347

2448
return LogFolderResource::collection($folders->values());

src/LogFolderCollection.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,38 @@ public function sortByLatestFirstIncludingFiles(): self
4545

4646
return $this;
4747
}
48+
49+
public function sortAlphabeticallyAsc(): self
50+
{
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+
return strcmp($a->cleanPath(), $b->cleanPath());
60+
})
61+
->values()
62+
->toArray();
63+
return $this;
64+
}
65+
66+
public function sortAlphabeticallyDesc(): self
67+
{
68+
$this->items = collect($this->items)
69+
->sort(function (LogFolder $a, LogFolder $b) {
70+
if ($a->isRoot() && !$b->isRoot()) {
71+
return -1;
72+
}
73+
if (!$a->isRoot() && $b->isRoot()) {
74+
return 1;
75+
}
76+
return strcmp($b->cleanPath(), $a->cleanPath());
77+
})
78+
->values()
79+
->toArray();
80+
return $this;
81+
}
4882
}

tests/Feature/LogFoldersControllerTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
<?php
22

3+
use Opcodes\LogViewer\Enums\FolderSortingMethod;
4+
use Opcodes\LogViewer\Enums\SortingOrder;
5+
36
use function Pest\Laravel\getJson;
47

58
beforeEach(function () {
69
config(['log-viewer.include_files' => ['*/**.log']]);
710
});
811

912
it('can get the log files', function () {
13+
config(['log-viewer.defaults.folder_sorting_method' => FolderSortingMethod::ModifiedTime]);
14+
config(['log-viewer.defaults.folder_sorting_order' => SortingOrder::Descending]);
15+
1016
generateLogFiles([
1117
'one/1.one.log',
1218
'one/2.two.log',
@@ -20,3 +26,25 @@
2026
->assertJsonFragment(['clean_path' => 'root'.DIRECTORY_SEPARATOR.'one'])
2127
->assertJsonFragment(['clean_path' => 'root'.DIRECTORY_SEPARATOR.'two']);
2228
});
29+
30+
it('folders are sorted alphabetically descending when configured', function () {
31+
config(['log-viewer.defaults.folder_sorting_method' => FolderSortingMethod::Alphabetical]);
32+
config(['log-viewer.defaults.folder_sorting_order' => SortingOrder::Ascending]);
33+
34+
generateLogFiles([
35+
'one/1.one.log',
36+
'one/2.two.log',
37+
'two/3.three.log',
38+
'alpha/4.alpha.log',
39+
'laravel.log',
40+
], randomContent: true);
41+
42+
$response = getJson(route('log-viewer.folders'));
43+
$folders = $response->json();
44+
// Should be sorted: 'root', 'alpha', 'one', 'two'
45+
$response->assertJsonCount(4);
46+
expect($folders[0]['clean_path'])->toBe('root');
47+
expect($folders[1]['clean_path'])->toBe('root'.DIRECTORY_SEPARATOR.'alpha');
48+
expect($folders[2]['clean_path'])->toBe('root'.DIRECTORY_SEPARATOR.'one');
49+
expect($folders[3]['clean_path'])->toBe('root'.DIRECTORY_SEPARATOR.'two');
50+
});

tests/Unit/LogFolderCollectionTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,33 @@
121121
expect($folderFiles[0])->toBe($secondFile)
122122
->and($folderFiles[1])->toBe($firstFile);
123123
});
124+
125+
test('LogFolderCollection can sort its folders alphabetically ascending, with root always on top', function () {
126+
$rootFolder = Mockery::mock(new LogFolder('', []))->allows(['isRoot' => true, 'cleanPath' => 'root']);
127+
$bFolder = Mockery::mock(new LogFolder('b', []))->allows(['isRoot' => false, 'cleanPath' => 'b']);
128+
$aFolder = Mockery::mock(new LogFolder('a', []))->allows(['isRoot' => false, 'cleanPath' => 'a']);
129+
$zFolder = Mockery::mock(new LogFolder('z', []))->allows(['isRoot' => false, 'cleanPath' => 'z']);
130+
$collection = new LogFolderCollection([$zFolder, $rootFolder, $bFolder, $aFolder]);
131+
132+
$collection->sortAlphabeticallyAsc();
133+
134+
expect($collection[0])->toBe($rootFolder)
135+
->and($collection[1])->toBe($aFolder)
136+
->and($collection[2])->toBe($bFolder)
137+
->and($collection[3])->toBe($zFolder);
138+
});
139+
140+
test('LogFolderCollection can sort its folders alphabetically descending, with root always on top', function () {
141+
$rootFolder = Mockery::mock(new LogFolder('', []))->allows(['isRoot' => true, 'cleanPath' => 'root']);
142+
$bFolder = Mockery::mock(new LogFolder('b', []))->allows(['isRoot' => false, 'cleanPath' => 'b']);
143+
$aFolder = Mockery::mock(new LogFolder('a', []))->allows(['isRoot' => false, 'cleanPath' => 'a']);
144+
$zFolder = Mockery::mock(new LogFolder('z', []))->allows(['isRoot' => false, 'cleanPath' => 'z']);
145+
$collection = new LogFolderCollection([$aFolder, $zFolder, $rootFolder, $bFolder]);
146+
147+
$collection->sortAlphabeticallyDesc();
148+
149+
expect($collection[0])->toBe($rootFolder)
150+
->and($collection[1])->toBe($zFolder)
151+
->and($collection[2])->toBe($bFolder)
152+
->and($collection[3])->toBe($aFolder);
153+
});

0 commit comments

Comments
 (0)