Browse Source

Dispatch pre-serialization event before handling data to have ability change type in listener

Vyacheslav Salakhutdinov 12 years ago
parent
commit
c465d068a2

+ 1 - 1
src/JMS/Serializer/EventDispatcher/PreSerializeEvent.php

@@ -10,6 +10,6 @@ class PreSerializeEvent extends Event
      */
     public function setType($typeName, array $params = array())
     {
-        $this->type = array('name' => $typeName, 'params' => $typeName);
+        $this->type = array('name' => $typeName, 'params' => $params);
     }
 }

+ 9 - 8
src/JMS/Serializer/GraphNavigator.php

@@ -153,6 +153,15 @@ final class GraphNavigator
                     $this->context->startVisiting($data);
                 }
 
+                // Trigger pre-serialization callbacks, and listeners if they exist.
+                // Dispatch pre-serialization event before handling data to have ability change type in listener
+                if ($isSerializing) {
+                    if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.pre_serialize', $type['name'], $this->context->getFormat())) {
+                        $this->dispatcher->dispatch('serializer.pre_serialize', $type['name'], $this->context->getFormat(), $event = new PreSerializeEvent($visitor, $data, $type));
+                        $type = $event->getType();
+                    }
+                }
+
                 // First, try whether a custom handler exists for the given type. This is done
                 // before loading metadata because the type name might not be a class, but
                 // could also simply be an artifical type.
@@ -164,14 +173,6 @@ final class GraphNavigator
                     return $rs;
                 }
 
-                // Trigger pre-serialization callbacks, and listeners if they exist.
-                if ($isSerializing) {
-                    if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.pre_serialize', $type['name'], $this->context->getFormat())) {
-                        $this->dispatcher->dispatch('serializer.pre_serialize', $type['name'], $this->context->getFormat(), $event = new PreSerializeEvent($visitor, $data, $type));
-                        $type = $event->getType();
-                    }
-                }
-
                 // Load metadata, and check whether this class should be excluded.
                 $metadata = $this->metadataFactory->getMetadataForClass($type['name']);
                 if (null !== $this->exclusionStrategy && $this->exclusionStrategy->shouldSkipClass($metadata, $this->context)) {

+ 32 - 0
tests/JMS/Serializer/Tests/Serializer/GraphNavigatorTest.php

@@ -90,6 +90,38 @@ class GraphNavigatorTest extends \PHPUnit_Framework_TestCase
         $this->navigator->accept('random', array('name' => $class, 'params' => array()), $this->visitor);
     }
 
+    public function testNavigatorChangeTypeOnSerialization()
+    {
+        $object = new SerializableClass;
+        $typeName = 'JsonSerializable';
+
+        $this->dispatcher->addListener('serializer.pre_serialize', function($event) use ($typeName) {
+            $type = $event->getType();
+            $type['name'] = $typeName;
+            $event->setType($type['name'], $type['params']);
+        });
+
+        $subscribingHandlerClass = $this->getMockClass('JMS\Serializer\Handler\SubscribingHandlerInterface', array('getSubscribingMethods', 'serialize'));
+        $subscribingHandlerClass::staticExpects($this->once())
+            ->method('getSubscribingMethods')
+            ->will($this->returnValue(array(array(
+                'type' => $typeName,
+                'format' => 'foo',
+                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
+                'method' => 'serialize'
+            ))));
+
+        $subscribingHandler = new $subscribingHandlerClass();
+        $subscribingHandler->expects($this->once())
+            ->method('serialize')
+            ->with($this->equalTo($this->visitor), $this->equalTo($object));
+
+        $this->handlerRegistry->registerSubscribingHandler($subscribingHandler);
+
+        $this->navigator = new GraphNavigator(GraphNavigator::DIRECTION_SERIALIZATION, $this->metadataFactory, 'foo', $this->handlerRegistry, $this->objectConstructor, null, $this->dispatcher);
+        $this->navigator->accept($object, null, $this->visitor);
+    }
+
     protected function setUp()
     {
         $this->visitor = $this->getMock('JMS\Serializer\VisitorInterface');