]> BookStack Code Mirror - bookstack/blob - app/Entities/Tools/BookContents.php
Sorting: Reorganised book sort code to its own directory
[bookstack] / app / Entities / Tools / BookContents.php
1 <?php
2
3 namespace BookStack\Entities\Tools;
4
5 use BookStack\Entities\Models\Book;
6 use BookStack\Entities\Models\BookChild;
7 use BookStack\Entities\Models\Chapter;
8 use BookStack\Entities\Models\Entity;
9 use BookStack\Entities\Models\Page;
10 use BookStack\Entities\Queries\EntityQueries;
11 use BookStack\Sorting\BookSortMap;
12 use BookStack\Sorting\BookSortMapItem;
13 use Illuminate\Support\Collection;
14
15 class BookContents
16 {
17     protected EntityQueries $queries;
18
19     public function __construct(
20         protected Book $book,
21     ) {
22         $this->queries = app()->make(EntityQueries::class);
23     }
24
25     /**
26      * Get the current priority of the last item at the top-level of the book.
27      */
28     public function getLastPriority(): int
29     {
30         $maxPage = $this->book->pages()
31             ->where('draft', '=', false)
32             ->where('chapter_id', '=', 0)
33             ->max('priority');
34
35         $maxChapter = $this->book->chapters()
36             ->max('priority');
37
38         return max($maxChapter, $maxPage, 1);
39     }
40
41     /**
42      * Get the contents as a sorted collection tree.
43      */
44     public function getTree(bool $showDrafts = false, bool $renderPages = false): Collection
45     {
46         $pages = $this->getPages($showDrafts, $renderPages);
47         $chapters = $this->book->chapters()->scopes('visible')->get();
48         $all = collect()->concat($pages)->concat($chapters);
49         $chapterMap = $chapters->keyBy('id');
50         $lonePages = collect();
51
52         $pages->groupBy('chapter_id')->each(function ($pages, $chapter_id) use ($chapterMap, &$lonePages) {
53             $chapter = $chapterMap->get($chapter_id);
54             if ($chapter) {
55                 $chapter->setAttribute('visible_pages', collect($pages)->sortBy($this->bookChildSortFunc()));
56             } else {
57                 $lonePages = $lonePages->concat($pages);
58             }
59         });
60
61         $chapters->whereNull('visible_pages')->each(function (Chapter $chapter) {
62             $chapter->setAttribute('visible_pages', collect([]));
63         });
64
65         $all->each(function (Entity $entity) use ($renderPages) {
66             $entity->setRelation('book', $this->book);
67
68             if ($renderPages && $entity instanceof Page) {
69                 $entity->html = (new PageContent($entity))->render();
70             }
71         });
72
73         return collect($chapters)->concat($lonePages)->sortBy($this->bookChildSortFunc());
74     }
75
76     /**
77      * Function for providing a sorting score for an entity in relation to the
78      * other items within the book.
79      */
80     protected function bookChildSortFunc(): callable
81     {
82         return function (Entity $entity) {
83             if (isset($entity['draft']) && $entity['draft']) {
84                 return -100;
85             }
86
87             return $entity['priority'] ?? 0;
88         };
89     }
90
91     /**
92      * Get the visible pages within this book.
93      */
94     protected function getPages(bool $showDrafts = false, bool $getPageContent = false): Collection
95     {
96         if ($getPageContent) {
97             $query = $this->queries->pages->visibleWithContents();
98         } else {
99             $query = $this->queries->pages->visibleForList();
100         }
101
102         if (!$showDrafts) {
103             $query->where('draft', '=', false);
104         }
105
106         return $query->where('book_id', '=', $this->book->id)->get();
107     }
108 }