]> BookStack Code Mirror - bookstack/blob - app/Entities/Models/Book.php
Input WYSIWYG: Added reference store & fetch handling
[bookstack] / app / Entities / Models / Book.php
1 <?php
2
3 namespace BookStack\Entities\Models;
4
5 use BookStack\Uploads\Image;
6 use Exception;
7 use Illuminate\Database\Eloquent\Factories\HasFactory;
8 use Illuminate\Database\Eloquent\Relations\BelongsTo;
9 use Illuminate\Database\Eloquent\Relations\BelongsToMany;
10 use Illuminate\Database\Eloquent\Relations\HasMany;
11 use Illuminate\Support\Collection;
12
13 /**
14  * Class Book.
15  *
16  * @property string                                   $description
17  * @property int                                      $image_id
18  * @property ?int                                     $default_template_id
19  * @property Image|null                               $cover
20  * @property \Illuminate\Database\Eloquent\Collection $chapters
21  * @property \Illuminate\Database\Eloquent\Collection $pages
22  * @property \Illuminate\Database\Eloquent\Collection $directPages
23  * @property \Illuminate\Database\Eloquent\Collection $shelves
24  * @property ?Page                                    $defaultTemplate
25  */
26 class Book extends Entity implements HasCoverImage
27 {
28     use HasFactory;
29     use HasHtmlDescription;
30
31     public float $searchFactor = 1.2;
32
33     protected $fillable = ['name'];
34     protected $hidden = ['pivot', 'image_id', 'deleted_at'];
35
36     /**
37      * Get the url for this book.
38      */
39     public function getUrl(string $path = ''): string
40     {
41         return url('/books/' . implode('/', [urlencode($this->slug), trim($path, '/')]));
42     }
43
44     /**
45      * Returns book cover image, if book cover not exists return default cover image.
46      */
47     public function getBookCover(int $width = 440, int $height = 250): string
48     {
49         $default = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
50         if (!$this->image_id || !$this->cover) {
51             return $default;
52         }
53
54         try {
55             return $this->cover->getThumb($width, $height, false) ?? $default;
56         } catch (Exception $err) {
57             return $default;
58         }
59     }
60
61     /**
62      * Get the cover image of the book.
63      */
64     public function cover(): BelongsTo
65     {
66         return $this->belongsTo(Image::class, 'image_id');
67     }
68
69     /**
70      * Get the type of the image model that is used when storing a cover image.
71      */
72     public function coverImageTypeKey(): string
73     {
74         return 'cover_book';
75     }
76
77     /**
78      * Get the Page that is used as default template for newly created pages within this Book.
79      */
80     public function defaultTemplate(): BelongsTo
81     {
82         return $this->belongsTo(Page::class, 'default_template_id');
83     }
84
85     /**
86      * Get all pages within this book.
87      */
88     public function pages(): HasMany
89     {
90         return $this->hasMany(Page::class);
91     }
92
93     /**
94      * Get the direct child pages of this book.
95      */
96     public function directPages(): HasMany
97     {
98         return $this->pages()->where('chapter_id', '=', '0');
99     }
100
101     /**
102      * Get all chapters within this book.
103      */
104     public function chapters(): HasMany
105     {
106         return $this->hasMany(Chapter::class);
107     }
108
109     /**
110      * Get the shelves this book is contained within.
111      */
112     public function shelves(): BelongsToMany
113     {
114         return $this->belongsToMany(Bookshelf::class, 'bookshelves_books', 'book_id', 'bookshelf_id');
115     }
116
117     /**
118      * Get the direct child items within this book.
119      */
120     public function getDirectChildren(): Collection
121     {
122         $pages = $this->directPages()->scopes('visible')->get();
123         $chapters = $this->chapters()->scopes('visible')->get();
124
125         return $pages->concat($chapters)->sortBy('priority')->sortByDesc('draft');
126     }
127
128     /**
129      * Get a visible book by its slug.
130      * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
131      */
132     public static function getBySlug(string $slug): self
133     {
134         return static::visible()->where('slug', '=', $slug)->firstOrFail();
135     }
136 }