]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/ReferenceController.php
Rolled out reference pages to all entities, added testing
[bookstack] / app / Http / Controllers / ReferenceController.php
1 <?php
2
3 namespace BookStack\Http\Controllers;
4
5 use BookStack\Auth\Permissions\PermissionApplicator;
6 use BookStack\Entities\Models\Book;
7 use BookStack\Entities\Models\Bookshelf;
8 use BookStack\Entities\Models\Chapter;
9 use BookStack\Entities\Models\Entity;
10 use BookStack\Entities\Models\Page;
11 use Illuminate\Database\Eloquent\Collection;
12 use Illuminate\Database\Eloquent\Relations\Relation;
13
14 class ReferenceController extends Controller
15 {
16
17     protected PermissionApplicator $permissions;
18
19     public function __construct(PermissionApplicator $permissions)
20     {
21         $this->permissions = $permissions;
22     }
23
24     /**
25      * Display the references to a given page.
26      */
27     public function page(string $bookSlug, string $pageSlug)
28     {
29         /** @var Page $page */
30         $page = Page::visible()->whereSlugs($bookSlug, $pageSlug)->firstOrFail();
31         $references = $this->getEntityReferences($page);
32
33         return view('pages.references', [
34             'page' => $page,
35             'references' => $references,
36         ]);
37     }
38
39     /**
40      * Display the references to a given chapter.
41      */
42     public function chapter(string $bookSlug, string $chapterSlug)
43     {
44         /** @var Chapter $chapter */
45         $chapter = Chapter::visible()->whereSlugs($bookSlug, $chapterSlug)->firstOrFail();
46         $references = $this->getEntityReferences($chapter);
47
48         return view('chapters.references', [
49             'chapter' => $chapter,
50             'references' => $references,
51         ]);
52     }
53
54     /**
55      * Display the references to a given book.
56      */
57     public function book(string $slug)
58     {
59         $book = Book::visible()->where('slug', '=', $slug)->firstOrFail();
60         $references = $this->getEntityReferences($book);
61
62         return view('books.references', [
63             'book' => $book,
64             'references' => $references,
65         ]);
66     }
67
68     /**
69      * Display the references to a given shelf.
70      */
71     public function shelf(string $slug)
72     {
73         $shelf = Bookshelf::visible()->where('slug', '=', $slug)->firstOrFail();
74         $references = $this->getEntityReferences($shelf);
75
76         return view('shelves.references', [
77             'shelf' => $shelf,
78             'references' => $references,
79         ]);
80     }
81
82     /**
83      * Query the references for the given entities.
84      * Loads the commonly required relations while taking permissions into account.
85      */
86     protected function getEntityReferences(Entity $entity): Collection
87     {
88         $baseQuery = $entity->referencesTo()
89             ->where('from_type', '=', (new Page())->getMorphClass())
90             ->with([
91                 'from' => fn(Relation $query) => $query->select(Page::$listAttributes),
92                 'from.book' => fn(Relation $query) => $query->scopes('visible'),
93                 'from.chapter' => fn(Relation $query) => $query->scopes('visible')
94             ]);
95
96         $references = $this->permissions->restrictEntityRelationQuery(
97             $baseQuery,
98             'references',
99             'from_id',
100             'from_type'
101         )->get();
102
103         return $references;
104     }
105 }