Last active
September 12, 2022 17:44
-
-
Save roquie/21ae3db03e45bc9b8d3f30d8694d6264 to your computer and use it in GitHub Desktop.
Cycle ORM typecaster
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 | |
declare(strict_types=1); | |
namespace App\Domain\Common; | |
use Ramsey\Uuid\Uuid; | |
use Ramsey\Uuid\UuidInterface; | |
final class SortableUuid implements \Stringable | |
{ | |
private UuidInterface $value; | |
public function __construct( | |
?UuidInterface $uuid = null | |
) { | |
$uuid = $uuid ?: Uuid::uuid6(); | |
if (!method_exists($uuid, 'getDateTime')) { | |
throw new \ValueError('Only UUID V6 supported.'); | |
} | |
$this->value = $uuid; | |
} | |
public function getValue(): UuidInterface | |
{ | |
return $this->value; | |
} | |
public function __toString(): string | |
{ | |
return (string) $this->value; | |
} | |
public function getDateTime(): \DateTimeImmutable | |
{ | |
return \DateTimeImmutable::createFromInterface( | |
$this->value->getDateTime() | |
); | |
} | |
} |
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 | |
declare(strict_types=1); | |
namespace App\Infrastructure\CycleORM; | |
use App\Domain\Common\Cause; | |
use App\Domain\Common\SortableUuid; | |
use App\Domain\Common\URL; | |
use App\Domain\Event\Duration; | |
use Cycle\ORM\Exception\TypecastException; | |
use Cycle\ORM\Parser\CastableInterface; | |
use Cycle\ORM\Parser\UncastableInterface; | |
use Ramsey\Uuid\Uuid; | |
use Ramsey\Uuid\UuidInterface; | |
final class TypeCaster implements CastableInterface, UncastableInterface | |
{ | |
/** @var array<class-string> */ | |
private const SUPPORTED_RULES = [ | |
URL::class, | |
Duration::class, | |
Cause::class, | |
UuidInterface::class, | |
SortableUuid::class, | |
]; | |
private array $rules = []; | |
public function setRules(array $rules): array | |
{ | |
foreach ($rules as $key => $rule) { | |
if (\in_array($rule, self::SUPPORTED_RULES, true)) { | |
unset($rules[$key]); | |
$this->rules[$key] = $rule; | |
} | |
} | |
return $rules; | |
} | |
public function cast(array $data): array | |
{ | |
foreach ($this->rules as $column => $rule) { | |
if (! isset($data[$column])) { | |
continue; | |
} | |
try { | |
if (\is_object($data[$column])) { | |
continue; | |
} | |
$data[$column] = match ($rule) { | |
URL::class => new URL($data[$column]), | |
Duration::class => new Duration($data[$column]), | |
Cause::class => new Cause($data[$column]), | |
SortableUuid::class => new SortableUuid(Uuid::fromString($data[$column])), | |
UuidInterface::class => Uuid::fromString($data[$column]), | |
default => $data[$column] | |
}; | |
} catch (\Throwable $e) { | |
throw new TypecastException("Unable to cast the `$column` field: {$e->getMessage()}"); | |
} | |
} | |
return $data; | |
} | |
public function uncast(array $data): array | |
{ | |
foreach ($this->rules as $column => $rule) { | |
if (! isset($data[$column])) { | |
continue; | |
} | |
try { | |
$data[$column] = match ($rule) { | |
URL::class, | |
UuidInterface::class, | |
Cause::class, | |
SortableUuid::class => (string) $data[$column], | |
Duration::class => $data[$column]->getValue(), | |
default => $data[$column] | |
}; | |
} catch (\Throwable $e) { | |
throw new TypecastException("Unable to uncast the `$column` field: {$e->getMessage()}"); | |
} | |
} | |
return $data; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment