Completed
Push — 14.x ( 855d13...227841 )
by Tim
02:29
created

AdditionalAttributeCsvSerializer   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 316
Duplicated Lines 12.97 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 96.83%

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 5
dl 41
loc 316
ccs 61
cts 63
cp 0.9683
rs 10
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 1
A getConfiguration() 0 4 1
A getValueCsvSerializerFactory() 0 4 1
A setValueCsvSerializer() 0 4 1
A getValueCsvSerializer() 0 4 1
A getImportProcessor() 0 4 1
A getEntityTypeId() 0 4 1
A getMultipleValueDelimiter() 0 4 1
A getMultipleFieldDelimiter() 0 4 1
A loadAttributeByAttributeCode() 0 4 1
A pack() 20 20 4
A init() 0 9 1
A unserialize() 0 21 4
A serialize() 0 16 4
A explode() 0 4 2
A implode() 0 4 2
A unpack() 20 20 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
3
/**
4
 * TechDivision\Import\Serializers\AdditionalAttributeCsvSerializer
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2018 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/techdivision/import
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Serializers;
22
23
use TechDivision\Import\Configuration\CsvConfigurationInterface;
24
use TechDivision\Import\Utils\FrontendInputTypes;
25
use TechDivision\Import\Utils\MemberNames;
26
use TechDivision\Import\ConfigurationInterface;
27
use TechDivision\Import\Services\ImportProcessorInterface;
28
29
/**
30
 * Serializer implementation that un-/serializes the additional product attribues found in the CSV file
31
 * in the row 'additional_attributes'.
32
 *
33
 * @author    Tim Wagner <[email protected]>
34
 * @copyright 2018 TechDivision GmbH <[email protected]>
35
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
36
 * @link      https://github.com/techdivision/import
37
 * @link      http://www.techdivision.com
38
 */
39
class AdditionalAttributeCsvSerializer extends AbstractCsvSerializer
40
{
41
42
    /**
43
     * The factory instance for the CSV value serializer.
44
     *
45
     * @var \TechDivision\Import\Serializers\ConfigurationAwareSerializerFactoryInterface
46
     */
47
    private $valueCsvSerializerFactory;
48
49
    /**
50
     * The CSV value serializer instance.
51
     *
52
     * @var \TechDivision\Import\Serializers\SerializerInterface
53
     */
54
    private $valueCsvSerializer;
55
56
    /**
57
     * The entity type from the configuration.
58
     *
59
     * @var array
60
     */
61
    private $entityType;
62
63
    /**
64
     *  The configuration instance.
65
     *
66
     * @var \TechDivision\Import\ConfigurationInterface
67
     */
68
    private $configuration;
69
70
    /**
71
     * The convert processor instance.
72
     *
73
     * @var \TechDivision\Import\Services\ImportProcessorInterface
74
     */
75
    private $importProcessor;
76
77
    /**
78
     * Initialize the serializer with the passed CSV value serializer factory.
79
     *
80
     * @param \TechDivision\Import\ConfigurationInterface                                   $configuration             The configuration instance
81
     * @param \TechDivision\Import\Services\ImportProcessorInterface                        $importProcessor           The processor instance
82
     * @param \TechDivision\Import\Serializers\ConfigurationAwareSerializerFactoryInterface $valueCsvSerializerFactory The CSV value serializer factory
83
     */
84 10
    public function __construct(
85
        ConfigurationInterface $configuration,
86
        ImportProcessorInterface $importProcessor,
87
        ConfigurationAwareSerializerFactoryInterface $valueCsvSerializerFactory
88
    ) {
89
90
        // set the passed instances
91 10
        $this->configuration = $configuration;
92 10
        $this->importProcessor = $importProcessor;
93 10
        $this->valueCsvSerializerFactory = $valueCsvSerializerFactory;
94
95
        // load the entity type for the entity type defined in the configuration
96 10
        $this->entityType = $importProcessor->getEavEntityTypeByEntityTypeCode($configuration->getEntityTypeCode());
97 10
    }
98
99
    /**
100
     * Returns the configuration instance.
101
     *
102
     * @return \TechDivision\Import\ConfigurationInterface The configuration instance
103
     */
104 10
    protected function getConfiguration()
105
    {
106 10
        return $this->configuration;
107
    }
108
109
    /**
110
     * Returns the factory instance for the CSV value serializer.
111
     *
112
     * @return \TechDivision\Import\Serializers\ConfigurationAwareSerializerFactoryInterface The CSV value serializer factory instance
113
     */
114 10
    protected function getValueCsvSerializerFactory()
115
    {
116 10
        return $this->valueCsvSerializerFactory;
117
    }
118
119
    /**
120
     * Returns the CSV value serializer instance.
121
     *
122
     * @param \TechDivision\Import\Serializers\SerializerInterface $valueCsvSerializer The CSV value serializer instance
123
     *
124
     * @return void
125
     */
126 10
    protected function setValueCsvSerializer(SerializerInterface $valueCsvSerializer)
127
    {
128 10
        $this->valueCsvSerializer = $valueCsvSerializer;
129 10
    }
130
131
    /**
132
     * Returns the CSV value serializer instance.
133
     *
134
     * @return \TechDivision\Import\Serializers\SerializerInterface The CSV value serializer instance
135
     */
136 10
    protected function getValueCsvSerializer()
137
    {
138 10
        return $this->valueCsvSerializer;
139
    }
140
141
    /**
142
     * Returns the import processor instance.
143
     *
144
     * @return \TechDivision\Import\Services\ImportProcessorInterface The import processor instance
145
     */
146 8
    protected function getImportProcessor()
147
    {
148 8
        return $this->importProcessor;
149
    }
150
151
    /**
152
     * Returns entity type ID mapped from the configuration.
153
     *
154
     * @return integer The mapped entity type ID
155
     */
156 8
    protected function getEntityTypeId()
157
    {
158 8
        return $this->entityType[MemberNames::ENTITY_TYPE_ID];
159
    }
160
161
    /**
162
     * Returns the multiple value delimiter from the configuration.
163
     *
164
     * @return string The multiple value delimiter
165
     */
166 4
    protected function getMultipleValueDelimiter()
167
    {
168 4
        return $this->getConfiguration()->getMultipleValueDelimiter();
169
    }
170
171
    /**
172
     * Returns the multiple field delimiter from the configuration.
173
     *
174
     * @return string The multiple field delimiter
175
     */
176 10
    protected function getMultipleFieldDelimiter()
177
    {
178 10
        return $this->getConfiguration()->getMultipleFieldDelimiter();
179
    }
180
181
    /**
182
     * Loads and returns the attribute with the passed code from the database.
183
     *
184
     * @param string $attributeCode The code of the attribute to return
185
     *
186
     * @return array The attribute
187
     */
188 8
    protected function loadAttributeByAttributeCode($attributeCode)
189
    {
190 8
        return $this->getImportProcessor()->getEavAttributeByEntityTypeIdAndAttributeCode($this->getEntityTypeId(), $attributeCode);
191
    }
192
193
    /**
194
     * Packs the passed value according to the frontend input type of the attribute with the passed code.
195
     *
196
     * @param string $attributeCode The code of the attribute to pack the passed value for
197
     * @param mixed  $value         The value to pack
198
     *
199
     * @return string The packed value
200
     */
201 3 View Code Duplication
    protected function pack($attributeCode, $value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
202
    {
203
204
        // load the attibute with the passed code
205 3
        $attribute = $this->loadAttributeByAttributeCode($attributeCode);
206
207
        // pack the value according to the attribute's frontend input type
208 3
        switch ($attribute[MemberNames::FRONTEND_INPUT]) {
209 3
            case FrontendInputTypes::MULTISELECT:
210 1
                return implode($this->getMultipleValueDelimiter(), $value);
211
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
212
213 3
            case FrontendInputTypes::BOOLEAN:
214 1
                return $value === true ? 'true' : 'false';
215
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
216
217
            default:
218 3
                return $value;
219
        }
220
    }
221
222
    /**
223
     * Unpacks the passed value according to the frontend input type of the attribute with the passed code.
224
     *
225
     * @param string $attributeCode The code of the attribute to pack the passed value for
226
     * @param string $value         The value to unpack
227
     *
228
     * @return mixed The unpacked value
229
     */
230 5 View Code Duplication
    protected function unpack($attributeCode, $value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
231
    {
232
233
        // load the attibute with the passed code
234 5
        $attribute = $this->loadAttributeByAttributeCode($attributeCode);
235
236
        // unpack the value according to the attribute's frontend input type
237 5
        switch ($attribute[MemberNames::FRONTEND_INPUT]) {
238 5
            case FrontendInputTypes::MULTISELECT:
239 3
                return explode($this->getMultipleValueDelimiter(), $value);
240
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
241
242 5
            case FrontendInputTypes::BOOLEAN:
243 3
                return filter_var($value, FILTER_VALIDATE_BOOLEAN);
244
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
245
246
            default:
247 5
                return $value;
248
        }
249
    }
250
251
    /**
252
     * Passes the configuration and initializes the serializer.
253
     *
254
     * @param \TechDivision\Import\Configuration\CsvConfigurationInterface $configuration The CSV configuration
255
     *
256
     * @return void
257
     */
258 10
    public function init(CsvConfigurationInterface $configuration)
259
    {
260
261
        // pass the configuration to the parent instance
262 10
        parent::init($configuration);
263
264
        // create the CSV value serializer instance
265 10
        $this->setValueCsvSerializer($this->getValueCsvSerializerFactory()->createSerializer($configuration));
266 10
    }
267
268
    /**
269
     * Unserializes the elements of the passed string.
270
     *
271
     * @param string|null $serialized The value to unserialize
272
     * @param string|null $delimiter  The delimiter used to unserialize the elements
273
     *
274
     * @return array The unserialized values
275
     * @see \TechDivision\Import\Serializers\SerializerInterface::unserialize()
276
     */
277 6
    public function unserialize($serialized = null, $delimiter = null)
278
    {
279
280
        // initialize the array for the attributes
281 6
        $attrs = array();
282
283
        // explode the additional attributes
284 6
        $additionalAttributes = $this->getValueCsvSerializer()->unserialize($serialized, $delimiter ? $delimiter : $this->getMultipleFieldDelimiter());
285
286
        // iterate over the attributes and append them to the row
287 6
        if (is_array($additionalAttributes)) {
288 5
            foreach ($additionalAttributes as $additionalAttribute) {
289
                // explode attribute code/option value from the attribute
290 5
                list ($attributeCode, $optionValue) = $this->explode($additionalAttribute, '=');
291 5
                $attrs[$attributeCode] = $this->unpack($attributeCode, $optionValue);
292
            }
293
        }
294
295
        // return the extracted array with the additional attributes
296 6
        return $attrs;
297
    }
298
299
    /**
300
     * Serializes the elements of the passed array.
301
     *
302
     * @param array|null  $unserialized The serialized data
303
     * @param string|null $delimiter    The delimiter used to serialize the values
304
     *
305
     * @return string The serialized array
306
     * @see \TechDivision\Import\Serializers\SerializerInterface::serialize()
307
     */
308 4
    public function serialize(array $unserialized = null, $delimiter = null)
309
    {
310
311
        // initialize the array for the attributes
312 4
        $attrs = array();
313
314
        // iterate over the attributes and append them to the row
315 4
        if (is_array($unserialized)) {
316 4
            foreach ($unserialized as $attributeCode => $optionValue) {
317 3
                $attrs[] = sprintf('%s=%s', $attributeCode, $this->pack($attributeCode, $optionValue));
318
            }
319
        }
320
321
        // implode the array with the packed additional attributes and return it
322 4
        return $this->getValueCsvSerializer()->serialize($attrs, $delimiter ? $delimiter : $this->getMultipleFieldDelimiter());
323
    }
324
325
    /**
326
     * Extracts the elements of the passed value by exploding them
327
     * with the also passed delimiter.
328
     *
329
     * @param string|null $value     The value to extract
330
     * @param string|null $delimiter The delimiter used to extrace the elements
331
     *
332
     * @return array|null The exploded values
333
     * @see \TechDivision\Import\Serializers\SerializerInterface::unserialize()
334
     */
335 5
    public function explode($value = null, $delimiter = null)
336
    {
337 5
        return $this->getValueCsvSerializer()->explode($value, $delimiter ? $delimiter : $this->getMultipleFieldDelimiter());
338
    }
339
340
    /**
341
     * Compacts the elements of the passed value by imploding them
342
     * with the also passed delimiter.
343
     *
344
     * @param array|null  $value     The values to compact
345
     * @param string|null $delimiter The delimiter use to implode the values
346
     *
347
     * @return string|null The compatected value
348
     * @see \TechDivision\Import\Serializers\SerializerInterface::serialize()
349
     */
350
    public function implode(array $value = null, $delimiter = null)
351
    {
352
        return $this->getValueCsvSerializer()->implode($value, $delimiter ? $delimiter : $this->getMultipleFieldDelimiter());
353
    }
354
}
355