Skip to content

Commit 7bd8931

Browse files
committed
Sorting: Updated sort set command, Changed sort timestamp handling
- Renamed AssignSortSetCommand to AssignSortRuleCommand, updated contents and testing. - Updated sorting operations to not update timestamps if only priority is changed.
1 parent b9306a9 commit 7bd8931

File tree

7 files changed

+193
-145
lines changed

7 files changed

+193
-145
lines changed

app/Console/Commands/AssignSortSetCommand.php renamed to app/Console/Commands/AssignSortRuleCommand.php

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,72 +7,72 @@
77
use BookStack\Sorting\SortRule;
88
use Illuminate\Console\Command;
99

10-
class AssignSortSetCommand extends Command
10+
class AssignSortRuleCommand extends Command
1111
{
1212
/**
1313
* The name and signature of the console command.
1414
*
1515
* @var string
1616
*/
17-
protected $signature = 'bookstack:assign-sort-set
18-
{sort-set=0: ID of the sort set to apply}
17+
protected $signature = 'bookstack:assign-sort-rule
18+
{sort-rule=0: ID of the sort rule to apply}
1919
{--all-books : Apply to all books in the system}
20-
{--books-without-sort : Apply to only books without a sort set already assigned}
21-
{--books-with-sort= : Apply to only books with the sort of given id}';
20+
{--books-without-sort : Apply to only books without a sort rule already assigned}
21+
{--books-with-sort= : Apply to only books with the sort rule of given id}';
2222

2323
/**
2424
* The console command description.
2525
*
2626
* @var string
2727
*/
28-
protected $description = 'Assign a sort set to content in the system';
28+
protected $description = 'Assign a sort rule to content in the system';
2929

3030
/**
3131
* Execute the console command.
3232
*/
3333
public function handle(BookSorter $sorter): int
3434
{
35-
$sortSetId = intval($this->argument('sort-set')) ?? 0;
36-
if ($sortSetId === 0) {
37-
return $this->listSortSets();
35+
$sortRuleId = intval($this->argument('sort-rule')) ?? 0;
36+
if ($sortRuleId === 0) {
37+
return $this->listSortRules();
3838
}
3939

40-
$set = SortRule::query()->find($sortSetId);
40+
$rule = SortRule::query()->find($sortRuleId);
4141
if ($this->option('all-books')) {
4242
$query = Book::query();
4343
} else if ($this->option('books-without-sort')) {
44-
$query = Book::query()->whereNull('sort_set_id');
44+
$query = Book::query()->whereNull('sort_rule_id');
4545
} else if ($this->option('books-with-sort')) {
4646
$sortId = intval($this->option('books-with-sort')) ?: 0;
4747
if (!$sortId) {
4848
$this->error("Provided --books-with-sort option value is invalid");
4949
return 1;
5050
}
51-
$query = Book::query()->where('sort_set_id', $sortId);
51+
$query = Book::query()->where('sort_rule_id', $sortId);
5252
} else {
5353
$this->error("No option provided to specify target. Run with the -h option to see all available options.");
5454
return 1;
5555
}
5656

57-
if (!$set) {
58-
$this->error("Sort set of provided id {$sortSetId} not found!");
57+
if (!$rule) {
58+
$this->error("Sort rule of provided id {$sortRuleId} not found!");
5959
return 1;
6060
}
6161

6262
$count = $query->clone()->count();
63-
$this->warn("This will apply sort set [{$set->id}: {$set->name}] to {$count} book(s) and run the sort on each.");
63+
$this->warn("This will apply sort rule [{$rule->id}: {$rule->name}] to {$count} book(s) and run the sort on each.");
6464
$confirmed = $this->confirm("Are you sure you want to continue?");
6565

6666
if (!$confirmed) {
6767
return 1;
6868
}
6969

7070
$processed = 0;
71-
$query->chunkById(10, function ($books) use ($set, $sorter, $count, &$processed) {
71+
$query->chunkById(10, function ($books) use ($rule, $sorter, $count, &$processed) {
7272
$max = min($count, ($processed + 10));
7373
$this->info("Applying to {$processed}-{$max} of {$count} books");
7474
foreach ($books as $book) {
75-
$book->sort_set_id = $set->id;
75+
$book->sort_rule_id = $rule->id;
7676
$book->save();
7777
$sorter->runBookAutoSort($book);
7878
}
@@ -84,14 +84,14 @@ public function handle(BookSorter $sorter): int
8484
return 0;
8585
}
8686

87-
protected function listSortSets(): int
87+
protected function listSortRules(): int
8888
{
8989

90-
$sets = SortRule::query()->orderBy('id', 'asc')->get();
91-
$this->error("Sort set ID required!");
92-
$this->warn("\nAvailable sort sets:");
93-
foreach ($sets as $set) {
94-
$this->info("{$set->id}: {$set->name}");
90+
$rules = SortRule::query()->orderBy('id', 'asc')->get();
91+
$this->error("Sort rule ID required!");
92+
$this->warn("\nAvailable sort rules:");
93+
foreach ($rules as $rule) {
94+
$this->info("{$rule->id}: {$rule->name}");
9595
}
9696

9797
return 1;

app/Sorting/BookSorter.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace BookStack\Sorting;
44

5+
use BookStack\App\Model;
56
use BookStack\Entities\Models\Book;
67
use BookStack\Entities\Models\BookChild;
78
use BookStack\Entities\Models\Chapter;
@@ -57,7 +58,7 @@ public function runBookAutoSort(Book $book): void
5758

5859
foreach ($topItems as $index => $topItem) {
5960
$topItem->priority = $index + 1;
60-
$topItem->save();
61+
$topItem::withoutTimestamps(fn () => $topItem->save());
6162
}
6263

6364
foreach ($chapters as $chapter) {
@@ -68,7 +69,7 @@ public function runBookAutoSort(Book $book): void
6869

6970
foreach ($pages as $index => $page) {
7071
$page->priority = $index + 1;
71-
$page->save();
72+
$page::withoutTimestamps(fn () => $page->save());
7273
}
7374
}
7475
}
@@ -166,7 +167,7 @@ protected function applySortUpdates(BookSortMapItem $sortMapItem, array $modelMa
166167
}
167168

168169
if ($chapterChanged || $priorityChanged) {
169-
$model->save();
170+
$model::withoutTimestamps(fn () => $model->save());
170171
}
171172
}
172173

lang/en/activities.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,13 @@
127127
'comment_update' => 'updated comment',
128128
'comment_delete' => 'deleted comment',
129129

130-
// Sort Sets
131-
'sort_set_create' => 'created sort set',
132-
'sort_set_create_notification' => 'Sort set successfully created',
133-
'sort_set_update' => 'updated sort set',
134-
'sort_set_update_notification' => 'Sort set successfully update',
135-
'sort_set_delete' => 'deleted sort set',
136-
'sort_set_delete_notification' => 'Sort set successfully deleted',
130+
// Sort Rules
131+
'sort_rule_create' => 'created sort rule',
132+
'sort_rule_create_notification' => 'Sort rule successfully created',
133+
'sort_rule_update' => 'updated sort rule',
134+
'sort_rule_update_notification' => 'Sort rule successfully update',
135+
'sort_rule_delete' => 'deleted sort rule',
136+
'sort_rule_delete_notification' => 'Sort rule successfully deleted',
137137

138138
// Other
139139
'permissions_update' => 'updated permissions',
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
3+
namespace Commands;
4+
5+
use BookStack\Entities\Models\Book;
6+
use BookStack\Sorting\SortRule;
7+
use Tests\TestCase;
8+
9+
class AssignSortRuleCommandTest extends TestCase
10+
{
11+
public function test_no_given_sort_rule_lists_options()
12+
{
13+
$sortRules = SortRule::factory()->createMany(10);
14+
15+
$commandRun = $this->artisan('bookstack:assign-sort-rule')
16+
->expectsOutputToContain('Sort rule ID required!')
17+
->assertExitCode(1);
18+
19+
foreach ($sortRules as $sortRule) {
20+
$commandRun->expectsOutputToContain("{$sortRule->id}: {$sortRule->name}");
21+
}
22+
}
23+
24+
public function test_run_without_options_advises_help()
25+
{
26+
$this->artisan("bookstack:assign-sort-rule 100")
27+
->expectsOutput("No option provided to specify target. Run with the -h option to see all available options.")
28+
->assertExitCode(1);
29+
}
30+
31+
public function test_run_without_valid_sort_advises_help()
32+
{
33+
$this->artisan("bookstack:assign-sort-rule 100342 --all-books")
34+
->expectsOutput("Sort rule of provided id 100342 not found!")
35+
->assertExitCode(1);
36+
}
37+
38+
public function test_confirmation_required()
39+
{
40+
$sortRule = SortRule::factory()->create();
41+
42+
$this->artisan("bookstack:assign-sort-rule {$sortRule->id} --all-books")
43+
->expectsConfirmation('Are you sure you want to continue?', 'no')
44+
->assertExitCode(1);
45+
46+
$booksWithSort = Book::query()->whereNotNull('sort_rule_id')->count();
47+
$this->assertEquals(0, $booksWithSort);
48+
}
49+
50+
public function test_assign_to_all_books()
51+
{
52+
$sortRule = SortRule::factory()->create();
53+
$booksWithoutSort = Book::query()->whereNull('sort_rule_id')->count();
54+
$this->assertGreaterThan(0, $booksWithoutSort);
55+
56+
$this->artisan("bookstack:assign-sort-rule {$sortRule->id} --all-books")
57+
->expectsOutputToContain("This will apply sort rule [{$sortRule->id}: {$sortRule->name}] to {$booksWithoutSort} book(s)")
58+
->expectsConfirmation('Are you sure you want to continue?', 'yes')
59+
->expectsOutputToContain("Sort applied to {$booksWithoutSort} book(s)")
60+
->assertExitCode(0);
61+
62+
$booksWithoutSort = Book::query()->whereNull('sort_rule_id')->count();
63+
$this->assertEquals(0, $booksWithoutSort);
64+
}
65+
66+
public function test_assign_to_all_books_without_sort()
67+
{
68+
$totalBooks = Book::query()->count();
69+
$book = $this->entities->book();
70+
$sortRuleA = SortRule::factory()->create();
71+
$sortRuleB = SortRule::factory()->create();
72+
$book->sort_rule_id = $sortRuleA->id;
73+
$book->save();
74+
75+
$booksWithoutSort = Book::query()->whereNull('sort_rule_id')->count();
76+
$this->assertEquals($totalBooks, $booksWithoutSort + 1);
77+
78+
$this->artisan("bookstack:assign-sort-rule {$sortRuleB->id} --books-without-sort")
79+
->expectsConfirmation('Are you sure you want to continue?', 'yes')
80+
->expectsOutputToContain("Sort applied to {$booksWithoutSort} book(s)")
81+
->assertExitCode(0);
82+
83+
$booksWithoutSort = Book::query()->whereNull('sort_rule_id')->count();
84+
$this->assertEquals(0, $booksWithoutSort);
85+
$this->assertEquals($totalBooks, $sortRuleB->books()->count() + 1);
86+
}
87+
88+
public function test_assign_to_all_books_with_sort()
89+
{
90+
$book = $this->entities->book();
91+
$sortRuleA = SortRule::factory()->create();
92+
$sortRuleB = SortRule::factory()->create();
93+
$book->sort_rule_id = $sortRuleA->id;
94+
$book->save();
95+
96+
$this->artisan("bookstack:assign-sort-rule {$sortRuleB->id} --books-with-sort={$sortRuleA->id}")
97+
->expectsConfirmation('Are you sure you want to continue?', 'yes')
98+
->expectsOutputToContain("Sort applied to 1 book(s)")
99+
->assertExitCode(0);
100+
101+
$book->refresh();
102+
$this->assertEquals($sortRuleB->id, $book->sort_rule_id);
103+
$this->assertEquals(1, $sortRuleB->books()->count());
104+
}
105+
106+
public function test_assign_to_all_books_with_sort_id_is_validated()
107+
{
108+
$this->artisan("bookstack:assign-sort-rule 50 --books-with-sort=beans")
109+
->expectsOutputToContain("Provided --books-with-sort option value is invalid")
110+
->assertExitCode(1);
111+
}
112+
}

tests/Commands/AssignSortSetCommandTest.php

Lines changed: 0 additions & 112 deletions
This file was deleted.

0 commit comments

Comments
 (0)