Files
reservas/app/Integrations/SnipeIt/SnipeItAssetMapper.php

87 lines
3.0 KiB
PHP

<?php
namespace App\Integrations\SnipeIt;
use App\Integrations\SnipeIt\Data\AssetData;
use App\Integrations\SnipeIt\Exceptions\SnipeItMappingException;
use Carbon\CarbonImmutable;
use Illuminate\Support\Arr;
use Throwable;
final class SnipeItAssetMapper
{
/** @param array<string, mixed> $row */
public function map(array $row): AssetData
{
$id = $this->integer($row['id'] ?? null);
$assetTag = $this->text($row['asset_tag'] ?? null);
if ($id === null || $id < 1 || $assetTag === null) {
throw new SnipeItMappingException('A resposta do Snipe-IT contém um ativo sem ID ou etiqueta válida.');
}
$modelName = $this->text(Arr::get($row, 'model.name'));
return new AssetData(
snipeAssetId: $id,
assetTag: $assetTag,
name: $this->text($row['name'] ?? null) ?? $modelName ?? $assetTag,
serial: $this->text($row['serial'] ?? null),
modelId: $this->integer(Arr::get($row, 'model.id')),
modelName: $modelName,
categoryId: $this->integer(Arr::get($row, 'category.id')),
categoryName: $this->text(Arr::get($row, 'category.name')),
manufacturer: $this->text(Arr::get($row, 'manufacturer.name')),
statusId: $this->integer(Arr::get($row, 'status_label.id')),
statusName: $this->text(Arr::get($row, 'status_label.name')),
locationId: $this->integer(Arr::get($row, 'rtd_location.id') ?? Arr::get($row, 'location.id')),
locationName: $this->text(Arr::get($row, 'rtd_location.name') ?? Arr::get($row, 'location.name')),
requestable: $this->boolean($row['requestable'] ?? false),
assignedType: $this->text(Arr::get($row, 'assigned_to.type')),
assignedId: $this->integer(Arr::get($row, 'assigned_to.id')),
imageUrl: $this->text($row['image'] ?? $row['image_url'] ?? null),
sourceUpdatedAt: $this->date(Arr::get($row, 'updated_at.datetime') ?? Arr::get($row, 'updated_at.date') ?? $row['updated_at'] ?? null),
);
}
private function text(mixed $value): ?string
{
if (! is_scalar($value)) {
return null;
}
$decoded = trim(html_entity_decode((string) $value, ENT_QUOTES | ENT_HTML5, 'UTF-8'));
return $decoded === '' ? null : $decoded;
}
private function integer(mixed $value): ?int
{
return is_numeric($value) ? (int) $value : null;
}
private function boolean(mixed $value): bool
{
if (is_bool($value)) {
return $value;
}
return in_array(strtolower((string) $value), ['1', 'true', 'yes', 'sim'], true);
}
private function date(mixed $value): ?CarbonImmutable
{
$text = $this->text($value);
if ($text === null) {
return null;
}
try {
return CarbonImmutable::parse($text);
} catch (Throwable) {
return null;
}
}
}