Completed
Pull Request — master (#103)
by
unknown
03:16
created

getDefaultFrontendInputCallbackMappings()   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 0
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\ConfigurationKeys;
24
use TechDivision\Import\Utils\RegistryKeys;
25
use TechDivision\Import\Utils\FrontendInputTypes;
26
use TechDivision\Import\Product\Utils\MemberNames;
27
use TechDivision\Import\Subjects\AbstractEavSubject;
28
use TechDivision\Import\Subjects\EntitySubjectInterface;
29
30
/**
31
 * The abstract product subject implementation that provides basic product
32
 * handling business logic.
33
 *
34
 * @author    Tim Wagner <[email protected]>
35
 * @copyright 2016 TechDivision GmbH <[email protected]>
36
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
37
 * @link      https://github.com/techdivision/import-product
38
 * @link      http://www.techdivision.com
39
 */
40
abstract class AbstractProductSubject extends AbstractEavSubject implements EntitySubjectInterface
41
{
42
43
    /**
44
     * The available stores.
45
     *
46
     * @var array
47
     */
48
    protected $stores = array();
49
50
    /**
51
     * The available store websites.
52
     *
53
     * @var array
54
     */
55
    protected $storeWebsites = array();
56
57
    /**
58
     * The available EAV attributes, grouped by their attribute set and the attribute set name as keys.
59
     *
60
     * @var array
61
     */
62
    protected $attributes = array();
63
64
    /**
65
     * The available tax classes.
66
     *
67
     * @var array
68
     */
69
    protected $taxClasses = array();
70
71
    /**
72
     * The available categories.
73
     *
74
     * @var array
75
     */
76
    protected $categories = array();
77
78
    /**
79
     * The available link types.
80
     *
81
     * @var array
82
     */
83
    protected $linkTypes = array();
84
85
    /**
86
     * The ID of the product that has been created recently.
87
     *
88
     * @var string
89
     */
90
    protected $lastEntityId;
91
92
    /**
93
     * The SKU of the product that has been created recently.
94
     *
95
     * @var string
96
     */
97
    protected $lastSku;
98
99
    /**
100
     * The Magento 2 configuration.
101
     *
102
     * @var array
103
     */
104
    protected $coreConfigData;
105
106
    /**
107
     * The mapping for the SKUs to the created entity IDs.
108
     *
109
     * @var array
110
     */
111
    protected $skuEntityIdMapping = array();
112
113
    /**
114
     * The mapping for the SKUs to the store view codes.
115
     *
116
     * @var array
117
     */
118
    protected $skuStoreViewCodeMapping = array();
119
120
    /**
121
     * The array with the available image types and their label columns.
122
     *
123
     * @var array
124
     */
125
    protected $imageTypes = array();
126
127
    /**
128
     * Mappings for CSV column header => attribute code.
129
     *
130
     * @var array
131
     */
132
    protected $headerMappings = array(
133
        'product_online'       => 'status',
134
        'tax_class_name'       => 'tax_class_id',
135
        'bundle_price_type'    => 'price_type',
136
        'bundle_sku_type'      => 'sku_type',
137
        'bundle_price_view'    => 'price_view',
138
        'bundle_weight_type'   => 'weight_type',
139
        'bundle_shipment_type' => 'shipment_type',
140
        'related_skus'         => 'relation_skus',
141
        'related_position'     => 'relation_position',
142
        'crosssell_skus'       => 'cross_sell_skus',
143
        'crosssell_position'   => 'cross_sell_position',
144
        'upsell_skus'          => 'up_sell_skus',
145
        'upsell_position'      => 'up_sell_position',
146
        'msrp_price'           => 'msrp',
147
        'base_image'           => 'image',
148
        'base_image_label'     => 'image_label',
149
        'thumbnail_image'      => 'thumbnail',
150
        'thumbnail_image_label'=> 'thumbnail_label'
151
    );
152
153
    /**
154
     * The default mappings for the user defined attributes, based on the attributes frontend input type.
155
     *
156
     * @var array
157
     */
158
    protected $defaultFrontendInputCallbackMappings = array(
159
        FrontendInputTypes::SELECT      => 'import_product.callback.select',
160
        FrontendInputTypes::MULTISELECT => 'import_product.callback.multiselect',
161
        FrontendInputTypes::BOOLEAN     => 'import_product.callback.boolean'
162
    );
163
164
    /**
165
     * Return's the default callback frontend input mappings for the user defined attributes.
166
     *
167
     * @return array The default frontend input callback mappings
168
     */
169
    public function getDefaultFrontendInputCallbackMappings()
170
    {
171
        return $this->defaultFrontendInputCallbackMappings;
172
    }
173 18
174
    /**
175 18
     * Return's the available link types.
176
     *
177
     * @return array The link types
178
     */
179
    public function getLinkTypes()
180
    {
181
        return $this->linkTypes;
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
    public function setLastEntityId($lastEntityId)
214
    {
215
        $this->lastEntityId = $lastEntityId;
216
    }
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
     * Queries whether or not the passed PK and store view code has already been processed.
242
     *
243
     * @param string $pk            The PK to check been processed
244
     * @param string $storeViewCode The store view code to check been processed
245
     *
246
     * @return boolean TRUE if the PK and store view code has been processed, else FALSE
247
     */
248
    public function storeViewHasBeenProcessed($pk, $storeViewCode)
249
    {
250
        return isset($this->skuEntityIdMapping[$pk]) && isset($this->skuStoreViewCodeMapping[$pk]) && in_array($storeViewCode, $this->skuStoreViewCodeMapping[$pk]);
251
    }
252
253
    /**
254
     * Add the passed SKU => entity ID mapping.
255
     *
256
     * @param string $sku The SKU
257
     *
258
     * @return void
259
     */
260
    public function addSkuEntityIdMapping($sku)
261
    {
262
        $this->skuEntityIdMapping[$sku] = $this->getLastEntityId();
263
    }
264
265
    /**
266
     * Add the passed SKU => store view code mapping.
267
     *
268
     * @param string $sku           The SKU
269
     * @param string $storeViewCode The store view code
270
     *
271
     * @return void
272
     */
273
    public function addSkuStoreViewCodeMapping($sku, $storeViewCode)
274
    {
275
        $this->skuStoreViewCodeMapping[$sku][] = $storeViewCode;
276
    }
277
278
    /**
279
     * Intializes the previously loaded global data for exactly one bunch.
280
     *
281
     * @param string $serial The serial of the actual import
282
     *
283
     * @return void
284
     */
285
    public function setUp($serial)
286
    {
287
288
        // load the status of the actual import
289 18
        $status = $this->getRegistryProcessor()->getAttribute($serial);
290
291
        // load the global data we've prepared initially
292
        $this->linkTypes = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::LINK_TYPES];
293 18
        $this->categories = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::CATEGORIES];
294
        $this->taxClasses = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::TAX_CLASSES];
295
        $this->imageTypes =  $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::IMAGE_TYPES];
296 18
        $this->storeWebsites =  $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::STORE_WEBSITES];
297 18
298 18
        // invoke the parent method
299 18
        parent::setUp($serial);
300
    }
301
302 18
303
    /**
304
     * Clean up the global data after importing the bunch.
305 18
     *
306 18
     * @param string $serial The serial of the actual import
307
     *
308
     * @return void
309
     */
310
    public function tearDown($serial)
311
    {
312
313
        // invoke the parent method
314
        parent::tearDown($serial);
315
316
        // load the registry processor
317
        $registryProcessor = $this->getRegistryProcessor();
318
319
        // update the status
320
        $registryProcessor->mergeAttributesRecursive(
321
            $serial,
322
            array(
323
                RegistryKeys::FILES => array($this->getFilename() => array(RegistryKeys::STATUS => 1)),
324
                RegistryKeys::SKU_ENTITY_ID_MAPPING => $this->skuEntityIdMapping,
325
                RegistryKeys::SKU_STORE_VIEW_CODE_MAPPING => $this->skuStoreViewCodeMapping
326
            )
327
        );
328
    }
329
330
    /**
331
     * Return's the available image types.
332
     *
333
     * @return array The array with the available image types
334
     */
335
    public function getImageTypes()
336
    {
337
        return $this->imageTypes;
338
    }
339
340
    /**
341
     * Return's the store ID of the actual row, or of the default store
342
     * if no store view code is set in the CSV file.
343
     *
344
     * @param string|null $default The default store view code to use, if no store view code is set in the CSV file
345
     *
346
     * @return integer The ID of the actual store
347
     * @throws \Exception Is thrown, if the store with the actual code is not available
348
     */
349
    public function getRowStoreId($default = null)
350
    {
351
352
        // initialize the default store view code, if not passed
353
        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...
354
            $defaultStore = $this->getDefaultStore();
355
            $default = $defaultStore[MemberNames::CODE];
356
        }
357
358
        // load the store view code the create the product/attributes for
359
        $storeViewCode = $this->getStoreViewCode($default);
360
361
        // query whether or not, the requested store is available
362
        if (isset($this->stores[$storeViewCode])) {
363
            return (integer) $this->stores[$storeViewCode][MemberNames::STORE_ID];
364
        }
365
366
        // throw an exception, if not
367
        throw new \Exception(
368
            $this->appendExceptionSuffix(
369
                sprintf('Found invalid store view code %s', $storeViewCode)
370
            )
371
        );
372
    }
373
374
    /**
375
     * Return's the tax class ID for the passed tax class name.
376
     *
377
     * @param string $taxClassName The tax class name to return the ID for
378
     *
379
     * @return integer The tax class ID
380
     * @throws \Exception Is thrown, if the tax class with the requested name is not available
381
     */
382 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...
383
    {
384
385
        // query whether or not, the requested tax class is available
386
        if (isset($this->taxClasses[$taxClassName])) {
387
            return (integer) $this->taxClasses[$taxClassName][MemberNames::CLASS_ID];
388
        }
389
390
        // throw an exception, if not
391
        throw new \Exception(
392
            $this->appendExceptionSuffix(
393
                sprintf('Found invalid tax class name %s', $taxClassName)
394
            )
395
        );
396
    }
397
398
    /**
399
     * Return's the store website for the passed code.
400
     *
401
     * @param string $code The code of the store website to return the ID for
402
     *
403
     * @return integer The store website ID
404
     * @throws \Exception Is thrown, if the store website with the requested code is not available
405
     */
406 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...
407
    {
408
409
        // query whether or not, the requested store website is available
410
        if (isset($this->storeWebsites[$code])) {
411
            return (integer) $this->storeWebsites[$code][MemberNames::WEBSITE_ID];
412
        }
413
414
        // throw an exception, if not
415
        throw new \Exception(
416
            $this->appendExceptionSuffix(
417
                sprintf('Found invalid website code %s', $code)
418
            )
419
        );
420
    }
421
422
    /**
423
     * Return's the category with the passed path.
424
     *
425
     * @param string $path The path of the category to return
426
     *
427
     * @return array The category
428
     * @throws \Exception Is thrown, if the requested category is not available
429
     */
430
    public function getCategoryByPath($path)
431
    {
432
433
        // query whether or not the category with the passed path exists
434
        if (isset($this->categories[$path])) {
435
            return $this->categories[$path];
436
        }
437
438
        // throw an exception, if not
439
        throw new \Exception(
440
            $this->appendExceptionSuffix(
441
                sprintf('Can\'t find category with path %s', $path)
442
            )
443
        );
444
    }
445
446
    /**
447
     * Return's the category with the passed ID.
448
     *
449
     * @param integer $categoryId The ID of the category to return
450
     *
451
     * @return array The category data
452
     * @throws \Exception Is thrown, if the category is not available
453
     */
454
    public function getCategory($categoryId)
455
    {
456
457
        // try to load the category with the passed ID
458
        foreach ($this->categories as $category) {
459
            if ($category[MemberNames::ENTITY_ID] == $categoryId) {
460
                return $category;
461
            }
462
        }
463
464
        // throw an exception if the category is NOT available
465
        throw new \Exception(
466
            $this->appendExceptionSuffix(
467
                sprintf('Can\'t load category with ID %d', $categoryId)
468
            )
469
        );
470
    }
471
472
    /**
473
     * Return's the root category for the actual view store.
474
     *
475
     * @return array The store's root category
476
     * @throws \Exception Is thrown if the root category for the passed store code is NOT available
477
     */
478
    public function getRootCategory()
479
    {
480
481
        // load the default store
482
        $defaultStore = $this->getDefaultStore();
483
484
        // load the actual store view code
485
        $storeViewCode = $this->getStoreViewCode($defaultStore[MemberNames::CODE]);
486
487
        // query weather or not we've a root category or not
488
        if (isset($this->rootCategories[$storeViewCode])) {
489
            return $this->rootCategories[$storeViewCode];
490
        }
491
492
        // throw an exception if the root category is NOT available
493
        throw new \Exception(
494
            $this->appendExceptionSuffix(
495
                sprintf('Root category for %s is not available', $storeViewCode)
496
            )
497
        );
498
    }
499
500
    /**
501
     * Returns an array with the codes of the store views related with the passed website code.
502
     *
503
     * @param string $websiteCode The code of the website to return the store view codes for
504
     *
505
     * @return array The array with the matching store view codes
506
     */
507
    public function getStoreViewCodesByWebsiteCode($websiteCode)
508
    {
509
510
        // query whether or not the website with the passed code exists
511
        if (!isset($this->storeWebsites[$websiteCode])) {
512
            // throw an exception if the website is NOT available
513
            throw new \Exception(
514
                $this->appendExceptionSuffix(
515
                    sprintf('Website with code "%s" is not available', $websiteCode)
516
                )
517
            );
518
        }
519
520
        // initialize the array for the store view codes
521
        $storeViewCodes = array();
522
523
        // load the website ID
524
        $websiteId = (integer) $this->storeWebsites[$websiteCode][MemberNames::WEBSITE_ID];
525
526
        // iterate over the available stores to find the one of the website
527
        foreach ($this->stores as $storeCode => $store) {
528
            if ((integer) $store[MemberNames::WEBSITE_ID] === $websiteId) {
529
                $storeViewCodes[] = $storeCode;
530
            }
531
        }
532
533
        // return the array with the matching store view codes
534
        return $storeViewCodes;
535
    }
536
537
    /**
538
     * Merge the columns from the configuration with all image type columns to define which columns should be cleaned up
539
     *
540
     * @return array|string
541
     */
542
    public function getCleanUpColumns()
543
    {
544
        $configurationCleanUpColumns = $this->getConfiguration()->getParam(ConfigurationKeys::CLEAN_UP_EMPTY_COLUMNS);
545
        if ($this->getConfiguration()->getParam(ConfigurationKeys::CLEAN_UP_EMPTY_IMAGE_COLUMNS, false) === true) {
546
            $imageTypes = array_keys($this->getImageTypes());
547
            foreach ($imageTypes as $imageAttribute) {
548
                $configurationCleanUpColumns[] = $imageAttribute;
549
            }
550
        }
551
        return $configurationCleanUpColumns;
552
    }
553
}
554