Completed
Pull Request — master (#55)
by Tim
04:53
created

AbstractProductSubject::getLastSku()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
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 TechDivision\Import\Utils\RegistryKeys;
24
use TechDivision\Import\Utils\FrontendInputTypes;
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
     * The default mappings for the user defined attributes, based on the attributes frontend input type.
156
     *
157
     * @var array
158
     */
159
    protected $defaultFrontendInputCallbackMappings = array(
160
        FrontendInputTypes::SELECT      => 'TechDivision\\Import\\Product\\Callbacks\\SelectCallback',
161
        FrontendInputTypes::MULTISELECT => 'TechDivision\\Import\\Product\\Callbacks\\MultiselectCallback',
162
        FrontendInputTypes::BOOLEAN     => 'TechDivision\\Import\\Product\\Callbacks\\BooleanCallback'
163
    );
164
165
    /**
166
     * Initialize the subject instance.
167
     *
168
     * @param \TechDivision\Import\Configuration\SubjectConfigurationInterface $configuration              The subject configuration instance
169
     * @param \TechDivision\Import\Services\RegistryProcessorInterface         $registryProcessor          The registry processor instance
170
     * @param \TechDivision\Import\Utils\Generators\GeneratorInterface         $coreConfigDataUidGenerator The UID generator for the core config data
171
     * @param array                                                            $systemLoggers              The array with the system logger instances
172
     * @param \TechDivision\Import\Product\Services\ProductProcessorInterface  $productProcessor           The product processor instance
173
     */
174 3
    public function __construct(
175
        SubjectConfigurationInterface $configuration,
176
        RegistryProcessorInterface $registryProcessor,
177
        GeneratorInterface $coreConfigDataUidGenerator,
178
        array $systemLoggers,
179
        ProductProcessorInterface $productProcessor
180
    ) {
181
182
        // pass the arguments to the parent constructor
183 3
        parent::__construct($configuration, $registryProcessor, $coreConfigDataUidGenerator, $systemLoggers);
184
185
        // initialize the product processor
186 3
        $this->productProcessor = $productProcessor;
187 3
    }
188
189
    /**
190
     * Return's the default callback frontend input mappings for the user defined attributes.
191
     *
192
     * @return array The default frontend input callback mappings
193
     */
194
    public function getDefaultFrontendInputCallbackMappings()
195
    {
196
        return $this->defaultFrontendInputCallbackMappings;
197
    }
198
199
    /**
200
     * Return's the available link types.
201
     *
202
     * @return array The link types
203
     */
204
    public function getLinkTypes()
205
    {
206
        return $this->linkTypes;
207
    }
208
209
    /**
210
     * Set's the product processor instance.
211
     *
212
     * @param \TechDivision\Import\Product\Services\ProductProcessorInterface $productProcessor The product processor instance
213
     *
214
     * @return void
215
     */
216 3
    public function setProductProcessor(ProductProcessorInterface $productProcessor)
217
    {
218 3
        $this->productProcessor = $productProcessor;
219 3
    }
220
221
    /**
222
     * Return's the product processor instance.
223
     *
224
     * @return \TechDivision\Import\Services\ProductProcessorInterface The product processor instance
225
     */
226 3
    public function getProductProcessor()
227
    {
228 3
        return $this->productProcessor;
229
    }
230
231
    /**
232
     * Set's the SKU of the last imported product.
233
     *
234
     * @param string $lastSku The SKU
235
     *
236
     * @return void
237
     */
238
    public function setLastSku($lastSku)
239
    {
240
        $this->lastSku = $lastSku;
241
    }
242
243
    /**
244
     * Return's the SKU of the last imported product.
245
     *
246
     * @return string|null The SKU
247
     */
248
    public function getLastSku()
249
    {
250
        return $this->lastSku;
251
    }
252
253
    /**
254
     * Set's the ID of the product that has been created recently.
255
     *
256
     * @param string $lastEntityId The entity ID
257
     *
258
     * @return void
259
     */
260 1
    public function setLastEntityId($lastEntityId)
261
    {
262 1
        $this->lastEntityId = $lastEntityId;
263 1
    }
264
265
    /**
266
     * Return's the ID of the product that has been created recently.
267
     *
268
     * @return string The entity Id
269
     */
270
    public function getLastEntityId()
271
    {
272
        return $this->lastEntityId;
273
    }
274
275
    /**
276
     * Queries whether or not the SKU has already been processed.
277
     *
278
     * @param string $sku The SKU to check been processed
279
     *
280
     * @return boolean TRUE if the SKU has been processed, else FALSE
281
     */
282
    public function hasBeenProcessed($sku)
283
    {
284
        return isset($this->skuEntityIdMapping[$sku]);
285
    }
286
287
    /**
288
     * Add the passed SKU => entity ID mapping.
289
     *
290
     * @param string $sku The SKU
291
     *
292
     * @return void
293
     */
294
    public function addSkuEntityIdMapping($sku)
295
    {
296
        $this->skuEntityIdMapping[$sku] = $this->getLastEntityId();
297
    }
298
299
    /**
300
     * Add the passed SKU => store view code mapping.
301
     *
302
     * @param string $sku           The SKU
303
     * @param string $storeViewCode The store view code
304
     *
305
     * @return void
306
     */
307
    public function addSkuStoreViewCodeMapping($sku, $storeViewCode)
308
    {
309
        $this->skuStoreViewCodeMapping[$sku] = $storeViewCode;
310
    }
311
312
    /**
313
     * Intializes the previously loaded global data for exactly one bunch.
314
     *
315
     * @return void
316
     * @see \Importer\Csv\Actions\ProductImportAction::prepare()
317
     */
318
    public function setUp()
319
    {
320
321
        // load the status of the actual import
322
        $status = $this->getRegistryProcessor()->getAttribute($this->getSerial());
323
324
        // load the global data we've prepared initially
325
        $this->linkTypes = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::LINK_TYPES];
326
        $this->categories = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::CATEGORIES];
327
        $this->taxClasses = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::TAX_CLASSES];
328
        $this->storeWebsites =  $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::STORE_WEBSITES];
329
330
        // invoke the parent method
331
        parent::setUp();
332
    }
333
334
    /**
335
     * Clean up the global data after importing the bunch.
336
     *
337
     * @return void
338
     */
339
    public function tearDown()
340
    {
341
342
        // invoke the parent method
343
        parent::tearDown();
344
345
        // load the registry processor
346
        $registryProcessor = $this->getRegistryProcessor();
347
348
        // update the status
349
        $registryProcessor->mergeAttributesRecursive(
350
            $this->getSerial(),
351
            array(
352
                RegistryKeys::FILES => array($this->getFilename() => array(RegistryKeys::STATUS => 1)),
353
                RegistryKeys::SKU_ENTITY_ID_MAPPING => $this->skuEntityIdMapping,
354
                RegistryKeys::SKU_STORE_VIEW_CODE_MAPPING => $this->skuStoreViewCodeMapping
355
            )
356
        );
357
    }
358
359
    /**
360
     * Return's the header mappings for the actual entity.
361
     *
362
     * @return array The header mappings
363
     */
364
    public function getHeaderMappings()
365
    {
366
        return $this->headerMappings;
367
    }
368
369
    /**
370
     * Return's an array with the available EAV attributes for the passed is user defined flag.
371
     *
372
     * @param integer $isUserDefined The flag itself
373
     *
374
     * @return array The array with the EAV attributes matching the passed flag
375
     */
376
    public function getEavAttributeByIsUserDefined($isUserDefined = 1)
377
    {
378
        return $this->getProductProcessor()->getEavAttributeByIsUserDefined($isUserDefined);
379
    }
380
381
    /**
382
     * Return's the attribute option value with the passed value and store ID.
383
     *
384
     * @param mixed   $value   The option value
385
     * @param integer $storeId The ID of the store
386
     *
387
     * @return array|boolean The attribute option value instance
388
     */
389
    public function getEavAttributeOptionValueByOptionValueAndStoreId($value, $storeId)
390
    {
391
        return $this->getProductProcessor()->getEavAttributeOptionValueByOptionValueAndStoreId($value, $storeId);
392
    }
393
394
    /**
395
     * Return's the store ID of the actual row, or of the default store
396
     * if no store view code is set in the CSV file.
397
     *
398
     * @param string|null $default The default store view code to use, if no store view code is set in the CSV file
399
     *
400
     * @return integer The ID of the actual store
401
     * @throws \Exception Is thrown, if the store with the actual code is not available
402
     */
403
    public function getRowStoreId($default = null)
404
    {
405
406
        // initialize the default store view code, if not passed
407
        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...
408
            $defaultStore = $this->getDefaultStore();
409
            $default = $defaultStore[MemberNames::CODE];
410
        }
411
412
        // load the store view code the create the product/attributes for
413
        $storeViewCode = $this->getStoreViewCode($default);
414
415
        // query whether or not, the requested store is available
416
        if (isset($this->stores[$storeViewCode])) {
417
            return (integer) $this->stores[$storeViewCode][MemberNames::STORE_ID];
418
        }
419
420
        // throw an exception, if not
421
        throw new \Exception(
422
            $this->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
The method appendExceptionSuffix() does not seem to exist on object<TechDivision\Impo...AbstractProductSubject>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
423
                sprintf('Found invalid store view code %s', $storeViewCode)
424
            )
425
        );
426
    }
427
428
    /**
429
     * Return's the tax class ID for the passed tax class name.
430
     *
431
     * @param string $taxClassName The tax class name to return the ID for
432
     *
433
     * @return integer The tax class ID
434
     * @throws \Exception Is thrown, if the tax class with the requested name is not available
435
     */
436 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...
437
    {
438
439
        // query whether or not, the requested tax class is available
440
        if (isset($this->taxClasses[$taxClassName])) {
441
            return (integer) $this->taxClasses[$taxClassName][MemberNames::CLASS_ID];
442
        }
443
444
        // throw an exception, if not
445
        throw new \Exception(
446
            $this->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
The method appendExceptionSuffix() does not seem to exist on object<TechDivision\Impo...AbstractProductSubject>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
447
                sprintf('Found invalid tax class name %s', $taxClassName)
448
            )
449
        );
450
    }
451
452
    /**
453
     * Return's the store website for the passed code.
454
     *
455
     * @param string $code The code of the store website to return the ID for
456
     *
457
     * @return integer The store website ID
458
     * @throws \Exception Is thrown, if the store website with the requested code is not available
459
     */
460 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...
461
    {
462
463
        // query whether or not, the requested store website is available
464
        if (isset($this->storeWebsites[$code])) {
465
            return (integer) $this->storeWebsites[$code][MemberNames::WEBSITE_ID];
466
        }
467
468
        // throw an exception, if not
469
        throw new \Exception(
470
            $this->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
The method appendExceptionSuffix() does not seem to exist on object<TechDivision\Impo...AbstractProductSubject>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
471
                sprintf('Found invalid website code %s', $code)
472
            )
473
        );
474
    }
475
476
    /**
477
     * Return's the category with the passed path.
478
     *
479
     * @param string $path The path of the category to return
480
     *
481
     * @return array The category
482
     * @throws \Exception Is thrown, if the requested category is not available
483
     */
484
    public function getCategoryByPath($path)
485
    {
486
487
        // query whether or not the category with the passed path exists
488
        if (isset($this->categories[$path])) {
489
            return $this->categories[$path];
490
        }
491
492
        // throw an exception, if not
493
        throw new \Exception(
494
            $this->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
The method appendExceptionSuffix() does not seem to exist on object<TechDivision\Impo...AbstractProductSubject>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
495
                sprintf('Can\'t find category with path %s', $path)
496
            )
497
        );
498
    }
499
500
    /**
501
     * Return's the category with the passed ID.
502
     *
503
     * @param integer $categoryId The ID of the category to return
504
     *
505
     * @return array The category data
506
     * @throws \Exception Is thrown, if the category is not available
507
     */
508
    public function getCategory($categoryId)
509
    {
510
511
        // try to load the category with the passed ID
512
        foreach ($this->categories as $category) {
513
            if ($category[MemberNames::ENTITY_ID] == $categoryId) {
514
                return $category;
515
            }
516
        }
517
518
        // throw an exception if the category is NOT available
519
        throw new \Exception(
520
            $this->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
The method appendExceptionSuffix() does not seem to exist on object<TechDivision\Impo...AbstractProductSubject>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
521
                sprintf('Can\'t load category with ID %d', $categoryId)
522
            )
523
        );
524
    }
525
526
    /**
527
     * Return's the root category for the actual view store.
528
     *
529
     * @return array The store's root category
530
     * @throws \Exception Is thrown if the root category for the passed store code is NOT available
531
     */
532
    public function getRootCategory()
533
    {
534
535
        // load the default store
536
        $defaultStore = $this->getDefaultStore();
537
538
        // load the actual store view code
539
        $storeViewCode = $this->getStoreViewCode($defaultStore[MemberNames::CODE]);
540
541
        // query weather or not we've a root category or not
542
        if (isset($this->rootCategories[$storeViewCode])) {
543
            return $this->rootCategories[$storeViewCode];
544
        }
545
546
        // throw an exception if the root category is NOT available
547
        throw new \Exception(
548
            $this->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
The method appendExceptionSuffix() does not seem to exist on object<TechDivision\Impo...AbstractProductSubject>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
549
                sprintf('Root category for %s is not available', $storeViewCode)
550
            )
551
        );
552
    }
553
}
554