Completed
Push — master ( f30d53...1e60b8 )
by JHONATAN
05:19
created

ProxyFactory::fetchHasManyIriCollection()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 23
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

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