From 61351218f90df455c6edcc530bfc746d60b43a12 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Fri, 24 Feb 2017 11:34:36 +0100 Subject: Save changes PHP CS Fixed Events on changes Renamed field First draft for migration (create table Change) Added setter for tag in EntryTaggedEvent Fixed migration for Change table Added API route for entry history Removed deletion history --- app/DoctrineMigrations/Version20170328185535.php | 99 ++++++++++++++++++++++ .../ApiBundle/Controller/EntryRestController.php | 35 +++++++- .../CoreBundle/Controller/EntryController.php | 10 ++- .../CoreBundle/Controller/TagController.php | 7 +- src/Wallabag/CoreBundle/Entity/Change.php | 86 +++++++++++++++++++ src/Wallabag/CoreBundle/Entity/Entry.php | 6 ++ src/Wallabag/CoreBundle/Event/EntryTaggedEvent.php | 42 +++++++++ .../CoreBundle/Event/EntryUpdatedEvent.php | 26 ++++++ .../Event/Subscriber/ChangesSubscriber.php | 59 +++++++++++++ .../CoreBundle/Repository/ChangeRepository.php | 26 ++++++ .../CoreBundle/Resources/config/services.yml | 8 ++ 11 files changed, 397 insertions(+), 7 deletions(-) create mode 100644 app/DoctrineMigrations/Version20170328185535.php create mode 100644 src/Wallabag/CoreBundle/Entity/Change.php create mode 100644 src/Wallabag/CoreBundle/Event/EntryTaggedEvent.php create mode 100644 src/Wallabag/CoreBundle/Event/EntryUpdatedEvent.php create mode 100644 src/Wallabag/CoreBundle/Event/Subscriber/ChangesSubscriber.php create mode 100644 src/Wallabag/CoreBundle/Repository/ChangeRepository.php diff --git a/app/DoctrineMigrations/Version20170328185535.php b/app/DoctrineMigrations/Version20170328185535.php new file mode 100644 index 00000000..f0afb7b9 --- /dev/null +++ b/app/DoctrineMigrations/Version20170328185535.php @@ -0,0 +1,99 @@ +container = $container; + } + + private function getTable($tableName) + { + return $this->container->getParameter('database_table_prefix').$tableName; + } + + /** + * @param Schema $schema + */ + public function up(Schema $schema) + { + try { + $schema->getTable($this->getTable('change')); + } catch (SchemaException $e) { + // The Change table doesn't exist, we need to create it + if (10 == $e->getCode()) { + if ($this->connection->getDatabasePlatform()->getName() == 'sqlite') { + $this->addSql('CREATE TABLE '.$this->getTable('change').' (id INTEGER NOT NULL, entry_id INTEGER DEFAULT NULL, type INTEGER NOT NULL, created_at DATETIME NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_133B9D0FBA364942 FOREIGN KEY (entry_id) REFERENCES '.$this->getTable('entry').' (id) NOT DEFERRABLE INITIALLY IMMEDIATE)'); + + return true; + } + + $changeTable = $schema->createTable($this->getTable('change')); + $changeTable->addColumn( + 'id', + 'integer', + ['autoincrement' => true] + ); + $changeTable->addColumn( + 'type', + 'integer', + ['notnull' => false] + ); + $changeTable->addColumn( + 'created_at', + 'datetime', + ['notnull' => false] + ); + $changeTable->addColumn( + 'entry_id', + 'integer', + ['notnull' => false] + ); + + $changeTable->setPrimaryKey(['id']); + + $changeTable->addForeignKeyConstraint( + $this->getTable('entry'), + ['entry_id'], + ['id'], + ['onDelete' => 'CASCADE'], + 'IDX_change_entry' + ); + + return true; + } + } + + throw new SkipMigrationException('It seems that you already played this migration.'); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + try { + $changeTable = $schema->getTable($this->getTable('change')); + $schema->dropTable($changeTable->getName()); + } catch (SchemaException $e) { + throw new SkipMigrationException('It seems that you already played this migration.'); + } + } +} diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php index 31bb67fd..2cf562bc 100644 --- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php +++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php @@ -12,7 +12,8 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; use Wallabag\CoreBundle\Event\EntrySavedEvent; -use Wallabag\CoreBundle\Event\EntryDeletedEvent; +use Wallabag\CoreBundle\Event\EntryTaggedEvent; +use Wallabag\CoreBundle\Event\EntryUpdatedEvent; class EntryRestController extends WallabagRestController { @@ -385,6 +386,8 @@ class EntryRestController extends WallabagRestController $em = $this->getDoctrine()->getManager(); $em->flush(); + $this->get('event_dispatcher')->dispatch(EntryUpdatedEvent::NAME, new EntryUpdatedEvent($entry)); + return $this->sendResponse($entry); } @@ -426,6 +429,7 @@ class EntryRestController extends WallabagRestController $em->flush(); // entry saved, dispatch event about it! + $this->get('event_dispatcher')->dispatch(EntryUpdatedEvent::NAME, new EntryUpdatedEvent($entry)); $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); return $this->sendResponse($entry); @@ -496,14 +500,17 @@ class EntryRestController extends WallabagRestController $this->validateUserAccess($entry->getUser()->getId()); $tags = $request->request->get('tags', ''); + $tagsEntries = []; if (!empty($tags)) { - $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); + $tagsEntries = $this->get('wallabag_core.tags_assigner')->assignTagsToEntry($entry, $tags); } $em = $this->getDoctrine()->getManager(); $em->persist($entry); $em->flush(); + $this->get('event_dispatcher')->dispatch(EntryTaggedEvent::NAME, new EntryTaggedEvent($entry, $tagsEntries)); + return $this->sendResponse($entry); } @@ -650,4 +657,28 @@ class EntryRestController extends WallabagRestController return (new JsonResponse())->setJson($json); } + + /** + * Gets history since a date. + * + * @ApiDoc( + * parameters={ + * {"name"="since", "dataType"="integer", "required"=true, "format"="A timestamp", "description"="Timestamp of the history's start"}, + * } + * ) + * + * @return JsonResponse + */ + public function getEntriesHistoryAction(Request $request) + { + $this->validateAuthentication(); + + $res = $this->getDoctrine() + ->getRepository('WallabagCoreBundle:Change') + ->findChangesSinceDate($request->query->get('since')); + + $json = $this->get('serializer')->serialize($res, 'json'); + + return (new JsonResponse())->setJson($json); + } } diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index 8d2ac6d4..2a287825 100644 --- a/src/Wallabag/CoreBundle/Controller/EntryController.php +++ b/src/Wallabag/CoreBundle/Controller/EntryController.php @@ -9,12 +9,12 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Wallabag\CoreBundle\Entity\Entry; +use Wallabag\CoreBundle\Event\EntryUpdatedEvent; use Wallabag\CoreBundle\Form\Type\EntryFilterType; use Wallabag\CoreBundle\Form\Type\EditEntryType; use Wallabag\CoreBundle\Form\Type\NewEntryType; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; use Wallabag\CoreBundle\Event\EntrySavedEvent; -use Wallabag\CoreBundle\Event\EntryDeletedEvent; use Wallabag\CoreBundle\Form\Type\SearchEntryType; class EntryController extends Controller @@ -391,6 +391,7 @@ class EntryController extends Controller $em->flush(); // entry saved, dispatch event about it! + $this->get('event_dispatcher')->dispatch(EntryUpdatedEvent::NAME, new EntryUpdatedEvent($entry)); $this->get('event_dispatcher')->dispatch(EntrySavedEvent::NAME, new EntrySavedEvent($entry)); return $this->redirect($this->generateUrl('view', ['id' => $entry->getId()])); @@ -413,6 +414,8 @@ class EntryController extends Controller $entry->toggleArchive(); $this->getDoctrine()->getManager()->flush(); + $this->get('event_dispatcher')->dispatch(EntryUpdatedEvent::NAME, new EntryUpdatedEvent($entry)); + $message = 'flashes.entry.notice.entry_unarchived'; if ($entry->isArchived()) { $message = 'flashes.entry.notice.entry_archived'; @@ -445,6 +448,8 @@ class EntryController extends Controller $entry->toggleStar(); $this->getDoctrine()->getManager()->flush(); + $this->get('event_dispatcher')->dispatch(EntryUpdatedEvent::NAME, new EntryUpdatedEvent($entry)); + $message = 'flashes.entry.notice.entry_unstarred'; if ($entry->isStarred()) { $message = 'flashes.entry.notice.entry_starred'; @@ -481,9 +486,6 @@ class EntryController extends Controller UrlGeneratorInterface::ABSOLUTE_PATH ); - // entry deleted, dispatch event about it! - $this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry)); - $em = $this->getDoctrine()->getManager(); $em->remove($entry); $em->flush(); diff --git a/src/Wallabag/CoreBundle/Controller/TagController.php b/src/Wallabag/CoreBundle/Controller/TagController.php index fb6a720b..e6d55931 100644 --- a/src/Wallabag/CoreBundle/Controller/TagController.php +++ b/src/Wallabag/CoreBundle/Controller/TagController.php @@ -9,6 +9,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; +use Wallabag\CoreBundle\Event\EntryTaggedEvent; use Wallabag\CoreBundle\Form\Type\NewTagType; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; @@ -28,7 +29,7 @@ class TagController extends Controller $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $this->get('wallabag_core.tags_assigner')->assignTagsToEntry( + $tags = $this->get('wallabag_core.tags_assigner')->assignTagsToEntry( $entry, $form->get('label')->getData() ); @@ -37,6 +38,8 @@ class TagController extends Controller $em->persist($entry); $em->flush(); + $this->get('event_dispatcher')->dispatch(EntryTaggedEvent::NAME, new EntryTaggedEvent($entry, $tags)); + $this->get('session')->getFlashBag()->add( 'notice', 'flashes.tag.notice.tag_added' @@ -64,6 +67,8 @@ class TagController extends Controller $em = $this->getDoctrine()->getManager(); $em->flush(); + $this->get('event_dispatcher')->dispatch(EntryTaggedEvent::NAME, new EntryTaggedEvent($entry, $tag)); + // remove orphan tag in case no entries are associated to it if (count($tag->getEntries()) === 0) { $em->remove($tag); diff --git a/src/Wallabag/CoreBundle/Entity/Change.php b/src/Wallabag/CoreBundle/Entity/Change.php new file mode 100644 index 00000000..203a2d31 --- /dev/null +++ b/src/Wallabag/CoreBundle/Entity/Change.php @@ -0,0 +1,86 @@ +type = $type; + $this->entry = $entry; + $this->createdAt = new \DateTime(); + } + + /** + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * @return int + */ + public function getType() + { + return $this->type; + } + + /** + * @return DateTime + */ + public function getCreatedAt() + { + return $this->createdAt; + } + + /** + * @return Entry + */ + public function getEntry() + { + return $this->entry; + } +} diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index 08a67c34..a24409b9 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php @@ -233,6 +233,11 @@ class Entry */ private $tags; + /** + * @ORM\OneToMany(targetEntity="Wallabag\CoreBundle\Entity\Change", mappedBy="entry", cascade={"remove"}) + */ + private $changes; + /* * @param User $user */ @@ -240,6 +245,7 @@ class Entry { $this->user = $user; $this->tags = new ArrayCollection(); + $this->changes = new ArrayCollection(); } /** diff --git a/src/Wallabag/CoreBundle/Event/EntryTaggedEvent.php b/src/Wallabag/CoreBundle/Event/EntryTaggedEvent.php new file mode 100644 index 00000000..88856fb1 --- /dev/null +++ b/src/Wallabag/CoreBundle/Event/EntryTaggedEvent.php @@ -0,0 +1,42 @@ +entry = $entry; + + if (false === is_array($tags)) { + $tags = [$tags]; + } + + $this->tags = $tags; + } + + public function getEntry() + { + return $this->entry; + } + + public function getTags() + { + return $this->tags; + } +} diff --git a/src/Wallabag/CoreBundle/Event/EntryUpdatedEvent.php b/src/Wallabag/CoreBundle/Event/EntryUpdatedEvent.php new file mode 100644 index 00000000..7282835e --- /dev/null +++ b/src/Wallabag/CoreBundle/Event/EntryUpdatedEvent.php @@ -0,0 +1,26 @@ +entry = $entry; + } + + public function getEntry() + { + return $this->entry; + } +} diff --git a/src/Wallabag/CoreBundle/Event/Subscriber/ChangesSubscriber.php b/src/Wallabag/CoreBundle/Event/Subscriber/ChangesSubscriber.php new file mode 100644 index 00000000..1ba18a4f --- /dev/null +++ b/src/Wallabag/CoreBundle/Event/Subscriber/ChangesSubscriber.php @@ -0,0 +1,59 @@ +logger = $logger; + $this->em = $em; + } + + public static function getSubscribedEvents() + { + return [ + EntryUpdatedEvent::NAME => 'onEntryUpdated', + EntryTaggedEvent::NAME => 'onEntryTagged', + ]; + } + + /** + * @param EntryUpdatedEvent $event + */ + public function onEntryUpdated(EntryUpdatedEvent $event) + { + $change = new Change(Change::MODIFIED_TYPE, $event->getEntry()); + + $this->em->persist($change); + $this->em->flush(); + + $this->logger->debug('saved updated entry '.$event->getEntry()->getId().' event '); + } + + /** + * @param EntryTaggedEvent $event + */ + public function onEntryTagged(EntryTaggedEvent $event) + { + $change = new Change(Change::CHANGED_TAG_TYPE, $event->getEntry()); + + $this->em->persist($change); + $this->em->flush(); + + $this->logger->debug('saved (un)tagged entry '.$event->getEntry()->getId().' event '); + } +} diff --git a/src/Wallabag/CoreBundle/Repository/ChangeRepository.php b/src/Wallabag/CoreBundle/Repository/ChangeRepository.php new file mode 100644 index 00000000..18d015a7 --- /dev/null +++ b/src/Wallabag/CoreBundle/Repository/ChangeRepository.php @@ -0,0 +1,26 @@ +setTimestamp($timestamp); + + return $this->createQueryBuilder('c') + ->where('c.createdAt >= :timestamp')->setParameter('timestamp', $date) + ->getQuery() + ->getResult(); + } +} diff --git a/src/Wallabag/CoreBundle/Resources/config/services.yml b/src/Wallabag/CoreBundle/Resources/config/services.yml index a68b2fdc..0def87f3 100644 --- a/src/Wallabag/CoreBundle/Resources/config/services.yml +++ b/src/Wallabag/CoreBundle/Resources/config/services.yml @@ -199,3 +199,11 @@ services: wallabag_core.entry.download_images.client: class: GuzzleHttp\Client + + wallabag_core.subscriber.changes: + class: Wallabag\CoreBundle\Event\Subscriber\ChangesSubscriber + arguments: + - "@doctrine.orm.default_entity_manager" + - "@logger" + tags: + - { name: kernel.event_subscriber } -- cgit v1.2.3