]> git.immae.eu Git - github/wallabag/wallabag.git/blob - src/Wallabag/CoreBundle/Entity/Entry.php
Fix index on MySQL
[github/wallabag/wallabag.git] / src / Wallabag / CoreBundle / Entity / Entry.php
1 <?php
2
3 namespace Wallabag\CoreBundle\Entity;
4
5 use Doctrine\Common\Collections\ArrayCollection;
6 use Doctrine\ORM\Mapping as ORM;
7 use Hateoas\Configuration\Annotation as Hateoas;
8 use JMS\Serializer\Annotation\Exclude;
9 use JMS\Serializer\Annotation\Groups;
10 use JMS\Serializer\Annotation\SerializedName;
11 use JMS\Serializer\Annotation\VirtualProperty;
12 use JMS\Serializer\Annotation\XmlRoot;
13 use Symfony\Component\Validator\Constraints as Assert;
14 use Wallabag\AnnotationBundle\Entity\Annotation;
15 use Wallabag\CoreBundle\Helper\EntityTimestampsTrait;
16 use Wallabag\UserBundle\Entity\User;
17
18 /**
19 * Entry.
20 *
21 * @XmlRoot("entry")
22 * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\EntryRepository")
23 * @ORM\Table(
24 * name="`entry`",
25 * options={"collate"="utf8mb4_unicode_ci", "charset"="utf8mb4"},
26 * indexes={
27 * @ORM\Index(name="created_at", columns={"created_at"}),
28 * @ORM\Index(name="uid", columns={"uid"}),
29 * @ORM\Index(name="hashed_url_user_id", columns={"user_id", "hashed_url"}, options={"lengths"={null, 40}})
30 * }
31 * )
32 * @ORM\HasLifecycleCallbacks()
33 * @Hateoas\Relation("self", href = "expr('/api/entries/' ~ object.getId())")
34 */
35 class Entry
36 {
37 use EntityTimestampsTrait;
38
39 /** @Serializer\XmlAttribute */
40 /**
41 * @var int
42 *
43 * @ORM\Column(name="id", type="integer")
44 * @ORM\Id
45 * @ORM\GeneratedValue(strategy="AUTO")
46 *
47 * @Groups({"entries_for_user", "export_all"})
48 */
49 private $id;
50
51 /**
52 * @var string
53 *
54 * @ORM\Column(name="uid", type="string", length=23, nullable=true)
55 *
56 * @Groups({"entries_for_user", "export_all"})
57 */
58 private $uid;
59
60 /**
61 * @var string
62 *
63 * @ORM\Column(name="title", type="text", nullable=true)
64 *
65 * @Groups({"entries_for_user", "export_all"})
66 */
67 private $title;
68
69 /**
70 * @var string
71 *
72 * @Assert\NotBlank()
73 * @ORM\Column(name="url", type="text", nullable=true)
74 *
75 * @Groups({"entries_for_user", "export_all"})
76 */
77 private $url;
78
79 /**
80 * @var string
81 *
82 * @ORM\Column(name="hashed_url", type="string", length=40, nullable=true)
83 */
84 private $hashedUrl;
85
86 /**
87 * @var bool
88 *
89 * @Exclude
90 *
91 * @ORM\Column(name="is_archived", type="boolean")
92 *
93 * @Groups({"entries_for_user", "export_all"})
94 */
95 private $isArchived = false;
96
97 /**
98 * @var \DateTime
99 *
100 * @ORM\Column(name="archived_at", type="datetime", nullable=true)
101 *
102 * @Groups({"entries_for_user", "export_all"})
103 */
104 private $archivedAt = null;
105
106 /**
107 * @var bool
108 *
109 * @Exclude
110 *
111 * @ORM\Column(name="is_starred", type="boolean")
112 *
113 * @Groups({"entries_for_user", "export_all"})
114 */
115 private $isStarred = false;
116
117 /**
118 * @var string
119 *
120 * @ORM\Column(name="content", type="text", nullable=true)
121 *
122 * @Groups({"entries_for_user", "export_all"})
123 */
124 private $content;
125
126 /**
127 * @var \DateTime
128 *
129 * @ORM\Column(name="created_at", type="datetime")
130 *
131 * @Groups({"entries_for_user", "export_all"})
132 */
133 private $createdAt;
134
135 /**
136 * @var \DateTime
137 *
138 * @ORM\Column(name="updated_at", type="datetime")
139 *
140 * @Groups({"entries_for_user", "export_all"})
141 */
142 private $updatedAt;
143
144 /**
145 * @var \DateTime
146 *
147 * @ORM\Column(name="published_at", type="datetime", nullable=true)
148 *
149 * @Groups({"entries_for_user", "export_all"})
150 */
151 private $publishedAt;
152
153 /**
154 * @var array
155 *
156 * @ORM\Column(name="published_by", type="array", nullable=true)
157 *
158 * @Groups({"entries_for_user", "export_all"})
159 */
160 private $publishedBy;
161
162 /**
163 * @var \DateTime
164 *
165 * @ORM\Column(name="starred_at", type="datetime", nullable=true)
166 *
167 * @Groups({"entries_for_user", "export_all"})
168 */
169 private $starredAt = null;
170
171 /**
172 * @ORM\OneToMany(targetEntity="Wallabag\AnnotationBundle\Entity\Annotation", mappedBy="entry", cascade={"persist", "remove"})
173 * @ORM\JoinTable
174 *
175 * @Groups({"entries_for_user", "export_all"})
176 */
177 private $annotations;
178
179 /**
180 * @var string
181 *
182 * @ORM\Column(name="mimetype", type="text", nullable=true)
183 *
184 * @Groups({"entries_for_user", "export_all"})
185 */
186 private $mimetype;
187
188 /**
189 * @var string
190 *
191 * @ORM\Column(name="language", type="text", nullable=true)
192 *
193 * @Groups({"entries_for_user", "export_all"})
194 */
195 private $language;
196
197 /**
198 * @var int
199 *
200 * @ORM\Column(name="reading_time", type="integer", nullable=false)
201 *
202 * @Groups({"entries_for_user", "export_all"})
203 */
204 private $readingTime = 0;
205
206 /**
207 * @var string
208 *
209 * @ORM\Column(name="domain_name", type="text", nullable=true)
210 *
211 * @Groups({"entries_for_user", "export_all"})
212 */
213 private $domainName;
214
215 /**
216 * @var string
217 *
218 * @ORM\Column(name="preview_picture", type="text", nullable=true)
219 *
220 * @Groups({"entries_for_user", "export_all"})
221 */
222 private $previewPicture;
223
224 /**
225 * @var string
226 *
227 * @ORM\Column(name="http_status", type="string", length=3, nullable=true)
228 *
229 * @Groups({"entries_for_user", "export_all"})
230 */
231 private $httpStatus;
232
233 /**
234 * @var array
235 *
236 * @ORM\Column(name="headers", type="array", nullable=true)
237 *
238 * @Groups({"entries_for_user", "export_all"})
239 */
240 private $headers;
241
242 /**
243 * @Exclude
244 *
245 * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User", inversedBy="entries")
246 *
247 * @Groups({"export_all"})
248 */
249 private $user;
250
251 /**
252 * @ORM\ManyToMany(targetEntity="Tag", inversedBy="entries", cascade={"persist"})
253 * @ORM\JoinTable(
254 * name="entry_tag",
255 * joinColumns={
256 * @ORM\JoinColumn(name="entry_id", referencedColumnName="id", onDelete="cascade")
257 * },
258 * inverseJoinColumns={
259 * @ORM\JoinColumn(name="tag_id", referencedColumnName="id", onDelete="cascade")
260 * }
261 * )
262 */
263 private $tags;
264
265 /**
266 * @var string
267 *
268 * @ORM\Column(name="origin_url", type="text", nullable=true)
269 *
270 * @Groups({"entries_for_user", "export_all"})
271 */
272 private $originUrl;
273
274 /*
275 * @param User $user
276 */
277 public function __construct(User $user)
278 {
279 $this->user = $user;
280 $this->tags = new ArrayCollection();
281 }
282
283 /**
284 * Get id.
285 *
286 * @return int
287 */
288 public function getId()
289 {
290 return $this->id;
291 }
292
293 /**
294 * Set title.
295 *
296 * @param string $title
297 *
298 * @return Entry
299 */
300 public function setTitle($title)
301 {
302 $this->title = $title;
303
304 return $this;
305 }
306
307 /**
308 * Get title.
309 *
310 * @return string
311 */
312 public function getTitle()
313 {
314 return $this->title;
315 }
316
317 /**
318 * Set url.
319 *
320 * @param string $url
321 *
322 * @return Entry
323 */
324 public function setUrl($url)
325 {
326 $this->url = $url;
327 $this->hashedUrl = hash('sha1', $url);
328
329 return $this;
330 }
331
332 /**
333 * Get url.
334 *
335 * @return string
336 */
337 public function getUrl()
338 {
339 return $this->url;
340 }
341
342 /**
343 * Set isArchived.
344 *
345 * @param bool $isArchived
346 *
347 * @return Entry
348 */
349 public function setArchived($isArchived)
350 {
351 $this->isArchived = $isArchived;
352
353 return $this;
354 }
355
356 /**
357 * update isArchived and archive_at fields.
358 *
359 * @param bool $isArchived
360 *
361 * @return Entry
362 */
363 public function updateArchived($isArchived = false)
364 {
365 $this->setArchived($isArchived);
366 $this->setArchivedAt(null);
367 if ($this->isArchived()) {
368 $this->setArchivedAt(new \DateTime());
369 }
370
371 return $this;
372 }
373
374 /**
375 * @return \DateTime|null
376 */
377 public function getArchivedAt()
378 {
379 return $this->archivedAt;
380 }
381
382 /**
383 * @param \DateTime|null $archivedAt
384 *
385 * @return Entry
386 */
387 public function setArchivedAt($archivedAt = null)
388 {
389 $this->archivedAt = $archivedAt;
390
391 return $this;
392 }
393
394 /**
395 * Get isArchived.
396 *
397 * @return bool
398 */
399 public function isArchived()
400 {
401 return $this->isArchived;
402 }
403
404 /**
405 * @VirtualProperty
406 * @SerializedName("is_archived")
407 * @Groups({"entries_for_user", "export_all"})
408 */
409 public function is_Archived()
410 {
411 return (int) $this->isArchived();
412 }
413
414 public function toggleArchive()
415 {
416 $this->updateArchived($this->isArchived() ^ 1);
417
418 return $this;
419 }
420
421 /**
422 * Set isStarred.
423 *
424 * @param bool $isStarred
425 *
426 * @return Entry
427 */
428 public function setStarred($isStarred)
429 {
430 $this->isStarred = $isStarred;
431
432 return $this;
433 }
434
435 /**
436 * Get isStarred.
437 *
438 * @return bool
439 */
440 public function isStarred()
441 {
442 return $this->isStarred;
443 }
444
445 /**
446 * @VirtualProperty
447 * @SerializedName("is_starred")
448 * @Groups({"entries_for_user", "export_all"})
449 */
450 public function is_Starred()
451 {
452 return (int) $this->isStarred();
453 }
454
455 public function toggleStar()
456 {
457 $this->isStarred = $this->isStarred() ^ 1;
458
459 return $this;
460 }
461
462 /**
463 * Set content.
464 *
465 * @param string $content
466 *
467 * @return Entry
468 */
469 public function setContent($content)
470 {
471 $this->content = $content;
472
473 return $this;
474 }
475
476 /**
477 * Get content.
478 *
479 * @return string
480 */
481 public function getContent()
482 {
483 return $this->content;
484 }
485
486 /**
487 * @return User
488 */
489 public function getUser()
490 {
491 return $this->user;
492 }
493
494 /**
495 * @VirtualProperty
496 * @SerializedName("user_name")
497 */
498 public function getUserName()
499 {
500 return $this->user->getUserName();
501 }
502
503 /**
504 * @VirtualProperty
505 * @SerializedName("user_email")
506 */
507 public function getUserEmail()
508 {
509 return $this->user->getEmail();
510 }
511
512 /**
513 * @VirtualProperty
514 * @SerializedName("user_id")
515 */
516 public function getUserId()
517 {
518 return $this->user->getId();
519 }
520
521 /**
522 * Set created_at.
523 * Only used when importing data from an other service.
524 *
525 * @param \DateTime $createdAt
526 *
527 * @return Entry
528 */
529 public function setCreatedAt(\DateTime $createdAt)
530 {
531 $this->createdAt = $createdAt;
532
533 return $this;
534 }
535
536 /**
537 * @return \DateTime
538 */
539 public function getCreatedAt()
540 {
541 return $this->createdAt;
542 }
543
544 /**
545 * @return \DateTime
546 */
547 public function getUpdatedAt()
548 {
549 return $this->updatedAt;
550 }
551
552 /**
553 * @return \DateTime|null
554 */
555 public function getStarredAt()
556 {
557 return $this->starredAt;
558 }
559
560 /**
561 * @param \DateTime|null $starredAt
562 *
563 * @return Entry
564 */
565 public function setStarredAt($starredAt = null)
566 {
567 $this->starredAt = $starredAt;
568
569 return $this;
570 }
571
572 /**
573 * update isStarred and starred_at fields.
574 *
575 * @param bool $isStarred
576 *
577 * @return Entry
578 */
579 public function updateStar($isStarred = false)
580 {
581 $this->setStarred($isStarred);
582 $this->setStarredAt(null);
583 if ($this->isStarred()) {
584 $this->setStarredAt(new \DateTime());
585 }
586
587 return $this;
588 }
589
590 /**
591 * @return ArrayCollection<Annotation>
592 */
593 public function getAnnotations()
594 {
595 return $this->annotations;
596 }
597
598 /**
599 * @param Annotation $annotation
600 */
601 public function setAnnotation(Annotation $annotation)
602 {
603 $this->annotations[] = $annotation;
604 }
605
606 /**
607 * @return string
608 */
609 public function getMimetype()
610 {
611 return $this->mimetype;
612 }
613
614 /**
615 * @param string $mimetype
616 */
617 public function setMimetype($mimetype)
618 {
619 $this->mimetype = $mimetype;
620 }
621
622 /**
623 * @return int
624 */
625 public function getReadingTime()
626 {
627 return $this->readingTime;
628 }
629
630 /**
631 * @param int $readingTime
632 */
633 public function setReadingTime($readingTime)
634 {
635 $this->readingTime = $readingTime;
636 }
637
638 /**
639 * @return string
640 */
641 public function getDomainName()
642 {
643 return $this->domainName;
644 }
645
646 /**
647 * @param string $domainName
648 */
649 public function setDomainName($domainName)
650 {
651 $this->domainName = $domainName;
652 }
653
654 /**
655 * @return ArrayCollection
656 */
657 public function getTags()
658 {
659 return $this->tags;
660 }
661
662 /**
663 * @VirtualProperty
664 * @SerializedName("tags")
665 * @Groups({"entries_for_user", "export_all"})
666 */
667 public function getSerializedTags()
668 {
669 $data = [];
670 foreach ($this->tags as $tag) {
671 $data[] = $tag->getLabel();
672 }
673
674 return $data;
675 }
676
677 /**
678 * @param Tag $tag
679 */
680 public function addTag(Tag $tag)
681 {
682 if ($this->tags->contains($tag)) {
683 return;
684 }
685
686 // check if tag already exist but has not yet be persisted
687 // it seems that the previous condition with `contains()` doesn't check that case
688 foreach ($this->tags as $existingTag) {
689 if ($existingTag->getLabel() === $tag->getLabel()) {
690 return;
691 }
692 }
693
694 $this->tags->add($tag);
695 $tag->addEntry($this);
696 }
697
698 /**
699 * Remove the given tag from the entry (if the tag is associated).
700 *
701 * @param Tag $tag
702 */
703 public function removeTag(Tag $tag)
704 {
705 if (!$this->tags->contains($tag)) {
706 return;
707 }
708
709 $this->tags->removeElement($tag);
710 $tag->removeEntry($this);
711 }
712
713 /**
714 * Remove all assigned tags from the entry.
715 */
716 public function removeAllTags()
717 {
718 foreach ($this->tags as $tag) {
719 $this->tags->removeElement($tag);
720 $tag->removeEntry($this);
721 }
722 }
723
724 /**
725 * Set previewPicture.
726 *
727 * @param string $previewPicture
728 *
729 * @return Entry
730 */
731 public function setPreviewPicture($previewPicture)
732 {
733 $this->previewPicture = $previewPicture;
734
735 return $this;
736 }
737
738 /**
739 * Get previewPicture.
740 *
741 * @return string
742 */
743 public function getPreviewPicture()
744 {
745 return $this->previewPicture;
746 }
747
748 /**
749 * Set language.
750 *
751 * @param string $language
752 *
753 * @return Entry
754 */
755 public function setLanguage($language)
756 {
757 $this->language = $language;
758
759 return $this;
760 }
761
762 /**
763 * Get language.
764 *
765 * @return string
766 */
767 public function getLanguage()
768 {
769 return $this->language;
770 }
771
772 /**
773 * @return string
774 */
775 public function getUid()
776 {
777 return $this->uid;
778 }
779
780 /**
781 * @param string $uid
782 *
783 * @return Entry
784 */
785 public function setUid($uid)
786 {
787 $this->uid = $uid;
788
789 return $this;
790 }
791
792 public function generateUid()
793 {
794 if (null === $this->uid) {
795 // @see http://blog.kevingomez.fr/til/2015/07/26/why-is-uniqid-slow/ for true parameter
796 $this->uid = uniqid('', true);
797 }
798 }
799
800 public function cleanUid()
801 {
802 $this->uid = null;
803 }
804
805 /**
806 * Used in the entries filter so it's more explicit for the end user than the uid.
807 * Also used in the API.
808 *
809 * @VirtualProperty
810 * @SerializedName("is_public")
811 * @Groups({"entries_for_user"})
812 *
813 * @return bool
814 */
815 public function isPublic()
816 {
817 return null !== $this->uid;
818 }
819
820 /**
821 * @return string
822 */
823 public function getHttpStatus()
824 {
825 return $this->httpStatus;
826 }
827
828 /**
829 * @param string $httpStatus
830 *
831 * @return Entry
832 */
833 public function setHttpStatus($httpStatus)
834 {
835 $this->httpStatus = $httpStatus;
836
837 return $this;
838 }
839
840 /**
841 * @return \Datetime
842 */
843 public function getPublishedAt()
844 {
845 return $this->publishedAt;
846 }
847
848 /**
849 * @param \Datetime $publishedAt
850 *
851 * @return Entry
852 */
853 public function setPublishedAt(\Datetime $publishedAt)
854 {
855 $this->publishedAt = $publishedAt;
856
857 return $this;
858 }
859
860 /**
861 * @return array
862 */
863 public function getPublishedBy()
864 {
865 return $this->publishedBy;
866 }
867
868 /**
869 * @param array $publishedBy
870 *
871 * @return Entry
872 */
873 public function setPublishedBy($publishedBy)
874 {
875 $this->publishedBy = $publishedBy;
876
877 return $this;
878 }
879
880 /**
881 * @return array
882 */
883 public function getHeaders()
884 {
885 return $this->headers;
886 }
887
888 /**
889 * @param array $headers
890 *
891 * @return Entry
892 */
893 public function setHeaders($headers)
894 {
895 $this->headers = $headers;
896
897 return $this;
898 }
899
900 /**
901 * Set origin url.
902 *
903 * @param string $originUrl
904 *
905 * @return Entry
906 */
907 public function setOriginUrl($originUrl)
908 {
909 $this->originUrl = $originUrl;
910
911 return $this;
912 }
913
914 /**
915 * Get origin url.
916 *
917 * @return string
918 */
919 public function getOriginUrl()
920 {
921 return $this->originUrl;
922 }
923
924 /**
925 * @return string
926 */
927 public function getHashedUrl()
928 {
929 return $this->hashedUrl;
930 }
931
932 /**
933 * @param mixed $hashedUrl
934 *
935 * @return Entry
936 */
937 public function setHashedUrl($hashedUrl)
938 {
939 $this->hashedUrl = $hashedUrl;
940
941 return $this;
942 }
943 }