]>
Commit | Line | Data |
---|---|---|
5d8de758 A |
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); | |
53054b2b | 57 | ++$count; |
5d8de758 A |
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 | ||
93175b6e A |
69 | if ($request->getParam('source') === 'batch') { |
70 | return $response->withStatus(204); | |
71 | } | |
72 | ||
330ac859 A |
73 | // Don't redirect to permalink after deletion. |
74 | return $this->redirectFromReferer($request, $response, ['shaare/']); | |
5d8de758 A |
75 | } |
76 | ||
77 | /** | |
78 | * GET /admin/shaare/visibility | |
79 | * | |
80 | * Change visibility (public/private) of one or multiple bookmarks (depending on `id` query parameter). | |
81 | */ | |
82 | public function changeVisibility(Request $request, Response $response): Response | |
83 | { | |
84 | $this->checkToken($request); | |
85 | ||
86 | $ids = trim(escape($request->getParam('id') ?? '')); | |
87 | if (empty($ids) || strpos($ids, ' ') !== false) { | |
88 | // multiple, space-separated ids provided | |
89 | $ids = array_values(array_filter(preg_split('/\s+/', $ids), 'ctype_digit')); | |
90 | } else { | |
91 | // only a single id provided | |
92 | $ids = [$ids]; | |
93 | } | |
94 | ||
95 | // assert at least one id is given | |
96 | if (0 === count($ids)) { | |
97 | $this->saveErrorMessage(t('Invalid bookmark ID provided.')); | |
98 | ||
99 | return $this->redirectFromReferer($request, $response, [], ['change_visibility']); | |
100 | } | |
101 | ||
102 | // assert that the visibility is valid | |
103 | $visibility = $request->getParam('newVisibility'); | |
104 | if (null === $visibility || false === in_array($visibility, ['public', 'private'], true)) { | |
105 | $this->saveErrorMessage(t('Invalid visibility provided.')); | |
106 | ||
107 | return $this->redirectFromReferer($request, $response, [], ['change_visibility']); | |
108 | } else { | |
109 | $isPrivate = $visibility === 'private'; | |
110 | } | |
111 | ||
112 | $formatter = $this->container->formatterFactory->getFormatter('raw'); | |
113 | $count = 0; | |
114 | ||
115 | foreach ($ids as $id) { | |
116 | try { | |
117 | $bookmark = $this->container->bookmarkService->get((int) $id); | |
118 | } catch (BookmarkNotFoundException $e) { | |
119 | $this->saveErrorMessage(sprintf( | |
120 | t('Bookmark with identifier %s could not be found.'), | |
121 | $id | |
122 | )); | |
123 | ||
124 | continue; | |
125 | } | |
126 | ||
127 | $bookmark->setPrivate($isPrivate); | |
128 | ||
129 | // To preserve backward compatibility with 3rd parties, plugins still use arrays | |
130 | $data = $formatter->format($bookmark); | |
131 | $this->executePageHooks('save_link', $data); | |
b3bd8c3e | 132 | $bookmark->fromArray($data, $this->container->conf->get('general.tags_separator', ' ')); |
5d8de758 A |
133 | |
134 | $this->container->bookmarkService->set($bookmark, false); | |
135 | ++$count; | |
136 | } | |
137 | ||
138 | if ($count > 0) { | |
139 | $this->container->bookmarkService->save(); | |
140 | } | |
141 | ||
142 | return $this->redirectFromReferer($request, $response, ['/visibility'], ['change_visibility']); | |
143 | } | |
144 | ||
145 | /** | |
146 | * GET /admin/shaare/{id}/pin - Pin or unpin a bookmark. | |
147 | */ | |
148 | public function pinBookmark(Request $request, Response $response, array $args): Response | |
149 | { | |
150 | $this->checkToken($request); | |
151 | ||
152 | $id = $args['id'] ?? ''; | |
153 | try { | |
154 | if (false === ctype_digit($id)) { | |
155 | throw new BookmarkNotFoundException(); | |
156 | } | |
157 | $bookmark = $this->container->bookmarkService->get((int) $id); // Read database | |
158 | } catch (BookmarkNotFoundException $e) { | |
159 | $this->saveErrorMessage(sprintf( | |
160 | t('Bookmark with identifier %s could not be found.'), | |
161 | $id | |
162 | )); | |
163 | ||
164 | return $this->redirectFromReferer($request, $response, ['/pin'], ['pin']); | |
165 | } | |
166 | ||
167 | $formatter = $this->container->formatterFactory->getFormatter('raw'); | |
168 | ||
169 | $bookmark->setSticky(!$bookmark->isSticky()); | |
170 | ||
171 | // To preserve backward compatibility with 3rd parties, plugins still use arrays | |
172 | $data = $formatter->format($bookmark); | |
173 | $this->executePageHooks('save_link', $data); | |
b3bd8c3e | 174 | $bookmark->fromArray($data, $this->container->conf->get('general.tags_separator', ' ')); |
5d8de758 A |
175 | |
176 | $this->container->bookmarkService->set($bookmark); | |
177 | ||
178 | return $this->redirectFromReferer($request, $response, ['/pin'], ['pin']); | |
179 | } | |
180 | ||
181 | /** | |
182 | * GET /admin/shaare/private/{hash} - Attach a private key to given bookmark, then redirect to the sharing URL. | |
183 | */ | |
184 | public function sharePrivate(Request $request, Response $response, array $args): Response | |
185 | { | |
186 | $this->checkToken($request); | |
187 | ||
188 | $hash = $args['hash'] ?? ''; | |
189 | $bookmark = $this->container->bookmarkService->findByHash($hash); | |
190 | ||
191 | if ($bookmark->isPrivate() !== true) { | |
192 | return $this->redirect($response, '/shaare/' . $hash); | |
193 | } | |
194 | ||
195 | if (empty($bookmark->getAdditionalContentEntry('private_key'))) { | |
196 | $privateKey = bin2hex(random_bytes(16)); | |
197 | $bookmark->addAdditionalContentEntry('private_key', $privateKey); | |
198 | $this->container->bookmarkService->set($bookmark); | |
199 | } | |
200 | ||
201 | return $this->redirect( | |
202 | $response, | |
203 | '/shaare/' . $hash . '?key=' . $bookmark->getAdditionalContentEntry('private_key') | |
204 | ); | |
205 | } | |
206 | } |