]> git.immae.eu Git - github/wallabag/wallabag.git/blame - src/Wallabag/ApiBundle/Controller/EntryRestController.php
WIP
[github/wallabag/wallabag.git] / src / Wallabag / ApiBundle / Controller / EntryRestController.php
CommitLineData
900c8448
NL
1<?php
2
3namespace Wallabag\ApiBundle\Controller;
4
5use Hateoas\Configuration\Route;
6use Hateoas\Representation\Factory\PagerfantaFactory;
7use Nelmio\ApiDocBundle\Annotation\ApiDoc;
72db15ca 8use Symfony\Component\HttpKernel\Exception\HttpException;
900c8448
NL
9use Symfony\Component\HttpFoundation\Request;
10use Symfony\Component\HttpFoundation\JsonResponse;
11use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
12use Wallabag\CoreBundle\Entity\Entry;
13use Wallabag\CoreBundle\Entity\Tag;
5a619812 14use Wallabag\CoreBundle\Event\EntryDeletedEvent;
bf6c0346
TC
15use Wallabag\CoreBundle\Event\EntrySavedEvent;
16use Wallabag\CoreBundle\Event\EntryTaggedEvent;
17use Wallabag\CoreBundle\Event\EntryUpdatedEvent;
900c8448
NL
18
19class EntryRestController extends WallabagRestController
20{
21 /**
22 * Check if an entry exist by url.
23 *
24 * @ApiDoc(
25 * parameters={
26 * {"name"="url", "dataType"="string", "required"=true, "format"="An url", "description"="Url to check if it exists"},
27 * {"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"}
28 * }
29 * )
30 *
31 * @return JsonResponse
32 */
33 public function getEntriesExistsAction(Request $request)
34 {
35 $this->validateAuthentication();
36
37 $urls = $request->query->get('urls', []);
38
39 // handle multiple urls first
40 if (!empty($urls)) {
41 $results = [];
42 foreach ($urls as $url) {
43 $res = $this->getDoctrine()
44 ->getRepository('WallabagCoreBundle:Entry')
45 ->findByUrlAndUserId($url, $this->getUser()->getId());
46
ca9a83ee 47 $results[$url] = $res instanceof Entry ? $res->getId() : false;
900c8448
NL
48 }
49
72db15ca 50 return $this->sendResponse($results);
900c8448
NL
51 }
52
53 // let's see if it is a simple url?
54 $url = $request->query->get('url', '');
55
56 if (empty($url)) {
57 throw $this->createAccessDeniedException('URL is empty?, logged user id: '.$this->getUser()->getId());
58 }
59
60 $res = $this->getDoctrine()
61 ->getRepository('WallabagCoreBundle:Entry')
62 ->findByUrlAndUserId($url, $this->getUser()->getId());
63
ca9a83ee 64 $exists = $res instanceof Entry ? $res->getId() : false;
900c8448 65
72db15ca 66 return $this->sendResponse(['exists' => $exists]);
900c8448
NL
67 }
68
69 /**
70 * Retrieve all entries. It could be filtered by many options.
71 *
72 * @ApiDoc(
73 * parameters={
74 * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by archived status."},
75 * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by starred status."},
76 * {"name"="sort", "dataType"="string", "required"=false, "format"="'created' or 'updated', default 'created'", "description"="sort entries by date."},
77 * {"name"="order", "dataType"="string", "required"=false, "format"="'asc' or 'desc', default 'desc'", "description"="order of sort."},
78 * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."},
79 * {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."},
80 * {"name"="tags", "dataType"="string", "required"=false, "format"="api,rest", "description"="a list of tags url encoded. Will returns entries that matches ALL tags."},
81 * {"name"="since", "dataType"="integer", "required"=false, "format"="default '0'", "description"="The timestamp since when you want entries updated."},
1112e547 82 * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0, all entries by default", "description"="filter by entries with a public link"},
900c8448
NL
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');
1112e547 94 $isPublic = (null === $request->query->get('public')) ? null : (bool) $request->query->get('public');
900c8448
NL
95 $sort = $request->query->get('sort', 'created');
96 $order = $request->query->get('order', 'desc');
97 $page = (int) $request->query->get('page', 1);
98 $perPage = (int) $request->query->get('perPage', 30);
99 $tags = $request->query->get('tags', '');
100 $since = $request->query->get('since', 0);
101
b60a666d 102 /** @var \Pagerfanta\Pagerfanta $pager */
1112e547
JB
103 $pager = $this->get('wallabag_core.entry_repository')->findEntries(
104 $this->getUser()->getId(),
105 $isArchived,
106 $isStarred,
107 $isPublic,
108 $sort,
109 $order,
110 $since,
111 $tags
112 );
900c8448 113
900c8448 114 $pager->setMaxPerPage($perPage);
b60a666d 115 $pager->setCurrentPage($page);
900c8448
NL
116
117 $pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
118 $paginatedCollection = $pagerfantaFactory->createRepresentation(
119 $pager,
120 new Route(
121 'api_get_entries',
122 [
123 'archive' => $isArchived,
124 'starred' => $isStarred,
1112e547 125 'public' => $isPublic,
900c8448
NL
126 'sort' => $sort,
127 'order' => $order,
128 'page' => $page,
129 'perPage' => $perPage,
130 'tags' => $tags,
131 'since' => $since,
132 ],
133 UrlGeneratorInterface::ABSOLUTE_URL
134 )
135 );
136
72db15ca 137 return $this->sendResponse($paginatedCollection);
900c8448
NL
138 }
139
140 /**
141 * Retrieve a single entry.
142 *
143 * @ApiDoc(
144 * requirements={
145 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
146 * }
147 * )
148 *
149 * @return JsonResponse
150 */
151 public function getEntryAction(Entry $entry)
152 {
153 $this->validateAuthentication();
154 $this->validateUserAccess($entry->getUser()->getId());
155
72db15ca 156 return $this->sendResponse($entry);
900c8448
NL
157 }
158
864c1dd2
JB
159 /**
160 * Retrieve a single entry as a predefined format.
161 *
162 * @ApiDoc(
163 * requirements={
164 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
165 * }
166 * )
167 *
168 * @return Response
169 */
170 public function getEntryExportAction(Entry $entry, Request $request)
171 {
172 $this->validateAuthentication();
173 $this->validateUserAccess($entry->getUser()->getId());
174
175 return $this->get('wallabag_core.helper.entries_export')
176 ->setEntries($entry)
177 ->updateTitle('entry')
178 ->exportAs($request->attributes->get('_format'));
179 }
180
1eca7831 181 /**
a7abcc7b 182 * Handles an entries list and delete URL.
1eca7831
NL
183 *
184 * @ApiDoc(
185 * parameters={
a7abcc7b 186 * {"name"="urls", "dataType"="string", "required"=true, "format"="A JSON array of urls [{'url': 'http://...'}, {'url': 'http://...'}]", "description"="Urls (as an array) to delete."}
1eca7831
NL
187 * }
188 * )
189 *
190 * @return JsonResponse
191 */
a7abcc7b 192 public function deleteEntriesListAction(Request $request)
1eca7831
NL
193 {
194 $this->validateAuthentication();
195
a7abcc7b 196 $urls = json_decode($request->query->get('urls', []));
72db15ca
JB
197
198 if (empty($urls)) {
199 return $this->sendResponse([]);
200 }
201
1eca7831
NL
202 $results = [];
203
204 // handle multiple urls
72db15ca
JB
205 foreach ($urls as $key => $url) {
206 $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId(
207 $url,
208 $this->getUser()->getId()
209 );
a7abcc7b 210
72db15ca 211 $results[$key]['url'] = $url;
a7abcc7b 212
72db15ca
JB
213 if (false !== $entry) {
214 $em = $this->getDoctrine()->getManager();
215 $em->remove($entry);
216 $em->flush();
1eca7831 217
72db15ca
JB
218 // entry deleted, dispatch event about it!
219 $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry));
a7abcc7b 220 }
1eca7831 221
72db15ca
JB
222 $results[$key]['entry'] = $entry instanceof Entry ? true : false;
223 }
1eca7831 224
72db15ca 225 return $this->sendResponse($results);
a7abcc7b 226 }
1eca7831 227
a7abcc7b
NL
228 /**
229 * Handles an entries list and create URL.
230 *
231 * @ApiDoc(
232 * parameters={
233 * {"name"="urls", "dataType"="string", "required"=true, "format"="A JSON array of urls [{'url': 'http://...'}, {'url': 'http://...'}]", "description"="Urls (as an array) to create."}
234 * }
235 * )
236 *
237 * @return JsonResponse
efd351c9 238 *
72db15ca 239 * @throws HttpException When limit is reached
a7abcc7b
NL
240 */
241 public function postEntriesListAction(Request $request)
242 {
243 $this->validateAuthentication();
1eca7831 244
a7abcc7b 245 $urls = json_decode($request->query->get('urls', []));
1eca7831 246
efd351c9
NL
247 $limit = $this->container->getParameter('wallabag_core.api_limit_mass_actions');
248
249 if (count($urls) > $limit) {
72db15ca 250 throw new HttpException(400, 'API limit reached');
efd351c9
NL
251 }
252
d5c2cc54
JB
253 $results = [];
254 if (empty($urls)) {
255 return $this->sendResponse($results);
256 }
257
a7abcc7b 258 // handle multiple urls
d5c2cc54
JB
259 foreach ($urls as $key => $url) {
260 $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId(
261 $url,
262 $this->getUser()->getId()
263 );
1eca7831 264
d5c2cc54 265 $results[$key]['url'] = $url;
1eca7831 266
d5c2cc54
JB
267 if (false === $entry) {
268 $entry = new Entry($this->getUser());
a7abcc7b 269
d5c2cc54
JB
270 $this->get('wallabag_core.content_proxy')->updateEntry($entry, $url);
271 }
a7abcc7b 272
d5c2cc54
JB
273 $em = $this->getDoctrine()->getManager();
274 $em->persist($entry);
275 $em->flush();
a7abcc7b 276
d5c2cc54
JB
277 $results[$key]['entry'] = $entry instanceof Entry ? $entry->getId() : false;
278
279 // entry saved, dispatch event about it!
280 $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
1eca7831
NL
281 }
282
72db15ca 283 return $this->sendResponse($results);
1eca7831
NL
284 }
285
900c8448
NL
286 /**
287 * Create an entry.
288 *
9e349f08
JB
289 * 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**.
290 * Otherwise, content will be fetched as normal from the url and values will be overwritten.
291 *
900c8448
NL
292 * @ApiDoc(
293 * parameters={
294 * {"name"="url", "dataType"="string", "required"=true, "format"="http://www.test.com/article.html", "description"="Url for the entry."},
295 * {"name"="title", "dataType"="string", "required"=false, "description"="Optional, we'll get the title from the page."},
296 * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
297 * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already starred"},
298 * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="entry already archived"},
e668a812
JB
299 * {"name"="content", "dataType"="string", "required"=false, "description"="Content of the entry"},
300 * {"name"="language", "dataType"="string", "required"=false, "description"="Language of the entry"},
301 * {"name"="preview_picture", "dataType"="string", "required"=false, "description"="Preview picture of the entry"},
f0378b4d 302 * {"name"="published_at", "dataType"="datetime|integer", "format"="YYYY-MM-DDTHH:II:SS+TZ or a timestamp", "required"=false, "description"="Published date of the entry"},
fb436e8c 303 * {"name"="authors", "dataType"="string", "format"="Name Firstname,author2,author3", "required"=false, "description"="Authors of the entry"},
1112e547 304 * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="will generate a public link for the entry"},
900c8448
NL
305 * }
306 * )
307 *
308 * @return JsonResponse
309 */
310 public function postEntriesAction(Request $request)
311 {
312 $this->validateAuthentication();
313
314 $url = $request->request->get('url');
900c8448 315
db0c48af
JB
316 $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId(
317 $url,
318 $this->getUser()->getId()
319 );
900c8448
NL
320
321 if (false === $entry) {
08f29ae7 322 $entry = new Entry($this->getUser());
e668a812 323 $entry->setUrl($url);
900c8448
NL
324 }
325
db0c48af 326 $this->upsertEntry($entry, $request);
5a619812 327
72db15ca 328 return $this->sendResponse($entry);
900c8448
NL
329 }
330
331 /**
332 * Change several properties of an entry.
333 *
334 * @ApiDoc(
335 * requirements={
336 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
337 * },
338 * parameters={
339 * {"name"="title", "dataType"="string", "required"=false},
340 * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
341 * {"name"="archive", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="archived the entry."},
342 * {"name"="starred", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="starred the entry."},
645291e8
JB
343 * {"name"="content", "dataType"="string", "required"=false, "description"="Content of the entry"},
344 * {"name"="language", "dataType"="string", "required"=false, "description"="Language of the entry"},
345 * {"name"="preview_picture", "dataType"="string", "required"=false, "description"="Preview picture of the entry"},
346 * {"name"="published_at", "dataType"="datetime|integer", "format"="YYYY-MM-DDTHH:II:SS+TZ or a timestamp", "required"=false, "description"="Published date of the entry"},
347 * {"name"="authors", "dataType"="string", "format"="Name Firstname,author2,author3", "required"=false, "description"="Authors of the entry"},
1112e547 348 * {"name"="public", "dataType"="integer", "required"=false, "format"="1 or 0", "description"="will generate a public link for the entry"},
900c8448
NL
349 * }
350 * )
351 *
352 * @return JsonResponse
353 */
354 public function patchEntriesAction(Entry $entry, Request $request)
355 {
356 $this->validateAuthentication();
357 $this->validateUserAccess($entry->getUser()->getId());
358
db0c48af 359 $this->upsertEntry($entry, $request, true);
900c8448 360
bf6c0346
TC
361 $this->get('event_dispatcher')->dispatch(EntryUpdatedEvent::NAME, new EntryUpdatedEvent($entry));
362
72db15ca 363 return $this->sendResponse($entry);
900c8448
NL
364 }
365
0a6f4568
JB
366 /**
367 * Reload an entry.
5cd0857e 368 * An empty response with HTTP Status 304 will be send if we weren't able to update the content (because it hasn't changed or we got an error).
0a6f4568
JB
369 *
370 * @ApiDoc(
371 * requirements={
372 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
373 * }
374 * )
375 *
376 * @return JsonResponse
377 */
378 public function patchEntriesReloadAction(Entry $entry)
379 {
380 $this->validateAuthentication();
381 $this->validateUserAccess($entry->getUser()->getId());
382
0a6f4568 383 try {
7aba665e 384 $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl());
0a6f4568
JB
385 } catch (\Exception $e) {
386 $this->get('logger')->error('Error while saving an entry', [
387 'exception' => $e,
388 'entry' => $entry,
389 ]);
390
5cd0857e 391 return new JsonResponse([], 304);
0a6f4568
JB
392 }
393
394 // if refreshing entry failed, don't save it
395 if ($this->getParameter('wallabag_core.fetching_error_message') === $entry->getContent()) {
5cd0857e 396 return new JsonResponse([], 304);
0a6f4568
JB
397 }
398
399 $em = $this->getDoctrine()->getManager();
400 $em->persist($entry);
401 $em->flush();
402
403 // entry saved, dispatch event about it!
bf6c0346 404 $this->get('event_dispatcher')->dispatch(EntryUpdatedEvent::NAME, new EntryUpdatedEvent($entry));
0a6f4568
JB
405 $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
406
72db15ca 407 return $this->sendResponse($entry);
0a6f4568
JB
408 }
409
900c8448
NL
410 /**
411 * Delete **permanently** an entry.
412 *
413 * @ApiDoc(
414 * requirements={
415 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
416 * }
417 * )
418 *
419 * @return JsonResponse
420 */
421 public function deleteEntriesAction(Entry $entry)
422 {
423 $this->validateAuthentication();
424 $this->validateUserAccess($entry->getUser()->getId());
425
426 $em = $this->getDoctrine()->getManager();
427 $em->remove($entry);
428 $em->flush();
429
5a619812
JB
430 // entry deleted, dispatch event about it!
431 $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry));
432
72db15ca 433 return $this->sendResponse($entry);
900c8448
NL
434 }
435
436 /**
437 * Retrieve all tags for an entry.
438 *
439 * @ApiDoc(
440 * requirements={
441 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
442 * }
443 * )
444 *
445 * @return JsonResponse
446 */
447 public function getEntriesTagsAction(Entry $entry)
448 {
449 $this->validateAuthentication();
450 $this->validateUserAccess($entry->getUser()->getId());
451
72db15ca 452 return $this->sendResponse($entry->getTags());
900c8448
NL
453 }
454
455 /**
456 * Add one or more tags to an entry.
457 *
458 * @ApiDoc(
459 * requirements={
460 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
461 * },
462 * parameters={
463 * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."},
464 * }
465 * )
466 *
467 * @return JsonResponse
468 */
469 public function postEntriesTagsAction(Request $request, Entry $entry)
470 {
471 $this->validateAuthentication();
472 $this->validateUserAccess($entry->getUser()->getId());
473
474 $tags = $request->request->get('tags', '');
bf6c0346 475 $tagsEntries = [];
900c8448 476 if (!empty($tags)) {
6bc6fb1f 477 $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags);
900c8448
NL
478 }
479
480 $em = $this->getDoctrine()->getManager();
481 $em->persist($entry);
482 $em->flush();
483
bf6c0346
TC
484 $this->get('event_dispatcher')->dispatch(EntryTaggedEvent::NAME, new EntryTaggedEvent($entry, $tagsEntries));
485
72db15ca 486 return $this->sendResponse($entry);
900c8448
NL
487 }
488
489 /**
490 * Permanently remove one tag for an entry.
491 *
492 * @ApiDoc(
493 * requirements={
494 * {"name"="tag", "dataType"="integer", "requirement"="\w+", "description"="The tag ID"},
495 * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
496 * }
497 * )
498 *
499 * @return JsonResponse
500 */
501 public function deleteEntriesTagsAction(Entry $entry, Tag $tag)
502 {
503 $this->validateAuthentication();
504 $this->validateUserAccess($entry->getUser()->getId());
505
506 $entry->removeTag($tag);
507 $em = $this->getDoctrine()->getManager();
508 $em->persist($entry);
509 $em->flush();
510
72db15ca 511 return $this->sendResponse($entry);
900c8448 512 }
d1fc5902
NL
513
514 /**
80299ed2 515 * Handles an entries list delete tags from them.
d1fc5902
NL
516 *
517 * @ApiDoc(
518 * parameters={
80299ed2 519 * {"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."}
d1fc5902
NL
520 * }
521 * )
522 *
523 * @return JsonResponse
524 */
80299ed2 525 public function deleteEntriesTagsListAction(Request $request)
d1fc5902
NL
526 {
527 $this->validateAuthentication();
528
529 $list = json_decode($request->query->get('list', []));
72db15ca
JB
530
531 if (empty($list)) {
532 return $this->sendResponse([]);
533 }
d1fc5902
NL
534
535 // handle multiple urls
72db15ca 536 $results = [];
d1fc5902 537
72db15ca
JB
538 foreach ($list as $key => $element) {
539 $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId(
540 $element->url,
541 $this->getUser()->getId()
542 );
d1fc5902 543
72db15ca
JB
544 $results[$key]['url'] = $element->url;
545 $results[$key]['entry'] = $entry instanceof Entry ? $entry->getId() : false;
d1fc5902 546
72db15ca 547 $tags = $element->tags;
80299ed2 548
72db15ca
JB
549 if (false !== $entry && !(empty($tags))) {
550 $tags = explode(',', $tags);
551 foreach ($tags as $label) {
552 $label = trim($label);
80299ed2 553
72db15ca
JB
554 $tag = $this->getDoctrine()
555 ->getRepository('WallabagCoreBundle:Tag')
556 ->findOneByLabel($label);
d1fc5902 557
72db15ca
JB
558 if (false !== $tag) {
559 $entry->removeTag($tag);
560 }
d1fc5902 561 }
72db15ca
JB
562
563 $em = $this->getDoctrine()->getManager();
564 $em->persist($entry);
565 $em->flush();
d1fc5902
NL
566 }
567 }
568
72db15ca 569 return $this->sendResponse($results);
d1fc5902 570 }
80299ed2
NL
571
572 /**
573 * Handles an entries list and add tags to them.
574 *
575 * @ApiDoc(
576 * parameters={
577 * {"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."}
578 * }
579 * )
580 *
581 * @return JsonResponse
582 */
583 public function postEntriesTagsListAction(Request $request)
584 {
585 $this->validateAuthentication();
586
587 $list = json_decode($request->query->get('list', []));
72db15ca
JB
588
589 if (empty($list)) {
590 return $this->sendResponse([]);
591 }
592
80299ed2
NL
593 $results = [];
594
595 // handle multiple urls
72db15ca
JB
596 foreach ($list as $key => $element) {
597 $entry = $this->get('wallabag_core.entry_repository')->findByUrlAndUserId(
598 $element->url,
599 $this->getUser()->getId()
600 );
80299ed2 601
72db15ca
JB
602 $results[$key]['url'] = $element->url;
603 $results[$key]['entry'] = $entry instanceof Entry ? $entry->getId() : false;
80299ed2 604
72db15ca 605 $tags = $element->tags;
80299ed2 606
72db15ca 607 if (false !== $entry && !(empty($tags))) {
6bc6fb1f 608 $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags);
80299ed2 609
72db15ca
JB
610 $em = $this->getDoctrine()->getManager();
611 $em->persist($entry);
612 $em->flush();
80299ed2
NL
613 }
614 }
615
72db15ca
JB
616 return $this->sendResponse($results);
617 }
618
619 /**
620 * Shortcut to send data serialized in json.
621 *
622 * @param mixed $data
623 *
624 * @return JsonResponse
625 */
626 private function sendResponse($data)
627 {
628 $json = $this->get('serializer')->serialize($data, 'json');
80299ed2
NL
629
630 return (new JsonResponse())->setJson($json);
631 }
db0c48af
JB
632
633 /**
634 * Update or Insert a new entry.
635 *
636 * @param Entry $entry
637 * @param Request $request
638 * @param bool $disableContentUpdate If we don't want the content to be update by fetching the url (used when patching instead of posting)
639 */
640 private function upsertEntry(Entry $entry, Request $request, $disableContentUpdate = false)
641 {
642 $title = $request->request->get('title');
643 $tags = $request->request->get('tags', []);
644 $isArchived = $request->request->get('archive');
645 $isStarred = $request->request->get('starred');
1112e547 646 $isPublic = $request->request->get('public');
db0c48af
JB
647 $content = $request->request->get('content');
648 $language = $request->request->get('language');
649 $picture = $request->request->get('preview_picture');
650 $publishedAt = $request->request->get('published_at');
651 $authors = $request->request->get('authors', '');
652
653 try {
654 $this->get('wallabag_core.content_proxy')->updateEntry(
655 $entry,
656 $entry->getUrl(),
657 [
658 'title' => !empty($title) ? $title : $entry->getTitle(),
659 'html' => !empty($content) ? $content : $entry->getContent(),
660 'url' => $entry->getUrl(),
661 'language' => !empty($language) ? $language : $entry->getLanguage(),
662 'date' => !empty($publishedAt) ? $publishedAt : $entry->getPublishedAt(),
663 // faking the open graph preview picture
664 'open_graph' => [
665 'og_image' => !empty($picture) ? $picture : $entry->getPreviewPicture(),
666 ],
667 'authors' => is_string($authors) ? explode(',', $authors) : $entry->getPublishedBy(),
668 ],
669 $disableContentUpdate
670 );
671 } catch (\Exception $e) {
672 $this->get('logger')->error('Error while saving an entry', [
673 'exception' => $e,
674 'entry' => $entry,
675 ]);
676 }
677
678 if (!is_null($isArchived)) {
bf6c0346 679 $entry->setArchived((bool)$isArchived);
db0c48af
JB
680 }
681
682 if (!is_null($isStarred)) {
bf6c0346 683 $entry->setStarred((bool)$isStarred);
db0c48af
JB
684 }
685
686 if (!empty($tags)) {
687 $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags);
688 }
689
1112e547 690 if (!is_null($isPublic)) {
bf6c0346 691 if (true === (bool)$isPublic && null === $entry->getUid()) {
1112e547 692 $entry->generateUid();
bf6c0346 693 } elseif (false === (bool)$isPublic) {
a9c6577f 694 $entry->cleanUid();
1112e547
JB
695 }
696 }
697
db0c48af
JB
698 $em = $this->getDoctrine()->getManager();
699 $em->persist($entry);
700 $em->flush();
701
702 // entry saved, dispatch event about it!
703 $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
704 }
bf6c0346
TC
705
706 /**
707 * Gets history since a date.
708 *
709 * @ApiDoc(
710 * parameters={
711 * {"name"="since", "dataType"="integer", "required"=true, "format"="A timestamp", "description"="Timestamp of the history's start"},
712 * }
713 * )
714 *
715 * @return JsonResponse
716 */
717 public function getEntriesHistoryAction(Request $request)
718 {
719 $this->validateAuthentication();
720
721 $res = $this->getDoctrine()
722 ->getRepository('WallabagCoreBundle:Change')
723 ->findChangesSinceDate($request->query->get('since'));
724
725 $json = $this->get('serializer')->serialize($res, 'json');
726
727 return (new JsonResponse())->setJson($json);
728 }
900c8448 729}