Completed
Push — master ( 2958af...77ccc9 )
by JHONATAN
02:21
created

YmlDriver   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 102
Duplicated Lines 0 %

Test Coverage

Coverage 88.46%

Importance

Changes 0
Metric Value
wmc 12
dl 0
loc 102
ccs 46
cts 52
cp 0.8846
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
B loadYml() 0 25 3
B loadMetadataForClass() 0 54 8
1
<?php
2
3
namespace Vox\Metadata\Driver;
4
5
use Metadata\Driver\DriverInterface;
6
use Metadata\MethodMetadata;
7
use ProxyManager\Proxy\AccessInterceptorValueHolderInterface;
8
use ReflectionClass;
9
use ReflectionProperty;
10
use RuntimeException;
11
use Symfony\Component\Yaml\Parser;
12
use Vox\Data\Mapping\Bindings;
13
use Vox\Metadata\ClassMetadata;
14
use Vox\Metadata\PropertyMetadata;
15
use Vox\Webservice\Mapping\BelongsTo;
16
use Vox\Webservice\Mapping\Id;
17
use Vox\Webservice\Mapping\Resource;
18
19
class YmlDriver implements DriverInterface
20
{
21
    private $ymlParser;
22
    
23
    private $path;
24
    
25
    private $classMetadataClassName;
26
    
27
    private $propertyMetadataClassName;
28
    
29 2
    public function __construct(
30
        string $path,
31
        string $classMetadataClassName = ClassMetadata::class,
32
        string $propertyMetadataClassName = PropertyMetadata::class
33
    ) {
34 2
        $this->ymlParser                 = new Parser();
35 2
        $this->path                      = realpath($path);
36 2
        $this->classMetadataClassName    = $classMetadataClassName;
37 2
        $this->propertyMetadataClassName = $propertyMetadataClassName;
38 2
    }
39
    
40 2
    public function loadMetadataForClass(ReflectionClass $class): ClassMetadata
41
    {
42 2
        if ($class->implementsInterface(AccessInterceptorValueHolderInterface::class)) {
43
            $class = $class->getParentClass();
44
        }
45
        
46 2
        $yml = $this->loadYml($class);
47
        
48
        /* @var $classMetadata ClassMetadata */
49 2
        $classMetadata = (new ReflectionClass($this->classMetadataClassName))->newInstance($class->name);
50
        
51 2
        if (isset($yml['resource'])) {
52 2
            $resource         = new Resource();
53 2
            $resource->client = $yml['resource']['client'] ?? null;
54 2
            $resource->route  = $yml['resource']['route'] ?? null;
55 2
            $classMetadata->setAnnotations([Resource::class => $resource]);
56
        }
57
        
58 2
        foreach ($class->getMethods() as $method) {
59 2
            $classMetadata->addMethodMetadata(new MethodMetadata($class->name, $method->name));
60
        }
61
        
62
        /* @var $reflectionProperty ReflectionProperty */
63 2
        foreach ($class->getProperties() as $reflectionProperty) {
64 2
            $annotations = [];
65 2
            $annotations[Bindings::class] = $bindings = new Bindings();
66
            
67 2
            if (isset($yml['parameters'][$reflectionProperty->name])) {
68 2
                $name             = $reflectionProperty->name;
69 2
                $config           = $yml['parameters'][$name];
70 2
                $bindings->source = $config['bindings']['source'] ?? null;
71 2
                $bindings->target = $config['bindings']['target'] ?? null;
72
73 2
                if ($name == $yml['id'] ?? null) {
74 2
                    $annotations[Id::class] = new Id();
75
                }
76
                
77 2
                if (isset($config['belongsTo'])) {
78
                    $belongsTo = new BelongsTo();
79
                    $belongsTo->foreignField = $config['belongsTo']['foreignField'];
80
                    $annotations[BelongsTo::class] = $belongsTo;
81
                }
82
            }
83
            
84
            /* @var $propertyMetadata PropertyMetadata */
85 2
            $propertyMetadata = (new ReflectionClass($this->propertyMetadataClassName))
86 2
                ->newInstance($class->name, $reflectionProperty->name);
87
            
88 2
            $propertyMetadata->setAnnotations($annotations);
89
            
90 2
            $classMetadata->addPropertyMetadata($propertyMetadata);
91
        }
92
        
93 2
        return $classMetadata;
94
    }
95
    
96 2
    private function loadYml(ReflectionClass $class)
97
    {
98 2
        $className = $class->getName();
99
        
100 2
        $path = sprintf(
101 2
            '%s/%s.yml', 
102 2
            preg_replace('/\/$/', '', $this->path), 
103 2
            str_replace('\\', DIRECTORY_SEPARATOR, $className)
104
        );
105
        
106 2
        if (is_file($path)) {
107
            return $this->ymlParser->parse(file_get_contents($path));
108
        }
109
        
110 2
        $path = sprintf(
111 2
            '%s/%s.yml', 
112 2
            preg_replace('/\/$/', '', $this->path), 
113 2
            str_replace('\\', '.', $className)
114
        );
115
        
116 2
        if (is_file($path)) {
117 2
            return $this->ymlParser->parse(file_get_contents($path));
118
        }
119
        
120
        throw new RuntimeException("metadata file not found for class $className");
121
    }
122
}
123