From 3d4b0b306456aa7e5f16d9dda9043a74438f320f Mon Sep 17 00:00:00 2001 From: Pascal MARTIN Date: Tue, 4 Oct 2016 13:57:03 +0200 Subject: [PATCH 1/3] Routing: epub format is allowed for API --- src/Wallabag/ApiBundle/Resources/config/routing_rest.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml index 5f43f9716..9aef7e8ec 100644 --- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml +++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml @@ -2,3 +2,5 @@ entries: type: rest resource: "WallabagApiBundle:WallabagRest" name_prefix: api_ + requirements: + _format: xml|json|html|epub From 24de86653440de3f84d585f089caab3734dcb573 Mon Sep 17 00:00:00 2001 From: Pascal MARTIN Date: Tue, 4 Oct 2016 13:57:18 +0200 Subject: [PATCH 2/3] API: getEntry can return EPUB --- .../ApiBundle/Controller/WallabagRestController.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php index a0d9d4f3a..072e5f851 100644 --- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php @@ -127,11 +127,18 @@ class WallabagRestController extends FOSRestController * * @return JsonResponse */ - public function getEntryAction(Entry $entry) + public function getEntryAction(Entry $entry, $_format) { $this->validateAuthentication(); $this->validateUserAccess($entry->getUser()->getId()); + if ($_format === 'epub') { + return $this->get('wallabag_core.helper.entries_export') + ->setEntries($entry) + ->updateTitle('entry') + ->exportAs($_format); + } + $json = $this->get('serializer')->serialize($entry, 'json'); return (new JsonResponse())->setJson($json); From 3f3a60879e168f4a8040c441e295fa63e024961d Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Sat, 8 Oct 2016 12:59:17 +0200 Subject: [PATCH 3/3] Add entry export in API Export isn't available for json & xml because user can use the default entry endpoint instead. --- app/config/config.yml | 2 + .../Controller/WallabagRestController.php | 38 +++++-- .../Resources/config/routing_rest.yml | 10 +- .../Controller/WallabagRestControllerTest.php | 104 ++++++++++-------- 4 files changed, 90 insertions(+), 64 deletions(-) diff --git a/app/config/config.yml b/app/config/config.yml index 75d7299c1..48f317c7e 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -130,6 +130,8 @@ fos_rest: nelmio_api_doc: sandbox: enabled: false + cache: + enabled: true name: wallabag API documentation nelmio_cors: diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php index 072e5f851..858755892 100644 --- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php +++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php @@ -3,7 +3,7 @@ namespace Wallabag\ApiBundle\Controller; use FOS\RestBundle\Controller\FOSRestController; -use Hateoas\Configuration\Route; +use Hateoas\Configuration\Route as HateoasRoute; use Hateoas\Representation\Factory\PagerfantaFactory; use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Symfony\Component\HttpFoundation\Request; @@ -12,6 +12,7 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Wallabag\CoreBundle\Entity\Entry; use Wallabag\CoreBundle\Entity\Tag; +use FOS\RestBundle\Controller\Annotations\Route; class WallabagRestController extends FOSRestController { @@ -95,7 +96,7 @@ class WallabagRestController extends FOSRestController $pagerfantaFactory = new PagerfantaFactory('page', 'perPage'); $paginatedCollection = $pagerfantaFactory->createRepresentation( $pager, - new Route( + new HateoasRoute( 'api_get_entries', [ 'archive' => $isArchived, @@ -127,23 +128,40 @@ class WallabagRestController extends FOSRestController * * @return JsonResponse */ - public function getEntryAction(Entry $entry, $_format) + public function getEntryAction(Entry $entry) { $this->validateAuthentication(); $this->validateUserAccess($entry->getUser()->getId()); - if ($_format === 'epub') { - return $this->get('wallabag_core.helper.entries_export') - ->setEntries($entry) - ->updateTitle('entry') - ->exportAs($_format); - } - $json = $this->get('serializer')->serialize($entry, 'json'); return (new JsonResponse())->setJson($json); } + /** + * Retrieve a single entry as a predefined format. + * + * @ApiDoc( + * requirements={ + * {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"} + * } + * ) + * + * @Route(requirements={"_format"="epub|mobi|pdf|txt|csv"}) + * + * @return Response + */ + public function getEntryExportAction(Entry $entry, Request $request) + { + $this->validateAuthentication(); + $this->validateUserAccess($entry->getUser()->getId()); + + return $this->get('wallabag_core.helper.entries_export') + ->setEntries($entry) + ->updateTitle('entry') + ->exportAs($request->attributes->get('_format')); + } + /** * Create an entry. * diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml index 9aef7e8ec..35f8b2c11 100644 --- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml +++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml @@ -1,6 +1,4 @@ -entries: - type: rest - resource: "WallabagApiBundle:WallabagRest" - name_prefix: api_ - requirements: - _format: xml|json|html|epub +api: + type: rest + resource: "WallabagApiBundle:WallabagRest" + name_prefix: api_ diff --git a/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php index 65b65290c..79353857c 100644 --- a/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php +++ b/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php @@ -32,12 +32,55 @@ class WallabagRestControllerTest extends WallabagApiTestCase $this->assertEquals($entry->getUserEmail(), $content['user_email']); $this->assertEquals($entry->getUserId(), $content['user_id']); - $this->assertTrue( - $this->client->getResponse()->headers->contains( - 'Content-Type', - 'application/json' - ) - ); + $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); + } + + public function testExportEntry() + { + $entry = $this->client->getContainer() + ->get('doctrine.orm.entity_manager') + ->getRepository('WallabagCoreBundle:Entry') + ->findOneBy(['user' => 1, 'isArchived' => false]); + + if (!$entry) { + $this->markTestSkipped('No content found in db.'); + } + + $this->client->request('GET', '/api/entries/'.$entry->getId().'/export.epub'); + $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); + + // epub format got the content type in the content + $this->assertContains('application/epub', $this->client->getResponse()->getContent()); + $this->assertEquals('application/epub+zip', $this->client->getResponse()->headers->get('Content-Type')); + + // re-auth client for mobi + $client = $this->createAuthorizedClient(); + $client->request('GET', '/api/entries/'.$entry->getId().'/export.mobi'); + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + + $this->assertEquals('application/x-mobipocket-ebook', $client->getResponse()->headers->get('Content-Type')); + + // re-auth client for pdf + $client = $this->createAuthorizedClient(); + $client->request('GET', '/api/entries/'.$entry->getId().'/export.pdf'); + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + + $this->assertContains('PDF-', $client->getResponse()->getContent()); + $this->assertEquals('application/pdf', $client->getResponse()->headers->get('Content-Type')); + + // re-auth client for pdf + $client = $this->createAuthorizedClient(); + $client->request('GET', '/api/entries/'.$entry->getId().'/export.txt'); + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + + $this->assertContains('text/plain', $client->getResponse()->headers->get('Content-Type')); + + // re-auth client for pdf + $client = $this->createAuthorizedClient(); + $client->request('GET', '/api/entries/'.$entry->getId().'/export.csv'); + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + + $this->assertContains('application/csv', $client->getResponse()->headers->get('Content-Type')); } public function testGetOneEntryWrongUser() @@ -70,12 +113,7 @@ class WallabagRestControllerTest extends WallabagApiTestCase $this->assertEquals(1, $content['page']); $this->assertGreaterThanOrEqual(1, $content['pages']); - $this->assertTrue( - $this->client->getResponse()->headers->contains( - 'Content-Type', - 'application/json' - ) - ); + $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); } public function testGetEntriesWithFullOptions() @@ -117,12 +155,7 @@ class WallabagRestControllerTest extends WallabagApiTestCase $this->assertContains('since=1443274283', $content['_links'][$link]['href']); } - $this->assertTrue( - $this->client->getResponse()->headers->contains( - 'Content-Type', - 'application/json' - ) - ); + $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); } public function testGetStarredEntries() @@ -150,12 +183,7 @@ class WallabagRestControllerTest extends WallabagApiTestCase $this->assertContains('sort=updated', $content['_links'][$link]['href']); } - $this->assertTrue( - $this->client->getResponse()->headers->contains( - 'Content-Type', - 'application/json' - ) - ); + $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); } public function testGetArchiveEntries() @@ -182,12 +210,7 @@ class WallabagRestControllerTest extends WallabagApiTestCase $this->assertContains('archive=1', $content['_links'][$link]['href']); } - $this->assertTrue( - $this->client->getResponse()->headers->contains( - 'Content-Type', - 'application/json' - ) - ); + $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); } public function testGetTaggedEntries() @@ -214,12 +237,7 @@ class WallabagRestControllerTest extends WallabagApiTestCase $this->assertContains('tags='.urlencode('foo,bar'), $content['_links'][$link]['href']); } - $this->assertTrue( - $this->client->getResponse()->headers->contains( - 'Content-Type', - 'application/json' - ) - ); + $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); } public function testGetDatedEntries() @@ -246,12 +264,7 @@ class WallabagRestControllerTest extends WallabagApiTestCase $this->assertContains('since=1443274283', $content['_links'][$link]['href']); } - $this->assertTrue( - $this->client->getResponse()->headers->contains( - 'Content-Type', - 'application/json' - ) - ); + $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); } public function testGetDatedSupEntries() @@ -279,12 +292,7 @@ class WallabagRestControllerTest extends WallabagApiTestCase $this->assertContains('since='.($future->getTimestamp() + 1000), $content['_links'][$link]['href']); } - $this->assertTrue( - $this->client->getResponse()->headers->contains( - 'Content-Type', - 'application/json' - ) - ); + $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); } public function testDeleteEntry()