X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/edc7c12edfbe4cabcf6d9a5090d29bb947ef35fb..refs/pull/5689/head:/app/Entities/Tools/BookContents.php diff --git a/app/Entities/Tools/BookContents.php b/app/Entities/Tools/BookContents.php index 96142bb7f..7dd3f3e11 100644 --- a/app/Entities/Tools/BookContents.php +++ b/app/Entities/Tools/BookContents.php @@ -7,34 +7,32 @@ use BookStack\Entities\Models\BookChild; use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; -use BookStack\Exceptions\SortOperationException; +use BookStack\Entities\Queries\EntityQueries; +use BookStack\Sorting\BookSortMap; +use BookStack\Sorting\BookSortMapItem; use Illuminate\Support\Collection; class BookContents { - /** - * @var Book - */ - protected $book; + protected EntityQueries $queries; - /** - * BookContents constructor. - */ - public function __construct(Book $book) - { - $this->book = $book; + public function __construct( + protected Book $book, + ) { + $this->queries = app()->make(EntityQueries::class); } /** - * Get the current priority of the last item - * at the top-level of the book. + * Get the current priority of the last item at the top-level of the book. */ public function getLastPriority(): int { - $maxPage = Page::visible()->where('book_id', '=', $this->book->id) + $maxPage = $this->book->pages() ->where('draft', '=', false) - ->where('chapter_id', '=', 0)->max('priority'); - $maxChapter = Chapter::visible()->where('book_id', '=', $this->book->id) + ->where('chapter_id', '=', 0) + ->max('priority'); + + $maxChapter = $this->book->chapters() ->max('priority'); return max($maxChapter, $maxPage, 1); @@ -46,7 +44,7 @@ class BookContents public function getTree(bool $showDrafts = false, bool $renderPages = false): Collection { $pages = $this->getPages($showDrafts, $renderPages); - $chapters = Chapter::visible()->where('book_id', '=', $this->book->id)->get(); + $chapters = $this->book->chapters()->scopes('visible')->get(); $all = collect()->concat($pages)->concat($chapters); $chapterMap = $chapters->keyBy('id'); $lonePages = collect(); @@ -95,124 +93,16 @@ class BookContents */ protected function getPages(bool $showDrafts = false, bool $getPageContent = false): Collection { - $query = Page::visible() - ->select($getPageContent ? Page::$contentAttributes : Page::$listAttributes) - ->where('book_id', '=', $this->book->id); + if ($getPageContent) { + $query = $this->queries->pages->visibleWithContents(); + } else { + $query = $this->queries->pages->visibleForList(); + } if (!$showDrafts) { $query->where('draft', '=', false); } - 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; + return $query->where('book_id', '=', $this->book->id)->get(); } }