public function testSetAccessorOrderAlphabetical()
 {
     $metadata = new ClassMetadata('JMS\\Serializer\\Tests\\Metadata\\PropertyMetadataOrder');
     $metadata->addPropertyMetadata(new PropertyMetadata('JMS\\Serializer\\Tests\\Metadata\\PropertyMetadataOrder', 'b'));
     $metadata->addPropertyMetadata(new PropertyMetadata('JMS\\Serializer\\Tests\\Metadata\\PropertyMetadataOrder', 'a'));
     $this->assertEquals(array('b', 'a'), array_keys($metadata->propertyMetadata));
     $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_ALPHABETICAL);
     $this->assertEquals(array('a', 'b'), array_keys($metadata->propertyMetadata));
 }
 /**
  * @dataProvider setAccessorOrderDataProvider
  */
 public function testSetAccessorOrder($order, array $customOrder, $expected, $message)
 {
     $class = 'JMS\\Serializer\\Tests\\Metadata\\PropertyMetadataOrder';
     // Note: defined in this file below ClassMetadataTest
     $metadata = new ClassMetadata($class);
     $metadata->addPropertyMetadata(new PropertyMetadata($class, 'z'));
     $metadata->addPropertyMetadata(new PropertyMetadata($class, 'a'));
     $metadata->addPropertyMetadata(new PropertyMetadata($class, 'b'));
     $metadata->addPropertyMetadata(new PropertyMetadata($class, 'c'));
     if ($order) {
         $metadata->setAccessorOrder($order, $customOrder);
     }
     $this->assertEquals($expected, array_keys($metadata->propertyMetadata), $message);
 }
 /**
  * Push the properties into ClassMetadata
  */
 public function build()
 {
     foreach ($this->properties as $prop) {
         $this->metadata->addPropertyMetadata($prop);
     }
     $this->currentPropertyName = null;
     $this->properties = array();
 }
 /**
  * When serializer wants to serialize a class, it will ask this method to produce the metadata.
  *
  * @param \ReflectionClass $class
  * @return \Metadata\ClassMetadata
  */
 public function loadMetadataForClass(ReflectionClass $class)
 {
     $className = $class->name;
     $classMetadata = new ClassMetadata($className);
     $mappingConfig = $this->config->get(sprintf('serializer::mappings.%s', $className));
     // If the class is an instance of Model, as a convenience, pre-configure $visible as defaults.
     if ($class->isSubclassOf('Illuminate\\Database\\Eloquent\\Model')) {
         $defaultProperties = $class->getDefaultProperties();
         if (!empty($defaultProperties['visible'])) {
             $mappingConfig['attributes'] = array_merge($defaultProperties['visible'], $mappingConfig['attributes']);
         }
     }
     //
     // Generate a Type Meta-Property
     $classMetadata->addPropertyMetadata(new StaticPropertyMetadata($className, '_type', snake_case($class->getShortName())));
     //
     //
     if (!empty($mappingConfig['attributes'])) {
         // Only serialize attributes present in the L4 config array.
         foreach ($mappingConfig['attributes'] as $attribute => $attributeConfig) {
             //
             // Select a property metadata class.
             // If there's a mutator method, it's virtual.
             $mutatorMethod = sprintf('get%sAttribute', studly_case($attribute));
             if ($class->hasMethod($mutatorMethod)) {
                 $propertyMetadata = new VirtualPropertyMetadata($className, $mutatorMethod);
             } elseif ($class->hasProperty($attribute) || $class->isSubclassOf('Illuminate\\Database\\Eloquent\\Model')) {
                 $propertyMetadata = new PropertyMetadata($className, $attribute);
             }
             //
             //
             if (!empty($propertyMetadata)) {
                 //
                 // Additional property config processing.
                 // An array config for the attribute means the attribute has more to set up.
                 if (is_array($attributeConfig)) {
                     foreach ($attributeConfig as $config => $value) {
                         $metadataSetMethod = sprintf('set%sMetadata', studly_case($config));
                         $this->{$metadataSetMethod}($propertyMetadata, $value);
                     }
                 } elseif (is_string($attributeConfig)) {
                     $this->setTypeMetadata($propertyMetadata, $attributeConfig);
                 }
                 // else - Any other value/null just lives with the defaults.
                 //
                 //
                 $classMetadata->addPropertyMetadata($propertyMetadata);
             }
         }
     }
     return $classMetadata;
 }
Beispiel #5
0
 public function testSetAccessorOrder()
 {
     $metadata = new ClassMetadata('JMS\\Serializer\\Tests\\Metadata\\PropertyMetadataOrder');
     $metadata->addPropertyMetadata(new PropertyMetadata('JMS\\Serializer\\Tests\\Metadata\\PropertyMetadataOrder', 'b'));
     $metadata->addPropertyMetadata(new PropertyMetadata('JMS\\Serializer\\Tests\\Metadata\\PropertyMetadataOrder', 'a'));
     $this->assertEquals(array('b', 'a'), array_keys($metadata->propertyMetadata));
     $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_ALPHABETICAL);
     $this->assertEquals(array('a', 'b'), array_keys($metadata->propertyMetadata));
     $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, array('b', 'a'));
     $this->assertEquals(array('b', 'a'), array_keys($metadata->propertyMetadata));
     $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, array('a', 'b'));
     $this->assertEquals(array('a', 'b'), array_keys($metadata->propertyMetadata));
     $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, array('b'));
     $this->assertEquals(array('b', 'a'), array_keys($metadata->propertyMetadata));
     $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, array('a'));
     $this->assertEquals(array('a', 'b'), array_keys($metadata->propertyMetadata));
     //We're not sure, in which order array will be sorted.
     //We only know, that it should contain both properties
     $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, array('foo', 'bar'));
     $this->assertArrayHasKey('a', $metadata->propertyMetadata);
     $this->assertArrayHasKey('b', $metadata->propertyMetadata);
     $this->assertCount(2, $metadata->propertyMetadata);
 }
 public function testParserWithVersion()
 {
     $metadataFactory = $this->getMock('Metadata\\MetadataFactoryInterface');
     $docCommentExtractor = $this->getMockBuilder('Nelmio\\ApiDocBundle\\Util\\DocCommentExtractor')->disableOriginalConstructor()->getMock();
     $propertyMetadataFoo = new PropertyMetadata('Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested', 'foo');
     $propertyMetadataFoo->type = array('name' => 'string');
     $propertyMetadataBar = new PropertyMetadata('Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested', 'bar');
     $propertyMetadataBar->type = array('name' => 'string');
     $propertyMetadataBar->sinceVersion = '2.0';
     $propertyMetadataBaz = new PropertyMetadata('Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested', 'baz');
     $propertyMetadataBaz->type = array('name' => 'string');
     $propertyMetadataBaz->untilVersion = '3.0';
     $input = 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsNested';
     $metadata = new ClassMetadata($input);
     $metadata->addPropertyMetadata($propertyMetadataFoo);
     $metadata->addPropertyMetadata($propertyMetadataBar);
     $metadata->addPropertyMetadata($propertyMetadataBaz);
     $metadataFactory->expects($this->any())->method('getMetadataForClass')->with($input)->will($this->returnValue($metadata));
     $propertyNamingStrategy = new CamelCaseNamingStrategy();
     $jmsMetadataParser = new JmsMetadataParser($metadataFactory, $propertyNamingStrategy, $docCommentExtractor);
     // No group specified.
     $output = $jmsMetadataParser->parse(array('class' => $input, 'groups' => array()));
     $this->assertEquals(array('foo' => array('dataType' => 'string', 'required' => false, 'description' => null, 'readonly' => false, 'sinceVersion' => null, 'untilVersion' => null), 'bar' => array('dataType' => 'string', 'required' => false, 'description' => null, 'readonly' => false, 'sinceVersion' => '2.0', 'untilVersion' => null), 'baz' => array('dataType' => 'string', 'required' => false, 'description' => null, 'readonly' => false, 'sinceVersion' => null, 'untilVersion' => '3.0')), $output);
 }
 public function loadMetadataForClass(\ReflectionClass $class)
 {
     $classMetadata = new ClassMetadata($name = $class->name);
     $classMetadata->fileResources[] = $class->getFilename();
     $propertiesMetadata = array();
     $propertiesAnnotations = array();
     $exclusionPolicy = 'NONE';
     $excludeAll = false;
     $classAccessType = PropertyMetadata::ACCESS_TYPE_PROPERTY;
     foreach ($this->reader->getClassAnnotations($class) as $annot) {
         if ($annot instanceof ExclusionPolicy) {
             $exclusionPolicy = $annot->policy;
         } elseif ($annot instanceof XmlRoot) {
             $classMetadata->xmlRootName = $annot->name;
         } elseif ($annot instanceof Exclude) {
             $excludeAll = true;
         } elseif ($annot instanceof AccessType) {
             $classAccessType = $annot->type;
         } elseif ($annot instanceof AccessorOrder) {
             $classMetadata->setAccessorOrder($annot->order, $annot->custom);
         } elseif ($annot instanceof Discriminator) {
             if ($annot->disabled) {
                 $classMetadata->discriminatorDisabled = true;
             } else {
                 $classMetadata->setDiscriminator($annot->field, $annot->map);
             }
         }
     }
     foreach ($class->getMethods() as $method) {
         if ($method->class !== $name) {
             continue;
         }
         $methodAnnotations = $this->reader->getMethodAnnotations($method);
         foreach ($methodAnnotations as $annot) {
             if ($annot instanceof PreSerialize) {
                 $classMetadata->addPreSerializeMethod(new MethodMetadata($name, $method->name));
                 continue 2;
             } elseif ($annot instanceof PostDeserialize) {
                 $classMetadata->addPostDeserializeMethod(new MethodMetadata($name, $method->name));
                 continue 2;
             } elseif ($annot instanceof PostSerialize) {
                 $classMetadata->addPostSerializeMethod(new MethodMetadata($name, $method->name));
                 continue 2;
             } elseif ($annot instanceof VirtualProperty) {
                 $virtualPropertyMetadata = new VirtualPropertyMetadata($name, $method->name);
                 $propertiesMetadata[] = $virtualPropertyMetadata;
                 $propertiesAnnotations[] = $methodAnnotations;
                 continue 2;
             } elseif ($annot instanceof HandlerCallback) {
                 $classMetadata->addHandlerCallback(GraphNavigator::parseDirection($annot->direction), $annot->format, $method->name);
                 continue 2;
             }
         }
     }
     if (!$excludeAll) {
         foreach ($class->getProperties() as $property) {
             if ($property->class !== $name) {
                 continue;
             }
             $propertiesMetadata[] = new PropertyMetadata($name, $property->getName());
             $propertiesAnnotations[] = $this->reader->getPropertyAnnotations($property);
         }
         foreach ($propertiesMetadata as $propertyKey => $propertyMetadata) {
             $isExclude = false;
             $isExpose = $propertyMetadata instanceof VirtualPropertyMetadata;
             $accessType = $classAccessType;
             $accessor = array(null, null);
             $propertyAnnotations = $propertiesAnnotations[$propertyKey];
             foreach ($propertyAnnotations as $annot) {
                 if ($annot instanceof Since) {
                     $propertyMetadata->sinceVersion = $annot->version;
                 } elseif ($annot instanceof Until) {
                     $propertyMetadata->untilVersion = $annot->version;
                 } elseif ($annot instanceof SerializedName) {
                     $propertyMetadata->serializedName = $annot->name;
                 } elseif ($annot instanceof Expose) {
                     $isExpose = true;
                 } elseif ($annot instanceof Exclude) {
                     $isExclude = true;
                 } elseif ($annot instanceof Type) {
                     $propertyMetadata->setType($annot->name);
                 } elseif ($annot instanceof XmlList) {
                     $propertyMetadata->xmlCollection = true;
                     $propertyMetadata->xmlCollectionInline = $annot->inline;
                     $propertyMetadata->xmlEntryName = $annot->entry;
                 } elseif ($annot instanceof XmlMap) {
                     $propertyMetadata->xmlCollection = true;
                     $propertyMetadata->xmlCollectionInline = $annot->inline;
                     $propertyMetadata->xmlEntryName = $annot->entry;
                     $propertyMetadata->xmlKeyAttribute = $annot->keyAttribute;
                 } elseif ($annot instanceof XmlKeyValuePairs) {
                     $propertyMetadata->xmlKeyValuePairs = true;
                 } elseif ($annot instanceof XmlAttribute) {
                     $propertyMetadata->xmlAttribute = true;
                 } elseif ($annot instanceof XmlValue) {
                     $propertyMetadata->xmlValue = true;
                     $propertyMetadata->xmlElementCData = $annot->cdata;
                 } elseif ($annot instanceof XmlElement) {
                     $propertyMetadata->xmlElementCData = $annot->cdata;
                 } elseif ($annot instanceof AccessType) {
                     $accessType = $annot->type;
                 } elseif ($annot instanceof ReadOnly) {
                     $propertyMetadata->readOnly = true;
                 } elseif ($annot instanceof Accessor) {
                     $accessor = array($annot->getter, $annot->setter);
                 } elseif ($annot instanceof Groups) {
                     $propertyMetadata->groups = $annot->groups;
                     foreach ((array) $propertyMetadata->groups as $groupName) {
                         if (false !== strpos($groupName, ',')) {
                             throw new InvalidArgumentException(sprintf('Invalid group name "%s" on "%s", did you mean to create multiple groups?', implode(', ', $propertyMetadata->groups), $propertyMetadata->class . '->' . $propertyMetadata->name));
                         }
                     }
                 } elseif ($annot instanceof Inline) {
                     $propertyMetadata->inline = true;
                 } elseif ($annot instanceof XmlAttributeMap) {
                     $propertyMetadata->xmlAttributeMap = true;
                 } elseif ($annot instanceof MaxDepth) {
                     $propertyMetadata->maxDepth = $annot->depth;
                 }
             }
             $propertyMetadata->setAccessor($accessType, $accessor[0], $accessor[1]);
             if (ExclusionPolicy::NONE === $exclusionPolicy && !$isExclude || ExclusionPolicy::ALL === $exclusionPolicy && $isExpose) {
                 $classMetadata->addPropertyMetadata($propertyMetadata);
             }
         }
     }
     return $classMetadata;
 }
 /**
  * Returns a Serializer MetadataFactory mock.
  *
  * @return \Metadata\MetadataFactoryInterface
  */
 protected function getMetadataFactoryMock()
 {
     $name = new PropertyMetadata($this->class, 'name');
     $name->groups = array('serialization_api_write');
     $url = new PropertyMetadata($this->class, 'url');
     $url->groups = array('serialization_api_write');
     $comments = new PropertyMetadata($this->class, 'comments');
     $comments->groups = array('serialization_api_write');
     $classMetadata = new SerializerMetadata($this->class);
     $classMetadata->addPropertyMetadata($name);
     $classMetadata->addPropertyMetadata($url);
     $classMetadata->addPropertyMetadata($comments);
     $metadataFactory = $this->getMock('Metadata\\MetadataFactoryInterface');
     $metadataFactory->expects($this->once())->method('getMetadataForClass')->will($this->returnValue($classMetadata));
     return $metadataFactory;
 }
<?php

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
$metadata = new ClassMetadata('JMS\\Serializer\\Tests\\Fixtures\\BlogPost');
$metadata->xmlRootName = 'blog-post';
$pMetadata = new PropertyMetadata('JMS\\Serializer\\Tests\\Fixtures\\BlogPost', 'id');
$pMetadata->setType('string');
$pMetadata->groups = array('comments', 'post');
$pMetadata->xmlElementCData = false;
$metadata->addPropertyMetadata($pMetadata);
$pMetadata = new PropertyMetadata('JMS\\Serializer\\Tests\\Fixtures\\BlogPost', 'title');
$pMetadata->setType('string');
$pMetadata->groups = array('comments', 'post');
$metadata->addPropertyMetadata($pMetadata);
$pMetadata = new PropertyMetadata('JMS\\Serializer\\Tests\\Fixtures\\BlogPost', 'createdAt');
$pMetadata->setType('DateTime');
$pMetadata->xmlAttribute = true;
$metadata->addPropertyMetadata($pMetadata);
$pMetadata = new PropertyMetadata('JMS\\Serializer\\Tests\\Fixtures\\BlogPost', 'published');
$pMetadata->setType('boolean');
$pMetadata->serializedName = 'is_published';
$pMetadata->groups = array('post');
$pMetadata->xmlAttribute = true;
$metadata->addPropertyMetadata($pMetadata);
$pMetadata = new PropertyMetadata('JMS\\Serializer\\Tests\\Fixtures\\BlogPost', 'comments');
$pMetadata->setType('ArrayCollection<JMS\\Serializer\\Tests\\Fixtures\\Comment>');
$pMetadata->xmlCollection = true;
$pMetadata->xmlCollectionInline = true;
$pMetadata->xmlEntryName = 'comment';
$pMetadata->groups = array('comments');
 public function testParserWithInline()
 {
     $metadataFactory = $this->getMock('Metadata\\MetadataFactoryInterface');
     $docCommentExtractor = $this->getMockBuilder('Nelmio\\ApiDocBundle\\Util\\DocCommentExtractor')->disableOriginalConstructor()->getMock();
     $propertyMetadataFoo = new PropertyMetadata('Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsInline', 'foo');
     $propertyMetadataFoo->type = array('name' => 'string');
     $propertyMetadataInline = new PropertyMetadata('Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsInline', 'inline');
     $propertyMetadataInline->type = array('name' => 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsTest');
     $propertyMetadataInline->inline = true;
     $input = 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsInline';
     $metadata = new ClassMetadata($input);
     $metadata->addPropertyMetadata($propertyMetadataFoo);
     $metadata->addPropertyMetadata($propertyMetadataInline);
     $propertyMetadataBar = new PropertyMetadata('Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsTest', 'bar');
     $propertyMetadataBar->type = array('name' => 'string');
     $subInput = 'Nelmio\\ApiDocBundle\\Tests\\Fixtures\\Model\\JmsTest';
     $subMetadata = new ClassMetadata($subInput);
     $subMetadata->addPropertyMetadata($propertyMetadataBar);
     $metadataFactory->expects($this->at(0))->method('getMetadataForClass')->with($input)->will($this->returnValue($metadata));
     $metadataFactory->expects($this->at(1))->method('getMetadataForClass')->with($subInput)->will($this->returnValue($subMetadata));
     $metadataFactory->expects($this->at(2))->method('getMetadataForClass')->with($subInput)->will($this->returnValue($subMetadata));
     $propertyNamingStrategy = new CamelCaseNamingStrategy();
     $jmsMetadataParser = new JmsMetadataParser($metadataFactory, $propertyNamingStrategy, $docCommentExtractor);
     $output = $jmsMetadataParser->parse(array('class' => $input, 'groups' => array()));
     $this->assertEquals(array('foo' => array('dataType' => 'string', 'actualType' => DataTypes::STRING, 'subType' => null, 'default' => null, 'required' => false, 'description' => null, 'readonly' => false, 'sinceVersion' => null, 'untilVersion' => null), 'bar' => array('dataType' => 'string', 'actualType' => DataTypes::STRING, 'subType' => null, 'default' => null, 'required' => false, 'description' => null, 'readonly' => false, 'sinceVersion' => null, 'untilVersion' => null)), $output);
 }
 protected function loadMetadataFromFile(\ReflectionClass $class, $path)
 {
     $previous = libxml_use_internal_errors(true);
     $elem = simplexml_load_file($path);
     libxml_use_internal_errors($previous);
     if (false === $elem) {
         throw new XmlErrorException(libxml_get_last_error());
     }
     $metadata = new ClassMetadata($name = $class->name);
     if (!($elems = $elem->xpath("./class[@name = '" . $name . "']"))) {
         throw new RuntimeException(sprintf('Could not find class %s inside XML element.', $name));
     }
     $elem = reset($elems);
     $metadata->fileResources[] = $path;
     $metadata->fileResources[] = $class->getFileName();
     $exclusionPolicy = strtoupper($elem->attributes()->{'exclusion-policy'}) ?: 'NONE';
     $excludeAll = null !== ($exclude = $elem->attributes()->exclude) ? 'true' === strtolower($exclude) : false;
     $classAccessType = (string) ($elem->attributes()->{'access-type'} ?: PropertyMetadata::ACCESS_TYPE_PROPERTY);
     $propertiesMetadata = array();
     $propertiesNodes = array();
     if (null !== ($accessorOrder = $elem->attributes()->{'accessor-order'})) {
         $metadata->setAccessorOrder((string) $accessorOrder, preg_split('/\\s*,\\s*/', (string) $elem->attributes()->{'custom-accessor-order'}));
     }
     if (null !== ($xmlRootName = $elem->attributes()->{'xml-root-name'})) {
         $metadata->xmlRootName = (string) $xmlRootName;
     }
     $discriminatorFieldName = (string) $elem->attributes()->{'discriminator-field-name'};
     $discriminatorMap = array();
     foreach ($elem->xpath('./discriminator-class') as $entry) {
         if (!isset($entry->attributes()->value)) {
             throw new RuntimeException('Each discriminator-class element must have a "value" attribute.');
         }
         $discriminatorMap[(string) $entry->attributes()->value] = (string) $entry;
     }
     if ('true' === (string) $elem->attributes()->{'discriminator-disabled'}) {
         $metadata->discriminatorDisabled = true;
     } elseif (!empty($discriminatorFieldName) || !empty($discriminatorMap)) {
         $metadata->setDiscriminator($discriminatorFieldName, $discriminatorMap);
     }
     foreach ($elem->xpath('./virtual-property') as $method) {
         if (!isset($method->attributes()->method)) {
             throw new RuntimeException('The method attribute must be set for all virtual-property elements.');
         }
         $virtualPropertyMetadata = new VirtualPropertyMetadata($name, (string) $method->attributes()->method);
         $propertiesMetadata[] = $virtualPropertyMetadata;
         $propertiesNodes[] = $method;
     }
     if (!$excludeAll) {
         foreach ($class->getProperties() as $property) {
             if ($name !== $property->class) {
                 continue;
             }
             $propertiesMetadata[] = new PropertyMetadata($name, $pName = $property->getName());
             $pElems = $elem->xpath("./property[@name = '" . $pName . "']");
             $propertiesNodes[] = $pElems ? reset($pElems) : null;
         }
         foreach ($propertiesMetadata as $propertyKey => $pMetadata) {
             $isExclude = false;
             $isExpose = $pMetadata instanceof VirtualPropertyMetadata;
             $pElem = $propertiesNodes[$propertyKey];
             if (!empty($pElem)) {
                 if (null !== ($exclude = $pElem->attributes()->exclude)) {
                     $isExclude = 'true' === strtolower($exclude);
                 }
                 if (null !== ($expose = $pElem->attributes()->expose)) {
                     $isExpose = 'true' === strtolower($expose);
                 }
                 if (null !== ($version = $pElem->attributes()->{'since-version'})) {
                     $pMetadata->sinceVersion = (string) $version;
                 }
                 if (null !== ($version = $pElem->attributes()->{'until-version'})) {
                     $pMetadata->untilVersion = (string) $version;
                 }
                 if (null !== ($serializedName = $pElem->attributes()->{'serialized-name'})) {
                     $pMetadata->serializedName = (string) $serializedName;
                 }
                 if (null !== ($type = $pElem->attributes()->type)) {
                     $pMetadata->setType((string) $type);
                 } elseif (isset($pElem->type)) {
                     $pMetadata->setType((string) $pElem->type);
                 }
                 if (null !== ($groups = $pElem->attributes()->groups)) {
                     $pMetadata->groups = preg_split('/\\s*,\\s*/', (string) $groups);
                 }
                 if (isset($pElem->{'xml-list'})) {
                     $pMetadata->xmlCollection = true;
                     $colConfig = $pElem->{'xml-list'};
                     if (isset($colConfig->attributes()->inline)) {
                         $pMetadata->xmlCollectionInline = 'true' === (string) $colConfig->attributes()->inline;
                     }
                     if (isset($colConfig->attributes()->{'entry-name'})) {
                         $pMetadata->xmlEntryName = (string) $colConfig->attributes()->{'entry-name'};
                     }
                 }
                 if (isset($pElem->{'xml-map'})) {
                     $pMetadata->xmlCollection = true;
                     $colConfig = $pElem->{'xml-map'};
                     if (isset($colConfig->attributes()->inline)) {
                         $pMetadata->xmlCollectionInline = 'true' === (string) $colConfig->attributes()->inline;
                     }
                     if (isset($colConfig->attributes()->{'entry-name'})) {
                         $pMetadata->xmlEntryName = (string) $colConfig->attributes()->{'entry-name'};
                     }
                     if (isset($colConfig->attributes()->{'key-attribute-name'})) {
                         $pMetadata->xmlKeyAttribute = (string) $colConfig->attributes()->{'key-attribute-name'};
                     }
                 }
                 if (isset($pElem->attributes()->{'xml-attribute'})) {
                     $pMetadata->xmlAttribute = 'true' === (string) $pElem->attributes()->{'xml-attribute'};
                 }
                 if (isset($pElem->attributes()->{'xml-attribute-map'})) {
                     $pMetadata->xmlAttribute = 'true' === (string) $pElem->attributes()->{'xml-attribute-map'};
                 }
                 if (isset($pElem->attributes()->{'xml-value'})) {
                     $pMetadata->xmlValue = 'true' === (string) $pElem->attributes()->{'xml-value'};
                 }
                 if (isset($pElem->attributes()->{'xml-key-value-pairs'})) {
                     $pMetadata->xmlKeyValuePairs = 'true' === (string) $pElem->attributes()->{'xml-key-value-pairs'};
                 }
                 //we need read-only before setter and getter set, because that method depends on flag being set
                 if (null !== ($readOnly = $pElem->attributes()->{'read-only'})) {
                     $pMetadata->readOnly = 'true' === strtolower($readOnly);
                 }
                 $getter = $pElem->attributes()->{'accessor-getter'};
                 $setter = $pElem->attributes()->{'accessor-setter'};
                 $pMetadata->setAccessor((string) ($pElem->attributes()->{'access-type'} ?: $classAccessType), $getter ? (string) $getter : null, $setter ? (string) $setter : null);
                 if (null !== ($inline = $pElem->attributes()->inline)) {
                     $pMetadata->inline = 'true' === strtolower($inline);
                 }
             }
             if (ExclusionPolicy::NONE === (string) $exclusionPolicy && !$isExclude || ExclusionPolicy::ALL === (string) $exclusionPolicy && $isExpose) {
                 $metadata->addPropertyMetadata($pMetadata);
             }
         }
     }
     foreach ($elem->xpath('./callback-method') as $method) {
         if (!isset($method->attributes()->type)) {
             throw new RuntimeException('The type attribute must be set for all callback-method elements.');
         }
         if (!isset($method->attributes()->name)) {
             throw new RuntimeException('The name attribute must be set for all callback-method elements.');
         }
         switch ((string) $method->attributes()->type) {
             case 'pre-serialize':
                 $metadata->addPreSerializeMethod(new MethodMetadata($name, (string) $method->attributes()->name));
                 break;
             case 'post-serialize':
                 $metadata->addPostSerializeMethod(new MethodMetadata($name, (string) $method->attributes()->name));
                 break;
             case 'post-deserialize':
                 $metadata->addPostDeserializeMethod(new MethodMetadata($name, (string) $method->attributes()->name));
                 break;
             case 'handler':
                 if (!isset($method->attributes()->format)) {
                     throw new RuntimeException('The format attribute must be set for "handler" callback methods.');
                 }
                 if (!isset($method->attributes()->direction)) {
                     throw new RuntimeException('The direction attribute must be set for "handler" callback methods.');
                 }
                 $direction = GraphNavigator::parseDirection((string) $method->attributes()->direction);
                 $format = (string) $method->attributes()->format;
                 $metadata->addHandlerCallback($direction, $format, (string) $method->attributes()->name);
                 break;
             default:
                 throw new RuntimeException(sprintf('The type "%s" is not supported.', $method->attributes()->name));
         }
     }
     return $metadata;
 }
 protected function loadMetadataFromFile(\ReflectionClass $class, $file)
 {
     $config = Yaml::parse(file_get_contents($file));
     if (!isset($config[$name = $class->name])) {
         throw new RuntimeException(sprintf('Expected metadata for class %s to be defined in %s.', $class->name, $file));
     }
     $config = $config[$name];
     $metadata = new ClassMetadata($name);
     $metadata->fileResources[] = $file;
     $metadata->fileResources[] = $class->getFileName();
     $exclusionPolicy = isset($config['exclusion_policy']) ? strtoupper($config['exclusion_policy']) : 'NONE';
     $excludeAll = isset($config['exclude']) ? (bool) $config['exclude'] : false;
     $classAccessType = isset($config['access_type']) ? $config['access_type'] : PropertyMetadata::ACCESS_TYPE_PROPERTY;
     $propertiesMetadata = array();
     if (isset($config['accessor_order'])) {
         $metadata->setAccessorOrder($config['accessor_order'], isset($config['custom_accessor_order']) ? $config['custom_accessor_order'] : array());
     }
     if (isset($config['xml_root_name'])) {
         $metadata->xmlRootName = (string) $config['xml_root_name'];
     }
     if (isset($config['discriminator'])) {
         if (isset($config['discriminator']['disabled']) && true === $config['discriminator']['disabled']) {
             $metadata->discriminatorDisabled = true;
         } else {
             if (!isset($config['discriminator']['field_name'])) {
                 throw new RuntimeException('The "field_name" attribute must be set for discriminators.');
             }
             if (!isset($config['discriminator']['map']) || !is_array($config['discriminator']['map'])) {
                 throw new RuntimeException('The "map" attribute must be set, and be an array for discriminators.');
             }
             $metadata->setDiscriminator($config['discriminator']['field_name'], $config['discriminator']['map']);
         }
     }
     if (array_key_exists('virtual_properties', $config)) {
         foreach ($config['virtual_properties'] as $methodName => $propertySettings) {
             if (!$class->hasMethod($methodName)) {
                 throw new RuntimeException('The method ' . $methodName . ' not found in class ' . $class->name);
             }
             $virtualPropertyMetadata = new VirtualPropertyMetadata($name, $methodName);
             $propertiesMetadata[$methodName] = $virtualPropertyMetadata;
             $config['properties'][$methodName] = $propertySettings;
         }
     }
     if (!$excludeAll) {
         foreach ($class->getProperties() as $property) {
             if ($name !== $property->class) {
                 continue;
             }
             $pName = $property->getName();
             $propertiesMetadata[$pName] = new PropertyMetadata($name, $pName);
         }
         foreach ($propertiesMetadata as $pName => $pMetadata) {
             $isExclude = false;
             $isExpose = $pMetadata instanceof VirtualPropertyMetadata;
             if (isset($config['properties'][$pName])) {
                 $pConfig = $config['properties'][$pName];
                 if (isset($pConfig['exclude'])) {
                     $isExclude = (bool) $pConfig['exclude'];
                 }
                 if (isset($pConfig['expose'])) {
                     $isExpose = (bool) $pConfig['expose'];
                 }
                 if (isset($pConfig['since_version'])) {
                     $pMetadata->sinceVersion = (string) $pConfig['since_version'];
                 }
                 if (isset($pConfig['until_version'])) {
                     $pMetadata->untilVersion = (string) $pConfig['until_version'];
                 }
                 if (isset($pConfig['serialized_name'])) {
                     $pMetadata->serializedName = (string) $pConfig['serialized_name'];
                 }
                 if (isset($pConfig['type'])) {
                     $pMetadata->setType((string) $pConfig['type']);
                 }
                 if (isset($pConfig['groups'])) {
                     $pMetadata->groups = $pConfig['groups'];
                 }
                 if (isset($pConfig['xml_list'])) {
                     $pMetadata->xmlCollection = true;
                     $colConfig = $pConfig['xml_list'];
                     if (isset($colConfig['inline'])) {
                         $pMetadata->xmlCollectionInline = (bool) $colConfig['inline'];
                     }
                     if (isset($colConfig['entry_name'])) {
                         $pMetadata->xmlEntryName = (string) $colConfig['entry_name'];
                     }
                 }
                 if (isset($pConfig['xml_map'])) {
                     $pMetadata->xmlCollection = true;
                     $colConfig = $pConfig['xml_map'];
                     if (isset($colConfig['inline'])) {
                         $pMetadata->xmlCollectionInline = (bool) $colConfig['inline'];
                     }
                     if (isset($colConfig['entry_name'])) {
                         $pMetadata->xmlEntryName = (string) $colConfig['entry_name'];
                     }
                     if (isset($colConfig['key_attribute_name'])) {
                         $pMetadata->xmlKeyAttribute = $colConfig['key_attribute_name'];
                     }
                 }
                 if (isset($pConfig['xml_attribute'])) {
                     $pMetadata->xmlAttribute = (bool) $pConfig['xml_attribute'];
                 }
                 if (isset($pConfig['xml_attribute_map'])) {
                     $pMetadata->xmlAttribute = (bool) $pConfig['xml_attribute_map'];
                 }
                 if (isset($pConfig['xml_value'])) {
                     $pMetadata->xmlValue = (bool) $pConfig['xml_value'];
                 }
                 if (isset($pConfig['xml_key_value_pairs'])) {
                     $pMetadata->xmlKeyValuePairs = (bool) $pConfig['xml_key_value_pairs'];
                 }
                 //we need read_only before setter and getter set, because that method depends on flag being set
                 if (isset($pConfig['read_only'])) {
                     $pMetadata->readOnly = (bool) $pConfig['read_only'];
                 }
                 $pMetadata->setAccessor(isset($pConfig['access_type']) ? $pConfig['access_type'] : $classAccessType, isset($pConfig['accessor']['getter']) ? $pConfig['accessor']['getter'] : null, isset($pConfig['accessor']['setter']) ? $pConfig['accessor']['setter'] : null);
                 if (isset($pConfig['inline'])) {
                     $pMetadata->inline = (bool) $pConfig['inline'];
                 }
             }
             if (ExclusionPolicy::NONE === $exclusionPolicy && !$isExclude || ExclusionPolicy::ALL === $exclusionPolicy && $isExpose) {
                 $metadata->addPropertyMetadata($pMetadata);
             }
         }
     }
     if (isset($config['handler_callbacks'])) {
         foreach ($config['handler_callbacks'] as $direction => $formats) {
             foreach ($formats as $format => $methodName) {
                 $direction = GraphNavigator::parseDirection($direction);
                 $metadata->addHandlerCallback($direction, $format, $methodName);
             }
         }
     }
     if (isset($config['callback_methods'])) {
         $cConfig = $config['callback_methods'];
         if (isset($cConfig['pre_serialize'])) {
             $metadata->preSerializeMethods = $this->getCallbackMetadata($class, $cConfig['pre_serialize']);
         }
         if (isset($cConfig['post_serialize'])) {
             $metadata->postSerializeMethods = $this->getCallbackMetadata($class, $cConfig['post_serialize']);
         }
         if (isset($cConfig['post_deserialize'])) {
             $metadata->postDeserializeMethods = $this->getCallbackMetadata($class, $cConfig['post_deserialize']);
         }
     }
     return $metadata;
 }
<?php

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
$metadata = new ClassMetadata('JMS\\Serializer\\Tests\\Fixtures\\Discriminator\\Vehicle');
$metadata->setDiscriminator('type', array('car' => 'JMS\\Serializer\\Tests\\Fixtures\\Discriminator\\Car', 'moped' => 'JMS\\Serializer\\Tests\\Fixtures\\Discriminator\\Moped'));
$km = new PropertyMetadata('JMS\\Serializer\\Tests\\Fixtures\\Discriminator\\Vehicle', 'km');
$km->setType('integer');
$metadata->addPropertyMetadata($km);
return $metadata;