Dan Brown

Refactored search and slug repo components

...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
4 class Entity extends Ownable 4 class Entity extends Ownable
5 { 5 {
6 6
7 + protected $fieldsToSearch = ['name', 'description'];
8 +
7 /** 9 /**
8 * Compares this entity to another given entity. 10 * Compares this entity to another given entity.
9 * Matches by comparing class and id. 11 * Matches by comparing class and id.
...@@ -157,7 +159,7 @@ class Entity extends Ownable ...@@ -157,7 +159,7 @@ class Entity extends Ownable
157 * @param string[] array $wheres 159 * @param string[] array $wheres
158 * @return mixed 160 * @return mixed
159 */ 161 */
160 - public function fullTextSearchQuery($fieldsToSearch, $terms, $wheres = []) 162 + public function fullTextSearchQuery($terms, $wheres = [])
161 { 163 {
162 $exactTerms = []; 164 $exactTerms = [];
163 $fuzzyTerms = []; 165 $fuzzyTerms = [];
...@@ -181,16 +183,16 @@ class Entity extends Ownable ...@@ -181,16 +183,16 @@ class Entity extends Ownable
181 // Perform fulltext search if relevant terms exist. 183 // Perform fulltext search if relevant terms exist.
182 if ($isFuzzy) { 184 if ($isFuzzy) {
183 $termString = implode(' ', $fuzzyTerms); 185 $termString = implode(' ', $fuzzyTerms);
184 - $fields = implode(',', $fieldsToSearch); 186 + $fields = implode(',', $this->fieldsToSearch);
185 $search = $search->selectRaw('*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS title_relevance', [$termString]); 187 $search = $search->selectRaw('*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS title_relevance', [$termString]);
186 $search = $search->whereRaw('MATCH(' . $fields . ') AGAINST(? IN BOOLEAN MODE)', [$termString]); 188 $search = $search->whereRaw('MATCH(' . $fields . ') AGAINST(? IN BOOLEAN MODE)', [$termString]);
187 } 189 }
188 190
189 // Ensure at least one exact term matches if in search 191 // Ensure at least one exact term matches if in search
190 if (count($exactTerms) > 0) { 192 if (count($exactTerms) > 0) {
191 - $search = $search->where(function ($query) use ($exactTerms, $fieldsToSearch) { 193 + $search = $search->where(function ($query) use ($exactTerms) {
192 foreach ($exactTerms as $exactTerm) { 194 foreach ($exactTerms as $exactTerm) {
193 - foreach ($fieldsToSearch as $field) { 195 + foreach ($this->fieldsToSearch as $field) {
194 $query->orWhere($field, 'like', $exactTerm); 196 $query->orWhere($field, 'like', $exactTerm);
195 } 197 }
196 } 198 }
......
...@@ -118,7 +118,7 @@ class ChapterController extends Controller ...@@ -118,7 +118,7 @@ class ChapterController extends Controller
118 $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug); 118 $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
119 $this->checkOwnablePermission('chapter-update', $chapter); 119 $this->checkOwnablePermission('chapter-update', $chapter);
120 if ($chapter->name !== $request->get('name')) { 120 if ($chapter->name !== $request->get('name')) {
121 - $chapter->slug = $this->chapterRepo->findSuitableSlug($request->get('name'), $chapter->book->id, $chapter->id); 121 + $chapter->slug = $this->entityRepo->findSuitableSlug('chapter', $request->get('name'), $chapter->id, $chapter->book->id);
122 } 122 }
123 $chapter->fill($request->all()); 123 $chapter->fill($request->all());
124 $chapter->updated_by = user()->id; 124 $chapter->updated_by = user()->id;
......
...@@ -26,6 +26,7 @@ class PageController extends Controller ...@@ -26,6 +26,7 @@ class PageController extends Controller
26 26
27 /** 27 /**
28 * PageController constructor. 28 * PageController constructor.
29 + * @param EntityRepo $entityRepo
29 * @param PageRepo $pageRepo 30 * @param PageRepo $pageRepo
30 * @param BookRepo $bookRepo 31 * @param BookRepo $bookRepo
31 * @param ChapterRepo $chapterRepo 32 * @param ChapterRepo $chapterRepo
......
1 <?php namespace BookStack\Http\Controllers; 1 <?php namespace BookStack\Http\Controllers;
2 2
3 +use BookStack\Repos\EntityRepo;
3 use BookStack\Services\ViewService; 4 use BookStack\Services\ViewService;
4 use Illuminate\Http\Request; 5 use Illuminate\Http\Request;
5 -use BookStack\Repos\BookRepo;
6 -use BookStack\Repos\ChapterRepo;
7 -use BookStack\Repos\PageRepo;
8 6
9 class SearchController extends Controller 7 class SearchController extends Controller
10 { 8 {
11 - protected $pageRepo; 9 + protected $entityRepo;
12 - protected $bookRepo;
13 - protected $chapterRepo;
14 protected $viewService; 10 protected $viewService;
15 11
16 /** 12 /**
17 * SearchController constructor. 13 * SearchController constructor.
18 - * @param PageRepo $pageRepo 14 + * @param EntityRepo $entityRepo
19 - * @param BookRepo $bookRepo
20 - * @param ChapterRepo $chapterRepo
21 * @param ViewService $viewService 15 * @param ViewService $viewService
22 */ 16 */
23 - public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, ViewService $viewService) 17 + public function __construct(EntityRepo $entityRepo, ViewService $viewService)
24 { 18 {
25 - $this->pageRepo = $pageRepo; 19 + $this->entityRepo = $entityRepo;
26 - $this->bookRepo = $bookRepo;
27 - $this->chapterRepo = $chapterRepo;
28 $this->viewService = $viewService; 20 $this->viewService = $viewService;
29 parent::__construct(); 21 parent::__construct();
30 } 22 }
...@@ -42,9 +34,9 @@ class SearchController extends Controller ...@@ -42,9 +34,9 @@ class SearchController extends Controller
42 } 34 }
43 $searchTerm = $request->get('term'); 35 $searchTerm = $request->get('term');
44 $paginationAppends = $request->only('term'); 36 $paginationAppends = $request->only('term');
45 - $pages = $this->pageRepo->getBySearch($searchTerm, [], 20, $paginationAppends); 37 + $pages = $this->entityRepo->getBySearch('page', $searchTerm, [], 20, $paginationAppends);
46 - $books = $this->bookRepo->getBySearch($searchTerm, 10, $paginationAppends); 38 + $books = $this->entityRepo->getBySearch('book', $searchTerm, [], 10, $paginationAppends);
47 - $chapters = $this->chapterRepo->getBySearch($searchTerm, [], 10, $paginationAppends); 39 + $chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, [], 10, $paginationAppends);
48 $this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm])); 40 $this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm]));
49 return view('search/all', [ 41 return view('search/all', [
50 'pages' => $pages, 42 'pages' => $pages,
...@@ -65,7 +57,7 @@ class SearchController extends Controller ...@@ -65,7 +57,7 @@ class SearchController extends Controller
65 57
66 $searchTerm = $request->get('term'); 58 $searchTerm = $request->get('term');
67 $paginationAppends = $request->only('term'); 59 $paginationAppends = $request->only('term');
68 - $pages = $this->pageRepo->getBySearch($searchTerm, [], 20, $paginationAppends); 60 + $pages = $this->entityRepo->getBySearch('page', $searchTerm, [], 20, $paginationAppends);
69 $this->setPageTitle(trans('entities.search_page_for_term', ['term' => $searchTerm])); 61 $this->setPageTitle(trans('entities.search_page_for_term', ['term' => $searchTerm]));
70 return view('search/entity-search-list', [ 62 return view('search/entity-search-list', [
71 'entities' => $pages, 63 'entities' => $pages,
...@@ -85,7 +77,7 @@ class SearchController extends Controller ...@@ -85,7 +77,7 @@ class SearchController extends Controller
85 77
86 $searchTerm = $request->get('term'); 78 $searchTerm = $request->get('term');
87 $paginationAppends = $request->only('term'); 79 $paginationAppends = $request->only('term');
88 - $chapters = $this->chapterRepo->getBySearch($searchTerm, [], 20, $paginationAppends); 80 + $chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, [], 20, $paginationAppends);
89 $this->setPageTitle(trans('entities.search_chapter_for_term', ['term' => $searchTerm])); 81 $this->setPageTitle(trans('entities.search_chapter_for_term', ['term' => $searchTerm]));
90 return view('search/entity-search-list', [ 82 return view('search/entity-search-list', [
91 'entities' => $chapters, 83 'entities' => $chapters,
...@@ -105,7 +97,7 @@ class SearchController extends Controller ...@@ -105,7 +97,7 @@ class SearchController extends Controller
105 97
106 $searchTerm = $request->get('term'); 98 $searchTerm = $request->get('term');
107 $paginationAppends = $request->only('term'); 99 $paginationAppends = $request->only('term');
108 - $books = $this->bookRepo->getBySearch($searchTerm, 20, $paginationAppends); 100 + $books = $this->entityRepo->getBySearch('book', $searchTerm, [], 20, $paginationAppends);
109 $this->setPageTitle(trans('entities.search_book_for_term', ['term' => $searchTerm])); 101 $this->setPageTitle(trans('entities.search_book_for_term', ['term' => $searchTerm]));
110 return view('search/entity-search-list', [ 102 return view('search/entity-search-list', [
111 'entities' => $books, 103 'entities' => $books,
...@@ -128,8 +120,8 @@ class SearchController extends Controller ...@@ -128,8 +120,8 @@ class SearchController extends Controller
128 } 120 }
129 $searchTerm = $request->get('term'); 121 $searchTerm = $request->get('term');
130 $searchWhereTerms = [['book_id', '=', $bookId]]; 122 $searchWhereTerms = [['book_id', '=', $bookId]];
131 - $pages = $this->pageRepo->getBySearch($searchTerm, $searchWhereTerms); 123 + $pages = $this->entityRepo->getBySearch('page', $searchTerm, $searchWhereTerms);
132 - $chapters = $this->chapterRepo->getBySearch($searchTerm, $searchWhereTerms); 124 + $chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, $searchWhereTerms);
133 return view('search/book', ['pages' => $pages, 'chapters' => $chapters, 'searchTerm' => $searchTerm]); 125 return view('search/book', ['pages' => $pages, 'chapters' => $chapters, 'searchTerm' => $searchTerm]);
134 } 126 }
135 127
...@@ -148,9 +140,11 @@ class SearchController extends Controller ...@@ -148,9 +140,11 @@ class SearchController extends Controller
148 140
149 // Search for entities otherwise show most popular 141 // Search for entities otherwise show most popular
150 if ($searchTerm !== false) { 142 if ($searchTerm !== false) {
151 - if ($entityTypes->contains('page')) $entities = $entities->merge($this->pageRepo->getBySearch($searchTerm)->items()); 143 + foreach (['page', 'chapter', 'book'] as $entityType) {
152 - if ($entityTypes->contains('chapter')) $entities = $entities->merge($this->chapterRepo->getBySearch($searchTerm)->items()); 144 + if ($entityTypes->contains($entityType)) {
153 - if ($entityTypes->contains('book')) $entities = $entities->merge($this->bookRepo->getBySearch($searchTerm)->items()); 145 + $entities = $entities->merge($this->entityRepo->getBySearch($entityType, $searchTerm)->items());
146 + }
147 + }
154 $entities = $entities->sortByDesc('title_relevance'); 148 $entities = $entities->sortByDesc('title_relevance');
155 } else { 149 } else {
156 $entityNames = $entityTypes->map(function ($type) { 150 $entityNames = $entityTypes->map(function ($type) {
......
...@@ -9,6 +9,8 @@ class Page extends Entity ...@@ -9,6 +9,8 @@ class Page extends Entity
9 9
10 protected $with = ['book']; 10 protected $with = ['book'];
11 11
12 + protected $fieldsToSearch = ['name', 'text'];
13 +
12 /** 14 /**
13 * Converts this page into a simplified array. 15 * Converts this page into a simplified array.
14 * @return mixed 16 * @return mixed
......
...@@ -27,7 +27,7 @@ class BookRepo extends EntityRepo ...@@ -27,7 +27,7 @@ class BookRepo extends EntityRepo
27 public function createFromInput($input) 27 public function createFromInput($input)
28 { 28 {
29 $book = $this->book->newInstance($input); 29 $book = $this->book->newInstance($input);
30 - $book->slug = $this->findSuitableSlug($book->name); 30 + $book->slug = $this->findSuitableSlug('book', $book->name);
31 $book->created_by = user()->id; 31 $book->created_by = user()->id;
32 $book->updated_by = user()->id; 32 $book->updated_by = user()->id;
33 $book->save(); 33 $book->save();
...@@ -44,7 +44,7 @@ class BookRepo extends EntityRepo ...@@ -44,7 +44,7 @@ class BookRepo extends EntityRepo
44 public function updateFromInput(Book $book, $input) 44 public function updateFromInput(Book $book, $input)
45 { 45 {
46 if ($book->name !== $input['name']) { 46 if ($book->name !== $input['name']) {
47 - $book->slug = $this->findSuitableSlug($input['name'], $book->id); 47 + $book->slug = $this->findSuitableSlug('book', $input['name'], $book->id);
48 } 48 }
49 $book->fill($input); 49 $book->fill($input);
50 $book->updated_by = user()->id; 50 $book->updated_by = user()->id;
...@@ -84,36 +84,6 @@ class BookRepo extends EntityRepo ...@@ -84,36 +84,6 @@ class BookRepo extends EntityRepo
84 } 84 }
85 85
86 /** 86 /**
87 - * @param string $slug
88 - * @param bool|false $currentId
89 - * @return bool
90 - */
91 - public function doesSlugExist($slug, $currentId = false)
92 - {
93 - $query = $this->book->where('slug', '=', $slug);
94 - if ($currentId) {
95 - $query = $query->where('id', '!=', $currentId);
96 - }
97 - return $query->count() > 0;
98 - }
99 -
100 - /**
101 - * Provides a suitable slug for the given book name.
102 - * Ensures the returned slug is unique in the system.
103 - * @param string $name
104 - * @param bool|false $currentId
105 - * @return string
106 - */
107 - public function findSuitableSlug($name, $currentId = false)
108 - {
109 - $slug = $this->nameToSlug($name);
110 - while ($this->doesSlugExist($slug, $currentId)) {
111 - $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
112 - }
113 - return $slug;
114 - }
115 -
116 - /**
117 * Get all child objects of a book. 87 * Get all child objects of a book.
118 * Returns a sorted collection of Pages and Chapters. 88 * Returns a sorted collection of Pages and Chapters.
119 * Loads the book slug onto child elements to prevent access database access for getting the slug. 89 * Loads the book slug onto child elements to prevent access database access for getting the slug.
...@@ -166,26 +136,4 @@ class BookRepo extends EntityRepo ...@@ -166,26 +136,4 @@ class BookRepo extends EntityRepo
166 }); 136 });
167 } 137 }
168 138
169 - /**
170 - * Get books by search term.
171 - * @param $term
172 - * @param int $count
173 - * @param array $paginationAppends
174 - * @return mixed
175 - */
176 - public function getBySearch($term, $count = 20, $paginationAppends = [])
177 - {
178 - $terms = $this->prepareSearchTerms($term);
179 - $bookQuery = $this->permissionService->enforceBookRestrictions($this->book->fullTextSearchQuery(['name', 'description'], $terms));
180 - $bookQuery = $this->addAdvancedSearchQueries($bookQuery, $term);
181 - $books = $bookQuery->paginate($count)->appends($paginationAppends);
182 - $words = join('|', explode(' ', preg_quote(trim($term), '/')));
183 - foreach ($books as $book) {
184 - //highlight
185 - $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $book->getExcerpt(100));
186 - $book->searchSnippet = $result;
187 - }
188 - return $books;
189 - }
190 -
191 } 139 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -45,7 +45,7 @@ class ChapterRepo extends EntityRepo ...@@ -45,7 +45,7 @@ class ChapterRepo extends EntityRepo
45 public function createFromInput($input, Book $book) 45 public function createFromInput($input, Book $book)
46 { 46 {
47 $chapter = $this->chapter->newInstance($input); 47 $chapter = $this->chapter->newInstance($input);
48 - $chapter->slug = $this->findSuitableSlug($chapter->name, $book->id); 48 + $chapter->slug = $this->findSuitableSlug('chapter', $chapter->name, false, $book->id);
49 $chapter->created_by = user()->id; 49 $chapter->created_by = user()->id;
50 $chapter->updated_by = user()->id; 50 $chapter->updated_by = user()->id;
51 $chapter = $book->chapters()->save($chapter); 51 $chapter = $book->chapters()->save($chapter);
...@@ -72,38 +72,6 @@ class ChapterRepo extends EntityRepo ...@@ -72,38 +72,6 @@ class ChapterRepo extends EntityRepo
72 $chapter->delete(); 72 $chapter->delete();
73 } 73 }
74 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 75
108 /** 76 /**
109 * Get a new priority value for a new page to be added 77 * Get a new priority value for a new page to be added
...@@ -118,29 +86,6 @@ class ChapterRepo extends EntityRepo ...@@ -118,29 +86,6 @@ class ChapterRepo extends EntityRepo
118 } 86 }
119 87
120 /** 88 /**
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. 89 * Changes the book relation of this chapter.
145 * @param $bookId 90 * @param $bookId
146 * @param Chapter $chapter 91 * @param Chapter $chapter
...@@ -155,7 +100,7 @@ class ChapterRepo extends EntityRepo ...@@ -155,7 +100,7 @@ class ChapterRepo extends EntityRepo
155 $activity->book_id = $bookId; 100 $activity->book_id = $bookId;
156 $activity->save(); 101 $activity->save();
157 } 102 }
158 - $chapter->slug = $this->findSuitableSlug($chapter->name, $bookId, $chapter->id); 103 + $chapter->slug = $this->findSuitableSlug('chapter', $chapter->name, $chapter->id, $bookId);
159 $chapter->save(); 104 $chapter->save();
160 // Update all child pages 105 // Update all child pages
161 foreach ($chapter->pages as $page) { 106 foreach ($chapter->pages as $page) {
......
...@@ -238,6 +238,83 @@ class EntityRepo ...@@ -238,6 +238,83 @@ class EntityRepo
238 ->skip($count * $page)->take($count)->get(); 238 ->skip($count * $page)->take($count)->get();
239 } 239 }
240 240
241 + public function getBySearch($type, $term, $whereTerms = [], $count = 20, $paginationAppends = [])
242 + {
243 + $terms = $this->prepareSearchTerms($term);
244 + $q = $this->permissionService->enforceChapterRestrictions($this->getEntity($type)->fullTextSearchQuery($terms, $whereTerms));
245 + $q = $this->addAdvancedSearchQueries($q, $term);
246 + $entities = $q->paginate($count)->appends($paginationAppends);
247 + $words = join('|', explode(' ', preg_quote(trim($term), '/')));
248 +
249 + // Highlight page content
250 + if ($type === 'page') {
251 + //lookahead/behind assertions ensures cut between words
252 + $s = '\s\x00-/:-@\[-`{-~'; //character set for start/end of words
253 +
254 + foreach ($entities as $page) {
255 + preg_match_all('#(?<=[' . $s . ']).{1,30}((' . $words . ').{1,30})+(?=[' . $s . '])#uis', $page->text, $matches, PREG_SET_ORDER);
256 + //delimiter between occurrences
257 + $results = [];
258 + foreach ($matches as $line) {
259 + $results[] = htmlspecialchars($line[0], 0, 'UTF-8');
260 + }
261 + $matchLimit = 6;
262 + if (count($results) > $matchLimit) $results = array_slice($results, 0, $matchLimit);
263 + $result = join('... ', $results);
264 +
265 + //highlight
266 + $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $result);
267 + if (strlen($result) < 5) $result = $page->getExcerpt(80);
268 +
269 + $page->searchSnippet = $result;
270 + }
271 + return $entities;
272 + }
273 +
274 + // Highlight chapter/book content
275 + foreach ($entities as $entity) {
276 + //highlight
277 + $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $entity->getExcerpt(100));
278 + $entity->searchSnippet = $result;
279 + }
280 + return $entities;
281 + }
282 +
283 + /**
284 + * Find a suitable slug for an entity.
285 + * @param string $type
286 + * @param string $name
287 + * @param bool|integer $currentId
288 + * @param bool|integer $bookId Only pass if type is not a book
289 + * @return string
290 + */
291 + public function findSuitableSlug($type, $name, $currentId = false, $bookId = false)
292 + {
293 + $slug = $this->nameToSlug($name);
294 + while ($this->slugExists($type, $slug, $currentId, $bookId)) {
295 + $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
296 + }
297 + return $slug;
298 + }
299 +
300 + /**
301 + * Check if a slug already exists in the database.
302 + * @param string $type
303 + * @param string $slug
304 + * @param bool|integer $currentId
305 + * @param bool|integer $bookId
306 + * @return bool
307 + */
308 + protected function slugExists($type, $slug, $currentId = false, $bookId = false)
309 + {
310 + $query = $this->getEntity($type)->where('slug', '=', $slug);
311 + if (strtolower($type) === 'page' || strtolower($type) === 'chapter') {
312 + $query = $query->where('book_id', '=', $bookId);
313 + }
314 + if ($currentId) $query = $query->where('id', '!=', $currentId);
315 + return $query->count() > 0;
316 + }
317 +
241 /** 318 /**
242 * Updates entity restrictions from a request 319 * Updates entity restrictions from a request
243 * @param $request 320 * @param $request
......
...@@ -66,17 +66,6 @@ class PageRepo extends EntityRepo ...@@ -66,17 +66,6 @@ class PageRepo extends EntityRepo
66 } 66 }
67 67
68 /** 68 /**
69 - * Get a new Page instance from the given input.
70 - * @param $input
71 - * @return Page
72 - */
73 - public function newFromInput($input)
74 - {
75 - $page = $this->page->fill($input);
76 - return $page;
77 - }
78 -
79 - /**
80 * Count the pages with a particular slug within a book. 69 * Count the pages with a particular slug within a book.
81 * @param $slug 70 * @param $slug
82 * @param $bookId 71 * @param $bookId
...@@ -103,7 +92,7 @@ class PageRepo extends EntityRepo ...@@ -103,7 +92,7 @@ class PageRepo extends EntityRepo
103 $this->tagRepo->saveTagsToEntity($draftPage, $input['tags']); 92 $this->tagRepo->saveTagsToEntity($draftPage, $input['tags']);
104 } 93 }
105 94
106 - $draftPage->slug = $this->findSuitableSlug($draftPage->name, $draftPage->book->id); 95 + $draftPage->slug = $this->findSuitableSlug('page', $draftPage->name, false, $draftPage->book->id);
107 $draftPage->html = $this->formatHtml($input['html']); 96 $draftPage->html = $this->formatHtml($input['html']);
108 $draftPage->text = strip_tags($draftPage->html); 97 $draftPage->text = strip_tags($draftPage->html);
109 $draftPage->draft = false; 98 $draftPage->draft = false;
...@@ -223,50 +212,6 @@ class PageRepo extends EntityRepo ...@@ -223,50 +212,6 @@ class PageRepo extends EntityRepo
223 212
224 213
225 /** 214 /**
226 - * Gets pages by a search term.
227 - * Highlights page content for showing in results.
228 - * @param string $term
229 - * @param array $whereTerms
230 - * @param int $count
231 - * @param array $paginationAppends
232 - * @return mixed
233 - */
234 - public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = [])
235 - {
236 - $terms = $this->prepareSearchTerms($term);
237 - $pageQuery = $this->permissionService->enforcePageRestrictions($this->page->fullTextSearchQuery(['name', 'text'], $terms, $whereTerms));
238 - $pageQuery = $this->addAdvancedSearchQueries($pageQuery, $term);
239 - $pages = $pageQuery->paginate($count)->appends($paginationAppends);
240 -
241 - // Add highlights to page text.
242 - $words = join('|', explode(' ', preg_quote(trim($term), '/')));
243 - //lookahead/behind assertions ensures cut between words
244 - $s = '\s\x00-/:-@\[-`{-~'; //character set for start/end of words
245 -
246 - foreach ($pages as $page) {
247 - preg_match_all('#(?<=[' . $s . ']).{1,30}((' . $words . ').{1,30})+(?=[' . $s . '])#uis', $page->text, $matches, PREG_SET_ORDER);
248 - //delimiter between occurrences
249 - $results = [];
250 - foreach ($matches as $line) {
251 - $results[] = htmlspecialchars($line[0], 0, 'UTF-8');
252 - }
253 - $matchLimit = 6;
254 - if (count($results) > $matchLimit) {
255 - $results = array_slice($results, 0, $matchLimit);
256 - }
257 - $result = join('... ', $results);
258 -
259 - //highlight
260 - $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $result);
261 - if (strlen($result) < 5) {
262 - $result = $page->getExcerpt(80);
263 - }
264 - $page->searchSnippet = $result;
265 - }
266 - return $pages;
267 - }
268 -
269 - /**
270 * Search for image usage. 215 * Search for image usage.
271 * @param $imageString 216 * @param $imageString
272 * @return mixed 217 * @return mixed
...@@ -297,7 +242,7 @@ class PageRepo extends EntityRepo ...@@ -297,7 +242,7 @@ class PageRepo extends EntityRepo
297 242
298 // Prevent slug being updated if no name change 243 // Prevent slug being updated if no name change
299 if ($page->name !== $input['name']) { 244 if ($page->name !== $input['name']) {
300 - $page->slug = $this->findSuitableSlug($input['name'], $book_id, $page->id); 245 + $page->slug = $this->findSuitableSlug('page', $input['name'], $page->id, $book_id);
301 } 246 }
302 247
303 // Save page tags if present 248 // Save page tags if present
...@@ -337,7 +282,7 @@ class PageRepo extends EntityRepo ...@@ -337,7 +282,7 @@ class PageRepo extends EntityRepo
337 $this->saveRevision($page); 282 $this->saveRevision($page);
338 $revision = $this->getRevisionById($revisionId); 283 $revision = $this->getRevisionById($revisionId);
339 $page->fill($revision->toArray()); 284 $page->fill($revision->toArray());
340 - $page->slug = $this->findSuitableSlug($page->name, $book->id, $page->id); 285 + $page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $book->id);
341 $page->text = strip_tags($page->html); 286 $page->text = strip_tags($page->html);
342 $page->updated_by = user()->id; 287 $page->updated_by = user()->id;
343 $page->save(); 288 $page->save();
...@@ -530,20 +475,6 @@ class PageRepo extends EntityRepo ...@@ -530,20 +475,6 @@ class PageRepo extends EntityRepo
530 } 475 }
531 476
532 /** 477 /**
533 - * Checks if a slug exists within a book already.
534 - * @param $slug
535 - * @param $bookId
536 - * @param bool|false $currentId
537 - * @return bool
538 - */
539 - public function doesSlugExist($slug, $bookId, $currentId = false)
540 - {
541 - $query = $this->page->where('slug', '=', $slug)->where('book_id', '=', $bookId);
542 - if ($currentId) $query = $query->where('id', '!=', $currentId);
543 - return $query->count() > 0;
544 - }
545 -
546 - /**
547 * Changes the related book for the specified page. 478 * Changes the related book for the specified page.
548 * Changes the book id of any relations to the page that store the book id. 479 * Changes the book id of any relations to the page that store the book id.
549 * @param int $bookId 480 * @param int $bookId
...@@ -557,7 +488,7 @@ class PageRepo extends EntityRepo ...@@ -557,7 +488,7 @@ class PageRepo extends EntityRepo
557 $activity->book_id = $bookId; 488 $activity->book_id = $bookId;
558 $activity->save(); 489 $activity->save();
559 } 490 }
560 - $page->slug = $this->findSuitableSlug($page->name, $bookId, $page->id); 491 + $page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $bookId);
561 $page->save(); 492 $page->save();
562 return $page; 493 return $page;
563 } 494 }
...@@ -579,22 +510,6 @@ class PageRepo extends EntityRepo ...@@ -579,22 +510,6 @@ class PageRepo extends EntityRepo
579 } 510 }
580 511
581 /** 512 /**
582 - * Gets a suitable slug for the resource
583 - * @param string $name
584 - * @param int $bookId
585 - * @param bool|false $currentId
586 - * @return string
587 - */
588 - public function findSuitableSlug($name, $bookId, $currentId = false)
589 - {
590 - $slug = $this->nameToSlug($name);
591 - while ($this->doesSlugExist($slug, $bookId, $currentId)) {
592 - $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
593 - }
594 - return $slug;
595 - }
596 -
597 - /**
598 * Destroy a given page along with its dependencies. 513 * Destroy a given page along with its dependencies.
599 * @param $page 514 * @param $page
600 */ 515 */
......