DataTransformer::checkNullable()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3
Metric Value
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4285
cc 3
eloc 4
nc 2
nop 3
crap 3
1
<?php
2
namespace Ajir\RabbitMqSqlBundle\DataTransformer;
3
4
use InvalidArgumentException;
5
use Ajir\RabbitMqSqlBundle\DataMapper\DataMapperInterface;
6
use Ajir\RabbitMqSqlBundle\DataValidator\DataValidatorInterface;
7
8
/**
9
 * Class DataTransformer
10
 *
11
 * @author Florian Ajir <[email protected]>
12
 */
13
class DataTransformer implements DataTransformerInterface
14
{
15
    const RELATED_KEY = '_related';
16
    const RELATED_RELATION_KEY = '_relation';
17
    const RELATED_DATA_KEY = '_data';
18
    const IDENTIFIER_KEY = '_identifier';
19
    const DISCRIMINATOR_KEY = '_discriminator';
20
    const TABLE_KEY = '_table';
21
22
    /**
23
     * @var DataMapperInterface
24
     */
25
    protected $mapper;
26
27
    /**
28
     * @var DataValidatorInterface
29
     */
30
    protected $validator;
31
32
    /**
33
     * @param DataMapperInterface    $mapper
34
     * @param DataValidatorInterface $validator
35
     */
36 10
    public function __construct(DataMapperInterface $mapper, DataValidatorInterface $validator = null)
37
    {
38 10
        $this->mapper = $mapper;
39 10
        $this->validator = $validator;
40 10
    }
41
42
    /**
43
     * Prepare data from mapping rules (recursive)
44
     *
45
     * @param string $type
46
     * @param array  $data
47
     *
48
     * @return array
49
     *
50
     * @throws InvalidArgumentException
51
     */
52 10
    public function prepare($type, array $data)
53
    {
54 10
        $prepared = array();
55 10
        $data = $this->prepareData($type, $data);
56 7
        $prepared[$type] = $this->checkFieldsMapping($type, $data);
57
58 6
        return $prepared;
59
    }
60
61
    /**
62
     * @param string $type
63
     * @param array  $data
64
     *
65
     * @return array
66
     */
67 10
    protected function prepareData($type, array $data)
68
    {
69 10
        $prepared = array();
70 10
        if ($identifier = $this->mapper->getIdentifier($type)) {
71 7
            $prepared[self::IDENTIFIER_KEY] = $identifier;
72
        }
73 10
        if ($tableName = $this->mapper->getTableName($type)) {
74 8
            $prepared[self::TABLE_KEY] = $tableName;
75
        }
76 10
        if ($discr = $this->mapper->getDiscriminator($type)) {
77 1
            if (array_key_exists($discr, $data)) {
78 1
                $prepared[self::TABLE_KEY] = $data[$discr];
79
            }
80
        }
81 10
        foreach ($data as $field => $value) {
82 10
            $fieldMapping = $this->mapper->getFieldMapping($type, $field);
83 10
            if (!empty($fieldMapping)) {
84 10
                $this->prepareField($prepared, $type, $field, $value);
85 3
            } elseif ($relation = $this->mapper->getRelation($type, $field)) {
86 8
                $this->prepareRelated($prepared, $type, $field, $value, $relation);
87
            }
88
        }
89
90 7
        return $prepared;
91
    }
92
93
    /**
94
     * @param array  &$prepared
95
     * @param string $type
96
     * @param string $field
97
     * @param string $value
98
     *
99
     * @return array
100
     */
101 10
    protected function prepareField(array &$prepared, $type, $field, $value)
102
    {
103 10
        if ($this->validator) {
104 5
            $this->validate($type, $field, $value);
105
        }
106 8
        $fieldColumn = $this->mapper->getFieldColumn($type, $field);
107 8
        $prepared[$fieldColumn] = $value;
108
109 8
        return $prepared;
110
    }
111
112
    /**
113
     * @param string $type
114
     * @param string $field
115
     * @param string  $value
116
     *
117
     * @throws InvalidArgumentException
118
     */
119 5
    protected function validate($type, $field, $value)
120
    {
121
        // validate length if defined
122 5 View Code Duplication
        if ($maxLength = $this->mapper->getFieldMaxLength($type, $field)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
123 4
            if (!$this->validator->validateLength($value, $maxLength)) {
124 2
                throw new InvalidArgumentException($type . '.' . $field . ' value length exceed database max length.');
125
            }
126
        }
127
        // validate field type
128 3 View Code Duplication
        if ($fieldType = $this->mapper->getFieldType($type, $field)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129 3
            if (!$this->validator->validateType($value, $fieldType)) {
130 1
                throw new InvalidArgumentException($type . '.' . $field . ' type not valid.');
131
            }
132
        }
133 3
    }
134
135
    /**
136
     * @param array  &$prepared
137
     * @param string $type
138
     * @param string $field
139
     * @param array  $data
140
     * @param string $relation
141
     *
142
     * @return array
143
     */
144 2
    protected function prepareRelated(array &$prepared, $type, $field, array $data, $relation)
145
    {
146 2
        $relationInfos = $this->mapper->getRelationInfos($type, $field, $relation);
147 2
        if ($relationInfos) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $relationInfos of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
148 2
            $collection = $this->mapper->isCollection($relation);
149 2
            $targetEntity = $this->mapper->getTargetEntity($type, $field, $relation);
150 2
            $prepared[self::RELATED_KEY][$relation][$targetEntity][self::RELATED_RELATION_KEY] = $relationInfos;
151 2
            $relatedData = array();
152 2
            if ($collection) {
153 1
                foreach ($data as $element) {
154 1
                    $relatedData[] = $this->prepare($targetEntity, $element);
155
                }
156
            } else {
157 1
                $relatedData = $this->prepare($targetEntity, $data);
158
            }
159 2
            $prepared[self::RELATED_KEY][$relation][$targetEntity][self::RELATED_DATA_KEY] = $relatedData;
160
        }
161
162 2
        return $prepared;
163
    }
164
165
    /**
166
     * Last step of prepare which loop over entity mapping fields
167
     *
168
     * @param string $type entity name
169
     * @param array  $data entity data
170
     *
171
     * @return array
172
     */
173 7
    protected function checkFieldsMapping($type, array $data)
174
    {
175 7
        foreach ($this->mapper->getFieldsName($type) as $field) {
176 7
            if ($this->validator) {
177 2
                $this->checkNullable($type, $field, $data);
178
            }
179 6
            if ($fixedValue = $this->mapper->getFixedFieldMapping($type, $field)) {
180 6
                $data = array_merge($data, $fixedValue);
181
            }
182
        }
183
184 6
        return $data;
185
    }
186
187
    /**
188
     * @param string $type
189
     * @param string $field
190
     * @param array  $data
191
     *
192
     * @throws InvalidArgumentException
193
     */
194 2
    protected function checkNullable($type, $field, array $data)
195
    {
196 2
        if (!$this->mapper->isFieldNullable($type, $field)
197 2
            && !isset($data[$this->mapper->getFieldColumn($type, $field)])
198
        ) {
199 1
            throw new InvalidArgumentException($type . '.' . $field . ' is not nullable.');
200
        }
201 1
    }
202
}
203