Completed
Push — master ( 28afa9...69e2c3 )
by JHONATAN
02:50
created

TransferPersister::setIdValueOnAssociation()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 3
crap 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 20
    public function __construct(
41
        MetadataFactoryInterface $metadataFactory,
42
        UnityOfWorkInterface $unityOfWork,
43
        WebserviceClientInterface $webserviceClient
44
    ) {
45 20
        $this->metadataFactory  = $metadataFactory;
46 20
        $this->unityOfWork      = $unityOfWork;
47 20
        $this->webserviceClient = $webserviceClient;
48 20
    }
49
50
    
51 9
    public function save($object)
52
    {
53 9
        $transfer = $object;
54
        
55 9
        if ($object instanceof AccessInterceptorValueHolderInterface) {
56 7
            $transfer = $transfer->getWrappedValueHolderValue();
57
        }
58
        
59 9
        $metadata = $this->getClassMetadata($transfer);
60
        
61 9
        foreach ($metadata->associations as $name => $association) {
62 2
            $assocValue = $association->getValue($transfer);
63
            
64 2
            if (!$assocValue) {
65 1
                continue;
66
            }
67
            
68 2
            $this->persistAssociation($object, $assocValue, $metadata, $association);
69
        }
70
        
71 9
        $this->persistTransfer($object);
72 9
    }
73
    
74 2
    private function persistAssociation($object, $association, TransferMetadata $metadata, PropertyMetadata $property)
75
    {
76 2
        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 2
        if (!$this->unityOfWork->isNew($association) && !$this->unityOfWork->isDirty($association)) {
85
            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 View Code Duplication
    private function persistBelongsTo($object, $association, TransferMetadata $metadata, PropertyMetadata $property)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 9
    private function persistTransfer($object)
145
    {
146 9
        if ($this->unityOfWork->isNew($object)) {
147 3
            $this->webserviceClient->post($object);
148 3
            $this->renewState($object);
149
            
150 3
            return;
151
        }
152
        
153 7
        if ($this->unityOfWork->isDirty($object)) {
154 6
            $this->webserviceClient->put($object);
155 6
            $this->renewState($object);
156
            
157 6
            return;
158
        }
159
        
160 1
        if ($this->unityOfWork->isRemoved($object)) {
161 1
            $this->webserviceClient->delete(get_class($object), $this->getIdValue($object));
162
        }
163 1
    }
164
    
165 8
    private function renewState($object)
166
    {
167 8
        $this->unityOfWork->detach($object);
168 8
        $this->unityOfWork->attach($object);
169 8
    }
170
}
171