- <?php
- namespace JMS\Serializer;
- use JMS\Serializer\Construction\ObjectConstructorInterface;
- use JMS\Serializer\ContextFactory\DefaultDeserializationContextFactory;
- use JMS\Serializer\ContextFactory\DefaultSerializationContextFactory;
- use JMS\Serializer\ContextFactory\DeserializationContextFactoryInterface;
- use JMS\Serializer\ContextFactory\SerializationContextFactoryInterface;
- use JMS\Serializer\EventDispatcher\EventDispatcherInterface;
- use JMS\Serializer\Exception\RuntimeException;
- use JMS\Serializer\Exception\UnsupportedFormatException;
- use JMS\Serializer\Expression\ExpressionEvaluatorInterface;
- use JMS\Serializer\Handler\HandlerRegistryInterface;
- use Metadata\MetadataFactoryInterface;
- use PhpCollection\MapInterface;
- /**
-  * Serializer Implementation.
-  *
-  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
-  */
- class Serializer implements SerializerInterface, ArrayTransformerInterface
- {
-     private $factory;
-     private $handlerRegistry;
-     private $objectConstructor;
-     private $dispatcher;
-     private $typeParser;
-     /** @var \PhpCollection\MapInterface */
-     private $serializationVisitors;
-     /** @var \PhpCollection\MapInterface */
-     private $deserializationVisitors;
-     private $navigator;
-     /**
-      * @var SerializationContextFactoryInterface
-      */
-     private $serializationContextFactory;
-     /**
-      * @var DeserializationContextFactoryInterface
-      */
-     private $deserializationContextFactory;
-     /**
-      * Constructor.
-      *
-      * @param \Metadata\MetadataFactoryInterface $factory
-      * @param Handler\HandlerRegistryInterface $handlerRegistry
-      * @param Construction\ObjectConstructorInterface $objectConstructor
-      * @param \PhpCollection\MapInterface $serializationVisitors of VisitorInterface
-      * @param \PhpCollection\MapInterface $deserializationVisitors of VisitorInterface
-      * @param EventDispatcher\EventDispatcherInterface $dispatcher
-      * @param TypeParser $typeParser
-      * @param ExpressionEvaluatorInterface|null $expressionEvaluator
-      */
-     public function __construct(
-         MetadataFactoryInterface $factory,
-         HandlerRegistryInterface $handlerRegistry,
-         ObjectConstructorInterface $objectConstructor,
-         MapInterface $serializationVisitors,
-         MapInterface $deserializationVisitors,
-         EventDispatcherInterface $dispatcher = null,
-         TypeParser $typeParser = null,
-         ExpressionEvaluatorInterface $expressionEvaluator = null
-     )
-     {
-         $this->factory = $factory;
-         $this->handlerRegistry = $handlerRegistry;
-         $this->objectConstructor = $objectConstructor;
-         $this->dispatcher = $dispatcher;
-         $this->typeParser = $typeParser ?: new TypeParser();
-         $this->serializationVisitors = $serializationVisitors;
-         $this->deserializationVisitors = $deserializationVisitors;
-         $this->navigator = new GraphNavigator($this->factory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher, $expressionEvaluator);
-         $this->serializationContextFactory = new DefaultSerializationContextFactory();
-         $this->deserializationContextFactory = new DefaultDeserializationContextFactory();
-     }
-     public function serialize($data, $format, SerializationContext $context = null)
-     {
-         if (null === $context) {
-             $context = $this->serializationContextFactory->createSerializationContext();
-         }
-         return $this->serializationVisitors->get($format)
-             ->map(function (VisitorInterface $visitor) use ($context, $data, $format) {
-                 $type = $context->getInitialType() !== null ? $this->typeParser->parse($context->getInitialType()) : null;
-                 $this->visit($visitor, $context, $visitor->prepare($data), $format, $type);
-                 return $visitor->getResult();
-             })
-             ->getOrThrow(new UnsupportedFormatException(sprintf('The format "%s" is not supported for serialization.', $format)));
-     }
-     public function deserialize($data, $type, $format, DeserializationContext $context = null)
-     {
-         if (null === $context) {
-             $context = $this->deserializationContextFactory->createDeserializationContext();
-         }
-         return $this->deserializationVisitors->get($format)
-             ->map(function (VisitorInterface $visitor) use ($context, $data, $format, $type) {
-                 $preparedData = $visitor->prepare($data);
-                 $navigatorResult = $this->visit($visitor, $context, $preparedData, $format, $this->typeParser->parse($type));
-                 return $this->handleDeserializeResult($visitor->getResult(), $navigatorResult);
-             })
-             ->getOrThrow(new UnsupportedFormatException(sprintf('The format "%s" is not supported for deserialization.', $format)));
-     }
-     /**
-      * {@InheritDoc}
-      */
-     public function toArray($data, SerializationContext $context = null)
-     {
-         if (null === $context) {
-             $context = $this->serializationContextFactory->createSerializationContext();
-         }
-         return $this->serializationVisitors->get('json')
-             ->map(function (JsonSerializationVisitor $visitor) use ($context, $data) {
-                 $type = $context->getInitialType() !== null ? $this->typeParser->parse($context->getInitialType()) : null;
-                 $this->visit($visitor, $context, $data, 'json', $type);
-                 $result = $this->convertArrayObjects($visitor->getRoot());
-                 if (!\is_array($result)) {
-                     throw new RuntimeException(sprintf(
-                         'The input data of type "%s" did not convert to an array, but got a result of type "%s".',
-                         \is_object($data) ? \get_class($data) : \gettype($data),
-                         \is_object($result) ? \get_class($result) : \gettype($result)
-                     ));
-                 }
-                 return $result;
-             })
-             ->get();
-     }
-     /**
-      * {@InheritDoc}
-      */
-     public function fromArray(array $data, $type, DeserializationContext $context = null)
-     {
-         if (null === $context) {
-             $context = $this->deserializationContextFactory->createDeserializationContext();
-         }
-         return $this->deserializationVisitors->get('json')
-             ->map(function (JsonDeserializationVisitor $visitor) use ($data, $type, $context) {
-                 $navigatorResult = $this->visit($visitor, $context, $data, 'json', $this->typeParser->parse($type));
-                 return $this->handleDeserializeResult($visitor->getResult(), $navigatorResult);
-             })
-             ->get();
-     }
-     private function visit(VisitorInterface $visitor, Context $context, $data, $format, array $type = null)
-     {
-         $context->initialize(
-             $format,
-             $visitor,
-             $this->navigator,
-             $this->factory
-         );
-         $visitor->setNavigator($this->navigator);
-         return $this->navigator->accept($data, $type, $context);
-     }
-     private function handleDeserializeResult($visitorResult, $navigatorResult)
-     {
-         // This is a special case if the root is handled by a callback on the object itself.
-         if (null === $visitorResult && null !== $navigatorResult) {
-             return $navigatorResult;
-         }
-         return $visitorResult;
-     }
-     private function convertArrayObjects($data)
-     {
-         if ($data instanceof \ArrayObject || $data instanceof \stdClass) {
-             $data = (array)$data;
-         }
-         if (\is_array($data)) {
-             foreach ($data as $k => $v) {
-                 $data[$k] = $this->convertArrayObjects($v);
-             }
-         }
-         return $data;
-     }
-     /**
-      * @return MetadataFactoryInterface
-      */
-     public function getMetadataFactory()
-     {
-         return $this->factory;
-     }
-     /**
-      * @param SerializationContextFactoryInterface $serializationContextFactory
-      *
-      * @return self
-      */
-     public function setSerializationContextFactory(SerializationContextFactoryInterface $serializationContextFactory)
-     {
-         $this->serializationContextFactory = $serializationContextFactory;
-         return $this;
-     }
-     /**
-      * @param DeserializationContextFactoryInterface $deserializationContextFactory
-      *
-      * @return self
-      */
-     public function setDeserializationContextFactory(DeserializationContextFactoryInterface $deserializationContextFactory)
-     {
-         $this->deserializationContextFactory = $deserializationContextFactory;
-         return $this;
-     }
- }
-