From f38e03dc02c96344677fd2720912605b21c90b5d Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Sun, 7 Feb 2016 16:52:59 +0100 Subject: Comment work with annotator v2 - add missing annotator.js file and fix typo - edit & delete routes, started tests - basic tests --- .../Controller/WallabagCommentController.php | 146 +++++++++++ .../DataFixtures/ORM/LoadCommentData.php | 45 ++++ .../DependencyInjection/Configuration.php | 20 ++ .../WallabagCommentExtension.php | 23 ++ src/Wallabag/CommentBundle/Entity/Comment.php | 270 +++++++++++++++++++++ .../CommentBundle/Repository/CommentRepository.php | 94 +++++++ .../CommentBundle/Resources/config/routing.yml | 0 .../Resources/config/routing_comments.yml | 4 + .../CommentBundle/Resources/config/services.yml | 4 + .../Tests/Controller/CommentControllerTest.php | 81 +++++++ .../Tests/WallabagCommentTestCase.php | 63 +++++ .../CommentBundle/WallabagCommentBundle.php | 9 + 12 files changed, 759 insertions(+) create mode 100644 src/Wallabag/CommentBundle/Controller/WallabagCommentController.php create mode 100644 src/Wallabag/CommentBundle/DataFixtures/ORM/LoadCommentData.php create mode 100644 src/Wallabag/CommentBundle/DependencyInjection/Configuration.php create mode 100644 src/Wallabag/CommentBundle/DependencyInjection/WallabagCommentExtension.php create mode 100644 src/Wallabag/CommentBundle/Entity/Comment.php create mode 100644 src/Wallabag/CommentBundle/Repository/CommentRepository.php create mode 100644 src/Wallabag/CommentBundle/Resources/config/routing.yml create mode 100644 src/Wallabag/CommentBundle/Resources/config/routing_comments.yml create mode 100644 src/Wallabag/CommentBundle/Resources/config/services.yml create mode 100644 src/Wallabag/CommentBundle/Tests/Controller/CommentControllerTest.php create mode 100644 src/Wallabag/CommentBundle/Tests/WallabagCommentTestCase.php create mode 100644 src/Wallabag/CommentBundle/WallabagCommentBundle.php (limited to 'src/Wallabag/CommentBundle') diff --git a/src/Wallabag/CommentBundle/Controller/WallabagCommentController.php b/src/Wallabag/CommentBundle/Controller/WallabagCommentController.php new file mode 100644 index 00000000..be11f226 --- /dev/null +++ b/src/Wallabag/CommentBundle/Controller/WallabagCommentController.php @@ -0,0 +1,146 @@ +getDoctrine() + ->getRepository('WallabagCommentBundle:Comment') + ->findCommentsByPageId($entry->getId(), $this->getUser()->getId()); + $total = count($commentRows); + $comments = array('total' => $total, 'rows' => $commentRows); + + $json = $this->get('serializer')->serialize($comments, 'json'); + + return $this->renderJsonResponse($json); + } + + /** + * Creates a new comment. + * + * @param Entry $entry + * + * @ApiDoc( + * requirements={ + * {"name"="ranges", "dataType"="array", "requirement"="\w+", "description"="The range array for the annotation"}, + * {"name"="quote", "dataType"="string", "required"=false, "description"="Optional, quote for the comment"}, + * {"name"="text", "dataType"="string", "required"=true, "description"=""}, + * } + * ) + * + * @return Response + */ + public function postAnnotationAction(Request $request, Entry $entry) + { + $data = json_decode($request->getContent(), true); + + $em = $this->getDoctrine()->getManager(); + + $comment = new Comment($this->getUser()); + + $comment->setText($data['text']); + if (array_key_exists('quote', $data)) { + $comment->setQuote($data['quote']); + } + if (array_key_exists('ranges', $data)) { + $comment->setRanges($data['ranges']); + } + + $comment->setEntry($entry); + + $em->persist($comment); + $em->flush(); + + $json = $this->get('serializer')->serialize($comment, 'json'); + + return $this->renderJsonResponse($json); + } + + /** + * Updates a comment. + * + * @ApiDoc( + * requirements={ + * {"name"="comment", "dataType"="string", "requirement"="\w+", "description"="The comment ID"} + * } + * ) + * + * @ParamConverter("comment", class="WallabagCommentBundle:Comment") + * + * @return Response + */ + public function putAnnotationAction(Comment $comment, Request $request) + { + $data = json_decode($request->getContent(), true); + + if (!is_null($data['text'])) { + $comment->setText($data['text']); + } + + $em = $this->getDoctrine()->getManager(); + $em->flush(); + + $json = $this->get('serializer')->serialize($comment, 'json'); + + return $this->renderJsonResponse($json); + } + + /** + * Removes a comment. + * + * @ApiDoc( + * requirements={ + * {"name"="comment", "dataType"="string", "requirement"="\w+", "description"="The comment ID"} + * } + * ) + * + * @ParamConverter("comment", class="WallabagCommentBundle:Comment") + * + * @return Response + */ + public function deleteAnnotationAction(Comment $comment) + { + $em = $this->getDoctrine()->getManager(); + $em->remove($comment); + $em->flush(); + + $json = $this->get('serializer')->serialize($comment, 'json'); + + return $this->renderJsonResponse($json); + } + + /** + * Send a JSON Response. + * We don't use the Symfony JsonRespone, because it takes an array as parameter instead of a JSON string. + * + * @param string $json + * + * @return Response + */ + private function renderJsonResponse($json, $code = 200) + { + return new Response($json, $code, array('application/json')); + } +} diff --git a/src/Wallabag/CommentBundle/DataFixtures/ORM/LoadCommentData.php b/src/Wallabag/CommentBundle/DataFixtures/ORM/LoadCommentData.php new file mode 100644 index 00000000..717f4863 --- /dev/null +++ b/src/Wallabag/CommentBundle/DataFixtures/ORM/LoadCommentData.php @@ -0,0 +1,45 @@ +getReference('admin-user')); + $comment1->setEntry($this->getReference('entry1')); + $comment1->setText('This is my comment /o/'); + $comment1->setQuote('content'); + + $manager->persist($comment1); + + $this->addReference('comment1', $comment1); + + $comment2 = new Comment($this->getReference('admin-user')); + $comment2->setEntry($this->getReference('entry2')); + $comment2->setText('This is my 2nd comment /o/'); + $comment2->setQuote('content'); + + $manager->persist($comment2); + + $this->addReference('comment2', $comment2); + + $manager->flush(); + } + + /** + * {@inheritdoc} + */ + public function getOrder() + { + return 35; + } +} diff --git a/src/Wallabag/CommentBundle/DependencyInjection/Configuration.php b/src/Wallabag/CommentBundle/DependencyInjection/Configuration.php new file mode 100644 index 00000000..bc8d0615 --- /dev/null +++ b/src/Wallabag/CommentBundle/DependencyInjection/Configuration.php @@ -0,0 +1,20 @@ +root('wallabag_comment'); + + return $treeBuilder; + } +} diff --git a/src/Wallabag/CommentBundle/DependencyInjection/WallabagCommentExtension.php b/src/Wallabag/CommentBundle/DependencyInjection/WallabagCommentExtension.php new file mode 100644 index 00000000..b58a17a0 --- /dev/null +++ b/src/Wallabag/CommentBundle/DependencyInjection/WallabagCommentExtension.php @@ -0,0 +1,23 @@ +processConfiguration($configuration, $configs); + + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.yml'); + } +} diff --git a/src/Wallabag/CommentBundle/Entity/Comment.php b/src/Wallabag/CommentBundle/Entity/Comment.php new file mode 100644 index 00000000..a89a2cb3 --- /dev/null +++ b/src/Wallabag/CommentBundle/Entity/Comment.php @@ -0,0 +1,270 @@ +user = $user; + } + + /** + * Get id. + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Set text. + * + * @param string $text + * + * @return Comment + */ + public function setText($text) + { + $this->text = $text; + + return $this; + } + + /** + * Get text. + * + * @return string + */ + public function getText() + { + return $this->text; + } + + /** + * @ORM\PrePersist + * @ORM\PreUpdate + */ + public function timestamps() + { + if (is_null($this->createdAt)) { + $this->createdAt = new \DateTime(); + } + $this->updatedAt = new \DateTime(); + } + + /** + * Get created. + * + * @return \DateTime + */ + public function getCreatedAt() + { + return $this->createdAt; + } + + /** + * Get updated. + * + * @return \DateTime + */ + public function getUpdatedAt() + { + return $this->updatedAt; + } + + /** + * Get quote. + * + * @return string + */ + public function getQuote() + { + return $this->quote; + } + + /** + * Set quote. + * + * @param string $quote + * + * @return Comment + */ + public function setQuote($quote) + { + $this->quote = $quote; + + return $this; + } + + /** + * Get ranges. + * + * @return array + */ + public function getRanges() + { + return $this->ranges; + } + + /** + * Set ranges. + * + * @param array $ranges + * + * @return Comment + */ + public function setRanges($ranges) + { + $this->ranges = $ranges; + + return $this; + } + + /** + * Set user. + * + * @param string $user + * + * @return Comment + */ + public function setUser($user) + { + $this->user = $user; + + return $this; + } + + /** + * Get user. + * + * @return string + */ + public function getUser() + { + return $this->user; + } + + /** + * @VirtualProperty + * @SerializedName("user") + */ + public function getUserName() + { + return $this->user->getName(); + } + + /** + * Set entry. + * + * @param Entry $entry + * + * @return Comment + */ + public function setEntry($entry) + { + $this->entry = $entry; + $entry->setComment($this); + + return $this; + } + + /** + * Get entry. + * + * @return Entry + */ + public function getEntry() + { + return $this->entry; + } + + /** + * @VirtualProperty + * @SerializedName("annotator_schema_version") + */ + public function getVersion() + { + return 'v1.0'; + } +} diff --git a/src/Wallabag/CommentBundle/Repository/CommentRepository.php b/src/Wallabag/CommentBundle/Repository/CommentRepository.php new file mode 100644 index 00000000..15acffbf --- /dev/null +++ b/src/Wallabag/CommentBundle/Repository/CommentRepository.php @@ -0,0 +1,94 @@ +createQueryBuilder('c') + ->leftJoin('c.user', 'u') + ->andWhere('u.id = :userId')->setParameter('userId', $userId) + ->orderBy('c.id', 'desc') + ; + } + + /** + * Retrieves all comments for a user. + * + * @param int $userId + * + * @return QueryBuilder + */ + public function getBuilderForAllByUser($userId) + { + return $this + ->getBuilderByUser($userId) + ; + } + + /** + * Get comment for this id. + * + * @param int $commentId + * + * @return array + */ + public function findCommentById($commentId) + { + return $this->createQueryBuilder('c') + ->andWhere('c.id = :commentId')->setParameter('commentId', $commentId) + ->getQuery()->getSingleResult() + ; + } + + /** + * Find comments for entry id. + * + * @param int $entryId + * @param int $userId + * + * @return array + */ + public function findCommentsByPageId($entryId, $userId) + { + return $this->createQueryBuilder('c') + ->where('c.entry = :entryId')->setParameter('entryId', $entryId) + ->andwhere('c.user = :userId')->setParameter('userId', $userId) + ->getQuery()->getResult() + ; + } + + /** + * Find last comment for a given entry id. Used only for tests. + * + * @param int $entryId + * + * @return array + */ + public function findLastCommentByPageId($entryId, $userId) + { + return $this->createQueryBuilder('c') + ->where('c.entry = :entryId')->setParameter('entryId', $entryId) + ->andwhere('c.user = :userId')->setParameter('userId', $userId) + ->orderBy('c.id', 'DESC') + ->setMaxResults(1) + ->getQuery() + ->getOneOrNullResult(); + } +} diff --git a/src/Wallabag/CommentBundle/Resources/config/routing.yml b/src/Wallabag/CommentBundle/Resources/config/routing.yml new file mode 100644 index 00000000..e69de29b diff --git a/src/Wallabag/CommentBundle/Resources/config/routing_comments.yml b/src/Wallabag/CommentBundle/Resources/config/routing_comments.yml new file mode 100644 index 00000000..1d3893d3 --- /dev/null +++ b/src/Wallabag/CommentBundle/Resources/config/routing_comments.yml @@ -0,0 +1,4 @@ +annotations: + type: rest + resource: "WallabagCommentBundle:WallabagComment" + name_prefix: annotations_ diff --git a/src/Wallabag/CommentBundle/Resources/config/services.yml b/src/Wallabag/CommentBundle/Resources/config/services.yml new file mode 100644 index 00000000..0e7972a4 --- /dev/null +++ b/src/Wallabag/CommentBundle/Resources/config/services.yml @@ -0,0 +1,4 @@ +services: +# wallabag_comment.example: +# class: Wallabag\CommentBundle\Example +# arguments: ["@service_id", "plain_value", %parameter%] diff --git a/src/Wallabag/CommentBundle/Tests/Controller/CommentControllerTest.php b/src/Wallabag/CommentBundle/Tests/Controller/CommentControllerTest.php new file mode 100644 index 00000000..f8b2a56f --- /dev/null +++ b/src/Wallabag/CommentBundle/Tests/Controller/CommentControllerTest.php @@ -0,0 +1,81 @@ +client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCommentBundle:Comment') + ->findOneBy(array('user' => 1)); + + if (!$comment) { + $this->markTestSkipped('No content found in db.'); + } + $this->logInAs('admin'); + $crawler = $this->client->request('GET', 'annotations/'.$comment->getEntry()->getId().'.json'); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); + + $content = json_decode($this->client->getResponse()->getContent(), true); + $this->assertEquals(1, $content['total']); + $this->assertEquals($comment->getText(), $content['rows'][0]['text']); + } + + public function testSetcomment() + { + $this->logInAs('admin'); + + $entry = $this->client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCoreBundle:Entry') + ->findOneBy(array('user' => 1)); + + $headers = array('CONTENT_TYPE' => 'application/json'); + $content = json_encode(array( + 'text' => 'my comment', + 'quote' => 'my quote', + 'range' => '[{"start":"","startOffset":24,"end":"","endOffset":31}]', + )); + $crawler = $this->client->request('POST', 'annotations/'.$entry->getId().'.json', array(), array(), $headers, $content); + + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); + + $comment = $this->client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCommentBundle:Comment') + ->findLastCommentByPageId($entry->getId(), 1); + + $this->assertEquals('my comment', $comment->getText()); + } + + public function testEditcomment() + { + $comment = $this->client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCommentBundle:Comment') + ->findOneBy(array('user' => 1)); + + $this->logInAs('admin'); + + $headers = array('CONTENT_TYPE' => 'application/json'); + $content = json_encode(array( + 'text' => 'a modified comment', + )); + $crawler = $this->client->request('PUT', 'annotations/'.$comment->getId().'.json', array(), array(), $headers, $content); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); + + $content = json_decode($this->client->getResponse()->getContent(), true); + + $this->assertEquals('a modified comment', $content['text']); + + $commentUpdated = $this->client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCommentBundle:Comment') + ->findCommentById($comment->getId()); + $this->assertEquals('a modified comment', $commentUpdated->getText()); + } +} diff --git a/src/Wallabag/CommentBundle/Tests/WallabagCommentTestCase.php b/src/Wallabag/CommentBundle/Tests/WallabagCommentTestCase.php new file mode 100644 index 00000000..f4a2ae6c --- /dev/null +++ b/src/Wallabag/CommentBundle/Tests/WallabagCommentTestCase.php @@ -0,0 +1,63 @@ +client = $this->createAuthorizedClient(); + } + + public function logInAs($username) + { + $crawler = $this->client->request('GET', '/login'); + $form = $crawler->filter('button[type=submit]')->form(); + $data = array( + '_username' => $username, + '_password' => 'mypassword', + ); + + $this->client->submit($form, $data); + } + + /** + * @return Client + */ + protected function createAuthorizedClient() + { + $client = static::createClient(); + $container = $client->getContainer(); + + /** @var $userManager \FOS\UserBundle\Doctrine\UserManager */ + $userManager = $container->get('fos_user.user_manager'); + /** @var $loginManager \FOS\UserBundle\Security\LoginManager */ + $loginManager = $container->get('fos_user.security.login_manager'); + $firewallName = $container->getParameter('fos_user.firewall_name'); + + $this->user = $userManager->findUserBy(array('username' => 'admin')); + $loginManager->loginUser($firewallName, $this->user); + + // save the login token into the session and put it in a cookie + $container->get('session')->set('_security_'.$firewallName, serialize($container->get('security.token_storage')->getToken())); + $container->get('session')->save(); + + $session = $container->get('session'); + $client->getCookieJar()->set(new Cookie($session->getName(), $session->getId())); + + return $client; + } +} diff --git a/src/Wallabag/CommentBundle/WallabagCommentBundle.php b/src/Wallabag/CommentBundle/WallabagCommentBundle.php new file mode 100644 index 00000000..8150034d --- /dev/null +++ b/src/Wallabag/CommentBundle/WallabagCommentBundle.php @@ -0,0 +1,9 @@ +