From b683a09880f792d3aee1eb24cae46703ab71ca6a Mon Sep 17 00:00:00 2001 From: Nikolay Novikov Date: Wed, 23 Aug 2023 17:05:19 +0300 Subject: [PATCH] patch --- src/Mapper.php | 55 ++++++++++++++++++++++-------------- src/Mapper/DefaultValue.php | 14 +++++++++ tests/MapperTest.php | 5 ++++ tests/Mappers/ModeMapper.php | 2 ++ 4 files changed, 55 insertions(+), 21 deletions(-) create mode 100644 src/Mapper/DefaultValue.php diff --git a/src/Mapper.php b/src/Mapper.php index 380c0bf..d9dc710 100644 --- a/src/Mapper.php +++ b/src/Mapper.php @@ -27,7 +27,7 @@ public static function from(array|object $data): static } $class = new \ReflectionClass(static::class); - $names = self::getMapping($class); + $rules = self::getRules($class); $args = []; foreach ($class->getConstructor()->getParameters() as $param) { @@ -36,17 +36,19 @@ public static function from(array|object $data): static throw new \RuntimeException('Constructor Property Promotion must be declared for all attributes.'); } - $name = $names[$name]; + $rule = $rules[$name]; if ($param->isDefaultValueAvailable()) { - $value = $data[$name] ?? $param->getDefaultValue(); - } elseif (array_key_exists($name, $data)) { - $value = $data[$name]; + $value = $data[$rule['name']] ?? $param->getDefaultValue(); + } elseif (array_key_exists($rule['name'], $data)) { + $value = $data[$rule['name']]; + } elseif (array_key_exists('default_value', $rule)) { + $value = $rule['default_value']; } else { if (stripos((string) $param->getType(), \AnourValar\LaravelAtom\Mapper\Optional::class) !== false) { $value = new \AnourValar\LaravelAtom\Mapper\Optional(); } else { - throw new \RuntimeException('Required parameter is missing: ' . $name); + throw new \RuntimeException('Required parameter is missing: ' . $rule['name']); } } @@ -68,7 +70,7 @@ public static function from(array|object $data): static */ public function toArray(): array { - return $this->resolveToArray((array) $this, static::getMapping(new \ReflectionClass(static::class))); + return $this->resolveToArray((array) $this, static::getRules(new \ReflectionClass(static::class))); } /** @@ -128,10 +130,10 @@ public function offsetGet($offset): mixed /** * @param array $data - * @param array $mapping + * @param array $rules * @return array */ - protected function resolveToArray(array $data, array $mapping = []): array + protected function resolveToArray(array $data, array $rules = []): array { $result = []; @@ -151,8 +153,8 @@ protected function resolveToArray(array $data, array $mapping = []): array $value = $this->resolveToArray($value); } - if ($mapping) { - $result[$mapping[$key]] = $value; + if ($rules) { + $result[$rules[$key]['name']] = $value; } else { $result[$key] = $value; } @@ -165,7 +167,7 @@ protected function resolveToArray(array $data, array $mapping = []): array * @param \ReflectionClass $class * @return array */ - protected static function getMapping(\ReflectionClass $class): array + protected static function getRules(\ReflectionClass $class): array { $result = []; @@ -173,24 +175,25 @@ protected static function getMapping(\ReflectionClass $class): array foreach ($class->getConstructor()->getParameters() as $param) { $originalName = $param->getName(); - $changedName = $originalName; + $result[$originalName] = ['name' => $originalName]; foreach (array_merge($attributes, $param->getAttributes()) as $attribute) { - $changedName = static::handleAttribute($changedName, $attribute); + $result[$originalName] = array_replace( + $result[$originalName], + static::handleAttribute($result[$originalName], $attribute) + ); } - - $result[$originalName] = $changedName; } return $result; } /** - * @param string $name + * @param array $rule * @param \ReflectionAttribute $attribute * @throws \RuntimeException * @return string */ - protected static function handleAttribute(string $name, \ReflectionAttribute $attribute): string + protected static function handleAttribute(array $rule, \ReflectionAttribute $attribute): array { // Mapping if ($attribute->getName() == \AnourValar\LaravelAtom\Mapper\Mapping::class) { @@ -199,15 +202,25 @@ protected static function handleAttribute(string $name, \ReflectionAttribute $at throw new \RuntimeException('Mapping attribute requires a name.'); } - $name = array_shift($args); + return ['name' => array_shift($args)]; } // MappingSnakeCase if ($attribute->getName() == \AnourValar\LaravelAtom\Mapper\MappingSnakeCase::class) { - $name = str()->snake($name); + return ['name' => str()->snake($rule['name'])]; + } + + // DefaultValue + if ($attribute->getName() == \AnourValar\LaravelAtom\Mapper\DefaultValue::class) { + $args = $attribute->getArguments(); + if (! $args) { + throw new \RuntimeException('DefaultValue attribute requires a value.'); + } + + return ['default_value' => array_shift($args)]; } - return $name; + return []; } } diff --git a/src/Mapper/DefaultValue.php b/src/Mapper/DefaultValue.php new file mode 100644 index 0000000..7a70177 --- /dev/null +++ b/src/Mapper/DefaultValue.php @@ -0,0 +1,14 @@ + 1, 'manager_id' => 2], $mapper->toArray() ); + + $this->assertSame( + ['user_id' => 1, 'manager_id' => 3], + ModeMapper::from(['user_id' => '1'])->toArray() + ); } } diff --git a/tests/Mappers/ModeMapper.php b/tests/Mappers/ModeMapper.php index 6293d38..b435b98 100644 --- a/tests/Mappers/ModeMapper.php +++ b/tests/Mappers/ModeMapper.php @@ -5,12 +5,14 @@ use AnourValar\LaravelAtom\Mapper; use AnourValar\LaravelAtom\Mapper\Mapping; use AnourValar\LaravelAtom\Mapper\MappingSnakeCase; +use AnourValar\LaravelAtom\Mapper\DefaultValue; #[MappingSnakeCase] class ModeMapper extends Mapper { public function __construct( public int $userId, + #[DefaultValue(3)] public int $managerId, ) {