diff --git a/composer.json b/composer.json index cdbde74..7c56dca 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "rinsvent/data2dto", "description": "Convert data to dto object", - "license": "proprietary", + "license": "MIT", "require": { "php": "^8.0", "ext-ctype": "*", diff --git a/src/Data2DtoConverter.php b/src/Data2DtoConverter.php index bce5336..a063a7c 100644 --- a/src/Data2DtoConverter.php +++ b/src/Data2DtoConverter.php @@ -2,6 +2,7 @@ namespace Rinsvent\Data2DTO; +use Rinsvent\AttributeExtractor\ClassExtractor; use Rinsvent\AttributeExtractor\PropertyExtractor; use Rinsvent\Data2DTO\Attribute\DTOMeta; use Rinsvent\Data2DTO\Attribute\PropertyPath; @@ -12,11 +13,16 @@ use function Symfony\Component\String\u; class Data2DtoConverter { - public function convert(array $data, string $class): object + public function convert(array $data, string $class, array $tags = [], ?object $instance = null): object { - $object = new $class; - + $tags = empty($tags) ? ['default'] : $tags; + $object = $instance ?? new $class; $reflectionObject = new \ReflectionObject($object); + $this->processClassTransformers($reflectionObject, $data, $tags); + if (is_object($data)) { + return $data; + } + $properties = $reflectionObject->getProperties(); /** @var \ReflectionProperty $property */ foreach ($properties as $property) { @@ -27,7 +33,7 @@ class Data2DtoConverter if ($dataPath = $this->grabDataPath($property, $data)) { $value = $data[$dataPath]; // Трансформируем данные - $this->processTransformers($property, $value); + $this->processTransformers($property, $value, $tags); if ($this->checkNullRule($value, $reflectionPropertyType)) { continue; @@ -98,12 +104,38 @@ class Data2DtoConverter return null; } - protected function processTransformers(\ReflectionProperty $property, &$data): void + protected function processClassTransformers(\ReflectionObject $object, &$data, array $tags): void + { + $className = $object->getName(); + $classExtractor = new ClassExtractor($className); + /** @var Meta $transformMeta */ + while ($transformMeta = $classExtractor->fetch(Meta::class)) { + $transformMeta->returnType = $className; + $filteredTags = array_diff($tags, $transformMeta->tags); + if (count($filteredTags) === count($tags)) { + continue; + } + + $transformer = $this->grabTransformer($transformMeta); + $transformer->transform($data, $transformMeta); + } + } + + protected function processTransformers(\ReflectionProperty $property, &$data, array $tags): void { $propertyName = $property->getName(); $propertyExtractor = new PropertyExtractor($property->class, $propertyName); /** @var Meta $transformMeta */ - if ($transformMeta = $propertyExtractor->fetch(Meta::class)) { + while ($transformMeta = $propertyExtractor->fetch(Meta::class)) { + $filteredTags = array_diff($tags, $transformMeta->tags); + if (count($filteredTags) === count($tags)) { + continue; + } + /** @var \ReflectionNamedType $reflectionPropertyType */ + $reflectionPropertyType = $property->getType(); + $propertyType = $reflectionPropertyType->getName(); + $transformMeta->returnType = $propertyType; + $transformMeta->allowsNull = $reflectionPropertyType->allowsNull(); $transformer = $this->grabTransformer($transformMeta); $transformer->transform($data, $transformMeta); } diff --git a/src/Transformer/Meta.php b/src/Transformer/Meta.php index 73e88dd..c0ac356 100644 --- a/src/Transformer/Meta.php +++ b/src/Transformer/Meta.php @@ -6,4 +6,8 @@ namespace Rinsvent\Data2DTO\Transformer; abstract class Meta { public const TYPE = 'simple'; + public ?string $returnType = null; + public ?bool $allowsNull = null; + /** @var string[] $tags */ + public array $tags = ['default']; } \ No newline at end of file