Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Cast properties with self or parent type
Browse files Browse the repository at this point in the history
  • Loading branch information
sebdesign committed Sep 6, 2021
1 parent 34289b1 commit 433a0fd
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/Reflection/DataTransferObjectProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use ReflectionClass;
use ReflectionNamedType;
use ReflectionProperty;
use ReflectionType;
use ReflectionUnionType;
use Spatie\DataTransferObject\Attributes\CastWith;
use Spatie\DataTransferObject\Attributes\DefaultCast;
Expand Down Expand Up @@ -84,19 +85,21 @@ private function resolveCaster(): ?Caster
$attribute = $attributes[0]->newInstance();

return new $attribute->casterClass(
array_map(fn ($type) => $type->getName(), $this->extractTypes()),
array_map(fn ($type) => $this->resolveTypeName($type), $this->extractTypes()),
...$attribute->args
);
}

private function resolveCasterFromType(): array
{
foreach ($this->extractTypes() as $type) {
if (! class_exists($type->getName())) {
$name = $this->resolveTypeName($type);

if (! class_exists($name)) {
continue;
}

$reflectionClass = new ReflectionClass($type->getName());
$reflectionClass = new ReflectionClass($name);

do {
$attributes = $reflectionClass->getAttributes(CastWith::class);
Expand Down Expand Up @@ -167,4 +170,13 @@ private function extractTypes(): array
ReflectionUnionType::class => $type->getTypes(),
};
}

private function resolveTypeName(ReflectionType $type): string
{
return match ($type->getName()) {
'self' => $this->dataTransferObject::class,
'parent' => get_parent_class($this->dataTransferObject),
default => $type->getName(),
};
}
}
32 changes: 32 additions & 0 deletions tests/DataTransferObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use Spatie\DataTransferObject\Tests\Dummy\ComplexDto;
use Spatie\DataTransferObject\Tests\Dummy\ComplexDtoWithCastedAttributeHavingCast;
use Spatie\DataTransferObject\Tests\Dummy\ComplexDtoWithNullableProperty;
use Spatie\DataTransferObject\Tests\Dummy\ComplexDtoWithParent;
use Spatie\DataTransferObject\Tests\Dummy\ComplexDtoWithSelf;
use Spatie\DataTransferObject\Tests\Dummy\ComplexStrictDto;
use Spatie\DataTransferObject\Tests\Dummy\WithDefaultValueDto;

Expand Down Expand Up @@ -208,4 +210,34 @@ public function test_clone()
$this->assertEquals('a', $clone->name);
$this->assertEquals('a', $clone->other->name);
}

/** @test */
public function create_with_nested_self()
{
$dto = new ComplexDtoWithSelf([
'name' => 'a',
'other' => [
'name' => 'b',
],
]);

$this->assertEquals('a', $dto->name);
$this->assertEquals('b', $dto->other->name);
$this->assertNull($dto->other->other);
}

/** @test */
public function create_with_nested_parent()
{
$dto = new ComplexDtoWithParent([
'name' => 'a',
'other' => [
'name' => 'b',
],
]);

$this->assertEquals('a', $dto->name);
$this->assertEquals('b', $dto->other->name);
$this->assertNull($dto->other->other);
}
}
10 changes: 10 additions & 0 deletions tests/Dummy/ComplexDtoWithParent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Spatie\DataTransferObject\Tests\Dummy;

class ComplexDtoWithParent extends ComplexDtoWithSelf
{
public string $name;

public ?parent $other;
}
12 changes: 12 additions & 0 deletions tests/Dummy/ComplexDtoWithSelf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Spatie\DataTransferObject\Tests\Dummy;

use Spatie\DataTransferObject\DataTransferObject;

class ComplexDtoWithSelf extends DataTransferObject
{
public string $name;

public ?self $other;
}

0 comments on commit 433a0fd

Please sign in to comment.