]> BookStack Code Mirror - bookstack/blob - app/Entities/Repos/BookshelfRepo.php
Apply fixes from StyleCI
[bookstack] / app / Entities / Repos / BookshelfRepo.php
1 <?php
2
3 namespace BookStack\Entities\Repos;
4
5 use BookStack\Actions\ActivityType;
6 use BookStack\Entities\Models\Book;
7 use BookStack\Entities\Models\Bookshelf;
8 use BookStack\Entities\Tools\TrashCan;
9 use BookStack\Exceptions\ImageUploadException;
10 use BookStack\Exceptions\NotFoundException;
11 use BookStack\Facades\Activity;
12 use Exception;
13 use Illuminate\Contracts\Pagination\LengthAwarePaginator;
14 use Illuminate\Http\UploadedFile;
15 use Illuminate\Support\Collection;
16
17 class BookshelfRepo
18 {
19     protected $baseRepo;
20
21     /**
22      * BookshelfRepo constructor.
23      */
24     public function __construct(BaseRepo $baseRepo)
25     {
26         $this->baseRepo = $baseRepo;
27     }
28
29     /**
30      * Get all bookshelves in a paginated format.
31      */
32     public function getAllPaginated(int $count = 20, string $sort = 'name', string $order = 'asc'): LengthAwarePaginator
33     {
34         return Bookshelf::visible()
35             ->with(['visibleBooks', 'cover'])
36             ->orderBy($sort, $order)
37             ->paginate($count);
38     }
39
40     /**
41      * Get the bookshelves that were most recently viewed by this user.
42      */
43     public function getRecentlyViewed(int $count = 20): Collection
44     {
45         return Bookshelf::visible()->withLastView()
46             ->having('last_viewed_at', '>', 0)
47             ->orderBy('last_viewed_at', 'desc')
48             ->take($count)->get();
49     }
50
51     /**
52      * Get the most popular bookshelves in the system.
53      */
54     public function getPopular(int $count = 20): Collection
55     {
56         return Bookshelf::visible()->withViewCount()
57             ->having('view_count', '>', 0)
58             ->orderBy('view_count', 'desc')
59             ->take($count)->get();
60     }
61
62     /**
63      * Get the most recently created bookshelves from the system.
64      */
65     public function getRecentlyCreated(int $count = 20): Collection
66     {
67         return Bookshelf::visible()->orderBy('created_at', 'desc')
68             ->take($count)->get();
69     }
70
71     /**
72      * Get a shelf by its slug.
73      */
74     public function getBySlug(string $slug): Bookshelf
75     {
76         $shelf = Bookshelf::visible()->where('slug', '=', $slug)->first();
77
78         if ($shelf === null) {
79             throw new NotFoundException(trans('errors.bookshelf_not_found'));
80         }
81
82         return $shelf;
83     }
84
85     /**
86      * Create a new shelf in the system.
87      */
88     public function create(array $input, array $bookIds): Bookshelf
89     {
90         $shelf = new Bookshelf();
91         $this->baseRepo->create($shelf, $input);
92         $this->updateBooks($shelf, $bookIds);
93         Activity::addForEntity($shelf, ActivityType::BOOKSHELF_CREATE);
94
95         return $shelf;
96     }
97
98     /**
99      * Update an existing shelf in the system using the given input.
100      */
101     public function update(Bookshelf $shelf, array $input, ?array $bookIds): Bookshelf
102     {
103         $this->baseRepo->update($shelf, $input);
104
105         if (!is_null($bookIds)) {
106             $this->updateBooks($shelf, $bookIds);
107         }
108
109         Activity::addForEntity($shelf, ActivityType::BOOKSHELF_UPDATE);
110
111         return $shelf;
112     }
113
114     /**
115      * Update which books are assigned to this shelf by
116      * syncing the given book ids.
117      * Function ensures the books are visible to the current user and existing.
118      */
119     protected function updateBooks(Bookshelf $shelf, array $bookIds)
120     {
121         $numericIDs = collect($bookIds)->map(function ($id) {
122             return intval($id);
123         });
124
125         $syncData = Book::visible()
126             ->whereIn('id', $bookIds)
127             ->get(['id'])->pluck('id')->mapWithKeys(function ($bookId) use ($numericIDs) {
128                 return [$bookId => ['order' => $numericIDs->search($bookId)]];
129             });
130
131         $shelf->books()->sync($syncData);
132     }
133
134     /**
135      * Update the given shelf cover image, or clear it.
136      *
137      * @throws ImageUploadException
138      * @throws Exception
139      */
140     public function updateCoverImage(Bookshelf $shelf, ?UploadedFile $coverImage, bool $removeImage = false)
141     {
142         $this->baseRepo->updateCoverImage($shelf, $coverImage, $removeImage);
143     }
144
145     /**
146      * Copy down the permissions of the given shelf to all child books.
147      */
148     public function copyDownPermissions(Bookshelf $shelf, $checkUserPermissions = true): int
149     {
150         $shelfPermissions = $shelf->permissions()->get(['role_id', 'action'])->toArray();
151         $shelfBooks = $shelf->books()->get(['id', 'restricted']);
152         $updatedBookCount = 0;
153
154         /** @var Book $book */
155         foreach ($shelfBooks as $book) {
156             if ($checkUserPermissions && !userCan('restrictions-manage', $book)) {
157                 continue;
158             }
159             $book->permissions()->delete();
160             $book->restricted = $shelf->restricted;
161             $book->permissions()->createMany($shelfPermissions);
162             $book->save();
163             $book->rebuildPermissions();
164             $updatedBookCount++;
165         }
166
167         return $updatedBookCount;
168     }
169
170     /**
171      * Remove a bookshelf from the system.
172      *
173      * @throws Exception
174      */
175     public function destroy(Bookshelf $shelf)
176     {
177         $trashCan = new TrashCan();
178         $trashCan->softDestroyShelf($shelf);
179         Activity::addForEntity($shelf, ActivityType::BOOKSHELF_DELETE);
180         $trashCan->autoClearOld();
181     }
182 }