Completed
Push — master ( baa810...02b974 )
by Tim
10s
created

AbstractProductSubject::tearDown()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 0
cts 12
cp 0
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 12
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * TechDivision\Import\Product\Subjects\AbstractProductSubject
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 2016 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-product
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Product\Subjects;
22
23
use Psr\Log\LoggerInterface;
24
use TechDivision\Import\Utils\RegistryKeys;
25
use TechDivision\Import\Subjects\AbstractEavSubject;
26
use TechDivision\Import\Product\Utils\MemberNames;
27
use TechDivision\Import\Product\Services\ProductProcessorInterface;
28
use TechDivision\Import\Services\RegistryProcessorInterface;
29
use TechDivision\Import\Configuration\SubjectConfigurationInterface;
30
31
/**
32
 * The abstract product subject implementation that provides basic product
33
 * handling business logic.
34
 *
35
 * @author    Tim Wagner <[email protected]>
36
 * @copyright 2016 TechDivision GmbH <[email protected]>
37
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
38
 * @link      https://github.com/techdivision/import-product
39
 * @link      http://www.techdivision.com
40
 */
41
abstract class AbstractProductSubject extends AbstractEavSubject
42
{
43
44
    /**
45
     * The processor to read/write the necessary product data.
46
     *
47
     * @var \TechDivision\Import\Product\Services\ProductProcessorInterface
48
     */
49
    protected $productProcessor;
50
51
    /**
52
     * The available stores.
53
     *
54
     * @var array
55
     */
56
    protected $stores = array();
57
58
    /**
59
     * The available store websites.
60
     *
61
     * @var array
62
     */
63
    protected $storeWebsites = array();
64
65
    /**
66
     * The available EAV attributes, grouped by their attribute set and the attribute set name as keys.
67
     *
68
     * @var array
69
     */
70
    protected $attributes = array();
71
72
    /**
73
     * The available tax classes.
74
     *
75
     * @var array
76
     */
77
    protected $taxClasses = array();
78
79
    /**
80
     * The available categories.
81
     *
82
     * @var array
83
     */
84
    protected $categories = array();
85
86
    /**
87
     * The ID of the product that has been created recently.
88
     *
89
     * @var string
90
     */
91
    protected $lastEntityId;
92
93
    /**
94
     * The SKU of the product that has been created recently.
95
     *
96
     * @var string
97
     */
98
    protected $lastSku;
99
100
    /**
101
     * The Magento 2 configuration.
102
     *
103
     * @var array
104
     */
105
    protected $coreConfigData;
106
107
    /**
108
     * The mapping for the SKUs to the created entity IDs.
109
     *
110
     * @var array
111
     */
112
    protected $skuEntityIdMapping = array();
113
114
    /**
115
     * The mapping for the SKUs to the store view codes.
116
     *
117
     * @var array
118
     */
119
    protected $skuStoreViewCodeMapping = array();
120
121
    /**
122
     * Mappings for attribute code => CSV column header.
123
     *
124
     * @var array
125
     */
126
    protected $headerMappings = array(
127
        'product_online' => 'status',
128
        'tax_class_name' => 'tax_class_id',
129
        'bundle_price_type' => 'price_type',
130
        'bundle_sku_type' => 'sku_type',
131
        'bundle_price_view' => 'price_view',
132
        'bundle_weight_type' => 'weight_type',
133
        'base_image' => 'image',
134
        'base_image_label' => 'image_label',
135
        'thumbnail_image' => 'thumbnail',
136
        'thumbnail_image_label'=> 'thumbnail_label',
137
        'bundle_shipment_type' => 'shipment_type'
138
    );
139
140
    /**
141
     * Initialize the subject instance.
142
     *
143
     * @param \Psr\Log\LoggerInterface                                         $systemLogger      The system logger instance
144
     * @param \TechDivision\Import\Configuration\SubjectConfigurationInterface $configuration     The subject configuration instance
145
     * @param \TechDivision\Import\Services\RegistryProcessorInterface         $registryProcessor The registry processor instance
146
     * @param \TechDivision\Import\Product\Services\ProductProcessorInterface  $productProcessor  The product processor instance
147
     */
148 3
    public function __construct(
149
        LoggerInterface $systemLogger,
150
        SubjectConfigurationInterface $configuration,
151
        RegistryProcessorInterface $registryProcessor,
152
        ProductProcessorInterface $productProcessor
153
    ) {
154
155
        // pass the arguments to the parent constructor
156 3
        parent::__construct($systemLogger, $configuration, $registryProcessor);
157
158
        // initialize the product processor
159 3
        $this->productProcessor = $productProcessor;
160 3
    }
161
162
    /**
163
     * Set's the product processor instance.
164
     *
165
     * @param \TechDivision\Import\Product\Services\ProductProcessorInterface $productProcessor The product processor instance
166
     *
167
     * @return void
168
     */
169 3
    public function setProductProcessor(ProductProcessorInterface $productProcessor)
170
    {
171 3
        $this->productProcessor = $productProcessor;
172 3
    }
173
174
    /**
175
     * Return's the product processor instance.
176
     *
177
     * @return \TechDivision\Import\Services\ProductProcessorInterface The product processor instance
178
     */
179 3
    public function getProductProcessor()
180
    {
181 3
        return $this->productProcessor;
182
    }
183
184
    /**
185
     * Set's the SKU of the last imported product.
186
     *
187
     * @param string $lastSku The SKU
188
     *
189
     * @return void
190
     */
191
    public function setLastSku($lastSku)
192
    {
193
        $this->lastSku = $lastSku;
194
    }
195
196
    /**
197
     * Return's the SKU of the last imported product.
198
     *
199
     * @return string|null The SKU
200
     */
201
    public function getLastSku()
202
    {
203
        return $this->lastSku;
204
    }
205
206
    /**
207
     * Set's the ID of the product that has been created recently.
208
     *
209
     * @param string $lastEntityId The entity ID
210
     *
211
     * @return void
212
     */
213 1
    public function setLastEntityId($lastEntityId)
214
    {
215 1
        $this->lastEntityId = $lastEntityId;
216 1
    }
217
218
    /**
219
     * Return's the ID of the product that has been created recently.
220
     *
221
     * @return string The entity Id
222
     */
223
    public function getLastEntityId()
224
    {
225
        return $this->lastEntityId;
226
    }
227
228
    /**
229
     * Queries whether or not the SKU has already been processed.
230
     *
231
     * @param string $sku The SKU to check been processed
232
     *
233
     * @return boolean TRUE if the SKU has been processed, else FALSE
234
     */
235
    public function hasBeenProcessed($sku)
236
    {
237
        return isset($this->skuEntityIdMapping[$sku]);
238
    }
239
240
    /**
241
     * Add the passed SKU => entity ID mapping.
242
     *
243
     * @param string $sku The SKU
244
     *
245
     * @return void
246
     */
247
    public function addSkuEntityIdMapping($sku)
248
    {
249
        $this->skuEntityIdMapping[$sku] = $this->getLastEntityId();
250
    }
251
252
    /**
253
     * Add the passed SKU => store view code mapping.
254
     *
255
     * @param string $sku           The SKU
256
     * @param string $storeViewCode The store view code
257
     *
258
     * @return void
259
     */
260
    public function addSkuStoreViewCodeMapping($sku, $storeViewCode)
261
    {
262
        $this->skuStoreViewCodeMapping[$sku] = $storeViewCode;
263
    }
264
265
    /**
266
     * Intializes the previously loaded global data for exactly one bunch.
267
     *
268
     * @return void
269
     * @see \Importer\Csv\Actions\ProductImportAction::prepare()
270
     */
271
    public function setUp()
272
    {
273
274
        // load the status of the actual import
275
        $status = $this->getRegistryProcessor()->getAttribute($this->getSerial());
276
277
        // load the global data we've prepared initially
278
        $this->storeWebsites =  $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::STORE_WEBSITES];
279
        $this->stores = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::STORES];
280
        $this->taxClasses = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::TAX_CLASSES];
281
        $this->categories = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::CATEGORIES];
282
        $this->coreConfigData = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::CORE_CONFIG_DATA];
283
284
        // invoke the parent method
285
        parent::setUp();
286
    }
287
288
    /**
289
     * Clean up the global data after importing the bunch.
290
     *
291
     * @return void
292
     */
293
    public function tearDown()
294
    {
295
296
        // invoke the parent method
297
        parent::tearDown();
298
299
        // load the registry processor
300
        $registryProcessor = $this->getRegistryProcessor();
301
302
        // update the status with the SKU => entity ID mapping
303
        $registryProcessor->mergeAttributesRecursive(
304
            $this->getSerial(),
305
            array()
306
        );
307
308
        // update the status
309
        $registryProcessor->mergeAttributesRecursive(
310
            $this->getSerial(),
311
            array(
312
                RegistryKeys::FILES => array($this->getFilename() => array(RegistryKeys::STATUS => 1)),
313
                RegistryKeys::SKU_ENTITY_ID_MAPPING => $this->skuEntityIdMapping,
314
                RegistryKeys::SKU_STORE_VIEW_CODE_MAPPING => $this->skuStoreViewCodeMapping
315
            )
316
        );
317
    }
318
319
    /**
320
     * Return's the header mappings for the actual entity.
321
     *
322
     * @return array The header mappings
323
     */
324
    public function getHeaderMappings()
325
    {
326
        return $this->headerMappings;
327
    }
328
329
    /**
330
     * Return's an array with the available EAV attributes for the passed is user defined flag.
331
     *
332
     * @param integer $isUserDefined The flag itself
333
     *
334
     * @return array The array with the EAV attributes matching the passed flag
335
     */
336
    public function getEavAttributeByIsUserDefined($isUserDefined = 1)
337
    {
338
        return $this->getProductProcessor()->getEavAttributeByIsUserDefined($isUserDefined);
339
    }
340
341
    /**
342
     * Return's the attribute option value with the passed value and store ID.
343
     *
344
     * @param mixed   $value   The option value
345
     * @param integer $storeId The ID of the store
346
     *
347
     * @return array|boolean The attribute option value instance
348
     */
349
    public function getEavAttributeOptionValueByOptionValueAndStoreId($value, $storeId)
350
    {
351
        return $this->getProductProcessor()->getEavAttributeOptionValueByOptionValueAndStoreId($value, $storeId);
352
    }
353
354
    /**
355
     * Return's the store ID of the actual row, or of the default store
356
     * if no store view code is set in the CSV file.
357
     *
358
     * @param string|null $default The default store view code to use, if no store view code is set in the CSV file
359
     *
360
     * @return integer The ID of the actual store
361
     * @throws \Exception Is thrown, if the store with the actual code is not available
362
     */
363
    public function getRowStoreId($default = null)
364
    {
365
366
        // initialize the default store view code, if not passed
367
        if ($default == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $default of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
368
            $defaultStore = $this->getDefaultStore();
369
            $default = $defaultStore[MemberNames::CODE];
370
        }
371
372
        // load the store view code the create the product/attributes for
373
        $storeViewCode = $this->getStoreViewCode($default);
374
375
        // query whether or not, the requested store is available
376
        if (isset($this->stores[$storeViewCode])) {
377
            return (integer) $this->stores[$storeViewCode][MemberNames::STORE_ID];
378
        }
379
380
        // throw an exception, if not
381
        throw new \Exception(
382
            sprintf(
383
                'Found invalid store view code %s in file %s on line %d',
384
                $storeViewCode,
385
                $this->getFilename(),
386
                $this->getLineNumber()
387
            )
388
        );
389
    }
390
391
    /**
392
     * Return's the tax class ID for the passed tax class name.
393
     *
394
     * @param string $taxClassName The tax class name to return the ID for
395
     *
396
     * @return integer The tax class ID
397
     * @throws \Exception Is thrown, if the tax class with the requested name is not available
398
     */
399 View Code Duplication
    public function getTaxClassIdByTaxClassName($taxClassName)
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...
400
    {
401
402
        // query whether or not, the requested tax class is available
403
        if (isset($this->taxClasses[$taxClassName])) {
404
            return (integer) $this->taxClasses[$taxClassName][MemberNames::CLASS_ID];
405
        }
406
407
        // throw an exception, if not
408
        throw new \Exception(
409
            sprintf(
410
                'Found invalid tax class name %s in file %s on line %d',
411
                $taxClassName,
412
                $this->getFilename(),
413
                $this->getLineNumber()
414
            )
415
        );
416
    }
417
418
    /**
419
     * Return's the store website for the passed code.
420
     *
421
     * @param string $code The code of the store website to return the ID for
422
     *
423
     * @return integer The store website ID
424
     * @throws \Exception Is thrown, if the store website with the requested code is not available
425
     */
426 View Code Duplication
    public function getStoreWebsiteIdByCode($code)
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...
427
    {
428
429
        // query whether or not, the requested store website is available
430
        if (isset($this->storeWebsites[$code])) {
431
            return (integer) $this->storeWebsites[$code][MemberNames::WEBSITE_ID];
432
        }
433
434
        // throw an exception, if not
435
        throw new \Exception(
436
            sprintf(
437
                'Found invalid website code %s in file %s on line %d',
438
                $code,
439
                $this->getFilename(),
440
                $this->getLineNumber()
441
            )
442
        );
443
    }
444
445
    /**
446
     * Return's the category with the passed path.
447
     *
448
     * @param string $path The path of the category to return
449
     *
450
     * @return array The category
451
     * @throws \Exception Is thrown, if the requested category is not available
452
     */
453 View Code Duplication
    public function getCategoryByPath($path)
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...
454
    {
455
456
        // query whether or not the category with the passed path exists
457
        if (isset($this->categories[$path])) {
458
            return $this->categories[$path];
459
        }
460
461
        // throw an exception, if not
462
        throw new \Exception(
463
            sprintf(
464
                'Can\'t find category with path %s in file %s on line %d',
465
                $path,
466
                $this->getFilename(),
467
                $this->getLineNumber()
468
            )
469
        );
470
    }
471
472
    /**
473
     * Return's the category with the passed ID.
474
     *
475
     * @param integer $categoryId The ID of the category to return
476
     *
477
     * @return array The category data
478
     * @throws \Exception Is thrown, if the category is not available
479
     */
480
    public function getCategory($categoryId)
481
    {
482
483
        // try to load the category with the passed ID
484
        foreach ($this->categories as $category) {
485
            if ($category[MemberNames::ENTITY_ID] == $categoryId) {
486
                return $category;
487
            }
488
        }
489
490
        // throw an exception if the category is NOT available
491
        throw new \Exception(
492
            sprintf(
493
                'Can\'t load category with ID %d in file %s on line %d',
494
                $categoryId,
495
                $this->getFilename(),
496
                $this->getLineNumber()
497
            )
498
        );
499
    }
500
501
    /**
502
     * Return's the root category for the actual view store.
503
     *
504
     * @return array The store's root category
505
     * @throws \Exception Is thrown if the root category for the passed store code is NOT available
506
     */
507
    public function getRootCategory()
508
    {
509
510
        // load the default store
511
        $defaultStore = $this->getDefaultStore();
512
513
        // load the actual store view code
514
        $storeViewCode = $this->getStoreViewCode($defaultStore[MemberNames::CODE]);
515
516
        // query weather or not we've a root category or not
517
        if (isset($this->rootCategories[$storeViewCode])) {
518
            return $this->rootCategories[$storeViewCode];
519
        }
520
521
        // throw an exception if the root category is NOT available
522
        throw new \Exception(sprintf('Root category for %s is not available', $storeViewCode));
523
    }
524
}
525