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