Completed
Push — 15.x ( 906ba9 )
by Tim
04:13
created

AbstractProductSubject::mapSkuToEntityId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 15
c 0
b 0
f 0
ccs 0
cts 8
cp 0
rs 9.7666
cc 2
nc 2
nop 1
crap 6
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\StoreViewCodes;
25
use TechDivision\Import\Utils\FrontendInputTypes;
26
use TechDivision\Import\Product\Utils\MemberNames;
27
use TechDivision\Import\Product\Utils\RelationTypes;
28
use TechDivision\Import\Product\Utils\ConfigurationKeys;
29
use TechDivision\Import\Subjects\AbstractEavSubject;
30
use TechDivision\Import\Subjects\EntitySubjectInterface;
31
use TechDivision\Import\Product\Exceptions\MapSkuToEntityIdException;
32
use TechDivision\Import\Product\Exceptions\MapLinkTypeCodeToIdException;
33
34
/**
35
 * The abstract product subject implementation that provides basic product
36
 * handling business logic.
37
 *
38
 * @author    Tim Wagner <[email protected]>
39
 * @copyright 2016 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-product
42
 * @link      http://www.techdivision.com
43
 */
44
abstract class AbstractProductSubject extends AbstractEavSubject implements EntitySubjectInterface, SkuToPkMappingAwareSubjectInterface
45
{
46
47
    /**
48
     * The trait with the SKU => PK mapping functionality.
49
     *
50
     * @var \TechDivision\Import\Product\Subjects\SkuToPkMappingTrait
51
     */
52
    use SkuToPkMappingTrait;
53
54
    /**
55
     * The available EAV attributes, grouped by their attribute set and the attribute set name as keys.
56
     *
57
     * @var array
58
     */
59
    protected $attributes = array();
60
61
    /**
62
     * The available tax classes.
63
     *
64
     * @var array
65
     */
66
    protected $taxClasses = array();
67
68
    /**
69
     * The available categories.
70
     *
71
     * @var array
72
     */
73
    protected $categories = array();
74
75
    /**
76
     * The available link types.
77
     *
78
     * @var array
79
     */
80
    protected $linkTypes = array();
81
82
    /**
83
     * The available link attributes.
84
     *
85
     * @var array
86
     */
87
    protected $linkAttributes = array();
88
89
    /**
90
     * The ID of the product that has been created recently.
91
     *
92
     * @var string
93
     */
94
    protected $lastEntityId;
95
96
    /**
97
     * The SKU of the product that has been created recently.
98
     *
99
     * @var string
100
     */
101
    protected $lastSku;
102
103
    /**
104
     * The Magento 2 configuration.
105
     *
106
     * @var array
107
     */
108
    protected $coreConfigData;
109
110
    /**
111
     * The mapping for the SKUs to the created entity IDs.
112
     *
113
     * @var array
114
     */
115
    protected $skuEntityIdMapping = array();
116
117
    /**
118
     * The mapping for the SKUs to the store view codes.
119
     *
120
     * @var array
121
     */
122
    protected $skuStoreViewCodeMapping = array();
123
124
    /**
125
     * The array with the available image types and their label columns.
126
     *
127
     * @var array
128
     */
129
    protected $imageTypes = array();
130
131
    /**
132
     * Mappings for CSV column header => attribute code.
133
     *
134
     * @var array
135
     */
136
    protected $headerMappings = array(
137
        'product_online'       => 'status',
138
        'tax_class_name'       => 'tax_class_id',
139
        'bundle_price_type'    => 'price_type',
140
        'bundle_sku_type'      => 'sku_type',
141
        'bundle_price_view'    => 'price_view',
142
        'bundle_weight_type'   => 'weight_type',
143
        'bundle_shipment_type' => 'shipment_type',
144
        'related_skus'         => 'relation_skus',
145
        'related_position'     => 'relation_position',
146
        'crosssell_skus'       => 'cross_sell_skus',
147
        'crosssell_position'   => 'cross_sell_position',
148
        'upsell_skus'          => 'up_sell_skus',
149
        'upsell_position'      => 'up_sell_position',
150
        'msrp_price'           => 'msrp',
151
        'base_image'           => 'image',
152
        'base_image_label'     => 'image_label',
153
        'thumbnail_image'      => 'thumbnail',
154
        'thumbnail_image_label'=> 'thumbnail_label'
155
    );
156
157
    /**
158
     * The default mappings for the user defined attributes, based on the attributes frontend input type.
159
     *
160
     * @var array
161
     */
162
    protected $defaultFrontendInputCallbackMappings = array(
163
        FrontendInputTypes::SELECT      => array('import_product.callback.select'),
164
        FrontendInputTypes::MULTISELECT => array('import_product.callback.multiselect'),
165
        FrontendInputTypes::BOOLEAN     => array('import_product.callback.boolean')
166
    );
167
168
    /**
169
     * Array that contains the relations that has already been processed.
170
     *
171
     * @var array
172
     */
173
    protected $processedRelations = array();
174
175
    /**
176
     * The array that contains the prepared link type mappings.
177
     *
178
     * @var array
179
     */
180
    protected $linkTypeMappings = array();
181
182
    /**
183
     * The array that contains the link type => column name prefix mapping.
184
     *
185
     * @var array
186
     */
187
    protected $linkTypeCodeToColumnNameMapping = array('super' => 'associated');
188
189
    /**
190
     * The array that contains the link type attribute column => callback mapping.
191
     *
192
     * @var array
193
     */
194
    protected $linkTypeAttributeColumnToCallbackMapping = array(
195
        'associated_skus' => array('associated_skus', 'explodeKey'),
196
        'associated_qty'  => array('associated_skus', 'explodeValue')
197
    );
198
199
    /**
200
     * Return's the default callback frontend input mappings for the user defined attributes.
201
     *
202
     * @return array The default frontend input callback mappings
203
     */
204 18
    public function getDefaultFrontendInputCallbackMappings()
205
    {
206 18
        return $this->defaultFrontendInputCallbackMappings;
207
    }
208
209
    /**
210
     * Return's the available link types.
211
     *
212
     * @return array The link types
213
     */
214 18
    public function getLinkTypes()
215
    {
216 18
        return $this->linkTypes;
217
    }
218
219
    /**
220
     * Set's the SKU of the last imported product.
221
     *
222
     * @param string $lastSku The SKU
223
     *
224
     * @return void
225
     */
226
    public function setLastSku($lastSku)
227
    {
228
        $this->lastSku = $lastSku;
229
    }
230
231
    /**
232
     * Return's the SKU of the last imported product.
233
     *
234
     * @return string|null The SKU
235
     */
236
    public function getLastSku()
237
    {
238
        return $this->lastSku;
239
    }
240
241
    /**
242
     * Set's the ID of the product that has been created recently.
243
     *
244
     * @param string $lastEntityId The entity ID
245
     *
246
     * @return void
247
     */
248
    public function setLastEntityId($lastEntityId)
249
    {
250
        $this->lastEntityId = $lastEntityId;
251
    }
252
253
    /**
254
     * Return's the ID of the product that has been created recently.
255
     *
256
     * @return string The entity Id
257
     */
258
    public function getLastEntityId()
259
    {
260
        return $this->lastEntityId;
261
    }
262
263
    /**
264
     * Queries whether or not the SKU has already been processed.
265
     *
266
     * @param string $sku The SKU to check been processed
267
     *
268
     * @return boolean TRUE if the SKU has been processed, else FALSE
269
     */
270
    public function hasBeenProcessed($sku)
271
    {
272
        return isset($this->skuEntityIdMapping[$sku]);
273
    }
274
275
    /**
276
     * Queries whether or not the passed PK and store view code has already been processed.
277
     *
278
     * @param string $pk            The PK to check been processed
279
     * @param string $storeViewCode The store view code to check been processed
280
     *
281
     * @return boolean TRUE if the PK and store view code has been processed, else FALSE
282
     */
283
    public function storeViewHasBeenProcessed($pk, $storeViewCode)
284
    {
285
        return isset($this->skuEntityIdMapping[$pk]) && isset($this->skuStoreViewCodeMapping[$pk]) && in_array($storeViewCode, $this->skuStoreViewCodeMapping[$pk]);
286
    }
287
288
    /**
289
     * Add the passed SKU => entity ID mapping.
290
     *
291
     * @param string       $sku      The SKU
292
     * @param integer|null $entityId The optional entity ID, the last processed entity ID is used, if not set
293
     *
294
     * @return void
295
     */
296
    public function addSkuEntityIdMapping($sku, $entityId = null)
297
    {
298
        $this->skuEntityIdMapping[$sku] = $entityId == null ? $this->getLastEntityId() : $entityId;
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $entityId of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
299
    }
300
301
    /**
302
     * Add the passed SKU => store view code mapping.
303
     *
304
     * @param string $sku           The SKU
305
     * @param string $storeViewCode The store view code
306
     *
307
     * @return void
308
     */
309
    public function addSkuStoreViewCodeMapping($sku, $storeViewCode)
310
    {
311
        $this->skuStoreViewCodeMapping[$sku][] = $storeViewCode;
312
    }
313
314
    /**
315
     * Intializes the previously loaded global data for exactly one bunch.
316
     *
317
     * @param string $serial The serial of the actual import
318
     *
319
     * @return void
320
     */
321 18
    public function setUp($serial)
322
    {
323
324
        // load the status of the actual import
325 18
        $status = $this->getRegistryProcessor()->getAttribute(RegistryKeys::STATUS);
326
327
        // load the global data we've prepared initially
328 18
        $this->linkTypes = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::LINK_TYPES];
329 18
        $this->categories = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::CATEGORIES];
330 18
        $this->taxClasses = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::TAX_CLASSES];
331 18
        $this->imageTypes =  $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::IMAGE_TYPES];
332 18
        $this->storeWebsites =  $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::STORE_WEBSITES];
333 18
        $this->linkAttributes = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::LINK_ATTRIBUTES];
334
335
        // prepare the link type mappings
336 18
        $this->linkTypeMappings = $this->prepareLinkTypeMappings();
337
338
        // invoke the parent method
339 18
        parent::setUp($serial);
340 18
    }
341
342
343
    /**
344
     * Clean up the global data after importing the bunch.
345
     *
346
     * @param string $serial The serial of the actual import
347
     *
348
     * @return void
349
     */
350
    public function tearDown($serial)
351
    {
352
353
        // load the registry processor
354
        $registryProcessor = $this->getRegistryProcessor();
355
356
        // update the status
357
        $registryProcessor->mergeAttributesRecursive(
358
            RegistryKeys::STATUS,
359
            array(
360
                RegistryKeys::SKU_ENTITY_ID_MAPPING => $this->skuEntityIdMapping,
361
                RegistryKeys::SKU_STORE_VIEW_CODE_MAPPING => $this->skuStoreViewCodeMapping
362
            )
363
        );
364
365
        // invoke the parent method
366
        parent::tearDown($serial);
367
    }
368
369
    /**
370
     * Return's the available image types.
371
     *
372
     * @return array The array with the available image types
373
     */
374
    public function getImageTypes()
375
    {
376
        return $this->imageTypes;
377
    }
378
379
    /**
380
     * Return's the link type code => colums mapping.
381
     *
382
     * @return array The mapping with the link type codes => colums
383
     */
384
    public function getLinkTypeMappings()
385
    {
386
        return $this->linkTypeMappings;
387
    }
388
389
    /**
390
     * Return's the store ID of the actual row, or of the default store
391
     * if no store view code is set in the CSV file.
392
     *
393
     * @param string|null $default The default store view code to use, if no store view code is set in the CSV file
394
     *
395
     * @return integer The ID of the actual store
396
     * @throws \Exception Is thrown, if the store with the actual code is not available
397
     */
398
    public function getRowStoreId($default = null)
399
    {
400
401
        // initialize the default store view code, if not passed
402
        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...
403
            $defaultStore = $this->getDefaultStore();
404
            $default = $defaultStore[MemberNames::CODE];
405
        }
406
407
        // load the store view code the create the product/attributes for
408
        $storeViewCode = $this->getStoreViewCode($default);
409
410
        // query whether or not, the requested store is available
411
        if (isset($this->stores[$storeViewCode])) {
412
            return (integer) $this->stores[$storeViewCode][MemberNames::STORE_ID];
413
        }
414
415
        // throw an exception, if not
416
        throw new \Exception(
417
            $this->appendExceptionSuffix(
418
                sprintf('Found invalid store view code %s', $storeViewCode)
419
            )
420
        );
421
    }
422
423
    /**
424
     * Return's the store for the passed store code.
425
     *
426
     * @param string $storeCode The store code to return the store for
427
     *
428
     * @return array The requested store
429
     * @throws \Exception Is thrown, if the requested store is not available
430
     */
431
    public function getStoreByStoreCode($storeCode)
432
    {
433
434
        // query whether or not the store with the passed store code exists
435
        if (isset($this->stores[$storeCode])) {
436
            return $this->stores[$storeCode];
437
        }
438
439
        // throw an exception, if not
440
        throw new \Exception(
441
            $this->appendExceptionSuffix(
442
                sprintf('Found invalid store code %s', $storeCode)
443
            )
444
        );
445
    }
446
447
    /**
448
     * Return's the tax class ID for the passed tax class name.
449
     *
450
     * @param string $taxClassName The tax class name to return the ID for
451
     *
452
     * @return integer The tax class ID
453
     * @throws \Exception Is thrown, if the tax class with the requested name is not available
454
     */
455 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...
456
    {
457
458
        // query whether or not, the requested tax class is available
459
        if (isset($this->taxClasses[$taxClassName])) {
460
            return (integer) $this->taxClasses[$taxClassName][MemberNames::CLASS_ID];
461
        }
462
463
        // throw an exception, if not
464
        throw new \Exception(
465
            $this->appendExceptionSuffix(
466
                sprintf('Found invalid tax class name %s', $taxClassName)
467
            )
468
        );
469
    }
470
471
    /**
472
     * Return's the store website for the passed code.
473
     *
474
     * @param string $code The code of the store website to return the ID for
475
     *
476
     * @return integer The store website ID
477
     * @throws \Exception Is thrown, if the store website with the requested code is not available
478
     */
479 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...
480
    {
481
482
        // query whether or not, the requested store website is available
483
        if (isset($this->storeWebsites[$code])) {
484
            return (integer) $this->storeWebsites[$code][MemberNames::WEBSITE_ID];
485
        }
486
487
        // throw an exception, if not
488
        throw new \Exception(
489
            $this->appendExceptionSuffix(
490
                sprintf('Found invalid website code %s', $code)
491
            )
492
        );
493
    }
494
495
    /**
496
     * Return's the category with the passed path.
497
     *
498
     * @param string $path          The path of the category to return
499
     * @param string $storeViewCode The code of a store view, defaults to admin
500
     *
501
     * @return array The category
502
     * @throws \Exception Is thrown, if the requested category is not available
503
     */
504 View Code Duplication
    public function getCategoryByPath($path, $storeViewCode = StoreViewCodes::ADMIN)
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...
505
    {
506
507
        // load the categories by the passed store view code
508
        $categories = $this->getCategoriesByStoreViewCode($storeViewCode);
509
510
        // query whether or not the category with the passed path exists
511
        if (isset($categories[$path])) {
512
            return $categories[$path];
513
        }
514
515
        // throw an exception, if not
516
        throw new \Exception(
517
            $this->appendExceptionSuffix(
518
                sprintf('Can\'t find category with path %s', $path)
519
            )
520
        );
521
    }
522
523
    /**
524
     * Retrieve categories by given store view code.
525
     *
526
     * @param string $storeViewCode The store view code to retrieve the categories for
527
     *
528
     * @return array The array with the categories for the passed store view code
529
     */
530
    public function getCategoriesByStoreViewCode($storeViewCode)
531
    {
532
        return isset($this->categories[$storeViewCode]) ? $this->categories[$storeViewCode] : array();
533
    }
534
535
    /**
536
     * Return's the category with the passed ID.
537
     *
538
     * @param integer $categoryId    The ID of the category to return
539
     * @param string  $storeViewCode The code of a store view, defaults to "admin"
540
     *
541
     * @return array The category data
542
     * @throws \Exception Is thrown, if the category is not available
543
     */
544 View Code Duplication
    public function getCategory($categoryId, $storeViewCode = StoreViewCodes::ADMIN)
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...
545
    {
546
547
        // retrieve the categories with for the passed store view code
548
        $categories = $this->getCategoriesByStoreViewCode($storeViewCode);
549
550
        // try to load the category with the passed ID
551
        foreach ($categories as $category) {
552
            if ($category[MemberNames::ENTITY_ID] == $categoryId) {
553
                return $category;
554
            }
555
        }
556
557
        // throw an exception if the category is NOT available
558
        throw new \Exception(
559
            $this->appendExceptionSuffix(
560
                sprintf('Can\'t load category with ID %d', $categoryId)
561
            )
562
        );
563
    }
564
565
    /**
566
     * Return's the root category for the actual view store.
567
     *
568
     * @return array The store's root category
569
     * @throws \Exception Is thrown if the root category for the passed store code is NOT available
570
     */
571
    public function getRootCategory()
572
    {
573
574
        // load the default store
575
        $defaultStore = $this->getDefaultStore();
576
577
        // load the actual store view code
578
        $storeViewCode = $this->getStoreViewCode($defaultStore[MemberNames::CODE]);
579
580
        // query weather or not we've a root category or not
581
        if (isset($this->rootCategories[$storeViewCode])) {
582
            return $this->rootCategories[$storeViewCode];
583
        }
584
585
        // throw an exception if the root category is NOT available
586
        throw new \Exception(
587
            $this->appendExceptionSuffix(
588
                sprintf('Root category for %s is not available', $storeViewCode)
589
            )
590
        );
591
    }
592
593
    /**
594
     * Returns an array with the codes of the store views related with the passed website code.
595
     *
596
     * @param string $websiteCode The code of the website to return the store view codes for
597
     *
598
     * @return array The array with the matching store view codes
599
     */
600
    public function getStoreViewCodesByWebsiteCode($websiteCode)
601
    {
602
603
        // query whether or not the website with the passed code exists
604
        if (!isset($this->storeWebsites[$websiteCode])) {
605
            // throw an exception if the website is NOT available
606
            throw new \Exception(
607
                $this->appendExceptionSuffix(
608
                    sprintf('Website with code "%s" is not available', $websiteCode)
609
                )
610
            );
611
        }
612
613
        // initialize the array for the store view codes
614
        $storeViewCodes = array();
615
616
        // load the website ID
617
        $websiteId = (integer) $this->storeWebsites[$websiteCode][MemberNames::WEBSITE_ID];
618
619
        // iterate over the available stores to find the one of the website
620
        foreach ($this->stores as $storeCode => $store) {
621
            if ((integer) $store[MemberNames::WEBSITE_ID] === $websiteId) {
622
                $storeViewCodes[] = $storeCode;
623
            }
624
        }
625
626
        // return the array with the matching store view codes
627
        return $storeViewCodes;
628
    }
629
630
    /**
631
     * Merge the columns from the configuration with all image type columns to define which
632
     * columns should be cleaned-up.
633
     *
634
     * @return array The columns that has to be cleaned-up
635
     */
636
    public function getCleanUpColumns()
637
    {
638
639
        // load the colums that has to be cleaned-up
640
        $cleanUpColumns = $this->getConfiguration()->getParam(ConfigurationKeys::CLEAN_UP_EMPTY_COLUMNS);
641
642
        // query whether or not the image columns has to be cleaned-up also
643
        if ($this->getConfiguration()->hasParam(ConfigurationKeys::CLEAN_UP_EMPTY_IMAGE_COLUMNS) &&
644
            $this->getConfiguration()->hasParam(ConfigurationKeys::CLEAN_UP_EMPTY_IMAGE_COLUMNS, false)
0 ignored issues
show
Unused Code introduced by
The call to SubjectConfigurationInterface::hasParam() has too many arguments starting with false.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
645
        ) {
646
            // if yes load the image column names
647
            $imageTypes = array_keys($this->getImageTypes());
648
649
            // and append them to the column names from the configuration
650
            foreach ($imageTypes as $imageAttribute) {
651
                $cleanUpColumns[] = $imageAttribute;
652
            }
653
        }
654
655
        // return the array with the column names that has to be cleaned-up
656
        return $cleanUpColumns;
657
    }
658
659
    /**
660
     * Marks the relation combination processed.
661
     *
662
     * @param string $key   The key of the relation
663
     * @param string $value One of the relation values
664
     * @param string $type  The relation type to add
665
     *
666
     * @return void
667
     */
668
    public function addProcessedRelation($key, $value, $type = RelationTypes::PRODUCT_RELATION)
669
    {
670
671
        // query whether or not the child SKU has already been processed
672
        if (isset($this->processedRelations[$type][$key])) {
673
            $this->processedRelations[$type][$key][] = $value;
674
        } else {
675
            $this->processedRelations[$type][$key] = array($value);
676
        }
677
    }
678
679
    /**
680
     * Query's whether or not the relation with the passed key
681
     * value combination and the given type has been processed.
682
     *
683
     * @param string $key   The key of the relation
684
     * @param string $value One of the relation values
685
     * @param string $type  The relation type to add
686
     *
687
     * @return boolean TRUE if the combination has been processed, else FALSE
688
     */
689
    public function hasBeenProcessedRelation($key, $value, $type = RelationTypes::PRODUCT_RELATION)
690
    {
691
692
        // query whether or not the parent SKU has already been registered
693
        if (isset($this->processedRelations[$type][$key])) {
694
            return in_array($value, $this->processedRelations[$type][$key]);
695
        }
696
697
        // return FALSE if NOT
698
        return false;
699
    }
700
701
    /**
702
     * Return's the link type ID for the passed link type code.
703
     *
704
     * @param string $linkTypeCode The link type code to return the link type ID for
705
     *
706
     * @return integer The mapped link type ID
707
     * @throws \TechDivision\Import\Product\Exceptions\MapLinkTypeCodeToIdException Is thrown if the link type code is not mapped yet
708
     */
709 View Code Duplication
    public function mapLinkTypeCodeToLinkTypeId($linkTypeCode)
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...
710
    {
711
712
        // query weather or not the link type code has been mapped
713
        if (isset($this->linkTypes[$linkTypeCode])) {
714
            return $this->linkTypes[$linkTypeCode][MemberNames::LINK_TYPE_ID];
715
        }
716
717
        // throw an exception if the link type code has not been mapped yet
718
        throw new MapLinkTypeCodeToIdException(
719
            $this->appendExceptionSuffix(
720
                sprintf('Found not mapped link type code %s', $linkTypeCode)
721
            )
722
        );
723
    }
724
725
    /**
726
     * Return's the link attribute for the passed link type ID and attribute code.
727
     *
728
     * @param integer $linkTypeId    The link type
729
     * @param string  $attributeCode The attribute code
730
     *
731
     * @return array The link attribute
732
     */
733 View Code Duplication
    public function getProductLinkAttribute($linkTypeId, $attributeCode)
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...
734
    {
735
736
        // try to load the link attribute with the passed link type ID and attribute code
737
        foreach ($this->linkAttributes as $linkAttribute) {
738
            if ($linkAttribute[MemberNames::LINK_TYPE_ID] === $linkTypeId &&
739
                $linkAttribute[MemberNames::PRODUCT_LINK_ATTRIBUTE_CODE] === $attributeCode
740
            ) {
741
                // return the matching link attribute
742
                return $linkAttribute;
743
            }
744
        }
745
    }
746
747
    /**
748
     * Return's the link attribute for the passed link type and attribute code.
749
     *
750
     * @param string $linkTypeCode  The link type code
751
     * @param string $attributeCode The attribute code
752
     *
753
     * @return array The link attribute
754
     */
755 View Code Duplication
    public function getProductLinkAttributeByLinkTypeCodeAndAttributeCode($linkTypeCode, $attributeCode)
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...
756
    {
757
758
        // map the link type code => ID
759
        $linkTypeId = $this->mapLinkTypeCodeToLinkTypeId($linkTypeCode);
760
761
        // try to load the link attribute with the passed link type ID and attribute code
762
        foreach ($this->linkAttributes as $linkAttribute) {
763
            if ($linkAttribute[MemberNames::LINK_TYPE_ID] === $linkTypeId &&
764
                $linkAttribute[MemberNames::PRODUCT_LINK_ATTRIBUTE_CODE] === $attributeCode
765
            ) {
766
                // return the matching link attribute
767
                return $linkAttribute;
768
            }
769
        }
770
    }
771
772
    /**
773
     * Returns the product link attributes for the passed link type code.
774
     *
775
     * @param string $linkTypeCode The link type code
776
     *
777
     * @return array The product link types
778
     */
779
    public function getProductLinkAttributes($linkTypeCode)
780
    {
781
782
        // map the link type code => ID
783
        $linkTypeId = $this->mapLinkTypeCodeToLinkTypeId($linkTypeCode);
784
785
        // initialize the array for the link attributes
786
        $linkAttributes = array();
787
788
        // try to load the link attribute with the passed link type ID and attribute code
789
        foreach ($this->linkAttributes as $linkAttribute) {
790
            if ($linkAttribute[MemberNames::LINK_TYPE_ID] === $linkTypeId) {
791
                // return the matching link attribute
792
                $linkAttributes[] = $linkAttribute;
793
            }
794
        }
795
796
        // return the link attributes
797
        return $linkAttributes;
798
    }
799
800
    /**
801
     * Maps the link type code to the apropriate column name.
802
     *
803
     * @param string $linkTypeCode The link type code to map
804
     *
805
     * @return string The mapped column name
806
     */
807
    public function mapLinkTypeCodeToColumnName($linkTypeCode)
808
    {
809
810
        // query whether or not the link type code has a mapping
811
        if (isset($this->linkTypeCodeToColumnNameMapping[$linkTypeCode])) {
812
            return $this->linkTypeCodeToColumnNameMapping[$linkTypeCode];
813
        }
814
815
        // return the passed link type code
816
        return $linkTypeCode;
817
    }
818
819
    /**
820
     * Return the entity ID for the passed SKU.
821
     *
822
     * @param string $sku The SKU to return the entity ID for
823
     *
824
     * @return integer The mapped entity ID
825
     * @throws \TechDivision\Import\Product\Exceptions\MapSkuToEntityIdException Is thrown if the SKU is not mapped yet
826
     */
827
    public function mapSkuToEntityId($sku)
828
    {
829
830
        // query weather or not the SKU has been mapped
831
        if (isset($this->skuEntityIdMapping[$sku])) {
832
            return $this->skuEntityIdMapping[$sku];
833
        }
834
835
        // throw an exception if the SKU has not been mapped yet
836
        throw new MapSkuToEntityIdException(
837
            $this->appendExceptionSuffix(
838
                sprintf('Found not mapped entity ID for SKU %s', $sku)
839
            )
840
        );
841
    }
842
843
    /**
844
     * Return's the link type code => colums mapping.
845
     *
846
     * @return array The mapping with the link type codes => colums
847
     */
848 18
    public function prepareLinkTypeMappings()
849
    {
850
851
        // initialize the array with link type mappings
852 18
        $linkTypeMappings = array();
853
854
        // prepare the link type mappings
855 18
        foreach ($this->getLinkTypes() as $linkType) {
856
            // map the link type code to the column name, if necessary
857
            $columnName = $this->mapLinkTypeCodeToColumnName($linkType[MemberNames::CODE]);
858
859
            // create the header for the link type mapping
860
            $linkTypeMappings[$linkType[MemberNames::CODE]][] = array (
861
                $fullColumnName = sprintf('%s_skus', $columnName),
862
                $this->getLinkTypeColumnCallback($fullColumnName)
863
            );
864
865
            // add the mappings for the columns that contains the values for the configured link type attributes
866
            foreach ($this->getProductLinkAttributes($linkType[MemberNames::CODE]) as $linkAttribute) {
867
                // initialize the full column name that uses the column name as prefix and the attribute code as suffix
868
                $fullColumnName = sprintf('%s_%s', $columnName, $linkAttribute[MemberNames::PRODUCT_LINK_ATTRIBUTE_CODE]);
869
                // load the callback that extracts the values from the columns
870
                $callback = $this->getLinkTypeColumnCallback($fullColumnName);
871
872
                // map the column name to the real column name
873
                if (isset($this->linkTypeAttributeColumnToCallbackMapping[$fullColumnName])) {
874
                    list ($fullColumnName, ) = $this->linkTypeAttributeColumnToCallbackMapping[$fullColumnName];
875
                }
876
877
                // add the link type mapping for the column with the link type value
878
                $linkTypeMappings[$linkType[MemberNames::CODE]][] = array(
879
                    $fullColumnName,
880
                    $callback,
881
                    $linkAttribute[MemberNames::PRODUCT_LINK_ATTRIBUTE_CODE]
882
                );
883
            }
884 18
        }
885
886
        // return the link type mappings
887 18
        return $linkTypeMappings;
888
    }
889
890
    /**
891
     * Returns the callback method used to extract the value of the passed
892
     * column to create the link type attribute value with.
893
     *
894
     * @param string $columnName The column name to create the callback for
895
     *
896
     * @return callable The callback
897
     */
898
    public function getLinkTypeColumnCallback($columnName)
899
    {
900
901
        // query whether or not a callback mapping is available
902
        if (isset($this->linkTypeAttributeColumnToCallbackMapping[$columnName])) {
903
            // load it from the array with the mappings
904
            list (, $callbackName) = $this->linkTypeAttributeColumnToCallbackMapping[$columnName];
905
            // prepare and return the callback
906
            return array($this, $callbackName);
907
        }
908
909
        // return the default callback
910
        return array($this, 'explode');
911
    }
912
913
    /**
914
     * Extracts the keys of the passed value by exploding them
915
     * with the also passed delimiter/value delmiter.
916
     *
917
     * @param string $value          The value to extract
918
     * @param string $delimiter      The delimiter used to extract the elements
919
     * @param string $valueDelimiter The delimiter used to extract the key from the value
920
     *
921
     * @return array The exploded keys
922
     */
923 View Code Duplication
    public function explodeKey($value, $delimiter = ',', $valueDelimiter = '=')
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...
924
    {
925
926
        // initialize the array for the keys
927
        $keys = array();
928
929
        // extract the keys from the value
930
        foreach ($this->explode($value, $delimiter) as $keyValue) {
931
            list($keys[], ) = $this->explode($keyValue, $valueDelimiter);
932
        }
933
934
        // return the array with the keys
935
        return $keys;
936
    }
937
938
    /**
939
     * Extracts the values of the passed value by exploding them
940
     * with the also passed delimiter/value delimiter.
941
     *
942
     * @param string $value          The value to extract
943
     * @param string $delimiter      The delimiter used to extract the elements
944
     * @param string $valueDelimiter The delimiter used to extract the key from the value
945
     *
946
     * @return array The exploded values
947
     */
948 View Code Duplication
    public function explodeValue($value, $delimiter = ',', $valueDelimiter = '=')
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...
949
    {
950
951
        // initialize the array for the values
952
        $values = array();
953
954
        // extract the values from the value
955
        foreach ($this->explode($value, $delimiter) as $keyValue) {
956
            list(, $values[]) = $this->explode($keyValue, $valueDelimiter);
957
        }
958
959
        // return the array with the values
960
        return $values;
961
    }
962
}
963