Dan Brown
Committed by GitHub

Merge pull request #262 from BookStackApp/entity_repo_refactor

Entity repo refactor
...@@ -5,6 +5,8 @@ class Chapter extends Entity ...@@ -5,6 +5,8 @@ class Chapter extends Entity
5 { 5 {
6 protected $fillable = ['name', 'description', 'priority', 'book_id']; 6 protected $fillable = ['name', 'description', 'priority', 'book_id'];
7 7
8 + protected $with = ['book'];
9 +
8 /** 10 /**
9 * Get the book this chapter is within. 11 * Get the book this chapter is within.
10 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo 12 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
...@@ -16,11 +18,12 @@ class Chapter extends Entity ...@@ -16,11 +18,12 @@ class Chapter extends Entity
16 18
17 /** 19 /**
18 * Get the pages that this chapter contains. 20 * Get the pages that this chapter contains.
21 + * @param string $dir
19 * @return mixed 22 * @return mixed
20 */ 23 */
21 - public function pages() 24 + public function pages($dir = 'ASC')
22 { 25 {
23 - return $this->hasMany(Page::class)->orderBy('priority', 'ASC'); 26 + return $this->hasMany(Page::class)->orderBy('priority', $dir);
24 } 27 }
25 28
26 /** 29 /**
......
...@@ -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 }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 2
3 use BookStack\Exceptions\FileUploadException; 3 use BookStack\Exceptions\FileUploadException;
4 use BookStack\Attachment; 4 use BookStack\Attachment;
5 -use BookStack\Repos\PageRepo; 5 +use BookStack\Repos\EntityRepo;
6 use BookStack\Services\AttachmentService; 6 use BookStack\Services\AttachmentService;
7 use Illuminate\Http\Request; 7 use Illuminate\Http\Request;
8 8
...@@ -10,19 +10,19 @@ class AttachmentController extends Controller ...@@ -10,19 +10,19 @@ class AttachmentController extends Controller
10 { 10 {
11 protected $attachmentService; 11 protected $attachmentService;
12 protected $attachment; 12 protected $attachment;
13 - protected $pageRepo; 13 + protected $entityRepo;
14 14
15 /** 15 /**
16 * AttachmentController constructor. 16 * AttachmentController constructor.
17 * @param AttachmentService $attachmentService 17 * @param AttachmentService $attachmentService
18 * @param Attachment $attachment 18 * @param Attachment $attachment
19 - * @param PageRepo $pageRepo 19 + * @param EntityRepo $entityRepo
20 */ 20 */
21 - public function __construct(AttachmentService $attachmentService, Attachment $attachment, PageRepo $pageRepo) 21 + public function __construct(AttachmentService $attachmentService, Attachment $attachment, EntityRepo $entityRepo)
22 { 22 {
23 $this->attachmentService = $attachmentService; 23 $this->attachmentService = $attachmentService;
24 $this->attachment = $attachment; 24 $this->attachment = $attachment;
25 - $this->pageRepo = $pageRepo; 25 + $this->entityRepo = $entityRepo;
26 parent::__construct(); 26 parent::__construct();
27 } 27 }
28 28
...@@ -40,7 +40,7 @@ class AttachmentController extends Controller ...@@ -40,7 +40,7 @@ class AttachmentController extends Controller
40 ]); 40 ]);
41 41
42 $pageId = $request->get('uploaded_to'); 42 $pageId = $request->get('uploaded_to');
43 - $page = $this->pageRepo->getById($pageId, true); 43 + $page = $this->entityRepo->getById('page', $pageId, true);
44 44
45 $this->checkPermission('attachment-create-all'); 45 $this->checkPermission('attachment-create-all');
46 $this->checkOwnablePermission('page-update', $page); 46 $this->checkOwnablePermission('page-update', $page);
...@@ -70,7 +70,7 @@ class AttachmentController extends Controller ...@@ -70,7 +70,7 @@ class AttachmentController extends Controller
70 ]); 70 ]);
71 71
72 $pageId = $request->get('uploaded_to'); 72 $pageId = $request->get('uploaded_to');
73 - $page = $this->pageRepo->getById($pageId, true); 73 + $page = $this->entityRepo->getById('page', $pageId, true);
74 $attachment = $this->attachment->findOrFail($attachmentId); 74 $attachment = $this->attachment->findOrFail($attachmentId);
75 75
76 $this->checkOwnablePermission('page-update', $page); 76 $this->checkOwnablePermission('page-update', $page);
...@@ -106,7 +106,7 @@ class AttachmentController extends Controller ...@@ -106,7 +106,7 @@ class AttachmentController extends Controller
106 ]); 106 ]);
107 107
108 $pageId = $request->get('uploaded_to'); 108 $pageId = $request->get('uploaded_to');
109 - $page = $this->pageRepo->getById($pageId, true); 109 + $page = $this->entityRepo->getById('page', $pageId, true);
110 $attachment = $this->attachment->findOrFail($attachmentId); 110 $attachment = $this->attachment->findOrFail($attachmentId);
111 111
112 $this->checkOwnablePermission('page-update', $page); 112 $this->checkOwnablePermission('page-update', $page);
...@@ -134,7 +134,7 @@ class AttachmentController extends Controller ...@@ -134,7 +134,7 @@ class AttachmentController extends Controller
134 ]); 134 ]);
135 135
136 $pageId = $request->get('uploaded_to'); 136 $pageId = $request->get('uploaded_to');
137 - $page = $this->pageRepo->getById($pageId, true); 137 + $page = $this->entityRepo->getById('page', $pageId, true);
138 138
139 $this->checkPermission('attachment-create-all'); 139 $this->checkPermission('attachment-create-all');
140 $this->checkOwnablePermission('page-update', $page); 140 $this->checkOwnablePermission('page-update', $page);
...@@ -153,7 +153,7 @@ class AttachmentController extends Controller ...@@ -153,7 +153,7 @@ class AttachmentController extends Controller
153 */ 153 */
154 public function listForPage($pageId) 154 public function listForPage($pageId)
155 { 155 {
156 - $page = $this->pageRepo->getById($pageId, true); 156 + $page = $this->entityRepo->getById('page', $pageId, true);
157 $this->checkOwnablePermission('page-view', $page); 157 $this->checkOwnablePermission('page-view', $page);
158 return response()->json($page->attachments); 158 return response()->json($page->attachments);
159 } 159 }
...@@ -170,7 +170,7 @@ class AttachmentController extends Controller ...@@ -170,7 +170,7 @@ class AttachmentController extends Controller
170 'files' => 'required|array', 170 'files' => 'required|array',
171 'files.*.id' => 'required|integer', 171 'files.*.id' => 'required|integer',
172 ]); 172 ]);
173 - $page = $this->pageRepo->getById($pageId); 173 + $page = $this->entityRepo->getById('page', $pageId);
174 $this->checkOwnablePermission('page-update', $page); 174 $this->checkOwnablePermission('page-update', $page);
175 175
176 $attachments = $request->get('files'); 176 $attachments = $request->get('files');
...@@ -186,7 +186,7 @@ class AttachmentController extends Controller ...@@ -186,7 +186,7 @@ class AttachmentController extends Controller
186 public function get($attachmentId) 186 public function get($attachmentId)
187 { 187 {
188 $attachment = $this->attachment->findOrFail($attachmentId); 188 $attachment = $this->attachment->findOrFail($attachmentId);
189 - $page = $this->pageRepo->getById($attachment->uploaded_to); 189 + $page = $this->entityRepo->getById('page', $attachment->uploaded_to);
190 $this->checkOwnablePermission('page-view', $page); 190 $this->checkOwnablePermission('page-view', $page);
191 191
192 if ($attachment->external) { 192 if ($attachment->external) {
......
1 <?php namespace BookStack\Http\Controllers; 1 <?php namespace BookStack\Http\Controllers;
2 2
3 use Activity; 3 use Activity;
4 +use BookStack\Repos\EntityRepo;
4 use BookStack\Repos\UserRepo; 5 use BookStack\Repos\UserRepo;
5 use Illuminate\Http\Request; 6 use Illuminate\Http\Request;
6 -use BookStack\Http\Requests;
7 -use BookStack\Repos\BookRepo;
8 -use BookStack\Repos\ChapterRepo;
9 -use BookStack\Repos\PageRepo;
10 use Illuminate\Http\Response; 7 use Illuminate\Http\Response;
11 use Views; 8 use Views;
12 9
13 class BookController extends Controller 10 class BookController extends Controller
14 { 11 {
15 12
16 - protected $bookRepo; 13 + protected $entityRepo;
17 - protected $pageRepo;
18 - protected $chapterRepo;
19 protected $userRepo; 14 protected $userRepo;
20 15
21 /** 16 /**
22 * BookController constructor. 17 * BookController constructor.
23 - * @param BookRepo $bookRepo 18 + * @param EntityRepo $entityRepo
24 - * @param PageRepo $pageRepo
25 - * @param ChapterRepo $chapterRepo
26 * @param UserRepo $userRepo 19 * @param UserRepo $userRepo
27 */ 20 */
28 - public function __construct(BookRepo $bookRepo, PageRepo $pageRepo, ChapterRepo $chapterRepo, UserRepo $userRepo) 21 + public function __construct(EntityRepo $entityRepo, UserRepo $userRepo)
29 { 22 {
30 - $this->bookRepo = $bookRepo; 23 + $this->entityRepo = $entityRepo;
31 - $this->pageRepo = $pageRepo;
32 - $this->chapterRepo = $chapterRepo;
33 $this->userRepo = $userRepo; 24 $this->userRepo = $userRepo;
34 parent::__construct(); 25 parent::__construct();
35 } 26 }
...@@ -40,9 +31,9 @@ class BookController extends Controller ...@@ -40,9 +31,9 @@ class BookController extends Controller
40 */ 31 */
41 public function index() 32 public function index()
42 { 33 {
43 - $books = $this->bookRepo->getAllPaginated(10); 34 + $books = $this->entityRepo->getAllPaginated('book', 10);
44 - $recents = $this->signedIn ? $this->bookRepo->getRecentlyViewed(4, 0) : false; 35 + $recents = $this->signedIn ? $this->entityRepo->getRecentlyViewed('book', 4, 0) : false;
45 - $popular = $this->bookRepo->getPopular(4, 0); 36 + $popular = $this->entityRepo->getPopular('book', 4, 0);
46 $this->setPageTitle('Books'); 37 $this->setPageTitle('Books');
47 return view('books/index', ['books' => $books, 'recents' => $recents, 'popular' => $popular]); 38 return view('books/index', ['books' => $books, 'recents' => $recents, 'popular' => $popular]);
48 } 39 }
...@@ -71,7 +62,7 @@ class BookController extends Controller ...@@ -71,7 +62,7 @@ class BookController extends Controller
71 'name' => 'required|string|max:255', 62 'name' => 'required|string|max:255',
72 'description' => 'string|max:1000' 63 'description' => 'string|max:1000'
73 ]); 64 ]);
74 - $book = $this->bookRepo->createFromInput($request->all()); 65 + $book = $this->entityRepo->createFromInput('book', $request->all());
75 Activity::add($book, 'book_create', $book->id); 66 Activity::add($book, 'book_create', $book->id);
76 return redirect($book->getUrl()); 67 return redirect($book->getUrl());
77 } 68 }
...@@ -83,9 +74,9 @@ class BookController extends Controller ...@@ -83,9 +74,9 @@ class BookController extends Controller
83 */ 74 */
84 public function show($slug) 75 public function show($slug)
85 { 76 {
86 - $book = $this->bookRepo->getBySlug($slug); 77 + $book = $this->entityRepo->getBySlug('book', $slug);
87 $this->checkOwnablePermission('book-view', $book); 78 $this->checkOwnablePermission('book-view', $book);
88 - $bookChildren = $this->bookRepo->getChildren($book); 79 + $bookChildren = $this->entityRepo->getBookChildren($book);
89 Views::add($book); 80 Views::add($book);
90 $this->setPageTitle($book->getShortName()); 81 $this->setPageTitle($book->getShortName());
91 return view('books/show', ['book' => $book, 'current' => $book, 'bookChildren' => $bookChildren]); 82 return view('books/show', ['book' => $book, 'current' => $book, 'bookChildren' => $bookChildren]);
...@@ -98,7 +89,7 @@ class BookController extends Controller ...@@ -98,7 +89,7 @@ class BookController extends Controller
98 */ 89 */
99 public function edit($slug) 90 public function edit($slug)
100 { 91 {
101 - $book = $this->bookRepo->getBySlug($slug); 92 + $book = $this->entityRepo->getBySlug('book', $slug);
102 $this->checkOwnablePermission('book-update', $book); 93 $this->checkOwnablePermission('book-update', $book);
103 $this->setPageTitle(trans('entities.books_edit_named',['bookName'=>$book->getShortName()])); 94 $this->setPageTitle(trans('entities.books_edit_named',['bookName'=>$book->getShortName()]));
104 return view('books/edit', ['book' => $book, 'current' => $book]); 95 return view('books/edit', ['book' => $book, 'current' => $book]);
...@@ -112,13 +103,13 @@ class BookController extends Controller ...@@ -112,13 +103,13 @@ class BookController extends Controller
112 */ 103 */
113 public function update(Request $request, $slug) 104 public function update(Request $request, $slug)
114 { 105 {
115 - $book = $this->bookRepo->getBySlug($slug); 106 + $book = $this->entityRepo->getBySlug('book', $slug);
116 $this->checkOwnablePermission('book-update', $book); 107 $this->checkOwnablePermission('book-update', $book);
117 $this->validate($request, [ 108 $this->validate($request, [
118 'name' => 'required|string|max:255', 109 'name' => 'required|string|max:255',
119 'description' => 'string|max:1000' 110 'description' => 'string|max:1000'
120 ]); 111 ]);
121 - $book = $this->bookRepo->updateFromInput($book, $request->all()); 112 + $book = $this->entityRepo->updateFromInput('book', $book, $request->all());
122 Activity::add($book, 'book_update', $book->id); 113 Activity::add($book, 'book_update', $book->id);
123 return redirect($book->getUrl()); 114 return redirect($book->getUrl());
124 } 115 }
...@@ -130,7 +121,7 @@ class BookController extends Controller ...@@ -130,7 +121,7 @@ class BookController extends Controller
130 */ 121 */
131 public function showDelete($bookSlug) 122 public function showDelete($bookSlug)
132 { 123 {
133 - $book = $this->bookRepo->getBySlug($bookSlug); 124 + $book = $this->entityRepo->getBySlug('book', $bookSlug);
134 $this->checkOwnablePermission('book-delete', $book); 125 $this->checkOwnablePermission('book-delete', $book);
135 $this->setPageTitle(trans('entities.books_delete_named', ['bookName'=>$book->getShortName()])); 126 $this->setPageTitle(trans('entities.books_delete_named', ['bookName'=>$book->getShortName()]));
136 return view('books/delete', ['book' => $book, 'current' => $book]); 127 return view('books/delete', ['book' => $book, 'current' => $book]);
...@@ -143,10 +134,10 @@ class BookController extends Controller ...@@ -143,10 +134,10 @@ class BookController extends Controller
143 */ 134 */
144 public function sort($bookSlug) 135 public function sort($bookSlug)
145 { 136 {
146 - $book = $this->bookRepo->getBySlug($bookSlug); 137 + $book = $this->entityRepo->getBySlug('book', $bookSlug);
147 $this->checkOwnablePermission('book-update', $book); 138 $this->checkOwnablePermission('book-update', $book);
148 - $bookChildren = $this->bookRepo->getChildren($book, true); 139 + $bookChildren = $this->entityRepo->getBookChildren($book, true);
149 - $books = $this->bookRepo->getAll(false); 140 + $books = $this->entityRepo->getAll('book', false);
150 $this->setPageTitle(trans('entities.books_sort_named', ['bookName'=>$book->getShortName()])); 141 $this->setPageTitle(trans('entities.books_sort_named', ['bookName'=>$book->getShortName()]));
151 return view('books/sort', ['book' => $book, 'current' => $book, 'books' => $books, 'bookChildren' => $bookChildren]); 142 return view('books/sort', ['book' => $book, 'current' => $book, 'books' => $books, 'bookChildren' => $bookChildren]);
152 } 143 }
...@@ -159,8 +150,8 @@ class BookController extends Controller ...@@ -159,8 +150,8 @@ class BookController extends Controller
159 */ 150 */
160 public function getSortItem($bookSlug) 151 public function getSortItem($bookSlug)
161 { 152 {
162 - $book = $this->bookRepo->getBySlug($bookSlug); 153 + $book = $this->entityRepo->getBySlug('book', $bookSlug);
163 - $bookChildren = $this->bookRepo->getChildren($book); 154 + $bookChildren = $this->entityRepo->getBookChildren($book);
164 return view('books/sort-box', ['book' => $book, 'bookChildren' => $bookChildren]); 155 return view('books/sort-box', ['book' => $book, 'bookChildren' => $bookChildren]);
165 } 156 }
166 157
...@@ -172,7 +163,7 @@ class BookController extends Controller ...@@ -172,7 +163,7 @@ class BookController extends Controller
172 */ 163 */
173 public function saveSort($bookSlug, Request $request) 164 public function saveSort($bookSlug, Request $request)
174 { 165 {
175 - $book = $this->bookRepo->getBySlug($bookSlug); 166 + $book = $this->entityRepo->getBySlug('book', $bookSlug);
176 $this->checkOwnablePermission('book-update', $book); 167 $this->checkOwnablePermission('book-update', $book);
177 168
178 // Return if no map sent 169 // Return if no map sent
...@@ -191,13 +182,13 @@ class BookController extends Controller ...@@ -191,13 +182,13 @@ class BookController extends Controller
191 $priority = $bookChild->sort; 182 $priority = $bookChild->sort;
192 $id = intval($bookChild->id); 183 $id = intval($bookChild->id);
193 $isPage = $bookChild->type == 'page'; 184 $isPage = $bookChild->type == 'page';
194 - $bookId = $this->bookRepo->exists($bookChild->book) ? intval($bookChild->book) : $defaultBookId; 185 + $bookId = $this->entityRepo->exists('book', $bookChild->book) ? intval($bookChild->book) : $defaultBookId;
195 $chapterId = ($isPage && $bookChild->parentChapter === false) ? 0 : intval($bookChild->parentChapter); 186 $chapterId = ($isPage && $bookChild->parentChapter === false) ? 0 : intval($bookChild->parentChapter);
196 - $model = $isPage ? $this->pageRepo->getById($id) : $this->chapterRepo->getById($id); 187 + $model = $this->entityRepo->getById($isPage?'page':'chapter', $id);
197 188
198 // Update models only if there's a change in parent chain or ordering. 189 // Update models only if there's a change in parent chain or ordering.
199 if ($model->priority !== $priority || $model->book_id !== $bookId || ($isPage && $model->chapter_id !== $chapterId)) { 190 if ($model->priority !== $priority || $model->book_id !== $bookId || ($isPage && $model->chapter_id !== $chapterId)) {
200 - $isPage ? $this->pageRepo->changeBook($bookId, $model) : $this->chapterRepo->changeBook($bookId, $model); 191 + $this->entityRepo->changeBook($isPage?'page':'chapter', $bookId, $model);
201 $model->priority = $priority; 192 $model->priority = $priority;
202 if ($isPage) $model->chapter_id = $chapterId; 193 if ($isPage) $model->chapter_id = $chapterId;
203 $model->save(); 194 $model->save();
...@@ -212,12 +203,12 @@ class BookController extends Controller ...@@ -212,12 +203,12 @@ class BookController extends Controller
212 203
213 // Add activity for books 204 // Add activity for books
214 foreach ($sortedBooks as $bookId) { 205 foreach ($sortedBooks as $bookId) {
215 - $updatedBook = $this->bookRepo->getById($bookId); 206 + $updatedBook = $this->entityRepo->getById('book', $bookId);
216 Activity::add($updatedBook, 'book_sort', $updatedBook->id); 207 Activity::add($updatedBook, 'book_sort', $updatedBook->id);
217 } 208 }
218 209
219 // Update permissions on changed models 210 // Update permissions on changed models
220 - $this->bookRepo->buildJointPermissions($updatedModels); 211 + $this->entityRepo->buildJointPermissions($updatedModels);
221 212
222 return redirect($book->getUrl()); 213 return redirect($book->getUrl());
223 } 214 }
...@@ -229,11 +220,10 @@ class BookController extends Controller ...@@ -229,11 +220,10 @@ class BookController extends Controller
229 */ 220 */
230 public function destroy($bookSlug) 221 public function destroy($bookSlug)
231 { 222 {
232 - $book = $this->bookRepo->getBySlug($bookSlug); 223 + $book = $this->entityRepo->getBySlug('book', $bookSlug);
233 $this->checkOwnablePermission('book-delete', $book); 224 $this->checkOwnablePermission('book-delete', $book);
234 Activity::addMessage('book_delete', 0, $book->name); 225 Activity::addMessage('book_delete', 0, $book->name);
235 - Activity::removeEntity($book); 226 + $this->entityRepo->destroyBook($book);
236 - $this->bookRepo->destroy($book);
237 return redirect('/books'); 227 return redirect('/books');
238 } 228 }
239 229
...@@ -244,7 +234,7 @@ class BookController extends Controller ...@@ -244,7 +234,7 @@ class BookController extends Controller
244 */ 234 */
245 public function showRestrict($bookSlug) 235 public function showRestrict($bookSlug)
246 { 236 {
247 - $book = $this->bookRepo->getBySlug($bookSlug); 237 + $book = $this->entityRepo->getBySlug('book', $bookSlug);
248 $this->checkOwnablePermission('restrictions-manage', $book); 238 $this->checkOwnablePermission('restrictions-manage', $book);
249 $roles = $this->userRepo->getRestrictableRoles(); 239 $roles = $this->userRepo->getRestrictableRoles();
250 return view('books/restrictions', [ 240 return view('books/restrictions', [
...@@ -262,9 +252,9 @@ class BookController extends Controller ...@@ -262,9 +252,9 @@ class BookController extends Controller
262 */ 252 */
263 public function restrict($bookSlug, Request $request) 253 public function restrict($bookSlug, Request $request)
264 { 254 {
265 - $book = $this->bookRepo->getBySlug($bookSlug); 255 + $book = $this->entityRepo->getBySlug('book', $bookSlug);
266 $this->checkOwnablePermission('restrictions-manage', $book); 256 $this->checkOwnablePermission('restrictions-manage', $book);
267 - $this->bookRepo->updateEntityPermissionsFromRequest($request, $book); 257 + $this->entityRepo->updateEntityPermissionsFromRequest($request, $book);
268 session()->flash('success', trans('entities.books_permissions_updated')); 258 session()->flash('success', trans('entities.books_permissions_updated'));
269 return redirect($book->getUrl()); 259 return redirect($book->getUrl());
270 } 260 }
......
1 <?php namespace BookStack\Http\Controllers; 1 <?php namespace BookStack\Http\Controllers;
2 2
3 use Activity; 3 use Activity;
4 +use BookStack\Repos\EntityRepo;
4 use BookStack\Repos\UserRepo; 5 use BookStack\Repos\UserRepo;
5 use Illuminate\Http\Request; 6 use Illuminate\Http\Request;
6 -use BookStack\Repos\BookRepo;
7 -use BookStack\Repos\ChapterRepo;
8 use Illuminate\Http\Response; 7 use Illuminate\Http\Response;
9 use Views; 8 use Views;
10 9
11 class ChapterController extends Controller 10 class ChapterController extends Controller
12 { 11 {
13 12
14 - protected $bookRepo;
15 - protected $chapterRepo;
16 protected $userRepo; 13 protected $userRepo;
14 + protected $entityRepo;
17 15
18 /** 16 /**
19 * ChapterController constructor. 17 * ChapterController constructor.
20 - * @param BookRepo $bookRepo 18 + * @param EntityRepo $entityRepo
21 - * @param ChapterRepo $chapterRepo
22 * @param UserRepo $userRepo 19 * @param UserRepo $userRepo
23 */ 20 */
24 - public function __construct(BookRepo $bookRepo, ChapterRepo $chapterRepo, UserRepo $userRepo) 21 + public function __construct(EntityRepo $entityRepo, UserRepo $userRepo)
25 { 22 {
26 - $this->bookRepo = $bookRepo; 23 + $this->entityRepo = $entityRepo;
27 - $this->chapterRepo = $chapterRepo;
28 $this->userRepo = $userRepo; 24 $this->userRepo = $userRepo;
29 parent::__construct(); 25 parent::__construct();
30 } 26 }
...@@ -36,7 +32,7 @@ class ChapterController extends Controller ...@@ -36,7 +32,7 @@ class ChapterController extends Controller
36 */ 32 */
37 public function create($bookSlug) 33 public function create($bookSlug)
38 { 34 {
39 - $book = $this->bookRepo->getBySlug($bookSlug); 35 + $book = $this->entityRepo->getBySlug('book', $bookSlug);
40 $this->checkOwnablePermission('chapter-create', $book); 36 $this->checkOwnablePermission('chapter-create', $book);
41 $this->setPageTitle(trans('entities.chapters_create')); 37 $this->setPageTitle(trans('entities.chapters_create'));
42 return view('chapters/create', ['book' => $book, 'current' => $book]); 38 return view('chapters/create', ['book' => $book, 'current' => $book]);
...@@ -54,12 +50,12 @@ class ChapterController extends Controller ...@@ -54,12 +50,12 @@ class ChapterController extends Controller
54 'name' => 'required|string|max:255' 50 'name' => 'required|string|max:255'
55 ]); 51 ]);
56 52
57 - $book = $this->bookRepo->getBySlug($bookSlug); 53 + $book = $this->entityRepo->getBySlug('book', $bookSlug);
58 $this->checkOwnablePermission('chapter-create', $book); 54 $this->checkOwnablePermission('chapter-create', $book);
59 55
60 $input = $request->all(); 56 $input = $request->all();
61 - $input['priority'] = $this->bookRepo->getNewPriority($book); 57 + $input['priority'] = $this->entityRepo->getNewBookPriority($book);
62 - $chapter = $this->chapterRepo->createFromInput($input, $book); 58 + $chapter = $this->entityRepo->createFromInput('chapter', $input, $book);
63 Activity::add($chapter, 'chapter_create', $book->id); 59 Activity::add($chapter, 'chapter_create', $book->id);
64 return redirect($chapter->getUrl()); 60 return redirect($chapter->getUrl());
65 } 61 }
...@@ -72,15 +68,14 @@ class ChapterController extends Controller ...@@ -72,15 +68,14 @@ class ChapterController extends Controller
72 */ 68 */
73 public function show($bookSlug, $chapterSlug) 69 public function show($bookSlug, $chapterSlug)
74 { 70 {
75 - $book = $this->bookRepo->getBySlug($bookSlug); 71 + $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
76 - $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
77 $this->checkOwnablePermission('chapter-view', $chapter); 72 $this->checkOwnablePermission('chapter-view', $chapter);
78 - $sidebarTree = $this->bookRepo->getChildren($book); 73 + $sidebarTree = $this->entityRepo->getBookChildren($chapter->book);
79 Views::add($chapter); 74 Views::add($chapter);
80 $this->setPageTitle($chapter->getShortName()); 75 $this->setPageTitle($chapter->getShortName());
81 - $pages = $this->chapterRepo->getChildren($chapter); 76 + $pages = $this->entityRepo->getChapterChildren($chapter);
82 return view('chapters/show', [ 77 return view('chapters/show', [
83 - 'book' => $book, 78 + 'book' => $chapter->book,
84 'chapter' => $chapter, 79 'chapter' => $chapter,
85 'current' => $chapter, 80 'current' => $chapter,
86 'sidebarTree' => $sidebarTree, 81 'sidebarTree' => $sidebarTree,
...@@ -96,11 +91,10 @@ class ChapterController extends Controller ...@@ -96,11 +91,10 @@ class ChapterController extends Controller
96 */ 91 */
97 public function edit($bookSlug, $chapterSlug) 92 public function edit($bookSlug, $chapterSlug)
98 { 93 {
99 - $book = $this->bookRepo->getBySlug($bookSlug); 94 + $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
100 - $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
101 $this->checkOwnablePermission('chapter-update', $chapter); 95 $this->checkOwnablePermission('chapter-update', $chapter);
102 $this->setPageTitle(trans('entities.chapters_edit_named', ['chapterName' => $chapter->getShortName()])); 96 $this->setPageTitle(trans('entities.chapters_edit_named', ['chapterName' => $chapter->getShortName()]));
103 - return view('chapters/edit', ['book' => $book, 'chapter' => $chapter, 'current' => $chapter]); 97 + return view('chapters/edit', ['book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter]);
104 } 98 }
105 99
106 /** 100 /**
...@@ -112,16 +106,15 @@ class ChapterController extends Controller ...@@ -112,16 +106,15 @@ class ChapterController extends Controller
112 */ 106 */
113 public function update(Request $request, $bookSlug, $chapterSlug) 107 public function update(Request $request, $bookSlug, $chapterSlug)
114 { 108 {
115 - $book = $this->bookRepo->getBySlug($bookSlug); 109 + $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
116 - $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
117 $this->checkOwnablePermission('chapter-update', $chapter); 110 $this->checkOwnablePermission('chapter-update', $chapter);
118 if ($chapter->name !== $request->get('name')) { 111 if ($chapter->name !== $request->get('name')) {
119 - $chapter->slug = $this->chapterRepo->findSuitableSlug($request->get('name'), $book->id, $chapter->id); 112 + $chapter->slug = $this->entityRepo->findSuitableSlug('chapter', $request->get('name'), $chapter->id, $chapter->book->id);
120 } 113 }
121 $chapter->fill($request->all()); 114 $chapter->fill($request->all());
122 $chapter->updated_by = user()->id; 115 $chapter->updated_by = user()->id;
123 $chapter->save(); 116 $chapter->save();
124 - Activity::add($chapter, 'chapter_update', $book->id); 117 + Activity::add($chapter, 'chapter_update', $chapter->book->id);
125 return redirect($chapter->getUrl()); 118 return redirect($chapter->getUrl());
126 } 119 }
127 120
...@@ -133,11 +126,10 @@ class ChapterController extends Controller ...@@ -133,11 +126,10 @@ class ChapterController extends Controller
133 */ 126 */
134 public function showDelete($bookSlug, $chapterSlug) 127 public function showDelete($bookSlug, $chapterSlug)
135 { 128 {
136 - $book = $this->bookRepo->getBySlug($bookSlug); 129 + $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
137 - $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
138 $this->checkOwnablePermission('chapter-delete', $chapter); 130 $this->checkOwnablePermission('chapter-delete', $chapter);
139 $this->setPageTitle(trans('entities.chapters_delete_named', ['chapterName' => $chapter->getShortName()])); 131 $this->setPageTitle(trans('entities.chapters_delete_named', ['chapterName' => $chapter->getShortName()]));
140 - return view('chapters/delete', ['book' => $book, 'chapter' => $chapter, 'current' => $chapter]); 132 + return view('chapters/delete', ['book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter]);
141 } 133 }
142 134
143 /** 135 /**
...@@ -148,11 +140,11 @@ class ChapterController extends Controller ...@@ -148,11 +140,11 @@ class ChapterController extends Controller
148 */ 140 */
149 public function destroy($bookSlug, $chapterSlug) 141 public function destroy($bookSlug, $chapterSlug)
150 { 142 {
151 - $book = $this->bookRepo->getBySlug($bookSlug); 143 + $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
152 - $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id); 144 + $book = $chapter->book;
153 $this->checkOwnablePermission('chapter-delete', $chapter); 145 $this->checkOwnablePermission('chapter-delete', $chapter);
154 Activity::addMessage('chapter_delete', $book->id, $chapter->name); 146 Activity::addMessage('chapter_delete', $book->id, $chapter->name);
155 - $this->chapterRepo->destroy($chapter); 147 + $this->entityRepo->destroyChapter($chapter);
156 return redirect($book->getUrl()); 148 return redirect($book->getUrl());
157 } 149 }
158 150
...@@ -164,13 +156,12 @@ class ChapterController extends Controller ...@@ -164,13 +156,12 @@ class ChapterController extends Controller
164 * @throws \BookStack\Exceptions\NotFoundException 156 * @throws \BookStack\Exceptions\NotFoundException
165 */ 157 */
166 public function showMove($bookSlug, $chapterSlug) { 158 public function showMove($bookSlug, $chapterSlug) {
167 - $book = $this->bookRepo->getBySlug($bookSlug); 159 + $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
168 - $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
169 $this->setPageTitle(trans('entities.chapters_move_named', ['chapterName' => $chapter->getShortName()])); 160 $this->setPageTitle(trans('entities.chapters_move_named', ['chapterName' => $chapter->getShortName()]));
170 $this->checkOwnablePermission('chapter-update', $chapter); 161 $this->checkOwnablePermission('chapter-update', $chapter);
171 return view('chapters/move', [ 162 return view('chapters/move', [
172 'chapter' => $chapter, 163 'chapter' => $chapter,
173 - 'book' => $book 164 + 'book' => $chapter->book
174 ]); 165 ]);
175 } 166 }
176 167
...@@ -183,8 +174,7 @@ class ChapterController extends Controller ...@@ -183,8 +174,7 @@ class ChapterController extends Controller
183 * @throws \BookStack\Exceptions\NotFoundException 174 * @throws \BookStack\Exceptions\NotFoundException
184 */ 175 */
185 public function move($bookSlug, $chapterSlug, Request $request) { 176 public function move($bookSlug, $chapterSlug, Request $request) {
186 - $book = $this->bookRepo->getBySlug($bookSlug); 177 + $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
187 - $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
188 $this->checkOwnablePermission('chapter-update', $chapter); 178 $this->checkOwnablePermission('chapter-update', $chapter);
189 179
190 $entitySelection = $request->get('entity_selection', null); 180 $entitySelection = $request->get('entity_selection', null);
...@@ -199,7 +189,7 @@ class ChapterController extends Controller ...@@ -199,7 +189,7 @@ class ChapterController extends Controller
199 $parent = false; 189 $parent = false;
200 190
201 if ($entityType == 'book') { 191 if ($entityType == 'book') {
202 - $parent = $this->bookRepo->getById($entityId); 192 + $parent = $this->entityRepo->getById('book', $entityId);
203 } 193 }
204 194
205 if ($parent === false || $parent === null) { 195 if ($parent === false || $parent === null) {
...@@ -207,7 +197,7 @@ class ChapterController extends Controller ...@@ -207,7 +197,7 @@ class ChapterController extends Controller
207 return redirect()->back(); 197 return redirect()->back();
208 } 198 }
209 199
210 - $this->chapterRepo->changeBook($parent->id, $chapter, true); 200 + $this->entityRepo->changeBook('chapter', $parent->id, $chapter, true);
211 Activity::add($chapter, 'chapter_move', $chapter->book->id); 201 Activity::add($chapter, 'chapter_move', $chapter->book->id);
212 session()->flash('success', trans('entities.chapter_move_success', ['bookName' => $parent->name])); 202 session()->flash('success', trans('entities.chapter_move_success', ['bookName' => $parent->name]));
213 203
...@@ -222,8 +212,7 @@ class ChapterController extends Controller ...@@ -222,8 +212,7 @@ class ChapterController extends Controller
222 */ 212 */
223 public function showRestrict($bookSlug, $chapterSlug) 213 public function showRestrict($bookSlug, $chapterSlug)
224 { 214 {
225 - $book = $this->bookRepo->getBySlug($bookSlug); 215 + $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
226 - $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
227 $this->checkOwnablePermission('restrictions-manage', $chapter); 216 $this->checkOwnablePermission('restrictions-manage', $chapter);
228 $roles = $this->userRepo->getRestrictableRoles(); 217 $roles = $this->userRepo->getRestrictableRoles();
229 return view('chapters/restrictions', [ 218 return view('chapters/restrictions', [
...@@ -241,10 +230,9 @@ class ChapterController extends Controller ...@@ -241,10 +230,9 @@ class ChapterController extends Controller
241 */ 230 */
242 public function restrict($bookSlug, $chapterSlug, Request $request) 231 public function restrict($bookSlug, $chapterSlug, Request $request)
243 { 232 {
244 - $book = $this->bookRepo->getBySlug($bookSlug); 233 + $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
245 - $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
246 $this->checkOwnablePermission('restrictions-manage', $chapter); 234 $this->checkOwnablePermission('restrictions-manage', $chapter);
247 - $this->chapterRepo->updateEntityPermissionsFromRequest($request, $chapter); 235 + $this->entityRepo->updateEntityPermissionsFromRequest($request, $chapter);
248 session()->flash('success', trans('entities.chapters_permissions_success')); 236 session()->flash('success', trans('entities.chapters_permissions_success'));
249 return redirect($chapter->getUrl()); 237 return redirect($chapter->getUrl());
250 } 238 }
......
...@@ -5,6 +5,7 @@ namespace BookStack\Http\Controllers; ...@@ -5,6 +5,7 @@ namespace BookStack\Http\Controllers;
5 use Activity; 5 use Activity;
6 use BookStack\Repos\EntityRepo; 6 use BookStack\Repos\EntityRepo;
7 use BookStack\Http\Requests; 7 use BookStack\Http\Requests;
8 +use Illuminate\Http\Response;
8 use Views; 9 use Views;
9 10
10 class HomeController extends Controller 11 class HomeController extends Controller
...@@ -31,9 +32,9 @@ class HomeController extends Controller ...@@ -31,9 +32,9 @@ class HomeController extends Controller
31 $activity = Activity::latest(10); 32 $activity = Activity::latest(10);
32 $draftPages = $this->signedIn ? $this->entityRepo->getUserDraftPages(6) : []; 33 $draftPages = $this->signedIn ? $this->entityRepo->getUserDraftPages(6) : [];
33 $recentFactor = count($draftPages) > 0 ? 0.5 : 1; 34 $recentFactor = count($draftPages) > 0 ? 0.5 : 1;
34 - $recents = $this->signedIn ? Views::getUserRecentlyViewed(12*$recentFactor, 0) : $this->entityRepo->getRecentlyCreatedBooks(10*$recentFactor); 35 + $recents = $this->signedIn ? Views::getUserRecentlyViewed(12*$recentFactor, 0) : $this->entityRepo->getRecentlyCreated('book', 10*$recentFactor);
35 - $recentlyCreatedPages = $this->entityRepo->getRecentlyCreatedPages(5); 36 + $recentlyCreatedPages = $this->entityRepo->getRecentlyCreated('page', 5);
36 - $recentlyUpdatedPages = $this->entityRepo->getRecentlyUpdatedPages(5); 37 + $recentlyUpdatedPages = $this->entityRepo->getRecentlyUpdated('page', 5);
37 return view('home', [ 38 return view('home', [
38 'activity' => $activity, 39 'activity' => $activity,
39 'recents' => $recents, 40 'recents' => $recents,
......
1 <?php namespace BookStack\Http\Controllers; 1 <?php namespace BookStack\Http\Controllers;
2 2
3 use BookStack\Exceptions\ImageUploadException; 3 use BookStack\Exceptions\ImageUploadException;
4 +use BookStack\Repos\EntityRepo;
4 use BookStack\Repos\ImageRepo; 5 use BookStack\Repos\ImageRepo;
5 use Illuminate\Filesystem\Filesystem as File; 6 use Illuminate\Filesystem\Filesystem as File;
6 use Illuminate\Http\Request; 7 use Illuminate\Http\Request;
...@@ -150,12 +151,12 @@ class ImageController extends Controller ...@@ -150,12 +151,12 @@ class ImageController extends Controller
150 151
151 /** 152 /**
152 * Deletes an image and all thumbnail/image files 153 * Deletes an image and all thumbnail/image files
153 - * @param PageRepo $pageRepo 154 + * @param EntityRepo $entityRepo
154 * @param Request $request 155 * @param Request $request
155 * @param int $id 156 * @param int $id
156 * @return \Illuminate\Http\JsonResponse 157 * @return \Illuminate\Http\JsonResponse
157 */ 158 */
158 - public function destroy(PageRepo $pageRepo, Request $request, $id) 159 + public function destroy(EntityRepo $entityRepo, Request $request, $id)
159 { 160 {
160 $image = $this->imageRepo->getById($id); 161 $image = $this->imageRepo->getById($id);
161 $this->checkOwnablePermission('image-delete', $image); 162 $this->checkOwnablePermission('image-delete', $image);
...@@ -163,7 +164,7 @@ class ImageController extends Controller ...@@ -163,7 +164,7 @@ class ImageController extends Controller
163 // Check if this image is used on any pages 164 // Check if this image is used on any pages
164 $isForced = ($request->has('force') && ($request->get('force') === 'true') || $request->get('force') === true); 165 $isForced = ($request->has('force') && ($request->get('force') === 'true') || $request->get('force') === true);
165 if (!$isForced) { 166 if (!$isForced) {
166 - $pageSearch = $pageRepo->searchForImage($image->url); 167 + $pageSearch = $entityRepo->searchForImage($image->url);
167 if ($pageSearch !== false) { 168 if ($pageSearch !== false) {
168 return response()->json($pageSearch, 400); 169 return response()->json($pageSearch, 400);
169 } 170 }
......
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) {
......
...@@ -4,8 +4,6 @@ namespace BookStack\Http\Middleware; ...@@ -4,8 +4,6 @@ namespace BookStack\Http\Middleware;
4 4
5 use Closure; 5 use Closure;
6 use Illuminate\Contracts\Auth\Guard; 6 use Illuminate\Contracts\Auth\Guard;
7 -use BookStack\Exceptions\UserRegistrationException;
8 -use Setting;
9 7
10 class Authenticate 8 class Authenticate
11 { 9 {
......
...@@ -7,6 +7,10 @@ class Page extends Entity ...@@ -7,6 +7,10 @@ class Page extends Entity
7 7
8 protected $simpleAttributes = ['name', 'id', 'slug']; 8 protected $simpleAttributes = ['name', 'id', 'slug'];
9 9
10 + protected $with = ['book'];
11 +
12 + protected $fieldsToSearch = ['name', 'text'];
13 +
10 /** 14 /**
11 * Converts this page into a simplified array. 15 * Converts this page into a simplified array.
12 * @return mixed 16 * @return mixed
......
1 -<?php namespace BookStack\Repos;
2 -
3 -use Alpha\B;
4 -use BookStack\Exceptions\NotFoundException;
5 -use Illuminate\Database\Eloquent\Collection;
6 -use Illuminate\Support\Str;
7 -use BookStack\Book;
8 -use Views;
9 -
10 -class BookRepo extends EntityRepo
11 -{
12 - protected $pageRepo;
13 - protected $chapterRepo;
14 -
15 - /**
16 - * BookRepo constructor.
17 - * @param PageRepo $pageRepo
18 - * @param ChapterRepo $chapterRepo
19 - */
20 - public function __construct(PageRepo $pageRepo, ChapterRepo $chapterRepo)
21 - {
22 - $this->pageRepo = $pageRepo;
23 - $this->chapterRepo = $chapterRepo;
24 - parent::__construct();
25 - }
26 -
27 - /**
28 - * Base query for getting books.
29 - * Takes into account any restrictions.
30 - * @return mixed
31 - */
32 - private function bookQuery()
33 - {
34 - return $this->permissionService->enforceBookRestrictions($this->book, 'view');
35 - }
36 -
37 - /**
38 - * Get the book that has the given id.
39 - * @param $id
40 - * @return mixed
41 - */
42 - public function getById($id)
43 - {
44 - return $this->bookQuery()->findOrFail($id);
45 - }
46 -
47 - /**
48 - * Get all books, Limited by count.
49 - * @param int $count
50 - * @return mixed
51 - */
52 - public function getAll($count = 10)
53 - {
54 - $bookQuery = $this->bookQuery()->orderBy('name', 'asc');
55 - if (!$count) return $bookQuery->get();
56 - return $bookQuery->take($count)->get();
57 - }
58 -
59 - /**
60 - * Get all books paginated.
61 - * @param int $count
62 - * @return mixed
63 - */
64 - public function getAllPaginated($count = 10)
65 - {
66 - return $this->bookQuery()
67 - ->orderBy('name', 'asc')->paginate($count);
68 - }
69 -
70 -
71 - /**
72 - * Get the latest books.
73 - * @param int $count
74 - * @return mixed
75 - */
76 - public function getLatest($count = 10)
77 - {
78 - return $this->bookQuery()->orderBy('created_at', 'desc')->take($count)->get();
79 - }
80 -
81 - /**
82 - * Gets the most recently viewed for a user.
83 - * @param int $count
84 - * @param int $page
85 - * @return mixed
86 - */
87 - public function getRecentlyViewed($count = 10, $page = 0)
88 - {
89 - return Views::getUserRecentlyViewed($count, $page, $this->book);
90 - }
91 -
92 - /**
93 - * Gets the most viewed books.
94 - * @param int $count
95 - * @param int $page
96 - * @return mixed
97 - */
98 - public function getPopular($count = 10, $page = 0)
99 - {
100 - return Views::getPopular($count, $page, $this->book);
101 - }
102 -
103 - /**
104 - * Get a book by slug
105 - * @param $slug
106 - * @return mixed
107 - * @throws NotFoundException
108 - */
109 - public function getBySlug($slug)
110 - {
111 - $book = $this->bookQuery()->where('slug', '=', $slug)->first();
112 - if ($book === null) throw new NotFoundException(trans('errors.book_not_found'));
113 - return $book;
114 - }
115 -
116 - /**
117 - * Checks if a book exists.
118 - * @param $id
119 - * @return bool
120 - */
121 - public function exists($id)
122 - {
123 - return $this->bookQuery()->where('id', '=', $id)->exists();
124 - }
125 -
126 - /**
127 - * Get a new book instance from request input.
128 - * @param array $input
129 - * @return Book
130 - */
131 - public function createFromInput($input)
132 - {
133 - $book = $this->book->newInstance($input);
134 - $book->slug = $this->findSuitableSlug($book->name);
135 - $book->created_by = user()->id;
136 - $book->updated_by = user()->id;
137 - $book->save();
138 - $this->permissionService->buildJointPermissionsForEntity($book);
139 - return $book;
140 - }
141 -
142 - /**
143 - * Update the given book from user input.
144 - * @param Book $book
145 - * @param $input
146 - * @return Book
147 - */
148 - public function updateFromInput(Book $book, $input)
149 - {
150 - if ($book->name !== $input['name']) {
151 - $book->slug = $this->findSuitableSlug($input['name'], $book->id);
152 - }
153 - $book->fill($input);
154 - $book->updated_by = user()->id;
155 - $book->save();
156 - $this->permissionService->buildJointPermissionsForEntity($book);
157 - return $book;
158 - }
159 -
160 - /**
161 - * Destroy the given book.
162 - * @param Book $book
163 - * @throws \Exception
164 - */
165 - public function destroy(Book $book)
166 - {
167 - foreach ($book->pages as $page) {
168 - $this->pageRepo->destroy($page);
169 - }
170 - foreach ($book->chapters as $chapter) {
171 - $this->chapterRepo->destroy($chapter);
172 - }
173 - $book->views()->delete();
174 - $book->permissions()->delete();
175 - $this->permissionService->deleteJointPermissionsForEntity($book);
176 - $book->delete();
177 - }
178 -
179 - /**
180 - * Get the next child element priority.
181 - * @param Book $book
182 - * @return int
183 - */
184 - public function getNewPriority($book)
185 - {
186 - $lastElem = $this->getChildren($book)->pop();
187 - return $lastElem ? $lastElem->priority + 1 : 0;
188 - }
189 -
190 - /**
191 - * @param string $slug
192 - * @param bool|false $currentId
193 - * @return bool
194 - */
195 - public function doesSlugExist($slug, $currentId = false)
196 - {
197 - $query = $this->book->where('slug', '=', $slug);
198 - if ($currentId) {
199 - $query = $query->where('id', '!=', $currentId);
200 - }
201 - return $query->count() > 0;
202 - }
203 -
204 - /**
205 - * Provides a suitable slug for the given book name.
206 - * Ensures the returned slug is unique in the system.
207 - * @param string $name
208 - * @param bool|false $currentId
209 - * @return string
210 - */
211 - public function findSuitableSlug($name, $currentId = false)
212 - {
213 - $slug = $this->nameToSlug($name);
214 - while ($this->doesSlugExist($slug, $currentId)) {
215 - $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
216 - }
217 - return $slug;
218 - }
219 -
220 - /**
221 - * Get all child objects of a book.
222 - * Returns a sorted collection of Pages and Chapters.
223 - * Loads the book slug onto child elements to prevent access database access for getting the slug.
224 - * @param Book $book
225 - * @param bool $filterDrafts
226 - * @return mixed
227 - */
228 - public function getChildren(Book $book, $filterDrafts = false)
229 - {
230 - $pageQuery = $book->pages()->where('chapter_id', '=', 0);
231 - $pageQuery = $this->permissionService->enforcePageRestrictions($pageQuery, 'view');
232 -
233 - if ($filterDrafts) {
234 - $pageQuery = $pageQuery->where('draft', '=', false);
235 - }
236 -
237 - $pages = $pageQuery->get();
238 -
239 - $chapterQuery = $book->chapters()->with(['pages' => function ($query) use ($filterDrafts) {
240 - $this->permissionService->enforcePageRestrictions($query, 'view');
241 - if ($filterDrafts) $query->where('draft', '=', false);
242 - }]);
243 - $chapterQuery = $this->permissionService->enforceChapterRestrictions($chapterQuery, 'view');
244 - $chapters = $chapterQuery->get();
245 - $children = $pages->values();
246 - foreach ($chapters as $chapter) {
247 - $children->push($chapter);
248 - }
249 - $bookSlug = $book->slug;
250 -
251 - $children->each(function ($child) use ($bookSlug) {
252 - $child->setAttribute('bookSlug', $bookSlug);
253 - if ($child->isA('chapter')) {
254 - $child->pages->each(function ($page) use ($bookSlug) {
255 - $page->setAttribute('bookSlug', $bookSlug);
256 - });
257 - $child->pages = $child->pages->sortBy(function ($child, $key) {
258 - $score = $child->priority;
259 - if ($child->draft) $score -= 100;
260 - return $score;
261 - });
262 - }
263 - });
264 -
265 - // Sort items with drafts first then by priority.
266 - return $children->sortBy(function ($child, $key) {
267 - $score = $child->priority;
268 - if ($child->isA('page') && $child->draft) $score -= 100;
269 - return $score;
270 - });
271 - }
272 -
273 - /**
274 - * Get books by search term.
275 - * @param $term
276 - * @param int $count
277 - * @param array $paginationAppends
278 - * @return mixed
279 - */
280 - public function getBySearch($term, $count = 20, $paginationAppends = [])
281 - {
282 - $terms = $this->prepareSearchTerms($term);
283 - $bookQuery = $this->permissionService->enforceBookRestrictions($this->book->fullTextSearchQuery(['name', 'description'], $terms));
284 - $bookQuery = $this->addAdvancedSearchQueries($bookQuery, $term);
285 - $books = $bookQuery->paginate($count)->appends($paginationAppends);
286 - $words = join('|', explode(' ', preg_quote(trim($term), '/')));
287 - foreach ($books as $book) {
288 - //highlight
289 - $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $book->getExcerpt(100));
290 - $book->searchSnippet = $result;
291 - }
292 - return $books;
293 - }
294 -
295 -}
...\ No newline at end of file ...\ No newline at end of file
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 - * Base query for getting chapters, Takes permissions into account.
26 - * @return mixed
27 - */
28 - private function chapterQuery()
29 - {
30 - return $this->permissionService->enforceChapterRestrictions($this->chapter, 'view');
31 - }
32 -
33 - /**
34 - * Check if an id exists.
35 - * @param $id
36 - * @return bool
37 - */
38 - public function idExists($id)
39 - {
40 - return $this->chapterQuery()->where('id', '=', $id)->count() > 0;
41 - }
42 -
43 - /**
44 - * Get a chapter by a specific id.
45 - * @param $id
46 - * @return mixed
47 - */
48 - public function getById($id)
49 - {
50 - return $this->chapterQuery()->findOrFail($id);
51 - }
52 -
53 - /**
54 - * Get all chapters.
55 - * @return \Illuminate\Database\Eloquent\Collection|static[]
56 - */
57 - public function getAll()
58 - {
59 - return $this->chapterQuery()->all();
60 - }
61 -
62 - /**
63 - * Get a chapter that has the given slug within the given book.
64 - * @param $slug
65 - * @param $bookId
66 - * @return mixed
67 - * @throws NotFoundException
68 - */
69 - public function getBySlug($slug, $bookId)
70 - {
71 - $chapter = $this->chapterQuery()->where('slug', '=', $slug)->where('book_id', '=', $bookId)->first();
72 - if ($chapter === null) throw new NotFoundException(trans('errors.chapter_not_found'));
73 - return $chapter;
74 - }
75 -
76 - /**
77 - * Get the child items for a chapter
78 - * @param Chapter $chapter
79 - */
80 - public function getChildren(Chapter $chapter)
81 - {
82 - $pages = $this->permissionService->enforcePageRestrictions($chapter->pages())->get();
83 - // Sort items with drafts first then by priority.
84 - return $pages->sortBy(function ($child, $key) {
85 - $score = $child->priority;
86 - if ($child->draft) $score -= 100;
87 - return $score;
88 - });
89 - }
90 -
91 - /**
92 - * Create a new chapter from request input.
93 - * @param $input
94 - * @param Book $book
95 - * @return Chapter
96 - */
97 - public function createFromInput($input, Book $book)
98 - {
99 - $chapter = $this->chapter->newInstance($input);
100 - $chapter->slug = $this->findSuitableSlug($chapter->name, $book->id);
101 - $chapter->created_by = user()->id;
102 - $chapter->updated_by = user()->id;
103 - $chapter = $book->chapters()->save($chapter);
104 - $this->permissionService->buildJointPermissionsForEntity($chapter);
105 - return $chapter;
106 - }
107 -
108 - /**
109 - * Destroy a chapter and its relations by providing its slug.
110 - * @param Chapter $chapter
111 - */
112 - public function destroy(Chapter $chapter)
113 - {
114 - if (count($chapter->pages) > 0) {
115 - foreach ($chapter->pages as $page) {
116 - $page->chapter_id = 0;
117 - $page->save();
118 - }
119 - }
120 - Activity::removeEntity($chapter);
121 - $chapter->views()->delete();
122 - $chapter->permissions()->delete();
123 - $this->permissionService->deleteJointPermissionsForEntity($chapter);
124 - $chapter->delete();
125 - }
126 -
127 - /**
128 - * Check if a chapter's slug exists.
129 - * @param $slug
130 - * @param $bookId
131 - * @param bool|false $currentId
132 - * @return bool
133 - */
134 - public function doesSlugExist($slug, $bookId, $currentId = false)
135 - {
136 - $query = $this->chapter->where('slug', '=', $slug)->where('book_id', '=', $bookId);
137 - if ($currentId) {
138 - $query = $query->where('id', '!=', $currentId);
139 - }
140 - return $query->count() > 0;
141 - }
142 -
143 - /**
144 - * Finds a suitable slug for the provided name.
145 - * Checks database to prevent duplicate slugs.
146 - * @param $name
147 - * @param $bookId
148 - * @param bool|false $currentId
149 - * @return string
150 - */
151 - public function findSuitableSlug($name, $bookId, $currentId = false)
152 - {
153 - $slug = $this->nameToSlug($name);
154 - while ($this->doesSlugExist($slug, $bookId, $currentId)) {
155 - $slug .= '-' . substr(md5(rand(1, 500)), 0, 3);
156 - }
157 - return $slug;
158 - }
159 -
160 - /**
161 - * Get a new priority value for a new page to be added
162 - * to the given chapter.
163 - * @param Chapter $chapter
164 - * @return int
165 - */
166 - public function getNewPriority(Chapter $chapter)
167 - {
168 - $lastPage = $chapter->pages->last();
169 - return $lastPage !== null ? $lastPage->priority + 1 : 0;
170 - }
171 -
172 - /**
173 - * Get chapters by the given search term.
174 - * @param string $term
175 - * @param array $whereTerms
176 - * @param int $count
177 - * @param array $paginationAppends
178 - * @return mixed
179 - */
180 - public function getBySearch($term, $whereTerms = [], $count = 20, $paginationAppends = [])
181 - {
182 - $terms = $this->prepareSearchTerms($term);
183 - $chapterQuery = $this->permissionService->enforceChapterRestrictions($this->chapter->fullTextSearchQuery(['name', 'description'], $terms, $whereTerms));
184 - $chapterQuery = $this->addAdvancedSearchQueries($chapterQuery, $term);
185 - $chapters = $chapterQuery->paginate($count)->appends($paginationAppends);
186 - $words = join('|', explode(' ', preg_quote(trim($term), '/')));
187 - foreach ($chapters as $chapter) {
188 - //highlight
189 - $result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $chapter->getExcerpt(100));
190 - $chapter->searchSnippet = $result;
191 - }
192 - return $chapters;
193 - }
194 -
195 - /**
196 - * Changes the book relation of this chapter.
197 - * @param $bookId
198 - * @param Chapter $chapter
199 - * @param bool $rebuildPermissions
200 - * @return Chapter
201 - */
202 - public function changeBook($bookId, Chapter $chapter, $rebuildPermissions = false)
203 - {
204 - $chapter->book_id = $bookId;
205 - // Update related activity
206 - foreach ($chapter->activity as $activity) {
207 - $activity->book_id = $bookId;
208 - $activity->save();
209 - }
210 - $chapter->slug = $this->findSuitableSlug($chapter->name, $bookId, $chapter->id);
211 - $chapter->save();
212 - // Update all child pages
213 - foreach ($chapter->pages as $page) {
214 - $this->pageRepo->changeBook($bookId, $page);
215 - }
216 -
217 - // Update permissions if applicable
218 - if ($rebuildPermissions) {
219 - $chapter->load('book');
220 - $this->permissionService->buildJointPermissionsForEntity($chapter->book);
221 - }
222 -
223 - return $chapter;
224 - }
225 -
226 -}
...\ No newline at end of file ...\ No newline at end of file
...@@ -38,7 +38,7 @@ class TagRepo ...@@ -38,7 +38,7 @@ class TagRepo
38 { 38 {
39 $entityInstance = $this->entity->getEntityInstance($entityType); 39 $entityInstance = $this->entity->getEntityInstance($entityType);
40 $searchQuery = $entityInstance->where('id', '=', $entityId)->with('tags'); 40 $searchQuery = $entityInstance->where('id', '=', $entityId)->with('tags');
41 - $searchQuery = $this->permissionService->enforceEntityRestrictions($searchQuery, $action); 41 + $searchQuery = $this->permissionService->enforceEntityRestrictions($entityType, $searchQuery, $action);
42 return $searchQuery->first(); 42 return $searchQuery->first();
43 } 43 }
44 44
......
...@@ -168,13 +168,13 @@ class UserRepo ...@@ -168,13 +168,13 @@ class UserRepo
168 public function getRecentlyCreated(User $user, $count = 20) 168 public function getRecentlyCreated(User $user, $count = 20)
169 { 169 {
170 return [ 170 return [
171 - 'pages' => $this->entityRepo->getRecentlyCreatedPages($count, 0, function ($query) use ($user) { 171 + 'pages' => $this->entityRepo->getRecentlyCreated('page', $count, 0, function ($query) use ($user) {
172 $query->where('created_by', '=', $user->id); 172 $query->where('created_by', '=', $user->id);
173 }), 173 }),
174 - 'chapters' => $this->entityRepo->getRecentlyCreatedChapters($count, 0, function ($query) use ($user) { 174 + 'chapters' => $this->entityRepo->getRecentlyCreated('chapter', $count, 0, function ($query) use ($user) {
175 $query->where('created_by', '=', $user->id); 175 $query->where('created_by', '=', $user->id);
176 }), 176 }),
177 - 'books' => $this->entityRepo->getRecentlyCreatedBooks($count, 0, function ($query) use ($user) { 177 + 'books' => $this->entityRepo->getRecentlyCreated('book', $count, 0, function ($query) use ($user) {
178 $query->where('created_by', '=', $user->id); 178 $query->where('created_by', '=', $user->id);
179 }) 179 })
180 ]; 180 ];
......
...@@ -114,7 +114,7 @@ class ActivityService ...@@ -114,7 +114,7 @@ class ActivityService
114 114
115 $activity = $this->permissionService 115 $activity = $this->permissionService
116 ->filterRestrictedEntityRelations($query, 'activities', 'entity_id', 'entity_type') 116 ->filterRestrictedEntityRelations($query, 'activities', 'entity_id', 'entity_type')
117 - ->orderBy('created_at', 'desc')->skip($count * $page)->take($count)->get(); 117 + ->orderBy('created_at', 'desc')->with(['entity', 'user.avatar'])->skip($count * $page)->take($count)->get();
118 118
119 return $this->filterSimilar($activity); 119 return $this->filterSimilar($activity);
120 } 120 }
......
...@@ -8,8 +8,9 @@ use BookStack\Ownable; ...@@ -8,8 +8,9 @@ use BookStack\Ownable;
8 use BookStack\Page; 8 use BookStack\Page;
9 use BookStack\Role; 9 use BookStack\Role;
10 use BookStack\User; 10 use BookStack\User;
11 +use Illuminate\Database\Connection;
12 +use Illuminate\Database\Eloquent\Builder;
11 use Illuminate\Support\Collection; 13 use Illuminate\Support\Collection;
12 -use Illuminate\Support\Facades\Log;
13 14
14 class PermissionService 15 class PermissionService
15 { 16 {
...@@ -23,6 +24,8 @@ class PermissionService ...@@ -23,6 +24,8 @@ class PermissionService
23 public $chapter; 24 public $chapter;
24 public $page; 25 public $page;
25 26
27 + protected $db;
28 +
26 protected $jointPermission; 29 protected $jointPermission;
27 protected $role; 30 protected $role;
28 31
...@@ -31,18 +34,21 @@ class PermissionService ...@@ -31,18 +34,21 @@ class PermissionService
31 /** 34 /**
32 * PermissionService constructor. 35 * PermissionService constructor.
33 * @param JointPermission $jointPermission 36 * @param JointPermission $jointPermission
37 + * @param Connection $db
34 * @param Book $book 38 * @param Book $book
35 * @param Chapter $chapter 39 * @param Chapter $chapter
36 * @param Page $page 40 * @param Page $page
37 * @param Role $role 41 * @param Role $role
38 */ 42 */
39 - public function __construct(JointPermission $jointPermission, Book $book, Chapter $chapter, Page $page, Role $role) 43 + public function __construct(JointPermission $jointPermission, Connection $db, Book $book, Chapter $chapter, Page $page, Role $role)
40 { 44 {
45 + $this->db = $db;
41 $this->jointPermission = $jointPermission; 46 $this->jointPermission = $jointPermission;
42 $this->role = $role; 47 $this->role = $role;
43 $this->book = $book; 48 $this->book = $book;
44 $this->chapter = $chapter; 49 $this->chapter = $chapter;
45 $this->page = $page; 50 $this->page = $page;
51 + // TODO - Update so admin still goes through filters
46 } 52 }
47 53
48 /** 54 /**
...@@ -302,6 +308,10 @@ class PermissionService ...@@ -302,6 +308,10 @@ class PermissionService
302 $explodedAction = explode('-', $action); 308 $explodedAction = explode('-', $action);
303 $restrictionAction = end($explodedAction); 309 $restrictionAction = end($explodedAction);
304 310
311 + if ($role->system_name === 'admin') {
312 + return $this->createJointPermissionDataArray($entity, $role, $action, true, true);
313 + }
314 +
305 if ($entity->isA('book')) { 315 if ($entity->isA('book')) {
306 316
307 if (!$entity->restricted) { 317 if (!$entity->restricted) {
...@@ -461,14 +471,61 @@ class PermissionService ...@@ -461,14 +471,61 @@ class PermissionService
461 return $q; 471 return $q;
462 } 472 }
463 473
474 + public function bookChildrenQuery($book_id, $filterDrafts = false) {
475 +
476 + // Draft setup
477 + $params = [
478 + 'userId' => $this->currentUser()->id,
479 + 'bookIdPage' => $book_id,
480 + 'bookIdChapter' => $book_id
481 + ];
482 + if (!$filterDrafts) {
483 + $params['userIdDrafts'] = $this->currentUser()->id;
484 + }
485 + // Role setup
486 + $userRoles = $this->getRoles();
487 + $roleBindings = [];
488 + $roleValues = [];
489 + foreach ($userRoles as $index => $roleId) {
490 + $roleBindings[':role'.$index] = $roleId;
491 + $roleValues['role'.$index] = $roleId;
492 + }
493 + // TODO - Clean this up, Maybe extract into a nice class for doing these kind of manual things
494 + // Something which will handle the above role crap in a nice clean way
495 + $roleBindingString = implode(',', array_keys($roleBindings));
496 + $query = "SELECT * from (
497 +(SELECT 'Bookstack\\\Page' as entity_type, id, slug, name, text, '' as description, book_id, priority, chapter_id, draft FROM {$this->page->getTable()}
498 + where book_id = :bookIdPage AND ". ($filterDrafts ? '(draft = 0)' : '(draft = 0 OR (draft = 1 AND created_by = :userIdDrafts))') .")
499 +UNION
500 +(SELECT 'Bookstack\\\Chapter' as entity_type, id, slug, name, '' as text, description, book_id, priority, 0 as chapter_id, 0 as draft FROM {$this->chapter->getTable()} WHERE book_id = :bookIdChapter)
501 +) as U WHERE (
502 + SELECT COUNT(*) FROM {$this->jointPermission->getTable()} jp
503 + WHERE
504 + jp.entity_id=U.id AND
505 + jp.entity_type=U.entity_type AND
506 + jp.action = 'view' AND
507 + jp.role_id IN ({$roleBindingString}) AND
508 + (
509 + jp.has_permission = 1 OR
510 + (jp.has_permission_own = 1 AND jp.created_by = :userId)
511 + )
512 +) > 0
513 +ORDER BY draft desc, priority asc";
514 +
515 + $this->clean();
516 + return $this->db->select($query, array_replace($roleValues, $params));
517 + }
518 +
464 /** 519 /**
465 - * Add restrictions for a page query 520 + * Add restrictions for a generic entity
466 - * @param $query 521 + * @param string $entityType
522 + * @param Builder|Entity $query
467 * @param string $action 523 * @param string $action
468 * @return mixed 524 * @return mixed
469 */ 525 */
470 - public function enforcePageRestrictions($query, $action = 'view') 526 + public function enforceEntityRestrictions($entityType, $query, $action = 'view')
471 { 527 {
528 + if (strtolower($entityType) === 'page') {
472 // Prevent drafts being visible to others. 529 // Prevent drafts being visible to others.
473 $query = $query->where(function ($query) { 530 $query = $query->where(function ($query) {
474 $query->where('draft', '=', false); 531 $query->where('draft', '=', false);
...@@ -478,44 +535,13 @@ class PermissionService ...@@ -478,44 +535,13 @@ class PermissionService
478 }); 535 });
479 } 536 }
480 }); 537 });
481 -
482 - return $this->enforceEntityRestrictions($query, $action);
483 - }
484 -
485 - /**
486 - * Add on permission restrictions to a chapter query.
487 - * @param $query
488 - * @param string $action
489 - * @return mixed
490 - */
491 - public function enforceChapterRestrictions($query, $action = 'view')
492 - {
493 - return $this->enforceEntityRestrictions($query, $action);
494 - }
495 -
496 - /**
497 - * Add restrictions to a book query.
498 - * @param $query
499 - * @param string $action
500 - * @return mixed
501 - */
502 - public function enforceBookRestrictions($query, $action = 'view')
503 - {
504 - return $this->enforceEntityRestrictions($query, $action);
505 } 538 }
506 539
507 - /**
508 - * Add restrictions for a generic entity
509 - * @param $query
510 - * @param string $action
511 - * @return mixed
512 - */
513 - public function enforceEntityRestrictions($query, $action = 'view')
514 - {
515 if ($this->isAdmin()) { 540 if ($this->isAdmin()) {
516 $this->clean(); 541 $this->clean();
517 return $query; 542 return $query;
518 } 543 }
544 +
519 $this->currentAction = $action; 545 $this->currentAction = $action;
520 return $this->entityRestrictionQuery($query); 546 return $this->entityRestrictionQuery($query);
521 } 547 }
...@@ -601,7 +627,7 @@ class PermissionService ...@@ -601,7 +627,7 @@ class PermissionService
601 private function isAdmin() 627 private function isAdmin()
602 { 628 {
603 if ($this->isAdminUser === null) { 629 if ($this->isAdminUser === null) {
604 - $this->isAdminUser = ($this->currentUser()->id !== null) ? $this->currentUser()->hasRole('admin') : false; 630 + $this->isAdminUser = ($this->currentUser()->id !== null) ? $this->currentUser()->hasSystemRole('admin') : false;
605 } 631 }
606 632
607 return $this->isAdminUser; 633 return $this->isAdminUser;
......
...@@ -5,9 +5,7 @@ use BookStack\View; ...@@ -5,9 +5,7 @@ use BookStack\View;
5 5
6 class ViewService 6 class ViewService
7 { 7 {
8 -
9 protected $view; 8 protected $view;
10 - protected $user;
11 protected $permissionService; 9 protected $permissionService;
12 10
13 /** 11 /**
...@@ -18,7 +16,6 @@ class ViewService ...@@ -18,7 +16,6 @@ class ViewService
18 public function __construct(View $view, PermissionService $permissionService) 16 public function __construct(View $view, PermissionService $permissionService)
19 { 17 {
20 $this->view = $view; 18 $this->view = $view;
21 - $this->user = user();
22 $this->permissionService = $permissionService; 19 $this->permissionService = $permissionService;
23 } 20 }
24 21
...@@ -29,8 +26,9 @@ class ViewService ...@@ -29,8 +26,9 @@ class ViewService
29 */ 26 */
30 public function add(Entity $entity) 27 public function add(Entity $entity)
31 { 28 {
32 - if ($this->user === null) return 0; 29 + $user = user();
33 - $view = $entity->views()->where('user_id', '=', $this->user->id)->first(); 30 + if ($user === null || $user->isDefault()) return 0;
31 + $view = $entity->views()->where('user_id', '=', $user->id)->first();
34 // Add view if model exists 32 // Add view if model exists
35 if ($view) { 33 if ($view) {
36 $view->increment('views'); 34 $view->increment('views');
...@@ -39,7 +37,7 @@ class ViewService ...@@ -39,7 +37,7 @@ class ViewService
39 37
40 // Otherwise create new view count 38 // Otherwise create new view count
41 $entity->views()->save($this->view->create([ 39 $entity->views()->save($this->view->create([
42 - 'user_id' => $this->user->id, 40 + 'user_id' => $user->id,
43 'views' => 1 41 'views' => 1
44 ])); 42 ]));
45 43
...@@ -78,13 +76,14 @@ class ViewService ...@@ -78,13 +76,14 @@ class ViewService
78 */ 76 */
79 public function getUserRecentlyViewed($count = 10, $page = 0, $filterModel = false) 77 public function getUserRecentlyViewed($count = 10, $page = 0, $filterModel = false)
80 { 78 {
81 - if ($this->user === null) return collect(); 79 + $user = user();
80 + if ($user === null || $user->isDefault()) return collect();
82 81
83 $query = $this->permissionService 82 $query = $this->permissionService
84 ->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type'); 83 ->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type');
85 84
86 if ($filterModel) $query = $query->where('viewable_type', '=', get_class($filterModel)); 85 if ($filterModel) $query = $query->where('viewable_type', '=', get_class($filterModel));
87 - $query = $query->where('user_id', '=', user()->id); 86 + $query = $query->where('user_id', '=', $user->id);
88 87
89 $viewables = $query->with('viewable')->orderBy('updated_at', 'desc') 88 $viewables = $query->with('viewable')->orderBy('updated_at', 'desc')
90 ->skip($count * $page)->take($count)->get()->pluck('viewable'); 89 ->skip($count * $page)->take($count)->get()->pluck('viewable');
......
...@@ -75,6 +75,16 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon ...@@ -75,6 +75,16 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
75 } 75 }
76 76
77 /** 77 /**
78 + * Check if the user has a role.
79 + * @param $role
80 + * @return mixed
81 + */
82 + public function hasSystemRole($role)
83 + {
84 + return $this->roles->pluck('system_name')->contains('admin');
85 + }
86 +
87 + /**
78 * Get all permissions belonging to a the current user. 88 * Get all permissions belonging to a the current user.
79 * @param bool $cache 89 * @param bool $cache
80 * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough 90 * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
......
...@@ -168,7 +168,7 @@ class EntityTest extends TestCase ...@@ -168,7 +168,7 @@ class EntityTest extends TestCase
168 $entities = $this->createEntityChainBelongingToUser($creator, $updater); 168 $entities = $this->createEntityChainBelongingToUser($creator, $updater);
169 $this->actingAs($creator); 169 $this->actingAs($creator);
170 app('BookStack\Repos\UserRepo')->destroy($creator); 170 app('BookStack\Repos\UserRepo')->destroy($creator);
171 - app('BookStack\Repos\PageRepo')->saveRevision($entities['page']); 171 + app('BookStack\Repos\EntityRepo')->savePageRevision($entities['page']);
172 172
173 $this->checkEntitiesViewable($entities); 173 $this->checkEntitiesViewable($entities);
174 } 174 }
...@@ -181,7 +181,7 @@ class EntityTest extends TestCase ...@@ -181,7 +181,7 @@ class EntityTest extends TestCase
181 $entities = $this->createEntityChainBelongingToUser($creator, $updater); 181 $entities = $this->createEntityChainBelongingToUser($creator, $updater);
182 $this->actingAs($updater); 182 $this->actingAs($updater);
183 app('BookStack\Repos\UserRepo')->destroy($updater); 183 app('BookStack\Repos\UserRepo')->destroy($updater);
184 - app('BookStack\Repos\PageRepo')->saveRevision($entities['page']); 184 + app('BookStack\Repos\EntityRepo')->savePageRevision($entities['page']);
185 185
186 $this->checkEntitiesViewable($entities); 186 $this->checkEntitiesViewable($entities);
187 } 187 }
......
...@@ -4,13 +4,13 @@ ...@@ -4,13 +4,13 @@
4 class PageDraftTest extends TestCase 4 class PageDraftTest extends TestCase
5 { 5 {
6 protected $page; 6 protected $page;
7 - protected $pageRepo; 7 + protected $entityRepo;
8 8
9 public function setUp() 9 public function setUp()
10 { 10 {
11 parent::setUp(); 11 parent::setUp();
12 $this->page = \BookStack\Page::first(); 12 $this->page = \BookStack\Page::first();
13 - $this->pageRepo = app('\BookStack\Repos\PageRepo'); 13 + $this->entityRepo = app('\BookStack\Repos\EntityRepo');
14 } 14 }
15 15
16 public function test_draft_content_shows_if_available() 16 public function test_draft_content_shows_if_available()
...@@ -20,7 +20,7 @@ class PageDraftTest extends TestCase ...@@ -20,7 +20,7 @@ class PageDraftTest extends TestCase
20 ->dontSeeInField('html', $addedContent); 20 ->dontSeeInField('html', $addedContent);
21 21
22 $newContent = $this->page->html . $addedContent; 22 $newContent = $this->page->html . $addedContent;
23 - $this->pageRepo->saveUpdateDraft($this->page, ['html' => $newContent]); 23 + $this->entityRepo->updatePageDraft($this->page, ['html' => $newContent]);
24 $this->asAdmin()->visit($this->page->getUrl() . '/edit') 24 $this->asAdmin()->visit($this->page->getUrl() . '/edit')
25 ->seeInField('html', $newContent); 25 ->seeInField('html', $newContent);
26 } 26 }
...@@ -33,7 +33,7 @@ class PageDraftTest extends TestCase ...@@ -33,7 +33,7 @@ class PageDraftTest extends TestCase
33 33
34 $newContent = $this->page->html . $addedContent; 34 $newContent = $this->page->html . $addedContent;
35 $newUser = $this->getEditor(); 35 $newUser = $this->getEditor();
36 - $this->pageRepo->saveUpdateDraft($this->page, ['html' => $newContent]); 36 + $this->entityRepo->updatePageDraft($this->page, ['html' => $newContent]);
37 $this->actingAs($newUser)->visit($this->page->getUrl() . '/edit') 37 $this->actingAs($newUser)->visit($this->page->getUrl() . '/edit')
38 ->dontSeeInField('html', $newContent); 38 ->dontSeeInField('html', $newContent);
39 } 39 }
...@@ -41,7 +41,7 @@ class PageDraftTest extends TestCase ...@@ -41,7 +41,7 @@ class PageDraftTest extends TestCase
41 public function test_alert_message_shows_if_editing_draft() 41 public function test_alert_message_shows_if_editing_draft()
42 { 42 {
43 $this->asAdmin(); 43 $this->asAdmin();
44 - $this->pageRepo->saveUpdateDraft($this->page, ['html' => 'test content']); 44 + $this->entityRepo->updatePageDraft($this->page, ['html' => 'test content']);
45 $this->asAdmin()->visit($this->page->getUrl() . '/edit') 45 $this->asAdmin()->visit($this->page->getUrl() . '/edit')
46 ->see('You are currently editing a draft'); 46 ->see('You are currently editing a draft');
47 } 47 }
...@@ -55,7 +55,7 @@ class PageDraftTest extends TestCase ...@@ -55,7 +55,7 @@ class PageDraftTest extends TestCase
55 55
56 $newContent = $this->page->html . $addedContent; 56 $newContent = $this->page->html . $addedContent;
57 $newUser = $this->getEditor(); 57 $newUser = $this->getEditor();
58 - $this->pageRepo->saveUpdateDraft($this->page, ['html' => $newContent]); 58 + $this->entityRepo->updatePageDraft($this->page, ['html' => $newContent]);
59 59
60 $this->actingAs($newUser) 60 $this->actingAs($newUser)
61 ->visit($this->page->getUrl() . '/edit') 61 ->visit($this->page->getUrl() . '/edit')
......
...@@ -13,8 +13,8 @@ class SortTest extends TestCase ...@@ -13,8 +13,8 @@ class SortTest extends TestCase
13 public function test_drafts_do_not_show_up() 13 public function test_drafts_do_not_show_up()
14 { 14 {
15 $this->asAdmin(); 15 $this->asAdmin();
16 - $pageRepo = app('\BookStack\Repos\PageRepo'); 16 + $entityRepo = app('\BookStack\Repos\EntityRepo');
17 - $draft = $pageRepo->getDraftPage($this->book); 17 + $draft = $entityRepo->getDraftPage($this->book);
18 18
19 $this->visit($this->book->getUrl()) 19 $this->visit($this->book->getUrl())
20 ->see($draft->name) 20 ->see($draft->name)
......
...@@ -90,7 +90,7 @@ class ImageTest extends TestCase ...@@ -90,7 +90,7 @@ class ImageTest extends TestCase
90 'type' => 'gallery' 90 'type' => 'gallery'
91 ]); 91 ]);
92 92
93 - $this->assertFalse(file_exists(public_path($relPath)), 'Uploaded image has been deleted'); 93 + $this->assertFalse(file_exists(public_path($relPath)), 'Uploaded image has not been deleted as expected');
94 } 94 }
95 95
96 } 96 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -65,9 +65,9 @@ class RestrictionsTest extends TestCase ...@@ -65,9 +65,9 @@ class RestrictionsTest extends TestCase
65 $this->forceVisit($bookUrl) 65 $this->forceVisit($bookUrl)
66 ->see('Book not found'); 66 ->see('Book not found');
67 $this->forceVisit($bookPage->getUrl()) 67 $this->forceVisit($bookPage->getUrl())
68 - ->see('Book not found'); 68 + ->see('Page not found');
69 $this->forceVisit($bookChapter->getUrl()) 69 $this->forceVisit($bookChapter->getUrl())
70 - ->see('Book not found'); 70 + ->see('Chapter not found');
71 71
72 $this->setEntityRestrictions($book, ['view']); 72 $this->setEntityRestrictions($book, ['view']);
73 73
......