Passed
Branch nested_save (73f795)
by JHONATAN
02:34
created

YmlDriver::loadMetadataForClass()   C

Complexity

Conditions 9
Paths 80

Size

Total Lines 61
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 9.0017

Importance

Changes 0
Metric Value
dl 0
loc 61
ccs 35
cts 36
cp 0.9722
rs 6.7603
c 0
b 0
f 0
cc 9
eloc 35
nc 80
nop 1
crap 9.0017

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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