]> BookStack Code Mirror - bookstack/blob - app/Repos/ChapterRepo.php
Merge branch 'custom_role_system'
[bookstack] / app / Repos / ChapterRepo.php
1 <?php namespace BookStack\Repos;
2
3
4 use Activity;
5 use BookStack\Exceptions\NotFoundException;
6 use BookStack\Services\RestrictionService;
7 use Illuminate\Support\Str;
8 use BookStack\Chapter;
9
10 class ChapterRepo
11 {
12
13     protected $chapter;
14     protected $restrictionService;
15
16     /**
17      * ChapterRepo constructor.
18      * @param Chapter $chapter
19      * @param RestrictionService $restrictionService
20      */
21     public function __construct(Chapter $chapter, RestrictionService $restrictionService)
22     {
23         $this->chapter = $chapter;
24         $this->restrictionService = $restrictionService;
25     }
26
27     /**
28      * Base query for getting chapters, Takes restrictions into account.
29      * @return mixed
30      */
31     private function chapterQuery()
32     {
33         return $this->restrictionService->enforceChapterRestrictions($this->chapter, 'view');
34     }
35
36     /**
37      * Check if an id exists.
38      * @param $id
39      * @return bool
40      */
41     public function idExists($id)
42     {
43         return $this->chapterQuery()->where('id', '=', $id)->count() > 0;
44     }
45
46     /**
47      * Get a chapter by a specific id.
48      * @param $id
49      * @return mixed
50      */
51     public function getById($id)
52     {
53         return $this->chapterQuery()->findOrFail($id);
54     }
55
56     /**
57      * Get all chapters.
58      * @return \Illuminate\Database\Eloquent\Collection|static[]
59      */
60     public function getAll()
61     {
62         return $this->chapterQuery()->all();
63     }
64
65     /**
66      * Get a chapter that has the given slug within the given book.
67      * @param $slug
68      * @param $bookId
69      * @return mixed
70      * @throws NotFoundException
71      */
72     public function getBySlug($slug, $bookId)
73     {
74         $chapter = $this->chapterQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
75         if ($chapter === null) throw new NotFoundException('Chapter not found');
76         return $chapter;
77     }
78
79     /**
80      * Get the child items for a chapter
81      * @param Chapter $chapter
82      */
83     public function getChildren(Chapter $chapter)
84     {
85         return $this->restrictionService->enforcePageRestrictions($chapter->pages())->get();
86     }
87
88     /**
89      * Create a new chapter from request input.
90      * @param $input
91      * @return $this
92      */
93     public function newFromInput($input)
94     {
95         return $this->chapter->fill($input);
96     }
97
98     /**
99      * Destroy a chapter and its relations by providing its slug.
100      * @param Chapter $chapter
101      */
102     public function destroy(Chapter $chapter)
103     {
104         if (count($chapter->pages) > 0) {
105             foreach ($chapter->pages as $page) {
106                 $page->chapter_id = 0;
107                 $page->save();
108             }
109         }
110         Activity::removeEntity($chapter);
111         $chapter->views()->delete();
112         $chapter->restrictions()->delete();
113         $chapter->delete();
114     }
115
116     /**
117      * Check if a chapter's slug exists.
118      * @param            $slug
119      * @param            $bookId
120      * @param bool|false $currentId
121      * @return bool
122      */
123     public function doesSlugExist($slug, $bookId, $currentId = false)
124     {
125         $query = $this->chapter->where('slug', '=', $slug)->where('book_id', '=', $bookId);
126         if ($currentId) {
127             $query = $query->where('id', '!=', $currentId);
128         }
129         return $query->count() > 0;
130     }
131
132     /**
133      * Finds a suitable slug for the provided name.
134      * Checks database to prevent duplicate slugs.
135      * @param            $name
136      * @param            $bookId
137      * @param bool|false $currentId
138      * @return string
139      */
140     public function findSuitableSlug($name, $bookId, $currentId = false)
141     {
142         $slug = Str::slug($name);
143         while ($this->doesSlugExist($slug, $bookId, $currentId)) {
144             $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
145         }
146         return $slug;
147     }
148
149     /**
150      * Get chapters by the given search term.
151      * @param       $term
152      * @param array $whereTerms
153      * @param int $count
154      * @param array $paginationAppends
155      * @return mixed
156      */
157     public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = [])
158     {
159         preg_match_all('/"(.*?)"/', $term, $matches);
160         if (count($matches[1]) > 0) {
161             $terms = $matches[1];
162             $term = trim(preg_replace('/"(.*?)"/', '', $term));
163         } else {
164             $terms = [];
165         }
166         if (!empty($term)) {
167             $terms = array_merge($terms, explode(' ', $term));
168         }
169         $chapters = $this->restrictionService->enforceChapterRestrictions($this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms))
170             ->paginate($count)->appends($paginationAppends);
171         $words = join('|', explode(' ', preg_quote(trim($term), '/')));
172         foreach ($chapters as $chapter) {
173             //highlight
174             $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $chapter->getExcerpt(100));
175             $chapter->searchSnippet = $result;
176         }
177         return $chapters;
178     }
179
180     /**
181      * Changes the book relation of this chapter.
182      * @param         $bookId
183      * @param Chapter $chapter
184      * @return Chapter
185      */
186     public function changeBook($bookId, Chapter $chapter)
187     {
188         $chapter->book_id = $bookId;
189         foreach ($chapter->activity as $activity) {
190             $activity->book_id = $bookId;
191             $activity->save();
192         }
193         $chapter->slug = $this->findSuitableSlug($chapter->name, $bookId, $chapter->id);
194         $chapter->save();
195         return $chapter;
196     }
197
198     /**
199      * Updates pages restrictions from a request
200      * @param $request
201      * @param $chapter
202      */
203     public function updateRestrictionsFromRequest($request, $chapter)
204     {
205         // TODO - extract into shared repo
206         $chapter->restricted = $request->has('restricted') && $request->get('restricted') === 'true';
207         $chapter->restrictions()->delete();
208         if ($request->has('restrictions')) {
209             foreach($request->get('restrictions') as $roleId => $restrictions) {
210                 foreach ($restrictions as $action => $value) {
211                     $chapter->restrictions()->create([
212                         'role_id' => $roleId,
213                         'action'  => strtolower($action)
214                     ]);
215                 }
216             }
217         }
218         $chapter->save();
219     }
220
221 }