5527b5f71731eef53f2e945d9d0b6406f90501e9
[yaffs-website] / serializer / Mapping / Loader / AnnotationLoader.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\Serializer\Mapping\Loader;
13
14 use Doctrine\Common\Annotations\Reader;
15 use Symfony\Component\Serializer\Annotation\Groups;
16 use Symfony\Component\Serializer\Annotation\MaxDepth;
17 use Symfony\Component\Serializer\Exception\MappingException;
18 use Symfony\Component\Serializer\Mapping\AttributeMetadata;
19 use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
20
21 /**
22  * Annotation loader.
23  *
24  * @author Kévin Dunglas <dunglas@gmail.com>
25  */
26 class AnnotationLoader implements LoaderInterface
27 {
28     private $reader;
29
30     public function __construct(Reader $reader)
31     {
32         $this->reader = $reader;
33     }
34
35     /**
36      * {@inheritdoc}
37      */
38     public function loadClassMetadata(ClassMetadataInterface $classMetadata)
39     {
40         $reflectionClass = $classMetadata->getReflectionClass();
41         $className = $reflectionClass->name;
42         $loaded = false;
43
44         $attributesMetadata = $classMetadata->getAttributesMetadata();
45
46         foreach ($reflectionClass->getProperties() as $property) {
47             if (!isset($attributesMetadata[$property->name])) {
48                 $attributesMetadata[$property->name] = new AttributeMetadata($property->name);
49                 $classMetadata->addAttributeMetadata($attributesMetadata[$property->name]);
50             }
51
52             if ($property->getDeclaringClass()->name === $className) {
53                 foreach ($this->reader->getPropertyAnnotations($property) as $annotation) {
54                     if ($annotation instanceof Groups) {
55                         foreach ($annotation->getGroups() as $group) {
56                             $attributesMetadata[$property->name]->addGroup($group);
57                         }
58                     } elseif ($annotation instanceof MaxDepth) {
59                         $attributesMetadata[$property->name]->setMaxDepth($annotation->getMaxDepth());
60                     }
61
62                     $loaded = true;
63                 }
64             }
65         }
66
67         foreach ($reflectionClass->getMethods() as $method) {
68             if ($method->getDeclaringClass()->name !== $className) {
69                 continue;
70             }
71
72             $accessorOrMutator = preg_match('/^(get|is|has|set)(.+)$/i', $method->name, $matches);
73             if ($accessorOrMutator) {
74                 $attributeName = lcfirst($matches[2]);
75
76                 if (isset($attributesMetadata[$attributeName])) {
77                     $attributeMetadata = $attributesMetadata[$attributeName];
78                 } else {
79                     $attributesMetadata[$attributeName] = $attributeMetadata = new AttributeMetadata($attributeName);
80                     $classMetadata->addAttributeMetadata($attributeMetadata);
81                 }
82             }
83
84             foreach ($this->reader->getMethodAnnotations($method) as $annotation) {
85                 if ($annotation instanceof Groups) {
86                     if (!$accessorOrMutator) {
87                         throw new MappingException(sprintf('Groups on "%s::%s" cannot be added. Groups can only be added on methods beginning with "get", "is", "has" or "set".', $className, $method->name));
88                     }
89
90                     foreach ($annotation->getGroups() as $group) {
91                         $attributeMetadata->addGroup($group);
92                     }
93                 } elseif ($annotation instanceof MaxDepth) {
94                     if (!$accessorOrMutator) {
95                         throw new MappingException(sprintf('MaxDepth on "%s::%s" cannot be added. MaxDepth can only be added on methods beginning with "get", "is", "has" or "set".', $className, $method->name));
96                     }
97
98                     $attributeMetadata->setMaxDepth($annotation->getMaxDepth());
99                 }
100
101                 $loaded = true;
102             }
103         }
104
105         return $loaded;
106     }
107 }