Added search term filtering to short codes list

This commit is contained in:
Alejandro Celaya 2016-10-22 12:40:51 +02:00
parent 4c76e17178
commit 543c0e62d0
6 changed files with 59 additions and 26 deletions

View file

@ -13,18 +13,18 @@ class PaginableRepositoryAdapter implements AdapterInterface
*/
private $paginableRepository;
/**
* @var null
* @var null|string
*/
private $searchTerm;
/**
* @var null
* @var null|array|string
*/
private $orderBy;
public function __construct(PaginableRepositoryInterface $paginableRepository, $searchTerm = null, $orderBy = null)
public function __construct(PaginableRepositoryInterface $paginableRepository, $searchQuery = null, $orderBy = null)
{
$this->paginableRepository = $paginableRepository;
$this->searchTerm = $searchTerm;
$this->searchTerm = trim(strip_tags($searchQuery));
$this->orderBy = $orderBy;
}

View file

@ -2,6 +2,7 @@
namespace Shlinkio\Shlink\Core\Repository;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use Shlinkio\Shlink\Core\Entity\ShortUrl;
class ShortUrlRepository extends EntityRepository implements ShortUrlRepositoryInterface
@ -15,7 +16,8 @@ class ShortUrlRepository extends EntityRepository implements ShortUrlRepositoryI
*/
public function findList($limit = null, $offset = null, $searchTerm = null, $orderBy = null)
{
$qb = $this->createQueryBuilder('s');
$qb = $this->createListQueryBuilder($searchTerm);
$qb->select('s');
if (isset($limit)) {
$qb->setMaxResults($limit);
@ -23,9 +25,6 @@ class ShortUrlRepository extends EntityRepository implements ShortUrlRepositoryI
if (isset($offset)) {
$qb->setFirstResult($offset);
}
if (isset($searchTerm)) {
// TODO
}
if (isset($orderBy)) {
if (is_string($orderBy)) {
$qb->orderBy($orderBy);
@ -43,19 +42,39 @@ class ShortUrlRepository extends EntityRepository implements ShortUrlRepositoryI
/**
* Counts the number of elements in a list using provided filtering data
*
* @param null $searchTerm
* @param null|string $searchTerm
* @return int
*/
public function countList($searchTerm = null)
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('COUNT(s)')
->from(ShortUrl::class, 's');
if (isset($searchTerm)) {
// TODO
}
$qb = $this->createListQueryBuilder($searchTerm);
$qb->select('COUNT(s)');
return (int) $qb->getQuery()->getSingleScalarResult();
}
/**
* @param null|string $searchTerm
* @return QueryBuilder
*/
protected function createListQueryBuilder($searchTerm = null)
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->from(ShortUrl::class, 's');
// Apply search term to every searchable field if not empty
if (! empty($searchTerm)) {
$conditions = [
$qb->expr()->like('s.originalUrl', ':searchPattern'),
$qb->expr()->like('s.shortCode', ':searchPattern'),
];
// Unpack and apply search conditions
$qb->where($qb->expr()->orX(...$conditions));
$searchTerm = '%' . $searchTerm . '%';
$qb->setParameter('searchPattern', $searchTerm);
}
return $qb;
}
}

View file

@ -32,13 +32,14 @@ class ShortUrlService implements ShortUrlServiceInterface
/**
* @param int $page
* @return Paginator|ShortUrl[]
* @param string $searchQuery
* @return ShortUrl[]|Paginator
*/
public function listShortUrls($page = 1)
public function listShortUrls($page = 1, $searchQuery = null)
{
/** @var ShortUrlRepository $repo */
$repo = $this->em->getRepository(ShortUrl::class);
$paginator = new Paginator(new PaginableRepositoryAdapter($repo));
$paginator = new Paginator(new PaginableRepositoryAdapter($repo, $searchQuery));
$paginator->setItemCountPerPage(PaginableRepositoryAdapter::ITEMS_PER_PAGE)
->setCurrentPageNumber($page);

View file

@ -9,9 +9,10 @@ interface ShortUrlServiceInterface
{
/**
* @param int $page
* @param string $searchQuery
* @return ShortUrl[]|Paginator
*/
public function listShortUrls($page = 1);
public function listShortUrls($page = 1, $searchQuery = null);
/**
* @param string $shortCode

View file

@ -53,8 +53,8 @@ class ListShortcodesAction extends AbstractRestAction
public function dispatch(Request $request, Response $response, callable $out = null)
{
try {
$query = $request->getQueryParams();
$shortUrls = $this->shortUrlService->listShortUrls(isset($query['page']) ? $query['page'] : 1);
$params = $this->queryToListParams($request->getQueryParams());
$shortUrls = $this->shortUrlService->listShortUrls(...$params);
return new JsonResponse(['shortUrls' => $this->serializePaginator($shortUrls)]);
} catch (\Exception $e) {
$this->logger->error('Unexpected error while listing short URLs.' . PHP_EOL . $e);
@ -64,4 +64,16 @@ class ListShortcodesAction extends AbstractRestAction
], 500);
}
}
/**
* @param array $query
* @return string
*/
public function queryToListParams(array $query)
{
return [
isset($query['page']) ? $query['page'] : 1,
isset($query['searchTerm']) ? $query['searchTerm'] : null,
];
}
}

View file

@ -34,8 +34,8 @@ class ListShortcodesActionTest extends TestCase
public function properListReturnsSuccessResponse()
{
$page = 3;
$this->service->listShortUrls($page)->willReturn(new Paginator(new ArrayAdapter()))
->shouldBeCalledTimes(1);
$this->service->listShortUrls($page, null)->willReturn(new Paginator(new ArrayAdapter()))
->shouldBeCalledTimes(1);
$response = $this->action->__invoke(
ServerRequestFactory::fromGlobals()->withQueryParams([
@ -52,8 +52,8 @@ class ListShortcodesActionTest extends TestCase
public function anExceptionsReturnsErrorResponse()
{
$page = 3;
$this->service->listShortUrls($page)->willThrow(\Exception::class)
->shouldBeCalledTimes(1);
$this->service->listShortUrls($page, null)->willThrow(\Exception::class)
->shouldBeCalledTimes(1);
$response = $this->action->__invoke(
ServerRequestFactory::fromGlobals()->withQueryParams([