]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
start work on user-shares share-articles-to-other-users 3121/head
authorThomas Citharel <tcit@tcit.fr>
Mon, 15 May 2017 09:12:33 +0000 (11:12 +0200)
committerThomas Citharel <tcit@tcit.fr>
Thu, 25 May 2017 17:10:48 +0000 (19:10 +0200)
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
src/Wallabag/CoreBundle/Controller/ShareController.php [new file with mode: 0644]
src/Wallabag/CoreBundle/Entity/Notification.php
src/Wallabag/CoreBundle/Entity/Share.php [new file with mode: 0644]

diff --git a/src/Wallabag/CoreBundle/Controller/ShareController.php b/src/Wallabag/CoreBundle/Controller/ShareController.php
new file mode 100644 (file)
index 0000000..bd1246c
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+
+namespace Wallabag\CoreBundle\Controller;
+
+use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
+use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\Security\Core\Exception\AccessDeniedException;
+use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
+use Wallabag\CoreBundle\Entity\Entry;
+use Wallabag\CoreBundle\Entity\Notification;
+use Wallabag\CoreBundle\Entity\Share;
+use Wallabag\CoreBundle\Event\EntrySavedEvent;
+use Wallabag\CoreBundle\Notifications\Action;
+use Wallabag\CoreBundle\Notifications\NoAction;
+use Wallabag\CoreBundle\Notifications\YesAction;
+use Wallabag\UserBundle\Entity\User;
+
+class ShareController extends Controller
+{
+    /**
+     * @Route("/share-user/{entry}/{destination}", name="share-entry-user", requirements={"entry" = "\d+", "destination" = "\d+"})
+     * @param Entry $entry
+     * @param User $destination
+     * @throws AccessDeniedException
+     * @throws InvalidArgumentException
+     */
+    public function shareEntryAction(Entry $entry, User $destination)
+    {
+
+        if ($entry->getUser() !== $this->getUser()) {
+            throw new AccessDeniedException("You can't share this entry");
+        }
+
+        if ($destination === $this->getUser()) {
+            throw new InvalidArgumentException("You can't share entries to yourself");
+        }
+
+        $share = new Share();
+        $share->setUserOrigin($this->getUser())
+            ->setEntry($entry)
+            ->setUserDestination($destination);
+
+        $em = $this->getDoctrine()->getManager();
+        $em->persist($share);
+        $em->flush();
+
+        $accept = new YesAction($this->generateUrl('share-entry-user-accept', ['share' => $share->getId()]));
+
+        $deny = new NoAction($this->generateUrl('share-entry-user-refuse', ['share' => $share->getId()]));
+
+        $notification = new Notification($destination);
+        $notification->setType(Notification::TYPE_SHARE)
+            ->setTitle($this->get('translator')->trans('share.notification.new.title'))
+            ->addAction($accept)
+            ->addAction($deny);
+
+        $em->persist($notification);
+        $em->flush();
+
+        $this->redirectToRoute('view', ['id' => $entry->getId()]);
+    }
+
+    /**
+     * @Route("/share-user/accept/{share}", name="share-entry-user-accept")
+     *
+     * @param Share $share
+     * @return RedirectResponse
+     * @throws AccessDeniedException
+     */
+    public function acceptShareAction(Share $share)
+    {
+        if ($share->getUserDestination() !== $this->getUser()) {
+            throw new AccessDeniedException("You can't accept this entry");
+        }
+
+        $entry = new Entry($this->getUser());
+        $entry->setUrl($share->getEntry()->getUrl());
+
+        $em = $this->getDoctrine()->getManager();
+
+        if (false === $this->checkIfEntryAlreadyExists($entry)) {
+            $this->updateEntry($entry);
+
+            $em->persist($entry);
+            $em->flush();
+
+            // entry saved, dispatch event about it!
+            $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry));
+        }
+
+        $em->remove($share);
+        $em->flush(); // we keep the previous flush above in case the event dispatcher would lead in using the saved entry
+
+        return $this->redirect($this->generateUrl('homepage'));
+    }
+
+    /**
+     * @Route("/share-user/refuse/{share}", name="share-entry-user-refuse")
+     *
+     * @param Share $share
+     * @return RedirectResponse
+     */
+    public function refuseShareAction(Share $share)
+    {
+        $em = $this->getDoctrine()->getManager();
+        $em->remove($share);
+        $em->flush();
+
+        return $this->redirect($this->generateUrl('homepage'));
+    }
+
+    /**
+     * Fetch content and update entry.
+     * In case it fails, entry will return to avod loosing the data.
+     *
+     * @param Entry  $entry
+     * @param string $prefixMessage Should be the translation key: entry_saved or entry_reloaded
+     *
+     * @return Entry
+     */
+    private function updateEntry(Entry $entry, $prefixMessage = 'entry_saved')
+    {
+        // put default title in case of fetching content failed
+        $entry->setTitle('No title found');
+
+        $message = 'flashes.entry.notice.'.$prefixMessage;
+
+        try {
+            $entry = $this->get('wallabag_core.content_proxy')->updateEntry($entry, $entry->getUrl());
+        } catch (\Exception $e) {
+            $this->get('logger')->error('Error while saving an entry', [
+                'exception' => $e,
+                'entry' => $entry,
+            ]);
+
+            $message = 'flashes.entry.notice.'.$prefixMessage.'_failed';
+        }
+
+        $this->get('session')->getFlashBag()->add('notice', $message);
+
+        return $entry;
+    }
+
+    /**
+     * Check for existing entry, if it exists, redirect to it with a message.
+     *
+     * @param Entry $entry
+     *
+     * @return Entry|bool
+     */
+    private function checkIfEntryAlreadyExists(Entry $entry)
+    {
+        return $this->get('wallabag_core.entry_repository')->findByUrlAndUserId($entry->getUrl(), $this->getUser()->getId());
+    }
+}
index e1c1b449516f970a33e99f34415c007b005f7466..26e398006317f07dbea14429a8875f00bcd98e3a 100644 (file)
@@ -77,6 +77,7 @@ class Notification implements NotificationInterface {
     const TYPE_ADMIN = 0;
     const TYPE_USER = 1;
     const TYPE_RELEASE = 2;
+    const TYPE_SHARE = 3;
 
     public function __construct(User $user = null)
     {
diff --git a/src/Wallabag/CoreBundle/Entity/Share.php b/src/Wallabag/CoreBundle/Entity/Share.php
new file mode 100644 (file)
index 0000000..d1db5eb
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+
+namespace Wallabag\CoreBundle\Entity;
+
+use Wallabag\UserBundle\Entity\User;
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * Share.
+ *
+ * @ORM\Entity
+ */
+class Share
+{
+    /**
+     * @var int
+     *
+     * @ORM\Column(name="id", type="integer")
+     * @ORM\Id
+     * @ORM\GeneratedValue(strategy="AUTO")
+     */
+    private $id;
+
+    /**
+     * @var User
+     *
+     * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User")
+     */
+    private $userOrigin;
+
+    /**
+     * @var User
+     *
+     * @ORM\ManyToOne(targetEntity="Wallabag\UserBundle\Entity\User")
+     */
+    private $userDestination;
+
+    /**
+     * @var Entry
+     *
+     * @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\Entry")
+     */
+    private $entry;
+
+    /**
+     * @var boolean
+     *
+     * @ORM\Column(name="accepted", type="boolean")
+     */
+    private $accepted;
+
+    /**
+     * Share constructor.
+     */
+    public function __construct()
+    {
+        $this->accepted = false;
+    }
+
+    /**
+     * @return int
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * @return User
+     */
+    public function getUserOrigin()
+    {
+        return $this->userOrigin;
+    }
+
+    /**
+     * @param User $userOrigin
+     * @return Share
+     */
+    public function setUserOrigin(User $userOrigin)
+    {
+        $this->userOrigin = $userOrigin;
+        return $this;
+    }
+
+    /**
+     * @return User
+     */
+    public function getUserDestination()
+    {
+        return $this->userDestination;
+    }
+
+    /**
+     * @param User $userDestination
+     * @return Share
+     */
+    public function setUserDestination(User $userDestination)
+    {
+        $this->userDestination = $userDestination;
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isAccepted()
+    {
+        return $this->accepted;
+    }
+
+    /**
+     * @param bool $accepted
+     * @return Share
+     */
+    public function setAccepted($accepted)
+    {
+        $this->accepted = $accepted;
+        return $this;
+    }
+
+    /**
+     * @return Entry
+     */
+    public function getEntry()
+    {
+        return $this->entry;
+    }
+
+    /**
+     * @param Entry $entry
+     * @return Share
+     */
+    public function setEntry(Entry $entry)
+    {
+        $this->entry = $entry;
+        return $this;
+    }
+}