| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace BookStack\Entities\Tools; | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 08:17:45 +08:00
										 |  |  | use BookStack\Entities\Models\Book; | 
					
						
							|  |  |  | use BookStack\Entities\Models\BookChild; | 
					
						
							|  |  |  | use BookStack\Entities\Models\Chapter; | 
					
						
							|  |  |  | use BookStack\Entities\Models\Entity; | 
					
						
							|  |  |  | use BookStack\Entities\Models\Page; | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | use Illuminate\Support\Collection; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BookContents | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @var Book | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected $book; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * BookContents constructor. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function __construct(Book $book) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->book = $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) | 
					
						
							|  |  |  |             ->where('draft', '=', false) | 
					
						
							|  |  |  |             ->where('chapter_id', '=', 0)->max('priority'); | 
					
						
							|  |  |  |         $maxChapter = Chapter::visible()->where('book_id', '=', $this->book->id) | 
					
						
							|  |  |  |             ->max('priority'); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         return max($maxChapter, $maxPage, 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the contents as a sorted collection tree. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getTree(bool $showDrafts = false, bool $renderPages = false): Collection | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-08-22 20:15:58 +08:00
										 |  |  |         $pages = $this->getPages($showDrafts, $renderPages); | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         $chapters = Chapter::visible()->where('book_id', '=', $this->book->id)->get(); | 
					
						
							|  |  |  |         $all = collect()->concat($pages)->concat($chapters); | 
					
						
							|  |  |  |         $chapterMap = $chapters->keyBy('id'); | 
					
						
							|  |  |  |         $lonePages = collect(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $pages->groupBy('chapter_id')->each(function ($pages, $chapter_id) use ($chapterMap, &$lonePages) { | 
					
						
							|  |  |  |             $chapter = $chapterMap->get($chapter_id); | 
					
						
							|  |  |  |             if ($chapter) { | 
					
						
							| 
									
										
										
										
											2020-12-18 01:31:18 +08:00
										 |  |  |                 $chapter->setAttribute('visible_pages', collect($pages)->sortBy($this->bookChildSortFunc())); | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 $lonePages = $lonePages->concat($pages); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-18 01:31:18 +08:00
										 |  |  |         $chapters->whereNull('visible_pages')->each(function (Chapter $chapter) { | 
					
						
							|  |  |  |             $chapter->setAttribute('visible_pages', collect([])); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-15 05:13:52 +08:00
										 |  |  |         $all->each(function (Entity $entity) use ($renderPages) { | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |             $entity->setRelation('book', $this->book); | 
					
						
							| 
									
										
										
										
											2020-08-15 05:13:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-20 22:03:56 +08:00
										 |  |  |             if ($renderPages && $entity instanceof Page) { | 
					
						
							| 
									
										
										
										
											2020-08-15 05:13:52 +08:00
										 |  |  |                 $entity->html = (new PageContent($entity))->render(); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return collect($chapters)->concat($lonePages)->sortBy($this->bookChildSortFunc()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Function for providing a sorting score for an entity in relation to the | 
					
						
							|  |  |  |      * other items within the book. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function bookChildSortFunc(): callable | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return function (Entity $entity) { | 
					
						
							|  |  |  |             if (isset($entity['draft']) && $entity['draft']) { | 
					
						
							|  |  |  |                 return -100; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |             return $entity['priority'] ?? 0; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the visible pages within this book. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-08-22 02:58:19 +08:00
										 |  |  |     protected function getPages(bool $showDrafts = false, bool $getPageContent = false): Collection | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-08-22 02:58:19 +08:00
										 |  |  |         $query = Page::visible() | 
					
						
							|  |  |  |             ->select($getPageContent ? Page::$contentAttributes : Page::$listAttributes) | 
					
						
							|  |  |  |             ->where('book_id', '=', $this->book->id); | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!$showDrafts) { | 
					
						
							|  |  |  |             $query->where('draft', '=', false); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $query->get(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2022-01-05 01:31:57 +08:00
										 |  |  |      * Sort the books content using the given sort map. | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |      * Returns a list of books that were involved in the operation. | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |      * @returns Book[] | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |     public function sortUsingMap(BookSortMap $sortMap): array | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         // Load models into map
 | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         $modelMap = $this->loadModelsFromSortMap($sortMap); | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |         // Sort our changes from our map to be chapters first
 | 
					
						
							|  |  |  |         // Since they need to be process to ensure book alignment for child page changes.
 | 
					
						
							|  |  |  |         $sortMapItems = $sortMap->all(); | 
					
						
							| 
									
										
										
										
											2022-01-06 20:18:11 +08:00
										 |  |  |         usort($sortMapItems, function (BookSortMapItem $itemA, BookSortMapItem $itemB) { | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |             $aScore = $itemA->type === 'page' ? 2 : 1; | 
					
						
							|  |  |  |             $bScore = $itemB->type === 'page' ? 2 : 1; | 
					
						
							| 
									
										
										
										
											2022-01-06 20:18:11 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |             return $aScore - $bScore; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         // Perform the sort
 | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |         foreach ($sortMapItems as $item) { | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |             $this->applySortUpdates($item, $modelMap); | 
					
						
							| 
									
										
										
										
											2022-01-05 01:31:57 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         /** @var Book[] $booksInvolved */ | 
					
						
							|  |  |  |         $booksInvolved = array_values(array_filter($modelMap, function (string $key) { | 
					
						
							|  |  |  |             return strpos($key, 'book:') === 0; | 
					
						
							|  |  |  |         }, ARRAY_FILTER_USE_KEY)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Update permissions of books involved
 | 
					
						
							|  |  |  |         foreach ($booksInvolved as $book) { | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |             $book->rebuildPermissions(); | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return $booksInvolved; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Using the given sort map item, detect changes for the related model | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |      * and update it if required. Changes where permissions are lacking will | 
					
						
							|  |  |  |      * be skipped and not throw an error. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array<string, Entity> $modelMap | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |     protected function applySortUpdates(BookSortMapItem $sortMapItem, array $modelMap): void | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         /** @var BookChild $model */ | 
					
						
							|  |  |  |         $model = $modelMap[$sortMapItem->type . ':' . $sortMapItem->id] ?? null; | 
					
						
							| 
									
										
										
										
											2022-01-05 01:31:57 +08:00
										 |  |  |         if (!$model) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 01:31:57 +08:00
										 |  |  |         $priorityChanged = $model->priority !== $sortMapItem->sort; | 
					
						
							|  |  |  |         $bookChanged = $model->book_id !== $sortMapItem->parentBookId; | 
					
						
							|  |  |  |         $chapterChanged = ($model instanceof Page) && $model->chapter_id !== $sortMapItem->parentChapterId; | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         // Stop if there's no change
 | 
					
						
							|  |  |  |         if (!$priorityChanged && !$bookChanged && !$chapterChanged) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-06 20:18:11 +08:00
										 |  |  |         $currentParentKey = 'book:' . $model->book_id; | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         if ($model instanceof Page && $model->chapter_id) { | 
					
						
							| 
									
										
										
										
											2022-01-06 20:18:11 +08:00
										 |  |  |             $currentParentKey = 'chapter:' . $model->chapter_id; | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |         $currentParent = $modelMap[$currentParentKey] ?? null; | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         /** @var Book $newBook */ | 
					
						
							| 
									
										
										
										
											2022-01-05 23:42:59 +08:00
										 |  |  |         $newBook = $modelMap['book:' . $sortMapItem->parentBookId] ?? null; | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         /** @var ?Chapter $newChapter */ | 
					
						
							|  |  |  |         $newChapter = $sortMapItem->parentChapterId ? ($modelMap['chapter:' . $sortMapItem->parentChapterId] ?? null) : null; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |         if (!$this->isSortChangePermissible($sortMapItem, $model, $currentParent, $newBook, $newChapter)) { | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Action the required changes
 | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         if ($bookChanged) { | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |             $model->changeBook($newBook->id); | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($chapterChanged) { | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |             $model->chapter_id = $newChapter->id ?? 0; | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($priorityChanged) { | 
					
						
							| 
									
										
										
										
											2022-01-05 01:31:57 +08:00
										 |  |  |             $model->priority = $sortMapItem->sort; | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($chapterChanged || $priorityChanged) { | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |             $model->save(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Check if the current user has permissions to apply the given sorting change. | 
					
						
							| 
									
										
										
										
											2022-01-05 23:42:59 +08:00
										 |  |  |      * Is quite complex since items can gain a different parent change. Acts as a: | 
					
						
							|  |  |  |      * - Update of old parent element (Change of content/order). | 
					
						
							|  |  |  |      * - Update of sorted/moved element. | 
					
						
							|  |  |  |      * - Deletion of element (Relative to parent upon move). | 
					
						
							|  |  |  |      * - Creation of element within parent (Upon move to new parent). | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-01-05 23:42:59 +08:00
										 |  |  |     protected function isSortChangePermissible(BookSortMapItem $sortMapItem, BookChild $model, ?Entity $currentParent, ?Entity $newBook, ?Entity $newChapter): bool | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         // Stop if we can't see the current parent or new book.
 | 
					
						
							|  |  |  |         if (!$currentParent || !$newBook) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 23:42:59 +08:00
										 |  |  |         $hasNewParent = $newBook->id !== $model->book_id || ($model instanceof Page && $model->chapter_id !== ($sortMapItem->parentChapterId ?? 0)); | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |         if ($model instanceof Chapter) { | 
					
						
							|  |  |  |             $hasPermission = userCan('book-update', $currentParent) | 
					
						
							| 
									
										
										
										
											2022-01-05 23:42:59 +08:00
										 |  |  |                 && userCan('book-update', $newBook) | 
					
						
							|  |  |  |                 && userCan('chapter-update', $model) | 
					
						
							|  |  |  |                 && (!$hasNewParent || userCan('chapter-create', $newBook)) | 
					
						
							|  |  |  |                 && (!$hasNewParent || userCan('chapter-delete', $model)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |             if (!$hasPermission) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($model instanceof Page) { | 
					
						
							|  |  |  |             $parentPermission = ($currentParent instanceof Chapter) ? 'chapter-update' : 'book-update'; | 
					
						
							|  |  |  |             $hasCurrentParentPermission = userCan($parentPermission, $currentParent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // This needs to check if there was an intended chapter location in the original sort map
 | 
					
						
							|  |  |  |             // rather than inferring from the $newChapter since that variable may be null
 | 
					
						
							|  |  |  |             // due to other reasons (Visibility).
 | 
					
						
							|  |  |  |             $newParent = $sortMapItem->parentChapterId ? $newChapter : $newBook; | 
					
						
							|  |  |  |             if (!$newParent) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 23:42:59 +08:00
										 |  |  |             $hasPageEditPermission = userCan('page-update', $model); | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |             $newParentInRightLocation = ($newParent instanceof Book || $newParent->book_id === $newBook->id); | 
					
						
							|  |  |  |             $newParentPermission = ($newParent instanceof Chapter) ? 'chapter-update' : 'book-update'; | 
					
						
							|  |  |  |             $hasNewParentPermission = userCan($newParentPermission, $newParent); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 23:42:59 +08:00
										 |  |  |             $hasDeletePermissionIfMoving = (!$hasNewParent || userCan('page-delete', $model)); | 
					
						
							|  |  |  |             $hasCreatePermissionIfMoving = (!$hasNewParent || userCan('page-create', $newParent)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $hasPermission = $hasCurrentParentPermission | 
					
						
							|  |  |  |                 && $newParentInRightLocation | 
					
						
							|  |  |  |                 && $hasNewParentPermission | 
					
						
							|  |  |  |                 && $hasPageEditPermission | 
					
						
							|  |  |  |                 && $hasDeletePermissionIfMoving | 
					
						
							|  |  |  |                 && $hasCreatePermissionIfMoving; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 22:39:21 +08:00
										 |  |  |             if (!$hasPermission) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Load models from the database into the given sort map. | 
					
						
							| 
									
										
										
										
											2022-01-06 20:18:11 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |      * @return array<string, Entity> | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |     protected function loadModelsFromSortMap(BookSortMap $sortMap): array | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         $modelMap = []; | 
					
						
							|  |  |  |         $ids = [ | 
					
						
							|  |  |  |             'chapter' => [], | 
					
						
							| 
									
										
										
										
											2022-01-06 20:18:11 +08:00
										 |  |  |             'page'    => [], | 
					
						
							|  |  |  |             'book'    => [], | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($sortMap->all() as $sortMapItem) { | 
					
						
							|  |  |  |             $ids[$sortMapItem->type][] = $sortMapItem->id; | 
					
						
							|  |  |  |             $ids['book'][] = $sortMapItem->parentBookId; | 
					
						
							|  |  |  |             if ($sortMapItem->parentChapterId) { | 
					
						
							|  |  |  |                 $ids['chapter'][] = $sortMapItem->parentChapterId; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         $pages = Page::visible()->whereIn('id', array_unique($ids['page']))->get(Page::$listAttributes); | 
					
						
							|  |  |  |         /** @var Page $page */ | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         foreach ($pages as $page) { | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |             $modelMap['page:' . $page->id] = $page; | 
					
						
							|  |  |  |             $ids['book'][] = $page->book_id; | 
					
						
							|  |  |  |             if ($page->chapter_id) { | 
					
						
							|  |  |  |                 $ids['chapter'][] = $page->chapter_id; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         $chapters = Chapter::visible()->whereIn('id', array_unique($ids['chapter']))->get(); | 
					
						
							|  |  |  |         /** @var Chapter $chapter */ | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         foreach ($chapters as $chapter) { | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |             $modelMap['chapter:' . $chapter->id] = $chapter; | 
					
						
							|  |  |  |             $ids['book'][] = $chapter->book_id; | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         $books = Book::visible()->whereIn('id', array_unique($ids['book']))->get(); | 
					
						
							|  |  |  |         /** @var Book $book */ | 
					
						
							|  |  |  |         foreach ($books as $book) { | 
					
						
							|  |  |  |             $modelMap['book:' . $book->id] = $book; | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-05 05:09:34 +08:00
										 |  |  |         return $modelMap; | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | } |