Merge branch 'feature/67' into develop

This commit is contained in:
Alejandro Celaya 2016-10-22 23:15:57 +02:00
commit c3fd433446
10 changed files with 91 additions and 24 deletions

View File

@ -90,6 +90,19 @@
}
}
},
{
"name": "orderBy",
"in": "query",
"description": "The field from which you want to order the result. (Since v1.3.0)",
"enum": [
"originalUrl",
"shortCode",
"dateCreated",
"visits"
],
"required": false,
"type": "string"
},
{
"$ref": "#/parameters/Authorization"
}

Binary file not shown.

View File

@ -1,8 +1,8 @@
msgid ""
msgstr ""
"Project-Id-Version: Shlink 1.0\n"
"POT-Creation-Date: 2016-10-22 13:14+0200\n"
"PO-Revision-Date: 2016-10-22 13:15+0200\n"
"POT-Creation-Date: 2016-10-22 23:12+0200\n"
"PO-Revision-Date: 2016-10-22 23:13+0200\n"
"Last-Translator: Alejandro Celaya <alejandro@alejandrocelaya.com>\n"
"Language-Team: \n"
"Language: es_ES\n"
@ -172,6 +172,12 @@ msgstr ""
msgid "A comma-separated list of tags to filter results"
msgstr "Una lista de etiquetas separadas por coma para filtrar el resultado"
msgid ""
"The field from which we want to order by. Pass ASC or DESC separated by a "
"comma"
msgstr ""
"El campo por el cual queremos ordernar. Pasa ASC o DESC separado por una coma"
msgid "Whether to display the tags or not"
msgstr "Si se desea mostrar las etiquetas o no"

View File

@ -70,6 +70,14 @@ class ListShortcodesCommand extends Command
InputOption::VALUE_OPTIONAL,
$this->translator->translate('A comma-separated list of tags to filter results')
)
->addOption(
'orderBy',
'o',
InputOption::VALUE_OPTIONAL,
$this->translator->translate(
'The field from which we want to order by. Pass ASC or DESC separated by a comma'
)
)
->addOption(
'showTags',
null,
@ -85,12 +93,13 @@ class ListShortcodesCommand extends Command
$tags = $input->getOption('tags');
$tags = ! empty($tags) ? explode(',', $tags) : [];
$showTags = $input->getOption('showTags');
$orderBy = $input->getOption('orderBy');
/** @var QuestionHelper $helper */
$helper = $this->getHelper('question');
do {
$result = $this->shortUrlService->listShortUrls($page, $searchTerm, $tags);
$result = $this->shortUrlService->listShortUrls($page, $searchTerm, $tags, $this->processOrderBy($input));
$page++;
$table = new Table($output);
@ -136,4 +145,15 @@ class ListShortcodesCommand extends Command
}
} while ($continue);
}
protected function processOrderBy(InputInterface $input)
{
$orderBy = $input->getOption('orderBy');
if (empty($orderBy)) {
return null;
}
$orderBy = explode(',', $orderBy);
return count($orderBy) === 1 ? $orderBy[0] : [$orderBy[0] => $orderBy[1]];
}
}

View File

@ -46,7 +46,7 @@ class ListShortcodesCommandTest extends TestCase
public function noInputCallsListJustOnce()
{
$this->questionHelper->setInputStream($this->getInputStream('\n'));
$this->shortUrlService->listShortUrls(1, null, [])->willReturn(new Paginator(new ArrayAdapter()))
$this->shortUrlService->listShortUrls(1, null, [], null)->willReturn(new Paginator(new ArrayAdapter()))
->shouldBeCalledTimes(1);
$this->commandTester->execute(['command' => 'shortcode:list']);
@ -103,7 +103,7 @@ class ListShortcodesCommandTest extends TestCase
{
$page = 5;
$this->questionHelper->setInputStream($this->getInputStream('\n'));
$this->shortUrlService->listShortUrls($page, null, [])->willReturn(new Paginator(new ArrayAdapter()))
$this->shortUrlService->listShortUrls($page, null, [], null)->willReturn(new Paginator(new ArrayAdapter()))
->shouldBeCalledTimes(1);
$this->commandTester->execute([
@ -118,7 +118,7 @@ class ListShortcodesCommandTest extends TestCase
public function ifTagsFlagIsProvidedTagsColumnIsIncluded()
{
$this->questionHelper->setInputStream($this->getInputStream('\n'));
$this->shortUrlService->listShortUrls(1, null, [])->willReturn(new Paginator(new ArrayAdapter()))
$this->shortUrlService->listShortUrls(1, null, [], null)->willReturn(new Paginator(new ArrayAdapter()))
->shouldBeCalledTimes(1);
$this->commandTester->execute([

View File

@ -20,21 +20,46 @@ class ShortUrlRepository extends EntityRepository implements ShortUrlRepositoryI
$qb = $this->createListQueryBuilder($searchTerm, $tags);
$qb->select('s');
// Set limit and offset
if (isset($limit)) {
$qb->setMaxResults($limit);
}
if (isset($offset)) {
$qb->setFirstResult($offset);
}
// In case the ordering has been specified, the query could be more complex. Process it
if (isset($orderBy)) {
if (is_string($orderBy)) {
$qb->orderBy($orderBy);
} elseif (is_array($orderBy)) {
$key = key($orderBy);
$qb->orderBy($key, $orderBy[$key]);
return $this->processOrderByForList($qb, $orderBy);
}
} else {
// With no order by, order by date and just return the list of ShortUrls
$qb->orderBy('s.dateCreated');
return $qb->getQuery()->getResult();
}
protected function processOrderByForList(QueryBuilder $qb, $orderBy)
{
$fieldName = is_array($orderBy) ? key($orderBy) : $orderBy;
$order = is_array($orderBy) ? $orderBy[$fieldName] : 'ASC';
if (in_array($fieldName, [
'visits',
'visitsCount',
'visitCount',
])) {
$qb->addSelect('COUNT(v) AS totalVisits')
->leftJoin('s.visits', 'v')
->groupBy('s')
->orderBy('totalVisits', $order);
return array_column($qb->getQuery()->getResult(), 0);
} elseif (in_array($fieldName, [
'originalUrl',
'shortCode',
'dateCreated',
])) {
$qb->orderBy('s.' . $fieldName, $order);
}
return $qb->getQuery()->getResult();

View File

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

View File

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

View File

@ -75,6 +75,7 @@ class ListShortcodesAction extends AbstractRestAction
isset($query['page']) ? $query['page'] : 1,
isset($query['searchTerm']) ? $query['searchTerm'] : null,
isset($query['tags']) ? $query['tags'] : [],
isset($query['orderBy']) ? $query['orderBy'] : null,
];
}
}

View File

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