Improved validation logic for nutritional values and added error handling for invalid inputs.
136 lines
3.8 KiB
PHP
136 lines
3.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Casts;
|
|
|
|
use Domain\Models\ValueObjects\Products\NutritionalValue;
|
|
use Domain\Models\ValueObjects\Products\NutritionalValues;
|
|
use Domain\Models\ValueObjects\Products\NutritionnalUnit;
|
|
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Arr;
|
|
|
|
/**
|
|
* @implements CastsAttributes<NutritionalValues|null, NutritionalValues|array<string, mixed>|string|null>
|
|
*/
|
|
class NutritionalValuesCast implements CastsAttributes
|
|
{
|
|
/**
|
|
* @param array<string, mixed> $attributes
|
|
*/
|
|
public function get(Model $model, string $key, mixed $value, array $attributes): ?NutritionalValues
|
|
{
|
|
if ($value === null || $value === '' || $value === '[]') {
|
|
return null;
|
|
}
|
|
|
|
if (! is_string($value)) {
|
|
throw new \InvalidArgumentException('The given value is not a string.');
|
|
}
|
|
|
|
$data = json_decode($value, true);
|
|
|
|
if (! is_array($data)) {
|
|
throw new \InvalidArgumentException('The given value is not a valid JSON array.');
|
|
}
|
|
|
|
if ($data === []) {
|
|
return null;
|
|
}
|
|
|
|
return $this->fromArray($data);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $attributes
|
|
* @return array<string, string>
|
|
*/
|
|
public function set(Model $model, string $key, mixed $value, array $attributes): array
|
|
{
|
|
if ($value === null || $value === [] || $value === '' || $value === '[]') {
|
|
return [$key => '[]'];
|
|
}
|
|
|
|
if (is_string($value)) {
|
|
$value = json_decode($value, true);
|
|
}
|
|
|
|
if (is_array($value)) {
|
|
$value = $this->fromArray($value);
|
|
}
|
|
|
|
if ($value === null) {
|
|
return [$key => '[]'];
|
|
}
|
|
|
|
if (! $value instanceof NutritionalValues) {
|
|
throw new \InvalidArgumentException('The given value is not a NutritionalValues instance.');
|
|
}
|
|
|
|
return [$key => (string) json_encode($value->toArray(), JSON_THROW_ON_ERROR)];
|
|
}
|
|
|
|
/**
|
|
* @param array<array-key, mixed> $data
|
|
*/
|
|
private function fromArray(array $data): ?NutritionalValues
|
|
{
|
|
if ($data === []) {
|
|
return null;
|
|
}
|
|
|
|
$getProperty = function (string $key) use ($data): ?NutritionalValue {
|
|
$item = Arr::get($data, $key);
|
|
|
|
return is_array($item) ? $this->toNutritionalValue($item) : null;
|
|
};
|
|
|
|
$refWeightG = $getProperty('refWeightG');
|
|
|
|
if ($refWeightG === null) {
|
|
return null;
|
|
}
|
|
|
|
return new NutritionalValues(
|
|
refWeightG: $refWeightG,
|
|
kj: $getProperty('kj'),
|
|
kcal: $getProperty('kcal'),
|
|
fatG: $getProperty('fatG'),
|
|
satFatG: $getProperty('satFatG'),
|
|
carbG: $getProperty('carbG'),
|
|
sugarG: $getProperty('sugarG'),
|
|
fiberG: $getProperty('fiberG'),
|
|
proteinG: $getProperty('proteinG'),
|
|
saltG: $getProperty('saltG'),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<array-key, mixed> $data
|
|
*/
|
|
private function toNutritionalValue(array $data): ?NutritionalValue
|
|
{
|
|
$rawItemVal = Arr::get($data, 'value');
|
|
$rawItemUnit = Arr::get($data, 'unit');
|
|
|
|
if (! is_string($rawItemVal) && ! is_numeric($rawItemVal)) {
|
|
return null;
|
|
}
|
|
|
|
if (! is_string($rawItemUnit) && ! $rawItemUnit instanceof NutritionnalUnit) {
|
|
return null;
|
|
}
|
|
|
|
$value = mb_trim((string) $rawItemVal);
|
|
$unit = $rawItemUnit instanceof NutritionnalUnit
|
|
? $rawItemUnit
|
|
: NutritionnalUnit::tryFrom((string) $rawItemUnit);
|
|
|
|
if ($value === '' || $unit === null) {
|
|
return null;
|
|
}
|
|
|
|
return new NutritionalValue($value, $unit);
|
|
}
|
|
}
|