Minor dependency updates
[yaffs-website] / vendor / symfony / serializer / Mapping / Factory / ClassMetadataFactory.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\Factory;
13
14 use Doctrine\Common\Cache\Cache;
15 use Symfony\Component\Serializer\Exception\InvalidArgumentException;
16 use Symfony\Component\Serializer\Mapping\ClassMetadata;
17 use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface;
18
19 /**
20  * Returns a {@link ClassMetadata}.
21  *
22  * @author Kévin Dunglas <dunglas@gmail.com>
23  */
24 class ClassMetadataFactory implements ClassMetadataFactoryInterface
25 {
26     /**
27      * @var LoaderInterface
28      */
29     private $loader;
30
31     /**
32      * @var Cache
33      */
34     private $cache;
35
36     /**
37      * @var array
38      */
39     private $loadedClasses;
40
41     /**
42      * @param LoaderInterface $loader
43      * @param Cache|null      $cache
44      */
45     public function __construct(LoaderInterface $loader, Cache $cache = null)
46     {
47         $this->loader = $loader;
48         $this->cache = $cache;
49     }
50
51     /**
52      * {@inheritdoc}
53      */
54     public function getMetadataFor($value)
55     {
56         $class = $this->getClass($value);
57         if (!$class) {
58             throw new InvalidArgumentException(sprintf('Cannot create metadata for non-objects. Got: "%s"', gettype($value)));
59         }
60
61         if (isset($this->loadedClasses[$class])) {
62             return $this->loadedClasses[$class];
63         }
64
65         if ($this->cache && ($this->loadedClasses[$class] = $this->cache->fetch($class))) {
66             return $this->loadedClasses[$class];
67         }
68
69         if (!class_exists($class) && !interface_exists($class)) {
70             throw new InvalidArgumentException(sprintf('The class or interface "%s" does not exist.', $class));
71         }
72
73         $classMetadata = new ClassMetadata($class);
74         $this->loader->loadClassMetadata($classMetadata);
75
76         $reflectionClass = $classMetadata->getReflectionClass();
77
78         // Include metadata from the parent class
79         if ($parent = $reflectionClass->getParentClass()) {
80             $classMetadata->merge($this->getMetadataFor($parent->name));
81         }
82
83         // Include metadata from all implemented interfaces
84         foreach ($reflectionClass->getInterfaces() as $interface) {
85             $classMetadata->merge($this->getMetadataFor($interface->name));
86         }
87
88         if ($this->cache) {
89             $this->cache->save($class, $classMetadata);
90         }
91
92         return $this->loadedClasses[$class] = $classMetadata;
93     }
94
95     /**
96      * {@inheritdoc}
97      */
98     public function hasMetadataFor($value)
99     {
100         $class = $this->getClass($value);
101
102         return class_exists($class) || interface_exists($class);
103     }
104
105     /**
106      * Gets a class name for a given class or instance.
107      *
108      * @param mixed $value
109      *
110      * @return string|bool
111      */
112     private function getClass($value)
113     {
114         if (!is_object($value) && !is_string($value)) {
115             return false;
116         }
117
118         return ltrim(is_object($value) ? get_class($value) : $value, '\\');
119     }
120 }