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