Passed
Pull Request — master (#14)
by Pavel
05:12
created

PatchDehydrator::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 3
crap 1
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 22
    public function __construct(EntityPersister $persister, ApiMetadata $metadata, ApiEntityManager $manager)
27
    {
28 22
        $this->persister = $persister;
29 22
        $this->metadata  = $metadata;
30 22
        $this->manager   = $manager;
31 22
    }
32
33 6
    public function convertEntityToData($entity)
34
    {
35 6
        $entityData = [];
36
37 6
        $discriminatorField = $this->metadata->getDiscriminatorField();
38
39 6
        if (null !== $discriminatorField) {
40 1
            $entityData[$discriminatorField['fieldName']] = $this->metadata->getDiscriminatorValue();
41 1
        }
42
43 6
        foreach ($this->metadata->getReflectionProperties() as $name => $property) {
44 6
            if ($this->metadata->isIdentifier($name) && $this->metadata->isIdentifierRemote()) {
45 6
                continue;
46
            }
47 6
            $apiField = $this->metadata->getApiFieldName($name);
48 6
            $value    = $property->getValue($entity);
49 6
            if (null === $value) {
50 6
                $entityData[$apiField] = $value;
51 6
                continue;
52
            }
53
54 3
            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);
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 1
                $typeName = $this->metadata->getTypeOfField($name);
76 1
                $type     = $this->manager->getConfiguration()->getTypeRegistry()->get($typeName);
77 1
                $value    = $type->toApiValue($value);
78
            }
79
80 3
            $entityData[$apiField] = $value;
81 6
        }
82
83 6
        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