]> git.immae.eu Git - github/wallabag/wallabag.git/commitdiff
Merge pull request #3627 from craig0990/feature/add-search-api-endpoint 2.4
authorJérémy Benoist <j0k3r@users.noreply.github.com>
Wed, 23 Jan 2019 08:19:37 +0000 (09:19 +0100)
committerGitHub <noreply@github.com>
Wed, 23 Jan 2019 08:19:37 +0000 (09:19 +0100)
Add a basic Search REST endpoint

src/Wallabag/ApiBundle/Controller/EntryRestController.php
src/Wallabag/ApiBundle/Controller/SearchRestController.php [new file with mode: 0644]
src/Wallabag/ApiBundle/Controller/WallabagRestController.php
src/Wallabag/ApiBundle/Resources/config/routing_rest.yml
tests/Wallabag/ApiBundle/Controller/SearchRestControllerTest.php [new file with mode: 0644]

index f792aaf23a6afd53b6a3a498e992858fb73da1c1..16d8a40b4e7c8f04ee9a8e2ece7576fcf0e0f526 100644 (file)
@@ -4,14 +4,12 @@ namespace Wallabag\ApiBundle\Controller;
 
 use Hateoas\Configuration\Route;
 use Hateoas\Representation\Factory\PagerfantaFactory;
-use JMS\Serializer\SerializationContext;
 use Nelmio\ApiDocBundle\Annotation\ApiDoc;
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
 use Symfony\Component\HttpKernel\Exception\HttpException;
-use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
 use Wallabag\CoreBundle\Entity\Entry;
 use Wallabag\CoreBundle\Entity\Tag;
 use Wallabag\CoreBundle\Event\EntryDeletedEvent;
@@ -141,7 +139,7 @@ class EntryRestController extends WallabagRestController
                     'tags' => $tags,
                     'since' => $since,
                 ],
-                UrlGeneratorInterface::ABSOLUTE_URL
+                true
             )
         );
 
@@ -773,24 +771,6 @@ class EntryRestController extends WallabagRestController
         return $this->sendResponse($results);
     }
 
-    /**
-     * Shortcut to send data serialized in json.
-     *
-     * @param mixed $data
-     *
-     * @return JsonResponse
-     */
-    private function sendResponse($data)
-    {
-        // https://github.com/schmittjoh/JMSSerializerBundle/issues/293
-        $context = new SerializationContext();
-        $context->setSerializeNull(true);
-
-        $json = $this->get('jms_serializer')->serialize($data, 'json', $context);
-
-        return (new JsonResponse())->setJson($json);
-    }
-
     /**
      * Retrieve value from the request.
      * Used for POST & PATCH on a an entry.
diff --git a/src/Wallabag/ApiBundle/Controller/SearchRestController.php b/src/Wallabag/ApiBundle/Controller/SearchRestController.php
new file mode 100644 (file)
index 0000000..d9f9984
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+
+namespace Wallabag\ApiBundle\Controller;
+
+use Hateoas\Configuration\Route;
+use Hateoas\Representation\Factory\PagerfantaFactory;
+use Nelmio\ApiDocBundle\Annotation\ApiDoc;
+use Pagerfanta\Adapter\DoctrineORMAdapter;
+use Pagerfanta\Pagerfanta;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
+
+class SearchRestController extends WallabagRestController
+{
+    /**
+     * Search all entries by term.
+     *
+     * @ApiDoc(
+     *       parameters={
+     *          {"name"="term", "dataType"="string", "required"=false, "format"="any", "description"="Any query term"},
+     *          {"name"="page", "dataType"="integer", "required"=false, "format"="default '1'", "description"="what page you want."},
+     *          {"name"="perPage", "dataType"="integer", "required"=false, "format"="default'30'", "description"="results per page."}
+     *       }
+     * )
+     *
+     * @return JsonResponse
+     */
+    public function getSearchAction(Request $request)
+    {
+        $this->validateAuthentication();
+
+        $term = $request->query->get('term');
+        $page = (int) $request->query->get('page', 1);
+        $perPage = (int) $request->query->get('perPage', 30);
+
+        $qb = $this->get('wallabag_core.entry_repository')
+            ->getBuilderForSearchByUser(
+                $this->getUser()->getId(),
+                $term,
+                null
+            );
+
+        $pagerAdapter = new DoctrineORMAdapter($qb->getQuery(), true, false);
+        $pager = new Pagerfanta($pagerAdapter);
+
+        $pager->setMaxPerPage($perPage);
+        $pager->setCurrentPage($page);
+
+        $pagerfantaFactory = new PagerfantaFactory('page', 'perPage');
+        $paginatedCollection = $pagerfantaFactory->createRepresentation(
+            $pager,
+            new Route(
+                'api_get_search',
+                [
+                    'term' => $term,
+                    'page' => $page,
+                    'perPage' => $perPage,
+                ],
+                true
+            )
+        );
+
+        return $this->sendResponse($paginatedCollection);
+    }
+}
index 3c7ad0cfeb177a512906df28c971df82911ba710..f18b0910d9d05120b5eeee9ec108ed41190ac5a3 100644 (file)
@@ -3,6 +3,7 @@
 namespace Wallabag\ApiBundle\Controller;
 
 use FOS\RestBundle\Controller\FOSRestController;
+use JMS\Serializer\SerializationContext;
 use Nelmio\ApiDocBundle\Annotation\ApiDoc;
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Symfony\Component\Security\Core\Exception\AccessDeniedException;
@@ -64,4 +65,22 @@ class WallabagRestController extends FOSRestController
             throw $this->createAccessDeniedException('Access forbidden. Entry user id: ' . $requestUserId . ', logged user id: ' . $user->getId());
         }
     }
+
+    /**
+     * Shortcut to send data serialized in json.
+     *
+     * @param mixed $data
+     *
+     * @return JsonResponse
+     */
+    protected function sendResponse($data)
+    {
+        // https://github.com/schmittjoh/JMSSerializerBundle/issues/293
+        $context = new SerializationContext();
+        $context->setSerializeNull(true);
+
+        $json = $this->get('jms_serializer')->serialize($data, 'json', $context);
+
+        return (new JsonResponse())->setJson($json);
+    }
 }
index c0283e71f159603317b1179bbf194c21514c12fa..06e62c379eedfd96778526474421f86d15d37e00 100644 (file)
@@ -3,6 +3,11 @@ entry:
   resource: "WallabagApiBundle:EntryRest"
   name_prefix:  api_
 
+search:
+  type: rest
+  resource: "WallabagApiBundle:SearchRest"
+  name_prefix:  api_
+
 tag:
   type: rest
   resource: "WallabagApiBundle:TagRest"
diff --git a/tests/Wallabag/ApiBundle/Controller/SearchRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/SearchRestControllerTest.php
new file mode 100644 (file)
index 0000000..fd52463
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+
+namespace Tests\Wallabag\ApiBundle\Controller;
+
+use Tests\Wallabag\ApiBundle\WallabagApiTestCase;
+
+class SearchRestControllerTest extends WallabagApiTestCase
+{
+    public function testGetSearchWithFullOptions()
+    {
+        $this->client->request('GET', '/api/search', [
+            'page' => 1,
+            'perPage' => 2,
+            'term' => 'entry', // 6 results
+        ]);
+
+        $this->assertSame(200, $this->client->getResponse()->getStatusCode());
+
+        $content = json_decode($this->client->getResponse()->getContent(), true);
+
+        $this->assertGreaterThanOrEqual(1, \count($content));
+        $this->assertArrayHasKey('items', $content['_embedded']);
+        $this->assertGreaterThanOrEqual(0, $content['total']);
+        $this->assertSame(1, $content['page']);
+        $this->assertSame(2, $content['limit']);
+        $this->assertGreaterThanOrEqual(1, $content['pages']);
+
+        $this->assertArrayHasKey('_links', $content);
+        $this->assertArrayHasKey('self', $content['_links']);
+        $this->assertArrayHasKey('first', $content['_links']);
+        $this->assertArrayHasKey('last', $content['_links']);
+
+        foreach (['self', 'first', 'last'] as $link) {
+            $this->assertArrayHasKey('href', $content['_links'][$link]);
+            $this->assertContains('term=entry', $content['_links'][$link]['href']);
+        }
+
+        $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+    }
+
+    public function testGetSearchWithNoLimit()
+    {
+        $this->client->request('GET', '/api/search', [
+            'term' => 'entry',
+        ]);
+
+        $this->assertSame(200, $this->client->getResponse()->getStatusCode());
+
+        $content = json_decode($this->client->getResponse()->getContent(), true);
+
+        $this->assertGreaterThanOrEqual(1, \count($content));
+        $this->assertArrayHasKey('items', $content['_embedded']);
+        $this->assertGreaterThanOrEqual(0, $content['total']);
+        $this->assertSame(1, $content['page']);
+        $this->assertGreaterThanOrEqual(1, $content['pages']);
+
+        $this->assertArrayHasKey('_links', $content);
+        $this->assertArrayHasKey('self', $content['_links']);
+        $this->assertArrayHasKey('first', $content['_links']);
+        $this->assertArrayHasKey('last', $content['_links']);
+
+        foreach (['self', 'first', 'last'] as $link) {
+            $this->assertArrayHasKey('href', $content['_links'][$link]);
+            $this->assertContains('term=entry', $content['_links'][$link]['href']);
+        }
+
+        $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
+    }
+}