Completed
Push — master ( 69e2c3...3de1cd )
by JHONATAN
02:37
created

TransferPersister   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 148
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 28
dl 0
loc 148
ccs 72
cts 72
cp 1
rs 10
c 1
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A persistTransfer() 0 18 4
A setIdValueOnAssociation() 0 7 2
A __construct() 0 8 1
A save() 0 21 4
A renewState() 0 4 1
A persistHas() 0 16 4
D persistAssociation() 0 26 10
A persistBelongsTo() 0 10 2
1
<?php
2
3
namespace Vox\Webservice;
4
5
use Doctrine\Common\Collections\Collection;
6
use Metadata\MetadataFactoryInterface;
7
use ProxyManager\Proxy\AccessInterceptorValueHolderInterface;
8
use Traversable;
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
15
/**
16
 * The transfer persister will do the work of persisting and assuring the objects are on the
17
 * correct state
18
 * 
19
 * @author Jhonatan Teixeira <[email protected]>
20
 */
21
class TransferPersister implements TransferPersisterInterface
22
{
23
    use MetadataTrait;
24
    
25
    /**
26
     * @var MetadataFactoryInterface
27
     */
28
    private $metadataFactory;
29
    
30
    /**
31
     * @var UnityOfWorkInterface
32
     */
33
    private $unityOfWork;
34
    
35
    /**
36
     * @var WebserviceClientInterface
37
     */
38
    private $webserviceClient;
39
    
40 24
    public function __construct(
41
        MetadataFactoryInterface $metadataFactory,
42
        UnityOfWorkInterface $unityOfWork,
43
        WebserviceClientInterface $webserviceClient
44
    ) {
45 24
        $this->metadataFactory  = $metadataFactory;
46 24
        $this->unityOfWork      = $unityOfWork;
47 24
        $this->webserviceClient = $webserviceClient;
48 24
    }
49
50
    
51 10
    public function save($object)
52
    {
53 10
        $transfer = $object;
54
        
55 10
        if ($object instanceof AccessInterceptorValueHolderInterface) {
56 8
            $transfer = $transfer->getWrappedValueHolderValue();
57
        }
58
        
59 10
        $metadata = $this->getClassMetadata($transfer);
60
        
61 10
        foreach ($metadata->associations as $name => $association) {
62 3
            $assocValue = $association->getValue($transfer);
63
            
64 3
            if (!$assocValue) {
65 2
                continue;
66
            }
67
            
68 3
            $this->persistAssociation($object, $assocValue, $metadata, $association);
69
        }
70
        
71 10
        $this->persistTransfer($object);
72 10
    }
73
    
74 3
    private function persistAssociation($object, $association, TransferMetadata $metadata, PropertyMetadata $property)
75
    {
76 3
        if (is_array($association) || $association instanceof Traversable || $association instanceof Collection) {
77 1
            foreach ($association as $transfer) {
78 1
                $this->persistAssociation($object, $transfer, $metadata, $property);
79
            }
80
81 1
            return;
82
        }
83
        
84 3
        if (!$this->unityOfWork->isNew($association) && !$this->unityOfWork->isDirty($association)) {
85 1
            return;
86
        }
87
        
88 2
        $this->save($association);
89
        
90 2
        if ($property->hasAnnotation(BelongsTo::class)) {
91 2
            $this->persistBelongsTo($object, $association, $metadata, $property);
92
        }
93
        
94 2
        if ($property->hasAnnotation(HasOne::class)) {
95 1
            $this->persistHas($object, $association, $property, $property->getAnnotation(HasOne::class));
96
        }
97
        
98 2
        if ($property->hasAnnotation(HasMany::class)) {
99 1
            $this->persistHas($object, $association, $property, $property->getAnnotation(HasMany::class));
100
        }
101 2
    }
102
    
103 2
    private function persistBelongsTo($object, $association, TransferMetadata $metadata, PropertyMetadata $property)
104
    {
105
        /* @var $belongsTo BelongsTo */
106 2
        $belongsTo       = $property->getAnnotation(BelongsTo::class);
107 2
        $foreignProperty = $metadata->propertyMetadata[$belongsTo->foreignField];
108 2
        $foreignId       = $foreignProperty->getValue($object);
109 2
        $currentId       = $this->getIdValue($association);
110
111 2
        if ($foreignId !== $currentId) {
112 1
            $foreignProperty->setValue($object, $currentId);
113
        }
114 2
    }
115
    
116 1
    private function persistHas($object, $association, PropertyMetadata $property, $annotation) 
117
    {
118 1
        $type                  = preg_replace('/\[\]$/', '', $property->type);
119 1
        $relationClassMetadata = $this->metadataFactory->getMetadataForClass($type);
120 1
        $relationObject        = $property->getValue($object);
121 1
        $foreignProperty       = $relationClassMetadata->propertyMetadata[$annotation->foreignField];
0 ignored issues
show
Bug introduced by
The property propertyMetadata does not seem to exist on Metadata\ClassHierarchyMetadata.
Loading history...
122
123 1
        if ($relationObject instanceof Traversable || is_array($relationObject)) {
124 1
            foreach ($relationObject as $relationItem) {
125 1
                $this->setIdValueOnAssociation($object, $relationItem, $foreignProperty);
126
            }
127
128 1
            return;
129
        }
130
131 1
        $this->setIdValueOnAssociation($object, $association, $foreignProperty);
132 1
    }
133
134 1
    private function setIdValueOnAssociation($object, $association, PropertyMetadata $foreignProperty)
135
    {
136 1
        $assocId  = $foreignProperty->getValue($association);
137 1
        $objectId = $this->getIdValue($object);
138
139 1
        if ($assocId !== $objectId) {
140 1
            $foreignProperty->setValue($association, $objectId);
141
        }
142 1
    }
143
    
144 10
    private function persistTransfer($object)
145
    {
146 10
        if ($this->unityOfWork->isNew($object)) {
147 3
            $this->webserviceClient->post($object);
148 3
            $this->renewState($object);
149
            
150 3
            return;
151
        }
152
        
153 8
        if ($this->unityOfWork->isDirty($object)) {
154 7
            $this->webserviceClient->put($object);
155 7
            $this->renewState($object);
156
            
157 7
            return;
158
        }
159
        
160 2
        if ($this->unityOfWork->isRemoved($object)) {
161 1
            $this->webserviceClient->delete(get_class($object), $this->getIdValue($object));
162
        }
163 2
    }
164
    
165 9
    private function renewState($object)
166
    {
167 9
        $this->unityOfWork->detach($object);
168 9
        $this->unityOfWork->attach($object);
169 9
    }
170
}
171