Passed
Pull Request — master (#14)
by Pavel
03:16
created

ApiPersister::loadById()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
ccs 4
cts 5
cp 0.8
rs 9.4285
cc 2
eloc 5
nc 2
nop 2
crap 2.032
1
<?php
2
3
namespace Bankiru\Api\Doctrine\Persister;
4
5
use Bankiru\Api\Doctrine\ApiEntityManager;
6
use Bankiru\Api\Doctrine\Dehydration\PatchDehydrator;
7
use Bankiru\Api\Doctrine\Dehydration\SearchDehydrator;
8
use Bankiru\Api\Doctrine\Mapping\EntityMetadata;
9
use Bankiru\Api\Doctrine\Proxy\ApiCollection;
10
use Bankiru\Api\Doctrine\Rpc\CrudsApiInterface;
11
use Doctrine\Common\Collections\AbstractLazyCollection;
12
13
/** @internal */
14
final class ApiPersister implements EntityPersister
15
{
16
    /** @var  EntityMetadata */
17
    private $metadata;
18
    /** @var ApiEntityManager */
19
    private $manager;
20
    /** @var CrudsApiInterface */
21
    private $api;
22
    /** @var array */
23
    private $pendingInserts = [];
24
    /** @var SearchDehydrator */
25
    private $searchDehydrator;
26
    /** @var PatchDehydrator */
27
    private $patchDehydrator;
28
29
    /**
30
     * ApiPersister constructor.
31
     *
32
     * @param ApiEntityManager  $manager
33
     * @param CrudsApiInterface $api
34
     */
35 23
    public function __construct(ApiEntityManager $manager, CrudsApiInterface $api)
36
    {
37 23
        $this->manager          = $manager;
38 23
        $this->metadata         = $api->getMetadata();
39 23
        $this->api              = $api;
40 23
        $this->searchDehydrator = new SearchDehydrator($this->metadata, $this->manager);
41 23
        $this->patchDehydrator  = new PatchDehydrator($this, $this->metadata, $this->manager);
42 23
    }
43
44
    /** {@inheritdoc} */
45
    public function getClassMetadata()
46
    {
47
        return $this->metadata;
48
    }
49
50
    /** {@inheritdoc} */
51 6
    public function getCrudsApi()
52
    {
53 6
        return $this->api;
54
    }
55
56
    /** {@inheritdoc} */
57 2
    public function update($entity)
58
    {
59 2
        $patch = $this->patchDehydrator->prepareUpdateData($entity);
60 2
        $data  = $this->patchDehydrator->convertEntityToData($entity);
61
62 2
        $this->api->patch($this->searchDehydrator->transformIdentifier($entity), $patch, $data);
63 2
    }
64
65
    /** {@inheritdoc} */
66 1
    public function delete($entity)
67
    {
68 1
        return $this->api->remove($this->searchDehydrator->transformIdentifier($entity));
69
    }
70
71
    /** {@inheritdoc} */
72 1
    public function count($criteria = [])
73
    {
74 1
        return $this->api->count($this->searchDehydrator->transformCriteria($criteria));
75
    }
76
77
    /** {@inheritdoc} */
78 5
    public function loadAll(array $criteria = [], array $orderBy = null, $limit = null, $offset = null)
79
    {
80 5
        $objects = $this->api->search(
81 5
            $this->searchDehydrator->transformCriteria($criteria),
82 5
            $this->searchDehydrator->transformOrder($orderBy),
83 5
            $limit,
84
            $offset
85 5
        );
86
87 5
        $entities = [];
88 5
        foreach ($objects as $object) {
89 5
            $entities[] = $this->manager->getUnitOfWork()->getOrCreateEntity($this->metadata->getName(), $object);
90 5
        }
91
92 5
        return $entities;
93
    }
94
95
    /** {@inheritdoc} */
96
    public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = [])
97
    {
98
        if (false !== ($foundEntity = $this->manager->getUnitOfWork()->tryGetById($identifier, $assoc['target']))) {
99
            return $foundEntity;
100
        }
101
102
        // Get identifiers from entity if the entity is not the owning side
103
        if (!$assoc['isOwningSide']) {
104
            $identifier = $this->metadata->getIdentifierValues($sourceEntity);
105
        }
106
107
        return $this->loadById($identifier);
108
    }
109
110
    /** {@inheritdoc} */
111 12
    public function loadById(array $identifiers, $entity = null)
112
    {
113 12
        $body = $this->api->find($this->searchDehydrator->transformFields($identifiers));
114
115 12
        if (null === $body) {
116
            return null;
117
        }
118
119 12
        return $this->manager->getUnitOfWork()->getOrCreateEntity($this->metadata->getName(), $body);
120
    }
121
122
    /** {@inheritdoc} */
123
    public function refresh(array $id, $entity)
124
    {
125
        $this->loadById($id, $entity);
126
    }
127
128
    /** {@inheritdoc} */
129 2
    public function loadOneToManyCollection(array $assoc, $sourceEntity, AbstractLazyCollection $collection)
130
    {
131
        $criteria = [
132 2
            $assoc['mappedBy'] => $sourceEntity,
133 2
        ];
134
135 2
        $orderBy = isset($assoc['orderBy']) ? $assoc['orderBy'] : [];
136
137 2
        $source = $this->api->search(
138 2
            $this->searchDehydrator->transformCriteria($criteria),
139 2
            $this->searchDehydrator->transformOrder($orderBy)
140 2
        );
141
142 2
        $target = $this->manager->getClassMetadata($assoc['target']);
143
144 2
        foreach ($source as $object) {
145 2
            $entity = $this->manager->getUnitOfWork()->getOrCreateEntity($target->getName(), $object);
146 2
            if (isset($assoc['orderBy'])) {
147
                $index = $target->getReflectionProperty($assoc['orderBy'])->getValue($entity);
148
                $collection->set($index, $entity);
149
            } else {
150 2
                $collection->add($entity);
151
            }
152
153 2
            $target->getReflectionProperty($assoc['mappedBy'])->setValue($entity, $sourceEntity);
154 2
        }
155
156 2
        return $collection;
157
    }
158
159
    /** {@inheritdoc} */
160 10
    public function getOneToManyCollection(array $assoc, $sourceEntity, $limit = null, $offset = null)
161
    {
162 10
        $targetClass = $assoc['target'];
163
        /** @var EntityMetadata $targetMetadata */
164 10
        $targetMetadata = $this->manager->getClassMetadata($targetClass);
165
166 10
        if ($this->metadata->isIdentifierComposite) {
167
            throw new \BadMethodCallException(__METHOD__ . ' on composite reference is not supported');
168
        }
169
170 10
        $apiCollection = new ApiCollection($this->manager, $targetMetadata);
171 10
        $apiCollection->setOwner($sourceEntity, $assoc);
172 10
        $apiCollection->setInitialized(false);
173
174 10
        return $apiCollection;
175
    }
176
177
    /** {@inheritdoc} */
178 5
    public function getToOneEntity(array $mapping, $sourceEntity, array $identifiers)
179
    {
180 5
        $metadata = $this->manager->getClassMetadata(get_class($sourceEntity));
181
182 5
        if (!$mapping['isOwningSide']) {
183
            $identifiers = $metadata->getIdentifierValues($sourceEntity);
184
        }
185
186 5
        return $this->manager->getReference($mapping['target'], $identifiers);
187
    }
188
189 6
    public function pushNewEntity($entity)
190
    {
191 6
        $this->pendingInserts[spl_object_hash($entity)] = $entity;
192 6
    }
193
194 6
    public function flushNewEntities()
195
    {
196 6
        $result = [];
197 6
        foreach ($this->pendingInserts as $entity) {
198 6
            $result[] = [
199 6
                'generatedId' => $this->getCrudsApi()->create($this->patchDehydrator->convertEntityToData($entity)),
200 6
                'entity'      => $entity,
201
            ];
202 6
        }
203
204 6
        $this->pendingInserts = [];
205
206 6
        if ($this->metadata->isIdentifierNatural()) {
207
            return [];
208
        }
209
210 6
        return $result;
211
    }
212
213
    /** {@inheritdoc} */
214 1
    public function hasPendingUpdates($oid)
215
    {
216 1
        return isset($this->pendingInserts[$oid]);
217
    }
218
}
219