Skip to content

Commit

Permalink
sorting lists (#191)
Browse files Browse the repository at this point in the history
* sorting lists

* fix

---------

Co-authored-by: dawid.miklas <dawid.miklas@escolasoft.com>
  • Loading branch information
dicani0 and dawid.miklas authored Apr 20, 2023
1 parent 67a628b commit 9e6f924
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 12 deletions.
6 changes: 4 additions & 2 deletions src/Http/Controllers/ContentApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace EscolaLms\HeadlessH5P\Http\Controllers;

use EscolaLms\Core\Dtos\OrderDto;
use EscolaLms\Core\Http\Controllers\EscolaLmsBaseController;
use EscolaLms\HeadlessH5P\Dtos\ContentFilterCriteriaDto;
use EscolaLms\HeadlessH5P\Http\Controllers\Swagger\ContentApiSwagger;
Expand Down Expand Up @@ -34,6 +35,7 @@ public function __construct(HeadlessH5PServiceContract $hh5pService, H5PContentR
public function index(ContentListRequest $request): JsonResponse
{
$contentFilterDto = ContentFilterCriteriaDto::instantiateFromRequest($request);
$orderDto = OrderDto::instantiateFromRequest($request);
$columns = [
'hh5p_contents.id',
'hh5p_contents.uuid',
Expand All @@ -43,8 +45,8 @@ public function index(ContentListRequest $request): JsonResponse
'hh5p_contents.parameters',
];
$list = $request->get('per_page') !== null && $request->get('per_page') == 0 ?
$this->contentRepository->unpaginatedList($contentFilterDto, $columns) :
$this->contentRepository->list($contentFilterDto, $request->get('per_page'), $columns);
$this->contentRepository->unpaginatedList($contentFilterDto, $columns, $orderDto) :
$this->contentRepository->list($contentFilterDto, $request->get('per_page'), $columns, $orderDto);

return $this->sendResponseForResource(ContentIndexResource::collection($list));
}
Expand Down
2 changes: 2 additions & 0 deletions src/Http/Requests/ContentListRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public function rules(): array
return [
'title' => ['sometimes', 'nullable', 'string'],
'library_id' => ['sometimes', 'nullable', 'integer'],
'order_by' => ['sometimes', 'nullable', 'string', 'in:id,title,library_id,library_title'],
'order' => ['sometimes', 'nullable', 'string', 'in:ASC,DESC'],
];
}
}
7 changes: 5 additions & 2 deletions src/Repositories/Contracts/H5PContentRepositoryContract.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace EscolaLms\HeadlessH5P\Repositories\Contracts;

use EscolaLms\Core\Dtos\OrderDto;
use EscolaLms\HeadlessH5P\Dtos\ContentFilterCriteriaDto;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Collection;
Expand All @@ -18,12 +19,14 @@ public function edit(int $id, string $library, string $params, string $nonce): i
public function list(
ContentFilterCriteriaDto $contentFilterDto,
$per_page = 15,
array $columns = ['hh5p_contents.*']
array $columns = ['hh5p_contents.*'],
?OrderDto $orderDto = null
): LengthAwarePaginator;

public function unpaginatedList(
ContentFilterCriteriaDto $contentFilterDto,
array $columns = ['hh5p_contents.*']
array $columns = ['hh5p_contents.*'],
?OrderDto $orderDto = null
): Collection;

public function delete(int $id): int;
Expand Down
34 changes: 27 additions & 7 deletions src/Repositories/H5PContentRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace EscolaLms\HeadlessH5P\Repositories;

use EscolaLms\Core\Dtos\OrderDto;
use EscolaLms\Core\Repositories\Criteria\Criterion;
use EscolaLms\HeadlessH5P\Dtos\ContentFilterCriteriaDto;
use EscolaLms\HeadlessH5P\Exceptions\H5PException;
Expand Down Expand Up @@ -129,10 +130,13 @@ private function moveTmpFilesToContentFolders($nonce, $contentId): bool

public function list(
ContentFilterCriteriaDto $contentFilterDto,
$per_page = 15,
array $columns = ['hh5p_contents.*']
): LengthAwarePaginator {
$per_page = 15,
array $columns = ['hh5p_contents.*'],
?OrderDto $orderDto = null,
): LengthAwarePaginator
{
$query = $this->getQueryContent($contentFilterDto, $columns);
$query = $this->orderBy($query, $orderDto);
$paginator = $query->paginate(intval($per_page));

$paginator->getCollection()->transform(function ($content) {
Expand All @@ -150,9 +154,12 @@ public function list(

public function unpaginatedList(
ContentFilterCriteriaDto $contentFilterDto,
array $columns = ['hh5p_contents.*']
): Collection {
array $columns = ['hh5p_contents.*'],
?OrderDto $orderDto = null,
): Collection
{
$query = $this->getQueryContent($contentFilterDto, $columns);
$query = $this->orderBy($query, $orderDto);
$list = $query->get();

$list->transform(function ($content) {
Expand Down Expand Up @@ -254,8 +261,7 @@ private function applyCriteria(Builder $query, array $criteria): Builder
private function getQueryContent(ContentFilterCriteriaDto $contentFilterDto, array $columns = ['*']): Builder
{
$query = H5PContent::with(['library'])
->select($columns)
->orderBy('id', 'desc');
->select($columns);

$query = self::applyQueryJoin($query);
$query = self::applyQuerySelect($query);
Expand All @@ -282,4 +288,18 @@ private function filterParameters(H5PContent $h5pContent, H5PLibrary $h5pLibrary

$this->hh5pService->getCore()->filterParameters($content);
}

private function orderBy(Builder $query, ?OrderDto $dto): Builder
{
if ($dto) {
match ($dto->getOrderBy()) {
'library_title' => $query
->withAggregate('library', 'title')
->orderBy('library_title', $dto->getOrder() ?? 'asc'),
'title' => $query->orderBy('parameters->metadata->title', $dto->getOrder() ?? 'asc'),
default => $query->orderBy($dto->getOrderBy() ?? 'id', $dto->getOrder() ?? 'desc'),
};
}
return $query;
}
}
108 changes: 107 additions & 1 deletion tests/Api/ContentApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,112 @@ public function testContentList(): void
$this->assertEquals($h5pContents->first()->getKey(), $data[count($data) - 1]->id);
}

public function testContentListWithSorts(): void
{
$libraryOne = H5PLibrary::factory()->create([
'name' => 'A Library',
'title' => 'A Library',
'runnable' => 1
]);
$libraryTwo = H5PLibrary::factory()->create([
'name' => 'B Library',
'title' => 'B Library',
'runnable' => 1
]);

$contentOne = H5PContent::factory()->create([
'parameters' => '{"params":{"taskDescription":"Documentation tool","pagesList":[{"params":{"elementList":[{"params":{},"library":"H5P.Text 1.1","metadata":{"contentType":"Text","license":"U","title":"Untitled Text","authors":[],"changes":[],"extraTitle":"Untitled Text"},"subContentId":"da3387da-355a-49fb-92bc-3a9a4e4646a9"}],"helpTextLabel":"More information","helpText":""},"library":"H5P.StandardPage 1.5","metadata":{"contentType":"Standard page","license":"U","title":"Untitled Standard page","authors":[],"changes":[],"extraTitle":"Untitled Standard page"},"subContentId":"ac6ffdac-be02-448c-861c-969e6a09dbd5"}],"i10n":{"previousLabel":"poprzedni","nextLabel":"Next","closeLabel":"Close"}},"metadata":{"license":"U","authors":[],"changes":[],"extraTitle":"A title","title":"A title"}}',
'library_id' => $libraryOne->getKey(),
]);

$contentTwo = H5PContent::factory()->create([
'parameters' => '{"params":{"taskDescription":"Documentation tool","pagesList":[{"params":{"elementList":[{"params":{},"library":"H5P.Text 1.1","metadata":{"contentType":"Text","license":"U","title":"Untitled Text","authors":[],"changes":[],"extraTitle":"Untitled Text"},"subContentId":"da3387da-355a-49fb-92bc-3a9a4e4646a9"}],"helpTextLabel":"More information","helpText":""},"library":"H5P.StandardPage 1.5","metadata":{"contentType":"Standard page","license":"U","title":"Untitled Standard page","authors":[],"changes":[],"extraTitle":"Untitled Standard page"},"subContentId":"ac6ffdac-be02-448c-861c-969e6a09dbd5"}],"i10n":{"previousLabel":"poprzedni","nextLabel":"Next","closeLabel":"Close"}},"metadata":{"license":"U","authors":[],"changes":[],"extraTitle":"B title","title":"B title"}}',
'library_id' => $libraryTwo->getKey(),
]);

$this->authenticateAsAdmin();

$response = $this
->actingAs($this->user, 'api')
->json('GET', '/api/admin/hh5p/content', [
'order_by' => 'library_title',
'order' => 'ASC'
]);

$this->assertTrue($response->getData()->data[0]->library->name === $libraryOne->name);
$this->assertTrue($response->getData()->data[1]->library->name === $libraryTwo->name);

$response = $this
->actingAs($this->user, 'api')
->json('GET', '/api/admin/hh5p/content', [
'order_by' => 'library_title',
'order' => 'DESC'
]);

$this->assertTrue($response->getData()->data[0]->library->name === $libraryTwo->name);
$this->assertTrue($response->getData()->data[1]->library->name === $libraryOne->name);

$response = $this
->actingAs($this->user, 'api')
->json('GET', '/api/admin/hh5p/content', [
'order_by' => 'title',
'order' => 'ASC'
]);

$this->assertTrue($response->getData()->data[0]->title === 'A title');
$this->assertTrue($response->getData()->data[1]->title === 'B title');

$response = $this
->actingAs($this->user, 'api')
->json('GET', '/api/admin/hh5p/content', [
'order_by' => 'title',
'order' => 'DESC'
]);

$this->assertTrue($response->getData()->data[0]->title === 'B title');
$this->assertTrue($response->getData()->data[1]->title === 'A title');

$response = $this
->actingAs($this->user, 'api')
->json('GET', '/api/admin/hh5p/content', [
'order_by' => 'id',
'order' => 'ASC'
]);

$this->assertTrue($response->getData()->data[0]->id === $contentOne->getKey());
$this->assertTrue($response->getData()->data[1]->id === $contentTwo->getKey());

$response = $this
->actingAs($this->user, 'api')
->json('GET', '/api/admin/hh5p/content', [
'order_by' => 'id',
'order' => 'DESC'
]);

$this->assertTrue($response->getData()->data[0]->id === $contentTwo->getKey());
$this->assertTrue($response->getData()->data[1]->id === $contentOne->getKey());

$response = $this
->actingAs($this->user, 'api')
->json('GET', '/api/admin/hh5p/content', [
'order_by' => 'library_id',
'order' => 'ASC'
]);

$this->assertTrue($response->getData()->data[0]->library_id === $libraryOne->getKey());
$this->assertTrue($response->getData()->data[1]->library_id === $libraryTwo->getKey());

$response = $this
->actingAs($this->user, 'api')
->json('GET', '/api/admin/hh5p/content', [
'order_by' => 'library_id',
'order' => 'DESC'
]);

$this->assertTrue($response->getData()->data[0]->library_id === $libraryTwo->getKey());
$this->assertTrue($response->getData()->data[1]->library_id === $libraryOne->getKey());
}

public function testContentUnpaginatedList(): void
{
$h5pContents = H5PContent::factory()
Expand Down Expand Up @@ -530,7 +636,7 @@ public function testContentUploading(): void
$this->assertEquals('Arithmetic Quiz', $data->title);
$this->assertNotEquals('New Content (from file)', $data->title);

$this->assertEquals($data->uuid,$result->uuid);
$this->assertEquals($data->uuid, $result->uuid);
$this->assertEquals('Arithmetic Quiz', $result->title);
}

Expand Down

0 comments on commit 9e6f924

Please sign in to comment.