MetadataFactory::hasMetadataFor()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
1
<?php
2
/*
3
 * This file is part of AppBundle the package.
4
 *
5
 * (c) Ruslan Muriev <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace RonteLtd\JsonApiBundle\Serializer\Mapping\Factory;
12
13
use RonteLtd\JsonApiBundle\Serializer\Mapping\ClassMetadata;
14
use RonteLtd\JsonApiBundle\Serializer\Mapping\Loader\LoaderInterface;
15
use RonteLtd\JsonApiBundle\Serializer\Exception\InvalidArgumentException;
16
17
/**
18
 * Class MetadataFactory
19
 *
20
 * @package RonteLtd\JsonApiBundle\Serializer\Mapping\Factory
21
 * @author Ruslan Muriev <[email protected]>
22
 */
23
class MetadataFactory implements MetadataFactoryInterface
24
{
25
    /**
26
     * @var LoaderInterface
27
     */
28
    private $loader;
29
30
    /**
31
     * @var array
32
     */
33
    private $loadedClasses;
34
35
    /**
36
     * @param LoaderInterface $loader
37
     */
38
    public function __construct(LoaderInterface $loader)
39
    {
40
        $this->loader = $loader;
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function getMetadataFor($value)
47
    {
48
        $class = $this->getClass($value);
49
50
        if (isset($this->loadedClasses[$class])) {
51
            return $this->loadedClasses[$class];
52
        }
53
54
        $classMetadata = new ClassMetadata($class);
55
        $this->loader->loadClassMetadata($classMetadata);
56
57
        $reflectionClass = $classMetadata->getReflectionClass();
58
59
        // Include metadata from the parent class
60
        if ($parent = $reflectionClass->getParentClass()) {
61
            $classMetadata->merge($this->getMetadataFor($parent->name));
62
        }
63
64
        // Include metadata from all implemented interfaces
65
        foreach ($reflectionClass->getInterfaces() as $interface) {
66
            $classMetadata->merge($this->getMetadataFor($interface->name));
67
        }
68
69
        return $this->loadedClasses[$class] = $classMetadata;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    public function hasMetadataFor($value)
76
    {
77
        try {
78
            $this->getClass($value);
79
80
            return true;
81
        } catch (InvalidArgumentException $invalidArgumentException) {
82
            // Return false in case of exception
83
        }
84
85
        return false;
86
    }
87
88
    /**
89
     * Gets a class name for a given class or instance.
90
     *
91
     * @param mixed $value
92
     *
93
     * @return string
94
     *
95
     * @throws InvalidArgumentException If the class does not exists
96
     */
97
    private function getClass($value)
98
    {
99
        if (is_string($value)) {
100
            if (!class_exists($value) && !interface_exists($value)) {
101
                throw new InvalidArgumentException(sprintf('The class or interface "%s" does not exist.', $value));
102
            }
103
104
            return ltrim($value, '\\');
105
        }
106
107
        if (!is_object($value)) {
108
            throw new InvalidArgumentException(sprintf('Cannot create metadata for non-objects. Got: "%s"', gettype($value)));
109
        }
110
111
        return get_class($value);
112
    }
113
}