diff --git a/Annotation/FormType.php b/Annotation/FormType.php new file mode 100644 index 0000000..a553fd3 --- /dev/null +++ b/Annotation/FormType.php @@ -0,0 +1,43 @@ +type = $values['value']; + } + } + + public function getType() + { + return $this->type; + } +} + diff --git a/Serializer/FormSerializer.php b/Serializer/FormSerializer.php index 9da3dfd..f2f7d43 100644 --- a/Serializer/FormSerializer.php +++ b/Serializer/FormSerializer.php @@ -71,8 +71,8 @@ public function serialize($object, $typeBuilder, $format) if (($typeBuilder instanceof FormTypeInterface) || is_string($typeBuilder)) { $form = $this->factory->create($typeBuilder, $object); } else if ($typeBuilder instanceof FormBuilderInterface) { + $typeBuilder->setData($object); $form = $typeBuilder->getForm(); - $form->setData($object); } else if ($typeBuilder instanceof FormInterface) { $form = $typeBuilder; if ( ! $form->isBound()) { diff --git a/Serializer/JMS/FormMetadataDriver.php b/Serializer/JMS/FormMetadataDriver.php new file mode 100644 index 0000000..2f87897 --- /dev/null +++ b/Serializer/JMS/FormMetadataDriver.php @@ -0,0 +1,117 @@ +reader = $reader; + $this->formFactory = $formFactory; + } + + public function loadMetadataForClass(\ReflectionClass $class) + { + $classMetadata = new ClassMetadata($name = $class->getName()); + + foreach ($this->reader->getClassAnnotations($class) as $annot) { + if ($annot instanceof FormType) { + $type = $annot->getType(); + + if (class_exists($type)) { + $type = new $type; + } + + $form = $this->formFactory->create($type, null, array()); + $options = $form->getConfig()->getOptions(); + + $classMetadata->xmlRootName = $options['serialize_xml_name']; + + $propertiesMetadata = array(); + foreach ($form->getChildren() as $children) { + $childOptions = $children->getConfig()->getOptions(); + $type = $children->getConfig()->getType(); + + $property = $class->getProperty($children->getName()); + $propertyMetadata = new PropertyMetadata($name, $property->getName()); + #$propertyMetadata->setAccessor('public_method', null, null); + + if (!empty($childOptions['serialize_name'])) { + $propertyMetadata->serializedName = $childOptions['serialize_name']; + } + + if ($type->getName() == "collection") { + $propertyMetadata->xmlCollection = true; + $propertyMetadata->xmlCollectionInline = $childOptions['serialize_xml_inline']; + + if ( ! empty($childOptions['serialize_xml_name'])) { + $propertyMetadata->xmlEntryName = $childOptions['serialize_xml_name']; + } + + $subForm = $this->formFactory->create($childOptions['type']); + + $propertyMetadata->type = sprintf('array<%s>', $this->translateType($subForm)); + } else if ($type->getName() == "choice") { + $propertyMetadata->type = $childOptions['multiple'] ? "array" : "string"; + } else if ($type->getName() == "entity") { + $propertyMetadata->type = $childOptions['multiple'] ? "array" : "string"; + } else { + $propertyMetadata->type = $this->translateType($children); + } + + if ($childOptions['serialize_xml_attribute']) { + $propertyMetadata->xmlAttribute = true; + } else if ($childOptions['serialize_xml_value']) { + $propertyMetadata->xmlValue = true; + } + + if ($childOptions['disabled']) { + $propertyMetadata->readOnly = true; + } + + $classMetadata->addPropertyMetadata($propertyMetadata); + } + } + } + + return $classMetadata; + } + + private function translateType($form) + { + $options = $form->getConfig()->getOptions(); + if ($options['data_class']) { + return $options['data_class']; + } + + switch ($form->getConfig()->getType()->getName()) { + case 'date': + case 'datetime': + case 'time': + case 'birthday'; + return 'DateTime'; + case 'number': + return 'double'; + case 'checkbox': + return 'boolean'; + case 'integer'; + return 'integer'; + default: + return 'string'; + } + } +} + diff --git a/Tests/Serializer/Fixture/Address.php b/Tests/Serializer/Fixture/Address.php index 22078e8..92f0ca8 100644 --- a/Tests/Serializer/Fixture/Address.php +++ b/Tests/Serializer/Fixture/Address.php @@ -2,9 +2,11 @@ namespace SimpleThings\FormSerializerBundle\Tests\Serializer\Fixture; use JMS\SerializerBundle\Annotation as JMS; +use SimpleThings\FormSerializerBundle\Annotation\FormType; /** * @JMS\ExclusionPolicy("none") + * @FormType("SimpleThings\FormSerializerBundle\Tests\Serializer\Fixture\AddressType") */ class Address { diff --git a/Tests/Serializer/Fixture/User.php b/Tests/Serializer/Fixture/User.php index 8016731..2cd1c7d 100644 --- a/Tests/Serializer/Fixture/User.php +++ b/Tests/Serializer/Fixture/User.php @@ -3,9 +3,11 @@ namespace SimpleThings\FormSerializerBundle\Tests\Serializer\Fixture; use JMS\SerializerBundle\Annotation as JMS; +use SimpleThings\FormSerializerBundle\Annotation\FormType; /** * @JMS\ExclusionPolicy("none") + * @FormType("SimpleThings\FormSerializerBundle\Tests\Serializer\Fixture\UserType") */ class User { diff --git a/Tests/Serializer/JmsFormMetadataDriverTest.php b/Tests/Serializer/JmsFormMetadataDriverTest.php new file mode 100644 index 0000000..d48342a --- /dev/null +++ b/Tests/Serializer/JmsFormMetadataDriverTest.php @@ -0,0 +1,73 @@ +createFormFactory()); + + $reflClass = new \ReflectionClass('SimpleThings\FormSerializerBundle\Tests\Serializer\Fixture\User'); + $metadata = $driver->loadMetadataForClass($reflClass); + + $this->assertInstanceOf('JMS\SerializerBundle\Metadata\ClassMetadata', $metadata); + $this->assertEquals(array('username', 'email', 'birthday', 'country', 'address', 'addresses'), array_keys($metadata->propertyMetadata)); + } + + public function testSerialize() + { + $serializer = $this->createJmsSerializer(true); + + $address = new Address(); + $address->street = "Somestreet 1"; + $address->zipCode = 12345; + $address->city = "Bonn"; + + $user = new User(); + $user->username = "beberlei"; + $user->email = "kontakt@beberlei.de"; + $user->birthday = new \DateTime("1984-03-18"); + $user->gender = 'male'; + $user->interests = array('sport', 'reading'); + $user->country = "DE"; + $user->address = $address; + $user->addresses = array($address, $address); + + $xml = $serializer->serialize($user, 'xml'); + + $this->assertEquals(<< + + + + 1984-03-18T00:00:00+0100 + +
+ +
+
+ + + +XML + , $xml); + + $json = $serializer->serialize($user, 'json'); + + $this->assertEquals(<<serializeList($list, new UserType(), 'xml', 'users'); - echo number_format(microtime(true) - $start, 4) . "\n"; + echo "Form Serializer: " . number_format(microtime(true) - $start, 4) . "\n"; #echo $this->formatXml($xml); $jmsSerializer = $this->createJmsSerializer(); + $xml = $jmsSerializer->serialize($list, 'xml'); $start = microtime(true); $xml = $jmsSerializer->serialize($list, 'xml'); - echo number_format(microtime(true) - $start, 4) . "\n"; + echo "JMS Annotations: " . number_format(microtime(true) - $start, 4) . "\n"; #echo $this->formatXml($xml); + + $jmsSerializer = $this->createJmsSerializer(true); + $xml = $jmsSerializer->serialize($list, 'xml'); + $start = microtime(true); + $xml = $jmsSerializer->serialize($list, 'xml'); + echo "JMS with Form Metadata: " . number_format(microtime(true) - $start, 4) . "\n"; } } diff --git a/Tests/TestCase.php b/Tests/TestCase.php index 3b1cbf2..3365870 100644 --- a/Tests/TestCase.php +++ b/Tests/TestCase.php @@ -59,7 +59,7 @@ public function createFormSerializer(SerializerOptions $options = null) return $formSerializer; } - public function createJmsSerializer() + public function createJmsSerializer($forms = false) { $namingStrategy = new SerializedNameAnnotationStrategy(new CamelCaseNamingStrategy()); $objectConstructor = new UnserializeObjectConstructor(); @@ -83,19 +83,26 @@ public function createJmsSerializer() 'xml' => new XmlDeserializationVisitor($namingStrategy, $customDeserializationHandlers, $objectConstructor), ); - $factory = $this->createJmsMetadataFactory(); + $factory = $this->createJmsMetadataFactory($forms); return new JMSSerializer($factory, $serializationVisitors, $deserializationVisitors); } - public function createJmsMetadataFactory() + public function createJmsMetadataFactory($forms = false) { $fileLocator = new \Metadata\Driver\FileLocator(array()); - $driver = new \Metadata\Driver\DriverChain(array( - new \JMS\SerializerBundle\Metadata\Driver\YamlDriver($fileLocator), - new \JMS\SerializerBundle\Metadata\Driver\XmlDriver($fileLocator), - new \JMS\SerializerBundle\Metadata\Driver\PhpDriver($fileLocator), - new \JMS\SerializerBundle\Metadata\Driver\AnnotationDriver(new \Doctrine\Common\Annotations\AnnotationReader()) - )); + if ($forms) { + $driver = new \SimpleThings\FormSerializerBundle\Serializer\JMS\FormMetadataDriver( + new \Doctrine\Common\Annotations\AnnotationReader(), + $this->createFormFactory() + ); + } else { + $driver = new \Metadata\Driver\DriverChain(array( + new \JMS\SerializerBundle\Metadata\Driver\YamlDriver($fileLocator), + new \JMS\SerializerBundle\Metadata\Driver\XmlDriver($fileLocator), + new \JMS\SerializerBundle\Metadata\Driver\PhpDriver($fileLocator), + new \JMS\SerializerBundle\Metadata\Driver\AnnotationDriver(new \Doctrine\Common\Annotations\AnnotationReader()) + )); + } return new MetadataFactory($driver); } @@ -175,7 +182,7 @@ protected function formatJson($json) } default: $new_json .= $char; - break; + break; } } diff --git a/Tests/bootstrap.php b/Tests/bootstrap.php index b88a643..efcf863 100644 --- a/Tests/bootstrap.php +++ b/Tests/bootstrap.php @@ -9,7 +9,7 @@ ); } -spl_autoload_register(function($class) { +$bundleLoader = (function($class) { if (0 === strpos($class, 'SimpleThings\\FormSerializerBundle\\')) { $path = __DIR__.'/../'.implode('/', array_slice(explode('\\', $class), 2)).'.php'; if (!stream_resolve_include_path($path)) { @@ -19,5 +19,8 @@ return true; } }); +spl_autoload_register($bundleLoader); Doctrine\Common\Annotations\AnnotationRegistry::registerLoader(array($loader, 'loadClass')); +Doctrine\Common\Annotations\AnnotationRegistry::registerLoader($bundleLoader); + diff --git a/composer.lock b/composer.lock index 48b5760..730fa16 100644 --- a/composer.lock +++ b/composer.lock @@ -14,8 +14,8 @@ { "package": "symfony/symfony", "version": "dev-master", - "source-reference": "cbd03ec4c66567cf2bf4ea9e0e3315a522b4eeb3", - "commit-date": "1343635713" + "source-reference": "a172a812960d060cd5dd13e4dcf3b2bc4043a18f", + "commit-date": "1343639879" }, { "package": "twig/twig",