diff --git a/app/Entities/Controllers/BookController.php b/app/Entities/Controllers/BookController.php index a1c586f47e7..f35130095bc 100644 --- a/app/Entities/Controllers/BookController.php +++ b/app/Entities/Controllers/BookController.php @@ -40,33 +40,49 @@ public function __construct( public function index(Request $request) { $view = setting()->getForCurrentUser('books_view_type'); - $listOptions = SimpleListOptions::fromRequest($request, 'books')->withSortOptions([ - 'name' => trans('common.sort_name'), - 'created_at' => trans('common.sort_created_at'), - 'updated_at' => trans('common.sort_updated_at'), - ]); + $listOptions = $this->getListOptions($request); + + $booksQuery = $this->queries->visibleForListWithCover(); + $this->applySortOptions($booksQuery, $listOptions); + + $books = $booksQuery->paginate(18); - $books = $this->queries->visibleForListWithCover() - ->orderBy($listOptions->getSort(), $listOptions->getOrder()) - ->paginate(18); $recents = $this->isSignedIn() ? $this->queries->recentlyViewedForCurrentUser()->take(4)->get() : false; $popular = $this->queries->popularForList()->take(4)->get(); $new = $this->queries->visibleForList()->orderBy('created_at', 'desc')->take(4)->get(); $this->shelfContext->clearShelfContext(); - $this->setPageTitle(trans('entities.books')); return view('books.index', [ - 'books' => $books, - 'recents' => $recents, - 'popular' => $popular, - 'new' => $new, - 'view' => $view, + 'books' => $books, + 'recents' => $recents, + 'popular' => $popular, + 'new' => $new, + 'view' => $view, 'listOptions' => $listOptions, ]); } + private function getListOptions(Request $request): SimpleListOptions + { + return SimpleListOptions::fromRequest($request, 'books')->withSortOptions([ + 'name' => trans('common.sort_name'), + 'created_at' => trans('common.sort_created_at'), + 'updated_at' => trans('common.sort_updated_at'), + 'view_count' => trans('common.sort_popularity'), + ]); + } + + private function applySortOptions($booksQuery, SimpleListOptions $listOptions): void + { + if ($listOptions->getSort() === 'view_count') { + $booksQuery->scopes('withViewCount')->orderBy('view_count', $listOptions->getOrder()); + } else { + $booksQuery->orderBy($listOptions->getSort(), $listOptions->getOrder()); + } + } + /** * Show the form for creating a new book. */ diff --git a/lang/en/common.php b/lang/en/common.php index 266174eed9d..9ae343b1c72 100644 --- a/lang/en/common.php +++ b/lang/en/common.php @@ -63,6 +63,7 @@ 'sort_default' => 'Default', 'sort_created_at' => 'Created Date', 'sort_updated_at' => 'Updated Date', + 'sort_popularity' => 'Popularity', // Misc 'deleted_user' => 'Deleted User', diff --git a/tests/Entity/BookSortingTest.php b/tests/Entity/BookSortingTest.php new file mode 100644 index 00000000000..76c88e76596 --- /dev/null +++ b/tests/Entity/BookSortingTest.php @@ -0,0 +1,130 @@ +users->editor(); + $this->actingAs($editor); + + // Step 2: Send a PATCH request to the endpoint + $updateRequest = $this->patch('/preferences/change-sort/books', [ + 'sort' => 'created_at', + 'order' => 'desc', + ]); + + // Step 3: Assert the response status + $updateRequest->assertStatus(302); + + // Step 4: Verify database changes + $this->assertDatabaseHas('settings', [ + 'setting_key' => 'user:' . $editor->id . ':books_sort', + 'value' => 'created_at', + ]); + $this->assertDatabaseHas('settings', [ + 'setting_key' => 'user:' . $editor->id . ':books_sort_order', + 'value' => 'desc', + ]); + + // Step 5: Check user settings + $this->assertEquals('created_at', setting()->getForCurrentUser('books_sort')); + $this->assertEquals('desc', setting()->getForCurrentUser('books_sort_order')); + + // Step 6: Check the order of books on the page + $response = $this->get('/books'); + $response->assertStatus(200); + $allBooks = Book::all(); + $this->assertBooksOrder($response->content(), $allBooks->sortByDesc('created_at')->pluck('name')->toArray()); + } + + // Test with different sort fields and orders + public function test_update_sort_preference_with_different_fields_and_orders() + { + // Step 1: Set up the test environment + $editor = $this->users->editor(); + $this->actingAs($editor); + + // Step 2: Send a PATCH request to the endpoint with different sort field and order + $updateRequest = $this->patch('/preferences/change-sort/books', [ + 'sort' => 'updated_at', + 'order' => 'asc', + ]); + + // Step 3: Assert the response status + $updateRequest->assertStatus(302); + + // Step 4: Verify database changes for the new sort field and order + $this->assertDatabaseHas('settings', [ + 'setting_key' => 'user:' . $editor->id . ':books_sort', + 'value' => 'updated_at', + ]); + $this->assertDatabaseHas('settings', [ + 'setting_key' => 'user:' . $editor->id . ':books_sort_order', + 'value' => 'asc', + ]); + + // Step 5: Check user settings for the updated sort field and order + $this->assertEquals('updated_at', setting()->getForCurrentUser('books_sort')); + $this->assertEquals('asc', setting()->getForCurrentUser('books_sort_order')); + + // Step 6: Check the order of books on the page + $response = $this->get('/books'); + $response->assertStatus(200); + $allBooks = Book::all(); + $this->assertBooksOrder($response->content(), $allBooks->sortBy('updated_at')->pluck('name')->toArray()); + } + + // Test the sort field popularity + public function test_sort_by_popularity() + { + // Step 1: Set up the test environment + $editor = $this->users->editor(); + $this->actingAs($editor); + + // Step 2: Send a PATCH request to the endpoint with sort field popularity + $updateRequest = $this->patch('/preferences/change-sort/books', [ + 'sort' => 'view_count', + 'order' => 'desc', + ]); + + // Step 3: Assert the response status + $updateRequest->assertStatus(302); + + // Step 4: Verify database changes for the sort field popularity + $this->assertDatabaseHas('settings', [ + 'setting_key' => 'user:' . $editor->id . ':books_sort', + 'value' => 'view_count', + ]); + $this->assertDatabaseHas('settings', [ + 'setting_key' => 'user:' . $editor->id . ':books_sort_order', + 'value' => 'desc', + ]); + + // Step 5: Check user settings for the sort field popularity + $this->assertEquals('view_count', setting()->getForCurrentUser('books_sort')); + $this->assertEquals('desc', setting()->getForCurrentUser('books_sort_order')); + + // Step 6: Check the order of books on the page + $response = $this->get('/books'); + $response->assertStatus(200); + $allBooks = Book::all(); + $this->assertBooksOrder($response->content(), $allBooks->sortByDesc('view_count')->pluck('name')->toArray()); + } + + private function assertBooksOrder($htmlContent, $expectedOrder) + { + $crawler = new Crawler($htmlContent); + $bookNames = $crawler->filter('.grid-card-content h2.text-limit-lines-2')->each(function (Crawler $node) { + return $node->text(); + }); + $this->assertEquals($expectedOrder, $bookNames); + } +} \ No newline at end of file