| 
									
										
										
										
											2015-09-11 02:31:09 +08:00
										 |  |  | <?php namespace BookStack\Repos; | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  | use Activity; | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  | use BookStack\Book; | 
					
						
							| 
									
										
										
										
											2016-03-06 02:09:21 +08:00
										 |  |  | use BookStack\Exceptions\NotFoundException; | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  | use Illuminate\Support\Str; | 
					
						
							| 
									
										
										
										
											2015-09-11 02:31:09 +08:00
										 |  |  | use BookStack\Chapter; | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 03:00:26 +08:00
										 |  |  | class ChapterRepo extends EntityRepo | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-25 22:31:38 +08:00
										 |  |  |     protected $pageRepo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * ChapterRepo constructor. | 
					
						
							|  |  |  |      * @param $pageRepo | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function __construct(PageRepo $pageRepo) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->pageRepo = $pageRepo; | 
					
						
							|  |  |  |         parent::__construct(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |      * Base query for getting chapters, Takes permissions into account. | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function chapterQuery() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         return $this->permissionService->enforceChapterRestrictions($this->chapter, 'view'); | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Check if an id exists. | 
					
						
							|  |  |  |      * @param $id | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-07-31 05:27:35 +08:00
										 |  |  |     public function idExists($id) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |         return $this->chapterQuery()->where('id', '=', $id)->count() > 0; | 
					
						
							| 
									
										
										
										
											2015-07-31 05:27:35 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get a chapter by a specific id. | 
					
						
							|  |  |  |      * @param $id | 
					
						
							|  |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     public function getById($id) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |         return $this->chapterQuery()->findOrFail($id); | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get all chapters. | 
					
						
							|  |  |  |      * @return \Illuminate\Database\Eloquent\Collection|static[] | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     public function getAll() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |         return $this->chapterQuery()->all(); | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get a chapter that has the given slug within the given book. | 
					
						
							|  |  |  |      * @param $slug | 
					
						
							|  |  |  |      * @param $bookId | 
					
						
							|  |  |  |      * @return mixed | 
					
						
							| 
									
										
										
										
											2016-03-06 02:09:21 +08:00
										 |  |  |      * @throws NotFoundException | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     public function getBySlug($slug, $bookId) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-02-29 03:03:04 +08:00
										 |  |  |         $chapter = $this->chapterQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first(); | 
					
						
							| 
									
										
										
										
											2016-03-06 02:09:21 +08:00
										 |  |  |         if ($chapter === null) throw new NotFoundException('Chapter not found'); | 
					
						
							| 
									
										
										
										
											2015-12-29 01:19:23 +08:00
										 |  |  |         return $chapter; | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 02:09:21 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get the child items for a chapter | 
					
						
							|  |  |  |      * @param Chapter $chapter | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getChildren(Chapter $chapter) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $pages = $this->permissionService->enforcePageRestrictions($chapter->pages())->get(); | 
					
						
							| 
									
										
										
										
											2016-03-13 20:04:08 +08:00
										 |  |  |         // Sort items with drafts first then by priority.
 | 
					
						
							| 
									
										
										
										
											2016-08-13 20:53:04 +08:00
										 |  |  |         return $pages->sortBy(function ($child, $key) { | 
					
						
							| 
									
										
										
										
											2016-03-13 20:04:08 +08:00
										 |  |  |             $score = $child->priority; | 
					
						
							|  |  |  |             if ($child->draft) $score -= 100; | 
					
						
							|  |  |  |             return $score; | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2016-03-06 02:09:21 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Create a new chapter from request input. | 
					
						
							|  |  |  |      * @param $input | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |      * @param Book $book | 
					
						
							|  |  |  |      * @return Chapter | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |     public function createFromInput($input, Book $book) | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |         $chapter = $this->chapter->newInstance($input); | 
					
						
							|  |  |  |         $chapter->slug = $this->findSuitableSlug($chapter->name, $book->id); | 
					
						
							|  |  |  |         $chapter->created_by = auth()->user()->id; | 
					
						
							|  |  |  |         $chapter->updated_by = auth()->user()->id; | 
					
						
							|  |  |  |         $chapter = $book->chapters()->save($chapter); | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $this->permissionService->buildJointPermissionsForEntity($chapter); | 
					
						
							| 
									
										
										
										
											2016-04-24 23:54:20 +08:00
										 |  |  |         return $chapter; | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Destroy a chapter and its relations by providing its slug. | 
					
						
							|  |  |  |      * @param Chapter $chapter | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function destroy(Chapter $chapter) | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |         if (count($chapter->pages) > 0) { | 
					
						
							|  |  |  |             foreach ($chapter->pages as $page) { | 
					
						
							|  |  |  |                 $page->chapter_id = 0; | 
					
						
							|  |  |  |                 $page->save(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Activity::removeEntity($chapter); | 
					
						
							|  |  |  |         $chapter->views()->delete(); | 
					
						
							| 
									
										
										
										
											2016-05-02 04:20:50 +08:00
										 |  |  |         $chapter->permissions()->delete(); | 
					
						
							|  |  |  |         $this->permissionService->deleteJointPermissionsForEntity($chapter); | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |         $chapter->delete(); | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Check if a chapter's slug exists. | 
					
						
							|  |  |  |      * @param            $slug | 
					
						
							|  |  |  |      * @param            $bookId | 
					
						
							|  |  |  |      * @param bool|false $currentId | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     public function doesSlugExist($slug, $bookId, $currentId = false) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $query = $this->chapter->where('slug', '=', $slug)->where('book_id', '=', $bookId); | 
					
						
							| 
									
										
										
										
											2015-11-22 02:11:46 +08:00
										 |  |  |         if ($currentId) { | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |             $query = $query->where('id', '!=', $currentId); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return $query->count() > 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Finds a suitable slug for the provided name. | 
					
						
							|  |  |  |      * Checks database to prevent duplicate slugs. | 
					
						
							|  |  |  |      * @param            $name | 
					
						
							|  |  |  |      * @param            $bookId | 
					
						
							|  |  |  |      * @param bool|false $currentId | 
					
						
							|  |  |  |      * @return string | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-07-29 03:57:13 +08:00
										 |  |  |     public function findSuitableSlug($name, $bookId, $currentId = false) | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $slug = Str::slug($name); | 
					
						
							| 
									
										
										
										
											2016-08-13 20:53:04 +08:00
										 |  |  |         if ($slug === "") $slug = substr(md5(rand(1, 500)), 0, 5); | 
					
						
							| 
									
										
										
										
											2015-11-22 02:11:46 +08:00
										 |  |  |         while ($this->doesSlugExist($slug, $bookId, $currentId)) { | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  |             $slug .= '-' . substr(md5(rand(1, 500)), 0, 3); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return $slug; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-08 02:03:00 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get a new priority value for a new page to be added | 
					
						
							|  |  |  |      * to the given chapter. | 
					
						
							|  |  |  |      * @param Chapter $chapter | 
					
						
							|  |  |  |      * @return int | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getNewPriority(Chapter $chapter) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $lastPage = $chapter->pages->last(); | 
					
						
							|  |  |  |         return $lastPage !== null ? $lastPage->priority + 1 : 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Get chapters by the given search term. | 
					
						
							| 
									
										
										
										
											2016-03-06 03:00:26 +08:00
										 |  |  |      * @param string $term | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |      * @param array $whereTerms | 
					
						
							| 
									
										
										
										
											2016-02-21 20:53:58 +08:00
										 |  |  |      * @param int $count | 
					
						
							|  |  |  |      * @param array $paginationAppends | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |      * @return mixed | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2016-02-21 20:53:58 +08:00
										 |  |  |     public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = []) | 
					
						
							| 
									
										
										
										
											2015-09-01 03:11:44 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-03-06 03:00:26 +08:00
										 |  |  |         $terms = $this->prepareSearchTerms($term); | 
					
						
							| 
									
										
										
										
											2016-05-15 20:41:18 +08:00
										 |  |  |         $chapterQuery = $this->permissionService->enforceChapterRestrictions($this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms)); | 
					
						
							|  |  |  |         $chapterQuery = $this->addAdvancedSearchQueries($chapterQuery, $term); | 
					
						
							|  |  |  |         $chapters = $chapterQuery->paginate($count)->appends($paginationAppends); | 
					
						
							| 
									
										
										
										
											2015-12-29 23:37:13 +08:00
										 |  |  |         $words = join('|', explode(' ', preg_quote(trim($term), '/'))); | 
					
						
							| 
									
										
										
										
											2015-09-01 03:11:44 +08:00
										 |  |  |         foreach ($chapters as $chapter) { | 
					
						
							|  |  |  |             //highlight
 | 
					
						
							|  |  |  |             $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $chapter->getExcerpt(100)); | 
					
						
							|  |  |  |             $chapter->searchSnippet = $result; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return $chapters; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2015-11-22 02:11:46 +08:00
										 |  |  |      * Changes the book relation of this chapter. | 
					
						
							| 
									
										
										
										
											2015-11-22 02:05:03 +08:00
										 |  |  |      * @param         $bookId | 
					
						
							|  |  |  |      * @param Chapter $chapter | 
					
						
							|  |  |  |      * @return Chapter | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2015-11-22 02:11:46 +08:00
										 |  |  |     public function changeBook($bookId, Chapter $chapter) | 
					
						
							| 
									
										
										
										
											2015-09-06 21:35:53 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $chapter->book_id = $bookId; | 
					
						
							| 
									
										
										
										
											2016-06-25 22:31:38 +08:00
										 |  |  |         // Update related activity
 | 
					
						
							| 
									
										
										
										
											2015-11-22 02:11:46 +08:00
										 |  |  |         foreach ($chapter->activity as $activity) { | 
					
						
							| 
									
										
										
										
											2015-09-06 21:35:53 +08:00
										 |  |  |             $activity->book_id = $bookId; | 
					
						
							|  |  |  |             $activity->save(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-11-22 02:11:46 +08:00
										 |  |  |         $chapter->slug = $this->findSuitableSlug($chapter->name, $bookId, $chapter->id); | 
					
						
							| 
									
										
										
										
											2015-09-06 21:35:53 +08:00
										 |  |  |         $chapter->save(); | 
					
						
							| 
									
										
										
										
											2016-06-25 22:31:38 +08:00
										 |  |  |         // Update all child pages
 | 
					
						
							|  |  |  |         foreach ($chapter->pages as $page) { | 
					
						
							|  |  |  |             $this->pageRepo->changeBook($bookId, $page); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // Update permissions
 | 
					
						
							|  |  |  |         $chapter->load('book'); | 
					
						
							|  |  |  |         $this->permissionService->buildJointPermissionsForEntity($chapter->book); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-06 21:35:53 +08:00
										 |  |  |         return $chapter; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-28 03:17:08 +08:00
										 |  |  | } |