]> BookStack Code Mirror - bookstack/blob - app/Entities/Repos/BookshelfRepo.php
Replaced embeds with images in exports
[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::add(ActivityType::BOOKSHELF_CREATE, $shelf);
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::add(ActivityType::BOOKSHELF_UPDATE, $shelf);
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             ->pluck('id')
128             ->mapWithKeys(function ($bookId) use ($numericIDs) {
129                 return [$bookId => ['order' => $numericIDs->search($bookId)]];
130             });
131
132         $shelf->books()->sync($syncData);
133     }
134
135     /**
136      * Update the given shelf cover image, or clear it.
137      *
138      * @throws ImageUploadException
139      * @throws Exception
140      */
141     public function updateCoverImage(Bookshelf $shelf, ?UploadedFile $coverImage, bool $removeImage = false)
142     {
143         $this->baseRepo->updateCoverImage($shelf, $coverImage, $removeImage);
144     }
145
146     /**
147      * Copy down the permissions of the given shelf to all child books.
148      */
149     public function copyDownPermissions(Bookshelf $shelf, $checkUserPermissions = true): int
150     {
151         $shelfPermissions = $shelf->permissions()->get(['role_id', 'action'])->toArray();
152         $shelfBooks = $shelf->books()->get(['id', 'restricted']);
153         $updatedBookCount = 0;
154
155         /** @var Book $book */
156         foreach ($shelfBooks as $book) {
157             if ($checkUserPermissions && !userCan('restrictions-manage', $book)) {
158                 continue;
159             }
160             $book->permissions()->delete();
161             $book->restricted = $shelf->restricted;
162             $book->permissions()->createMany($shelfPermissions);
163             $book->save();
164             $book->rebuildPermissions();
165             $updatedBookCount++;
166         }
167
168         return $updatedBookCount;
169     }
170
171     /**
172      * Remove a bookshelf from the system.
173      *
174      * @throws Exception
175      */
176     public function destroy(Bookshelf $shelf)
177     {
178         $trashCan = new TrashCan();
179         $trashCan->softDestroyShelf($shelf);
180         Activity::add(ActivityType::BOOKSHELF_DELETE, $shelf);
181         $trashCan->autoClearOld();
182     }
183 }