From 0f00688096645606c7806a619ca27e6f30ce820c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 20 Feb 2015 11:45:38 +0100 Subject: [PATCH 01/25] first draft of hypermedia implementation --- app/AppKernel.php | 3 +- composer.json | 1 + composer.lock | 170 +++++++++++++++--- .../Controller/WallabagRestController.php | 10 +- src/Wallabag/CoreBundle/Entity/Entry.php | 6 +- src/Wallabag/CoreBundle/Entity/User.php | 4 + .../CoreBundle/Repository/EntryRepository.php | 3 +- 7 files changed, 166 insertions(+), 31 deletions(-) diff --git a/app/AppKernel.php b/app/AppKernel.php index d134de3cc..601b52c3f 100644 --- a/app/AppKernel.php +++ b/app/AppKernel.php @@ -22,7 +22,8 @@ class AppKernel extends Kernel new Nelmio\ApiDocBundle\NelmioApiDocBundle(), new Nelmio\CorsBundle\NelmioCorsBundle(), new Liip\ThemeBundle\LiipThemeBundle(), - new Wallabag\CoreBundle\WallabagCoreBundle() + new Wallabag\CoreBundle\WallabagCoreBundle(), + new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle() ); if (in_array($this->getEnvironment(), array('dev', 'test'))) { diff --git a/composer.json b/composer.json index 0b162c028..0793bcab3 100644 --- a/composer.json +++ b/composer.json @@ -74,6 +74,7 @@ "robmorgan/phinx": "~0.4", "tecnick.com/tcpdf": "~6.2", "simplepie/simplepie": "~1.3.1", + "willdurand/hateoas-bundle": "1.0.*@dev", "htmlawed/htmlawed": "dev-master", "liip/theme-bundle": "1.1.3", "wallabag/PHP-Flash-Messages": "dev-master", diff --git a/composer.lock b/composer.lock index a6102a819..f5b232803 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "fd56c671d70f498ccc1996450479fbdc", + "hash": "a078afa674d2816ebe7f7ad333d9f3b4", "packages": [ { "name": "doctrine/annotations", @@ -1386,16 +1386,16 @@ }, { "name": "michelf/php-markdown", - "version": "1.4.1", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/michelf/php-markdown.git", - "reference": "de9a19c7bf352d41cc99ed86c3c0ef17e87394b6" + "reference": "e1aabe18173231ebcefc90e615565742fc1c7fd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/michelf/php-markdown/zipball/de9a19c7bf352d41cc99ed86c3c0ef17e87394b6", - "reference": "de9a19c7bf352d41cc99ed86c3c0ef17e87394b6", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/e1aabe18173231ebcefc90e615565742fc1c7fd9", + "reference": "e1aabe18173231ebcefc90e615565742fc1c7fd9", "shasum": "" }, "require": { @@ -1417,36 +1417,36 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Michel Fortin", - "email": "michel.fortin@michelf.ca", - "homepage": "http://michelf.ca/", - "role": "Developer" - }, { "name": "John Gruber", "homepage": "http://daringfireball.net/" + }, + { + "name": "Michel Fortin", + "email": "michel.fortin@michelf.ca", + "homepage": "https://michelf.ca/", + "role": "Developer" } ], "description": "PHP Markdown", - "homepage": "http://michelf.ca/projects/php-markdown/", + "homepage": "https://michelf.ca/projects/php-markdown/", "keywords": [ "markdown" ], - "time": "2014-05-05 02:43:50" + "time": "2015-03-01 12:03:08" }, { "name": "monolog/monolog", - "version": "1.12.0", + "version": "1.13.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f" + "reference": "c41c218e239b50446fd883acb1ecfd4b770caeae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1fbe8c2641f2b163addf49cc5e18f144bec6b19f", - "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c41c218e239b50446fd883acb1ecfd4b770caeae", + "reference": "c41c218e239b50446fd883acb1ecfd4b770caeae", "shasum": "" }, "require": { @@ -1463,6 +1463,7 @@ "phpunit/phpunit": "~4.0", "raven/raven": "~0.5", "ruflin/elastica": "0.90.*", + "swiftmailer/swiftmailer": "~5.3", "videlalvaro/php-amqplib": "~2.4" }, "suggest": { @@ -1479,7 +1480,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.12.x-dev" + "dev-master": "1.13.x-dev" } }, "autoload": { @@ -1505,7 +1506,7 @@ "logging", "psr-3" ], - "time": "2014-12-29 21:29:35" + "time": "2015-03-05 01:12:12" }, { "name": "nelmio/api-doc-bundle", @@ -2645,7 +2646,7 @@ "description": "Libraries from @fivefilters.", "homepage": "https://github.com/wallabag/Fivefilters_Libraries", "support": { - "source": "https://github.com/wallabag/Fivefilters_Libraries/tree/1.0.0", + "source": "https://github.com/wallabag/Fivefilters_Libraries/tree/master", "issues": "https://github.com/wallabag/Fivefilters_Libraries/issues" }, "time": "2015-01-19 20:19:28" @@ -2690,7 +2691,7 @@ "description": "PHP Classes for dynamically generating EPub files.", "homepage": "https://github.com/wallabag/PHPePub", "support": { - "source": "https://github.com/wallabag/PHPePub/tree/2.1.0" + "source": "https://github.com/wallabag/PHPePub/tree/master" }, "time": "2015-01-19 11:44:19" }, @@ -2727,7 +2728,7 @@ "description": "A simple and smart (or stupid) php5 snippets repository", "homepage": "https://github.com/wallabag/kriss_php5", "support": { - "source": "https://github.com/wallabag/kriss_php5/tree/1.0.0" + "source": "https://github.com/wallabag/kriss_php5/tree/master" }, "time": "2015-01-18 21:21:43" }, @@ -2764,7 +2765,7 @@ "description": "Paginate record sets, not tied in directly to a database.", "homepage": "https://github.com/wallabag/pagination", "support": { - "source": "https://github.com/wallabag/pagination/tree/1.0.0" + "source": "https://github.com/wallabag/pagination/tree/master" }, "time": "2015-01-19 09:24:39" }, @@ -2810,7 +2811,7 @@ "sessions" ], "support": { - "source": "https://github.com/wallabag/PHP-Flash-Messages/tree/1.0.0" + "source": "https://github.com/wallabag/PHP-Flash-Messages/tree/master" }, "time": "2015-01-18 19:51:55" }, @@ -2864,7 +2865,7 @@ "html" ], "support": { - "source": "https://github.com/wallabag/php-readability/tree/1.0.0", + "source": "https://github.com/wallabag/php-readability/tree/master", "issues": "https://github.com/wallabag/php-readability/issues" }, "time": "2015-01-19 12:25:38" @@ -2902,10 +2903,126 @@ "description": "An experimental Mobipocket file creator in PHP.", "homepage": "https://github.com/wallabag/phpMobi", "support": { - "source": "https://github.com/wallabag/phpMobi/tree/1.0.0" + "source": "https://github.com/wallabag/phpMobi/tree/master" }, "time": "2015-01-19 12:43:17" }, + { + "name": "willdurand/hateoas", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/willdurand/Hateoas.git", + "reference": "89fe19ad9ce25f15323d76ac22272282ae8a9f14" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/willdurand/Hateoas/zipball/89fe19ad9ce25f15323d76ac22272282ae8a9f14", + "reference": "89fe19ad9ce25f15323d76ac22272282ae8a9f14", + "shasum": "" + }, + "require": { + "doctrine/annotations": "~1.0", + "doctrine/common": "~2.0", + "jms/metadata": "~1.1", + "jms/serializer": "~0.13@dev", + "symfony/expression-language": "~2.4" + }, + "require-dev": { + "atoum/atoum": "*@dev", + "hautelook/frankenstein": "~0.1", + "pagerfanta/pagerfanta": "~1.0", + "phpunit/phpunit": "~3.7", + "symfony/dependency-injection": "~2.0", + "symfony/routing": "~2.0", + "symfony/yaml": "~2.0", + "twig/twig": "~1.12" + }, + "suggest": { + "symfony/routing": "To use the SymfonyRouteFactory.", + "symfony/yaml": "To use yaml based configuration.", + "twig/twig": "To use the Twig extensions." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "psr-0": { + "Hateoas": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Adrien Brault", + "email": "adrien.brault@gmail.com" + }, + { + "name": "William Durand", + "email": "william.durand1@gmail.com" + } + ], + "description": "A PHP library to support implementing representations for HATEOAS REST web services", + "time": "2015-02-24 15:28:33" + }, + { + "name": "willdurand/hateoas-bundle", + "version": "dev-master", + "target-dir": "Bazinga/Bundle/HateoasBundle", + "source": { + "type": "git", + "url": "https://github.com/willdurand/BazingaHateoasBundle.git", + "reference": "3c86e8080e8a229365a0ce91818da6fe6562376b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/willdurand/BazingaHateoasBundle/zipball/3c86e8080e8a229365a0ce91818da6fe6562376b", + "reference": "3c86e8080e8a229365a0ce91818da6fe6562376b", + "shasum": "" + }, + "require": { + "jms/serializer-bundle": "~0.13", + "symfony/framework-bundle": "~2.2", + "willdurand/hateoas": "~2.0" + }, + "require-dev": { + "symfony/expression-language": "~2.4", + "twig/twig": "~1.12" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Bazinga\\Bundle\\HateoasBundle": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "William Durand", + "email": "william.durand1@gmail.com" + } + ], + "description": "Integration of Hateoas into Symfony2.", + "keywords": [ + "HATEOAS", + "rest" + ], + "time": "2015-02-19 16:27:51" + }, { "name": "willdurand/jsonp-callback-validator", "version": "v1.1.0", @@ -4068,6 +4185,7 @@ "minimum-stability": "dev", "stability-flags": { "nelmio/cors-bundle": 20, + "willdurand/hateoas-bundle": 20, "htmlawed/htmlawed": 20, "wallabag/php-flash-messages": 20, "wallabag/kriss_php5": 20, diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index e9cd8c939..cadd7e755 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -5,10 +5,12 @@ namespace Wallabag\CoreBundle\Controller; use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; use Wallabag\CoreBundle\Service\Extractor; +use Hateoas\HateoasBuilder; class WallabagRestController extends Controller { @@ -72,6 +74,9 @@ class WallabagRestController extends Controller throw $this->createNotFoundException(); } + $hateoas = HateoasBuilder::create()->build(); + $json = $hateoas->serialize($entries, 'json'); + return $entries; } @@ -87,7 +92,10 @@ class WallabagRestController extends Controller */ public function getEntryAction(Entry $entry) { - return $entry; + $hateoas = HateoasBuilder::create()->build(); + $json = $hateoas->serialize($entry, 'json'); + + return new Response($json, 200, array('application/json')); } /** diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index 937213b44..4f57eb0af 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php @@ -4,17 +4,21 @@ namespace Wallabag\CoreBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; +use Hateoas\Configuration\Annotation as Hateoas; +use JMS\Serializer\Annotation\XmlRoot; /** * Entry * + * @XmlRoot("entry") * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\EntryRepository") * @ORM\Table(name="entry") * @ORM\HasLifecycleCallbacks() - * + * @Hateoas\Relation("self", href = "expr('/api/entries/' ~ object.getId())") */ class Entry { + /** @Serializer\XmlAttribute */ /** * @var integer * diff --git a/src/Wallabag/CoreBundle/Entity/User.php b/src/Wallabag/CoreBundle/Entity/User.php index ed5cfe535..5589c039e 100644 --- a/src/Wallabag/CoreBundle/Entity/User.php +++ b/src/Wallabag/CoreBundle/Entity/User.php @@ -7,6 +7,8 @@ use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\AdvancedUserInterface; use Symfony\Component\Validator\Constraints as Assert; +use JMS\Serializer\Annotation\ExclusionPolicy; +use JMS\Serializer\Annotation\Expose; /** * User @@ -14,12 +16,14 @@ use Symfony\Component\Validator\Constraints as Assert; * @ORM\Table(name="user") * @ORM\Entity * @ORM\HasLifecycleCallbacks() + * @ExclusionPolicy("all") */ class User implements AdvancedUserInterface, \Serializable { /** * @var integer * + * @Expose * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index bedc90d2b..32394d2ab 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -102,8 +102,7 @@ class EntryRepository extends EntityRepository public function findEntries($userId, $isArchived = null, $isStarred = null, $isDeleted = null, $sort = 'created', $order = 'ASC') { $qb = $this->createQueryBuilder('e') - ->leftJoin('e.user', 'u') - ->where('u.id =:userId')->setParameter('userId', $userId); + ->where('e.user =:userId')->setParameter('userId', $userId); if (null !== $isArchived) { $qb->andWhere('e.isArchived =:isArchived')->setParameter('isArchived', (bool) $isArchived); From 0ed6302212eec00e188c61acbd92bde80406f4ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 20 Feb 2015 12:00:20 +0100 Subject: [PATCH 02/25] returns serialzed object for GET /entries --- src/Wallabag/CoreBundle/Controller/WallabagRestController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index cadd7e755..d48c7bbb2 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -77,7 +77,7 @@ class WallabagRestController extends Controller $hateoas = HateoasBuilder::create()->build(); $json = $hateoas->serialize($entries, 'json'); - return $entries; + return new Response($json, 200, array('application/json')); } /** From aa4d6562c196926a55819326b0fbe504daf2156f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 20 Feb 2015 14:18:01 +0100 Subject: [PATCH 03/25] improve hateoas implementation --- .../CoreBundle/Controller/WallabagRestController.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index d48c7bbb2..b9f7efea0 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -10,7 +10,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; use Wallabag\CoreBundle\Service\Extractor; -use Hateoas\HateoasBuilder; class WallabagRestController extends Controller { @@ -74,8 +73,7 @@ class WallabagRestController extends Controller throw $this->createNotFoundException(); } - $hateoas = HateoasBuilder::create()->build(); - $json = $hateoas->serialize($entries, 'json'); + $json = $this->get('serializer')->serialize($entries, 'json'); return new Response($json, 200, array('application/json')); } @@ -92,8 +90,7 @@ class WallabagRestController extends Controller */ public function getEntryAction(Entry $entry) { - $hateoas = HateoasBuilder::create()->build(); - $json = $hateoas->serialize($entry, 'json'); + $json = $this->get('serializer')->serialize($entry, 'json'); return new Response($json, 200, array('application/json')); } @@ -124,7 +121,9 @@ class WallabagRestController extends Controller $em->persist($entry); $em->flush(); - return $entry; + $json = $this->get('serializer')->serialize($entry, 'json'); + + return new Response($json, 200, array('application/json')); } /** From 1d14779154481b320e1c44fccf2558d8c9fa43a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 20 Feb 2015 15:36:25 +0100 Subject: [PATCH 04/25] remove isDeleted flag --- .../CoreBundle/Controller/EntryController.php | 5 ++-- .../Controller/WallabagRestController.php | 22 +++++------------- src/Wallabag/CoreBundle/Entity/Entry.php | 23 ------------------- .../CoreBundle/Repository/EntryRepository.php | 10 +------- .../Tests/Controller/EntryControllerTest.php | 9 +++----- .../Controller/WallabagRestControllerTest.php | 16 ++++++++----- 6 files changed, 23 insertions(+), 62 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/EntryController.php b/src/Wallabag/CoreBundle/Controller/EntryController.php index 81ab77887..8a8f3cd79 100644 --- a/src/Wallabag/CoreBundle/Controller/EntryController.php +++ b/src/Wallabag/CoreBundle/Controller/EntryController.php @@ -192,8 +192,9 @@ class EntryController extends Controller { $this->checkUserAction($entry); - $entry->setDeleted(1); - $this->getDoctrine()->getManager()->flush(); + $em = $this->getDoctrine()->getManager(); + $em->remove($entry); + $em->flush(); $this->get('session')->getFlashBag()->add( 'notice', diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index b9f7efea0..276cfe1c7 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -43,7 +43,6 @@ class WallabagRestController extends Controller * parameters={ * {"name"="archive", "dataType"="boolean", "required"=false, "format"="true or false, all entries by default", "description"="filter by archived status."}, * {"name"="star", "dataType"="boolean", "required"=false, "format"="true or false, all entries by default", "description"="filter by starred status."}, - * {"name"="delete", "dataType"="boolean", "required"=false, "format"="true or false, default '0'", "description"="filter by deleted status."}, * {"name"="sort", "dataType"="string", "required"=false, "format"="'created' or 'updated', default 'created'", "description"="sort entries by date."}, * {"name"="order", "dataType"="string", "required"=false, "format"="'asc' or 'desc', default 'desc'", "description"="order of sort."}, * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."}, @@ -57,7 +56,6 @@ class WallabagRestController extends Controller { $isArchived = $request->query->get('archive'); $isStarred = $request->query->get('star'); - $isDeleted = $request->query->get('delete', 0); $sort = $request->query->get('sort', 'created'); $order = $request->query->get('order', 'desc'); $page = $request->query->get('page', 1); @@ -67,7 +65,7 @@ class WallabagRestController extends Controller $entries = $this ->getDoctrine() ->getRepository('WallabagCoreBundle:Entry') - ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $isDeleted, $sort, $order); + ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order); if (!($entries)) { throw $this->createNotFoundException(); @@ -138,8 +136,7 @@ class WallabagRestController extends Controller * {"name"="tags", "dataType"="string", "required"=false, "format"="tag1,tag2,tag3", "description"="a comma-separated list of tags."}, * {"name"="archive", "dataType"="boolean", "required"=false, "format"="true or false", "description"="archived the entry."}, * {"name"="star", "dataType"="boolean", "required"=false, "format"="true or false", "description"="starred the entry."}, - * {"name"="delete", "dataType"="boolean", "required"=false, "format"="true or false", "description"="flag as deleted. Default false. In case that you don't want to *really* remove it.."}, - * } + * } * ) * @return Entry */ @@ -148,7 +145,6 @@ class WallabagRestController extends Controller $title = $request->request->get("title"); $tags = $request->request->get("tags", array()); $isArchived = $request->request->get("archive"); - $isDeleted = $request->request->get("delete"); $isStarred = $request->request->get("star"); if (!is_null($title)) { @@ -159,10 +155,6 @@ class WallabagRestController extends Controller $entry->setArchived($isArchived); } - if (!is_null($isDeleted)) { - $entry->setDeleted($isDeleted); - } - if (!is_null($isStarred)) { $entry->setStarred($isStarred); } @@ -185,15 +177,13 @@ class WallabagRestController extends Controller */ public function deleteEntriesAction(Entry $entry) { - if ($entry->isDeleted()) { - throw new NotFoundHttpException('This entry is already deleted'); - } - $em = $this->getDoctrine()->getManager(); - $entry->setDeleted(1); + $em->remove($entry); $em->flush(); - return $entry; + $json = $this->get('serializer')->serialize($entry, 'json'); + + return new Response($json, 200, array('application/json')); } /** diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index 4f57eb0af..e47848b61 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php @@ -57,13 +57,6 @@ class Entry */ private $isStarred = false; - /** - * @var boolean - * - * @ORM\Column(name="is_deleted", type="boolean") - */ - private $isDeleted = false; - /** * @var string * @@ -280,22 +273,6 @@ class Entry return $this->user; } - /** - * @return string - */ - public function isDeleted() - { - return $this->isDeleted; - } - - /** - * @param string $isDeleted - */ - public function setDeleted($isDeleted) - { - $this->isDeleted = $isDeleted; - } - /** * @return string */ diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index 32394d2ab..005142fc5 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -24,7 +24,6 @@ class EntryRepository extends EntityRepository ->leftJoin('e.user', 'u') ->where('e.isArchived = false') ->andWhere('u.id =:userId')->setParameter('userId', $userId) - ->andWhere('e.isDeleted=false') ->orderBy('e.createdAt', 'desc') ->getQuery(); @@ -51,7 +50,6 @@ class EntryRepository extends EntityRepository ->leftJoin('e.user', 'u') ->where('e.isArchived = true') ->andWhere('u.id =:userId')->setParameter('userId', $userId) - ->andWhere('e.isDeleted=false') ->orderBy('e.createdAt', 'desc') ->getQuery(); @@ -78,7 +76,6 @@ class EntryRepository extends EntityRepository ->leftJoin('e.user', 'u') ->where('e.isStarred = true') ->andWhere('u.id =:userId')->setParameter('userId', $userId) - ->andWhere('e.isDeleted = false') ->orderBy('e.createdAt', 'desc') ->getQuery(); @@ -93,13 +90,12 @@ class EntryRepository extends EntityRepository * @param int $userId * @param bool $isArchived * @param bool $isStarred - * @param bool $isDeleted * @param string $sort * @param string $order * * @return array */ - public function findEntries($userId, $isArchived = null, $isStarred = null, $isDeleted = null, $sort = 'created', $order = 'ASC') + public function findEntries($userId, $isArchived = null, $isStarred = null, $sort = 'created', $order = 'ASC') { $qb = $this->createQueryBuilder('e') ->where('e.user =:userId')->setParameter('userId', $userId); @@ -112,10 +108,6 @@ class EntryRepository extends EntityRepository $qb->andWhere('e.isStarred =:isStarred')->setParameter('isStarred', (bool) $isStarred); } - if (null !== $isDeleted) { - $qb->andWhere('e.isDeleted =:isDeleted')->setParameter('isDeleted', (bool) $isDeleted); - } - if ('created' === $sort) { $qb->orderBy('e.createdAt', $order); } elseif ('updated' === $sort) { diff --git a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php index 2634141e5..99a3a9452 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/EntryControllerTest.php @@ -161,18 +161,15 @@ class EntryControllerTest extends WallabagTestCase $content = $client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') - ->findOneByIsDeleted(false); + ->findOneById(1); $client->request('GET', '/delete/'.$content->getId()); $this->assertEquals(302, $client->getResponse()->getStatusCode()); - $res = $client->getContainer() - ->get('doctrine.orm.entity_manager') - ->getRepository('WallabagCoreBundle:Entry') - ->findOneById($content->getId()); + $client->request('GET', '/delete/'.$content->getId()); - $this->assertEquals($res->isDeleted(), true); + $this->assertEquals(404, $client->getResponse()->getStatusCode()); } public function testViewOtherUserEntry() diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index fcfa8ccf9..4164e5161 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php @@ -130,7 +130,7 @@ class WallabagRestControllerTest extends WallabagTestCase $entry = $client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') - ->findOneByIsDeleted(false); + ->findOneByUser(1); if (!$entry) { $this->markTestSkipped('No content found in db.'); @@ -140,10 +140,14 @@ class WallabagRestControllerTest extends WallabagTestCase $this->assertEquals(200, $client->getResponse()->getStatusCode()); - $res = $client->getContainer() - ->get('doctrine.orm.entity_manager') - ->getRepository('WallabagCoreBundle:Entry') - ->findOneById($entry->getId()); - $this->assertEquals($res->isDeleted(), true); + // We'll try to delete this entry again + $client->request('GET', '/api/salts/admin.json'); + $salt = json_decode($client->getResponse()->getContent()); + + $headers = $this->generateHeaders('admin', 'test', $salt[0]); + + $client->request('DELETE', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers); + + $this->assertEquals(404, $client->getResponse()->getStatusCode()); } } From 2691cf04384239c546e141af6cc3c22b210dae58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 20 Feb 2015 16:38:24 +0100 Subject: [PATCH 05/25] GET /api/tags/id_tag method --- .../Controller/WallabagRestController.php | 17 ++++++-- .../DataFixtures/ORM/LoadTagData.php | 42 +++++++++++++++++++ src/Wallabag/CoreBundle/Entity/Tag.php | 2 +- .../Controller/WallabagRestControllerTest.php | 29 +++++++++++++ 4 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index 276cfe1c7..cb68784d5 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -6,7 +6,6 @@ use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; use Wallabag\CoreBundle\Service\Extractor; @@ -244,12 +243,24 @@ class WallabagRestController extends Controller * * @ApiDoc( * requirements={ - * {"name"="tag", "dataType"="string", "requirement"="\w+", "description"="The tag"} + * {"name"="label", "dataType"="string", "requirement"="\w+", "description"="Label of the tag"} * } * ) */ - public function getTagAction(Tag $tag) + public function getTagAction($label) { + $tag = $this + ->getDoctrine() + ->getRepository('WallabagCoreBundle:Tag') + ->findOneByLabel($label); + + if (is_null($tag)) { + throw $this->createNotFoundException(); + } + + $json = $this->get('serializer')->serialize($tag, 'json'); + + return new Response($json, 200, array('application/json')); } /** diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php new file mode 100644 index 000000000..6b13c2bee --- /dev/null +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php @@ -0,0 +1,42 @@ +setLabel('foo'); + + $manager->persist($tag1); + + $tag2 = new Tag(); + $tag2->setLabel('bar'); + + $manager->persist($tag2); + + $tag3 = new Tag(); + $tag3->setLabel('baz'); + + $manager->persist($tag3); + + $manager->flush(); + } + + /** + * {@inheritDoc} + */ + public function getOrder() + { + return 30; + } +} diff --git a/src/Wallabag/CoreBundle/Entity/Tag.php b/src/Wallabag/CoreBundle/Entity/Tag.php index 310175635..963f32b1e 100644 --- a/src/Wallabag/CoreBundle/Entity/Tag.php +++ b/src/Wallabag/CoreBundle/Entity/Tag.php @@ -58,6 +58,6 @@ class Tag */ public function getLabel() { - return $this->value; + return $this->label; } } diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index 4164e5161..0ffe7fe62 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php @@ -150,4 +150,33 @@ class WallabagRestControllerTest extends WallabagTestCase $this->assertEquals(404, $client->getResponse()->getStatusCode()); } + + public function testGetOneTag() + { + $client = $this->createClient(); + $client->request('GET', '/api/salts/admin.json'); + $salt = json_decode($client->getResponse()->getContent()); + + $headers = $this->generateHeaders('admin', 'test', $salt[0]); + + $tag = $client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCoreBundle:Tag') + ->findOneByLabel('foo'); + + if (!$tag) { + $this->markTestSkipped('No content found in db.'); + } + + $client->request('GET', '/api/tags/'.$tag->getLabel().'.json', array(), array(), $headers); + + $this->assertEquals(json_encode($tag), $client->getResponse()->getContent()); + + $this->assertTrue( + $client->getResponse()->headers->contains( + 'Content-Type', + 'application/json' + ) + ); + } } From b3dc0749d3a007b9dced1d96b1f4000115c14784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 20 Feb 2015 17:18:48 +0100 Subject: [PATCH 06/25] remove GET /tags/id --- .../CoreBundle/Repository/TagRepository.php | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/Wallabag/CoreBundle/Repository/TagRepository.php diff --git a/src/Wallabag/CoreBundle/Repository/TagRepository.php b/src/Wallabag/CoreBundle/Repository/TagRepository.php new file mode 100644 index 000000000..005142fc5 --- /dev/null +++ b/src/Wallabag/CoreBundle/Repository/TagRepository.php @@ -0,0 +1,121 @@ +createQueryBuilder('e') + ->setFirstResult($firstResult) + ->setMaxResults($maxResults) + ->leftJoin('e.user', 'u') + ->where('e.isArchived = false') + ->andWhere('u.id =:userId')->setParameter('userId', $userId) + ->orderBy('e.createdAt', 'desc') + ->getQuery(); + + $paginator = new Paginator($qb); + + return $paginator; + } + + /** + * Retrieves read entries for a user + * + * @param int $userId + * @param int $firstResult + * @param int $maxResults + * + * @return Paginator + */ + public function findArchiveByUser($userId, $firstResult, $maxResults = 12) + { + $qb = $this->createQueryBuilder('e') + ->select('e') + ->setFirstResult($firstResult) + ->setMaxResults($maxResults) + ->leftJoin('e.user', 'u') + ->where('e.isArchived = true') + ->andWhere('u.id =:userId')->setParameter('userId', $userId) + ->orderBy('e.createdAt', 'desc') + ->getQuery(); + + $paginator = new Paginator($qb); + + return $paginator; + } + + /** + * Retrieves starred entries for a user + * + * @param int $userId + * @param int $firstResult + * @param int $maxResults + * + * @return Paginator + */ + public function findStarredByUser($userId, $firstResult, $maxResults = 12) + { + $qb = $this->createQueryBuilder('e') + ->select('e') + ->setFirstResult($firstResult) + ->setMaxResults($maxResults) + ->leftJoin('e.user', 'u') + ->where('e.isStarred = true') + ->andWhere('u.id =:userId')->setParameter('userId', $userId) + ->orderBy('e.createdAt', 'desc') + ->getQuery(); + + $paginator = new Paginator($qb); + + return $paginator; + } + + /** + * Find Entries + * + * @param int $userId + * @param bool $isArchived + * @param bool $isStarred + * @param string $sort + * @param string $order + * + * @return array + */ + public function findEntries($userId, $isArchived = null, $isStarred = null, $sort = 'created', $order = 'ASC') + { + $qb = $this->createQueryBuilder('e') + ->where('e.user =:userId')->setParameter('userId', $userId); + + if (null !== $isArchived) { + $qb->andWhere('e.isArchived =:isArchived')->setParameter('isArchived', (bool) $isArchived); + } + + if (null !== $isStarred) { + $qb->andWhere('e.isStarred =:isStarred')->setParameter('isStarred', (bool) $isStarred); + } + + if ('created' === $sort) { + $qb->orderBy('e.createdAt', $order); + } elseif ('updated' === $sort) { + $qb->orderBy('e.updatedAt', $order); + } + + return $qb + ->getQuery() + ->getResult(); + } +} From 6d37a7e6c11666c2c220c9eb358a877f15bcfa0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 20 Feb 2015 17:20:12 +0100 Subject: [PATCH 07/25] remove dumb code --- .../Controller/WallabagRestController.php | 28 +---- src/Wallabag/CoreBundle/Entity/Tag.php | 4 +- .../CoreBundle/Repository/TagRepository.php | 113 +----------------- 3 files changed, 6 insertions(+), 139 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index cb68784d5..2384325f4 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -232,37 +232,13 @@ class WallabagRestController extends Controller * Retrieve all tags * * @ApiDoc( + * {"name"="user", "dataType"="integer", "requirement"="\w+", "description"="The user ID"} * ) */ - public function getTagsAction() + public function getTagsUserAction() { } - /** - * Retrieve a single tag - * - * @ApiDoc( - * requirements={ - * {"name"="label", "dataType"="string", "requirement"="\w+", "description"="Label of the tag"} - * } - * ) - */ - public function getTagAction($label) - { - $tag = $this - ->getDoctrine() - ->getRepository('WallabagCoreBundle:Tag') - ->findOneByLabel($label); - - if (is_null($tag)) { - throw $this->createNotFoundException(); - } - - $json = $this->get('serializer')->serialize($tag, 'json'); - - return new Response($json, 200, array('application/json')); - } - /** * Permanently remove one tag from **every** entry * diff --git a/src/Wallabag/CoreBundle/Entity/Tag.php b/src/Wallabag/CoreBundle/Entity/Tag.php index 963f32b1e..0d7f8c2b2 100644 --- a/src/Wallabag/CoreBundle/Entity/Tag.php +++ b/src/Wallabag/CoreBundle/Entity/Tag.php @@ -3,12 +3,14 @@ namespace Wallabag\CoreBundle\Entity; use Doctrine\ORM\Mapping as ORM; +use JMS\Serializer\Annotation\XmlRoot; /** * Tag * + * @XmlRoot("tag") * @ORM\Table(name="tag") - * @ORM\Entity + * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\TagRepository") */ class Tag { diff --git a/src/Wallabag/CoreBundle/Repository/TagRepository.php b/src/Wallabag/CoreBundle/Repository/TagRepository.php index 005142fc5..903a99cda 100644 --- a/src/Wallabag/CoreBundle/Repository/TagRepository.php +++ b/src/Wallabag/CoreBundle/Repository/TagRepository.php @@ -3,119 +3,8 @@ namespace Wallabag\CoreBundle\Repository; use Doctrine\ORM\EntityRepository; -use Doctrine\ORM\Tools\Pagination\Paginator; -class EntryRepository extends EntityRepository +class TagRepository extends EntityRepository { - /** - * Retrieves unread entries for a user - * - * @param int $userId - * @param int $firstResult - * @param int $maxResults - * - * @return Paginator - */ - public function findUnreadByUser($userId, $firstResult, $maxResults = 12) - { - $qb = $this->createQueryBuilder('e') - ->setFirstResult($firstResult) - ->setMaxResults($maxResults) - ->leftJoin('e.user', 'u') - ->where('e.isArchived = false') - ->andWhere('u.id =:userId')->setParameter('userId', $userId) - ->orderBy('e.createdAt', 'desc') - ->getQuery(); - $paginator = new Paginator($qb); - - return $paginator; - } - - /** - * Retrieves read entries for a user - * - * @param int $userId - * @param int $firstResult - * @param int $maxResults - * - * @return Paginator - */ - public function findArchiveByUser($userId, $firstResult, $maxResults = 12) - { - $qb = $this->createQueryBuilder('e') - ->select('e') - ->setFirstResult($firstResult) - ->setMaxResults($maxResults) - ->leftJoin('e.user', 'u') - ->where('e.isArchived = true') - ->andWhere('u.id =:userId')->setParameter('userId', $userId) - ->orderBy('e.createdAt', 'desc') - ->getQuery(); - - $paginator = new Paginator($qb); - - return $paginator; - } - - /** - * Retrieves starred entries for a user - * - * @param int $userId - * @param int $firstResult - * @param int $maxResults - * - * @return Paginator - */ - public function findStarredByUser($userId, $firstResult, $maxResults = 12) - { - $qb = $this->createQueryBuilder('e') - ->select('e') - ->setFirstResult($firstResult) - ->setMaxResults($maxResults) - ->leftJoin('e.user', 'u') - ->where('e.isStarred = true') - ->andWhere('u.id =:userId')->setParameter('userId', $userId) - ->orderBy('e.createdAt', 'desc') - ->getQuery(); - - $paginator = new Paginator($qb); - - return $paginator; - } - - /** - * Find Entries - * - * @param int $userId - * @param bool $isArchived - * @param bool $isStarred - * @param string $sort - * @param string $order - * - * @return array - */ - public function findEntries($userId, $isArchived = null, $isStarred = null, $sort = 'created', $order = 'ASC') - { - $qb = $this->createQueryBuilder('e') - ->where('e.user =:userId')->setParameter('userId', $userId); - - if (null !== $isArchived) { - $qb->andWhere('e.isArchived =:isArchived')->setParameter('isArchived', (bool) $isArchived); - } - - if (null !== $isStarred) { - $qb->andWhere('e.isStarred =:isStarred')->setParameter('isStarred', (bool) $isStarred); - } - - if ('created' === $sort) { - $qb->orderBy('e.createdAt', $order); - } elseif ('updated' === $sort) { - $qb->orderBy('e.updatedAt', $order); - } - - return $qb - ->getQuery() - ->getResult(); - } } From 0a018fe03980b35c9f7aca838e67a8efa43b7f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 20 Feb 2015 20:29:33 +0100 Subject: [PATCH 08/25] add relation between entry and tag --- .../Controller/WallabagRestController.php | 3 + src/Wallabag/CoreBundle/Entity/Entry.php | 27 ++++++ src/Wallabag/CoreBundle/Entity/Tag.php | 10 ++ .../CoreBundle/Entity/TagsEntries.php | 93 ------------------- .../CoreBundle/Repository/TagRepository.php | 13 +++ .../Controller/WallabagRestControllerTest.php | 29 ------ 6 files changed, 53 insertions(+), 122 deletions(-) delete mode 100644 src/Wallabag/CoreBundle/Entity/TagsEntries.php diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index 2384325f4..b895b67cd 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -196,6 +196,9 @@ class WallabagRestController extends Controller */ public function getEntriesTagsAction(Entry $entry) { + $json = $this->get('serializer')->serialize($entry, 'json'); + + return new Response($json, 200, array('application/json')); } /** diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index e47848b61..e0d1b839c 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php @@ -2,6 +2,7 @@ namespace Wallabag\CoreBundle\Entity; +use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; use Hateoas\Configuration\Annotation as Hateoas; @@ -118,12 +119,22 @@ class Entry */ private $user; + /** + * @ORM\ManyToMany(targetEntity="Tag", inversedBy="entries", cascade={"persist", "merge"}) + * @ORM\JoinTable(name="tags_entries", + * joinColumns={@ORM\JoinColumn(name="entry_id", referencedColumnName="id")}, + * inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id")} + * ) + */ + private $tags; + /* * @param User $user */ public function __construct(User $user) { $this->user = $user; + $this->tags = new ArrayCollection(); } /** @@ -381,4 +392,20 @@ class Entry { $this->isPublic = $isPublic; } + + /** + * @return ArrayCollection + */ + public function getTags() + { + return $this->tags; + } + + /** + * @param Tag $tag + */ + public function addTag(Tag $tag) + { + $this->tags[] = $tag; + } } diff --git a/src/Wallabag/CoreBundle/Entity/Tag.php b/src/Wallabag/CoreBundle/Entity/Tag.php index 0d7f8c2b2..1cdf4df02 100644 --- a/src/Wallabag/CoreBundle/Entity/Tag.php +++ b/src/Wallabag/CoreBundle/Entity/Tag.php @@ -4,6 +4,8 @@ namespace Wallabag\CoreBundle\Entity; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation\XmlRoot; +use JMS\Serializer\Annotation\ExclusionPolicy; +use JMS\Serializer\Annotation\Expose; /** * Tag @@ -11,12 +13,14 @@ use JMS\Serializer\Annotation\XmlRoot; * @XmlRoot("tag") * @ORM\Table(name="tag") * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\TagRepository") + * @ExclusionPolicy("all") */ class Tag { /** * @var integer * + * @Expose * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") @@ -26,10 +30,16 @@ class Tag /** * @var string * + * @Expose * @ORM\Column(name="label", type="text") */ private $label; + /** + * @ORM\ManyToMany(targetEntity="Entry", mappedBy="tags", cascade={"persist", "merge"}) + */ + private $entries; + /** * Get id * diff --git a/src/Wallabag/CoreBundle/Entity/TagsEntries.php b/src/Wallabag/CoreBundle/Entity/TagsEntries.php deleted file mode 100644 index 228263875..000000000 --- a/src/Wallabag/CoreBundle/Entity/TagsEntries.php +++ /dev/null @@ -1,93 +0,0 @@ -id; - } - - /** - * Set entryId - * - * @param integer $entryId - * @return TagsEntries - */ - public function setEntryId($entryId) - { - $this->entryId = $entryId; - - return $this; - } - - /** - * Get entryId - * - * @return integer - */ - public function getEntryId() - { - return $this->entryId; - } - - /** - * Set tagId - * - * @param integer $tagId - * @return TagsEntries - */ - public function setTagId($tagId) - { - $this->tagId = $tagId; - - return $this; - } - - /** - * Get tagId - * - * @return integer - */ - public function getTagId() - { - return $this->tagId; - } -} diff --git a/src/Wallabag/CoreBundle/Repository/TagRepository.php b/src/Wallabag/CoreBundle/Repository/TagRepository.php index 903a99cda..0f362f79e 100644 --- a/src/Wallabag/CoreBundle/Repository/TagRepository.php +++ b/src/Wallabag/CoreBundle/Repository/TagRepository.php @@ -6,5 +6,18 @@ use Doctrine\ORM\EntityRepository; class TagRepository extends EntityRepository { + public function findByEntries($entryId) + { + $qb = $this->createQueryBuilder('t') + ->select('t') + ->leftJoin('t.id', 'u') + ->where('e.isStarred = true') + ->andWhere('u.id =:userId')->setParameter('userId', $userId) + ->orderBy('e.createdAt', 'desc') + ->getQuery(); + $paginator = new Paginator($qb); + + return $paginator; + } } diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index 0ffe7fe62..4164e5161 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php @@ -150,33 +150,4 @@ class WallabagRestControllerTest extends WallabagTestCase $this->assertEquals(404, $client->getResponse()->getStatusCode()); } - - public function testGetOneTag() - { - $client = $this->createClient(); - $client->request('GET', '/api/salts/admin.json'); - $salt = json_decode($client->getResponse()->getContent()); - - $headers = $this->generateHeaders('admin', 'test', $salt[0]); - - $tag = $client->getContainer() - ->get('doctrine.orm.entity_manager') - ->getRepository('WallabagCoreBundle:Tag') - ->findOneByLabel('foo'); - - if (!$tag) { - $this->markTestSkipped('No content found in db.'); - } - - $client->request('GET', '/api/tags/'.$tag->getLabel().'.json', array(), array(), $headers); - - $this->assertEquals(json_encode($tag), $client->getResponse()->getContent()); - - $this->assertTrue( - $client->getResponse()->headers->contains( - 'Content-Type', - 'application/json' - ) - ); - } } From 1bd12b62296569764ac329d88e964059dec530be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 20 Feb 2015 20:36:05 +0100 Subject: [PATCH 09/25] fix GET /api/entries/{entry}/tags --- src/Wallabag/CoreBundle/Controller/WallabagRestController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index b895b67cd..db9cf1be4 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -196,7 +196,7 @@ class WallabagRestController extends Controller */ public function getEntriesTagsAction(Entry $entry) { - $json = $this->get('serializer')->serialize($entry, 'json'); + $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); return new Response($json, 200, array('application/json')); } From 6c87418ff013cfd03093c3f01e20518e580d80bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Sun, 22 Feb 2015 21:25:24 +0100 Subject: [PATCH 10/25] fixtures for tag --- .../DataFixtures/ORM/LoadTagData.php | 19 +++++ .../CoreBundle/Entity/TagsEntries.php | 81 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 src/Wallabag/CoreBundle/Entity/TagsEntries.php diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php index 6b13c2bee..4d9846b61 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php @@ -6,6 +6,7 @@ use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\Persistence\ObjectManager; use Wallabag\CoreBundle\Entity\Tag; +use Wallabag\CoreBundle\Entity\TagsEntries; class LoadTagData extends AbstractFixture implements OrderedFixtureInterface { @@ -19,16 +20,34 @@ class LoadTagData extends AbstractFixture implements OrderedFixtureInterface $manager->persist($tag1); + $this->addReference('tag1', $tag1); + + $tagsEntries1 = new TagsEntries(); + $tagsEntries1->setEntryId($this->getReference('entry1')); + $manager->persist($tagsEntries1); + $tag2 = new Tag(); $tag2->setLabel('bar'); $manager->persist($tag2); + $this->addReference('tag2', $tag2); + + $tagsEntries2 = new TagsEntries(); + $tagsEntries2->setEntryId($this->getReference('entry2')); + $manager->persist($tagsEntries2); + $tag3 = new Tag(); $tag3->setLabel('baz'); $manager->persist($tag3); + $this->addReference('tag3', $tag3); + + $tagsEntries3 = new TagsEntries(); + $tagsEntries3->setEntryId($this->getReference('entry2')); + $manager->persist($tagsEntries3); + $manager->flush(); } diff --git a/src/Wallabag/CoreBundle/Entity/TagsEntries.php b/src/Wallabag/CoreBundle/Entity/TagsEntries.php new file mode 100644 index 000000000..589f26f82 --- /dev/null +++ b/src/Wallabag/CoreBundle/Entity/TagsEntries.php @@ -0,0 +1,81 @@ +id; + } + + /** + * @return mixed + */ + public function getEntryId() + { + return $this->entryId; + } + + /** + * @param mixed $entryId + */ + public function setEntryId($entryId) + { + $this->entryId = $entryId; + } + + /** + * @return mixed + */ + public function getTagId() + { + return $this->tagId; + } + + /** + * @param mixed $tagId + */ + public function setTagId($tagId) + { + $this->tagId = $tagId; + } + +} From 46bbd8d321e6a00131f0e6ed96fa6f3d693b3678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 24 Feb 2015 07:42:09 +0100 Subject: [PATCH 11/25] relation between tags and entries --- .../DataFixtures/ORM/LoadEntryData.php | 9 +++ .../DataFixtures/ORM/LoadTagData.php | 61 -------------- src/Wallabag/CoreBundle/Entity/Entry.php | 8 +- src/Wallabag/CoreBundle/Entity/Tag.php | 12 ++- .../CoreBundle/Entity/TagsEntries.php | 81 ------------------- .../CoreBundle/Repository/EntryRepository.php | 11 +++ .../Controller/WallabagRestControllerTest.php | 26 ++++++ 7 files changed, 60 insertions(+), 148 deletions(-) delete mode 100644 src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php delete mode 100644 src/Wallabag/CoreBundle/Entity/TagsEntries.php diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php index 3be323ed7..edab9adcd 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php @@ -6,6 +6,7 @@ use Doctrine\Common\DataFixtures\AbstractFixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\Persistence\ObjectManager; use Wallabag\CoreBundle\Entity\Entry; +use Wallabag\CoreBundle\Entity\Tag; class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface { @@ -37,6 +38,14 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface $entry3->setTitle('test title entry3'); $entry3->setContent('This is my content /o/'); + $tag1 = new Tag(); + $tag1->setLabel("foo"); + $tag2 = new Tag(); + $tag2->setLabel("bar"); + + $entry3->addTag($tag1); + $entry3->addTag($tag2); + $manager->persist($entry3); $this->addReference('entry3', $entry3); diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php deleted file mode 100644 index 4d9846b61..000000000 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadTagData.php +++ /dev/null @@ -1,61 +0,0 @@ -setLabel('foo'); - - $manager->persist($tag1); - - $this->addReference('tag1', $tag1); - - $tagsEntries1 = new TagsEntries(); - $tagsEntries1->setEntryId($this->getReference('entry1')); - $manager->persist($tagsEntries1); - - $tag2 = new Tag(); - $tag2->setLabel('bar'); - - $manager->persist($tag2); - - $this->addReference('tag2', $tag2); - - $tagsEntries2 = new TagsEntries(); - $tagsEntries2->setEntryId($this->getReference('entry2')); - $manager->persist($tagsEntries2); - - $tag3 = new Tag(); - $tag3->setLabel('baz'); - - $manager->persist($tag3); - - $this->addReference('tag3', $tag3); - - $tagsEntries3 = new TagsEntries(); - $tagsEntries3->setEntryId($this->getReference('entry2')); - $manager->persist($tagsEntries3); - - $manager->flush(); - } - - /** - * {@inheritDoc} - */ - public function getOrder() - { - return 30; - } -} diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index e0d1b839c..229a67045 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php @@ -120,11 +120,8 @@ class Entry private $user; /** - * @ORM\ManyToMany(targetEntity="Tag", inversedBy="entries", cascade={"persist", "merge"}) - * @ORM\JoinTable(name="tags_entries", - * joinColumns={@ORM\JoinColumn(name="entry_id", referencedColumnName="id")}, - * inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id")} - * ) + * @ORM\ManyToMany(targetEntity="Tag", inversedBy="entries", cascade={"persist"}) + * @ORM\JoinTable(name="entry_tags") */ private $tags; @@ -407,5 +404,6 @@ class Entry public function addTag(Tag $tag) { $this->tags[] = $tag; + $tag->addEntry($this); } } diff --git a/src/Wallabag/CoreBundle/Entity/Tag.php b/src/Wallabag/CoreBundle/Entity/Tag.php index 1cdf4df02..5aed1fa01 100644 --- a/src/Wallabag/CoreBundle/Entity/Tag.php +++ b/src/Wallabag/CoreBundle/Entity/Tag.php @@ -6,6 +6,7 @@ use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation\XmlRoot; use JMS\Serializer\Annotation\ExclusionPolicy; use JMS\Serializer\Annotation\Expose; +use Doctrine\Common\Collections\ArrayCollection; /** * Tag @@ -36,10 +37,14 @@ class Tag private $label; /** - * @ORM\ManyToMany(targetEntity="Entry", mappedBy="tags", cascade={"persist", "merge"}) + * @ORM\ManyToMany(targetEntity="Entry", mappedBy="tags", cascade={"persist"}) */ private $entries; + public function __construct() + { + $this->entries = new ArrayCollection(); + } /** * Get id * @@ -72,4 +77,9 @@ class Tag { return $this->label; } + + public function addEntry(Entry $entry) + { + $this->entries[] = $entry; + } } diff --git a/src/Wallabag/CoreBundle/Entity/TagsEntries.php b/src/Wallabag/CoreBundle/Entity/TagsEntries.php deleted file mode 100644 index 589f26f82..000000000 --- a/src/Wallabag/CoreBundle/Entity/TagsEntries.php +++ /dev/null @@ -1,81 +0,0 @@ -id; - } - - /** - * @return mixed - */ - public function getEntryId() - { - return $this->entryId; - } - - /** - * @param mixed $entryId - */ - public function setEntryId($entryId) - { - $this->entryId = $entryId; - } - - /** - * @return mixed - */ - public function getTagId() - { - return $this->tagId; - } - - /** - * @param mixed $tagId - */ - public function setTagId($tagId) - { - $this->tagId = $tagId; - } - -} diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index 005142fc5..f6f60c6fe 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -118,4 +118,15 @@ class EntryRepository extends EntityRepository ->getQuery() ->getResult(); } + + public function findOneWithTags() + { + $qb = $this->createQueryBuilder('e') + ->innerJoin('e.tags', 't') + ->addSelect('t'); + + return $qb + ->getQuery() + ->getOneOrNullResult(); + } } diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index 4164e5161..d23900556 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php @@ -150,4 +150,30 @@ class WallabagRestControllerTest extends WallabagTestCase $this->assertEquals(404, $client->getResponse()->getStatusCode()); } + + public function testGetTagsEntry() + { + $client = $this->createClient(); + $client->request('GET', '/api/salts/admin.json'); + $salt = json_decode($client->getResponse()->getContent()); + $headers = $this->generateHeaders('admin', 'test', $salt[0]); + + $entry = $client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCoreBundle:Entry') + ->findOneWithTags(); + + if (!$entry) { + $this->markTestSkipped('No content found in db.'); + } + + $tags = array(); + foreach ($entry->getTags() as $tag) { + $tags[] = array('id' => $tag->getId(), 'label' => $tag->getLabel()); + } + + $client->request('GET', '/api/entries/'.$entry->getId().'/tags', array(), array(), $headers); + + $this->assertEquals(json_encode($tags), $client->getResponse()->getContent()); + } } From a36737f4859e3acbddf5cfe90c279ba725a6d88a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Tue, 24 Feb 2015 22:00:24 +0100 Subject: [PATCH 12/25] POST entries/tags with test --- .../Controller/WallabagRestController.php | 28 +++++++++++++- .../CoreBundle/Repository/EntryRepository.php | 5 +++ .../Controller/WallabagRestControllerTest.php | 37 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index db9cf1be4..e59ad4b7b 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -213,8 +213,34 @@ class WallabagRestController extends Controller * } * ) */ - public function postEntriesTagsAction(Entry $entry) + public function postEntriesTagsAction(Request $request, Entry $entry) { + $tags = explode(',', $request->request->get('tags')); + + foreach ($tags as $label) { + $tagEntity = $this + ->getDoctrine() + ->getRepository('WallabagCoreBundle:Tag') + ->findOneByLabel($label); + + if (is_null($tagEntity)) { + $tagEntity = new Tag(); + $tagEntity->setLabel($label); + } + + // only add the tag on the entry if the relation doesn't exist + if (!$entry->getTags()->contains($tagEntity)) { + $entry->addTag($tagEntity); + } + } + + $em = $this->getDoctrine()->getManager(); + $em->persist($entry); + $em->flush(); + + $json = $this->get('serializer')->serialize($entry, 'json'); + + return new Response($json, 200, array('application/json')); } /** diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index f6f60c6fe..10fb9bf79 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -119,6 +119,11 @@ class EntryRepository extends EntityRepository ->getResult(); } + /** + * Fetch an entry with a tag. Only used for tests. + * + * @return Entry + */ public function findOneWithTags() { $qb = $this->createQueryBuilder('e') diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index d23900556..cadbb70b7 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php @@ -176,4 +176,41 @@ class WallabagRestControllerTest extends WallabagTestCase $this->assertEquals(json_encode($tags), $client->getResponse()->getContent()); } + + public function testPostTagsOnEntry() + { + $client = $this->createClient(); + $client->request('GET', '/api/salts/admin.json'); + $salt = json_decode($client->getResponse()->getContent()); + $headers = $this->generateHeaders('admin', 'test', $salt[0]); + + $entry = $client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCoreBundle:Entry') + ->findOneByUser(1); + + if (!$entry) { + $this->markTestSkipped('No content found in db.'); + } + + $newTags = 'tag1,tag2,tag3'; + + $client->request('POST', '/api/entries/'.$entry->getId().'/tags', array('tags' => $newTags), array(), $headers); + + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + + $entryDB = $client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCoreBundle:Entry') + ->find($entry->getId()); + + $tagsInDB = array(); + foreach ($entryDB->getTags()->toArray() as $tag) { + $tagsInDB[$tag->getId()] = $tag->getLabel(); + } + + foreach (explode(',', $newTags) as $tag) { + $this->assertContains($tag, $tagsInDB); + } + } } From 092ca70725b0263390e45c46f93828c613eca3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Thu, 26 Feb 2015 09:41:42 +0100 Subject: [PATCH 13/25] add relation between user and tags, tests are broken --- .../Controller/WallabagRestController.php | 104 ++++++++++++++---- .../DataFixtures/ORM/LoadEntryData.php | 4 +- src/Wallabag/CoreBundle/Entity/Entry.php | 5 + src/Wallabag/CoreBundle/Entity/Tag.php | 8 +- src/Wallabag/CoreBundle/Entity/User.php | 30 ++++- .../CoreBundle/Repository/EntryRepository.php | 7 +- .../Controller/WallabagRestControllerTest.php | 4 +- 7 files changed, 131 insertions(+), 31 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index e59ad4b7b..81bfbe12a 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -9,9 +9,35 @@ use Symfony\Component\HttpFoundation\Response; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; use Wallabag\CoreBundle\Service\Extractor; +use Symfony\Component\Security\Core\Exception\AccessDeniedException; class WallabagRestController extends Controller { + /** + * @param Entry $entry + * @param string $tags + */ + private function assignTagsToEntry(Entry $entry, $tags) + { + foreach (explode(',', $tags) as $label) { + $label = trim($label); + $tagEntity = $this + ->getDoctrine() + ->getRepository('WallabagCoreBundle:Tag') + ->findOneByLabel($label); + + if (is_null($tagEntity)) { + $tagEntity = new Tag($this->getUser()); + $tagEntity->setLabel($label); + } + + // only add the tag on the entry if the relation doesn't exist + if (!$entry->getTags()->contains($tagEntity)) { + $entry->addTag($tagEntity); + } + } + } + /** * Retrieve salt for a giver user. * @@ -87,6 +113,10 @@ class WallabagRestController extends Controller */ public function getEntryAction(Entry $entry) { + if ($entry->getUser()->getId() != $this->getUser()->getId()) { + throw $this->createAccessDeniedException(); + } + $json = $this->get('serializer')->serialize($entry, 'json'); return new Response($json, 200, array('application/json')); @@ -106,7 +136,6 @@ class WallabagRestController extends Controller */ public function postEntriesAction(Request $request) { - //TODO gérer si on passe les tags $url = $request->request->get('url'); $content = Extractor::extract($url); @@ -114,6 +143,9 @@ class WallabagRestController extends Controller $entry->setUrl($url); $entry->setTitle($request->request->get('title') ?: $content->getTitle()); $entry->setContent($content->getBody()); + + $this->assignTagsToEntry($entry, $request->request->get('tags', array())); + $em = $this->getDoctrine()->getManager(); $em->persist($entry); $em->flush(); @@ -141,8 +173,11 @@ class WallabagRestController extends Controller */ public function patchEntriesAction(Entry $entry, Request $request) { + if ($entry->getUser()->getId() != $this->getUser()->getId()) { + throw $this->createAccessDeniedException(); + } + $title = $request->request->get("title"); - $tags = $request->request->get("tags", array()); $isArchived = $request->request->get("archive"); $isStarred = $request->request->get("star"); @@ -158,6 +193,8 @@ class WallabagRestController extends Controller $entry->setStarred($isStarred); } + $this->assignTagsToEntry($entry, $request->request->get('tags', array())); + $em = $this->getDoctrine()->getManager(); $em->flush(); @@ -176,6 +213,10 @@ class WallabagRestController extends Controller */ public function deleteEntriesAction(Entry $entry) { + if ($entry->getUser()->getId() != $this->getUser()->getId()) { + throw $this->createAccessDeniedException(); + } + $em = $this->getDoctrine()->getManager(); $em->remove($entry); $em->flush(); @@ -196,6 +237,12 @@ class WallabagRestController extends Controller */ public function getEntriesTagsAction(Entry $entry) { + var_dump($entry->getUser()->getId()); + var_dump($this->getUser()->getId()); + if ($entry->getUser()->getId() != $this->getUser()->getId()) { + throw $this->createAccessDeniedException(); + } + $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); return new Response($json, 200, array('application/json')); @@ -215,25 +262,12 @@ class WallabagRestController extends Controller */ public function postEntriesTagsAction(Request $request, Entry $entry) { - $tags = explode(',', $request->request->get('tags')); - - foreach ($tags as $label) { - $tagEntity = $this - ->getDoctrine() - ->getRepository('WallabagCoreBundle:Tag') - ->findOneByLabel($label); - - if (is_null($tagEntity)) { - $tagEntity = new Tag(); - $tagEntity->setLabel($label); - } - - // only add the tag on the entry if the relation doesn't exist - if (!$entry->getTags()->contains($tagEntity)) { - $entry->addTag($tagEntity); - } + if ($entry->getUser()->getId() != $this->getUser()->getId()) { + throw $this->createAccessDeniedException(); } + $this->assignTagsToEntry($entry, $request->request->get('tags', array())); + $em = $this->getDoctrine()->getManager(); $em->persist($entry); $em->flush(); @@ -255,17 +289,30 @@ class WallabagRestController extends Controller */ public function deleteEntriesTagsAction(Entry $entry, Tag $tag) { + if ($entry->getUser()->getId() != $this->getUser()->getId()) { + throw $this->createAccessDeniedException(); + } + + $entry->removeTag($tag); + $em = $this->getDoctrine()->getManager(); + $em->persist($entry); + $em->flush(); + + $json = $this->get('serializer')->serialize($entry, 'json'); + + return new Response($json, 200, array('application/json')); } /** * Retrieve all tags * - * @ApiDoc( - * {"name"="user", "dataType"="integer", "requirement"="\w+", "description"="The user ID"} - * ) + * @ApiDoc() */ - public function getTagsUserAction() + public function getTagsAction() { + $json = $this->get('serializer')->serialize($this->getUser()->getTags(), 'json'); + + return new Response($json, 200, array('application/json')); } /** @@ -279,5 +326,16 @@ class WallabagRestController extends Controller */ public function deleteTagAction(Tag $tag) { + if ($tag->getUser()->getId() != $this->getUser()->getId()) { + throw $this->createAccessDeniedException(); + } + + $em = $this->getDoctrine()->getManager(); + $em->remove($tag); + $em->flush(); + + $json = $this->get('serializer')->serialize($tag, 'json'); + + return new Response($json, 200, array('application/json')); } } diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php index edab9adcd..b0f077550 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php @@ -38,9 +38,9 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface $entry3->setTitle('test title entry3'); $entry3->setContent('This is my content /o/'); - $tag1 = new Tag(); + $tag1 = new Tag($this->getReference('admin-user')); $tag1->setLabel("foo"); - $tag2 = new Tag(); + $tag2 = new Tag($this->getReference('admin-user')); $tag2->setLabel("bar"); $entry3->addTag($tag1); diff --git a/src/Wallabag/CoreBundle/Entity/Entry.php b/src/Wallabag/CoreBundle/Entity/Entry.php index 229a67045..75aeae84b 100644 --- a/src/Wallabag/CoreBundle/Entity/Entry.php +++ b/src/Wallabag/CoreBundle/Entity/Entry.php @@ -406,4 +406,9 @@ class Entry $this->tags[] = $tag; $tag->addEntry($this); } + + public function removeTag(Tag $tag) + { + $this->tags->removeElement($tag); + } } diff --git a/src/Wallabag/CoreBundle/Entity/Tag.php b/src/Wallabag/CoreBundle/Entity/Tag.php index 5aed1fa01..29a5e4b5e 100644 --- a/src/Wallabag/CoreBundle/Entity/Tag.php +++ b/src/Wallabag/CoreBundle/Entity/Tag.php @@ -41,8 +41,14 @@ class Tag */ private $entries; - public function __construct() + /** + * @ORM\ManyToOne(targetEntity="User", inversedBy="tags") + */ + private $user; + + public function __construct(User $user) { + $this->user = $user; $this->entries = new ArrayCollection(); } /** diff --git a/src/Wallabag/CoreBundle/Entity/User.php b/src/Wallabag/CoreBundle/Entity/User.php index 5589c039e..f05c8760e 100644 --- a/src/Wallabag/CoreBundle/Entity/User.php +++ b/src/Wallabag/CoreBundle/Entity/User.php @@ -101,10 +101,17 @@ class User implements AdvancedUserInterface, \Serializable */ private $config; + /** + * @ORM\OneToMany(targetEntity="Tag", mappedBy="user", cascade={"remove"}) + */ + private $tags; + public function __construct() { - $this->salt = md5(uniqid(null, true)); - $this->entries = new ArrayCollection(); + $this->isActive = true; + $this->salt = md5(uniqid(null, true)); + $this->entries = new ArrayCollection(); + $this->tags = new ArrayCollection(); } /** @@ -278,6 +285,25 @@ class User implements AdvancedUserInterface, \Serializable return $this->entries; } + /** + * @param Entry $entry + * + * @return User + */ + public function addTag(Tag $tag) + { + $this->tags[] = $tag; + + return $this; + } + + /** + * @return ArrayCollection + */ + public function getTags() + { + return $this->tags; + } /** * @inheritDoc */ diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index 10fb9bf79..a8085ac9c 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -124,11 +124,14 @@ class EntryRepository extends EntityRepository * * @return Entry */ - public function findOneWithTags() + public function findOneWithTags($userId) { $qb = $this->createQueryBuilder('e') ->innerJoin('e.tags', 't') - ->addSelect('t'); + ->addSelect('t') + ->where('t.user=:userId')->setParameter('userId', 1); + + return $qb->getQuery()->getOneOrNullResult(); return $qb ->getQuery() diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index cadbb70b7..044485376 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php @@ -161,7 +161,9 @@ class WallabagRestControllerTest extends WallabagTestCase $entry = $client->getContainer() ->get('doctrine.orm.entity_manager') ->getRepository('WallabagCoreBundle:Entry') - ->findOneWithTags(); + ->findOneWithTags(1); + + var_dump($entry->getTitle()); if (!$entry) { $this->markTestSkipped('No content found in db.'); From d8f9f37ab2deb172f8dfc58b3b3775990188762f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Thu, 26 Feb 2015 12:35:59 +0100 Subject: [PATCH 14/25] remove debug lines --- src/Wallabag/CoreBundle/Controller/WallabagRestController.php | 2 -- src/Wallabag/CoreBundle/Repository/EntryRepository.php | 4 ---- .../Tests/Controller/WallabagRestControllerTest.php | 2 -- 3 files changed, 8 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index 81bfbe12a..4215e4478 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -237,8 +237,6 @@ class WallabagRestController extends Controller */ public function getEntriesTagsAction(Entry $entry) { - var_dump($entry->getUser()->getId()); - var_dump($this->getUser()->getId()); if ($entry->getUser()->getId() != $this->getUser()->getId()) { throw $this->createAccessDeniedException(); } diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index a8085ac9c..e102edc7a 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -132,9 +132,5 @@ class EntryRepository extends EntityRepository ->where('t.user=:userId')->setParameter('userId', 1); return $qb->getQuery()->getOneOrNullResult(); - - return $qb - ->getQuery() - ->getOneOrNullResult(); } } diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index 044485376..b0f4a8425 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php @@ -163,8 +163,6 @@ class WallabagRestControllerTest extends WallabagTestCase ->getRepository('WallabagCoreBundle:Entry') ->findOneWithTags(1); - var_dump($entry->getTitle()); - if (!$entry) { $this->markTestSkipped('No content found in db.'); } From 0ca374e6a1698926b08635d6a276ff3bf91c76a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Thu, 26 Feb 2015 14:25:40 +0100 Subject: [PATCH 15/25] replace Response with JsonResponse --- .../Controller/WallabagRestController.php | 44 ++++++++++++------- .../CoreBundle/Repository/EntryRepository.php | 8 ++-- .../CoreBundle/Repository/TagRepository.php | 14 ------ 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index 4215e4478..a382caf75 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -5,11 +5,10 @@ namespace Wallabag\CoreBundle\Controller; use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\JsonResponse; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; use Wallabag\CoreBundle\Service\Extractor; -use Symfony\Component\Security\Core\Exception\AccessDeniedException; class WallabagRestController extends Controller { @@ -48,12 +47,12 @@ class WallabagRestController extends Controller * ) * @return array */ - public function getSaltAction($username) + public function getSaltAction(Request $request) { $user = $this ->getDoctrine() ->getRepository('WallabagCoreBundle:User') - ->findOneByUsername($username); + ->findOneByUsername($request->query->get('username')); if (is_null($user)) { throw $this->createNotFoundException(); @@ -98,7 +97,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entries, 'json'); - return new Response($json, 200, array('application/json')); + return new JsonResponse($json, 200); } /** @@ -119,7 +118,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new Response($json, 200, array('application/json')); + return new JsonResponse($json, 200); } /** @@ -144,7 +143,10 @@ class WallabagRestController extends Controller $entry->setTitle($request->request->get('title') ?: $content->getTitle()); $entry->setContent($content->getBody()); - $this->assignTagsToEntry($entry, $request->request->get('tags', array())); + $tags = $request->request->get('tags', ''); + if (!empty($tags)) { + $this->assignTagsToEntry($entry, $tags); + } $em = $this->getDoctrine()->getManager(); $em->persist($entry); @@ -152,7 +154,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new Response($json, 200, array('application/json')); + return new JsonResponse($json, 200); } /** @@ -193,12 +195,17 @@ class WallabagRestController extends Controller $entry->setStarred($isStarred); } - $this->assignTagsToEntry($entry, $request->request->get('tags', array())); + $tags = $request->request->get('tags', ''); + if (!empty($tags)) { + $this->assignTagsToEntry($entry, $tags); + } $em = $this->getDoctrine()->getManager(); $em->flush(); - return $entry; + $json = $this->get('serializer')->serialize($entry, 'json'); + + return new JsonResponse($json, 200); } /** @@ -223,7 +230,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new Response($json, 200, array('application/json')); + return new JsonResponse($json, 200); } /** @@ -243,7 +250,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); - return new Response($json, 200, array('application/json')); + return new JsonResponse($json, 200); } /** @@ -264,7 +271,10 @@ class WallabagRestController extends Controller throw $this->createAccessDeniedException(); } - $this->assignTagsToEntry($entry, $request->request->get('tags', array())); + $tags = $request->request->get('tags', ''); + if (!empty($tags)) { + $this->assignTagsToEntry($entry, $tags); + } $em = $this->getDoctrine()->getManager(); $em->persist($entry); @@ -272,7 +282,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new Response($json, 200, array('application/json')); + return new JsonResponse($json, 200); } /** @@ -298,7 +308,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new Response($json, 200, array('application/json')); + return new JsonResponse($json, 200); } /** @@ -310,7 +320,7 @@ class WallabagRestController extends Controller { $json = $this->get('serializer')->serialize($this->getUser()->getTags(), 'json'); - return new Response($json, 200, array('application/json')); + return new JsonResponse($json, 200); } /** @@ -334,6 +344,6 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($tag, 'json'); - return new Response($json, 200, array('application/json')); + return new JsonResponse($json, 200); } } diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index e102edc7a..04fe6aa34 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -128,9 +128,11 @@ class EntryRepository extends EntityRepository { $qb = $this->createQueryBuilder('e') ->innerJoin('e.tags', 't') - ->addSelect('t') - ->where('t.user=:userId')->setParameter('userId', 1); + ->innerJoin('e.user', 'u') + ->addSelect('t', 'u') + ->where('e.user=:userId')->setParameter('userId', $userId) + ; - return $qb->getQuery()->getOneOrNullResult(); + return $qb->getQuery()->getResult(); } } diff --git a/src/Wallabag/CoreBundle/Repository/TagRepository.php b/src/Wallabag/CoreBundle/Repository/TagRepository.php index 0f362f79e..52f319f11 100644 --- a/src/Wallabag/CoreBundle/Repository/TagRepository.php +++ b/src/Wallabag/CoreBundle/Repository/TagRepository.php @@ -6,18 +6,4 @@ use Doctrine\ORM\EntityRepository; class TagRepository extends EntityRepository { - public function findByEntries($entryId) - { - $qb = $this->createQueryBuilder('t') - ->select('t') - ->leftJoin('t.id', 'u') - ->where('e.isStarred = true') - ->andWhere('u.id =:userId')->setParameter('userId', $userId) - ->orderBy('e.createdAt', 'desc') - ->getQuery(); - - $paginator = new Paginator($qb); - - return $paginator; - } } From 6ee416a06963916ca8050e7711538d4e9463a2bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Thu, 26 Feb 2015 15:00:28 +0100 Subject: [PATCH 16/25] commit bug with getSalt --- .../CoreBundle/Controller/WallabagRestController.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index a382caf75..819743714 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -40,19 +40,15 @@ class WallabagRestController extends Controller /** * Retrieve salt for a giver user. * - * @ApiDoc( - * parameters={ - * {"name"="username", "dataType"="string", "required"=true, "description"="username"} - * } - * ) + * @ApiDoc() * @return array */ - public function getSaltAction(Request $request) + public function getSaltAction($username) { $user = $this ->getDoctrine() ->getRepository('WallabagCoreBundle:User') - ->findOneByUsername($request->query->get('username')); + ->findOneByUsername($username); if (is_null($user)) { throw $this->createNotFoundException(); From 1df1204d94a26cda064886c827a23ba642ebc769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Thu, 26 Feb 2015 15:27:00 +0100 Subject: [PATCH 17/25] remove useless code --- .../Tests/Controller/WallabagRestControllerTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index b0f4a8425..7ccc37d20 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php @@ -44,10 +44,6 @@ class WallabagRestControllerTest extends WallabagTestCase public function testWithBadHeaders() { $client = $this->createClient(); - $client->request('GET', '/api/salts/admin.json'); - $salt = json_decode($client->getResponse()->getContent()); - - $headers = $this->generateHeaders('admin', 'mypassword', $salt[0]); $entry = $client->getContainer() ->get('doctrine.orm.entity_manager') From b0cce9e6369b0b821c01163a0e4df5552f9924f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 27 Feb 2015 15:24:36 +0100 Subject: [PATCH 18/25] fix tests for GET /entries/tags --- .../Controller/WallabagRestController.php | 3 ++- .../DataFixtures/ORM/LoadEntryData.php | 21 +++++++++++++++++-- .../Controller/WallabagRestControllerTest.php | 4 +++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index 819743714..e25ac6db8 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -6,6 +6,7 @@ use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Response; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; use Wallabag\CoreBundle\Service\Extractor; @@ -246,7 +247,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); - return new JsonResponse($json, 200); + return new Response($json, 200, array('application/json')); } /** diff --git a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php index b0f077550..ce12ec5d5 100644 --- a/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php +++ b/src/Wallabag/CoreBundle/DataFixtures/ORM/LoadEntryData.php @@ -38,9 +38,9 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface $entry3->setTitle('test title entry3'); $entry3->setContent('This is my content /o/'); - $tag1 = new Tag($this->getReference('admin-user')); + $tag1 = new Tag($this->getReference('bob-user')); $tag1->setLabel("foo"); - $tag2 = new Tag($this->getReference('admin-user')); + $tag2 = new Tag($this->getReference('bob-user')); $tag2->setLabel("bar"); $entry3->addTag($tag1); @@ -50,6 +50,23 @@ class LoadEntryData extends AbstractFixture implements OrderedFixtureInterface $this->addReference('entry3', $entry3); + $entry4 = new Entry($this->getReference('admin-user')); + $entry4->setUrl('http://0.0.0.0'); + $entry4->setTitle('test title entry4'); + $entry4->setContent('This is my content /o/'); + + $tag1 = new Tag($this->getReference('admin-user')); + $tag1->setLabel("foo"); + $tag2 = new Tag($this->getReference('admin-user')); + $tag2->setLabel("bar"); + + $entry4->addTag($tag1); + $entry4->addTag($tag2); + + $manager->persist($entry4); + + $this->addReference('entry4', $entry4); + $manager->flush(); } diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index 7ccc37d20..c45e52d78 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php @@ -159,6 +159,8 @@ class WallabagRestControllerTest extends WallabagTestCase ->getRepository('WallabagCoreBundle:Entry') ->findOneWithTags(1); + $entry = $entry[0]; + if (!$entry) { $this->markTestSkipped('No content found in db.'); } @@ -170,7 +172,7 @@ class WallabagRestControllerTest extends WallabagTestCase $client->request('GET', '/api/entries/'.$entry->getId().'/tags', array(), array(), $headers); - $this->assertEquals(json_encode($tags), $client->getResponse()->getContent()); + $this->assertEquals(json_encode($tags, JSON_HEX_QUOT), $client->getResponse()->getContent()); } public function testPostTagsOnEntry() From db2b4bf678c4c9e778ed0b817df182c9ee06520f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Fri, 27 Feb 2015 17:51:36 +0100 Subject: [PATCH 19/25] remove JsonResponse --- .../Controller/WallabagRestController.php | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index e25ac6db8..612c59d11 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -5,7 +5,6 @@ namespace Wallabag\CoreBundle\Controller; use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; @@ -94,7 +93,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entries, 'json'); - return new JsonResponse($json, 200); + return new Response($json, 200, array('application/json')); } /** @@ -115,7 +114,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new JsonResponse($json, 200); + return new Response($json, 200, array('application/json')); } /** @@ -151,7 +150,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new JsonResponse($json, 200); + return new Response($json, 200, array('application/json')); } /** @@ -202,7 +201,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new JsonResponse($json, 200); + return new Response($json, 200, array('application/json')); } /** @@ -227,7 +226,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new JsonResponse($json, 200); + return new Response($json, 200, array('application/json')); } /** @@ -279,7 +278,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new JsonResponse($json, 200); + return new Response($json, 200, array('application/json')); } /** @@ -305,7 +304,7 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($entry, 'json'); - return new JsonResponse($json, 200); + return new Response($json, 200, array('application/json')); } /** @@ -317,7 +316,7 @@ class WallabagRestController extends Controller { $json = $this->get('serializer')->serialize($this->getUser()->getTags(), 'json'); - return new JsonResponse($json, 200); + return new Response($json, 200, array('application/json')); } /** @@ -341,6 +340,6 @@ class WallabagRestController extends Controller $json = $this->get('serializer')->serialize($tag, 'json'); - return new JsonResponse($json, 200); + return new Response($json, 200, array('application/json')); } } From 2ab8cb681608d5887e0b6a92fcafff600a435e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Sat, 28 Feb 2015 14:22:11 +0100 Subject: [PATCH 20/25] fix tests --- .../Tests/Controller/WallabagRestControllerTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php index c45e52d78..0eca7cde6 100644 --- a/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php +++ b/src/Wallabag/CoreBundle/Tests/Controller/WallabagRestControllerTest.php @@ -140,7 +140,7 @@ class WallabagRestControllerTest extends WallabagTestCase $client->request('GET', '/api/salts/admin.json'); $salt = json_decode($client->getResponse()->getContent()); - $headers = $this->generateHeaders('admin', 'test', $salt[0]); + $headers = $this->generateHeaders('admin', 'mypassword', $salt[0]); $client->request('DELETE', '/api/entries/'.$entry->getId().'.json', array(), array(), $headers); @@ -152,7 +152,7 @@ class WallabagRestControllerTest extends WallabagTestCase $client = $this->createClient(); $client->request('GET', '/api/salts/admin.json'); $salt = json_decode($client->getResponse()->getContent()); - $headers = $this->generateHeaders('admin', 'test', $salt[0]); + $headers = $this->generateHeaders('admin', 'mypassword', $salt[0]); $entry = $client->getContainer() ->get('doctrine.orm.entity_manager') @@ -180,7 +180,7 @@ class WallabagRestControllerTest extends WallabagTestCase $client = $this->createClient(); $client->request('GET', '/api/salts/admin.json'); $salt = json_decode($client->getResponse()->getContent()); - $headers = $this->generateHeaders('admin', 'test', $salt[0]); + $headers = $this->generateHeaders('admin', 'mypassword', $salt[0]); $entry = $client->getContainer() ->get('doctrine.orm.entity_manager') From efad7e53a1e881dd686c003b624b429ee1e5b52e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Thu, 5 Mar 2015 19:34:30 +0100 Subject: [PATCH 21/25] add more log on AccessDeniedException --- .../Controller/WallabagRestController.php | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index 612c59d11..3e25fe49b 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -40,7 +40,11 @@ class WallabagRestController extends Controller /** * Retrieve salt for a giver user. * - * @ApiDoc() + * @ApiDoc( + * parameters={ + * {"name"="username", "dataType"="string", "required"=true, "description"="username"} + * } + * ) * @return array */ public function getSaltAction($username) @@ -87,7 +91,7 @@ class WallabagRestController extends Controller ->getRepository('WallabagCoreBundle:Entry') ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order); - if (!($entries)) { + if (!$entries) { throw $this->createNotFoundException(); } @@ -109,7 +113,7 @@ class WallabagRestController extends Controller public function getEntryAction(Entry $entry) { if ($entry->getUser()->getId() != $this->getUser()->getId()) { - throw $this->createAccessDeniedException(); + throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId()); } $json = $this->get('serializer')->serialize($entry, 'json'); @@ -172,7 +176,7 @@ class WallabagRestController extends Controller public function patchEntriesAction(Entry $entry, Request $request) { if ($entry->getUser()->getId() != $this->getUser()->getId()) { - throw $this->createAccessDeniedException(); + throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId()); } $title = $request->request->get("title"); @@ -217,7 +221,7 @@ class WallabagRestController extends Controller public function deleteEntriesAction(Entry $entry) { if ($entry->getUser()->getId() != $this->getUser()->getId()) { - throw $this->createAccessDeniedException(); + throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId()); } $em = $this->getDoctrine()->getManager(); @@ -241,7 +245,7 @@ class WallabagRestController extends Controller public function getEntriesTagsAction(Entry $entry) { if ($entry->getUser()->getId() != $this->getUser()->getId()) { - throw $this->createAccessDeniedException(); + throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId()); } $json = $this->get('serializer')->serialize($entry->getTags(), 'json'); @@ -264,7 +268,7 @@ class WallabagRestController extends Controller public function postEntriesTagsAction(Request $request, Entry $entry) { if ($entry->getUser()->getId() != $this->getUser()->getId()) { - throw $this->createAccessDeniedException(); + throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId()); } $tags = $request->request->get('tags', ''); @@ -294,7 +298,7 @@ class WallabagRestController extends Controller public function deleteEntriesTagsAction(Entry $entry, Tag $tag) { if ($entry->getUser()->getId() != $this->getUser()->getId()) { - throw $this->createAccessDeniedException(); + throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$entry->getUser()->getId().', logged user id: '.$this->getUser()->getId()); } $entry->removeTag($tag); @@ -331,7 +335,7 @@ class WallabagRestController extends Controller public function deleteTagAction(Tag $tag) { if ($tag->getUser()->getId() != $this->getUser()->getId()) { - throw $this->createAccessDeniedException(); + throw $this->createAccessDeniedException('Access forbidden. Entry user id: '.$tag->getUser()->getId().', logged user id: '.$this->getUser()->getId()); } $em = $this->getDoctrine()->getManager(); From 48b67328e24f1cde00287613507a8f5fcd222f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20L=C5=93uillet?= Date: Thu, 5 Mar 2015 19:41:23 +0100 Subject: [PATCH 22/25] add getUser on Tag entity --- src/Wallabag/CoreBundle/Entity/Tag.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Wallabag/CoreBundle/Entity/Tag.php b/src/Wallabag/CoreBundle/Entity/Tag.php index 29a5e4b5e..9ae5867c6 100644 --- a/src/Wallabag/CoreBundle/Entity/Tag.php +++ b/src/Wallabag/CoreBundle/Entity/Tag.php @@ -88,4 +88,12 @@ class Tag { $this->entries[] = $entry; } + + /** + * @return User + */ + public function getUser() + { + return $this->user; + } } From a24f2c8808fe4921ebad475162ef58ed73305281 Mon Sep 17 00:00:00 2001 From: William Durand Date: Fri, 6 Mar 2015 11:06:46 +0100 Subject: [PATCH 23/25] Add Pagerfanta --- composer.json | 3 ++- composer.lock | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 0793bcab3..590e26293 100644 --- a/composer.json +++ b/composer.json @@ -83,7 +83,8 @@ "wallabag/PHPePub": "dev-master", "wallabag/php-readability": "dev-master", "wallabag/phpMobi": "dev-master", - "wallabag/Fivefilters_Libraries": "dev-master" + "wallabag/Fivefilters_Libraries": "dev-master", + "pagerfanta/pagerfanta": "~1.0@dev" }, "require-dev": { "doctrine/doctrine-fixtures-bundle": "dev-master", diff --git a/composer.lock b/composer.lock index f5b232803..66f4738b2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "a078afa674d2816ebe7f7ad333d9f3b4", + "hash": "43d869c37ae73d7b74d3f77c4028bf9c", "packages": [ { "name": "doctrine/annotations", @@ -1638,6 +1638,73 @@ ], "time": "2014-12-10 17:26:49" }, + { + "name": "pagerfanta/pagerfanta", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/whiteoctober/Pagerfanta.git", + "reference": "a874d3612d954dcbbb49e5ffe178890918fb76fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/whiteoctober/Pagerfanta/zipball/a874d3612d954dcbbb49e5ffe178890918fb76fb", + "reference": "a874d3612d954dcbbb49e5ffe178890918fb76fb", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "doctrine/orm": "~2.3", + "doctrine/phpcr-odm": "1.*", + "jackalope/jackalope-doctrine-dbal": "1.*", + "jmikola/geojson": "~1.0", + "mandango/mandango": "~1.0@dev", + "mandango/mondator": "~1.0@dev", + "phpunit/phpunit": "~4", + "propel/propel1": "~1.6", + "ruflin/elastica": "~1.3", + "solarium/solarium": "~3.1" + }, + "suggest": { + "doctrine/mongodb-odm": "To use the DoctrineODMMongoDBAdapter.", + "doctrine/orm": "To use the DoctrineORMAdapter.", + "doctrine/phpcr-odm": "To use the DoctrineODMPhpcrAdapter. >= 1.1.0", + "mandango/mandango": "To use the MandangoAdapter.", + "propel/propel1": "To use the PropelAdapter", + "solarium/solarium": "To use the SolariumAdapter." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pagerfanta\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Pablo Díez", + "email": "pablodip@gmail.com" + } + ], + "description": "Pagination for PHP 5.3", + "keywords": [ + "page", + "pagination", + "paginator", + "paging" + ], + "time": "2014-10-06 10:57:25" + }, { "name": "phpcollection/phpcollection", "version": "0.4.0", @@ -4194,6 +4261,7 @@ "wallabag/php-readability": 20, "wallabag/phpmobi": 20, "wallabag/fivefilters_libraries": 20, + "pagerfanta/pagerfanta": 20, "doctrine/doctrine-fixtures-bundle": 20 }, "prefer-stable": true, From bcf53ab75b2fbd0cc18faf2db61c81fa3d7c471d Mon Sep 17 00:00:00 2001 From: William Durand Date: Fri, 6 Mar 2015 11:07:22 +0100 Subject: [PATCH 24/25] Return pager into EntryRepository (for entries only) --- src/Wallabag/CoreBundle/Repository/EntryRepository.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Wallabag/CoreBundle/Repository/EntryRepository.php b/src/Wallabag/CoreBundle/Repository/EntryRepository.php index 04fe6aa34..53e8e2ba1 100644 --- a/src/Wallabag/CoreBundle/Repository/EntryRepository.php +++ b/src/Wallabag/CoreBundle/Repository/EntryRepository.php @@ -4,6 +4,8 @@ namespace Wallabag\CoreBundle\Repository; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Tools\Pagination\Paginator; +use Pagerfanta\Adapter\DoctrineORMAdapter; +use Pagerfanta\Pagerfanta; class EntryRepository extends EntityRepository { @@ -114,9 +116,9 @@ class EntryRepository extends EntityRepository $qb->orderBy('e.updatedAt', $order); } - return $qb - ->getQuery() - ->getResult(); + $pagerAdapter = new DoctrineORMAdapter($qb); + + return new Pagerfanta($pagerAdapter); } /** From 6e22bd737b2e543c85487864a9a25b0f2d5cc3f2 Mon Sep 17 00:00:00 2001 From: William Durand Date: Fri, 6 Mar 2015 11:07:39 +0100 Subject: [PATCH 25/25] Use pager in getEntries() and return Hateoas collection --- .../Controller/WallabagRestController.php | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php index 3e25fe49b..14f42c488 100644 --- a/src/Wallabag/CoreBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/CoreBundle/Controller/WallabagRestController.php @@ -9,6 +9,8 @@ use Symfony\Component\HttpFoundation\Response; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; use Wallabag\CoreBundle\Service\Extractor; +use Hateoas\Configuration\Route; +use Hateoas\Representation\Factory\PagerfantaFactory; class WallabagRestController extends Controller { @@ -82,20 +84,29 @@ class WallabagRestController extends Controller $isStarred = $request->query->get('star'); $sort = $request->query->get('sort', 'created'); $order = $request->query->get('order', 'desc'); - $page = $request->query->get('page', 1); - $perPage = $request->query->get('perPage', 30); + $page = (int) $request->query->get('page', 1); + $perPage = (int) $request->query->get('perPage', 30); $tags = $request->query->get('tags', array()); - $entries = $this + $pager = $this ->getDoctrine() ->getRepository('WallabagCoreBundle:Entry') ->findEntries($this->getUser()->getId(), $isArchived, $isStarred, $sort, $order); - if (!$entries) { + if (0 === $pager->getNbResults()) { throw $this->createNotFoundException(); } - $json = $this->get('serializer')->serialize($entries, 'json'); + $pager->setCurrentPage($page); + $pager->setMaxPerPage($perPage); + + $pagerfantaFactory = new PagerfantaFactory('page', 'perPage'); + $paginatedCollection = $pagerfantaFactory->createRepresentation( + $pager, + new Route('api_get_entries', [], $absolute = true) + ); + + $json = $this->get('serializer')->serialize($paginatedCollection, 'json'); return new Response($json, 200, array('application/json')); }