ldc-arcadia-api/src/Infra/Adapters/Directories/EloquentIncoShortSheetDirectory.php

140 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
namespace Infra\Adapters\Directories;
use Domain\Models\Entities\Inco\IncoShortSheet;
use Domain\Models\ValueObjects\Inco\IncoId;
use Domain\Models\ValueObjects\Inco\IncoIdQuery;
use Domain\Models\ValueObjects\Inco\IncoSheetFilter;
use Domain\Models\ValueObjects\Inco\IncoSheetSortColumn;
use Domain\Models\ValueObjects\Inco\IncoSheetSorter;
use Domain\Ports\Directories\IncoShortSheetDirectory;
use Infra\Database\Models\IncoSheet as IncoSheetModel;
use Shared\Helpers\DatesHelper;
use Shared\Paginated;
use Shared\Pagination;
final class EloquentIncoShortSheetDirectory implements IncoShortSheetDirectory
{
private const SHORT_FIELDS = ['id', 'name', 'label', 'created_at', 'updated_at'];
#[\Override]
public function findAll(
Pagination $pagination,
IncoSheetSorter $sorter,
?IncoSheetFilter $filter = null
): Paginated {
$query = IncoSheetModel::query()->select(self::SHORT_FIELDS);
if ($filter !== null) {
if ($filter->since !== null) {
$query->where(static function ($q) use ($filter): void {
$q->where('updated_at', '>=', $filter->since)
->orWhere('created_at', '>=', $filter->since);
});
}
if (! empty($filter->brands)) {
$query->whereIn('brand->code', $filter->brands);
}
}
$total = (int) (clone $query)->count();
$rows = (clone $query)
->orderBy(
$this->toSqlColumn($sorter->sortBy),
$sorter->direction
)
->offset($pagination->from())
->limit($pagination->pageSize())
->get();
$items = [];
foreach ($rows as $row) {
$items[] = $this->toDomain($row);
}
/** @var IncoShortSheet[] $items */
return new Paginated($pagination, $items, $total);
}
#[\Override]
public function search(
IncoIdQuery $query,
Pagination $pagination,
string ...$brands
): Paginated {
$dbQuery = IncoSheetModel::query()->select(self::SHORT_FIELDS);
$dbQuery->where('id', 'LIKE', $query->value);
if (! empty($brands)) {
$dbQuery->whereIn('brand->code', $brands);
}
$total = (int) (clone $dbQuery)->count();
$rows = $dbQuery
->offset($pagination->from())
->limit($pagination->pageSize())
->get();
$items = [];
foreach ($rows as $row) {
$items[] = $this->toDomain($row);
}
/** @var IncoShortSheet[] $items */
return new Paginated($pagination, $items, $total);
}
#[\Override]
public function find(IncoId $id): ?IncoShortSheet
{
$model = IncoSheetModel::query()
->select(self::SHORT_FIELDS)
->where('id', $id->value)
->first();
if ($model === null) {
return null;
}
return $this->toDomain($model);
}
private function toDomain(IncoSheetModel $model): IncoShortSheet
{
$rawId = $model->getAttribute('id');
$rawName = $model->getAttribute('name');
$rawLabel = $model->getAttribute('label');
$rawCreatedAt = $model->getAttribute('created_at');
$rawUpdatedAt = $model->getAttribute('updated_at');
$id = is_string($rawId) || is_numeric($rawId) ? (string) $rawId : '';
$name = is_string($rawName) ? $rawName : '';
$label = is_string($rawLabel) ? $rawLabel : '';
$createdAt = is_string($rawCreatedAt) ? DatesHelper::parseDateTime($rawCreatedAt) : null;
$updatedAt = is_string($rawUpdatedAt) ? DatesHelper::parseDateTime($rawUpdatedAt) : null;
return new IncoShortSheet(
id: new IncoId($id),
name: $name,
label: $label,
createdAt: $createdAt,
updatedAt: $updatedAt,
);
}
private function toSqlColumn(IncoSheetSortColumn $column): string
{
return match ($column) {
IncoSheetSortColumn::incoSheetId => 'id',
IncoSheetSortColumn::createdAt => 'created_at',
IncoSheetSortColumn::updatedAt => 'updated_at',
};
}
}