Passed
Push — master ( f10307...f30d53 )
by JHONATAN
07:03
created

ProxyFactory   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 161
Duplicated Lines 0 %

Test Coverage

Coverage 98.48%

Importance

Changes 0
Metric Value
wmc 25
dl 0
loc 161
c 0
b 0
f 0
ccs 65
cts 66
cp 0.9848
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B createProxy() 0 17 5
A createGetterInterceptor() 0 15 2
A fetchBelongsTo() 0 14 4
A fetchBelongsToSingle() 0 23 3
A registerProxyAutoloader() 0 4 2
A fetchBelongsToMulti() 0 20 2
A fetchHasMany() 0 15 3
A fetchHasOne() 0 15 3
1
<?php
2
3
namespace Vox\Webservice\Proxy;
4
5
use ProxyManager\Configuration;
6
use ProxyManager\Factory\AccessInterceptorValueHolderFactory;
7
use ProxyManager\Proxy\AccessInterceptorValueHolderInterface;
8
use Vox\Metadata\PropertyMetadata;
9
use Vox\Webservice\Mapping\BelongsTo;
10
use Vox\Webservice\Mapping\HasMany;
11
use Vox\Webservice\Mapping\HasOne;
12
use Vox\Webservice\Metadata\TransferMetadata;
13
use Vox\Webservice\TransferManagerInterface;
14
15
/**
16
 * a proxy factory for the transfers, it uses the ocramius proxy generator
17
 * 
18
 * @author Jhonatan Teixeira <[email protected]>
19
 */
20
class ProxyFactory implements ProxyFactoryInterface
21
{
22
    /**
23
     * @var AccessInterceptorValueHolderFactory
24
     */
25
    private $accessInterceptorFactory;
26
    
27
    /**
28
     * @var Configuration
29
     */
30
    private $proxyConfig;
31
32 34
    public function __construct(Configuration $proxyConfig = null)
33
    {
34 34
        $this->accessInterceptorFactory = new AccessInterceptorValueHolderFactory($proxyConfig);
35 34
        $this->proxyConfig              = $proxyConfig;
36 34
    }
37
    
38 21
    public function createProxy($class, TransferManagerInterface $transferManager): AccessInterceptorValueHolderInterface
39
    {
40 21
        $className = is_object($class) ? get_class($class) : $class;
41 21
        $metadata  = $transferManager->getClassMetadata($className);
42 21
        $object    = is_object($class) ? $class : new $class();
43
44 21
        $interceptors = [];
45
46 21
        foreach ($metadata->propertyMetadata as $name => $config) {
47 21
            $getter = sprintf('get%s', ucfirst($name));
48
49 21
            if (isset($metadata->methodMetadata[$getter])) {
50 21
                $interceptors[$getter] = $this->createGetterInterceptor($metadata, $name, $object, $transferManager);
51
            }
52
        }
53
54 21
        return $this->accessInterceptorFactory->createProxy($object, $interceptors);
55
    }
56
57
    private function createGetterInterceptor(
58
        TransferMetadata $metadata,
59
        string $name,
60
        $object,
61
        TransferManagerInterface $transferManager
62
    ): callable {
63 16
        return function () use ($metadata, $name, $object, $transferManager) {
64
            /* @var $propertyMetadata PropertyMetadata */
65 10
            $propertyMetadata = $metadata->propertyMetadata[$name];
66 10
            $type             = $propertyMetadata->getParsedType();
67
68 10
            if (class_exists($type)) {
69 8
                $this->fetchBelongsTo($metadata, $propertyMetadata, $transferManager, $object, $type);
70 8
                $this->fetchHasOne($metadata, $propertyMetadata, $transferManager, $object, $type);
71 8
                $this->fetchHasMany($metadata, $propertyMetadata, $transferManager, $object, $type);
72
            }
73 16
        };
74
    }
75
    
76 8
    private function fetchBelongsTo(
77
        TransferMetadata $metadata,
78
        PropertyMetadata $propertyMetadata,
79
        TransferManagerInterface $transferManager,
80
        $object,
81
        string $type
82
    ) {
83 8
        $belongsTo = $propertyMetadata->getAnnotation(BelongsTo::class);
84
        
85 8
        if ($belongsTo instanceof BelongsTo && empty($propertyMetadata->getValue($object))) {
86 7
            if (is_array($belongsTo->foreignField)) {
87 3
                $this->fetchBelongsToMulti($object, $type, $metadata, $propertyMetadata, $belongsTo, $transferManager);
88
            } else {
89 7
                $this->fetchBelongsToSingle($object, $type, $metadata, $propertyMetadata, $belongsTo, $transferManager);
90
            }
91
        }
92 8
    }
93
94 7
    private function fetchBelongsToSingle(
95
        $object,
96
        string $type,
97
        TransferMetadata $metadata,
98
        PropertyMetadata $propertyMetadata,
99
        BelongsTo $belongsTo,
100
        TransferManagerInterface $transferManager
101
    ) {
102 7
        $idValue  = $metadata->propertyMetadata[$belongsTo->foreignField]->getValue($object);
103
104 7
        if (!$idValue) {
105
            return;
106
        }
107
        
108 7
        if (!is_integer($idValue)) {
109 1
            preg_match('/\w+$/', $idValue, $matches);
110 1
            $idValue = $matches[0];
111
        }
112
113
        $data = $transferManager
114 7
            ->find($type, $idValue);
115
116 7
        $propertyMetadata->setValue($object, $data);
117 7
    }
118
119 3
    private function fetchBelongsToMulti(
120
        $object,
121
        string $type,
122
        TransferMetadata $metadata,
123
        PropertyMetadata $propertyMetadata,
124
        BelongsTo $belongsTo,
125
        TransferManagerInterface $transferManager
126
127
    ) {
128 3
        $criteria = [];
129
        
130 3
        foreach ($belongsTo->foreignField as $field) {
131 3
            $criteria[] = sprintf('%s=%s', $field, $metadata->propertyMetadata[$field]->getValue($object));
132
            //$criteria[$field] = $metadata->propertyMetadata[$field]->getValue($object);
133
        }
134
135 3
        $data = $transferManager->getRepository($type)
136 3
            ->find(implode(';', $criteria));
137
138 3
        $propertyMetadata->setValue($object, $data);
139 3
    }
140
141 8
    private function fetchHasOne(
142
        TransferMetadata $metadata,
143
        PropertyMetadata $propertyMetadata,
144
        TransferManagerInterface $transferManager,
145
        $object,
146
        string $type
147
    ) {
148 8
        $hasOne = $propertyMetadata->getAnnotation(HasOne::class);
149 8
        $id     = $metadata->id->getValue($object);
150
        
151 8
        if ($hasOne instanceof HasOne && !empty($id)) {
152 2
            $data = $transferManager->getRepository($type)
153 2
                ->findOneBy([$hasOne->foreignField => $id]);
154
155 2
            $propertyMetadata->setValue($object, $data);
156
        }
157 8
    }
158
159 8
    private function fetchHasMany(
160
        TransferMetadata $metadata,
161
        PropertyMetadata $propertyMetadata,
162
        TransferManagerInterface $transferManager,
163
        $object,
164
        string $type
165
    ) {
166 8
        $hasMany = $propertyMetadata->getAnnotation(HasMany::class);
167 8
        $id      = $metadata->id->getValue($object);
168
169 8
        if ($hasMany instanceof HasMany && !empty($id)) {
170 3
            $data = $transferManager->getRepository($type)
171 3
                ->findBy([$hasMany->foreignField => $metadata->id->getValue($object)]);
172
173 3
            $propertyMetadata->setValue($object, $data);
174
        }
175 8
    }
176
177 4
    public function registerProxyAutoloader()
178
    {
179 4
        if ($this->proxyConfig) {
180 4
            spl_autoload_register($this->proxyConfig->getProxyAutoloader());
181
        }
182 4
    }
183
}
184