DataTransformer   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 190
Duplicated Lines 5.26 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%
Metric Value
wmc 28
lcom 1
cbo 2
dl 10
loc 190
ccs 64
cts 64
cp 1
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A prepare() 0 8 1
C prepareData() 0 25 8
A prepareField() 0 10 2
B validate() 10 15 5
A prepareRelated() 0 20 4
A checkFieldsMapping() 0 13 4
A checkNullable() 0 8 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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