Ver código fonte

Added support for ReadOnly annotation

Ruud Kamphuis 13 anos atrás
pai
commit
33568ff707

+ 27 - 0
Annotation/ReadOnly.php

@@ -0,0 +1,27 @@
+<?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\Annotation;
+
+/**
+ * @Annotation
+ * @Target("PROPERTY")
+ */
+final class ReadOnly
+{
+}

+ 3 - 0
Metadata/Driver/AnnotationDriver.php

@@ -44,6 +44,7 @@ use JMS\SerializerBundle\Annotation\Until;
 use JMS\SerializerBundle\Annotation\Since;
 use JMS\SerializerBundle\Annotation\Since;
 use JMS\SerializerBundle\Annotation\ExclusionPolicy;
 use JMS\SerializerBundle\Annotation\ExclusionPolicy;
 use JMS\SerializerBundle\Annotation\Inline;
 use JMS\SerializerBundle\Annotation\Inline;
+use JMS\SerializerBundle\Annotation\ReadOnly;
 use JMS\SerializerBundle\Metadata\ClassMetadata;
 use JMS\SerializerBundle\Metadata\ClassMetadata;
 use JMS\SerializerBundle\Metadata\PropertyMetadata;
 use JMS\SerializerBundle\Metadata\PropertyMetadata;
 use Metadata\Driver\DriverInterface;
 use Metadata\Driver\DriverInterface;
@@ -123,6 +124,8 @@ class AnnotationDriver implements DriverInterface
                         $propertyMetadata->setGroups($annot->names);
                         $propertyMetadata->setGroups($annot->names);
                     } else if ($annot instanceof Inline) {
                     } else if ($annot instanceof Inline) {
                         $propertyMetadata->inline = true;
                         $propertyMetadata->inline = true;
+                   	} else if ($annot instanceof ReadOnly) {
+                        $propertyMetadata->readOnly = true;
                     }
                     }
                 }
                 }
 
 

+ 4 - 0
Metadata/Driver/XmlDriver.php

@@ -147,6 +147,10 @@ class XmlDriver extends AbstractFileDriver
                     if (null !== $inline = $pElem->attributes()->inline) {
                     if (null !== $inline = $pElem->attributes()->inline) {
                         $pMetadata->inline = 'true' === strtolower($inline);
                         $pMetadata->inline = 'true' === strtolower($inline);
                     }
                     }
+
+                    if (null !== $readOnly = $pElem->attributes()->{'read-only'}) {
+                        $pMetadata->readOnly = 'true' === strtolower($readOnly);
+                    }
                 }
                 }
 
 
                 if ((ExclusionPolicy::NONE === (string)$exclusionPolicy && !$isExclude)
                 if ((ExclusionPolicy::NONE === (string)$exclusionPolicy && !$isExclude)

+ 4 - 0
Metadata/Driver/YamlDriver.php

@@ -133,6 +133,10 @@ class YamlDriver extends AbstractFileDriver
                     if (isset($pConfig['inline'])) {
                     if (isset($pConfig['inline'])) {
                         $pMetadata->inline = (Boolean) $pConfig['inline'];
                         $pMetadata->inline = (Boolean) $pConfig['inline'];
                     }
                     }
+
+                    if (isset($pConfig['read_only'])) {
+                        $pMetadata->readOnly = (Boolean) $pConfig['read_only'];
+                    }
                 }
                 }
                 if ((ExclusionPolicy::NONE === $exclusionPolicy && !$isExclude)
                 if ((ExclusionPolicy::NONE === $exclusionPolicy && !$isExclude)
                 || (ExclusionPolicy::ALL === $exclusionPolicy && $isExpose)) {
                 || (ExclusionPolicy::ALL === $exclusionPolicy && $isExpose)) {

+ 3 - 0
Metadata/PropertyMetadata.php

@@ -38,6 +38,7 @@ class PropertyMetadata extends BasePropertyMetadata
     public $getter;
     public $getter;
     public $setter;
     public $setter;
     public $inline = false;
     public $inline = false;
+    public $readOnly = false;
 
 
     public function setAccessor($type, $getter = null, $setter = null)
     public function setAccessor($type, $getter = null, $setter = null)
     {
     {
@@ -83,6 +84,7 @@ class PropertyMetadata extends BasePropertyMetadata
             $this->getter,
             $this->getter,
             $this->setter,
             $this->setter,
             $this->inline,
             $this->inline,
+            $this->readOnly,
             parent::serialize(),
             parent::serialize(),
         ));
         ));
     }
     }
@@ -103,6 +105,7 @@ class PropertyMetadata extends BasePropertyMetadata
             $this->getter,
             $this->getter,
             $this->setter,
             $this->setter,
             $this->inline,
             $this->inline,
+            $this->readOnly,
             $parentStr
             $parentStr
         ) = unserialize($str);
         ) = unserialize($str);
 
 

+ 7 - 0
Resources/doc/index.rst

@@ -341,6 +341,11 @@ should be inlined.
 objects with this annotation. Also, AccessorOrder will be using the name of the property
 objects with this annotation. Also, AccessorOrder will be using the name of the property
 to determine the order.
 to determine the order.
 
 
+@ReadOnly
+~~~~~~~~
+This annotation can be defined on a property to indicate that the data of the property
+is read only and cannot be set during deserialization.
+
 @PreSerialize
 @PreSerialize
 ~~~~~~~~~~~~~
 ~~~~~~~~~~~~~
 This annotation can be defined on a method which is supposed to be called before
 This annotation can be defined on a method which is supposed to be called before
@@ -583,6 +588,7 @@ XML Reference
                       accessor-getter="getSomeProperty"
                       accessor-getter="getSomeProperty"
                       accessor-setter="setSomeProperty"
                       accessor-setter="setSomeProperty"
                       inline="true"
                       inline="true"
+                      read-only="true"
             >
             >
                 <!-- You can also specify the type as element which is necessary if
                 <!-- You can also specify the type as element which is necessary if
                      your type contains "<" or ">" characters. -->
                      your type contains "<" or ">" characters. -->
@@ -619,6 +625,7 @@ YAML Reference
                 until_version: 1.1
                 until_version: 1.1
                 xml_attribute: true
                 xml_attribute: true
                 inline: true
                 inline: true
+                read_only: true
                 xml_list:
                 xml_list:
                     inline: true
                     inline: true
                     entry_name: foo
                     entry_name: foo

+ 4 - 0
Serializer/GenericDeserializationVisitor.php

@@ -173,6 +173,10 @@ abstract class GenericDeserializationVisitor extends AbstractDeserializationVisi
             return;
             return;
         }
         }
 
 
+        if ($metadata->readOnly) {
+	        return;
+	    }
+
         if (!$metadata->type) {
         if (!$metadata->type) {
             throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->getDeclaringClass()->getName(), $metadata->name));
             throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->getDeclaringClass()->getName(), $metadata->name));
         }
         }

+ 5 - 1
Serializer/XmlDeserializationVisitor.php

@@ -196,7 +196,11 @@ class XmlDeserializationVisitor extends AbstractDeserializationVisitor
     public function visitProperty(PropertyMetadata $metadata, $data)
     public function visitProperty(PropertyMetadata $metadata, $data)
     {
     {
         $name = $this->namingStrategy->translateName($metadata);
         $name = $this->namingStrategy->translateName($metadata);
-
+        
+        if ($metadata->readOnly) {
+	        return;
+	    }
+	
         if (!$metadata->type) {
         if (!$metadata->type) {
             throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->getDeclaringClass()->getName(), $metadata->name));
             throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->getDeclaringClass()->getName(), $metadata->name));
         }
         }

+ 56 - 0
Tests/Fixtures/AuthorReadOnly.php

@@ -0,0 +1,56 @@
+<?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\SerializedName;
+use JMS\SerializerBundle\Annotation\Type;
+use JMS\SerializerBundle\Annotation\XmlRoot;
+use JMS\SerializerBundle\Annotation\ReadOnly;
+
+/** @XmlRoot("author") */
+class AuthorReadOnly
+{
+    /**
+     * @ReadOnly
+     * @SerializedName("id")
+     */
+    private $id;
+
+    /**
+     * @Type("string")
+     * @SerializedName("full_name")
+     */
+    private $name;
+
+    public function __construct($id, $name)
+    {
+        $this->id = $id;
+        $this->name = $name;
+    }
+
+	public function getId()
+    {
+        return $this->id;
+    }
+
+    public function getName()
+    {
+        return $this->name;
+    }
+}

+ 13 - 0
Tests/Serializer/BaseSerializationTest.php

@@ -52,6 +52,7 @@ use JMS\SerializerBundle\Serializer\Handler\ConstraintViolationHandler;
 use JMS\SerializerBundle\Serializer\Handler\DoctrineProxyHandler;
 use JMS\SerializerBundle\Serializer\Handler\DoctrineProxyHandler;
 use JMS\SerializerBundle\Tests\Fixtures\Comment;
 use JMS\SerializerBundle\Tests\Fixtures\Comment;
 use JMS\SerializerBundle\Tests\Fixtures\Author;
 use JMS\SerializerBundle\Tests\Fixtures\Author;
+use JMS\SerializerBundle\Tests\Fixtures\AuthorReadOnly;
 use JMS\SerializerBundle\Tests\Fixtures\BlogPost;
 use JMS\SerializerBundle\Tests\Fixtures\BlogPost;
 use JMS\SerializerBundle\Tests\Fixtures\ObjectWithLifecycleCallbacks;
 use JMS\SerializerBundle\Tests\Fixtures\ObjectWithLifecycleCallbacks;
 use JMS\SerializerBundle\Tests\Fixtures\CircularReferenceParent;
 use JMS\SerializerBundle\Tests\Fixtures\CircularReferenceParent;
@@ -198,6 +199,18 @@ abstract class BaseSerializationTest extends \PHPUnit_Framework_TestCase
         }
         }
     }
     }
 
 
+	public function testReadOnly()
+    {
+        $author = new AuthorReadOnly(123, 'Ruud Kamphuis');
+        $this->assertEquals($this->getContent('readonly'), $this->serialize($author));
+
+        if ($this->hasDeserializer()) {
+            $deserialized = $this->deserialize($this->getContent('readonly'), get_class($author));
+            $this->assertEquals(null, $this->getField($deserialized, 'id'));
+            $this->assertEquals('Ruud Kamphuis', $this->getField($deserialized, 'name'));
+        }
+    }
+
     public function testPrice()
     public function testPrice()
     {
     {
         $price = new Price(3);
         $price = new Price(3);

+ 1 - 0
Tests/Serializer/JsonSerializationTest.php

@@ -28,6 +28,7 @@ class JsonSerializationTest extends BaseSerializationTest
         static $outputs = array();
         static $outputs = array();
 
 
         if (!$outputs) {
         if (!$outputs) {
+	        $outputs['readonly'] = '{"id":123,"full_name":"Ruud Kamphuis"}';
             $outputs['string'] = '"foo"';
             $outputs['string'] = '"foo"';
             $outputs['boolean_true'] = 'true';
             $outputs['boolean_true'] = 'true';
             $outputs['boolean_false'] = 'false';
             $outputs['boolean_false'] = 'false';

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

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<author>
+  <id>123</id>
+  <full_name><![CDATA[Ruud Kamphuis]]></full_name>
+</author>

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

@@ -0,0 +1,2 @@
+id: 123
+full_name: 'Ruud Kamphuis'