-
-
Notifications
You must be signed in to change notification settings - Fork 585
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
added support for xml-attributes as discriminators #692
Changes from 3 commits
14fadd2
9ba0de2
5d63f75
8d4548d
23348ad
a1f4e04
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?php | ||
|
||
/* | ||
* Copyright 2016 Björn Bösel <[email protected]> | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
namespace JMS\Serializer\Annotation; | ||
|
||
|
||
/** | ||
* @Annotation | ||
* @Target("CLASS") | ||
*/ | ||
class XmlDiscriminator | ||
{ | ||
/** | ||
* @var boolean | ||
*/ | ||
public $attribute = false; | ||
|
||
/** | ||
* @var boolean | ||
*/ | ||
public $cdata = true; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,6 +58,9 @@ class ClassMetadata extends MergeableClassMetadata | |
public $discriminatorMap = array(); | ||
public $discriminatorGroups = array(); | ||
|
||
public $xmlDiscriminatorAttribute = false; | ||
public $xmlDiscriminatorCData = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should it be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. capitalizing CD follows the convention used in PropertyMetadata::$xmlElementCData ... |
||
|
||
public function setDiscriminator($fieldName, array $map, array $groups = array()) | ||
{ | ||
if (empty($fieldName)) { | ||
|
@@ -203,6 +206,7 @@ public function merge(MergeableInterface $object) | |
$this->discriminatorGroups | ||
); | ||
$discriminatorProperty->serializedName = $this->discriminatorFieldName; | ||
$discriminatorProperty->xmlAttribute = $this->xmlDiscriminatorAttribute; | ||
$this->propertyMetadata[$this->discriminatorFieldName] = $discriminatorProperty; | ||
} | ||
|
||
|
@@ -249,6 +253,8 @@ public function serialize() | |
$this->discriminatorGroups, | ||
parent::serialize(), | ||
'discriminatorGroups' => $this->discriminatorGroups, | ||
'xmlDiscriminatorAttribute' => $this->xmlDiscriminatorAttribute, | ||
'xmlDiscriminatorCData' => $this->xmlDiscriminatorCData, | ||
)); | ||
} | ||
|
||
|
@@ -279,6 +285,14 @@ public function unserialize($str) | |
$this->discriminatorGroups = $deserializedData['discriminatorGroups']; | ||
} | ||
|
||
if (isset($deserializedData['xmlDiscriminatorAttribute'])) { | ||
$this->xmlDiscriminatorAttribute = $deserializedData['xmlDiscriminatorAttribute']; | ||
} | ||
|
||
if (isset($deserializedData['xmlDiscriminatorCData'])) { | ||
$this->xmlDiscriminatorCData = $deserializedData['xmlDiscriminatorCData']; | ||
} | ||
|
||
parent::unserialize($parentStr); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ | |
namespace JMS\Serializer\Metadata\Driver; | ||
|
||
use JMS\Serializer\Annotation\Discriminator; | ||
use JMS\Serializer\Annotation\XmlDiscriminator; | ||
use JMS\Serializer\GraphNavigator; | ||
use JMS\Serializer\Annotation\HandlerCallback; | ||
use JMS\Serializer\Annotation\AccessorOrder; | ||
|
@@ -99,6 +100,9 @@ public function loadMetadataForClass(\ReflectionClass $class) | |
} else { | ||
$classMetadata->setDiscriminator($annot->field, $annot->map, $annot->groups); | ||
} | ||
} elseif ($annot instanceof XmlDiscriminator) { | ||
$classMetadata->xmlDiscriminatorAttribute = $annot->attribute; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cast to boolean please |
||
$classMetadata->xmlDiscriminatorCData = $annot->cdata; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cast to boolean please |
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -257,6 +257,15 @@ private function addClassProperties(ClassMetadata $metadata, array $config) | |
$metadata->xmlRootNamespace = (string) $config['xml_root_namespace']; | ||
} | ||
|
||
if (isset($config['xml_discriminator'])) { | ||
if (isset($config['xml_discriminator']['attribute'])) { | ||
$metadata->xmlDiscriminatorAttribute = $config['xml_discriminator']['attribute']; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cast to boolean please |
||
} | ||
if (isset($config['xml_discriminator']['cdata'])) { | ||
$metadata->xmlDiscriminatorCData = $config['xml_discriminator']['cdata']; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cast to boolean please |
||
} | ||
} | ||
|
||
if (array_key_exists('xml_namespaces', $config)) { | ||
|
||
foreach ($config['xml_namespaces'] as $prefix => $uri) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
/* | ||
* Copyright 2016 Björn Bösel <[email protected]> | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
namespace JMS\Serializer\Tests\Fixtures\Discriminator; | ||
|
||
class ObjectWithXmlAttributeDiscriminatorChild extends ObjectWithXmlAttributeDiscriminatorParent | ||
{ | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
/* | ||
* Copyright 2016 Björn Bösel <[email protected]> | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
namespace JMS\Serializer\Tests\Fixtures\Discriminator; | ||
|
||
use JMS\Serializer\Annotation as Serializer; | ||
|
||
/** | ||
* @Serializer\Discriminator(field = "type", map = { | ||
* "child": "JMS\Serializer\Tests\Fixtures\Discriminator\ObjectWithXmlAttributeDiscriminatorChild" | ||
* }) | ||
* @Serializer\XmlDiscriminator(attribute=true, cdata=false) | ||
*/ | ||
class ObjectWithXmlAttributeDiscriminatorParent | ||
{ | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?php | ||
|
||
use JMS\Serializer\Metadata\ClassMetadata; | ||
use JMS\Serializer\Metadata\PropertyMetadata; | ||
|
||
$metadata = new ClassMetadata('JMS\Serializer\Tests\Fixtures\Discriminator\ObjectWithXmlAttributeDiscriminatorParent'); | ||
$metadata->setDiscriminator('type', array( | ||
'child' => 'JMS\Serializer\Tests\Fixtures\Discriminator\ObjectWithXmlAttributeDiscriminatorChild' | ||
)); | ||
$metadata->xmlDiscriminatorAttribute = true; | ||
$metadata->xmlDiscriminatorCData = false; | ||
return $metadata; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<serializer> | ||
<class name="JMS\Serializer\Tests\Fixtures\Discriminator\ObjectWithXmlAttributeDiscriminatorParent" | ||
discriminator-field-name="type" | ||
xml-discriminator-attribute="true" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is this attribute (i mean There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry, forgot to remove that one... |
||
> | ||
<discriminator-class value="child">JMS\Serializer\Tests\Fixtures\Discriminator\ObjectWithXmlAttributeDiscriminatorChild</discriminator-class> | ||
<xml-discriminator attribute="true" cdata="false" /> | ||
</class> | ||
</serializer> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
JMS\Serializer\Tests\Fixtures\Discriminator\ObjectWithXmlAttributeDiscriminatorParent: | ||
discriminator: | ||
field_name: type | ||
map: | ||
child: JMS\Serializer\Tests\Fixtures\Discriminator\ObjectWithXmlAttributeDiscriminatorChild | ||
xml_discriminator: | ||
attribute: true | ||
cdata: false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about having a structure as:
this is not a big deal, but is just to keep consistency with the current YAML metadata format. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having the YAML format being wildly different to annotations and xml feels odd to me, but if you insist, i will change it... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My idea is just to keep it consistent. I would like to keep consistency within a format mainly. Since XML and YAML formats have already differences, and users use only one of them, will try to keep them consistent with the rest of the format itself. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ | |
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy; | ||
use JMS\Serializer\SerializationContext; | ||
use JMS\Serializer\Serializer; | ||
use JMS\Serializer\Tests\Fixtures\Discriminator\ObjectWithXmlAttributeDiscriminatorParent; | ||
use JMS\Serializer\Tests\Fixtures\InvalidUsageOfXmlValue; | ||
use JMS\Serializer\Exception\InvalidArgumentException; | ||
use JMS\Serializer\Tests\Fixtures\PersonCollection; | ||
|
@@ -40,6 +41,7 @@ | |
use JMS\Serializer\Tests\Fixtures\ObjectWithNamespacesAndList; | ||
use JMS\Serializer\XmlSerializationVisitor; | ||
use PhpCollection\Map; | ||
use JMS\Serializer\Tests\Fixtures\Discriminator\ObjectWithXmlAttributeDiscriminatorChild; | ||
|
||
class XmlSerializationTest extends BaseSerializationTest | ||
{ | ||
|
@@ -361,6 +363,20 @@ public function testWithoutFormatedOutputByXmlSerializationVisitor() | |
$this->assertXmlStringEqualsXmlString($this->getContent('simple_class_object_minified'), $stringXml); | ||
} | ||
|
||
public function testDiscriminatorAsXmlAttribute() | ||
{ | ||
$xml = simplexml_load_string($this->serialize(new ObjectWithXmlAttributeDiscriminatorChild())); | ||
$this->assertEquals('type="child"', trim($xml->xpath('//result/@type')[0]->saveXML())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of "re-loading" the xml into a simplexml object, why not re-use the $xml = $this->serialize(new ObjectWithXmlAttributeDiscriminatorChild());
$this->assertEquals($this->getContent('xml_discriminator_attribute'), $xml);
$this->assertInstanceOf(
ObjectWithXmlAttributeDiscriminatorChild::class,
$this->deserialize(
$xml,
ObjectWithXmlAttributeDiscriminatorParent::class
)
); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would be the benefit when comparing to a predefined xml? I assumed the test should only cover if the discriminator is rendered as an attribute, while other aspects of xml-generation (whitespace, xml-header, if the tag is rendered as self-closing...) should not break the test, which might happen when comparing to predefined xml.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an interesting topic about testing, and how much we want to do "unit" testing... Your test currently tests only of the type is rendered as attribute... but what if for some other change, make the type to be rendered using both strategies.. I mean as attribute and as element? This test will not detect it. Of course, testing the whole xml content, has some drawbacks, as example will give some "false" failures if we decide to change indentation or other format specific differences... that generally should not make fail your testcase. To be honest, I prefer to have a false failure, instead of having a not detected failure. (this means less "unit" testing, and going more in direction of functional or integration tests... (event if the border between this definitions is really blurry) What is your opinion on it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally and totally subjective, i like to have my tests represent actual requirements and i like to be able to treat them as much. When working with foreign code, i can not determine of a false failure is indeed false, or if there is an actual requirement... But since in this case, it is pretty obvious, i feel okay doing it your way. |
||
|
||
$this->assertInstanceOf( | ||
ObjectWithXmlAttributeDiscriminatorChild::class, | ||
$this->deserialize( | ||
$xml->asXML(), | ||
ObjectWithXmlAttributeDiscriminatorParent::class | ||
) | ||
); | ||
} | ||
|
||
private function xpathFirstToString(\SimpleXMLElement $xml, $xpath) | ||
{ | ||
$nodes = $xml->xpath($xpath); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i will put this statement before the previous one