diff options
Diffstat (limited to 'src/Wallabag/ApiBundle')
4 files changed, 432 insertions, 56 deletions
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php index 54c1747c..93c8157e 100644 --- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php +++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php | |||
@@ -5,6 +5,7 @@ namespace Wallabag\ApiBundle\Controller; | |||
5 | use Hateoas\Configuration\Route; | 5 | use Hateoas\Configuration\Route; |
6 | use Hateoas\Representation\Factory\PagerfantaFactory; | 6 | use Hateoas\Representation\Factory\PagerfantaFactory; |
7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | 7 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; |
8 | use Symfony\Component\HttpKernel\Exception\HttpException; | ||
8 | use Symfony\Component\HttpFoundation\Request; | 9 | use Symfony\Component\HttpFoundation\Request; |
9 | use Symfony\Component\HttpFoundation\JsonResponse; | 10 | use Symfony\Component\HttpFoundation\JsonResponse; |
10 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | 11 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
@@ -41,12 +42,10 @@ class EntryRestController extends WallabagRestController | |||
41 | ->getRepository('WallabagCoreBundle:Entry') | 42 | ->getRepository('WallabagCoreBundle:Entry') |
42 | ->findByUrlAndUserId($url, $this->getUser()->getId()); | 43 | ->findByUrlAndUserId($url, $this->getUser()->getId()); |
43 | 44 | ||
44 | $results[$url] = false === $res ? false : true; | 45 | $results[$url] = $res instanceof Entry ? $res->getId() : false; |
45 | } | 46 | } |
46 | 47 | ||
47 | $json = $this->get('serializer')->serialize($results, 'json'); | 48 | return $this->sendResponse($results); |
48 | |||
49 | return (new JsonResponse())->setJson($json); | ||
50 | } | 49 | } |
51 | 50 | ||
52 | // let's see if it is a simple url? | 51 | // let's see if it is a simple url? |
@@ -60,11 +59,9 @@ class EntryRestController extends WallabagRestController | |||
60 | ->getRepository('WallabagCoreBundle:Entry') | 59 | ->getRepository('WallabagCoreBundle:Entry') |
61 | ->findByUrlAndUserId($url, $this->getUser()->getId()); | 60 | ->findByUrlAndUserId($url, $this->getUser()->getId()); |
62 | 61 | ||
63 | $exists = false === $res ? false : true; | 62 | $exists = $res instanceof Entry ? $res->getId() : false; |
64 | |||
65 | $json = $this->get('serializer')->serialize(['exists' => $exists], 'json'); | ||
66 | 63 | ||
67 | return (new JsonResponse())->setJson($json); | 64 | return $this->sendResponse(['exists' => $exists]); |
68 | } | 65 | } |
69 | 66 | ||
70 | /** | 67 | /** |
@@ -125,9 +122,7 @@ class EntryRestController extends WallabagRestController | |||
125 | ) | 122 | ) |
126 | ); | 123 | ); |
127 | 124 | ||
128 | $json = $this->get('serializer')->serialize($paginatedCollection, 'json'); | 125 | return $this->sendResponse($paginatedCollection); |
129 | |||
130 | return (new JsonResponse())->setJson($json); | ||
131 | } | 126 | } |
132 | 127 | ||
133 | /** | 128 | /** |
@@ -146,9 +141,7 @@ class EntryRestController extends WallabagRestController | |||
146 | $this->validateAuthentication(); | 141 | $this->validateAuthentication(); |
147 | $this->validateUserAccess($entry->getUser()->getId()); | 142 | $this->validateUserAccess($entry->getUser()->getId()); |
148 | 143 | ||
149 | $json = $this->get('serializer')->serialize($entry, 'json'); | 144 | return $this->sendResponse($entry); |
150 | |||
151 | return (new JsonResponse())->setJson($json); | ||
152 | } | 145 | } |
153 | 146 | ||
154 | /** | 147 | /** |
@@ -174,8 +167,116 @@ class EntryRestController extends WallabagRestController | |||
174 | } | 167 | } |
175 | 168 | ||
176 | /** | 169 | /** |
170 | * Handles an entries list and delete URL. | ||
171 | * | ||
172 | * @ApiDoc( | ||
173 | * parameters={ | ||
174 | * {"name"="urls", "dataType"="string", "required"=true, "format"="A JSON array of urls [{'url': 'http://...'}, {'url': 'http://...'}]", "description"="Urls (as an array) to delete."} | ||
175 | * } | ||
176 | * ) | ||
177 | * | ||
178 | * @return JsonResponse | ||
179 | */ | ||
180 | public function deleteEntriesListAction(Request $request) | ||
181 | { | ||
182 | $this->validateAuthentication(); | ||
183 | |||
184 | $urls = json_decode($request->query->get('urls', [])); | ||
185 | |||
186 | if (empty($urls)) { | ||
187 | return $this->sendResponse([]); | ||
188 | } | ||
189 | |||
190 | $results = []; | ||
191 | |||
192 | // handle multiple urls | ||
193 | foreach ($urls as $key => $url) { | ||
194 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId( | ||
195 | $url, | ||
196 | $this->getUser()->getId() | ||
197 | ); | ||
198 | |||
199 | $results[$key]['url'] = $url; | ||
200 | |||
201 | if (false !== $entry) { | ||
202 | $em = $this->getDoctrine()->getManager(); | ||
203 | $em->remove($entry); | ||
204 | $em->flush(); | ||
205 | |||
206 | // entry deleted, dispatch event about it! | ||
207 | $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); | ||
208 | } | ||
209 | |||
210 | $results[$key]['entry'] = $entry instanceof Entry ? true : false; | ||
211 | } | ||
212 | |||
213 | return $this->sendResponse($results); | ||
214 | } | ||
215 | |||
216 | /** | ||
217 | * Handles an entries list and create URL. | ||
218 | * | ||
219 | * @ApiDoc( | ||
220 | * parameters={ | ||
221 | * {"name"="urls", "dataType"="string", "required"=true, "format"="A JSON array of urls [{'url': 'http://...'}, {'url': 'http://...'}]", "description"="Urls (as an array) to create."} | ||
222 | * } | ||
223 | * ) | ||
224 | * | ||
225 | * @return JsonResponse | ||
226 | * | ||
227 | * @throws HttpException When limit is reached | ||
228 | */ | ||
229 | public function postEntriesListAction(Request $request) | ||
230 | { | ||
231 | $this->validateAuthentication(); | ||
232 | |||
233 | $urls = json_decode($request->query->get('urls', [])); | ||
234 | |||
235 | $limit = $this->container->getParameter('wallabag_core.api_limit_mass_actions'); | ||
236 | |||
237 | if (count($urls) > $limit) { | ||
238 | throw new HttpException(400, 'API limit reached'); | ||
239 | } | ||
240 | |||
241 | $results = []; | ||
242 | if (empty($urls)) { | ||
243 | return $this->sendResponse($results); | ||
244 | } | ||
245 | |||
246 | // handle multiple urls | ||
247 | foreach ($urls as $key => $url) { | ||
248 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId( | ||
249 | $url, | ||
250 | $this->getUser()->getId() | ||
251 | ); | ||
252 | |||
253 | $results[$key]['url'] = $url; | ||
254 | |||
255 | if (false === $entry) { | ||
256 | $entry = new Entry($this->getUser()); | ||
257 | |||
258 | $this->get('wallabag_core.content_proxy')->updateEntry($entry, $url); | ||
259 | } | ||
260 | |||
261 | $em = $this->getDoctrine()->getManager(); | ||
262 | $em->persist($entry); | ||
263 | $em->flush(); | ||
264 | |||
265 | $results[$key]['entry'] = $entry instanceof Entry ? $entry->getId() : false; | ||
266 | |||
267 | // entry saved, dispatch event about it! | ||
268 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | ||
269 | } | ||
270 | |||
271 | return $this->sendResponse($results); | ||
272 | } | ||
273 | |||
274 | /** | ||
177 | * Create an entry. | 275 | * Create an entry. |
178 | * | 276 | * |
277 | * If you want to provide the HTML content (which means wallabag won't fetch it from the url), you must provide `content`, `title` & `url` fields **non-empty**. | ||
278 | * Otherwise, content will be fetched as normal from the url and values will be overwritten. | ||
279 | * | ||
179 | * @ApiDoc( | 280 | * @ApiDoc( |
180 | * parameters={ | 281 | * parameters={ |
181 | * {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."}, | 282 | * {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."}, |
@@ -183,6 +284,11 @@ class EntryRestController extends WallabagRestController | |||
183 | * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."}, | 284 | * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."}, |
184 | * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already starred"}, | 285 | * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already starred"}, |
185 | * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already archived"}, | 286 | * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already archived"}, |
287 | * {"name"="content", "dataType"="string", "required"=false, "description"="Content of the entry"}, | ||
288 | * {"name"="language", "dataType"="string", "required"=false, "description"="Language of the entry"}, | ||
289 | * {"name"="preview_picture", "dataType"="string", "required"=false, "description"="Preview picture of the entry"}, | ||
290 | * {"name"="published_at", "dataType"="datetime|integer", "format"="YYYY-MM-DDTHH:II:SS+TZ or a timestamp", "required"=false, "description"="Published date of the entry"}, | ||
291 | * {"name"="authors", "dataType"="string", "format"="Name Firstname,author2,author3", "required"=false, "description"="Authors of the entry"}, | ||
186 | * } | 292 | * } |
187 | * ) | 293 | * ) |
188 | * | 294 | * |
@@ -194,34 +300,48 @@ class EntryRestController extends WallabagRestController | |||
194 | 300 | ||
195 | $url = $request->request->get('url'); | 301 | $url = $request->request->get('url'); |
196 | $title = $request->request->get('title'); | 302 | $title = $request->request->get('title'); |
303 | $tags = $request->request->get('tags', []); | ||
197 | $isArchived = $request->request->get('archive'); | 304 | $isArchived = $request->request->get('archive'); |
198 | $isStarred = $request->request->get('starred'); | 305 | $isStarred = $request->request->get('starred'); |
306 | $content = $request->request->get('content'); | ||
307 | $language = $request->request->get('language'); | ||
308 | $picture = $request->request->get('preview_picture'); | ||
309 | $publishedAt = $request->request->get('published_at'); | ||
310 | $authors = $request->request->get('authors', ''); | ||
199 | 311 | ||
200 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId()); | 312 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($url, $this->getUser()->getId()); |
201 | 313 | ||
202 | if (false === $entry) { | 314 | if (false === $entry) { |
203 | $entry = new Entry($this->getUser()); | 315 | $entry = new Entry($this->getUser()); |
204 | try { | ||
205 | $entry = $this->get('wallabag_core.content_proxy')->updateEntry( | ||
206 | $entry, | ||
207 | $url | ||
208 | ); | ||
209 | } catch (\Exception $e) { | ||
210 | $this->get('logger')->error('Error while saving an entry', [ | ||
211 | 'exception' => $e, | ||
212 | 'entry' => $entry, | ||
213 | ]); | ||
214 | $entry->setUrl($url); | ||
215 | } | ||
216 | } | 316 | } |
217 | 317 | ||
218 | if (!is_null($title)) { | 318 | try { |
219 | $entry->setTitle($title); | 319 | $this->get('wallabag_core.content_proxy')->updateEntry( |
320 | $entry, | ||
321 | $url, | ||
322 | [ | ||
323 | 'title' => $title, | ||
324 | 'html' => $content, | ||
325 | 'url' => $url, | ||
326 | 'language' => $language, | ||
327 | 'date' => $publishedAt, | ||
328 | // faking the preview picture | ||
329 | 'open_graph' => [ | ||
330 | 'og_image' => $picture, | ||
331 | ], | ||
332 | 'authors' => explode(',', $authors), | ||
333 | ] | ||
334 | ); | ||
335 | } catch (\Exception $e) { | ||
336 | $this->get('logger')->error('Error while saving an entry', [ | ||
337 | 'exception' => $e, | ||
338 | 'entry' => $entry, | ||
339 | ]); | ||
340 | $entry->setUrl($url); | ||
220 | } | 341 | } |
221 | 342 | ||
222 | $tags = $request->request->get('tags', ''); | ||
223 | if (!empty($tags)) { | 343 | if (!empty($tags)) { |
224 | $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags); | 344 | $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); |
225 | } | 345 | } |
226 | 346 | ||
227 | if (!is_null($isStarred)) { | 347 | if (!is_null($isStarred)) { |
@@ -239,9 +359,7 @@ class EntryRestController extends WallabagRestController | |||
239 | // entry saved, dispatch event about it! | 359 | // entry saved, dispatch event about it! |
240 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | 360 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); |
241 | 361 | ||
242 | $json = $this->get('serializer')->serialize($entry, 'json'); | 362 | return $this->sendResponse($entry); |
243 | |||
244 | return (new JsonResponse())->setJson($json); | ||
245 | } | 363 | } |
246 | 364 | ||
247 | /** | 365 | /** |
@@ -284,15 +402,13 @@ class EntryRestController extends WallabagRestController | |||
284 | 402 | ||
285 | $tags = $request->request->get('tags', ''); | 403 | $tags = $request->request->get('tags', ''); |
286 | if (!empty($tags)) { | 404 | if (!empty($tags)) { |
287 | $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags); | 405 | $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); |
288 | } | 406 | } |
289 | 407 | ||
290 | $em = $this->getDoctrine()->getManager(); | 408 | $em = $this->getDoctrine()->getManager(); |
291 | $em->flush(); | 409 | $em->flush(); |
292 | 410 | ||
293 | $json = $this->get('serializer')->serialize($entry, 'json'); | 411 | return $this->sendResponse($entry); |
294 | |||
295 | return (new JsonResponse())->setJson($json); | ||
296 | } | 412 | } |
297 | 413 | ||
298 | /** | 414 | /** |
@@ -313,7 +429,7 @@ class EntryRestController extends WallabagRestController | |||
313 | $this->validateUserAccess($entry->getUser()->getId()); | 429 | $this->validateUserAccess($entry->getUser()->getId()); |
314 | 430 | ||
315 | try { | 431 | try { |
316 | $entry = $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl()); | 432 | $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl()); |
317 | } catch (\Exception $e) { | 433 | } catch (\Exception $e) { |
318 | $this->get('logger')->error('Error while saving an entry', [ | 434 | $this->get('logger')->error('Error while saving an entry', [ |
319 | 'exception' => $e, | 435 | 'exception' => $e, |
@@ -335,9 +451,7 @@ class EntryRestController extends WallabagRestController | |||
335 | // entry saved, dispatch event about it! | 451 | // entry saved, dispatch event about it! |
336 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); | 452 | $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); |
337 | 453 | ||
338 | $json = $this->get('serializer')->serialize($entry, 'json'); | 454 | return $this->sendResponse($entry); |
339 | |||
340 | return (new JsonResponse())->setJson($json); | ||
341 | } | 455 | } |
342 | 456 | ||
343 | /** | 457 | /** |
@@ -363,9 +477,7 @@ class EntryRestController extends WallabagRestController | |||
363 | // entry deleted, dispatch event about it! | 477 | // entry deleted, dispatch event about it! |
364 | $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); | 478 | $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); |
365 | 479 | ||
366 | $json = $this->get('serializer')->serialize($entry, 'json'); | 480 | return $this->sendResponse($entry); |
367 | |||
368 | return (new JsonResponse())->setJson($json); | ||
369 | } | 481 | } |
370 | 482 | ||
371 | /** | 483 | /** |
@@ -384,9 +496,7 @@ class EntryRestController extends WallabagRestController | |||
384 | $this->validateAuthentication(); | 496 | $this->validateAuthentication(); |
385 | $this->validateUserAccess($entry->getUser()->getId()); | 497 | $this->validateUserAccess($entry->getUser()->getId()); |
386 | 498 | ||
387 | $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); | 499 | return $this->sendResponse($entry->getTags()); |
388 | |||
389 | return (new JsonResponse())->setJson($json); | ||
390 | } | 500 | } |
391 | 501 | ||
392 | /** | 502 | /** |
@@ -410,16 +520,14 @@ class EntryRestController extends WallabagRestController | |||
410 | 520 | ||
411 | $tags = $request->request->get('tags', ''); | 521 | $tags = $request->request->get('tags', ''); |
412 | if (!empty($tags)) { | 522 | if (!empty($tags)) { |
413 | $this->get('wallabag_core.content_proxy')->assignTagsToEntry($entry, $tags); | 523 | $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); |
414 | } | 524 | } |
415 | 525 | ||
416 | $em = $this->getDoctrine()->getManager(); | 526 | $em = $this->getDoctrine()->getManager(); |
417 | $em->persist($entry); | 527 | $em->persist($entry); |
418 | $em->flush(); | 528 | $em->flush(); |
419 | 529 | ||
420 | $json = $this->get('serializer')->serialize($entry, 'json'); | 530 | return $this->sendResponse($entry); |
421 | |||
422 | return (new JsonResponse())->setJson($json); | ||
423 | } | 531 | } |
424 | 532 | ||
425 | /** | 533 | /** |
@@ -444,7 +552,124 @@ class EntryRestController extends WallabagRestController | |||
444 | $em->persist($entry); | 552 | $em->persist($entry); |
445 | $em->flush(); | 553 | $em->flush(); |
446 | 554 | ||
447 | $json = $this->get('serializer')->serialize($entry, 'json'); | 555 | return $this->sendResponse($entry); |
556 | } | ||
557 | |||
558 | /** | ||
559 | * Handles an entries list delete tags from them. | ||
560 | * | ||
561 | * @ApiDoc( | ||
562 | * parameters={ | ||
563 | * {"name"="list", "dataType"="string", "required"=true, "format"="A JSON array of urls [{'url': 'http://...','tags': 'tag1, tag2'}, {'url': 'http://...','tags': 'tag1, tag2'}]", "description"="Urls (as an array) to handle."} | ||
564 | * } | ||
565 | * ) | ||
566 | * | ||
567 | * @return JsonResponse | ||
568 | */ | ||
569 | public function deleteEntriesTagsListAction(Request $request) | ||
570 | { | ||
571 | $this->validateAuthentication(); | ||
572 | |||
573 | $list = json_decode($request->query->get('list', [])); | ||
574 | |||
575 | if (empty($list)) { | ||
576 | return $this->sendResponse([]); | ||
577 | } | ||
578 | |||
579 | // handle multiple urls | ||
580 | $results = []; | ||
581 | |||
582 | foreach ($list as $key => $element) { | ||
583 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId( | ||
584 | $element->url, | ||
585 | $this->getUser()->getId() | ||
586 | ); | ||
587 | |||
588 | $results[$key]['url'] = $element->url; | ||
589 | $results[$key]['entry'] = $entry instanceof Entry ? $entry->getId() : false; | ||
590 | |||
591 | $tags = $element->tags; | ||
592 | |||
593 | if (false !== $entry && !(empty($tags))) { | ||
594 | $tags = explode(',', $tags); | ||
595 | foreach ($tags as $label) { | ||
596 | $label = trim($label); | ||
597 | |||
598 | $tag = $this->getDoctrine() | ||
599 | ->getRepository('WallabagCoreBundle:Tag') | ||
600 | ->findOneByLabel($label); | ||
601 | |||
602 | if (false !== $tag) { | ||
603 | $entry->removeTag($tag); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | $em = $this->getDoctrine()->getManager(); | ||
608 | $em->persist($entry); | ||
609 | $em->flush(); | ||
610 | } | ||
611 | } | ||
612 | |||
613 | return $this->sendResponse($results); | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * Handles an entries list and add tags to them. | ||
618 | * | ||
619 | * @ApiDoc( | ||
620 | * parameters={ | ||
621 | * {"name"="list", "dataType"="string", "required"=true, "format"="A JSON array of urls [{'url': 'http://...','tags': 'tag1, tag2'}, {'url': 'http://...','tags': 'tag1, tag2'}]", "description"="Urls (as an array) to handle."} | ||
622 | * } | ||
623 | * ) | ||
624 | * | ||
625 | * @return JsonResponse | ||
626 | */ | ||
627 | public function postEntriesTagsListAction(Request $request) | ||
628 | { | ||
629 | $this->validateAuthentication(); | ||
630 | |||
631 | $list = json_decode($request->query->get('list', [])); | ||
632 | |||
633 | if (empty($list)) { | ||
634 | return $this->sendResponse([]); | ||
635 | } | ||
636 | |||
637 | $results = []; | ||
638 | |||
639 | // handle multiple urls | ||
640 | foreach ($list as $key => $element) { | ||
641 | $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId( | ||
642 | $element->url, | ||
643 | $this->getUser()->getId() | ||
644 | ); | ||
645 | |||
646 | $results[$key]['url'] = $element->url; | ||
647 | $results[$key]['entry'] = $entry instanceof Entry ? $entry->getId() : false; | ||
648 | |||
649 | $tags = $element->tags; | ||
650 | |||
651 | if (false !== $entry && !(empty($tags))) { | ||
652 | $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); | ||
653 | |||
654 | $em = $this->getDoctrine()->getManager(); | ||
655 | $em->persist($entry); | ||
656 | $em->flush(); | ||
657 | } | ||
658 | } | ||
659 | |||
660 | return $this->sendResponse($results); | ||
661 | } | ||
662 | |||
663 | /** | ||
664 | * Shortcut to send data serialized in json. | ||
665 | * | ||
666 | * @param mixed $data | ||
667 | * | ||
668 | * @return JsonResponse | ||
669 | */ | ||
670 | private function sendResponse($data) | ||
671 | { | ||
672 | $json = $this->get('serializer')->serialize($data, 'json'); | ||
448 | 673 | ||
449 | return (new JsonResponse())->setJson($json); | 674 | return (new JsonResponse())->setJson($json); |
450 | } | 675 | } |
diff --git a/src/Wallabag/ApiBundle/Controller/TagRestController.php b/src/Wallabag/ApiBundle/Controller/TagRestController.php index bc6d4e64..354187a0 100644 --- a/src/Wallabag/ApiBundle/Controller/TagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/TagRestController.php | |||
@@ -31,7 +31,7 @@ class TagRestController extends WallabagRestController | |||
31 | } | 31 | } |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * Permanently remove one tag from **every** entry. | 34 | * Permanently remove one tag from **every** entry by passing the Tag label. |
35 | * | 35 | * |
36 | * @ApiDoc( | 36 | * @ApiDoc( |
37 | * requirements={ | 37 | * requirements={ |
@@ -44,7 +44,7 @@ class TagRestController extends WallabagRestController | |||
44 | public function deleteTagLabelAction(Request $request) | 44 | public function deleteTagLabelAction(Request $request) |
45 | { | 45 | { |
46 | $this->validateAuthentication(); | 46 | $this->validateAuthentication(); |
47 | $label = $request->request->get('tag', ''); | 47 | $label = $request->get('tag', ''); |
48 | 48 | ||
49 | $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($label); | 49 | $tag = $this->getDoctrine()->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($label); |
50 | 50 | ||
@@ -78,7 +78,7 @@ class TagRestController extends WallabagRestController | |||
78 | { | 78 | { |
79 | $this->validateAuthentication(); | 79 | $this->validateAuthentication(); |
80 | 80 | ||
81 | $tagsLabels = $request->request->get('tags', ''); | 81 | $tagsLabels = $request->get('tags', ''); |
82 | 82 | ||
83 | $tags = []; | 83 | $tags = []; |
84 | 84 | ||
@@ -106,7 +106,7 @@ class TagRestController extends WallabagRestController | |||
106 | } | 106 | } |
107 | 107 | ||
108 | /** | 108 | /** |
109 | * Permanently remove one tag from **every** entry. | 109 | * Permanently remove one tag from **every** entry by passing the Tag ID. |
110 | * | 110 | * |
111 | * @ApiDoc( | 111 | * @ApiDoc( |
112 | * requirements={ | 112 | * requirements={ |
diff --git a/src/Wallabag/ApiBundle/Controller/UserRestController.php b/src/Wallabag/ApiBundle/Controller/UserRestController.php new file mode 100644 index 00000000..8f675b8d --- /dev/null +++ b/src/Wallabag/ApiBundle/Controller/UserRestController.php | |||
@@ -0,0 +1,146 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\ApiBundle\Controller; | ||
4 | |||
5 | use FOS\UserBundle\Event\UserEvent; | ||
6 | use FOS\UserBundle\FOSUserEvents; | ||
7 | use JMS\Serializer\SerializationContext; | ||
8 | use Nelmio\ApiDocBundle\Annotation\ApiDoc; | ||
9 | use Symfony\Component\HttpFoundation\Request; | ||
10 | use Symfony\Component\HttpFoundation\JsonResponse; | ||
11 | use Wallabag\UserBundle\Entity\User; | ||
12 | |||
13 | class UserRestController extends WallabagRestController | ||
14 | { | ||
15 | /** | ||
16 | * Retrieve current logged in user informations. | ||
17 | * | ||
18 | * @ApiDoc() | ||
19 | * | ||
20 | * @return JsonResponse | ||
21 | */ | ||
22 | public function getUserAction() | ||
23 | { | ||
24 | $this->validateAuthentication(); | ||
25 | |||
26 | return $this->sendUser($this->getUser()); | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * Register an user. | ||
31 | * | ||
32 | * @ApiDoc( | ||
33 | * requirements={ | ||
34 | * {"name"="username", "dataType"="string", "required"=true, "description"="The user's username"}, | ||
35 | * {"name"="password", "dataType"="string", "required"=true, "description"="The user's password"}, | ||
36 | * {"name"="email", "dataType"="string", "required"=true, "description"="The user's email"} | ||
37 | * } | ||
38 | * ) | ||
39 | * | ||
40 | * @todo Make this method (or the whole API) accessible only through https | ||
41 | * | ||
42 | * @return JsonResponse | ||
43 | */ | ||
44 | public function putUserAction(Request $request) | ||
45 | { | ||
46 | if (!$this->getParameter('fosuser_registration') || !$this->get('craue_config')->get('api_user_registration')) { | ||
47 | $json = $this->get('serializer')->serialize(['error' => "Server doesn't allow registrations"], 'json'); | ||
48 | |||
49 | return (new JsonResponse()) | ||
50 | ->setJson($json) | ||
51 | ->setStatusCode(JsonResponse::HTTP_FORBIDDEN); | ||
52 | } | ||
53 | |||
54 | $userManager = $this->get('fos_user.user_manager'); | ||
55 | $user = $userManager->createUser(); | ||
56 | // user will be disabled BY DEFAULT to avoid spamming account to be enabled | ||
57 | $user->setEnabled(false); | ||
58 | |||
59 | $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [ | ||
60 | 'csrf_protection' => false, | ||
61 | ]); | ||
62 | |||
63 | // simulate form submission | ||
64 | $form->submit([ | ||
65 | 'username' => $request->request->get('username'), | ||
66 | 'plainPassword' => [ | ||
67 | 'first' => $request->request->get('password'), | ||
68 | 'second' => $request->request->get('password'), | ||
69 | ], | ||
70 | 'email' => $request->request->get('email'), | ||
71 | ]); | ||
72 | |||
73 | if ($form->isSubmitted() && false === $form->isValid()) { | ||
74 | $view = $this->view($form, 400); | ||
75 | $view->setFormat('json'); | ||
76 | |||
77 | // handle errors in a more beautiful way than the default view | ||
78 | $data = json_decode($this->handleView($view)->getContent(), true)['children']; | ||
79 | $errors = []; | ||
80 | |||
81 | if (isset($data['username']['errors'])) { | ||
82 | $errors['username'] = $this->translateErrors($data['username']['errors']); | ||
83 | } | ||
84 | |||
85 | if (isset($data['email']['errors'])) { | ||
86 | $errors['email'] = $this->translateErrors($data['email']['errors']); | ||
87 | } | ||
88 | |||
89 | if (isset($data['plainPassword']['children']['first']['errors'])) { | ||
90 | $errors['password'] = $this->translateErrors($data['plainPassword']['children']['first']['errors']); | ||
91 | } | ||
92 | |||
93 | $json = $this->get('serializer')->serialize(['error' => $errors], 'json'); | ||
94 | |||
95 | return (new JsonResponse()) | ||
96 | ->setJson($json) | ||
97 | ->setStatusCode(JsonResponse::HTTP_BAD_REQUEST); | ||
98 | } | ||
99 | |||
100 | $userManager->updateUser($user); | ||
101 | |||
102 | // dispatch a created event so the associated config will be created | ||
103 | $event = new UserEvent($user, $request); | ||
104 | $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); | ||
105 | |||
106 | return $this->sendUser($user, JsonResponse::HTTP_CREATED); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * Send user response. | ||
111 | * | ||
112 | * @param User $user | ||
113 | * @param int $status HTTP Status code to send | ||
114 | * | ||
115 | * @return JsonResponse | ||
116 | */ | ||
117 | private function sendUser(User $user, $status = JsonResponse::HTTP_OK) | ||
118 | { | ||
119 | $json = $this->get('serializer')->serialize( | ||
120 | $user, | ||
121 | 'json', | ||
122 | SerializationContext::create()->setGroups(['user_api']) | ||
123 | ); | ||
124 | |||
125 | return (new JsonResponse()) | ||
126 | ->setJson($json) | ||
127 | ->setStatusCode($status); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * Translate errors message. | ||
132 | * | ||
133 | * @param array $errors | ||
134 | * | ||
135 | * @return array | ||
136 | */ | ||
137 | private function translateErrors($errors) | ||
138 | { | ||
139 | $translatedErrors = []; | ||
140 | foreach ($errors as $error) { | ||
141 | $translatedErrors[] = $this->get('translator')->trans($error); | ||
142 | } | ||
143 | |||
144 | return $translatedErrors; | ||
145 | } | ||
146 | } | ||
diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml index 57d37f4b..c0283e71 100644 --- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml +++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml | |||
@@ -17,3 +17,8 @@ misc: | |||
17 | type: rest | 17 | type: rest |
18 | resource: "WallabagApiBundle:WallabagRest" | 18 | resource: "WallabagApiBundle:WallabagRest" |
19 | name_prefix: api_ | 19 | name_prefix: api_ |
20 | |||
21 | user: | ||
22 | type: rest | ||
23 | resource: "WallabagApiBundle:UserRest" | ||
24 | name_prefix: api_ | ||