Skip to content

Commit

Permalink
Check format in serializer (#96)
Browse files Browse the repository at this point in the history
  • Loading branch information
liquetsoft authored Sep 30, 2024
1 parent 2f63322 commit 77de2c1
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 33 deletions.
6 changes: 4 additions & 2 deletions generator/SerializerGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Illuminate\Database\Eloquent\Model;
use Liquetsoft\Fias\Component\EntityDescriptor\EntityDescriptor;
use Liquetsoft\Fias\Component\Serializer\FiasSerializerFormat;
use Nette\PhpGenerator\ClassType;
use Nette\PhpGenerator\Literal;
use Nette\PhpGenerator\Method;
Expand Down Expand Up @@ -50,6 +51,7 @@ protected function decorateNamespace(PhpNamespace $namespace): void
$namespace->addUse(AbstractNormalizer::class);
$namespace->addUse(Model::class);
$namespace->addUse(InvalidArgumentException::class);
$namespace->addUse(FiasSerializerFormat::class);

$descriptors = $this->registry->getDescriptors();
foreach ($descriptors as $descriptor) {
Expand Down Expand Up @@ -102,7 +104,7 @@ protected function decorateClass(ClassType $class): void
->addComment("{@inheritDoc}\n")
->setVisibility('public')
->setReturnType('bool')
->setBody('return \\array_key_exists(trim($type, " \t\n\r\0\x0B\\\\/"), self::ALLOWED_ENTITIES);');
->setBody('return FiasSerializerFormat::XML->isEqual($format) && \\array_key_exists(trim($type, " \t\n\r\0\x0B\\\\/"), self::ALLOWED_ENTITIES);');
$supports->addParameter('data');
$supports->addParameter('type')->setType('string');
$supports->addParameter('format', new Literal('null'))->setType('string');
Expand All @@ -123,7 +125,7 @@ protected function decorateClass(ClassType $class): void
->addComment("{@inheritDoc}\n")
->setVisibility('public')
->setReturnType('array')
->setBody('return self::ALLOWED_ENTITIES;');
->setBody('return FiasSerializerFormat::XML->isEqual($format) ? self::ALLOWED_ENTITIES : [];');
$getSupportedTypes->addParameter('format')->setType('string')->setNullable(true);

$convertDataToInternalFormatBody = <<<EOT
Expand Down
5 changes: 3 additions & 2 deletions src/Serializer/CompiledEntitesDenormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Serializer;

use Illuminate\Database\Eloquent\Model;
use Liquetsoft\Fias\Component\Serializer\FiasSerializerFormat;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Entity\AddrObj;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Entity\AddrObjDivision;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Entity\AddrObjTypes;
Expand Down Expand Up @@ -68,7 +69,7 @@ final class CompiledEntitesDenormalizer implements DenormalizerInterface
*/
public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []): bool
{
return \array_key_exists(trim($type, " \t\n\r\0\x0B\\/"), self::ALLOWED_ENTITIES);
return FiasSerializerFormat::XML->isEqual($format) && \array_key_exists(trim($type, " \t\n\r\0\x0B\\/"), self::ALLOWED_ENTITIES);
}

/**
Expand Down Expand Up @@ -172,7 +173,7 @@ public function denormalize($data, string $type, ?string $format = null, array $
*/
public function getSupportedTypes(?string $format): array
{
return self::ALLOWED_ENTITIES;
return FiasSerializerFormat::XML->isEqual($format) ? self::ALLOWED_ENTITIES : [];
}

private function convertDataToInternalFormat(mixed $data): array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Serializer;

use Illuminate\Database\Eloquent\Model;
use Liquetsoft\Fias\Component\Serializer\FiasSerializerFormat;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Serializer\TypeCaster\EloquentTypeCaster;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Serializer\TypeCaster\TypeCaster;
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
Expand All @@ -14,7 +15,7 @@
/**
* Нормализатор для объектов eloquent.
*/
final class EloquentDenormalizer implements DenormalizerInterface
final class FiasEloquentDenormalizer implements DenormalizerInterface
{
private readonly TypeCaster $typeCaster;

Expand All @@ -28,7 +29,8 @@ public function __construct(?TypeCaster $typeCaster = null)
*/
public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []): bool
{
return is_subclass_of($type, Model::class);
return FiasSerializerFormat::XML->isEqual($format)
&& is_subclass_of($type, Model::class);
}

/**
Expand Down Expand Up @@ -67,6 +69,10 @@ public function denormalize($data, string $type, ?string $format = null, array $
*/
public function getSupportedTypes(?string $format): array
{
if (!FiasSerializerFormat::XML->isEqual($format)) {
return [];
}

return [
Model::class => true,
];
Expand Down
2 changes: 1 addition & 1 deletion src/Serializer/FiasSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function __construct(?array $normalizers = null, ?array $encoders = null)
if ($normalizers === null) {
$normalizers = [
new CompiledEntitesDenormalizer(),
new EloquentDenormalizer(),
new FiasEloquentDenormalizer(),
new DateTimeNormalizer(),
new ObjectNormalizer(
nameConverter: new FiasNameConverter(),
Expand Down
46 changes: 38 additions & 8 deletions tests/Serializer/CompiledEntitesDenormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Tests\Serializer;

use Liquetsoft\Fias\Component\Serializer\FiasSerializerFormat;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Entity\AddrObj;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Serializer\CompiledEntitesDenormalizer;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Tests\BaseCase;
Expand All @@ -19,23 +20,30 @@ final class CompiledEntitesDenormalizerTest extends BaseCase
*
* @dataProvider provideSupportsDenormalization
*/
public function testSupportsDenormalization(string $type, bool $expected): void
public function testSupportsDenormalization(string $type, string $format, bool $expected): void
{
$denormalizer = new CompiledEntitesDenormalizer();
$res = $denormalizer->supportsDenormalization([], $type);
$res = $denormalizer->supportsDenormalization([], $type, $format);

$this->assertSame($expected, $res);
}

public static function provideSupportsDenormalization(): array
{
return [
'supported type' => [
'supported type and format' => [
AddrObj::class,
FiasSerializerFormat::XML->value,
true,
],
'unsupported type' => [
'test',
FiasSerializerFormat::XML->value,
false,
],
'unsupported format' => [
AddrObj::class,
'json',
false,
],
];
Expand All @@ -54,7 +62,7 @@ public function testDenormalize(): void
];

$denormalizer = new CompiledEntitesDenormalizer();
$res = $denormalizer->denormalize($data, AddrObj::class);
$res = $denormalizer->denormalize($data, AddrObj::class, FiasSerializerFormat::XML->value);

$this->assertInstanceOf(AddrObj::class, $res);
$this->assertSame((int) $data['@ID'], $res->getAttribute('id'));
Expand All @@ -76,7 +84,7 @@ public function testDenormalizeModelNames(): void
];

$denormalizer = new CompiledEntitesDenormalizer();
$res = $denormalizer->denormalize($data, AddrObj::class);
$res = $denormalizer->denormalize($data, AddrObj::class, FiasSerializerFormat::XML->value);

$this->assertInstanceOf(AddrObj::class, $res);
$this->assertSame((int) $data['id'], $res->getAttribute('id'));
Expand All @@ -102,6 +110,7 @@ public function testDenormalizeWithObjectToPopulate(): void
$res = $denormalizer->denormalize(
data: $data,
type: AddrObj::class,
format: FiasSerializerFormat::XML->value,
context: [
'object_to_populate' => $model,
]
Expand Down Expand Up @@ -131,6 +140,7 @@ public function testDenormalizeWithObjectToPopulateException(): void
$denormalizer->denormalize(
data: $data,
type: AddrObj::class,
format: FiasSerializerFormat::XML->value,
context: [
'object_to_populate' => $model,
]
Expand All @@ -139,12 +149,32 @@ public function testDenormalizeWithObjectToPopulateException(): void

/**
* Проверяет, что денормалайзер вернет верный список поддерживаемых объектов.
*
* @dataProvider provideGetSupportedTypes
*/
public function testGetSupportedTypes(): void
public function testGetSupportedTypes(?string $format, array|true $expected): void
{
$denormalizer = new CompiledEntitesDenormalizer();
$res = $denormalizer->getSupportedTypes(null);
$res = $denormalizer->getSupportedTypes($format);

if ($expected === true) {
$this->assertNotEmpty($res);
} else {
$this->assertSame($expected, $res);
}
}

$this->assertNotEmpty($res);
public static function provideGetSupportedTypes(): array
{
return [
'xml format' => [
FiasSerializerFormat::XML->value,
true,
],
'non xml format' => [
'json',
[],
],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
namespace Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Tests\Serializer;

use Illuminate\Database\Eloquent\Model;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Serializer\EloquentDenormalizer;
use Liquetsoft\Fias\Component\Serializer\FiasSerializerFormat;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Serializer\FiasEloquentDenormalizer;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Serializer\TypeCaster\TypeCaster;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Tests\BaseCase;
use Liquetsoft\Fias\Laravel\LiquetsoftFiasBundle\Tests\MockModel\FiasSerializerMock;
Expand All @@ -15,32 +16,39 @@
/**
* @internal
*/
final class EloquentDenormalizerTest extends BaseCase
final class FiasEloquentDenormalizerTest extends BaseCase
{
/**
* Проверяет, что денормалайзер правильно определит, что может преобразовать тип.
*
* @dataProvider provideSupportsDenormalization
*/
public function testSupportsDenormalization(string $type, bool $expected): void
public function testSupportsDenormalization(string $type, string $format, bool $expected): void
{
$caster = $this->mock(TypeCaster::class);

$denormalizer = new EloquentDenormalizer($caster);
$res = $denormalizer->supportsDenormalization([], $type);
$denormalizer = new FiasEloquentDenormalizer($caster);
$res = $denormalizer->supportsDenormalization([], $type, $format);

$this->assertSame($expected, $res);
}

public static function provideSupportsDenormalization(): array
{
return [
'supported type' => [
'supported type and format' => [
FiasSerializerMock::class,
FiasSerializerFormat::XML->value,
true,
],
'unsupported type' => [
'test',
FiasSerializerFormat::XML->value,
false,
],
'unsupported format' => [
FiasSerializerMock::class,
'json',
false,
],
];
Expand All @@ -61,8 +69,8 @@ public function testDenormalize(): void
'wrong_attr' => 'wrong attr value',
];

$denormalizer = new EloquentDenormalizer();
$res = $denormalizer->denormalize($data, FiasSerializerMock::class);
$denormalizer = new FiasEloquentDenormalizer();
$res = $denormalizer->denormalize($data, FiasSerializerMock::class, FiasSerializerFormat::XML->value);

$this->assertInstanceOf(FiasSerializerMock::class, $res);
$this->assertSame((int) $data['actstatid'], $res->getAttribute('ACTSTATID'));
Expand All @@ -88,10 +96,11 @@ public function testDenormalizeWithObjectToPopulate(): void
];
$model = new FiasSerializerMock();

$denormalizer = new EloquentDenormalizer();
$denormalizer = new FiasEloquentDenormalizer();
$res = $denormalizer->denormalize(
data: $data,
type: FiasSerializerMock::class,
format: FiasSerializerFormat::XML->value,
context: [
'object_to_populate' => $model,
]
Expand All @@ -117,12 +126,13 @@ public function testDenormalizeWithObjectToPopulateException(): void
];
$model = new \stdClass();

$denormalizer = new EloquentDenormalizer();
$denormalizer = new FiasEloquentDenormalizer();

$this->expectException(InvalidArgumentException::class);
$denormalizer->denormalize(
data: $data,
type: FiasSerializerMock::class,
format: FiasSerializerFormat::XML->value,
context: [
'object_to_populate' => $model,
]
Expand All @@ -143,25 +153,44 @@ public function testDenormalizeNotNormalizableValueException(): void
->method('canCast')
->willThrowException(new \RuntimeException());

$denormalizer = new EloquentDenormalizer($caster);
$denormalizer = new FiasEloquentDenormalizer($caster);

$this->expectException(NotNormalizableValueException::class);
$denormalizer->denormalize($data, FiasSerializerMock::class);
$denormalizer->denormalize($data, FiasSerializerMock::class, FiasSerializerFormat::XML->value);
}

/**
* Проверяет, что денормалайзер вернет верный список поддерживаемых объектов.
*
* @dataProvider provideGetSupportedTypes
*/
public function testGetSupportedTypes(): void
public function testGetSupportedTypes(?string $format, array $expected): void
{
$expected = [
Model::class => true,
];
$caster = $this->mock(TypeCaster::class);

$denormalizer = new EloquentDenormalizer($caster);
$res = $denormalizer->getSupportedTypes(null);
$denormalizer = new FiasEloquentDenormalizer($caster);
$res = $denormalizer->getSupportedTypes($format);

$this->assertSame($expected, $res);
}

public static function provideGetSupportedTypes(): array
{
return [
'xml format' => [
FiasSerializerFormat::XML->value,
[
Model::class => true,
],
],
'null format' => [
null,
[],
],
'json format' => [
'json',
[],
],
];
}
}

0 comments on commit 77de2c1

Please sign in to comment.