Skip to content

Commit

Permalink
Add @virtual annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
anyx committed Apr 29, 2012
1 parent 6bf2f09 commit 38912e0
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 22 deletions.
18 changes: 18 additions & 0 deletions Annotation/Virtual.php
@@ -0,0 +1,18 @@
<?php

namespace JMS\SerializerBundle\Annotation;

/**
* @Annotation
* @Target("METHOD")
*
* @author Alexander Klimenkov <alx.devel@gmail.com>
*/
final class Virtual
{
/**
* @Required
* @var string
*/
public $field;
}
52 changes: 30 additions & 22 deletions Metadata/ClassMetadata.php
Expand Up @@ -38,6 +38,7 @@ class ClassMetadata extends MergeableClassMetadata
public $preSerializeMethods = array();
public $postSerializeMethods = array();
public $postDeserializeMethods = array();
public $virtualPropertyMethods = array();
public $xmlRootName;
public $accessorOrder;
public $customOrder;
Expand Down Expand Up @@ -86,6 +87,11 @@ public function addPostDeserializeMethod(MethodMetadata $method)
$this->postDeserializeMethods[] = $method;
}

public function addVirtualPropertyMethod(MethodMetadata $method, $field)
{
$this->virtualPropertyMethods[$field] = $method;
}

public function merge(MergeableInterface $object)
{
if (!$object instanceof ClassMetadata) {
Expand Down Expand Up @@ -114,6 +120,7 @@ public function serialize()
$this->preSerializeMethods,
$this->postSerializeMethods,
$this->postDeserializeMethods,
$this->virtualPropertyMethods,
$this->xmlRootName,
$this->accessorOrder,
$this->customOrder,
Expand All @@ -127,6 +134,7 @@ public function unserialize($str)
$this->preSerializeMethods,
$this->postSerializeMethods,
$this->postDeserializeMethods,
$this->virtualPropertyMethods,
$this->xmlRootName,
$this->accessorOrder,
$this->customOrder,
Expand All @@ -138,32 +146,32 @@ public function unserialize($str)

private function sortProperties()
{
switch ($this->accessorOrder) {
case self::ACCESSOR_ORDER_ALPHABETICAL:
ksort($this->propertyMetadata);
break;

case self::ACCESSOR_ORDER_CUSTOM:
switch ($this->accessorOrder) {
case self::ACCESSOR_ORDER_ALPHABETICAL:
ksort($this->propertyMetadata);
break;

case self::ACCESSOR_ORDER_CUSTOM:
$order = $this->customOrder;
uksort($this->propertyMetadata, function($a, $b) use ($order) {
$existsA = isset($order[$a]);
$existsB = isset($order[$b]);

if (!$existsA && !$existsB) {
return 0;
}

if (!$existsA) {
return 1;
}

if (!$existsB) {
return -1;
$existsA = isset($order[$a]);
$existsB = isset($order[$b]);

if (!$existsA && !$existsB) {
return 0;
}

return $order[$a] < $order[$b] ? -1 : 1;
if (!$existsA) {
return 1;
}

if (!$existsB) {
return -1;
}

return $order[$a] < $order[$b] ? -1 : 1;
});
break;
}
break;
}
}
}
4 changes: 4 additions & 0 deletions Metadata/Driver/AnnotationDriver.php
Expand Up @@ -32,6 +32,7 @@
use JMS\SerializerBundle\Annotation\PostSerialize;
use JMS\SerializerBundle\Annotation\PostDeserialize;
use JMS\SerializerBundle\Annotation\PreSerialize;
use JMS\SerializerBundle\Annotation\Virtual;
use Metadata\MethodMetadata;
use Doctrine\Common\Annotations\Reader;
use JMS\SerializerBundle\Annotation\Type;
Expand Down Expand Up @@ -152,6 +153,9 @@ public function loadMetadataForClass(\ReflectionClass $class)
} else if ($annot instanceof PostSerialize) {
$classMetadata->addPostSerializeMethod(new MethodMetadata($name, $method->getName()));
continue 2;
} else if ($annot instanceof Virtual) {
$classMetadata->addVirtualPropertyMethod( new MethodMetadata($name, $method->getName()), $annot->field);
continue 2;
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions Serializer/GenericSerializationVisitor.php
Expand Up @@ -113,6 +113,10 @@ public function startVisitingObject(ClassMetadata $metadata, $data, $type)

$this->dataStack->push($this->data);
$this->data = array();

foreach( $metadata->virtualPropertyMethods as $field => $method ) {
$this->data[$field] = $method->invoke($data);
}
}

public function endVisitingObject(ClassMetadata $metadata, $data, $type)
Expand Down
6 changes: 6 additions & 0 deletions Serializer/XmlSerializationVisitor.php
Expand Up @@ -143,6 +143,12 @@ public function startVisitingObject(ClassMetadata $metadata, $data, $type)
}

$this->hasValue = false;

foreach( $metadata->virtualPropertyMethods as $field => $method ) {
$element = $this->getDocument()->createElement($field);
$element->appendChild($this->getDocument()->createCDATASection( (string) $method->invoke($data)));
$this->getCurrentNode()->appendChild($element);
}
}

public function visitProperty(PropertyMetadata $metadata, $object)
Expand Down
4 changes: 4 additions & 0 deletions Serializer/YamlSerializationVisitor.php
Expand Up @@ -143,6 +143,10 @@ public function visitTraversable($data, $type)

public function startVisitingObject(ClassMetadata $metadata, $data, $type)
{
foreach( $metadata->virtualPropertyMethods as $field => $method ) {
$this->writer
->writeln(Inline::dump($field).': ' . $method->invoke($data));
}
}

public function visitProperty(PropertyMetadata $metadata, $data)
Expand Down
36 changes: 36 additions & 0 deletions Tests/Fixtures/ObjectWithVirtualProperty.php
@@ -0,0 +1,36 @@
<?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\Virtual;

class ObjectWithVirtualProperty
{

protected $existField = 'value';

/**
*
* @Virtual(field="foo")
*/
public function getValue() {
return 'bar';
}
}
5 changes: 5 additions & 0 deletions Tests/Serializer/BaseSerializationTest.php
Expand Up @@ -58,6 +58,7 @@
use JMS\SerializerBundle\Tests\Fixtures\CircularReferenceParent;
use JMS\SerializerBundle\Tests\Fixtures\InlineParent;
use JMS\SerializerBundle\Tests\Fixtures\GroupsObject;
use JMS\SerializerBundle\Tests\Fixtures\ObjectWithVirtualProperty;
use JMS\SerializerBundle\Serializer\XmlSerializationVisitor;
use Doctrine\Common\Annotations\AnnotationReader;
use JMS\SerializerBundle\Metadata\Driver\AnnotationDriver;
Expand Down Expand Up @@ -438,6 +439,10 @@ public function testGroups()
$serializer->setGroups(array());
$this->assertEquals($this->getContent('groups_all'), $serializer->serialize($groupsObject, $this->getFormat()));
}

public function testVirtualProperty() {
$this->assertEquals($this->getContent('virtual_property'), $this->serialize(new ObjectWithVirtualProperty()));
}

abstract protected function getContent($key);
abstract protected function getFormat();
Expand Down
1 change: 1 addition & 0 deletions Tests/Serializer/JsonSerializationTest.php
Expand Up @@ -64,6 +64,7 @@ protected function getContent($key)
$outputs['groups_all'] = '{"foo":"foo","foobar":"foobar","bar":"bar","none":"none"}';
$outputs['groups_foo'] = '{"foo":"foo","foobar":"foobar"}';
$outputs['groups_foobar'] = '{"foo":"foo","foobar":"foobar","bar":"bar"}';
$outputs['virtual_property'] = '{"foo":"bar","exist_field":"value"}';
}

if (!isset($outputs[$key])) {
Expand Down
5 changes: 5 additions & 0 deletions Tests/Serializer/xml/virtual_property.xml
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<result>
<foo><![CDATA[bar]]></foo>
<exist_field><![CDATA[value]]></exist_field>
</result>
2 changes: 2 additions & 0 deletions Tests/Serializer/yml/virtual_property.yml
@@ -0,0 +1,2 @@
foo: bar
exist_field: value

0 comments on commit 38912e0

Please sign in to comment.