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