diff --git a/src/Attribute/PropertyPath.php b/src/Attribute/PropertyPath.php new file mode 100644 index 0000000..78b6019 --- /dev/null +++ b/src/Attribute/PropertyPath.php @@ -0,0 +1,13 @@ +grabValue($object, $sourceName); + $value = $this->grabValue($object, $sourceName, $tags); // Если нет карты, то не сериализуем. if (is_object($value) && is_array($propertyInfo)) { @@ -84,13 +85,22 @@ class Dto2DataConverter return $tempValue; } - protected function grabValue(object $object, $sourceName) + protected function grabValue(object $object, $sourceName, array $tags) { if (method_exists($object, $sourceName)) { $reflectionSource = new ReflectionMethod($object, $sourceName); return $this->getMethodValue($object, $reflectionSource); } elseif (property_exists($object, $sourceName)) { $reflectionSource = new ReflectionProperty($object, $sourceName); + $propertyExtractor = new PropertyExtractor($object::class, $sourceName); + /** @var PropertyPath $propertyPath */ + while ($propertyPath = $propertyExtractor->fetch(PropertyPath::class)) { + $filteredTags = array_diff($tags, $propertyPath->tags); + if (count($filteredTags) === count($tags)) { + continue; + } + return $this->getValueByPath($object, $propertyPath->path); + } return $this->getValue($object, $reflectionSource); } @@ -214,6 +224,41 @@ class Dto2DataConverter return $resolver->resolve($meta); } + private function getValueByPath($data, string $path) + { + $parts = explode('.', $path); + $length = count($parts); + $i = 1; + foreach ($parts as $part) { + // Если получили скалярное значение но прошли не весь путь, то вернем null + if (is_scalar($data) && $i < $length) { + return null; + } + // Если объекс реализует ArrayAccess, то получаем значение и идем дальше + if (is_object($data) && $data instanceof \ArrayAccess) { + $data = $data[$part] ?? null; + continue; + } + // Если объект, то достаем значение + if (is_object($data)) { + if (!property_exists($data, $part)) { + return null; + } + $property = new ReflectionProperty($data, $part); + $data = $this->getValue($data, $property); + continue; + } + // Если массив, то достаем занчение и идем дальше + if (is_array($data)) { + $data = $data[$part] ?? null; + continue; + } + $i++; + } + + return $data; + } + private function getValue(object $object, \ReflectionProperty $property) { if (!$property->isPublic()) { diff --git a/tests/unit/Converter/FillTest.php b/tests/unit/Converter/FillTest.php index 2ec7964..0900a39 100644 --- a/tests/unit/Converter/FillTest.php +++ b/tests/unit/Converter/FillTest.php @@ -7,6 +7,7 @@ use Rinsvent\DTO2Data\Tests\unit\Converter\fixtures\FillTest\Author; use Rinsvent\DTO2Data\Tests\unit\Converter\fixtures\FillTest\Bar; use Rinsvent\DTO2Data\Tests\unit\Converter\fixtures\FillTest\BuyRequest; use Rinsvent\DTO2Data\Tests\unit\Converter\fixtures\FillTest\HelloRequest; +use Rinsvent\DTO2Data\Tests\unit\Converter\fixtures\FillTest\UUID; class FillTest extends \Codeception\Test\Unit { @@ -67,6 +68,7 @@ class FillTest extends \Codeception\Test\Unit $bar = new Bar(); $bar->barField = 32; $helloRequest->bar = $bar; + $helloRequest->uuid = new UUID('qwerqw-qwerqwe-werqw-qwerqw'); $dto = $dto2DataConverter->convert($helloRequest); // codecept_debug(json_encode($dto)); @@ -103,7 +105,8 @@ class FillTest extends \Codeception\Test\Unit ], "bar" => [ "barField" => 32 - ] + ], + 'uuid' => 'qwerqw-qwerqwe-werqw-qwerqw' ], $dto); } } diff --git a/tests/unit/Converter/fixtures/FillTest/HelloRequest.php b/tests/unit/Converter/fixtures/FillTest/HelloRequest.php index bd42c9b..fac8df5 100644 --- a/tests/unit/Converter/fixtures/FillTest/HelloRequest.php +++ b/tests/unit/Converter/fixtures/FillTest/HelloRequest.php @@ -3,6 +3,7 @@ namespace Rinsvent\DTO2Data\Tests\unit\Converter\fixtures\FillTest; use Rinsvent\DTO2Data\Attribute\DataPath; +use Rinsvent\DTO2Data\Attribute\PropertyPath; use Rinsvent\DTO2Data\Transformer\Trim; #[HelloSchema] @@ -18,4 +19,6 @@ class HelloRequest public array $authors3; public BuyRequest $buy; public BarInterface $bar; + #[PropertyPath(path: 'uuid.id')] + public UUID $uuid; } diff --git a/tests/unit/Converter/fixtures/FillTest/HelloSchema.php b/tests/unit/Converter/fixtures/FillTest/HelloSchema.php index d21b5c9..9162f63 100644 --- a/tests/unit/Converter/fixtures/FillTest/HelloSchema.php +++ b/tests/unit/Converter/fixtures/FillTest/HelloSchema.php @@ -25,6 +25,7 @@ class HelloSchema extends Schema ], 'bar' => [ 'barField' - ] + ], + 'uuid' ]; } diff --git a/tests/unit/Converter/fixtures/FillTest/UUID.php b/tests/unit/Converter/fixtures/FillTest/UUID.php new file mode 100644 index 0000000..cac0f47 --- /dev/null +++ b/tests/unit/Converter/fixtures/FillTest/UUID.php @@ -0,0 +1,14 @@ +id = $id; + } +}