Passed
Push — master ( 68f2b4...691f88 )
by Pavel
03:56 queued 21s
created

SearchDehydrator   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 143
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 83.87%

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 8
dl 0
loc 143
ccs 52
cts 62
cp 0.8387
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A transformIdentifier() 0 4 1
A transformCriteria() 0 17 3
A transformFields() 0 4 1
A transformOrder() 0 9 2
C doTransform() 0 56 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\Mapping\EntityMetadata;
8
use Bankiru\Api\Doctrine\Proxy\ApiCollection;
9
use Doctrine\Common\Collections\Collection;
10
11
/** @internal */
12
final class SearchDehydrator
13
{
14
    /** @var  ApiMetadata */
15
    private $metadata;
16
    /** @var  ApiEntityManager */
17
    private $manager;
18
19
    /**
20
     * SearchDehydrator constructor.
21
     *
22
     * @param ApiMetadata      $metadata
23
     * @param ApiEntityManager $manager
24
     */
25 26
    public function __construct(ApiMetadata $metadata, ApiEntityManager $manager)
26
    {
27 26
        $this->metadata = $metadata;
28 26
        $this->manager  = $manager;
29 26
    }
30
31
    /**
32
     * Converts doctrine object identifiers to API-ready criteria (converts types and field names)
33
     *
34
     * @param object $entity
35
     *
36
     * @return array API-ready identifier criteria
37
     */
38 3
    public function transformIdentifier($entity)
39
    {
40 3
        return $this->doTransform($this->metadata->getIdentifierValues($entity));
41
    }
42
43
    /**
44
     * Converts doctrine entity criteria to API-ready criteria (converts types and field names)
45
     * Appends discriminator for searching
46
     *
47
     * @param array $criteria
48
     *
49
     * @return array API-ready criteria
50
     */
51 8
    public function transformCriteria(array $criteria)
52
    {
53 8
        $apiCriteria = $this->doTransform($criteria);
54
55 8
        $discriminatorField = $this->metadata->getDiscriminatorField();
56
57 8
        if (null !== $discriminatorField) {
58 2
            $apiCriteria[$discriminatorField['fieldName']] = [$this->metadata->getDiscriminatorValue()];
59 2
            foreach ($this->metadata->getSubclasses() as $subclass) {
60 2
                $apiCriteria[$discriminatorField['fieldName']][] =
61 2
                    $this->manager->getClassMetadata($subclass)->getDiscriminatorValue();
62 2
            }
63 2
            sort($apiCriteria[$discriminatorField['fieldName']]);
64 2
        }
65
66 8
        return $apiCriteria;
67
    }
68
69
    /**
70
     * Converts doctrine entity criteria to API-ready criteria (converts types and field names)
71
     *
72
     * @param array $criteria
73
     *
74
     * @return array API-ready criteria
75
     */
76 14
    public function transformFields(array $criteria)
77
    {
78 14
        return $this->doTransform($criteria);
79
    }
80
81
    /**
82
     * Converts doctrine entity order to API-ready order (converts field names)
83
     *
84
     * @param array $orderBy
85
     *
86
     * @return array API-ready order
87
     */
88 7
    public function transformOrder(array $orderBy = null)
89
    {
90 7
        $apiOrder = [];
91 7
        foreach ((array)$orderBy as $field => $direction) {
92
            $apiOrder[$this->metadata->getApiFieldName($field)] = $direction;
93 7
        }
94
95 7
        return $apiOrder;
96
    }
97
98 22
    private function doTransform(array $criteria)
99
    {
100 22
        $apiCriteria = [];
101
102 22
        foreach ($criteria as $field => $values) {
103 20
            if ($this->metadata->hasAssociation($field)) {
104 4
                $mapping = $this->metadata->getAssociationMapping($field);
105
                /** @var EntityMetadata $target */
106 4
                $target = $this->manager->getClassMetadata($mapping['target']);
107
108
                $converter = function ($value) use ($target) {
109 4
                    if (!is_object($value)) {
110 1
                        return $value;
111
                    }
112
113 4
                    $ids = $target->getIdentifierValues($value);
114 4
                    if ($target->isIdentifierComposite) {
115
                        return $ids;
116
                    }
117
118 4
                    return array_shift($ids);
119 4
                };
120
121 4
                if ($values instanceof Collection) {
122
                    if ($values instanceof ApiCollection && !$values->isInitialized()) {
123
                        continue;
124
                    }
125
                    $values = $values->toArray();
126
                }
127
128 4
                if (is_array($values)) {
129
                    $values = array_map($converter, $values);
130
                } else {
131 4
                    $values = $converter($values);
132
                }
133 4
            } else {
134 20
                $caster = function ($value) use ($field) {
135 20
                    $type = $this->manager
136 20
                        ->getConfiguration()
137 20
                        ->getTypeRegistry()->get($this->metadata->getTypeOfField($field));
138
139 20
                    return $type->toApiValue($value, $this->metadata->getFieldOptions($field));
140 20
                };
141
142 20
                if (is_array($values)) {
143
                    $values = array_map($caster, $values);
144
                } else {
145 20
                    $values = $caster($values);
146
                }
147
            }
148
149 20
            $apiCriteria[$this->metadata->getApiFieldName($field)] = $values;
150 22
        }
151
152 22
        return $apiCriteria;
153
    }
154
}
155