aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorThomas Citharel <tcit@tcit.fr>2017-05-15 11:12:33 +0200
committerThomas Citharel <tcit@tcit.fr>2017-05-25 19:10:48 +0200
commit7f699602655aaa9d90bbf5a76cf33f84837d444b (patch)
treeaedf99095e2c1e79168b13776ca2439f95fbe4b3
parent4fa9470f36b9dc8b000b06c7742c921a1df71e42 (diff)
downloadwallabag-share-articles-to-other-users.tar.gz
wallabag-share-articles-to-other-users.tar.zst
wallabag-share-articles-to-other-users.zip
start work on user-sharesshare-articles-to-other-users
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
-rw-r--r--src/Wallabag/CoreBundle/Controller/ShareController.php156
-rw-r--r--src/Wallabag/CoreBundle/Entity/Notification.php1
-rw-r--r--src/Wallabag/CoreBundle/Entity/Share.php139
3 files changed, 296 insertions, 0 deletions
diff --git a/src/Wallabag/CoreBundle/Controller/ShareController.php b/src/Wallabag/CoreBundle/Controller/ShareController.php
new file mode 100644
index 00000000..bd1246c7
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Controller/ShareController.php
@@ -0,0 +1,156 @@
1<?php
2
3namespace Wallabag\CoreBundle\Controller;
4
5use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
6use Symfony\Bundle\FrameworkBundle\Controller\Controller;
7use Symfony\Component\HttpFoundation\RedirectResponse;
8use Symfony\Component\Security\Core\Exception\AccessDeniedException;
9use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
10use Wallabag\CoreBundle\Entity\Entry;
11use Wallabag\CoreBundle\Entity\Notification;
12use Wallabag\CoreBundle\Entity\Share;
13use Wallabag\CoreBundle\Event\EntrySavedEvent;
14use Wallabag\CoreBundle\Notifications\Action;
15use Wallabag\CoreBundle\Notifications\NoAction;
16use Wallabag\CoreBundle\Notifications\YesAction;
17use Wallabag\UserBundle\Entity\User;
18
19class ShareController extends Controller
20{
21 /**
22 * @Route("/share-user/{entry}/{destination}", name="share-entry-user", requirements={"entry" = "\d+", "destination" = "\d+"})
23 * @param Entry $entry
24 * @param User $destination
25 * @throws AccessDeniedException
26 * @throws InvalidArgumentException
27 */
28 public function shareEntryAction(Entry $entry, User $destination)
29 {
30
31 if ($entry->getUser() !== $this->getUser()) {
32 throw new AccessDeniedException("You can't share this entry");
33 }
34
35 if ($destination === $this->getUser()) {
36 throw new InvalidArgumentException("You can't share entries to yourself");
37 }
38
39 $share = new Share();
40 $share->setUserOrigin($this->getUser())
41 ->setEntry($entry)
42 ->setUserDestination($destination);
43
44 $em = $this->getDoctrine()->getManager();
45 $em->persist($share);
46 $em->flush();
47
48 $accept = new YesAction($this->generateUrl('share-entry-user-accept', ['share' => $share->getId()]));
49
50 $deny = new NoAction($this->generateUrl('share-entry-user-refuse', ['share' => $share->getId()]));
51
52 $notification = new Notification($destination);
53 $notification->setType(Notification::TYPE_SHARE)
54 ->setTitle($this->get('translator')->trans('share.notification.new.title'))
55 ->addAction($accept)
56 ->addAction($deny);
57
58 $em->persist($notification);
59 $em->flush();
60
61 $this->redirectToRoute('view', ['id' => $entry->getId()]);
62 }
63
64 /**
65 * @Route("/share-user/accept/{share}", name="share-entry-user-accept")
66 *
67 * @param Share $share
68 * @return RedirectResponse
69 * @throws AccessDeniedException
70 */
71 public function acceptShareAction(Share $share)
72 {
73 if ($share->getUserDestination() !== $this->getUser()) {
74 throw new AccessDeniedException("You can't accept this entry");
75 }
76
77 $entry = new Entry($this->getUser());
78 $entry->setUrl($share->getEntry()->getUrl());
79
80 $em = $this->getDoctrine()->getManager();
81
82 if (false === $this->checkIfEntryAlreadyExists($entry)) {
83 $this->updateEntry($entry);
84
85 $em->persist($entry);
86 $em->flush();
87
88 // entry saved, dispatch event about it!
89 $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
90 }
91
92 $em->remove($share);
93 $em->flush(); // we keep the previous flush above in case the event dispatcher would lead in using the saved entry
94
95 return $this->redirect($this->generateUrl('homepage'));
96 }
97
98 /**
99 * @Route("/share-user/refuse/{share}", name="share-entry-user-refuse")
100 *
101 * @param Share $share
102 * @return RedirectResponse
103 */
104 public function refuseShareAction(Share $share)
105 {
106 $em = $this->getDoctrine()->getManager();
107 $em->remove($share);
108 $em->flush();
109
110 return $this->redirect($this->generateUrl('homepage'));
111 }
112
113 /**
114 * Fetch content and update entry.
115 * In case it fails, entry will return to avod loosing the data.
116 *
117 * @param Entry $entry
118 * @param string $prefixMessage Should be the translation key: entry_saved or entry_reloaded
119 *
120 * @return Entry
121 */
122 private function updateEntry(Entry $entry, $prefixMessage = 'entry_saved')
123 {
124 // put default title in case of fetching content failed
125 $entry->setTitle('No title found');
126
127 $message = 'flashes.entry.notice.'.$prefixMessage;
128
129 try {
130 $entry = $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl());
131 } catch (\Exception $e) {
132 $this->get('logger')->error('Error while saving an entry', [
133 'exception' => $e,
134 'entry' => $entry,
135 ]);
136
137 $message = 'flashes.entry.notice.'.$prefixMessage.'_failed';
138 }
139
140 $this->get('session')->getFlashBag()->add('notice', $message);
141
142 return $entry;
143 }
144
145 /**
146 * Check for existing entry, if it exists, redirect to it with a message.
147 *
148 * @param Entry $entry
149 *
150 * @return Entry|bool
151 */
152 private function checkIfEntryAlreadyExists(Entry $entry)
153 {
154 return $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($entry->getUrl(), $this->getUser()->getId());
155 }
156}
diff --git a/src/Wallabag/CoreBundle/Entity/Notification.php b/src/Wallabag/CoreBundle/Entity/Notification.php
index e1c1b449..26e39800 100644
--- a/src/Wallabag/CoreBundle/Entity/Notification.php
+++ b/src/Wallabag/CoreBundle/Entity/Notification.php
@@ -77,6 +77,7 @@ class Notification implements NotificationInterface {
77 const TYPE_ADMIN = 0; 77 const TYPE_ADMIN = 0;
78 const TYPE_USER = 1; 78 const TYPE_USER = 1;
79 const TYPE_RELEASE = 2; 79 const TYPE_RELEASE = 2;
80 const TYPE_SHARE = 3;
80 81
81 public function __construct(User $user = null) 82 public function __construct(User $user = null)
82 { 83 {
diff --git a/src/Wallabag/CoreBundle/Entity/Share.php b/src/Wallabag/CoreBundle/Entity/Share.php
new file mode 100644
index 00000000..d1db5eb0
--- /dev/null
+++ b/src/Wallabag/CoreBundle/Entity/Share.php
@@ -0,0 +1,139 @@
1<?php
2
3namespace Wallabag\CoreBundle\Entity;
4
5use Wallabag\UserBundle\Entity\User;
6use Doctrine\ORM\Mapping as ORM;
7
8/**
9 * Share.
10 *
11 * @ORM\Entity
12 */
13class Share
14{
15 /**
16 * @var int
17 *
18 * @ORM\Column(name="id", type="integer")
19 * @ORM\Id
20 * @ORM\GeneratedValue(strategy="AUTO")
21 */
22 private $id;
23
24 /**
25 * @var User
26 *
27 * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User")
28 */
29 private $userOrigin;
30
31 /**
32 * @var User
33 *
34 * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User")
35 */
36 private $userDestination;
37
38 /**
39 * @var Entry
40 *
41 * @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\Entry")
42 */
43 private $entry;
44
45 /**
46 * @var boolean
47 *
48 * @ORM\Column(name="accepted", type="boolean")
49 */
50 private $accepted;
51
52 /**
53 * Share constructor.
54 */
55 public function __construct()
56 {
57 $this->accepted = false;
58 }
59
60 /**
61 * @return int
62 */
63 public function getId()
64 {
65 return $this->id;
66 }
67
68 /**
69 * @return User
70 */
71 public function getUserOrigin()
72 {
73 return $this->userOrigin;
74 }
75
76 /**
77 * @param User $userOrigin
78 * @return Share
79 */
80 public function setUserOrigin(User $userOrigin)
81 {
82 $this->userOrigin = $userOrigin;
83 return $this;
84 }
85
86 /**
87 * @return User
88 */
89 public function getUserDestination()
90 {
91 return $this->userDestination;
92 }
93
94 /**
95 * @param User $userDestination
96 * @return Share
97 */
98 public function setUserDestination(User $userDestination)
99 {
100 $this->userDestination = $userDestination;
101 return $this;
102 }
103
104 /**
105 * @return bool
106 */
107 public function isAccepted()
108 {
109 return $this->accepted;
110 }
111
112 /**
113 * @param bool $accepted
114 * @return Share
115 */
116 public function setAccepted($accepted)
117 {
118 $this->accepted = $accepted;
119 return $this;
120 }
121
122 /**
123 * @return Entry
124 */
125 public function getEntry()
126 {
127 return $this->entry;
128 }
129
130 /**
131 * @param Entry $entry
132 * @return Share
133 */
134 public function setEntry(Entry $entry)
135 {
136 $this->entry = $entry;
137 return $this;
138 }
139}