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