]> BookStack Code Mirror - bookstack/blob - app/Entities/Models/Page.php
Queries: Update API to align data with previous versions
[bookstack] / app / Entities / Models / Page.php
1 <?php
2
3 namespace BookStack\Entities\Models;
4
5 use BookStack\Entities\Tools\PageContent;
6 use BookStack\Permissions\PermissionApplicator;
7 use BookStack\Uploads\Attachment;
8 use Illuminate\Database\Eloquent\Builder;
9 use Illuminate\Database\Eloquent\Collection;
10 use Illuminate\Database\Eloquent\Factories\HasFactory;
11 use Illuminate\Database\Eloquent\Relations\BelongsTo;
12 use Illuminate\Database\Eloquent\Relations\HasMany;
13 use Illuminate\Database\Eloquent\Relations\HasOne;
14
15 /**
16  * Class Page.
17  *
18  * @property int          $chapter_id
19  * @property string       $html
20  * @property string       $markdown
21  * @property string       $text
22  * @property bool         $template
23  * @property bool         $draft
24  * @property int          $revision_count
25  * @property string       $editor
26  * @property Chapter      $chapter
27  * @property Collection   $attachments
28  * @property Collection   $revisions
29  * @property PageRevision $currentRevision
30  */
31 class Page extends BookChild
32 {
33     use HasFactory;
34
35     protected $fillable = ['name', 'priority'];
36
37     public string $textField = 'text';
38     public string $htmlField = 'html';
39
40     protected $hidden = ['html', 'markdown', 'text', 'pivot', 'deleted_at'];
41
42     protected $casts = [
43         'draft'    => 'boolean',
44         'template' => 'boolean',
45     ];
46
47     /**
48      * Get the entities that are visible to the current user.
49      */
50     public function scopeVisible(Builder $query): Builder
51     {
52         $query = app()->make(PermissionApplicator::class)->restrictDraftsOnPageQuery($query);
53
54         return parent::scopeVisible($query);
55     }
56
57     /**
58      * Get the chapter that this page is in, If applicable.
59      *
60      * @return BelongsTo
61      */
62     public function chapter()
63     {
64         return $this->belongsTo(Chapter::class);
65     }
66
67     /**
68      * Check if this page has a chapter.
69      */
70     public function hasChapter(): bool
71     {
72         return $this->chapter()->count() > 0;
73     }
74
75     /**
76      * Get the associated page revisions, ordered by created date.
77      * Only provides actual saved page revision instances, Not drafts.
78      */
79     public function revisions(): HasMany
80     {
81         return $this->allRevisions()
82             ->where('type', '=', 'version')
83             ->orderBy('created_at', 'desc')
84             ->orderBy('id', 'desc');
85     }
86
87     /**
88      * Get the current revision for the page if existing.
89      */
90     public function currentRevision(): HasOne
91     {
92         return $this->hasOne(PageRevision::class)
93             ->where('type', '=', 'version')
94             ->orderBy('created_at', 'desc')
95             ->orderBy('id', 'desc');
96     }
97
98     /**
99      * Get all revision instances assigned to this page.
100      * Includes all types of revisions.
101      */
102     public function allRevisions(): HasMany
103     {
104         return $this->hasMany(PageRevision::class);
105     }
106
107     /**
108      * Get the attachments assigned to this page.
109      *
110      * @return HasMany
111      */
112     public function attachments()
113     {
114         return $this->hasMany(Attachment::class, 'uploaded_to')->orderBy('order', 'asc');
115     }
116
117     /**
118      * Get the url of this page.
119      */
120     public function getUrl(string $path = ''): string
121     {
122         $parts = [
123             'books',
124             urlencode($this->book_slug ?? $this->book->slug),
125             $this->draft ? 'draft' : 'page',
126             $this->draft ? $this->id : urlencode($this->slug),
127             trim($path, '/'),
128         ];
129
130         return url('/' . implode('/', $parts));
131     }
132
133     /**
134      * Get this page for JSON display.
135      */
136     public function forJsonDisplay(): self
137     {
138         $refreshed = $this->refresh()->unsetRelations()->load(['tags', 'createdBy', 'updatedBy', 'ownedBy']);
139         $refreshed->setHidden(array_diff($refreshed->getHidden(), ['html', 'markdown']));
140         $refreshed->setAttribute('raw_html', $refreshed->html);
141         $refreshed->html = (new PageContent($refreshed))->render();
142
143         return $refreshed;
144     }
145 }