Jelajahi Sumber

Per class read only

Asmir Mustafic 11 tahun lalu
induk
melakukan
7701e28d0f

+ 1 - 0
doc/reference/yml_reference.rst

@@ -7,6 +7,7 @@ YAML Reference
         exclusion_policy: ALL
         xml_root_name: foobar
         exclude: true
+        read_only: false
         access_type: public_method # defaults to property
         accessor_order: custom
         custom_accessor_order: [propertyName1, propertyName2, ..., propertyNameN]

+ 1 - 1
src/JMS/Serializer/Annotation/ReadOnly.php

@@ -20,7 +20,7 @@ namespace JMS\Serializer\Annotation;
 
 /**
  * @Annotation
- * @Target("PROPERTY")
+ * @Target({"CLASS","PROPERTY"})
  */
 final class ReadOnly
 {

+ 4 - 1
src/JMS/Serializer/Metadata/Driver/AnnotationDriver.php

@@ -76,6 +76,7 @@ class AnnotationDriver implements DriverInterface
         $exclusionPolicy = 'NONE';
         $excludeAll = false;
         $classAccessType = PropertyMetadata::ACCESS_TYPE_PROPERTY;
+        $readOnlyClass = false;
         foreach ($this->reader->getClassAnnotations($class) as $annot) {
             if ($annot instanceof ExclusionPolicy) {
                 $exclusionPolicy = $annot->policy;
@@ -87,6 +88,8 @@ class AnnotationDriver implements DriverInterface
                 $excludeAll = true;
             } elseif ($annot instanceof AccessType) {
                 $classAccessType = $annot->type;
+            } elseif ($annot instanceof ReadOnly) {
+                $readOnlyClass = true;
             } elseif ($annot instanceof AccessorOrder) {
                 $classMetadata->setAccessorOrder($annot->order, $annot->custom);
             } elseif ($annot instanceof Discriminator) {
@@ -137,7 +140,7 @@ class AnnotationDriver implements DriverInterface
             }
 
             foreach ($propertiesMetadata as $propertyKey => $propertyMetadata) {
-
+                $propertyMetadata->readOnly = $propertyMetadata->readOnly || $readOnlyClass;
                 $isExclude = false;
                 $isExpose = $propertyMetadata instanceof VirtualPropertyMetadata;
                 $accessType = $classAccessType;

+ 4 - 2
src/JMS/Serializer/Metadata/Driver/XmlDriver.php

@@ -63,6 +63,8 @@ class XmlDriver extends AbstractFileDriver
             $metadata->xmlRootName = (string) $xmlRootName;
         }
 
+        $readOnlyClass = !!strtolower($elem->attributes()->{'read-only'});
+
         $discriminatorFieldName = (string) $elem->attributes()->{'discriminator-field-name'};
         $discriminatorMap = array();
         foreach ($elem->xpath('./discriminator-class') as $entry) {
@@ -154,7 +156,7 @@ class XmlDriver extends AbstractFileDriver
                     if (null !== $groups = $pElem->attributes()->groups) {
                         $pMetadata->groups =  preg_split('/\s*,\s*/', (string) $groups);
                     }
-                    
+
                     if (isset($pElem->{'xml-list'})) {
                         $pMetadata->xmlCollection = true;
 
@@ -218,7 +220,7 @@ class XmlDriver extends AbstractFileDriver
 
                     //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);
+                        $pMetadata->readOnly = $readOnlyClass || 'true' === strtolower($readOnly);
                     }
 
                     $getter = $pElem->attributes()->{'accessor-getter'};

+ 2 - 2
src/JMS/Serializer/Metadata/Driver/YamlDriver.php

@@ -45,7 +45,7 @@ class YamlDriver extends AbstractFileDriver
         $exclusionPolicy = isset($config['exclusion_policy']) ? strtoupper($config['exclusion_policy']) : 'NONE';
         $excludeAll = isset($config['exclude']) ? (Boolean) $config['exclude'] : false;
         $classAccessType = isset($config['access_type']) ? $config['access_type'] : PropertyMetadata::ACCESS_TYPE_PROPERTY;
-
+        $readOnlyClass =  isset($config['read_only']) ? (Boolean) $config['read_only'] : false;
         $this->addClassProperties($metadata, $config);
 
         $propertiesMetadata = array();
@@ -167,7 +167,7 @@ class YamlDriver extends AbstractFileDriver
 
                     //we need read_only before setter and getter set, because that method depends on flag being set
                     if (isset($pConfig['read_only'])) {
-                          $pMetadata->readOnly = (Boolean) $pConfig['read_only'];
+                          $pMetadata->readOnly = $readOnlyClass || (Boolean) $pConfig['read_only'];
                     }
 
                     $pMetadata->setAccessor(

+ 0 - 1
src/JMS/Serializer/Metadata/PropertyMetadata.php

@@ -83,7 +83,6 @@ class PropertyMetadata extends BasePropertyMetadata
         if (null === $this->getter) {
             return parent::getValue($obj);
         }
-
         return $obj->{$this->getter}();
     }
 

+ 1 - 1
tests/JMS/Serializer/Tests/Metadata/Driver/BaseDriverTest.php

@@ -225,7 +225,7 @@ abstract class BaseDriverTest extends \PHPUnit_Framework_TestCase
         $this->assertNotNull($m);
         $this->assertFalse($m->propertyMetadata['name']->xmlElementCData);
     }
-    
+
     public function testXmlNamespaceInheritanceMetadata()
     {
         $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\SimpleClassObject'));

+ 13 - 0
tests/JMS/Serializer/Tests/Serializer/BaseSerializationTest.php

@@ -90,6 +90,7 @@ use Symfony\Component\Validator\ConstraintViolationList;
 use PhpCollection\Map;
 use JMS\Serializer\Exclusion\DepthExclusionStrategy;
 use JMS\Serializer\Tests\Fixtures\Node;
+use JMS\Serializer\Tests\Fixtures\AuthorReadOnlyPerClass;
 
 abstract class BaseSerializationTest extends \PHPUnit_Framework_TestCase
 {
@@ -344,6 +345,18 @@ abstract class BaseSerializationTest extends \PHPUnit_Framework_TestCase
         }
     }
 
+    public function testReadOnlyClass()
+    {
+        $author = new AuthorReadOnlyPerClass(123, 'Ruud Kamphuis');
+        $this->assertEquals($this->getContent('readonly'), $this->serialize($author));
+
+        if ($this->hasDeserializer()) {
+            $deserialized = $this->deserialize($this->getContent('readonly'), get_class($author));
+            $this->assertNull($this->getField($deserialized, 'id'));
+            $this->assertNull($this->getField($deserialized, 'name'));
+        }
+    }
+
     public function testPrice()
     {
         $price = new Price(3);