Добавил PropertyPath
This commit is contained in:
parent
5498eeb420
commit
697ec830e3
13
src/Attribute/PropertyPath.php
Normal file
13
src/Attribute/PropertyPath.php
Normal file
@ -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'
|
||||
];
|
||||
}
|
||||
|
14
tests/unit/Converter/fixtures/FillTest/UUID.php
Normal file
14
tests/unit/Converter/fixtures/FillTest/UUID.php
Normal file
@ -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…
Reference in New Issue
Block a user