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