Skip to content

Commit

Permalink
Improve alias usage with dernormalization
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Sep 26, 2024
1 parent a9df61a commit 4d05533
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 38 deletions.
31 changes: 3 additions & 28 deletions src/Serializer/AfterMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
use Attribute;
use ReflectionAttribute;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;

/**
* @deprecated since version 9.17.0
Expand All @@ -27,36 +25,13 @@
#[Attribute(Attribute::TARGET_CLASS)]
final class AfterMapping
{
/** @var array<string> $methods */
public readonly MapRecord $mapRecord;
public readonly array $methods;

public function __construct(string ...$methods)
{
$this->methods = $methods;
}

/**
*
* @return array<ReflectionMethod>
*/
public function afterMappingMethods(ReflectionClass $class): array
{
$methods = [];
foreach ($this->methods as $method) {
try {
$accessor = $class->getMethod($method);
} catch (ReflectionException $exception) {
throw new MappingFailed('The method `'.$method.'` is not defined on the `'.$class->getName().'` class.', 0, $exception);
}

if (0 !== $accessor->getNumberOfRequiredParameters()) {
throw new MappingFailed('The method `'.$class->getName().'::'.$accessor->getName().'` has too many required parameters.');
}

$methods[] = $accessor;
}

return $methods;
$this->mapRecord = new MapRecord($methods);
$this->methods = $this->mapRecord->afterMapping;
}

public static function from(ReflectionClass $class): ?self
Expand Down
49 changes: 41 additions & 8 deletions src/Serializer/CallbackCasting.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,30 @@ public function setOptions(
}

/** @var Closure $callback */
$callback = self::$aliases[$this->type][$this->alias];
$callback = self::resolveAliasCallback($this->type);
$this->callback = $callback;
$this->options = $options;
}

private static function resolveAliasCallback(string $type): Closure
{
foreach (self::aliases() as $alias => $registeredType) {
if ($type === $registeredType) {
return self::$aliases[$registeredType][$alias];
}

try {
$reflType = new ReflectionClass($type); /* @phpstan-ignore-line */
if ($reflType->implementsInterface($registeredType)) {
return self::$aliases[$registeredType][$alias];
}
} catch (Throwable) {
}
}

throw new MappingFailed('The `'.$type.'` could not be resolved.');
}

/**
* @return TValue
*/
Expand Down Expand Up @@ -239,17 +258,32 @@ public static function supports(ReflectionParameter|ReflectionProperty $reflecti

foreach ($propertyTypeList as $propertyType) {
$type = $propertyType->getName();
if (null === $alias) {
if (self::supportsType($type)) {
return true;
}
if (null === $alias && self::supportsType($type)) {
return true;
}

continue;
if (self::isAliasValid($type) || (Type::Mixed->value === $type && self::supportsAlias($alias))) {
return true;
}
}

return false;
}

if ((self::aliases()[$alias] ?? null) === $type || (Type::Mixed->value === $type && self::supportsAlias($alias))) {
private static function isAliasValid(string $type): bool
{
foreach (self::aliases() as $alias => $registeredType) {
if ($type === $registeredType) {
return true;
}

try {
$reflType = new ReflectionClass($type); /* @phpstan-ignore-line */
if ($reflType->implementsInterface($registeredType)) {
return true;
}
} catch (Throwable) {
}
}

return false;
Expand Down Expand Up @@ -277,7 +311,6 @@ private static function resolveSupportedType(string $type): Closure
throw new MappingFailed('The `'.$type.'` could not be resolved.');
}


/**
* @throws MappingFailed
*
Expand Down
2 changes: 1 addition & 1 deletion src/Serializer/Denormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ private function setPropertySetters(array $propertyNames): array
private function setAfterMappingCalls(): array
{
return $this->mapRecord?->afterMappingMethods($this->class)
?? AfterMapping::from($this->class)?->afterMappingMethods($this->class) /* @phpstan-ignore-line */
?? AfterMapping::from($this->class)?->mapRecord->afterMappingMethods($this->class) /* @phpstan-ignore-line */
?? [];
}

Expand Down
11 changes: 10 additions & 1 deletion src/Serializer/DenormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@

final class DenormalizerTest extends TestCase
{
protected function setUp(): void
{
Denormalizer::unregisterAll();
}

protected function tearDown(): void
{
Denormalizer::unregisterAll();
}

public function testItConvertsAnIterableListOfRecords(): void
{
$records = [
Expand Down Expand Up @@ -601,7 +611,6 @@ public function __construct(
};

$instance = Denormalizer::assign($class::class, ['place' => 'YaMouSSokro']);

self::assertInstanceOf($class::class, $instance);
self::assertSame('yamoussokro', $instance->str);
}
Expand Down

0 comments on commit 4d05533

Please sign in to comment.