aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorCraig Roberts <craig@craig0990.co.uk>2018-04-09 17:24:45 +0800
committerJeremy Benoist <jeremy.benoist@gmail.com>2019-01-22 20:42:24 +0100
commitb32057980e33e7ddd93480017496a589006b8260 (patch)
tree901d98556d378b68c2e654f3c892616b302331aa
parent3527c300215e6e6010efb8bb840b8b6f5c63a1cc (diff)
downloadwallabag-b32057980e33e7ddd93480017496a589006b8260.tar.gz
wallabag-b32057980e33e7ddd93480017496a589006b8260.tar.zst
wallabag-b32057980e33e7ddd93480017496a589006b8260.zip
Fixes [wallabag/wallabag#2611] Add a basic Search REST endpoint
- Adds a new `search` key to `src/Wallabag/ApiBundle/Resources/config/routing_rest.yml` - Reuses the `getBuilderForSearchByUser` method from the EntryRepository - Supports, `term`, `page`, and `perPage` query parameters - Some very basic tests
-rw-r--r--src/Wallabag/ApiBundle/Controller/SearchRestController.php91
-rw-r--r--src/Wallabag/ApiBundle/Resources/config/routing_rest.yml5
-rw-r--r--tests/Wallabag/ApiBundle/Controller/SearchRestControllerTest.php73
3 files changed, 169 insertions, 0 deletions
diff --git a/src/Wallabag/ApiBundle/Controller/SearchRestController.php b/src/Wallabag/ApiBundle/Controller/SearchRestController.php
new file mode 100644
index 00000000..c0b2cb24
--- /dev/null
+++ b/src/Wallabag/ApiBundle/Controller/SearchRestController.php
@@ -0,0 +1,91 @@
1<?php
2
3namespace Wallabag\ApiBundle\Controller;
4
5use Hateoas\Configuration\Route;
6use Hateoas\Representation\Factory\PagerfantaFactory;
7use JMS\Serializer\SerializationContext;
8use Nelmio\ApiDocBundle\Annotation\ApiDoc;
9use Pagerfanta\Adapter\DoctrineORMAdapter;
10use Pagerfanta\Pagerfanta;
11use Symfony\Component\HttpFoundation\JsonResponse;
12use Symfony\Component\HttpFoundation\Request;
13use Symfony\Component\HttpFoundation\Response;
14use Symfony\Component\HttpKernel\Exception\HttpException;
15use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
16use Wallabag\CoreBundle\Entity\Entry;
17use Wallabag\CoreBundle\Entity\Tag;
18use Wallabag\CoreBundle\Event\EntryDeletedEvent;
19use Wallabag\CoreBundle\Event\EntrySavedEvent;
20
21class SearchRestController extends WallabagRestController
22{
23 /**
24 * Search all entries by term.
25 *
26 * @ApiDoc(
27 * parameters={
28 * {"name"="term", "dataType"="string", "required"=false, "format"="any", "description"="Any query term"},
29 * {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."},
30 * {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."}
31 * }
32 * )
33 *
34 * @return JsonResponse
35 */
36 public function getSearchAction(Request $request)
37 {
38 $this->validateAuthentication();
39
40 $term = $request->query->get('term');
41 $page = (int) $request->query->get('page', 1);
42 $perPage = (int) $request->query->get('perPage', 30);
43
44 $qb = $this->get('wallabag_core.entry_repository')
45 ->getBuilderForSearchByUser(
46 $this->getUser()->getId(),
47 $term,
48 null
49 );
50
51 $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false);
52 $pager = new Pagerfanta($pagerAdapter);
53
54 $pager->setMaxPerPage($perPage);
55 $pager->setCurrentPage($page);
56
57 $pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
58 $paginatedCollection = $pagerfantaFactory->createRepresentation(
59 $pager,
60 new Route(
61 'api_get_search',
62 [
63 'term' => $term,
64 'page' => $page,
65 'perPage' => $perPage,
66 ],
67 UrlGeneratorInterface::ABSOLUTE_URL
68 )
69 );
70
71 return $this->sendResponse($paginatedCollection);
72 }
73
74 /**
75 * Shortcut to send data serialized in json.
76 *
77 * @param mixed $data
78 *
79 * @return JsonResponse
80 */
81 private function sendResponse($data)
82 {
83 // https://github.com/schmittjoh/JMSSerializerBundle/issues/293
84 $context = new SerializationContext();
85 $context->setSerializeNull(true);
86
87 $json = $this->get('jms_serializer')->serialize($data, 'json', $context);
88
89 return (new JsonResponse())->setJson($json);
90 }
91}
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..5900ae53
--- /dev/null
+++ b/tests/Wallabag/ApiBundle/Controller/SearchRestControllerTest.php
@@ -0,0 +1,73 @@
1<?php
2
3namespace Tests\Wallabag\ApiBundle\Controller;
4
5use Tests\Wallabag\ApiBundle\WallabagApiTestCase;
6use Wallabag\CoreBundle\Entity\Entry;
7use Wallabag\CoreBundle\Entity\Tag;
8use Wallabag\CoreBundle\Helper\ContentProxy;
9use Wallabag\UserBundle\Entity\User;
10
11class SearchRestControllerTest extends WallabagApiTestCase
12{
13 public function testGetSearchWithFullOptions()
14 {
15 $this->client->request('GET', '/api/search', [
16 'page' => 1,
17 'perPage' => 2,
18 'term' => 'entry' // 6 results
19 ]);
20
21 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
22
23 $content = json_decode($this->client->getResponse()->getContent(), true);
24
25 $this->assertGreaterThanOrEqual(1, count($content));
26 $this->assertArrayHasKey('items', $content['_embedded']);
27 $this->assertGreaterThanOrEqual(0, $content['total']);
28 $this->assertSame(1, $content['page']);
29 $this->assertSame(2, $content['limit']);
30 $this->assertGreaterThanOrEqual(1, $content['pages']);
31
32 $this->assertArrayHasKey('_links', $content);
33 $this->assertArrayHasKey('self', $content['_links']);
34 $this->assertArrayHasKey('first', $content['_links']);
35 $this->assertArrayHasKey('last', $content['_links']);
36
37 foreach (['self', 'first', 'last'] as $link) {
38 $this->assertArrayHasKey('href', $content['_links'][$link]);
39 $this->assertContains('term=entry', $content['_links'][$link]['href']);
40 }
41
42 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
43 }
44
45 public function testGetSearchWithNoLimit()
46 {
47 $this->client->request('GET', '/api/search', [
48 'term' => 'entry'
49 ]);
50
51 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
52
53 $content = json_decode($this->client->getResponse()->getContent(), true);
54
55 $this->assertGreaterThanOrEqual(1, count($content));
56 $this->assertArrayHasKey('items', $content['_embedded']);
57 $this->assertGreaterThanOrEqual(0, $content['total']);
58 $this->assertSame(1, $content['page']);
59 $this->assertGreaterThanOrEqual(1, $content['pages']);
60
61 $this->assertArrayHasKey('_links', $content);
62 $this->assertArrayHasKey('self', $content['_links']);
63 $this->assertArrayHasKey('first', $content['_links']);
64 $this->assertArrayHasKey('last', $content['_links']);
65
66 foreach (['self', 'first', 'last'] as $link) {
67 $this->assertArrayHasKey('href', $content['_links'][$link]);
68 $this->assertContains('term=entry', $content['_links'][$link]['href']);
69 }
70
71 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
72 }
73}