Skip to content

Commit

Permalink
patch
Browse files Browse the repository at this point in the history
  • Loading branch information
AnourValar committed Aug 23, 2023
1 parent 754f570 commit b683a09
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 21 deletions.
55 changes: 34 additions & 21 deletions src/Mapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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']);
}
}

Expand All @@ -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)));
}

/**
Expand Down Expand Up @@ -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 = [];

Expand All @@ -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;
}
Expand All @@ -165,32 +167,33 @@ 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 = [];

$attributes = $class->getAttributes();
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) {
Expand All @@ -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 [];
}
}
14 changes: 14 additions & 0 deletions src/Mapper/DefaultValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace AnourValar\LaravelAtom\Mapper;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
class DefaultValue
{
public function __construct(public $value)
{

}
}
5 changes: 5 additions & 0 deletions tests/MapperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,10 @@ public function test_mode()
['user_id' => 1, 'manager_id' => 2],
$mapper->toArray()
);

$this->assertSame(
['user_id' => 1, 'manager_id' => 3],
ModeMapper::from(['user_id' => '1'])->toArray()
);
}
}
2 changes: 2 additions & 0 deletions tests/Mappers/ModeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
) {

Expand Down

0 comments on commit b683a09

Please sign in to comment.