Skip to content

Commit

Permalink
support for JMS Serializer 2
Browse files Browse the repository at this point in the history
  • Loading branch information
VasekPurchart committed Nov 29, 2018
1 parent d49de96 commit d7a7cb2
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 60 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"require": {
"php": "~7.2",
"consistence/consistence": "~1.0",
"jms/serializer": "^1.4.2"
"jms/serializer": "~2.0"
},
"require-dev": {
"consistence/coding-standard": "3.5",
Expand Down
105 changes: 49 additions & 56 deletions src/Enum/EnumSerializerHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
use Consistence\Enum\MultiEnum;
use Consistence\Type\ArrayType\ArrayType;
use Consistence\Type\Type;
use JMS\Serializer\AbstractVisitor;
use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\GraphNavigatorInterface;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\VisitorInterface;
use JMS\Serializer\Visitor\DeserializationVisitorInterface;
use JMS\Serializer\Visitor\SerializationVisitorInterface;
use Traversable;

class EnumSerializerHandler implements \JMS\Serializer\Handler\SubscribingHandlerInterface
Expand All @@ -35,13 +35,13 @@ public static function getSubscribingMethods(): array
$methods = [];
foreach ($formats as $format) {
$methods[] = [
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
'type' => self::TYPE_ENUM,
'format' => $format,
'method' => 'serializeEnum',
];
$methods[] = [
'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
'direction' => GraphNavigatorInterface::DIRECTION_DESERIALIZATION,
'type' => self::TYPE_ENUM,
'format' => $format,
'method' => 'deserializeEnum',
Expand All @@ -52,29 +52,28 @@ public static function getSubscribingMethods(): array
}

/**
* @param \JMS\Serializer\VisitorInterface $visitor
* @param \JMS\Serializer\Visitor\SerializationVisitorInterface $visitor
* @param \Consistence\Enum\Enum $enum
* @param mixed[] $type
* @param \JMS\Serializer\Context $context
* @return mixed
*/
public function serializeEnum(VisitorInterface $visitor, Enum $enum, array $type, Context $context)
public function serializeEnum(SerializationVisitorInterface $visitor, Enum $enum, array $type, Context $context)
{
try {
return $this->serializeEnumValue($visitor, $enum, $type, $context);
return $this->serializeEnumValue($visitor, $enum, $type);
} catch (\Consistence\JmsSerializer\Enum\MappedClassMismatchException $e) {
throw new \Consistence\JmsSerializer\Enum\SerializationInvalidValueException($this->getPropertyPath($context), $e);
}
}

/**
* @param \JMS\Serializer\VisitorInterface $visitor
* @param \JMS\Serializer\Visitor\SerializationVisitorInterface $visitor
* @param \Consistence\Enum\Enum $enum
* @param mixed[] $type
* @param \JMS\Serializer\Context $context
* @return mixed
*/
private function serializeEnumValue(VisitorInterface $visitor, Enum $enum, array $type, Context $context)
private function serializeEnumValue(SerializationVisitorInterface $visitor, Enum $enum, array $type)
{
if ($this->hasEnumClassParameter($type)) {
$mappedEnumClass = $this->getEnumClass($type);
Expand All @@ -98,47 +97,33 @@ private function serializeEnumValue(VisitorInterface $visitor, Enum $enum, array
],
],
];
return $visitor->visitArray(array_values($enum->getEnums()), $arrayValueType, $context);
return $visitor->visitArray(array_values($enum->getEnums()), $arrayValueType);
}
}

return $this->serializationVisitType($visitor, $enum, $type, $context);
return $this->serializationVisitType($visitor, $enum, $type);
}

/**
* @param \JMS\Serializer\VisitorInterface $visitor
* @param \JMS\Serializer\Visitor\SerializationVisitorInterface $visitor
* @param \Consistence\Enum\Enum $enum
* @param mixed[] $typeMetadata
* @param \JMS\Serializer\Context $context
* @return mixed
*/
private function serializationVisitType(VisitorInterface $visitor, Enum $enum, array $typeMetadata, Context $context)
private function serializationVisitType(SerializationVisitorInterface $visitor, Enum $enum, array $typeMetadata)
{
$value = $enum->getValue();
$valueType = EnumValueType::get(Type::getType($value));

return $this->visitType($visitor, $value, $valueType, $typeMetadata, $context);
}

/**
* @param \JMS\Serializer\VisitorInterface $visitor
* @param mixed $data
* @param \Consistence\JmsSerializer\Enum\EnumValueType $dataType
* @param mixed[] $typeMetadata
* @param \JMS\Serializer\Context $context
* @return mixed
*/
private function visitType(VisitorInterface $visitor, $data, EnumValueType $dataType, array $typeMetadata, Context $context)
{
switch (true) {
case $dataType->equalsValue(EnumValueType::INTEGER):
return $visitor->visitInteger($data, $typeMetadata, $context);
case $dataType->equalsValue(EnumValueType::STRING):
return $visitor->visitString($data, $typeMetadata, $context);
case $dataType->equalsValue(EnumValueType::FLOAT):
return $visitor->visitDouble($data, $typeMetadata, $context);
case $dataType->equalsValue(EnumValueType::BOOLEAN):
return $visitor->visitBoolean($data, $typeMetadata, $context);
case $valueType->equalsValue(EnumValueType::INTEGER):
return $visitor->visitInteger($value, $typeMetadata);
case $valueType->equalsValue(EnumValueType::STRING):
return $visitor->visitString($value, $typeMetadata);
case $valueType->equalsValue(EnumValueType::FLOAT):
return $visitor->visitDouble($value, $typeMetadata);
case $valueType->equalsValue(EnumValueType::BOOLEAN):
return $visitor->visitBoolean($value, $typeMetadata);
// @codeCoverageIgnoreStart
// should never happen, other types are not allowed in Enums
default:
Expand All @@ -148,31 +133,30 @@ private function visitType(VisitorInterface $visitor, $data, EnumValueType $data
}

/**
* @param \JMS\Serializer\VisitorInterface $visitor
* @param \JMS\Serializer\Visitor\DeserializationVisitorInterface $visitor
* @param mixed $data
* @param mixed[] $type
* @param \JMS\Serializer\Context $context
* @return \Consistence\Enum\Enum
*/
public function deserializeEnum(VisitorInterface $visitor, $data, array $type, Context $context): Enum
public function deserializeEnum(DeserializationVisitorInterface $visitor, $data, array $type, Context $context): Enum
{
try {
return $this->deserializeEnumValue($visitor, $data, $type, $context);
return $this->deserializeEnumValue($visitor, $data, $type);
} catch (\Consistence\Enum\InvalidEnumValueException $e) {
throw new \Consistence\JmsSerializer\Enum\DeserializationInvalidValueException($this->getFieldPath($visitor, $context), $e);
throw new \Consistence\JmsSerializer\Enum\DeserializationInvalidValueException($this->getFieldPath($context), $e);
} catch (\Consistence\JmsSerializer\Enum\NotIterableValueException $e) {
throw new \Consistence\JmsSerializer\Enum\DeserializationInvalidValueException($this->getFieldPath($visitor, $context), $e);
throw new \Consistence\JmsSerializer\Enum\DeserializationInvalidValueException($this->getFieldPath($context), $e);
}
}

/**
* @param \JMS\Serializer\VisitorInterface $visitor
* @param \JMS\Serializer\Visitor\DeserializationVisitorInterface $visitor
* @param mixed $data
* @param mixed[] $type
* @param \JMS\Serializer\Context $context
* @return \Consistence\Enum\Enum
*/
private function deserializeEnumValue(VisitorInterface $visitor, $data, array $type, Context $context): Enum
private function deserializeEnumValue(DeserializationVisitorInterface $visitor, $data, array $type): Enum
{
$enumClass = $this->getEnumClass($type);
if ($this->hasAsSingleParameter($type)) {
Expand All @@ -186,30 +170,43 @@ private function deserializeEnumValue(VisitorInterface $visitor, $data, array $t
throw new \Consistence\JmsSerializer\Enum\NotIterableValueException($data);
}
foreach ($data as $item) {
$singleEnums[] = $singleEnumClass::get($this->deserializationVisitType($visitor, $item, $type, $context));
$singleEnums[] = $singleEnumClass::get($this->deserializationVisitType($visitor, $item, $type));
}

return $enumClass::getMultiByEnums($singleEnums);
}

return $enumClass::get($this->deserializationVisitType($visitor, $data, $type, $context));
return $enumClass::get($this->deserializationVisitType($visitor, $data, $type));
}

/**
* @param \JMS\Serializer\VisitorInterface $visitor
* @param \JMS\Serializer\Visitor\DeserializationVisitorInterface $visitor
* @param mixed $data
* @param mixed[] $typeMetadata
* @param \JMS\Serializer\Context $context
* @return mixed
*/
private function deserializationVisitType(VisitorInterface $visitor, $data, array $typeMetadata, Context $context)
private function deserializationVisitType(DeserializationVisitorInterface $visitor, $data, array $typeMetadata)
{
$deserializationType = $this->findDeserializationType($typeMetadata);
if ($deserializationType === null) {
return $data;
}

return $this->visitType($visitor, $data, $deserializationType, $typeMetadata, $context);
switch (true) {
case $deserializationType->equalsValue(EnumValueType::INTEGER):
return $visitor->visitInteger($data, $typeMetadata);
case $deserializationType->equalsValue(EnumValueType::STRING):
return $visitor->visitString($data, $typeMetadata);
case $deserializationType->equalsValue(EnumValueType::FLOAT):
return $visitor->visitDouble($data, $typeMetadata);
case $deserializationType->equalsValue(EnumValueType::BOOLEAN):
return $visitor->visitBoolean($data, $typeMetadata);
// @codeCoverageIgnoreStart
// should never happen, other types are not allowed in Enums
default:
throw new \Exception('Unexpected type');
}
// @codeCoverageIgnoreEnd
}

/**
Expand Down Expand Up @@ -303,16 +300,12 @@ private function getPropertyPath(Context $context): string
return $path;
}

private function getFieldPath(VisitorInterface $visitor, Context $context): string
private function getFieldPath(Context $context): string
{
$path = '';
foreach ($context->getMetadataStack() as $element) {
if ($element instanceof PropertyMetadata) {
$name = ($element->serializedName !== null) ? $element->serializedName : $element->name;
if ($visitor instanceof AbstractVisitor) {
$name = $visitor->getNamingStrategy()->translateName($element);
}

$path = $name . self::PATH_FIELD_SEPARATOR . $path;
}
}
Expand Down
8 changes: 5 additions & 3 deletions tests/Enum/EnumSerializerHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Consistence\JmsSerializer\Enum;

use Consistence\Type\Type;
use JMS\Serializer\Handler\HandlerRegistry;
use JMS\Serializer\Serializer;
use JMS\Serializer\SerializerBuilder;
Expand Down Expand Up @@ -124,11 +125,12 @@ public function testDeserializeEnumFromXml(): void
public function testDeserializeJsonTypes($value, $serializedValue): void
{
$serializer = $this->getSerializer();
$type = Type::getType($value);
$user = $serializer->deserialize(sprintf('{
"type_enum": %s
}', $serializedValue), User::class, 'json');
"%s": %s
}', $type, $serializedValue), User::class, 'json');
$this->assertInstanceOf(User::class, $user);
$this->assertSame(TypeEnum::get($value), $user->typeEnum);
$this->assertSame(TypeEnum::get($value), $user->$type);
}

public function testSerializeMultiEnum(): void
Expand Down
24 changes: 24 additions & 0 deletions tests/Enum/data/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,28 @@ class User
*/
public $typeEnumWithType;

/**
* @JMS\Type("enum<Consistence\JmsSerializer\Enum\TypeEnum, string>")
* @var \Consistence\JmsSerializer\Enum\TypeEnum
*/
public $string;

/**
* @JMS\Type("enum<Consistence\JmsSerializer\Enum\TypeEnum, int>")
* @var \Consistence\JmsSerializer\Enum\TypeEnum
*/
public $int;

/**
* @JMS\Type("enum<Consistence\JmsSerializer\Enum\TypeEnum, bool>")
* @var \Consistence\JmsSerializer\Enum\TypeEnum
*/
public $bool;

/**
* @JMS\Type("enum<Consistence\JmsSerializer\Enum\TypeEnum, float>")
* @var \Consistence\JmsSerializer\Enum\TypeEnum
*/
public $float;

}

0 comments on commit d7a7cb2

Please sign in to comment.