Completed
Push — master ( 2727c0...993f12 )
by Tim
03:10
created

AbstractProductSubject::tearDown()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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