Passed
Push — 9.x ( 0d3798...8a51bd )
by
unknown
07:06
created

process()   B

Complexity

Conditions 10
Paths 11

Size

Total Lines 93
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 41
c 1
b 0
f 0
dl 0
loc 93
ccs 0
cts 47
cp 0
rs 7.6666
cc 10
nc 11
nop 0
crap 110

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * TechDivision\Import\Converter\Product\Attribute\Observers\ProductToAttributeOptionValueConverterObserver
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 2019 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-converter-product-attribute
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Converter\Product\Attribute\Observers;
22
23
use TechDivision\Import\Utils\StoreViewCodes;
24
use TechDivision\Import\Utils\FrontendInputTypes;
25
use TechDivision\Import\Attribute\Utils\ColumnKeys;
26
use TechDivision\Import\Attribute\Utils\MemberNames;
27
use TechDivision\Import\Product\Utils\ConfigurationKeys;
28
use TechDivision\Import\Observers\StateDetectorInterface;
29
use TechDivision\Import\Services\ImportProcessorInterface;
30
use TechDivision\Import\Converter\Observers\AbstractConverterObserver;
31
use TechDivision\Import\Attribute\Callbacks\SwatchTypeLoaderInterface;
32
use TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface;
33
use TechDivision\Import\Observers\CleanUpEmptyColumnsTrait;
0 ignored issues
show
Bug introduced by
The type TechDivision\Import\Obse...leanUpEmptyColumnsTrait was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
35
/**
36
 * Observer that extracts the missing attribute option values from a product CSV.
37
 *
38
 * @author    Tim Wagner <[email protected]>
39
 * @copyright 2019 TechDivision GmbH <[email protected]>
40
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
41
 * @link      https://github.com/techdivision/import-converter-product-attribute
42
 * @link      http://www.techdivision.com
43
 */
44
class ProductToAttributeOptionValueConverterObserver extends AbstractConverterObserver
45
{
46
    use CleanUpEmptyColumnsTrait;
47
48
    /**
49
     * The artefact type.
50
     *
51
     * @var string
52
     */
53
    const ARTEFACT_TYPE = 'option-import';
54
55
    /**
56
     * The import processor instance.
57
     *
58
     * @var \TechDivision\Import\Services\ImportProcessorInterface
59
     */
60
    protected $importProcessor;
61
62
    /**
63
     * The attribute bunch processor instance.
64
     *
65
     * @var \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface
66
     */
67
    protected $attributeBunchProcessor;
68
69
    /**
70
     * The swatch type loader instance.
71
     *
72
     * @var \TechDivision\Import\Attribute\Callbacks\SwatchTypeLoaderInterface
73
     */
74
    protected $swatchTypeLoader;
75
76
    /**
77
     * Initialize the observer with the passed product bunch processor instance.
78
     *
79
     * @param \TechDivision\Import\Services\ImportProcessorInterface                   $importProcessor         The product bunch processor instance
80
     * @param \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface $attributeBunchProcessor The attribute bunch processor instance
81
     * @param \TechDivision\Import\Attribute\Callbacks\SwatchTypeLoaderInterface       $swatchTypeLoader        The swatch type loader instance
82
     * @param \TechDivision\Import\Observers\StateDetectorInterface|null               $stateDetector           The state detector instance to use
83
     */
84
    public function __construct(
85
        ImportProcessorInterface $importProcessor,
86
        AttributeBunchProcessorInterface $attributeBunchProcessor,
87
        SwatchTypeLoaderInterface $swatchTypeLoader,
88
        StateDetectorInterface $stateDetector = null
89
    ) {
90
91
        // initialize the swatch type loader and the processor instances
92
        $this->importProcessor = $importProcessor;
93
        $this->swatchTypeLoader = $swatchTypeLoader;
94
        $this->attributeBunchProcessor = $attributeBunchProcessor;
95
96
        // pass the state detector to the parent method
97
        parent::__construct($stateDetector);
98
    }
99
100
    /**
101
     * Process the observer's business logic.
102
     *
103
     * @return void
104
     */
105
    protected function process()
106
    {
107
108
        // initialize the store view code
109
        $this->prepareStoreViewCode();
110
111
        // load the store ID, use the admin store if NO store view code has been set
112
        $storeId = $this->getStoreId(StoreViewCodes::ADMIN);
113
114
        // load the user defined EAV attributes by the found attribute set and the backend types
115
        $attributes = $this->getEavUserDefinedAttributes();
116
117
        // load the header keys
118
        $headers = array_flip($this->getHeaders());
119
120
        // remove all the empty values from the row
121
        $row = $this->clearRow();
122
123
        // initialize the array for the artefacts
124
        $artefacts = array();
125
126
        // load the entity type ID
127
        $entityType = $this->loadEavEntityTypeByEntityTypeCode($this->getSubject()->getEntityTypeCode());
128
        $entityTypeId = $entityType[MemberNames::ENTITY_TYPE_ID];
129
130
        // iterate over the attributes and append them to the row
131
        foreach ($row as $key => $attributeValue) {
132
            // query whether or not attribute with the found code exists
133
            if (!isset($attributes[$attributeCode = $headers[$key]])) {
134
                // log a message in debug mode
135
                if ($this->isDebugMode()) {
136
                    $this->getSystemLogger()->debug(
137
                        $this->appendExceptionSuffix(
138
                            sprintf(
139
                                'Can\'t find attribute with attribute code %s',
140
                                $attributeCode
141
                            )
142
                        )
143
                    );
144
                }
145
146
                // stop processing
147
                continue;
148
            } else {
149
                // log a message in debug mode
150
                if ($this->isDebugMode()) {
151
                    // log a message in debug mode
152
                    $this->getSystemLogger()->debug(
153
                        $this->appendExceptionSuffix(
154
                            sprintf(
155
                                'Found attribute with attribute code %s',
156
                                $attributeCode
157
                            )
158
                        )
159
                    );
160
                }
161
            }
162
163
            // if yes, load the attribute by its code
164
            $attribute = $attributes[$attributeCode];
165
166
            // we only support user defined EAV attributes of type select and multiselect
167
            if (in_array($attribute[MemberNames::FRONTEND_INPUT], array(FrontendInputTypes::SELECT, FrontendInputTypes::MULTISELECT))) {
168
                // explode the values if we've a multiselect
169
                $values = $this->explode($attributeValue, $this->getMultipleValueDelimiter());
170
                // iterate over the values
171
                foreach ($values as $value) {
172
                    // query whether or not the attribute value already exists
173
                    if ($this->loadAttributeOptionValueByEntityTypeIdAndAttributeCodeAndStoreIdAndValue($entityTypeId, $attributeCode, $storeId, $value)) {
174
                        continue;
175
                    }
176
177
                    // try to load the swatch type, if available
178
                    $swatchType = $this->getSwatchTypeLoader()->loadSwatchType($entityTypeId, $attributeCode);
179
180
                    // add the artefact to the array
181
                    $artefacts[] = $this->newArtefact(
182
                        array(
183
                            ColumnKeys::DEFAULT_VALUE  => $attribute[MemberNames::DEFAULT_VALUE],
184
                            ColumnKeys::ATTRIBUTE_CODE => $attribute[MemberNames::ATTRIBUTE_CODE],
185
                            ColumnKeys::SORT_ORDER     => 0,
186
                            ColumnKeys::VALUE          => is_null($swatchType) ? $value : null,
187
                            ColumnKeys::SWATCH_TYPE    => $swatchType,
188
                            ColumnKeys::SWATCH_VALUE   => $swatchType ? $value : null
189
                        ),
190
                        array()
191
                    );
192
                }
193
            }
194
        }
195
196
        // export the array with artefacts
197
        $this->addArtefacts($artefacts);
198
    }
199
200
    /**
201
     * Returns the value(s) of the primary key column(s). As the primary key column can
202
     * also consist of two columns, the return value can be an array also.
203
     *
204
     * @return mixed The primary key value(s)
205
     */
206
    protected function getPrimaryKeyValue()
207
    {
208
        return $this->getValue(\TechDivision\Import\Product\Utils\ColumnKeys::SKU);
209
    }
210
211
    /**
212
     * Return's the import processor instance.
213
     *
214
     * @return \TechDivision\Import\Services\ImportProcessorInterface The import processor instance
215
     */
216
    protected function getImportProcessor()
217
    {
218
        return $this->importProcessor;
219
    }
220
221
    /**
222
     * Return's the attribute bunch processor instance.
223
     *
224
     * @return \TechDivision\Import\Attribute\Services\AttributeBunchProcessorInterface The attribute bunch processor instance
225
     */
226
    protected function getAttributeBunchProcessor()
227
    {
228
        return $this->attributeBunchProcessor;
229
    }
230
231
    /**
232
     * Return's the swatch type loader instance.
233
     *
234
     * @return \TechDivision\Import\Attribute\Callbacks\SwatchTypeLoaderInterface The swatch type loader instance
235
     */
236
    protected function getSwatchTypeLoader()
237
    {
238
        return $this->swatchTypeLoader;
239
    }
240
241
    /**
242
     * Return's an array with the available user defined EAV attributes for the actual entity type.
243
     *
244
     * @return array The array with the user defined EAV attributes
245
     */
246
    protected function getEavUserDefinedAttributes()
247
    {
248
        return $this->getSubject()->getEavUserDefinedAttributes();
249
    }
250
251
    /**
252
     * Return's an EAV entity type with the passed entity type code.
253
     *
254
     * @param string $entityTypeCode The code of the entity type to return
255
     *
256
     * @return array The entity type with the passed entity type code
257
     */
258
    protected function loadEavEntityTypeByEntityTypeCode($entityTypeCode)
259
    {
260
        return $this->getImportProcessor()->getEavEntityTypeByEntityTypeCode($entityTypeCode);
261
    }
262
263
    /**
264
     * Load's and return's the EAV attribute option value with the passed entity type ID, code, store ID and value.
265
     *
266
     * @param string  $entityTypeId  The entity type ID of the EAV attribute to load the option value for
267
     * @param string  $attributeCode The code of the EAV attribute option to load
268
     * @param integer $storeId       The store ID of the attribute option to load
269
     * @param string  $value         The value of the attribute option to load
270
     *
271
     * @return array The EAV attribute option value
272
     */
273
    protected function loadAttributeOptionValueByEntityTypeIdAndAttributeCodeAndStoreIdAndValue($entityTypeId, $attributeCode, $storeId, $value)
274
    {
275
        return $this->getAttributeBunchProcessor()->loadAttributeOptionValueByEntityTypeIdAndAttributeCodeAndStoreIdAndValue($entityTypeId, $attributeCode, $storeId, $value);
276
    }
277
278
    /**
279
     * Create's and return's a new empty artefact entity.
280
     *
281
     * @param array $columns             The array with the column data
282
     * @param array $originalColumnNames The array with a mapping from the old to the new column names
283
     *
284
     * @return array The new artefact entity
285
     */
286
    protected function newArtefact(array $columns, array $originalColumnNames)
287
    {
288
        return $this->getSubject()->newArtefact($columns, $originalColumnNames);
289
    }
290
291
    /**
292
     * Add the passed product type artefacts to the product with the
293
     * last entity ID.
294
     *
295
     * @param array $artefacts The product type artefacts
296
     *
297
     * @return void
298
     * @uses \TechDivision\Import\Product\Media\Subjects\MediaSubject::getLastEntityId()
299
     */
300
    protected function addArtefacts(array $artefacts)
301
    {
302
        $this->getSubject()->addArtefacts(ProductToAttributeOptionValueConverterObserver::ARTEFACT_TYPE, $artefacts);
303
    }
304
}
305