- return $query->get();
- }
-
- /**
- * Sort the books content using the given sort map.
- * Returns a list of books that were involved in the operation.
- *
- * @throws SortOperationException
- */
- public function sortUsingMap(BookSortMap $sortMap): Collection
- {
- // Load models into map
- $this->loadModelsIntoSortMap($sortMap);
- $booksInvolved = $this->getBooksInvolvedInSort($sortMap);
-
- // Perform the sort
- foreach ($sortMap->all() as $item) {
- $this->applySortUpdates($item);
- }
-
- // Update permissions and activity.
- $booksInvolved->each(function (Book $book) {
- $book->rebuildPermissions();
- });
-
- return $booksInvolved;
- }
-
- /**
- * Using the given sort map item, detect changes for the related model
- * and update it if required.
- */
- protected function applySortUpdates(BookSortMapItem $sortMapItem): void
- {
- $model = $sortMapItem->model;
- if (!$model) {
- return;
- }
-
- $priorityChanged = $model->priority !== $sortMapItem->sort;
- $bookChanged = $model->book_id !== $sortMapItem->parentBookId;
- $chapterChanged = ($model instanceof Page) && $model->chapter_id !== $sortMapItem->parentChapterId;
-
- if ($bookChanged) {
- $model->changeBook($sortMapItem->parentBookId);
- }
-
- if ($chapterChanged) {
- $model->chapter_id = intval($sortMapItem->parentChapterId);
- $model->save();
- }
-
- if ($priorityChanged) {
- $model->priority = $sortMapItem->sort;
- $model->save();
- }
- }
-
- /**
- * Load models from the database into the given sort map.
- */
- protected function loadModelsIntoSortMap(BookSortMap $sortMap): void
- {
- $collection = collect($sortMap->all());
-
- $keyMap = $collection->keyBy(function (BookSortMapItem $sortMapItem) {
- return $sortMapItem->type . ':' . $sortMapItem->id;
- });
-
- $pageIds = $collection->where('type', '=', 'page')->pluck('id');
- $chapterIds = $collection->where('type', '=', 'chapter')->pluck('id');
-
- $pages = Page::visible()->whereIn('id', $pageIds)->get();
- $chapters = Chapter::visible()->whereIn('id', $chapterIds)->get();
-
- foreach ($pages as $page) {
- /** @var BookSortMapItem $sortItem */
- $sortItem = $keyMap->get('page:' . $page->id);
- $sortItem->model = $page;
- }
-
- foreach ($chapters as $chapter) {
- /** @var BookSortMapItem $sortItem */
- $sortItem = $keyMap->get('chapter:' . $chapter->id);
- $sortItem->model = $chapter;
- }
- }
-
- /**
- * Get the books involved in a sort.
- * The given sort map should have its models loaded first.
- *
- * @throws SortOperationException
- */
- protected function getBooksInvolvedInSort(BookSortMap $sortMap): Collection
- {
- $collection = collect($sortMap->all());
-
- $bookIdsInvolved = array_unique(array_merge(
- [$this->book->id],
- $collection->pluck('parentBookId')->values()->all(),
- $collection->pluck('model.book_id')->values()->all(),
- ));
-
- $books = Book::hasPermission('update')->whereIn('id', $bookIdsInvolved)->get();
-
- if (count($books) !== count($bookIdsInvolved)) {
- throw new SortOperationException('Could not find all books requested in sort operation');
- }
-
- return $books;