Skip to content

Commit

Permalink
chore: create cast resolver and cast contract
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielgomes94 committed Oct 17, 2023
1 parent 00dfb78 commit 5332992
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 46 deletions.
12 changes: 12 additions & 0 deletions src/Model/Casts/CastInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Mongolid\Model\Casts;

use MongoDB\BSON\UTCDateTime;

interface CastInterface
{
public static function get(mixed $value): mixed;

public static function set(mixed $value): mixed;
}
35 changes: 35 additions & 0 deletions src/Model/Casts/CastResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Mongolid\Model\Casts;

use Mongolid\Model\Casts\DateTime\DateTimeCast;
use Mongolid\Model\Casts\DateTime\DateTimeImmutableCast;
use Mongolid\Model\Casts\Exceptions\InvalidCastException;

class CastResolver
{
private const DATE_TIME = 'datetime';
private const IMMUTABLE_DATE_TIME = 'immutable_datetime';

public static array $validCasts = [
self::DATE_TIME,
self::IMMUTABLE_DATE_TIME,
];

public static function resolve(?string $cast): ?object
{
if (is_null($cast)) {
return null;
}

if (!in_array($cast, self::$validCasts)) {
throw new InvalidCastException($cast);
}

return match($cast) {
self::DATE_TIME => new DateTimeCast(),
self::IMMUTABLE_DATE_TIME => new DateTimeImmutableCast(),
default => null,
};
}
}
32 changes: 13 additions & 19 deletions src/Model/Casts/DateTime/BaseDateTimeCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@
use MongoDB\BSON\UTCDateTime;
use MongoDB\BSON\UTCDateTimeInterface;
use Mongolid\Model\Casts\CasterInterface;
use Mongolid\Model\Casts\CastInterface;

abstract class BaseDateTimeCast
abstract class BaseDateTimeCast implements CastInterface
{
private const DATE_TIME = 'datetime';
private const IMMUTABLE_DATE_TIME = 'immutable_datetime';


abstract public static function get(?UTCDateTime $value): ?DateTimeInterface;

public static function set(
null|DateTimeInterface|UTCDateTimeInterface $value
): ?UTCDateTime
/**
* @param UTCDateTime|null $value
* @return DateTimeInterface|null
*/
abstract public static function get(mixed $value): mixed;

/**
* @param DateTimeInterface|UTCDateTimeInterface|null $value
* @return UTCDateTime|null
*/
public static function set(mixed $value): mixed
{
if (is_null($value)) {
return null;
Expand All @@ -29,13 +32,4 @@ public static function set(

return new UTCDateTime($value);
}

public static function resolve(?string $cast): ?self
{
return match($cast) {
self::DATE_TIME => new DateTimeCast(),
self::IMMUTABLE_DATE_TIME => new DateTimeImmutableCast(),
default => null,
};
}
}
7 changes: 6 additions & 1 deletion src/Model/Casts/DateTime/DateTimeCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@

class DateTimeCast extends BaseDateTimeCast
{
public static function get(?UTCDateTime $value): ?DateTime
/**
* @param UTCDateTime|null $value
* @return DateTime|null
*/
public static function get(mixed $value): mixed
{
if (is_null($value)) {

return null;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Model/Casts/DateTime/DateTimeImmutableCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class DateTimeImmutableCast extends BaseDateTimeCast
* @param UTCDateTime|null $value
* @return DateTimeImmutable|null
*/
public static function get(?UTCDateTime $value): ?DateTimeImmutable
public static function get(mixed $value): mixed
{
if (is_null($value)) {
return null;
Expand Down
17 changes: 17 additions & 0 deletions src/Model/Casts/Exceptions/InvalidCastException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Mongolid\Model\Casts\Exceptions;

use InvalidArgumentException;
use Mongolid\Model\Casts\CastResolver;

class InvalidCastException extends InvalidArgumentException
{
public function __construct(string $cast)
{
$available = implode(',', CastResolver::$validCasts);
$message = "Invalid cast attribute: $cast. Use a valid one like $available";

parent::__construct($message);
}
}
9 changes: 4 additions & 5 deletions src/Model/HasAttributesTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
use Exception;
use Illuminate\Support\Str;
use Mongolid\Container\Container;
use Mongolid\Model\Casts\CastResolver;
use Mongolid\Model\Casts\DateTime\BaseDateTimeCast;
use Mongolid\Model\Casts\DateTime\DateTimeCast;
use Mongolid\Model\Casts\DateTime\DateTimeImmutableCast;
use stdClass;

/**
Expand Down Expand Up @@ -134,8 +133,8 @@ public function &getDocumentAttribute(string $key)
return $this->mutableCache[$key];
}

if ($caster = BaseDateTimeCast::resolve($this->casts[$key] ?? null)) {
$value = $caster->get($this->attributes[$key]);
if ($caster = CastResolver::resolve($this->casts[$key] ?? null)) {
$value = $caster->get($this->attributes[$key] ?? null);

return $value;
}
Expand Down Expand Up @@ -188,7 +187,7 @@ public function setDocumentAttribute(string $key, $value)
$value = $this->{$this->buildMutatorMethod($key, 'set')}($value);
}

if ($caster = BaseDateTimeCast::resolve($this->casts[$key] ?? null)) {
if ($caster = CastResolver::resolve($this->casts[$key] ?? null)) {
$value = $caster->set($value);
$this->attributes[$key] = $value;

Expand Down
15 changes: 8 additions & 7 deletions src/Model/HasLegacyAttributesTrait.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Mongolid\Model;

use Mongolid\Model\Casts\CastResolver;
use Mongolid\Model\Casts\DateTime\BaseDateTimeCast;
use Mongolid\Model\Casts\DateTime\DateTimeCast;
use Mongolid\Model\Casts\DateTime\DateTimeImmutableCast;
Expand Down Expand Up @@ -75,14 +76,14 @@ public function getAttribute(string $key)
{
$inAttributes = array_key_exists($key, $this->attributes);

if ($inAttributes) {
if ($caster = BaseDateTimeCast::resolve($this->casts[$key] ?? null)) {
$value = $caster->get($this->attributes[$key]);
$this->attributes[$key] = $value;
if ($caster = CastResolver::resolve($this->casts[$key] ?? null)) {
$value = $caster->get($this->attributes[$key] ?? null);
$this->attributes[$key] = $value;

return $this->attributes[$key];
}
return $this->attributes[$key];
}

if ($inAttributes) {
return $this->attributes[$key];
} elseif ('attributes' == $key) {
return $this->attributes;
Expand Down Expand Up @@ -140,7 +141,7 @@ public function cleanAttribute(string $key)
*/
public function setAttribute(string $key, $value)
{
if ($caster = BaseDateTimeCast::resolve($this->casts[$key] ?? null)) {
if ($caster = CastResolver::resolve($this->casts[$key] ?? null)) {
$value = $caster->set($value);
}

Expand Down
32 changes: 32 additions & 0 deletions tests/Unit/Model/Casts/CastResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Mongolid\Model\Casts;

use Mongolid\Model\Casts\DateTime\DateTimeCast;
use Mongolid\Model\Casts\DateTime\DateTimeImmutableCast;
use Mongolid\Model\Casts\Exceptions\InvalidCastException;
use Mongolid\TestCase;

class CastResolverTest extends TestCase
{
public function testShouldResolveCast(): void
{
// Actions
$dateTimeCast = CastResolver::resolve('datetime');
$dateTimeImmutableCast = CastResolver::resolve('immutable_datetime');

// Assertions
$this->assertInstanceOf(DateTimeCast::class, $dateTimeCast);
$this->assertInstanceOf(DateTimeImmutableCast::class, $dateTimeImmutableCast);
}

public function testShouldThrowExceptionWhenGivenInvalidCastToBeResolved(): void
{
// Expectations
$this->expectException(InvalidCastException::class);
$this->expectExceptionMessage('Invalid cast attribute: invalid. Use a valid one like datetime,immutable_datetime');

// Actions
CastResolver::resolve('invalid');
}
}
13 changes: 0 additions & 13 deletions tests/Unit/Model/Casts/DateTime/BaseDateTimeCastTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,4 @@ public function testShouldSet(): void
$this->assertInstanceOf(UTCDateTime::class, $restored_at);
$this->assertNull($nulled_at);
}

public function testShouldResolve(): void
{
// Actions
$dateTimeCast = BaseDateTimeCast::resolve('datetime');
$dateTimeImmutableCast = BaseDateTimeCast::resolve('immutable_datetime');
$invalidCast = BaseDateTimeCast::resolve('invalid');

// Assertions
$this->assertInstanceOf(DateTimeCast::class, $dateTimeCast);
$this->assertInstanceOf(DateTimeImmutableCast::class, $dateTimeImmutableCast);
$this->assertNull($invalidCast);
}
}

0 comments on commit 5332992

Please sign in to comment.