|
|
@ -4,6 +4,10 @@ namespace Rinsvent\Data2DTO; |
|
|
|
|
|
|
|
|
|
|
|
use Rinsvent\AttributeExtractor\PropertyExtractor; |
|
|
|
use Rinsvent\AttributeExtractor\PropertyExtractor; |
|
|
|
use Rinsvent\Data2DTO\Attribute\PropertyPath; |
|
|
|
use Rinsvent\Data2DTO\Attribute\PropertyPath; |
|
|
|
|
|
|
|
use Rinsvent\Data2DTO\Resolver\TransformerResolverStorage; |
|
|
|
|
|
|
|
use Rinsvent\Data2DTO\Transformer\Meta; |
|
|
|
|
|
|
|
use Rinsvent\Data2DTO\Transformer\TransformerInterface; |
|
|
|
|
|
|
|
use function Symfony\Component\String\u; |
|
|
|
|
|
|
|
|
|
|
|
class Data2DtoConverter |
|
|
|
class Data2DtoConverter |
|
|
|
{ |
|
|
|
{ |
|
|
@ -15,32 +19,78 @@ class Data2DtoConverter |
|
|
|
$properties = $reflectionObject->getProperties(); |
|
|
|
$properties = $reflectionObject->getProperties(); |
|
|
|
/** @var \ReflectionProperty $property */ |
|
|
|
/** @var \ReflectionProperty $property */ |
|
|
|
foreach ($properties as $property) { |
|
|
|
foreach ($properties as $property) { |
|
|
|
$propertyName = $property->getName(); |
|
|
|
|
|
|
|
$propertyExtractor = new PropertyExtractor($object::class, $propertyName); |
|
|
|
|
|
|
|
/** @var PropertyPath $propertyPath */ |
|
|
|
|
|
|
|
if ($propertyPath = $propertyExtractor->fetch(PropertyPath::class)) { |
|
|
|
|
|
|
|
$customPath = $propertyPath->path; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @var \ReflectionNamedType $reflectionPropertyType */ |
|
|
|
/** @var \ReflectionNamedType $reflectionPropertyType */ |
|
|
|
$reflectionPropertyType = $property->getType(); |
|
|
|
$reflectionPropertyType = $property->getType(); |
|
|
|
$propertyType = $reflectionPropertyType->getName(); |
|
|
|
$propertyType = $reflectionPropertyType->getName(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ($dataPath = $this->grabDataPath($property, $data)) { |
|
|
|
|
|
|
|
$value = $data[$dataPath]; |
|
|
|
|
|
|
|
// Трансформируем данные |
|
|
|
|
|
|
|
$this->processTransformers($property, $value); |
|
|
|
|
|
|
|
|
|
|
|
if(key_exists($propertyName, $data)) { |
|
|
|
// Если значение в $data = null, но поле не может его принять - пропустим |
|
|
|
$value = $data[$propertyName]; |
|
|
|
|
|
|
|
if ($value === null && !$reflectionPropertyType->allowsNull()) { |
|
|
|
if ($value === null && !$reflectionPropertyType->allowsNull()) { |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// В данных лежит объект, то дальше его не заполняем. Только присваиваем. Например, entity, document |
|
|
|
|
|
|
|
if (is_object($value)) { |
|
|
|
|
|
|
|
$property->setValue($object, $value); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Если это class, то рекурсивно заполняем дальше |
|
|
|
if (class_exists($propertyType)) { |
|
|
|
if (class_exists($propertyType)) { |
|
|
|
$value = $this->convert($value, $propertyType); |
|
|
|
$value = $this->convert($value, $propertyType); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// присваиваем получившееся значение |
|
|
|
$property->setValue($object, $value); |
|
|
|
$property->setValue($object, $value); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return $object; |
|
|
|
return $object; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected function grabDataPath(\ReflectionProperty $property, array $data): ?string |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$propertyName = $property->getName(); |
|
|
|
|
|
|
|
$propertyExtractor = new PropertyExtractor($property->class, $propertyName); |
|
|
|
|
|
|
|
/** @var PropertyPath $propertyPath */ |
|
|
|
|
|
|
|
if ($propertyPath = $propertyExtractor->fetch(PropertyPath::class)) { |
|
|
|
|
|
|
|
return $propertyPath->path; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (key_exists($propertyName, $data)) { |
|
|
|
|
|
|
|
return $propertyName; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$variants = [ |
|
|
|
|
|
|
|
u($propertyName)->camel()->toString(), |
|
|
|
|
|
|
|
u($propertyName)->snake()->toString(), |
|
|
|
|
|
|
|
u($propertyName)->snake()->upper()->toString(), |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
foreach ($variants as $variant) { |
|
|
|
|
|
|
|
if (key_exists($variant, $data)) { |
|
|
|
|
|
|
|
return $variant; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected function processTransformers(\ReflectionProperty $property, &$data): void |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$propertyName = $property->getName(); |
|
|
|
|
|
|
|
$propertyExtractor = new PropertyExtractor($property->class, $propertyName); |
|
|
|
|
|
|
|
/** @var Meta $transformMeta */ |
|
|
|
|
|
|
|
if ($transformMeta = $propertyExtractor->fetch(Meta::class)) { |
|
|
|
|
|
|
|
$transformer = $this->grabTransformer($transformMeta); |
|
|
|
|
|
|
|
$transformer->transform($data, $transformMeta); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected function grabTransformer(Meta $meta): TransformerInterface |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
$storage = TransformerResolverStorage::getInstance(); |
|
|
|
|
|
|
|
$resolver = $storage->get($meta::TYPE); |
|
|
|
|
|
|
|
return $resolver->resolve($meta); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |