Рефакторинг

This commit is contained in:
Rinsvent 2021-08-16 22:56:23 +07:00
parent f27e92544f
commit 44ef3f1143

View File

@ -2,6 +2,7 @@
namespace Rinsvent\Data2DTO; namespace Rinsvent\Data2DTO;
use ReflectionProperty;
use Rinsvent\AttributeExtractor\ClassExtractor; use Rinsvent\AttributeExtractor\ClassExtractor;
use Rinsvent\AttributeExtractor\PropertyExtractor; use Rinsvent\AttributeExtractor\PropertyExtractor;
use Rinsvent\Data2DTO\Attribute\DTOMeta; use Rinsvent\Data2DTO\Attribute\DTOMeta;
@ -19,7 +20,6 @@ class Data2DtoConverter
$tags = empty($tags) ? ['default'] : $tags; $tags = empty($tags) ? ['default'] : $tags;
$reflectionObject = new \ReflectionObject($object); $reflectionObject = new \ReflectionObject($object);
// Трнансформируем на уровне класса
$this->processClassTransformers($reflectionObject, $data, $tags); $this->processClassTransformers($reflectionObject, $data, $tags);
if (is_object($data)) { if (is_object($data)) {
return $data; return $data;
@ -32,66 +32,34 @@ class Data2DtoConverter
$reflectionPropertyType = $property->getType(); $reflectionPropertyType = $property->getType();
$propertyType = $reflectionPropertyType->getName(); $propertyType = $reflectionPropertyType->getName();
// Для виртуальных полей добавляем пустой масиив, чтобы заполнить поля дто if ($this->processVirtualProperty($object, $property, $data, $tags)) {
$propertyExtractor = new PropertyExtractor($property->class, $property->getName());
if ($propertyExtractor->fetch(VirtualProperty::class)) {
if ($property->isInitialized($object)) {
$propertyValue = $property->getValue($object);
$value = $this->convert($data, $propertyValue, $tags);
} else {
$value = $this->convert($data, new $propertyType, $tags);
}
// присваиваем получившееся значение
$property->setValue($object, $value);
continue; continue;
} }
if ($dataPath = $this->grabDataPath($property, $data, $tags)) { if ($dataPath = $this->grabDataPath($property, $data, $tags)) {
$value = $data[$dataPath]; $value = $data[$dataPath];
// Трансформируем данные
$this->processTransformers($property, $value, $tags); $this->processTransformers($property, $value, $tags);
// В данных лежит объект, то дальше его не заполняем. Только присваиваем. Например, entity, document if ($this->processDataObject($object, $property, $value)) {
if (is_object($value)) {
$property->setValue($object, $value);
continue; continue;
} }
if (!$this->transformArray($value, $property, $tags)) { if ($this->processArray($value, $property, $tags)) {
continue; continue;
} }
$preparedPropertyType = $propertyType; $preparedPropertyType = $propertyType;
if ($this->processInterface($property, $preparedPropertyType)) {
if (interface_exists($preparedPropertyType)) { continue;
$attributedPropertyClass = $this->grabPropertyDTOClass($property); }
// Если не указали мета информацию для интерфейса - пропустим
if (!$attributedPropertyClass) { $this->processClass($object, $property, $preparedPropertyType, $value, $tags);
continue;
} if ($this->processNull($value, $reflectionPropertyType)) {
// Если класс не реализует интерфейс свойства - пропустим
$interfaces = class_implements($attributedPropertyClass);
if (!isset($interfaces[$preparedPropertyType])) {
continue;
}
$preparedPropertyType = $attributedPropertyClass;
}
// Если это class, то рекурсивно заполняем дальше
if (class_exists($preparedPropertyType)) {
if ($property->isInitialized($object)) {
$propertyValue = $property->getValue($object);
$value = $this->convert($value, new $preparedPropertyType, $tags, $propertyValue);
} else {
$value = $this->convert($value, new $preparedPropertyType, $tags);
}
}
if ($this->checkNullRule($value, $reflectionPropertyType)) {
continue; continue;
} }
// присваиваем получившееся значение
$property->setValue($object, $value); $property->setValue($object, $value);
} }
} }
@ -99,6 +67,72 @@ class Data2DtoConverter
return $object; return $object;
} }
/**
* Для виртуальных полей добавляем пустой масиив, чтобы заполнить поля дто
*/
protected function processVirtualProperty(object $object, \ReflectionProperty $property, array $data, array $tags): bool
{
$propertyExtractor = new PropertyExtractor($property->class, $property->getName());
if ($propertyExtractor->fetch(VirtualProperty::class)) {
if ($property->isInitialized($object)) {
$propertyValue = $property->getValue($object);
$value = $this->convert($data, $propertyValue, $tags);
} else {
$propertyType = $property->getType()->getName();
$value = $this->convert($data, new $propertyType, $tags);
}
// присваиваем получившееся значение
$property->setValue($object, $value);
return true;
}
return false;
}
/**
* В данных лежит объект, то дальше его не заполняем. Только присваиваем. Например, entity, document
*/
protected function processDataObject(object $object, \ReflectionProperty $property, $value): bool
{
if (is_object($value)) {
$property->setValue($object, $value);
return true;
}
return false;
}
protected function processInterface(ReflectionProperty $property, &$preparedPropertyType): bool
{
if (interface_exists($preparedPropertyType)) {
$attributedPropertyClass = $this->grabPropertyDTOClass($property);
// Если не указали мета информацию для интерфейса - пропустим
if (!$attributedPropertyClass) {
return true;
}
// Если класс не реализует интерфейс свойства - пропустим
$interfaces = class_implements($attributedPropertyClass);
if (!isset($interfaces[$preparedPropertyType])) {
return true;
}
$preparedPropertyType = $attributedPropertyClass;
}
return false;
}
/**
* Если это class, то рекурсивно заполняем дальше
*/
protected function processClass(object $object, ReflectionProperty $property, string $preparedPropertyType, &$value, array $tags)
{
if (class_exists($preparedPropertyType)) {
if ($property->isInitialized($object)) {
$propertyValue = $property->getValue($object);
$value = $this->convert($value, $propertyValue, $tags);
} else {
$value = $this->convert($value, new $preparedPropertyType, $tags);
}
}
}
protected function grabDataPath(\ReflectionProperty $property, array $data, array $tags): ?string protected function grabDataPath(\ReflectionProperty $property, array $data, array $tags): ?string
{ {
$propertyName = $property->getName(); $propertyName = $property->getName();
@ -131,6 +165,9 @@ class Data2DtoConverter
return null; return null;
} }
/**
* Трнансформируем на уровне класса
*/
protected function processClassTransformers(\ReflectionObject $object, &$data, array $tags): void protected function processClassTransformers(\ReflectionObject $object, &$data, array $tags): void
{ {
$className = $object->getName(); $className = $object->getName();
@ -148,6 +185,9 @@ class Data2DtoConverter
} }
} }
/**
* Трнансформируем на уровне свойст объекта
*/
protected function processTransformers(\ReflectionProperty $property, &$data, array $tags): void protected function processTransformers(\ReflectionProperty $property, &$data, array $tags): void
{ {
$propertyName = $property->getName(); $propertyName = $property->getName();
@ -178,12 +218,12 @@ class Data2DtoConverter
/** /**
* Если значение в $data = null, но поле не может его принять - пропустим * Если значение в $data = null, но поле не может его принять - пропустим
*/ */
private function checkNullRule($value, \ReflectionNamedType $reflectionPropertyType): bool private function processNull($value, \ReflectionNamedType $reflectionPropertyType): bool
{ {
return $value === null && !$reflectionPropertyType->allowsNull(); return $value === null && !$reflectionPropertyType->allowsNull();
} }
private function transformArray(&$value, \ReflectionProperty $property, array $tags): bool private function processArray(&$value, \ReflectionProperty $property, array $tags): bool
{ {
$attributedPropertyClass = $this->grabPropertyDTOClass($property); $attributedPropertyClass = $this->grabPropertyDTOClass($property);
@ -195,7 +235,7 @@ class Data2DtoConverter
if ($propertyType === 'array' && $attributedPropertyClass) { if ($propertyType === 'array' && $attributedPropertyClass) {
// Если тип у ДТО - массив, а в значении не массив - пропустим // Если тип у ДТО - массив, а в значении не массив - пропустим
if (!is_array($value)) { if (!is_array($value)) {
return false; return true;
} }
$tempValue = []; $tempValue = [];
foreach ($value as $itemValue) { foreach ($value as $itemValue) {
@ -203,18 +243,17 @@ class Data2DtoConverter
} }
$value = $tempValue; $value = $tempValue;
} }
return true; return false;
} }
private function grabPropertyDTOClass(\ReflectionProperty $property): ?string private function grabPropertyDTOClass(\ReflectionProperty $property): ?string
{ {
$attributedPropertyClass = null;
$propertyName = $property->getName(); $propertyName = $property->getName();
$propertyExtractor = new PropertyExtractor($property->class, $propertyName); $propertyExtractor = new PropertyExtractor($property->class, $propertyName);
/** @var DTOMeta $dtoMeta */ /** @var DTOMeta $dtoMeta */
if ($dtoMeta = $propertyExtractor->fetch(DTOMeta::class)) { if ($dtoMeta = $propertyExtractor->fetch(DTOMeta::class)) {
$attributedPropertyClass = $dtoMeta->class; return $dtoMeta->class;
} }
return $attributedPropertyClass; return null;
} }
} }