mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'feature/67' into develop
This commit is contained in:
commit
c3fd433446
@ -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"
|
"$ref": "#/parameters/Authorization"
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
@ -1,8 +1,8 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Shlink 1.0\n"
|
"Project-Id-Version: Shlink 1.0\n"
|
||||||
"POT-Creation-Date: 2016-10-22 13:14+0200\n"
|
"POT-Creation-Date: 2016-10-22 23:12+0200\n"
|
||||||
"PO-Revision-Date: 2016-10-22 13:15+0200\n"
|
"PO-Revision-Date: 2016-10-22 23:13+0200\n"
|
||||||
"Last-Translator: Alejandro Celaya <alejandro@alejandrocelaya.com>\n"
|
"Last-Translator: Alejandro Celaya <alejandro@alejandrocelaya.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: es_ES\n"
|
"Language: es_ES\n"
|
||||||
@ -172,6 +172,12 @@ msgstr ""
|
|||||||
msgid "A comma-separated list of tags to filter results"
|
msgid "A comma-separated list of tags to filter results"
|
||||||
msgstr "Una lista de etiquetas separadas por coma para filtrar el resultado"
|
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"
|
msgid "Whether to display the tags or not"
|
||||||
msgstr "Si se desea mostrar las etiquetas o no"
|
msgstr "Si se desea mostrar las etiquetas o no"
|
||||||
|
|
||||||
|
@ -70,6 +70,14 @@ class ListShortcodesCommand extends Command
|
|||||||
InputOption::VALUE_OPTIONAL,
|
InputOption::VALUE_OPTIONAL,
|
||||||
$this->translator->translate('A comma-separated list of tags to filter results')
|
$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(
|
->addOption(
|
||||||
'showTags',
|
'showTags',
|
||||||
null,
|
null,
|
||||||
@ -85,12 +93,13 @@ class ListShortcodesCommand extends Command
|
|||||||
$tags = $input->getOption('tags');
|
$tags = $input->getOption('tags');
|
||||||
$tags = ! empty($tags) ? explode(',', $tags) : [];
|
$tags = ! empty($tags) ? explode(',', $tags) : [];
|
||||||
$showTags = $input->getOption('showTags');
|
$showTags = $input->getOption('showTags');
|
||||||
|
$orderBy = $input->getOption('orderBy');
|
||||||
|
|
||||||
/** @var QuestionHelper $helper */
|
/** @var QuestionHelper $helper */
|
||||||
$helper = $this->getHelper('question');
|
$helper = $this->getHelper('question');
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$result = $this->shortUrlService->listShortUrls($page, $searchTerm, $tags);
|
$result = $this->shortUrlService->listShortUrls($page, $searchTerm, $tags, $this->processOrderBy($input));
|
||||||
$page++;
|
$page++;
|
||||||
$table = new Table($output);
|
$table = new Table($output);
|
||||||
|
|
||||||
@ -136,4 +145,15 @@ class ListShortcodesCommand extends Command
|
|||||||
}
|
}
|
||||||
} while ($continue);
|
} 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]];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,8 @@ class ListShortcodesCommandTest extends TestCase
|
|||||||
public function noInputCallsListJustOnce()
|
public function noInputCallsListJustOnce()
|
||||||
{
|
{
|
||||||
$this->questionHelper->setInputStream($this->getInputStream('\n'));
|
$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);
|
->shouldBeCalledTimes(1);
|
||||||
|
|
||||||
$this->commandTester->execute(['command' => 'shortcode:list']);
|
$this->commandTester->execute(['command' => 'shortcode:list']);
|
||||||
}
|
}
|
||||||
@ -103,8 +103,8 @@ class ListShortcodesCommandTest extends TestCase
|
|||||||
{
|
{
|
||||||
$page = 5;
|
$page = 5;
|
||||||
$this->questionHelper->setInputStream($this->getInputStream('\n'));
|
$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);
|
->shouldBeCalledTimes(1);
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
'command' => 'shortcode:list',
|
'command' => 'shortcode:list',
|
||||||
@ -118,8 +118,8 @@ class ListShortcodesCommandTest extends TestCase
|
|||||||
public function ifTagsFlagIsProvidedTagsColumnIsIncluded()
|
public function ifTagsFlagIsProvidedTagsColumnIsIncluded()
|
||||||
{
|
{
|
||||||
$this->questionHelper->setInputStream($this->getInputStream('\n'));
|
$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);
|
->shouldBeCalledTimes(1);
|
||||||
|
|
||||||
$this->commandTester->execute([
|
$this->commandTester->execute([
|
||||||
'command' => 'shortcode:list',
|
'command' => 'shortcode:list',
|
||||||
|
@ -20,21 +20,46 @@ class ShortUrlRepository extends EntityRepository implements ShortUrlRepositoryI
|
|||||||
$qb = $this->createListQueryBuilder($searchTerm, $tags);
|
$qb = $this->createListQueryBuilder($searchTerm, $tags);
|
||||||
$qb->select('s');
|
$qb->select('s');
|
||||||
|
|
||||||
|
// Set limit and offset
|
||||||
if (isset($limit)) {
|
if (isset($limit)) {
|
||||||
$qb->setMaxResults($limit);
|
$qb->setMaxResults($limit);
|
||||||
}
|
}
|
||||||
if (isset($offset)) {
|
if (isset($offset)) {
|
||||||
$qb->setFirstResult($offset);
|
$qb->setFirstResult($offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In case the ordering has been specified, the query could be more complex. Process it
|
||||||
if (isset($orderBy)) {
|
if (isset($orderBy)) {
|
||||||
if (is_string($orderBy)) {
|
return $this->processOrderByForList($qb, $orderBy);
|
||||||
$qb->orderBy($orderBy);
|
}
|
||||||
} elseif (is_array($orderBy)) {
|
|
||||||
$key = key($orderBy);
|
// With no order by, order by date and just return the list of ShortUrls
|
||||||
$qb->orderBy($key, $orderBy[$key]);
|
$qb->orderBy('s.dateCreated');
|
||||||
}
|
return $qb->getQuery()->getResult();
|
||||||
} else {
|
}
|
||||||
$qb->orderBy('s.dateCreated');
|
|
||||||
|
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();
|
return $qb->getQuery()->getResult();
|
||||||
|
@ -34,13 +34,14 @@ class ShortUrlService implements ShortUrlServiceInterface
|
|||||||
* @param int $page
|
* @param int $page
|
||||||
* @param string $searchQuery
|
* @param string $searchQuery
|
||||||
* @param array $tags
|
* @param array $tags
|
||||||
|
* @param null $orderBy
|
||||||
* @return ShortUrl[]|Paginator
|
* @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 */
|
/** @var ShortUrlRepository $repo */
|
||||||
$repo = $this->em->getRepository(ShortUrl::class);
|
$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)
|
$paginator->setItemCountPerPage(PaginableRepositoryAdapter::ITEMS_PER_PAGE)
|
||||||
->setCurrentPageNumber($page);
|
->setCurrentPageNumber($page);
|
||||||
|
|
||||||
|
@ -11,9 +11,10 @@ interface ShortUrlServiceInterface
|
|||||||
* @param int $page
|
* @param int $page
|
||||||
* @param string $searchQuery
|
* @param string $searchQuery
|
||||||
* @param array $tags
|
* @param array $tags
|
||||||
|
* @param null $orderBy
|
||||||
* @return ShortUrl[]|Paginator
|
* @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
|
* @param string $shortCode
|
||||||
|
@ -75,6 +75,7 @@ class ListShortcodesAction extends AbstractRestAction
|
|||||||
isset($query['page']) ? $query['page'] : 1,
|
isset($query['page']) ? $query['page'] : 1,
|
||||||
isset($query['searchTerm']) ? $query['searchTerm'] : null,
|
isset($query['searchTerm']) ? $query['searchTerm'] : null,
|
||||||
isset($query['tags']) ? $query['tags'] : [],
|
isset($query['tags']) ? $query['tags'] : [],
|
||||||
|
isset($query['orderBy']) ? $query['orderBy'] : null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,8 @@ class ListShortcodesActionTest extends TestCase
|
|||||||
public function properListReturnsSuccessResponse()
|
public function properListReturnsSuccessResponse()
|
||||||
{
|
{
|
||||||
$page = 3;
|
$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);
|
->shouldBeCalledTimes(1);
|
||||||
|
|
||||||
$response = $this->action->__invoke(
|
$response = $this->action->__invoke(
|
||||||
ServerRequestFactory::fromGlobals()->withQueryParams([
|
ServerRequestFactory::fromGlobals()->withQueryParams([
|
||||||
@ -52,8 +52,8 @@ class ListShortcodesActionTest extends TestCase
|
|||||||
public function anExceptionsReturnsErrorResponse()
|
public function anExceptionsReturnsErrorResponse()
|
||||||
{
|
{
|
||||||
$page = 3;
|
$page = 3;
|
||||||
$this->service->listShortUrls($page, null, [])->willThrow(\Exception::class)
|
$this->service->listShortUrls($page, null, [], null)->willThrow(\Exception::class)
|
||||||
->shouldBeCalledTimes(1);
|
->shouldBeCalledTimes(1);
|
||||||
|
|
||||||
$response = $this->action->__invoke(
|
$response = $this->action->__invoke(
|
||||||
ServerRequestFactory::fromGlobals()->withQueryParams([
|
ServerRequestFactory::fromGlobals()->withQueryParams([
|
||||||
|
Loading…
Reference in New Issue
Block a user