Browse Source

Added support for ReadOnly annotation

Ruud Kamphuis 13 years ago
parent
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\ExclusionPolicy;
 use JMS\SerializerBundle\Annotation\Inline;
+use JMS\SerializerBundle\Annotation\ReadOnly;
 use JMS\SerializerBundle\Metadata\ClassMetadata;
 use JMS\SerializerBundle\Metadata\PropertyMetadata;
 use Metadata\Driver\DriverInterface;
@@ -123,6 +124,8 @@ class AnnotationDriver implements DriverInterface
                         $propertyMetadata->setGroups($annot->names);
                     } else if ($annot instanceof Inline) {
                         $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) {
                         $pMetadata->inline = 'true' === strtolower($inline);
                     }
+
+                    if (null !== $readOnly = $pElem->attributes()->{'read-only'}) {
+                        $pMetadata->readOnly = 'true' === strtolower($readOnly);
+                    }
                 }
 
                 if ((ExclusionPolicy::NONE === (string)$exclusionPolicy && !$isExclude)

+ 4 - 0
Metadata/Driver/YamlDriver.php

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

+ 3 - 0
Metadata/PropertyMetadata.php

@@ -38,6 +38,7 @@ class PropertyMetadata extends BasePropertyMetadata
     public $getter;
     public $setter;
     public $inline = false;
+    public $readOnly = false;
 
     public function setAccessor($type, $getter = null, $setter = null)
     {
@@ -83,6 +84,7 @@ class PropertyMetadata extends BasePropertyMetadata
             $this->getter,
             $this->setter,
             $this->inline,
+            $this->readOnly,
             parent::serialize(),
         ));
     }
@@ -103,6 +105,7 @@ class PropertyMetadata extends BasePropertyMetadata
             $this->getter,
             $this->setter,
             $this->inline,
+            $this->readOnly,
             $parentStr
         ) = 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
 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
 ~~~~~~~~~~~~~
 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-setter="setSomeProperty"
                       inline="true"
+                      read-only="true"
             >
                 <!-- You can also specify the type as element which is necessary if
                      your type contains "<" or ">" characters. -->
@@ -619,6 +625,7 @@ YAML Reference
                 until_version: 1.1
                 xml_attribute: true
                 inline: true
+                read_only: true
                 xml_list:
                     inline: true
                     entry_name: foo

+ 4 - 0
Serializer/GenericDeserializationVisitor.php

@@ -173,6 +173,10 @@ abstract class GenericDeserializationVisitor extends AbstractDeserializationVisi
             return;
         }
 
+        if ($metadata->readOnly) {
+	        return;
+	    }
+
         if (!$metadata->type) {
             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)
     {
         $name = $this->namingStrategy->translateName($metadata);
-
+        
+        if ($metadata->readOnly) {
+	        return;
+	    }
+	
         if (!$metadata->type) {
             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\Tests\Fixtures\Comment;
 use JMS\SerializerBundle\Tests\Fixtures\Author;
+use JMS\SerializerBundle\Tests\Fixtures\AuthorReadOnly;
 use JMS\SerializerBundle\Tests\Fixtures\BlogPost;
 use JMS\SerializerBundle\Tests\Fixtures\ObjectWithLifecycleCallbacks;
 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()
     {
         $price = new Price(3);

+ 1 - 0
Tests/Serializer/JsonSerializationTest.php

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