Passed
Push — master ( 30b30c...28afa9 )
by JHONATAN
09:58
created

TransferPersister::renewState()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Vox\Webservice;
4
5
use Metadata\MetadataFactoryInterface;
6
use ProxyManager\Proxy\AccessInterceptorValueHolderInterface;
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 15
    public function __construct(
40
        MetadataFactoryInterface $metadataFactory,
41
        UnityOfWorkInterface $unityOfWork,
42
        WebserviceClientInterface $webserviceClient
43
    ) {
44 15
        $this->metadataFactory  = $metadataFactory;
45 15
        $this->unityOfWork      = $unityOfWork;
46 15
        $this->webserviceClient = $webserviceClient;
47 15
    }
48
49
    
50 6
    public function save($object)
51
    {
52 6
        $transfer = $object;
53
        
54 6
        if ($object instanceof AccessInterceptorValueHolderInterface) {
55 5
            $transfer = $transfer->getWrappedValueHolderValue();
56
        }
57
        
58 6
        $metadata = $this->getClassMetadata($transfer);
59
        
60 6
        foreach ($metadata->associations as $name => $association) {
61 1
            $assocValue = $association->getValue($transfer);
62
            
63 1
            if (!$assocValue) {
64
                continue;
65
            }
66
            
67 1
            $this->persistAssociation($object, $assocValue, $metadata, $association);
68
        }
69
        
70 6
        $this->persistTransfer($object);
71 6
    }
72
    
73 1
    private function persistAssociation($object, $association, TransferMetadata $metadata, PropertyMetadata $property)
74
    {
75 1
        if (is_array($association) || $association instanceof Traversable) {
76
            foreach ($association as $transfer) {
77
                $this->persistAssociation($object, $transfer, $metadata, $property);
78
            }
79
        }
80
        
81 1
        if (!$this->unityOfWork->isNew($association) && !$this->unityOfWork->isDirty($association)) {
82
            return;
83
        }
84
        
85 1
        $this->save($association);
86
        
87 1
        if ($property->hasAnnotation(BelongsTo::class)) {
88 1
            $this->persistBelongsTo($object, $association, $metadata, $property);
89
        }
90
        
91 1
        if ($property->hasAnnotation(HasOne::class)) {
92
            $this->persistHas($object, $association, $property, $property->getAnnotation(HasOne::class));
93
        }
94
        
95 1
        if ($property->hasAnnotation(HasMany::class)) {
96
            $this->persistHas($object, $association, $property, $property->getAnnotation(HasMany::class));
97
        }
98 1
    }
99
    
100 1
    private function persistBelongsTo($object, $association, TransferMetadata $metadata, PropertyMetadata $property)
101
    {
102
        /* @var $belongsTo BelongsTo */
103 1
        $belongsTo       = $property->getAnnotation(BelongsTo::class);
104 1
        $foreignProperty = $metadata->propertyMetadata[$belongsTo->foreignField];
105 1
        $foreignId       = $foreignProperty->getValue($object);
106 1
        $currentId       = $this->getIdValue($association);
107
108 1
        if ($foreignId !== $currentId) {
109 1
            $foreignProperty->setValue($object, $currentId);
110
        }
111 1
    }
112
    
113
    private function persistHas($object, $association, PropertyMetadata $property, $annotation) 
114
    {
115
        $relationClassMetadata = $this->metadataFactory->getMetadataForClass($property->type);
116
        $relationObject        = $property->getValue($object);
117
        $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...
118
        $foreignId             = $foreignProperty->getValue($relationObject);
119
        $currentId             = $this->getIdValue($association);
120
121
        if ($foreignId !== $currentId) {
122
            $foreignProperty->setValue($relationObject, $currentId);
123
        }
124
    }
125
    
126 6
    private function persistTransfer($object)
127
    {
128 6
        if ($this->unityOfWork->isNew($object)) {
129 2
            $this->webserviceClient->post($object);
130 2
            $this->renewState($object);
131
            
132 2
            return;
133
        }
134
        
135 5
        if ($this->unityOfWork->isDirty($object)) {
136 4
            $this->webserviceClient->put($object);
137 4
            $this->renewState($object);
138
            
139 4
            return;
140
        }
141
        
142 1
        if ($this->unityOfWork->isRemoved($object)) {
143 1
            $this->webserviceClient->delete(get_class($object), $this->getIdValue($object));
144
        }
145 1
    }
146
    
147 5
    private function renewState($object)
148
    {
149 5
        $this->unityOfWork->detach($object);
150 5
        $this->unityOfWork->attach($object);
151 5
    }
152
}
153