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

SearchDehydrator   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 83.61%

Importance

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