Merge pull request #3627 from craig0990/feature/add-search-api-endpoint

Add a basic Search REST endpoint
This commit is contained in:
Jérémy Benoist 2019-01-23 09:19:37 +01:00 committed by GitHub
commit c6024246b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 159 additions and 21 deletions

View 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.

View file

@ -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);
}
}

View 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);
}
}

View 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"

View file

@ -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'));
}
}