87 lines
3.0 KiB
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;
|
|
}
|
|
}
|
|
}
|