diff options
Diffstat (limited to 'src/Wallabag/ApiBundle/Controller/EntryRestController.php')
-rw-r--r-- | src/Wallabag/ApiBundle/Controller/EntryRestController.php | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php new file mode 100644 index 00000000..b3622c62 --- /dev/null +++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php | |||
@@ -0,0 +1,374 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\ApiBundle\Controller; | ||
4 | |||
5 | use Hateoas\Configuration\Route; | ||
6 | use Hateoas\Representation\Factory\PagerfantaFactory; | ||
7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | ||
8 | use Symfony\Component\HttpFoundation\Request; | ||
9 | use Symfony\Component\HttpFoundation\JsonResponse; | ||
10 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | ||
11 | use Wallabag\CoreBundle\Entity\Entry; | ||
12 | use Wallabag\CoreBundle\Entity\Tag; | ||
13 | use Wallabag\CoreBundle\Event\EntrySavedEvent; | ||
14 | use Wallabag\CoreBundle\Event\EntryDeletedEvent; | ||
15 | |||
16 | class EntryRestController extends WallabagRestController | ||
17 | { | ||
18 | /** | ||
19 | * Check if an entry exist by url. | ||
20 | * | ||
21 | * @ApiDoc( | ||
22 | * parameters={ | ||
23 | * {"name"="url", "dataType"="string", "required"=true, "format"="An url", "description"="Url to check if it exists"}, | ||
24 | * {"name"="urls", "dataType"="string", "required"=false, "format"="An array of urls (?urls[]=http...&urls[]=http...)", "description"="Urls (as an array) to check if it exists"} | ||
25 | * } | ||
26 | * ) | ||
27 | * | ||
28 | * @return JsonResponse | ||
29 | */ | ||
30 | public function getEntriesExistsAction(Request $request) | ||
31 | { | ||
32 | $this->validateAuthentication(); | ||
33 | |||
34 | $urls = $request->query->get('urls', []); | ||
35 | |||
36 | // handle multiple urls first | ||
37 | if (!empty($urls)) { | ||
38 | $results = []; | ||
39 | foreach ($urls as $url) { | ||
40 | $res = $this->getDoctrine() | ||
41 | ->getRepository('WallabagCoreBundle:Entry') | ||
42 | ->findByUrlAndUserId($url, $this->getUser()->getId()); | ||
43 | |||
44 | $results[$url] = false === $res ? false : true; | ||
45 | } | ||
46 | |||
47 | $json = $this->get('serializer')->serialize($results, 'json'); | ||
48 | |||
49 | return (new JsonResponse())->setJson($json); | ||
50 | } | ||
51 | |||
52 | // let's see if it is a simple url? | ||
53 | $url = $request->query->get('url', ''); | ||
54 | |||
55 | if (empty($url)) { | ||
56 | throw $this->createAccessDeniedException('URL is empty?, logged user id: '.$this->getUser()->getId()); | ||
57 | } | ||
58 | |||
59 | $res = $this->getDoctrine() | ||
60 | ->getRepository('WallabagCoreBundle:Entry') | ||
61 | ->findByUrlAndUserId($url, $this->getUser()->getId()); | ||
62 | |||
63 | $exists = false === $res ? false : true; | ||
64 | |||
65 | $json = $this->get('serializer')->serialize(['exists' => $exists], 'json'); | ||
66 | |||
67 | return (new JsonResponse())->setJson($json); | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * Retrieve all entries. It could be filtered by many options. | ||
72 | * | ||
73 | * @ApiDoc( | ||
74 | * parameters={ | ||
75 | * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by archived status."}, | ||
76 | * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by starred status."}, | ||
77 | * {"name"="sort", "dataType"="string", "required"=false, "format"="'created' or 'updated', default 'created'", "description"="sort entries by date."}, | ||
78 | * {"name"="order", "dataType"="string", "required"=false, "format"="'asc' or 'desc', default 'desc'", "description"="order of sort."}, | ||
79 | * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."}, | ||
80 | * {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."}, | ||
81 | * {"name"="tags", "dataType"="string", "required"=false, "format"="api,rest", "description"="a list of tags url encoded. Will returns entries that matches ALL tags."}, | ||
82 | * {"name"="since", "dataType"="integer", "required"=false, "format"="default '0'", "description"="The timestamp since when you want entries updated."}, | ||
83 | * } | ||
84 | * ) | ||
85 | * | ||
86 | * @return JsonResponse | ||
87 | */ | ||
88 | public function getEntriesAction(Request $request) | ||
89 | { | ||
90 | $this->validateAuthentication(); | ||
91 | |||
92 | $isArchived = (null === $request->query->get('archive')) ? null : (bool) $request->query->get('archive'); | ||
93 | $isStarred = (null === $request->query->get('starred')) ? null : (bool) $request->query->get('starred'); | ||
94 | $sort = $request->query->get('sort', 'created'); | ||
95 | $order = $request->query->get('order', 'desc'); | ||
96 | $page = (int) $request->query->get('page', 1); | ||
97 | $perPage = (int) $request->query->get('perPage', 30); | ||
98 | $tags = $request->query->get('tags', ''); | ||
99 | $since = $request->query->get('since', 0); | ||
100 | |||
101 | $pager = $this->getDoctrine() | ||
102 | ->getRepository('WallabagCoreBundle:Entry') | ||
103 | ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order, $since, $tags); | ||
104 | |||
105 | $pager->setCurrentPage($page); | ||
106 | $pager->setMaxPerPage($perPage); | ||
107 | |||
108 | $pagerfantaFactory = new PagerfantaFactory('page', 'perPage'); | ||
109 | $paginatedCollection = $pagerfantaFactory->createRepresentation( | ||
110 | $pager, | ||
111 | new Route( | ||
112 | 'api_get_entries', | ||
113 | [ | ||
114 | 'archive' => $isArchived, | ||
115 | 'starred' => $isStarred, | ||
116 | 'sort' => $sort, | ||
117 | 'order' => $order, | ||
118 | 'page' => $page, | ||
119 | 'perPage' => $perPage, | ||
120 | 'tags' => $tags, | ||
121 | 'since' => $since, | ||
122 | ], | ||
123 | UrlGeneratorInterface::ABSOLUTE_URL | ||
124 | ) | ||
125 | ); | ||
126 | |||
127 | $json = $this->get('serializer')->serialize($paginatedCollection, 'json'); | ||
128 | |||
129 | return (new JsonResponse())->setJson($json); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Retrieve a single entry. | ||
134 | * | ||
135 | * @ApiDoc( | ||
136 | * requirements={ | ||
137 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | ||
138 | * } | ||
139 | * ) | ||
140 | * | ||
141 | * @return JsonResponse | ||
142 | */ | ||
143 | public function getEntryAction(Entry $entry) | ||
144 | { | ||
145 | $this->validateAuthentication(); | ||
146 | $this->validateUserAccess($entry->getUser()->getId()); | ||
147 | |||
148 | $json = $this->get('serializer')->serialize($entry, 'json'); | ||
149 | |||
150 | return (new JsonResponse())->setJson($json); | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Create an entry. | ||
155 | * | ||
156 | * @ApiDoc( | ||
157 | * parameters={ | ||
158 | * {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."}, | ||
159 | * {"name"="title", "dataType"="string", "required"=false, "description"="Optional, we'll get the title from the page."}, | ||
160 | * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."}, | ||
161 | * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already starred"}, | ||
162 | * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already archived"}, | ||
163 | * } | ||
164 | * ) | ||
165 | * | ||
166 | * @return JsonResponse | ||
167 | */ | ||
168 | public function postEntriesAction(Request $request) | ||
169 | { | ||
170 | $this->validateAuthentication(); | ||
171 | |||
172 | $url = $request->request->get('url'); | ||
173 | $title = $request->request->get('title'); | ||
174 | $isArchived = $request->request->get('archive'); | ||
175 | $isStarred = $request->request->get('starred'); | ||
176 | |||
177 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId()); | ||
178 | |||
179 | if (false === $entry) { | ||
180 | $entry = $this->get('wallabag_core.content_proxy')->updateEntry( | ||
181 | new Entry($this->getUser()), | ||
182 | $url | ||
183 | ); | ||
184 | } | ||
185 | |||
186 | if (!is_null($title)) { | ||
187 | $entry->setTitle($title); | ||
188 | } | ||
189 | |||
190 | $tags = $request->request->get('tags', ''); | ||
191 | if (!empty($tags)) { | ||
192 | $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags); | ||
193 | } | ||
194 | |||
195 | if (!is_null($isStarred)) { | ||
196 | $entry->setStarred((bool) $isStarred); | ||
197 | } | ||
198 | |||
199 | if (!is_null($isArchived)) { | ||
200 | $entry->setArchived((bool) $isArchived); | ||
201 | } | ||
202 | |||
203 | $em = $this->getDoctrine()->getManager(); | ||
204 | $em->persist($entry); | ||
205 | $em->flush(); | ||
206 | |||
207 | // entry saved, dispatch event about it! | ||
208 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
209 | |||
210 | $json = $this->get('serializer')->serialize($entry, 'json'); | ||
211 | |||
212 | return (new JsonResponse())->setJson($json); | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * Change several properties of an entry. | ||
217 | * | ||
218 | * @ApiDoc( | ||
219 | * requirements={ | ||
220 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | ||
221 | * }, | ||
222 | * parameters={ | ||
223 | * {"name"="title", "dataType"="string", "required"=false}, | ||
224 | * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."}, | ||
225 | * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="archived the entry."}, | ||
226 | * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="starred the entry."}, | ||
227 | * } | ||
228 | * ) | ||
229 | * | ||
230 | * @return JsonResponse | ||
231 | */ | ||
232 | public function patchEntriesAction(Entry $entry, Request $request) | ||
233 | { | ||
234 | $this->validateAuthentication(); | ||
235 | $this->validateUserAccess($entry->getUser()->getId()); | ||
236 | |||
237 | $title = $request->request->get('title'); | ||
238 | $isArchived = $request->request->get('archive'); | ||
239 | $isStarred = $request->request->get('starred'); | ||
240 | |||
241 | if (!is_null($title)) { | ||
242 | $entry->setTitle($title); | ||
243 | } | ||
244 | |||
245 | if (!is_null($isArchived)) { | ||
246 | $entry->setArchived((bool) $isArchived); | ||
247 | } | ||
248 | |||
249 | if (!is_null($isStarred)) { | ||
250 | $entry->setStarred((bool) $isStarred); | ||
251 | } | ||
252 | |||
253 | $tags = $request->request->get('tags', ''); | ||
254 | if (!empty($tags)) { | ||
255 | $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags); | ||
256 | } | ||
257 | |||
258 | $em = $this->getDoctrine()->getManager(); | ||
259 | $em->flush(); | ||
260 | |||
261 | $json = $this->get('serializer')->serialize($entry, 'json'); | ||
262 | |||
263 | return (new JsonResponse())->setJson($json); | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * Delete **permanently** an entry. | ||
268 | * | ||
269 | * @ApiDoc( | ||
270 | * requirements={ | ||
271 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | ||
272 | * } | ||
273 | * ) | ||
274 | * | ||
275 | * @return JsonResponse | ||
276 | */ | ||
277 | public function deleteEntriesAction(Entry $entry) | ||
278 | { | ||
279 | $this->validateAuthentication(); | ||
280 | $this->validateUserAccess($entry->getUser()->getId()); | ||
281 | |||
282 | $em = $this->getDoctrine()->getManager(); | ||
283 | $em->remove($entry); | ||
284 | $em->flush(); | ||
285 | |||
286 | // entry deleted, dispatch event about it! | ||
287 | $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); | ||
288 | |||
289 | $json = $this->get('serializer')->serialize($entry, 'json'); | ||
290 | |||
291 | return (new JsonResponse())->setJson($json); | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * Retrieve all tags for an entry. | ||
296 | * | ||
297 | * @ApiDoc( | ||
298 | * requirements={ | ||
299 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | ||
300 | * } | ||
301 | * ) | ||
302 | * | ||
303 | * @return JsonResponse | ||
304 | */ | ||
305 | public function getEntriesTagsAction(Entry $entry) | ||
306 | { | ||
307 | $this->validateAuthentication(); | ||
308 | $this->validateUserAccess($entry->getUser()->getId()); | ||
309 | |||
310 | $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); | ||
311 | |||
312 | return (new JsonResponse())->setJson($json); | ||
313 | } | ||
314 | |||
315 | /** | ||
316 | * Add one or more tags to an entry. | ||
317 | * | ||
318 | * @ApiDoc( | ||
319 | * requirements={ | ||
320 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | ||
321 | * }, | ||
322 | * parameters={ | ||
323 | * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."}, | ||
324 | * } | ||
325 | * ) | ||
326 | * | ||
327 | * @return JsonResponse | ||
328 | */ | ||
329 | public function postEntriesTagsAction(Request $request, Entry $entry) | ||
330 | { | ||
331 | $this->validateAuthentication(); | ||
332 | $this->validateUserAccess($entry->getUser()->getId()); | ||
333 | |||
334 | $tags = $request->request->get('tags', ''); | ||
335 | if (!empty($tags)) { | ||
336 | $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags); | ||
337 | } | ||
338 | |||
339 | $em = $this->getDoctrine()->getManager(); | ||
340 | $em->persist($entry); | ||
341 | $em->flush(); | ||
342 | |||
343 | $json = $this->get('serializer')->serialize($entry, 'json'); | ||
344 | |||
345 | return (new JsonResponse())->setJson($json); | ||
346 | } | ||
347 | |||
348 | /** | ||
349 | * Permanently remove one tag for an entry. | ||
350 | * | ||
351 | * @ApiDoc( | ||
352 | * requirements={ | ||
353 | * {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag ID"}, | ||
354 | * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} | ||
355 | * } | ||
356 | * ) | ||
357 | * | ||
358 | * @return JsonResponse | ||
359 | */ | ||
360 | public function deleteEntriesTagsAction(Entry $entry, Tag $tag) | ||
361 | { | ||
362 | $this->validateAuthentication(); | ||
363 | $this->validateUserAccess($entry->getUser()->getId()); | ||
364 | |||
365 | $entry->removeTag($tag); | ||
366 | $em = $this->getDoctrine()->getManager(); | ||
367 | $em->persist($entry); | ||
368 | $em->flush(); | ||
369 | |||
370 | $json = $this->get('serializer')->serialize($entry, 'json'); | ||
371 | |||
372 | return (new JsonResponse())->setJson($json); | ||
373 | } | ||
374 | } | ||