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