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

PatchDehydrator   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 94.52%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 8
dl 0
loc 137
ccs 69
cts 73
cp 0.9452
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
C convertEntityToData() 0 52 11
D prepareUpdateData() 0 39 10
1
<?php
2
3
namespace Bankiru\Api\Doctrine\Dehydration;
4
5
use Bankiru\Api\Doctrine\ApiEntityManager;
6
use Bankiru\Api\Doctrine\Mapping\ApiMetadata;
7
use Bankiru\Api\Doctrine\Persister\EntityPersister;
8
9
/** @internal */
10
final class PatchDehydrator
11
{
12
    /** @var EntityPersister */
13
    private $persister;
14
    /** @var ApiMetadata */
15
    private $metadata;
16
    /** @var ApiEntityManager */
17
    private $manager;
18
19
    /**
20
     * PatchDehydrator constructor.
21
     *
22
     * @param EntityPersister  $persister
23
     * @param ApiMetadata      $metadata
24
     * @param ApiEntityManager $manager
25
     */
26 25
    public function __construct(EntityPersister $persister, ApiMetadata $metadata, ApiEntityManager $manager)
27
    {
28 25
        $this->persister = $persister;
29 25
        $this->metadata  = $metadata;
30 25
        $this->manager   = $manager;
31 25
    }
32
33 7
    public function convertEntityToData($entity)
34
    {
35 7
        $entityData = [];
36
37 7
        $discriminatorField = $this->metadata->getDiscriminatorField();
38
39 7
        if (null !== $discriminatorField) {
40 1
            $entityData[$discriminatorField['fieldName']] = $this->metadata->getDiscriminatorValue();
41 1
        }
42
43 7
        foreach ($this->metadata->getReflectionProperties() as $name => $property) {
44 7
            if ($this->metadata->isIdentifier($name) && $this->metadata->isIdentifierRemote()) {
45 7
                continue;
46
            }
47 7
            $apiField = $this->metadata->getApiFieldName($name);
48 7
            $value    = $property->getValue($entity);
49 7
            if (null === $value) {
50 6
                $entityData[$apiField] = $value;
51 6
                continue;
52
            }
53
54 4
            if ($this->metadata->hasAssociation($name)) {
55 2
                $mapping = $this->metadata->getAssociationMapping($name);
56 2
                if (($mapping['type'] & ApiMetadata::TO_MANY) && !$mapping['isOwningSide']) {
57 2
                    continue;
58
                }
59 2
                $target         = $this->metadata->getAssociationMapping($name)['target'];
60 2
                $targetMetadata = $this->manager->getClassMetadata($target);
61 2
                $value          = $targetMetadata->getIdentifierValues($value);
62 2
                $ids            = [];
63 2
                foreach ($value as $idName => $idValue) {
64 2
                    $typeName        = $targetMetadata->getTypeOfField($idName);
65 2
                    $idApiName       = $targetMetadata->getApiFieldName($idName);
66 2
                    $type            = $this->manager->getConfiguration()->getTypeRegistry()->get($typeName);
67 2
                    $idValue         = $type->toApiValue($idValue, $targetMetadata->getFieldOptions($idName));
68 2
                    $ids[$idApiName] = $idValue;
69 2
                }
70 2
                if (!$targetMetadata->isIdentifierComposite()) {
0 ignored issues
show
Bug introduced by
The method isIdentifierComposite() does not exist on Doctrine\Common\Persistence\Mapping\ClassMetadata. Did you maybe mean isIdentifier()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
71 2
                    $ids = array_shift($ids);
72 2
                }
73 2
                $value = $ids;
74 2
            } else {
75 2
                $typeName = $this->metadata->getTypeOfField($name);
76 2
                $type     = $this->manager->getConfiguration()->getTypeRegistry()->get($typeName);
77 2
                $value    = $type->toApiValue($value, $this->metadata->getFieldOptions($name));
78
            }
79
80 4
            $entityData[$apiField] = $value;
81 7
        }
82
83 7
        return $entityData;
84
    }
85
86
    /**
87
     * Prepares the changeset of an entity for database insertion (UPDATE).
88
     *
89
     * The changeset is obtained from the currently running UnitOfWork.
90
     *
91
     * During this preparation the array that is passed as the second parameter is filled with
92
     * <columnName> => <value> pairs, grouped by table name.
93
     *
94
     * Example:
95
     * <code>
96
     * array(
97
     *    'foo_table' => array('column1' => 'value1', 'column2' => 'value2', ...),
98
     *    'bar_table' => array('columnX' => 'valueX', 'columnY' => 'valueY', ...),
99
     *    ...
100
     * )
101
     * </code>
102
     *
103
     * @param object $entity The entity for which to prepare the data.
104
     *
105
     * @return array The prepared data.
106
     */
107 2
    public function prepareUpdateData($entity)
108
    {
109 2
        $result = [];
110 2
        $uow    = $this->manager->getUnitOfWork();
111 2
        foreach ($uow->getEntityChangeSet($entity) as $field => $change) {
112 2
            $newVal = $change[1];
113 2
            if (!$this->metadata->hasAssociation($field)) {
114
115 1
                $result[$this->metadata->getApiFieldName($field)] = $newVal;
116 1
                continue;
117
            }
118 1
            $assoc = $this->metadata->getAssociationMapping($field);
119
            // Only owning side of x-1 associations can have a FK column.
120 1
            if (!$assoc['isOwningSide'] || !($assoc['type'] & ApiMetadata::TO_ONE)) {
121
                continue;
122
            }
123 1
            if ($newVal !== null) {
124 1
                $oid = spl_object_hash($newVal);
125 1
                if ($this->persister->hasPendingUpdates($oid) || $uow->isScheduledForInsert($newVal)) {
126
                    // The associated entity $newVal is not yet persisted, so we must
127
                    // set $newVal = null, in order to insert a null value and schedule an
128
                    // extra update on the UnitOfWork.
129
                    $uow->scheduleExtraUpdate($entity, [$field => [null, $newVal]]);
130
                    $newVal = null;
131
                }
132 1
            }
133 1
            $newValId = null;
134 1
            if ($newVal !== null) {
135 1
                $newValId = $uow->getEntityIdentifier($newVal);
136 1
            }
137
            $targetClass                                      =
138 1
                $this->manager->getClassMetadata($assoc['target']);
139 1
            $result[$this->metadata->getApiFieldName($field)] = $newValId
140 1
                ? $newValId[$targetClass->getIdentifierFieldNames()[0]]
141 1
                : null;
142 2
        }
143
144 2
        return $result;
145
    }
146
}
147