Completed
Push — master ( 6751ec...bd2805 )
by JHONATAN
03:37
created

TransferPersister::updateMultiBelongsToIds()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 11
cts 11
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 11
nc 4
nop 2
crap 4
1
<?php
2
3
namespace Vox\Webservice;
4
5
use Doctrine\Common\Collections\Collection;
6
use Metadata\MetadataFactoryInterface;
7
use Traversable;
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
14
/**
15
 * The transfer persister will do the work of persisting and assuring the objects are on the
16
 * correct state
17
 * 
18
 * @author Jhonatan Teixeira <[email protected]>
19
 */
20
class TransferPersister implements TransferPersisterInterface
21
{
22
    use MetadataTrait;
23
    
24
    /**
25
     * @var MetadataFactoryInterface
26
     */
27
    private $metadataFactory;
28
    
29
    /**
30
     * @var UnityOfWorkInterface
31
     */
32
    private $unityOfWork;
33
    
34
    /**
35
     * @var WebserviceClientInterface
36
     */
37
    private $webserviceClient;
38
    
39 27
    public function __construct(
40
        MetadataFactoryInterface $metadataFactory,
41
        UnityOfWorkInterface $unityOfWork,
42
        WebserviceClientInterface $webserviceClient
43
    ) {
44 27
        $this->metadataFactory  = $metadataFactory;
45 27
        $this->unityOfWork      = $unityOfWork;
46 27
        $this->webserviceClient = $webserviceClient;
47 27
    }
48
49 13
    public function save($object, $owner = null)
50
    {
51 13
        $transfer = $object;
52
        
53 13
        $metadata = $this->getClassMetadata($transfer);
54
        
55 13
        foreach ($metadata->associations as $name => $association) {
56 6
            $assocValue = $association->getValue($transfer);
57
            
58 6
            if (!$assocValue) {
59 5
                continue;
60
            }
61
            
62 5
            $this->persistAssociation($object, $assocValue, $metadata, $association);
63
        }
64
        
65 13
        $this->persistTransfer($object, $owner);
66 13
    }
67
    
68 5
    private function persistAssociation($object, $association, TransferMetadata $metadata, PropertyMetadata $property)
69
    {
70 5
        if (is_array($association) || $association instanceof Traversable || $association instanceof Collection) {
71 2
            foreach ($association as $transfer) {
72 2
                $this->persistAssociation($object, $transfer, $metadata, $property);
73
            }
74
75 2
            return;
76
        }
77
78 5
        if ($this->unityOfWork->isDetached($association)) {
79 3
            $this->unityOfWork->attach($association);
80
        }
81
82 5
        if (!$this->unityOfWork->isNew($association) && !$this->unityOfWork->isDirty($association)) {
83 2
            return;
84
        }
85
86 4
        $this->save($association, $object);
87 4
    }
88
89 13
    private function persistTransfer($object, $owner = null)
90
    {
91 13
        if ($this->unityOfWork->isNew($object)) {
92 6
            $this->updateRelationshipsIds($object, $owner);
93 6
            $this->webserviceClient->post($object);
94 6
            $this->renewState($object);
95
            
96 6
            return;
97
        }
98
99 11
        if ($this->unityOfWork->isRemoved($object)) {
100 2
            $this->webserviceClient->delete(get_class($object), $this->getIdValue($object));
101 2
            $this->unityOfWork->detach($object);
102
103 2
            return;
104
        }
105
106 9
        if ($this->unityOfWork->isDirty($object)) {
107 8
            $this->updateRelationshipsIds($object, $owner);
108 8
            $this->webserviceClient->put($object);
109 8
            $this->renewState($object);
110
        }
111 9
    }
112
113 12
    private function updateRelationshipsIds($object, $owner = null)
114
    {
115 12
        if ($owner) {
116 4
            $this->updateRelationshipsIds($owner);
117
        }
118
119 12
        $objectMetadata = $this->getClassMetadata($object);
120
121 12
        foreach ($objectMetadata->associations as $associationProperty) {
122 6
            $association = $associationProperty->getValue($object);
123
124 6
            if (!$association) {
125 5
                continue;
126
            }
127
128 5
            $associationMetadata = $this->getClassMetadata($association);
129
130 5
            if ($associationProperty->hasAnnotation(BelongsTo::class)) {
131 4
                if ($associationMetadata->id->isMultiId()) {
132 1
                    $this->updateMultiBelongsToIds($object, $association);
133
                } else {
134 4
                    $this->updateBelogsToId($object, $association, $associationProperty);
135
                }
136
137 4
                continue;
138
            }
139
140 2
            if ($associationProperty->hasAnnotation(HasOne::class)) {
141 1
                $this->updateHasOneId($object, $association, $associationProperty->getAnnotation(HasOne::class));
142
143 1
                continue;
144
            }
145
146 2
            if ($associationProperty->hasAnnotation(HasMany::class)) {
147 2
                $this->updateHasManyIds($object, $association, $associationProperty->getAnnotation(HasMany::class));
148
149 2
                continue;
150
            }
151
        }
152 12
    }
153
154 1
    private function updateMultiBelongsToIds($object, $association)
155
    {
156 1
        $id             = $this->getIdValue($association);
157 1
        $objectMetadata = $this->getClassMetadata($object);
158
159 1
        if (empty($id)) {
160 1
            foreach ($this->getClassMetadata($association)->id->getIds() as $idProperty) {
161 1
                $idProperty->setValue(
162 1
                    $association,
163 1
                    $objectMetadata->propertyMetadata[$idProperty->name]->getValue($object)
164
                );
165
            }
166
        } else {
167 1
            foreach ($this->getClassMetadata($association)->id->getIds() as $idProperty) {
168 1
                $objectMetadata->propertyMetadata[$idProperty->name]
169 1
                    ->setValue($object, $idProperty->getValue($association));
170
            }
171
        }
172 1
    }
173
174 4
    private function updateBelogsToId($object, $association, PropertyMetadata $associationProperty)
175
    {
176
        /* @var $belongsTo BelongsTo */
177 4
        $belongsTo = $associationProperty->getAnnotation(BelongsTo::class);
178
179 4
        $objectMetadata = $this->getClassMetadata($object);
180
181 4
        $objectMetadata->propertyMetadata[$belongsTo->foreignField]
182 4
            ->setValue($object, $this->getIdValue($association));
183 4
    }
184
185
    /**
186
     * @param $object
187
     * @param $association
188
     * @param HasOne|HasMany $annotation
189
     */
190 2
    private function updateHasOneId($object, $association, $annotation)
191
    {
192 2
        $id                  = $this->getIdValue($object);
193 2
        $associationMetadata = $this->getClassMetadata($association);
194
195 2
        $associationMetadata->propertyMetadata[$annotation->foreignField]
196 2
            ->setValue($association, $id);
197 2
    }
198
199
    /**
200
     * @param $object
201
     * @param Traversable $associations
202
     * @param HasOne|HasMany $annotation
203
     */
204 2
    private function updateHasManyIds($object, Traversable $associations, $annotation)
205
    {
206 2
        foreach ($associations as $association) {
207 2
            $this->updateHasOneId($object, $association, $annotation);
208
        }
209 2
    }
210
211 12
    private function renewState($object)
212
    {
213 12
        $this->unityOfWork->detach($object);
214 12
        $this->unityOfWork->attach($object);
215 12
    }
216
}
217