]>
Commit | Line | Data |
---|---|---|
1 | <?php | |
2 | ||
3 | declare(strict_types=1); | |
4 | ||
5 | namespace Shaarli\Front\Controller\Admin; | |
6 | ||
7 | use Shaarli\Bookmark\Exception\BookmarkNotFoundException; | |
8 | use Slim\Http\Request; | |
9 | use Slim\Http\Response; | |
10 | ||
11 | /** | |
12 | * Class PostBookmarkController | |
13 | * | |
14 | * Slim controller used to handle Shaarli create or edit bookmarks. | |
15 | */ | |
16 | class ShaareManageController extends ShaarliAdminController | |
17 | { | |
18 | /** | |
19 | * GET /admin/shaare/delete - Delete one or multiple bookmarks (depending on `id` query parameter). | |
20 | */ | |
21 | public function deleteBookmark(Request $request, Response $response): Response | |
22 | { | |
23 | $this->checkToken($request); | |
24 | ||
25 | $ids = escape(trim($request->getParam('id') ?? '')); | |
26 | if (empty($ids) || strpos($ids, ' ') !== false) { | |
27 | // multiple, space-separated ids provided | |
28 | $ids = array_values(array_filter(preg_split('/\s+/', $ids), 'ctype_digit')); | |
29 | } else { | |
30 | $ids = [$ids]; | |
31 | } | |
32 | ||
33 | // assert at least one id is given | |
34 | if (0 === count($ids)) { | |
35 | $this->saveErrorMessage(t('Invalid bookmark ID provided.')); | |
36 | ||
37 | return $this->redirectFromReferer($request, $response, [], ['delete-shaare']); | |
38 | } | |
39 | ||
40 | $formatter = $this->container->formatterFactory->getFormatter('raw'); | |
41 | $count = 0; | |
42 | foreach ($ids as $id) { | |
43 | try { | |
44 | $bookmark = $this->container->bookmarkService->get((int) $id); | |
45 | } catch (BookmarkNotFoundException $e) { | |
46 | $this->saveErrorMessage(sprintf( | |
47 | t('Bookmark with identifier %s could not be found.'), | |
48 | $id | |
49 | )); | |
50 | ||
51 | continue; | |
52 | } | |
53 | ||
54 | $data = $formatter->format($bookmark); | |
55 | $this->executePageHooks('delete_link', $data); | |
56 | $this->container->bookmarkService->remove($bookmark, false); | |
57 | ++ $count; | |
58 | } | |
59 | ||
60 | if ($count > 0) { | |
61 | $this->container->bookmarkService->save(); | |
62 | } | |
63 | ||
64 | // If we are called from the bookmarklet, we must close the popup: | |
65 | if ($request->getParam('source') === 'bookmarklet') { | |
66 | return $response->write('<script>self.close();</script>'); | |
67 | } | |
68 | ||
69 | // Don't redirect to where we were previously because the datastore has changed. | |
70 | return $this->redirect($response, '/'); | |
71 | } | |
72 | ||
73 | /** | |
74 | * GET /admin/shaare/visibility | |
75 | * | |
76 | * Change visibility (public/private) of one or multiple bookmarks (depending on `id` query parameter). | |
77 | */ | |
78 | public function changeVisibility(Request $request, Response $response): Response | |
79 | { | |
80 | $this->checkToken($request); | |
81 | ||
82 | $ids = trim(escape($request->getParam('id') ?? '')); | |
83 | if (empty($ids) || strpos($ids, ' ') !== false) { | |
84 | // multiple, space-separated ids provided | |
85 | $ids = array_values(array_filter(preg_split('/\s+/', $ids), 'ctype_digit')); | |
86 | } else { | |
87 | // only a single id provided | |
88 | $ids = [$ids]; | |
89 | } | |
90 | ||
91 | // assert at least one id is given | |
92 | if (0 === count($ids)) { | |
93 | $this->saveErrorMessage(t('Invalid bookmark ID provided.')); | |
94 | ||
95 | return $this->redirectFromReferer($request, $response, [], ['change_visibility']); | |
96 | } | |
97 | ||
98 | // assert that the visibility is valid | |
99 | $visibility = $request->getParam('newVisibility'); | |
100 | if (null === $visibility || false === in_array($visibility, ['public', 'private'], true)) { | |
101 | $this->saveErrorMessage(t('Invalid visibility provided.')); | |
102 | ||
103 | return $this->redirectFromReferer($request, $response, [], ['change_visibility']); | |
104 | } else { | |
105 | $isPrivate = $visibility === 'private'; | |
106 | } | |
107 | ||
108 | $formatter = $this->container->formatterFactory->getFormatter('raw'); | |
109 | $count = 0; | |
110 | ||
111 | foreach ($ids as $id) { | |
112 | try { | |
113 | $bookmark = $this->container->bookmarkService->get((int) $id); | |
114 | } catch (BookmarkNotFoundException $e) { | |
115 | $this->saveErrorMessage(sprintf( | |
116 | t('Bookmark with identifier %s could not be found.'), | |
117 | $id | |
118 | )); | |
119 | ||
120 | continue; | |
121 | } | |
122 | ||
123 | $bookmark->setPrivate($isPrivate); | |
124 | ||
125 | // To preserve backward compatibility with 3rd parties, plugins still use arrays | |
126 | $data = $formatter->format($bookmark); | |
127 | $this->executePageHooks('save_link', $data); | |
128 | $bookmark->fromArray($data); | |
129 | ||
130 | $this->container->bookmarkService->set($bookmark, false); | |
131 | ++$count; | |
132 | } | |
133 | ||
134 | if ($count > 0) { | |
135 | $this->container->bookmarkService->save(); | |
136 | } | |
137 | ||
138 | return $this->redirectFromReferer($request, $response, ['/visibility'], ['change_visibility']); | |
139 | } | |
140 | ||
141 | /** | |
142 | * GET /admin/shaare/{id}/pin - Pin or unpin a bookmark. | |
143 | */ | |
144 | public function pinBookmark(Request $request, Response $response, array $args): Response | |
145 | { | |
146 | $this->checkToken($request); | |
147 | ||
148 | $id = $args['id'] ?? ''; | |
149 | try { | |
150 | if (false === ctype_digit($id)) { | |
151 | throw new BookmarkNotFoundException(); | |
152 | } | |
153 | $bookmark = $this->container->bookmarkService->get((int) $id); // Read database | |
154 | } catch (BookmarkNotFoundException $e) { | |
155 | $this->saveErrorMessage(sprintf( | |
156 | t('Bookmark with identifier %s could not be found.'), | |
157 | $id | |
158 | )); | |
159 | ||
160 | return $this->redirectFromReferer($request, $response, ['/pin'], ['pin']); | |
161 | } | |
162 | ||
163 | $formatter = $this->container->formatterFactory->getFormatter('raw'); | |
164 | ||
165 | $bookmark->setSticky(!$bookmark->isSticky()); | |
166 | ||
167 | // To preserve backward compatibility with 3rd parties, plugins still use arrays | |
168 | $data = $formatter->format($bookmark); | |
169 | $this->executePageHooks('save_link', $data); | |
170 | $bookmark->fromArray($data); | |
171 | ||
172 | $this->container->bookmarkService->set($bookmark); | |
173 | ||
174 | return $this->redirectFromReferer($request, $response, ['/pin'], ['pin']); | |
175 | } | |
176 | ||
177 | /** | |
178 | * GET /admin/shaare/private/{hash} - Attach a private key to given bookmark, then redirect to the sharing URL. | |
179 | */ | |
180 | public function sharePrivate(Request $request, Response $response, array $args): Response | |
181 | { | |
182 | $this->checkToken($request); | |
183 | ||
184 | $hash = $args['hash'] ?? ''; | |
185 | $bookmark = $this->container->bookmarkService->findByHash($hash); | |
186 | ||
187 | if ($bookmark->isPrivate() !== true) { | |
188 | return $this->redirect($response, '/shaare/' . $hash); | |
189 | } | |
190 | ||
191 | if (empty($bookmark->getAdditionalContentEntry('private_key'))) { | |
192 | $privateKey = bin2hex(random_bytes(16)); | |
193 | $bookmark->addAdditionalContentEntry('private_key', $privateKey); | |
194 | $this->container->bookmarkService->set($bookmark); | |
195 | } | |
196 | ||
197 | return $this->redirect( | |
198 | $response, | |
199 | '/shaare/' . $hash . '?key=' . $bookmark->getAdditionalContentEntry('private_key') | |
200 | ); | |
201 | } | |
202 | } |