| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace BookStack\Entities\Repos; | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-08 06:37:27 +08:00
										 |  |  | use BookStack\Actions\ActivityType; | 
					
						
							| 
									
										
										
										
											2020-11-22 08:17:45 +08:00
										 |  |  | use BookStack\Entities\Models\Book; | 
					
						
							|  |  |  | use BookStack\Entities\Models\Bookshelf; | 
					
						
							| 
									
										
										
										
											2020-11-22 07:20:54 +08:00
										 |  |  | use BookStack\Entities\Tools\TrashCan; | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | use BookStack\Exceptions\ImageUploadException; | 
					
						
							|  |  |  | use BookStack\Exceptions\NotFoundException; | 
					
						
							| 
									
										
										
										
											2020-11-08 06:37:27 +08:00
										 |  |  | use BookStack\Facades\Activity; | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  | use Exception; | 
					
						
							|  |  |  | use Illuminate\Contracts\Pagination\LengthAwarePaginator; | 
					
						
							|  |  |  | use Illuminate\Http\UploadedFile; | 
					
						
							|  |  |  | use Illuminate\Support\Collection; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BookshelfRepo | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     protected $baseRepo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * BookshelfRepo constructor. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function __construct(BaseRepo $baseRepo) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->baseRepo = $baseRepo; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get all bookshelves in a paginated format. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getAllPaginated(int $count = 20, string $sort = 'name', string $order = 'asc'): LengthAwarePaginator | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-05-13 05:21:45 +08:00
										 |  |  |         return Bookshelf::visible() | 
					
						
							| 
									
										
										
										
											2021-01-11 07:12:51 +08:00
										 |  |  |             ->with(['visibleBooks', 'cover']) | 
					
						
							| 
									
										
										
										
											2020-05-13 05:21:45 +08:00
										 |  |  |             ->orderBy($sort, $order) | 
					
						
							|  |  |  |             ->paginate($count); | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the bookshelves that were most recently viewed by this user. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getRecentlyViewed(int $count = 20): Collection | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return Bookshelf::visible()->withLastView() | 
					
						
							|  |  |  |             ->having('last_viewed_at', '>', 0) | 
					
						
							|  |  |  |             ->orderBy('last_viewed_at', 'desc') | 
					
						
							|  |  |  |             ->take($count)->get(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the most popular bookshelves in the system. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getPopular(int $count = 20): Collection | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return Bookshelf::visible()->withViewCount() | 
					
						
							|  |  |  |             ->having('view_count', '>', 0) | 
					
						
							|  |  |  |             ->orderBy('view_count', 'desc') | 
					
						
							|  |  |  |             ->take($count)->get(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the most recently created bookshelves from the system. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getRecentlyCreated(int $count = 20): Collection | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return Bookshelf::visible()->orderBy('created_at', 'desc') | 
					
						
							|  |  |  |             ->take($count)->get(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get a shelf by its slug. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getBySlug(string $slug): Bookshelf | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $shelf = Bookshelf::visible()->where('slug', '=', $slug)->first(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($shelf === null) { | 
					
						
							|  |  |  |             throw new NotFoundException(trans('errors.bookshelf_not_found')); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $shelf; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create a new shelf in the system. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function create(array $input, array $bookIds): Bookshelf | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $shelf = new Bookshelf(); | 
					
						
							|  |  |  |         $this->baseRepo->create($shelf, $input); | 
					
						
							|  |  |  |         $this->updateBooks($shelf, $bookIds); | 
					
						
							| 
									
										
										
										
											2020-11-08 07:15:13 +08:00
										 |  |  |         Activity::addForEntity($shelf, ActivityType::BOOKSHELF_CREATE); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         return $shelf; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2020-11-08 06:37:27 +08:00
										 |  |  |      * Update an existing shelf in the system using the given input. | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-04-10 22:19:18 +08:00
										 |  |  |     public function update(Bookshelf $shelf, array $input, ?array $bookIds): Bookshelf | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $this->baseRepo->update($shelf, $input); | 
					
						
							| 
									
										
										
										
											2020-04-10 22:19:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!is_null($bookIds)) { | 
					
						
							|  |  |  |             $this->updateBooks($shelf, $bookIds); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-08 07:15:13 +08:00
										 |  |  |         Activity::addForEntity($shelf, ActivityType::BOOKSHELF_UPDATE); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         return $shelf; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Update which books are assigned to this shelf by | 
					
						
							|  |  |  |      * syncing the given book ids. | 
					
						
							|  |  |  |      * Function ensures the books are visible to the current user and existing. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function updateBooks(Bookshelf $shelf, array $bookIds) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $numericIDs = collect($bookIds)->map(function ($id) { | 
					
						
							|  |  |  |             return intval($id); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $syncData = Book::visible() | 
					
						
							|  |  |  |             ->whereIn('id', $bookIds) | 
					
						
							|  |  |  |             ->get(['id'])->pluck('id')->mapWithKeys(function ($bookId) use ($numericIDs) { | 
					
						
							|  |  |  |                 return [$bookId => ['order' => $numericIDs->search($bookId)]]; | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $shelf->books()->sync($syncData); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Update the given shelf cover image, or clear it. | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |      * @throws ImageUploadException | 
					
						
							|  |  |  |      * @throws Exception | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-02-16 02:38:36 +08:00
										 |  |  |     public function updateCoverImage(Bookshelf $shelf, ?UploadedFile $coverImage, bool $removeImage = false) | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $this->baseRepo->updateCoverImage($shelf, $coverImage, $removeImage); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Copy down the permissions of the given shelf to all child books. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-12-12 05:21:19 +08:00
										 |  |  |     public function copyDownPermissions(Bookshelf $shelf, $checkUserPermissions = true): int | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $shelfPermissions = $shelf->permissions()->get(['role_id', 'action'])->toArray(); | 
					
						
							| 
									
										
										
										
											2019-12-12 05:21:19 +08:00
										 |  |  |         $shelfBooks = $shelf->books()->get(['id', 'restricted']); | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |         $updatedBookCount = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** @var Book $book */ | 
					
						
							|  |  |  |         foreach ($shelfBooks as $book) { | 
					
						
							| 
									
										
										
										
											2019-12-12 05:21:19 +08:00
										 |  |  |             if ($checkUserPermissions && !userCan('restrictions-manage', $book)) { | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $book->permissions()->delete(); | 
					
						
							|  |  |  |             $book->restricted = $shelf->restricted; | 
					
						
							|  |  |  |             $book->permissions()->createMany($shelfPermissions); | 
					
						
							|  |  |  |             $book->save(); | 
					
						
							|  |  |  |             $book->rebuildPermissions(); | 
					
						
							|  |  |  |             $updatedBookCount++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $updatedBookCount; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Remove a bookshelf from the system. | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |      * @throws Exception | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function destroy(Bookshelf $shelf) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $trashCan = new TrashCan(); | 
					
						
							| 
									
										
										
										
											2020-09-28 06:24:33 +08:00
										 |  |  |         $trashCan->softDestroyShelf($shelf); | 
					
						
							| 
									
										
										
										
											2020-11-08 07:15:13 +08:00
										 |  |  |         Activity::addForEntity($shelf, ActivityType::BOOKSHELF_DELETE); | 
					
						
							| 
									
										
										
										
											2020-11-07 21:58:23 +08:00
										 |  |  |         $trashCan->autoClearOld(); | 
					
						
							| 
									
										
										
										
											2019-10-05 19:55:01 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | } |