]> BookStack Code Mirror - bookstack/blob - app/Repos/ChapterRepo.php
Started refactor to merge entity repos
[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     protected $pageRepo;
13
14     /**
15      * ChapterRepo constructor.
16      * @param $pageRepo
17      */
18     public function __construct(PageRepo $pageRepo)
19     {
20         $this->pageRepo = $pageRepo;
21         parent::__construct();
22     }
23
24     /**
25      * Get the child items for a chapter
26      * @param Chapter $chapter
27      */
28     public function getChildren(Chapter $chapter)
29     {
30         $pages = $this->permissionService->enforcePageRestrictions($chapter->pages())->get();
31         // Sort items with drafts first then by priority.
32         return $pages->sortBy(function ($child, $key) {
33             $score = $child->priority;
34             if ($child->draft) $score -= 100;
35             return $score;
36         });
37     }
38
39     /**
40      * Create a new chapter from request input.
41      * @param $input
42      * @param Book $book
43      * @return Chapter
44      */
45     public function createFromInput($input, Book $book)
46     {
47         $chapter = $this->chapter->newInstance($input);
48         $chapter->slug = $this->findSuitableSlug($chapter->name, $book->id);
49         $chapter->created_by = user()->id;
50         $chapter->updated_by = user()->id;
51         $chapter = $book->chapters()->save($chapter);
52         $this->permissionService->buildJointPermissionsForEntity($chapter);
53         return $chapter;
54     }
55
56     /**
57      * Destroy a chapter and its relations by providing its slug.
58      * @param Chapter $chapter
59      */
60     public function destroy(Chapter $chapter)
61     {
62         if (count($chapter->pages) > 0) {
63             foreach ($chapter->pages as $page) {
64                 $page->chapter_id = 0;
65                 $page->save();
66             }
67         }
68         Activity::removeEntity($chapter);
69         $chapter->views()->delete();
70         $chapter->permissions()->delete();
71         $this->permissionService->deleteJointPermissionsForEntity($chapter);
72         $chapter->delete();
73     }
74
75     /**
76      * Check if a chapter's slug exists.
77      * @param            $slug
78      * @param            $bookId
79      * @param bool|false $currentId
80      * @return bool
81      */
82     public function doesSlugExist($slug, $bookId, $currentId = false)
83     {
84         $query = $this->chapter->where('slug', '=', $slug)->where('book_id', '=', $bookId);
85         if ($currentId) {
86             $query = $query->where('id', '!=', $currentId);
87         }
88         return $query->count() > 0;
89     }
90
91     /**
92      * Finds a suitable slug for the provided name.
93      * Checks database to prevent duplicate slugs.
94      * @param            $name
95      * @param            $bookId
96      * @param bool|false $currentId
97      * @return string
98      */
99     public function findSuitableSlug($name, $bookId, $currentId = false)
100     {
101         $slug = $this->nameToSlug($name);
102         while ($this->doesSlugExist($slug, $bookId, $currentId)) {
103             $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
104         }
105         return $slug;
106     }
107
108     /**
109      * Get a new priority value for a new page to be added
110      * to the given chapter.
111      * @param Chapter $chapter
112      * @return int
113      */
114     public function getNewPriority(Chapter $chapter)
115     {
116         $lastPage = $chapter->pages->last();
117         return $lastPage !== null ? $lastPage->priority + 1 : 0;
118     }
119
120     /**
121      * Get chapters by the given search term.
122      * @param string $term
123      * @param array $whereTerms
124      * @param int $count
125      * @param array $paginationAppends
126      * @return mixed
127      */
128     public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = [])
129     {
130         $terms = $this->prepareSearchTerms($term);
131         $chapterQuery = $this->permissionService->enforceChapterRestrictions($this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms));
132         $chapterQuery = $this->addAdvancedSearchQueries($chapterQuery, $term);
133         $chapters = $chapterQuery->paginate($count)->appends($paginationAppends);
134         $words = join('|', explode(' ', preg_quote(trim($term), '/')));
135         foreach ($chapters as $chapter) {
136             //highlight
137             $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $chapter->getExcerpt(100));
138             $chapter->searchSnippet = $result;
139         }
140         return $chapters;
141     }
142
143     /**
144      * Changes the book relation of this chapter.
145      * @param $bookId
146      * @param Chapter $chapter
147      * @param bool $rebuildPermissions
148      * @return Chapter
149      */
150     public function changeBook($bookId, Chapter $chapter, $rebuildPermissions = false)
151     {
152         $chapter->book_id = $bookId;
153         // Update related activity
154         foreach ($chapter->activity as $activity) {
155             $activity->book_id = $bookId;
156             $activity->save();
157         }
158         $chapter->slug = $this->findSuitableSlug($chapter->name, $bookId, $chapter->id);
159         $chapter->save();
160         // Update all child pages
161         foreach ($chapter->pages as $page) {
162             $this->pageRepo->changeBook($bookId, $page);
163         }
164
165         // Update permissions if applicable
166         if ($rebuildPermissions) {
167             $chapter->load('book');
168             $this->permissionService->buildJointPermissionsForEntity($chapter->book);
169         }
170
171         return $chapter;
172     }
173
174 }