]> BookStack Code Mirror - bookstack/blob - app/Repos/ChapterRepo.php
Added restriction tests and fixed any bugs in the process
[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         $terms = explode(' ', $term);
160         $chapters = $this->restrictionService->enforceChapterRestrictions($this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms))
161             ->paginate($count)->appends($paginationAppends);
162         $words = join('|', explode(' ', preg_quote(trim($term), '/')));
163         foreach ($chapters as $chapter) {
164             //highlight
165             $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $chapter->getExcerpt(100));
166             $chapter->searchSnippet = $result;
167         }
168         return $chapters;
169     }
170
171     /**
172      * Changes the book relation of this chapter.
173      * @param         $bookId
174      * @param Chapter $chapter
175      * @return Chapter
176      */
177     public function changeBook($bookId, Chapter $chapter)
178     {
179         $chapter->book_id = $bookId;
180         foreach ($chapter->activity as $activity) {
181             $activity->book_id = $bookId;
182             $activity->save();
183         }
184         $chapter->slug = $this->findSuitableSlug($chapter->name, $bookId, $chapter->id);
185         $chapter->save();
186         return $chapter;
187     }
188
189     /**
190      * Updates pages restrictions from a request
191      * @param $request
192      * @param $chapter
193      */
194     public function updateRestrictionsFromRequest($request, $chapter)
195     {
196         // TODO - extract into shared repo
197         $chapter->restricted = $request->has('restricted') && $request->get('restricted') === 'true';
198         $chapter->restrictions()->delete();
199         if ($request->has('restrictions')) {
200             foreach($request->get('restrictions') as $roleId => $restrictions) {
201                 foreach ($restrictions as $action => $value) {
202                     $chapter->restrictions()->create([
203                         'role_id' => $roleId,
204                         'action'  => strtolower($action)
205                     ]);
206                 }
207             }
208         }
209         $chapter->save();
210     }
211
212 }