Browse Source

Support virtual-property node for XmlDriver, tests

Aleksandr Klimenkov 13 years ago
parent
commit
e90b0a414a

+ 1 - 1
Annotation/Inline.php

@@ -20,7 +20,7 @@ namespace JMS\SerializerBundle\Annotation;
 
 /**
  * @Annotation
- * @Target({"PROPERTY"})
+ * @Target({"PROPERTY","METHOD"})
  */
 final class Inline
 {

+ 1 - 1
Annotation/Since.php

@@ -20,7 +20,7 @@ namespace JMS\SerializerBundle\Annotation;
 
 /**
  * @Annotation
- * @Target("PROPERTY")
+ * @Target({"PROPERTY", "METHOD"})
  */
 final class Since extends Version
 {

+ 1 - 1
Annotation/Until.php

@@ -20,7 +20,7 @@ namespace JMS\SerializerBundle\Annotation;
 
 /**
  * @Annotation
- * @Target("PROPERTY")
+ * @Target({"PROPERTY", "METHOD"})
  */
 final class Until extends Version
 {

+ 1 - 1
Annotation/XmlList.php

@@ -20,7 +20,7 @@ namespace JMS\SerializerBundle\Annotation;
 
 /**
  * @Annotation
- * @Target("PROPERTY")
+ * @Target({"PROPERTY","METHOD"})
  */
 final class XmlList extends XmlCollection
 {

+ 1 - 1
Annotation/XmlMap.php

@@ -22,7 +22,7 @@ use JMS\SerializerBundle\Exception\InvalidArgumentException;
 
 /**
  * @Annotation
- * @Target("PROPERTY")
+ * @Target({"PROPERTY","METHOD"})
  */
 final class XmlMap extends XmlCollection
 {

+ 37 - 5
Metadata/Driver/XmlDriver.php

@@ -22,6 +22,7 @@ use JMS\SerializerBundle\Exception\RuntimeException;
 use JMS\SerializerBundle\Exception\XmlErrorException;
 use JMS\SerializerBundle\Annotation\ExclusionPolicy;
 use JMS\SerializerBundle\Metadata\PropertyMetadata;
+use JMS\SerializerBundle\Metadata\VirtualPropertyMetadata;
 use Metadata\MethodMetadata;
 use JMS\SerializerBundle\Metadata\ClassMetadata;
 use Metadata\Driver\AbstractFileDriver;
@@ -50,6 +51,9 @@ class XmlDriver extends AbstractFileDriver
         $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'}));
         }
@@ -58,19 +62,47 @@ class XmlDriver extends AbstractFileDriver
             $metadata->xmlRootName = (string) $xmlRootName;
         }
 
+        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.');
+            }
+            if (!isset($method->attributes()->name)) {
+                throw new RuntimeException('The name attribute must be set for all virtual-property elements.');
+            }
+            
+            if ( !$class->hasMethod( $method->attributes()->method ) ) {
+                throw new RuntimeException('The method '.$method->attributes()->method.' not found in class ' . $class->name);
+            }
+            
+            $virtualPropertyMetadata = new VirtualPropertyMetadata( $name, (string)$method->attributes()->name );
+            $virtualPropertyMetadata->getter = (string) $method->attributes()->method;
+            
+            $propertiesMetadata[] = $virtualPropertyMetadata;
+            $propertiesNodes[] = $method;
+        }
+        
         if (!$excludeAll) {
+            
             foreach ($class->getProperties() as $property) {
                 if ($name !== $property->getDeclaringClass()->getName()) {
                     continue;
                 }
+                
+                $propertiesMetadata[] = new PropertyMetadata($name, $pName = $property->getName());
+                $pElems = $elem->xpath("./property[@name = '".$pName."']");
+                
+                $propertiesNodes[] = $pElems ? reset( $pElems ) : null;
+            }
+            
+            foreach ($propertiesMetadata as $propertyKey => $pMetadata) {
+                if ($name !== $property->getDeclaringClass()->getName()) {
+                    continue;
+                }
 
-                $pMetadata = new PropertyMetadata($name, $pName = $property->getName());
                 $isExclude = $isExpose = false;
 
-                $pElems = $elem->xpath("./property[@name = '".$pName."']");
-
-                if ($pElems) {
-                    $pElem = reset($pElems);
+                $pElem = $propertiesNodes[$propertyKey];
+                if (!empty( $pElem )) {
 
                     if (null !== $exclude = $pElem->attributes()->exclude) {
                         $isExclude = 'true' === strtolower($exclude);

+ 1 - 1
Serializer/XmlSerializationVisitor.php

@@ -167,7 +167,7 @@ class XmlSerializationVisitor extends AbstractSerializationVisitor
 
         if (($metadata->xmlValue && $this->currentNode->childNodes->length > 0)
             || (!$metadata->xmlValue && $this->hasValue)) {
-            throw new \RuntimeException(sprintf('If you make use of @XmlValue, all other properties in the class must have the @XmlAttribute annotation. Invalid usage detected in class %s.', $metadata->reflection->class));
+            throw new \RuntimeException(sprintf('If you make use of @XmlValue, all other properties in the class must have the @XmlAttribute annotation. Invalid usage detected in class %s.', $metadata->class));
         }
 
         if ($metadata->xmlValue) {

+ 55 - 0
Tests/Fixtures/ObjectWithVersionedVirtualProperties.php

@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
+ *
+ * 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\SerializerBundle\Tests\Fixtures;
+
+use JMS\SerializerBundle\Annotation\Groups;
+use JMS\SerializerBundle\Annotation\XmlValue;
+use JMS\SerializerBundle\Annotation\XmlAttribute;
+use JMS\SerializerBundle\Annotation\XmlList;
+use JMS\SerializerBundle\Annotation\XmlMap;
+use JMS\SerializerBundle\Annotation\Since;
+use JMS\SerializerBundle\Annotation\Until;
+use JMS\SerializerBundle\Annotation\VirtualProperty;
+
+class ObjectWithVersionedVirtualProperties
+{
+
+    /**
+     *
+     * @Groups({"versions"})
+     * @VirtualProperty("low")
+     * @Until("8")
+     */
+    public function getVirualLowValue()
+    {
+        return 1;
+    }
+    
+    /**
+     *
+     * @Groups({"versions"})
+     * @VirtualProperty("high")
+     * @Since("6")
+     */
+    public function getVirualHighValue()
+    {
+        return 8;
+    }
+
+}

+ 52 - 0
Tests/Fixtures/ObjectWithVirtualXmlProperties.php

@@ -21,6 +21,10 @@ namespace JMS\SerializerBundle\Tests\Fixtures;
 use JMS\SerializerBundle\Annotation\Groups;
 use JMS\SerializerBundle\Annotation\XmlValue;
 use JMS\SerializerBundle\Annotation\XmlAttribute;
+use JMS\SerializerBundle\Annotation\XmlList;
+use JMS\SerializerBundle\Annotation\XmlMap;
+use JMS\SerializerBundle\Annotation\Since;
+use JMS\SerializerBundle\Annotation\Until;
 use JMS\SerializerBundle\Annotation\VirtualProperty;
 
 class ObjectWithVirtualXmlProperties
@@ -47,4 +51,52 @@ class ObjectWithVirtualXmlProperties
     {
         return 'xml-value';
     }
+    
+    /**
+     *
+     * @Groups({"list"})
+     * @VirtualProperty("list")
+     * @XmlList(inline = true, entry = "val")
+     */
+    public function getVirualXmlList()
+    {
+        return array('One','Two');
+    }
+
+    /**
+     *
+     * @Groups({"map"})
+     * @VirtualProperty("map")
+     * @XmlMap(keyAttribute = "key")
+     */
+    public function getVirualXmlMap()
+    {
+        return array(
+            'key-one'   => 'One',
+            'key-two'   => 'Two'
+        );
+    }
+    
+    /**
+     *
+     * @Groups({"versions"})
+     * @VirtualProperty("low")
+     * @Until("8")
+     */
+    public function getVirualLowValue()
+    {
+        return 1;
+    }
+    
+    /**
+     *
+     * @Groups({"versions"})
+     * @VirtualProperty("hight")
+     * @Since("8")
+     */
+    public function getVirualHighValue()
+    {
+        return 8;
+    }
+
 }

+ 17 - 0
Tests/Metadata/Driver/XmlDriverTest.php

@@ -20,6 +20,8 @@ namespace JMS\SerializerBundle\Tests\Metadata\Driver;
 
 use Metadata\Driver\FileLocator;
 use JMS\SerializerBundle\Metadata\PropertyMetadata;
+use JMS\SerializerBundle\Metadata\VirtualPropertyMetadata;
+
 use JMS\SerializerBundle\Metadata\Driver\XmlDriver;
 
 class XmlDriverTest extends BaseDriverTest
@@ -81,6 +83,21 @@ class XmlDriverTest extends BaseDriverTest
 
         $this->assertEquals($p, $m->propertyMetadata['name']);
     }
+    
+    public function testVirtualProperty()
+    {
+        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\SerializerBundle\Tests\Fixtures\ObjectWithVirtualProperties'));
+
+        $this->assertArrayHasKey('existField', $m->propertyMetadata);
+        $this->assertArrayHasKey('foo', $m->propertyMetadata);
+        $this->assertArrayHasKey('prop_name', $m->propertyMetadata);
+        
+        $p = new VirtualPropertyMetadata($m->name, 'foo');
+        $p->getter = 'getVirtualValue';
+
+        $this->assertEquals($p, $m->propertyMetadata['foo']);
+    }
+    
 
     protected function getDriver()
     {

+ 8 - 0
Tests/Metadata/Driver/xml/ObjectWithVirtualProperties.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<serializer>
+    <class name="JMS\SerializerBundle\Tests\Fixtures\ObjectWithVirtualProperties">
+        <property name="existField" type="string"/>
+        <virtual-property name="foo" method="getVirtualValue"/>
+        <virtual-property name="prop_name" method="getVirtualSerializedValue"/>
+    </class>
+</serializer>

+ 14 - 0
Tests/Serializer/BaseSerializationTest.php

@@ -70,6 +70,7 @@ use JMS\SerializerBundle\Serializer\Naming\CamelCaseNamingStrategy;
 use JMS\SerializerBundle\Serializer\Naming\SerializedNameAnnotationStrategy;
 use JMS\SerializerBundle\Serializer\JsonSerializationVisitor;
 use JMS\SerializerBundle\Serializer\Serializer;
+use JMS\SerializerBundle\Tests\Fixtures\ObjectWithVersionedVirtualProperties;
 
 abstract class BaseSerializationTest extends \PHPUnit_Framework_TestCase
 {
@@ -444,6 +445,19 @@ abstract class BaseSerializationTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($this->getContent('virtual_properties'), $this->serialize(new ObjectWithVirtualProperties()));
     }
 
+    public function testVirtualVersions() {
+        $serializer = $this->getSerializer();
+        
+        $serializer->setVersion(2);
+        $this->assertEquals($this->getContent('virtual_properties_low'), $serializer->serialize(new ObjectWithVersionedVirtualProperties(), $this->getFormat()));
+        
+        $serializer->setVersion(7);
+        $this->assertEquals($this->getContent('virtual_properties_all'), $serializer->serialize(new ObjectWithVersionedVirtualProperties(), $this->getFormat()));
+
+        $serializer->setVersion(9);
+        $this->assertEquals($this->getContent('virtual_properties_high'), $serializer->serialize(new ObjectWithVersionedVirtualProperties(), $this->getFormat()));
+    }
+    
     abstract protected function getContent($key);
     abstract protected function getFormat();
 

+ 3 - 0
Tests/Serializer/JsonSerializationTest.php

@@ -65,6 +65,9 @@ class JsonSerializationTest extends BaseSerializationTest
             $outputs['groups_foo'] = '{"foo":"foo","foobar":"foobar"}';
             $outputs['groups_foobar'] = '{"foo":"foo","foobar":"foobar","bar":"bar"}';
             $outputs['virtual_properties'] = '{"test":"other-name","exist_field":"value","foo":"value"}';
+            $outputs['virtual_properties_low'] = '{"low":1}';
+            $outputs['virtual_properties_high'] = '{"high":8}';
+            $outputs['virtual_properties_all'] = '{"low":1,"high":8}';
         }
 
         if (!isset($outputs[$key])) {

+ 12 - 0
Tests/Serializer/XmlSerializationTest.php

@@ -62,7 +62,19 @@ class XmlSerializationTest extends BaseSerializationTest
         $serializer->setGroups(array('values'));
         $this->assertEquals($this->getContent('virtual_values'), $serializer->serialize(new ObjectWithVirtualXmlProperties(),'xml'));
     }
+    
+    public function testVirtualXmlList() {
+        $serializer = $this->getSerializer();
+        $serializer->setGroups(array('list'));
+        $this->assertEquals($this->getContent('virtual_properties_list'), $serializer->serialize(new ObjectWithVirtualXmlProperties(),'xml'));
+    }
 
+    public function testVirtualXmlMap() {
+        $serializer = $this->getSerializer();
+        $serializer->setGroups(array('map'));
+        $this->assertEquals($this->getContent('virtual_properties_map'), $serializer->serialize(new ObjectWithVirtualXmlProperties(),'xml'));
+    }
+    
     protected function getContent($key)
     {
         if (!file_exists($file = __DIR__.'/xml/'.$key.'.xml')) {

+ 5 - 0
Tests/Serializer/xml/virtual_properties_all.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result>
+  <low>1</low>
+  <high>8</high>
+</result>

+ 4 - 0
Tests/Serializer/xml/virtual_properties_high.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result>
+  <high>8</high>
+</result>

+ 5 - 0
Tests/Serializer/xml/virtual_properties_list.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result>
+  <val><![CDATA[One]]></val>
+  <val><![CDATA[Two]]></val>
+</result>

+ 4 - 0
Tests/Serializer/xml/virtual_properties_low.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result>
+  <low>1</low>
+</result>

+ 7 - 0
Tests/Serializer/xml/virtual_properties_map.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<result>
+  <map>
+    <entry key="key-one"><![CDATA[One]]></entry>
+    <entry key="key-two"><![CDATA[Two]]></entry>
+  </map>
+</result>

+ 2 - 0
Tests/Serializer/yml/virtual_properties_all.yml

@@ -0,0 +1,2 @@
+low: 1
+high: 8

+ 1 - 0
Tests/Serializer/yml/virtual_properties_high.yml

@@ -0,0 +1 @@
+high: 8

+ 1 - 0
Tests/Serializer/yml/virtual_properties_low.yml

@@ -0,0 +1 @@
+low: 1