Created
November 30, 2022 12:26
-
-
Save Gummibeer/764547ef1248b701ce1b2470853f38eb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Hospitable\Avalara\DTOs; | |
use Carbon\CarbonInterface; | |
use Hospitable\Avalara\Collections\Collection; | |
use Illuminate\Contracts\Support\Arrayable; | |
use Illuminate\Contracts\Support\Jsonable; | |
use JsonSerializable; | |
use ReflectionClass; | |
use TypeError; | |
abstract class DataTransferObject implements Arrayable, Jsonable, JsonSerializable | |
{ | |
public static function fromArray(array $data): static | |
{ | |
$class = new ReflectionClass(static::class); | |
$properties = $class->getProperties(); | |
$arguments = []; | |
foreach ($properties as $property) { | |
$type = $property->getType()?->getName() ?? 'string'; | |
$value = data_get($data, $property->getName()); | |
if (enum_exists($type)) { | |
$arguments[$property->getName()] = $type::from($value); | |
continue; | |
} | |
if (! class_exists($type)) { | |
$arguments[$property->getName()] = $value; | |
continue; | |
} | |
if (is_subclass_of($type, Collection::class)) { | |
$arguments[$property->getName()] = $type::fromArray($value ?? []); | |
continue; | |
} | |
if (is_subclass_of($type, self::class)) { | |
$arguments[$property->getName()] = $value ? $type::fromArray($value) : null; | |
continue; | |
} | |
if (in_array(CarbonInterface::class, class_implements($type), true)) { | |
$arguments[$property->getName()] = $type::make($value); | |
continue; | |
} | |
throw new TypeError("[{$type}] is an existing class but not handled by DataTransferObject::fromArray() implementation."); | |
} | |
return new static(...$arguments); | |
} | |
/** | |
* @param array|static $data | |
* @return static | |
*/ | |
public function merge(array|self $data): static | |
{ | |
return static::fromArray(array_merge( | |
$this->toArray(), | |
$data instanceof self ? $data->toArray() : $data | |
)); | |
} | |
public function toArray(): array | |
{ | |
return collect(get_object_vars($this)) | |
->filter(fn (mixed $value): bool => filled($value)) | |
->map(fn (mixed $value): mixed => $value instanceof CarbonInterface ? $value->toDateString() : $value) | |
->toArray(); | |
} | |
public function toJson($options = 0): string | |
{ | |
return json_encode($this, JSON_THROW_ON_ERROR | $options); | |
} | |
public function jsonSerialize(): array | |
{ | |
return $this->toArray(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment