Passed
Push — master ( 0c659c...e395d1 )
by Pavel
06:21
created

SearchDehydrator   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 84.85%

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 9
dl 0
loc 147
ccs 56
cts 66
cp 0.8485
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
B transformCriteria() 0 21 5
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
            if (!$this->metadata->getReflectionClass()->isAbstract()) {
59 2
                $apiCriteria[$discriminatorField['fieldName']] = [$this->metadata->getDiscriminatorValue()];
60 2
            }
61 2
            foreach ($this->metadata->getSubclasses() as $subclass) {
62 2
                $subClassMetadata = $this->manager->getClassMetadata($subclass);
63 2
                if (!$subClassMetadata->getReflectionClass()->isAbstract()) {
64 2
                    $apiCriteria[$discriminatorField['fieldName']][] = $subClassMetadata->getDiscriminatorValue();
65 2
                }
66 2
            }
67 2
            sort($apiCriteria[$discriminatorField['fieldName']]);
68 2
        }
69
        
70 8
        return $apiCriteria;
71
    }
72
73
    /**
74
     * Converts doctrine entity criteria to API-ready criteria (converts types and field names)
75
     *
76
     * @param array $criteria
77
     *
78
     * @return array API-ready criteria
79
     */
80 14
    public function transformFields(array $criteria)
81
    {
82 14
        return $this->doTransform($criteria);
83
    }
84
85
    /**
86
     * Converts doctrine entity order to API-ready order (converts field names)
87
     *
88
     * @param array $orderBy
89
     *
90
     * @return array API-ready order
91
     */
92 7
    public function transformOrder(array $orderBy = null)
93
    {
94 7
        $apiOrder = [];
95 7
        foreach ((array)$orderBy as $field => $direction) {
96
            $apiOrder[$this->metadata->getApiFieldName($field)] = $direction;
97 7
        }
98
99 7
        return $apiOrder;
100
    }
101
102 22
    private function doTransform(array $criteria)
103
    {
104 22
        $apiCriteria = [];
105
106 22
        foreach ($criteria as $field => $values) {
107 20
            if ($this->metadata->hasAssociation($field)) {
108 4
                $mapping = $this->metadata->getAssociationMapping($field);
109
                /** @var EntityMetadata $target */
110 4
                $target = $this->manager->getClassMetadata($mapping['target']);
111
112
                $converter = function ($value) use ($target) {
113 4
                    if (!is_object($value)) {
114 1
                        return $value;
115
                    }
116
117 4
                    $ids = $target->getIdentifierValues($value);
118 4
                    if ($target->isIdentifierComposite) {
119
                        return $ids;
120
                    }
121
122 4
                    return array_shift($ids);
123 4
                };
124
125 4
                if ($values instanceof Collection) {
126
                    if ($values instanceof ApiCollection && !$values->isInitialized()) {
127
                        continue;
128
                    }
129
                    $values = $values->toArray();
130
                }
131
132 4
                if (is_array($values)) {
133
                    $values = array_map($converter, $values);
134
                } else {
135 4
                    $values = $converter($values);
136
                }
137 4
            } else {
138 20
                $caster = function ($value) use ($field) {
139 20
                    $type = $this->manager
140 20
                        ->getConfiguration()
141 20
                        ->getTypeRegistry()->get($this->metadata->getTypeOfField($field));
142
143 20
                    return $type->toApiValue($value, $this->metadata->getFieldOptions($field));
144 20
                };
145
146 20
                if (is_array($values)) {
147
                    $values = array_map($caster, $values);
148
                } else {
149 20
                    $values = $caster($values);
150
                }
151
            }
152
153 20
            $apiCriteria[$this->metadata->getApiFieldName($field)] = $values;
154 22
        }
155
156 22
        return $apiCriteria;
157
    }
158
}
159