aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJérémy Benoist <j0k3r@users.noreply.github.com>2019-01-23 09:19:37 +0100
committerGitHub <noreply@github.com>2019-01-23 09:19:37 +0100
commitc6024246b744e411175318065f7c396bbb5a213e (patch)
tree635cbb8cd75888990e90c52317db72068196291d
parenta8f4f7665c98753cca15140c283d49e0aa4cd0ab (diff)
parent801042544444d58580d87d04d5602797027153fc (diff)
downloadwallabag-2.4.tar.gz
wallabag-2.4.tar.zst
wallabag-2.4.zip
Merge pull request #3627 from craig0990/feature/add-search-api-endpoint2.4
Add a basic Search REST endpoint
-rw-r--r--src/Wallabag/ApiBundle/Controller/EntryRestController.php22
-rw-r--r--src/Wallabag/ApiBundle/Controller/SearchRestController.php65
-rw-r--r--src/Wallabag/ApiBundle/Controller/WallabagRestController.php19
-rw-r--r--src/Wallabag/ApiBundle/Resources/config/routing_rest.yml5
-rw-r--r--tests/Wallabag/ApiBundle/Controller/SearchRestControllerTest.php69
5 files changed, 159 insertions, 21 deletions
diff --git a/src/Wallabag/ApiBundle/Controller/EntryRestController.php b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
index f792aaf2..16d8a40b 100644
--- a/src/Wallabag/ApiBundle/Controller/EntryRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/EntryRestController.php
@@ -4,14 +4,12 @@ namespace Wallabag\ApiBundle\Controller;
4 4
5use Hateoas\Configuration\Route; 5use Hateoas\Configuration\Route;
6use Hateoas\Representation\Factory\PagerfantaFactory; 6use Hateoas\Representation\Factory\PagerfantaFactory;
7use JMS\Serializer\SerializationContext;
8use Nelmio\ApiDocBundle\Annotation\ApiDoc; 7use Nelmio\ApiDocBundle\Annotation\ApiDoc;
9use Symfony\Component\HttpFoundation\JsonResponse; 8use Symfony\Component\HttpFoundation\JsonResponse;
10use Symfony\Component\HttpFoundation\Request; 9use Symfony\Component\HttpFoundation\Request;
11use Symfony\Component\HttpFoundation\Response; 10use Symfony\Component\HttpFoundation\Response;
12use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; 11use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
13use Symfony\Component\HttpKernel\Exception\HttpException; 12use Symfony\Component\HttpKernel\Exception\HttpException;
14use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
15use Wallabag\CoreBundle\Entity\Entry; 13use Wallabag\CoreBundle\Entity\Entry;
16use Wallabag\CoreBundle\Entity\Tag; 14use Wallabag\CoreBundle\Entity\Tag;
17use Wallabag\CoreBundle\Event\EntryDeletedEvent; 15use Wallabag\CoreBundle\Event\EntryDeletedEvent;
@@ -141,7 +139,7 @@ class EntryRestController extends WallabagRestController
141 'tags' => $tags, 139 'tags' => $tags,
142 'since' => $since, 140 'since' => $since,
143 ], 141 ],
144 UrlGeneratorInterface::ABSOLUTE_URL 142 true
145 ) 143 )
146 ); 144 );
147 145
@@ -774,24 +772,6 @@ class EntryRestController extends WallabagRestController
774 } 772 }
775 773
776 /** 774 /**
777 * Shortcut to send data serialized in json.
778 *
779 * @param mixed $data
780 *
781 * @return JsonResponse
782 */
783 private function sendResponse($data)
784 {
785 // https://github.com/schmittjoh/JMSSerializerBundle/issues/293
786 $context = new SerializationContext();
787 $context->setSerializeNull(true);
788
789 $json = $this->get('jms_serializer')->serialize($data, 'json', $context);
790
791 return (new JsonResponse())->setJson($json);
792 }
793
794 /**
795 * Retrieve value from the request. 775 * Retrieve value from the request.
796 * Used for POST & PATCH on a an entry. 776 * Used for POST & PATCH on a an entry.
797 * 777 *
diff --git a/src/Wallabag/ApiBundle/Controller/SearchRestController.php b/src/Wallabag/ApiBundle/Controller/SearchRestController.php
new file mode 100644
index 00000000..d9f99844
--- /dev/null
+++ b/src/Wallabag/ApiBundle/Controller/SearchRestController.php
@@ -0,0 +1,65 @@
1<?php
2
3namespace Wallabag\ApiBundle\Controller;
4
5use Hateoas\Configuration\Route;
6use Hateoas\Representation\Factory\PagerfantaFactory;
7use Nelmio\ApiDocBundle\Annotation\ApiDoc;
8use Pagerfanta\Adapter\DoctrineORMAdapter;
9use Pagerfanta\Pagerfanta;
10use Symfony\Component\HttpFoundation\JsonResponse;
11use Symfony\Component\HttpFoundation\Request;
12
13class SearchRestController extends WallabagRestController
14{
15 /**
16 * Search all entries by term.
17 *
18 * @ApiDoc(
19 * parameters={
20 * {"name"="term", "dataType"="string", "required"=false, "format"="any", "description"="Any query term"},
21 * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."},
22 * {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."}
23 * }
24 * )
25 *
26 * @return JsonResponse
27 */
28 public function getSearchAction(Request $request)
29 {
30 $this->validateAuthentication();
31
32 $term = $request->query->get('term');
33 $page = (int) $request->query->get('page', 1);
34 $perPage = (int) $request->query->get('perPage', 30);
35
36 $qb = $this->get('wallabag_core.entry_repository')
37 ->getBuilderForSearchByUser(
38 $this->getUser()->getId(),
39 $term,
40 null
41 );
42
43 $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false);
44 $pager = new Pagerfanta($pagerAdapter);
45
46 $pager->setMaxPerPage($perPage);
47 $pager->setCurrentPage($page);
48
49 $pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
50 $paginatedCollection = $pagerfantaFactory->createRepresentation(
51 $pager,
52 new Route(
53 'api_get_search',
54 [
55 'term' => $term,
56 'page' => $page,
57 'perPage' => $perPage,
58 ],
59 true
60 )
61 );
62
63 return $this->sendResponse($paginatedCollection);
64 }
65}
diff --git a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
index 3c7ad0cf..f18b0910 100644
--- a/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
+++ b/src/Wallabag/ApiBundle/Controller/WallabagRestController.php
@@ -3,6 +3,7 @@
3namespace Wallabag\ApiBundle\Controller; 3namespace Wallabag\ApiBundle\Controller;
4 4
5use FOS\RestBundle\Controller\FOSRestController; 5use FOS\RestBundle\Controller\FOSRestController;
6use JMS\Serializer\SerializationContext;
6use Nelmio\ApiDocBundle\Annotation\ApiDoc; 7use Nelmio\ApiDocBundle\Annotation\ApiDoc;
7use Symfony\Component\HttpFoundation\JsonResponse; 8use Symfony\Component\HttpFoundation\JsonResponse;
8use Symfony\Component\Security\Core\Exception\AccessDeniedException; 9use Symfony\Component\Security\Core\Exception\AccessDeniedException;
@@ -64,4 +65,22 @@ class WallabagRestController extends FOSRestController
64 throw $this->createAccessDeniedException('Access forbidden. Entry user id: ' . $requestUserId . ', logged user id: ' . $user->getId()); 65 throw $this->createAccessDeniedException('Access forbidden. Entry user id: ' . $requestUserId . ', logged user id: ' . $user->getId());
65 } 66 }
66 } 67 }
68
69 /**
70 * Shortcut to send data serialized in json.
71 *
72 * @param mixed $data
73 *
74 * @return JsonResponse
75 */
76 protected function sendResponse($data)
77 {
78 // https://github.com/schmittjoh/JMSSerializerBundle/issues/293
79 $context = new SerializationContext();
80 $context->setSerializeNull(true);
81
82 $json = $this->get('jms_serializer')->serialize($data, 'json', $context);
83
84 return (new JsonResponse())->setJson($json);
85 }
67} 86}
diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
index c0283e71..06e62c37 100644
--- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
+++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
@@ -3,6 +3,11 @@ entry:
3 resource: "WallabagApiBundle:EntryRest" 3 resource: "WallabagApiBundle:EntryRest"
4 name_prefix: api_ 4 name_prefix: api_
5 5
6search:
7 type: rest
8 resource: "WallabagApiBundle:SearchRest"
9 name_prefix: api_
10
6tag: 11tag:
7 type: rest 12 type: rest
8 resource: "WallabagApiBundle:TagRest" 13 resource: "WallabagApiBundle:TagRest"
diff --git a/tests/Wallabag/ApiBundle/Controller/SearchRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/SearchRestControllerTest.php
new file mode 100644
index 00000000..fd524639
--- /dev/null
+++ b/tests/Wallabag/ApiBundle/Controller/SearchRestControllerTest.php
@@ -0,0 +1,69 @@
1<?php
2
3namespace Tests\Wallabag\ApiBundle\Controller;
4
5use Tests\Wallabag\ApiBundle\WallabagApiTestCase;
6
7class SearchRestControllerTest extends WallabagApiTestCase
8{
9 public function testGetSearchWithFullOptions()
10 {
11 $this->client->request('GET', '/api/search', [
12 'page' => 1,
13 'perPage' => 2,
14 'term' => 'entry', // 6 results
15 ]);
16
17 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
18
19 $content = json_decode($this->client->getResponse()->getContent(), true);
20
21 $this->assertGreaterThanOrEqual(1, \count($content));
22 $this->assertArrayHasKey('items', $content['_embedded']);
23 $this->assertGreaterThanOrEqual(0, $content['total']);
24 $this->assertSame(1, $content['page']);
25 $this->assertSame(2, $content['limit']);
26 $this->assertGreaterThanOrEqual(1, $content['pages']);
27
28 $this->assertArrayHasKey('_links', $content);
29 $this->assertArrayHasKey('self', $content['_links']);
30 $this->assertArrayHasKey('first', $content['_links']);
31 $this->assertArrayHasKey('last', $content['_links']);
32
33 foreach (['self', 'first', 'last'] as $link) {
34 $this->assertArrayHasKey('href', $content['_links'][$link]);
35 $this->assertContains('term=entry', $content['_links'][$link]['href']);
36 }
37
38 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
39 }
40
41 public function testGetSearchWithNoLimit()
42 {
43 $this->client->request('GET', '/api/search', [
44 'term' => 'entry',
45 ]);
46
47 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
48
49 $content = json_decode($this->client->getResponse()->getContent(), true);
50
51 $this->assertGreaterThanOrEqual(1, \count($content));
52 $this->assertArrayHasKey('items', $content['_embedded']);
53 $this->assertGreaterThanOrEqual(0, $content['total']);
54 $this->assertSame(1, $content['page']);
55 $this->assertGreaterThanOrEqual(1, $content['pages']);
56
57 $this->assertArrayHasKey('_links', $content);
58 $this->assertArrayHasKey('self', $content['_links']);
59 $this->assertArrayHasKey('first', $content['_links']);
60 $this->assertArrayHasKey('last', $content['_links']);
61
62 foreach (['self', 'first', 'last'] as $link) {
63 $this->assertArrayHasKey('href', $content['_links'][$link]);
64 $this->assertContains('term=entry', $content['_links'][$link]['href']);
65 }
66
67 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
68 }
69}