Добавил PropertyPath

master
Rinsvent 3 years ago
parent 5498eeb420
commit 697ec830e3
  1. 13
      src/Attribute/PropertyPath.php
  2. 49
      src/Dto2DataConverter.php
  3. 5
      tests/unit/Converter/FillTest.php
  4. 3
      tests/unit/Converter/fixtures/FillTest/HelloRequest.php
  5. 3
      tests/unit/Converter/fixtures/FillTest/HelloSchema.php
  6. 14
      tests/unit/Converter/fixtures/FillTest/UUID.php

@ -0,0 +1,13 @@
<?php
namespace Rinsvent\DTO2Data\Attribute;
#[\Attribute(\Attribute::TARGET_ALL|\Attribute::IS_REPEATABLE)]
class PropertyPath
{
public function __construct(
public string $path,
/** @var string[] $tags */
public array $tags = ['default']
) {}
}

@ -9,6 +9,7 @@ use Rinsvent\AttributeExtractor\MethodExtractor;
use Rinsvent\AttributeExtractor\PropertyExtractor;
use Rinsvent\DTO2Data\Attribute\DataPath;
use Rinsvent\DTO2Data\Attribute\HandleTags;
use Rinsvent\DTO2Data\Attribute\PropertyPath;
use Rinsvent\DTO2Data\Attribute\Schema;
use Rinsvent\DTO2Data\Resolver\TransformerResolverStorage;
use Rinsvent\DTO2Data\Transformer\Meta;
@ -40,7 +41,7 @@ class Dto2DataConverter
continue;
}
$value = $this->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()) {

@ -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);
}
}

@ -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;
}

@ -25,6 +25,7 @@ class HelloSchema extends Schema
],
'bar' => [
'barField'
]
],
'uuid'
];
}

@ -0,0 +1,14 @@
<?php
namespace Rinsvent\DTO2Data\Tests\unit\Converter\fixtures\FillTest;
class UUID
{
public string $id;
public int $version = 4;
public function __construct(string $id)
{
$this->id = $id;
}
}
Loading…
Cancel
Save