Completed
Push — master ( bce332...18fde1 )
by Tim
9s
created

BunchSubject::getRowStoreId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 5

Duplication

Lines 14
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 14
loc 14
rs 9.4285
c 0
b 0
f 0
ccs 0
cts 5
cp 0
cc 2
eloc 5
nc 2
nop 0
crap 6

1 Method

Rating   Name   Duplication   Size   Complexity  
A BunchSubject::persistStockItem() 0 4 1
1
<?php
2
3
/**
4
 * TechDivision\Import\Product\Subjects\BunchSubject
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 Goodby\CSV\Export\Standard\Exporter;
24
use Goodby\CSV\Export\Standard\ExporterConfig;
25
use TechDivision\Import\Subjects\AbstractSubject;
26
use TechDivision\Import\Utils\RegistryKeys;
27
use TechDivision\Import\Services\RegistryProcessor;
28
use TechDivision\Import\Product\Utils\MemberNames;
29
use TechDivision\Import\Product\Utils\VisibilityKeys;
30
use TechDivision\Import\Product\Services\ProductProcessorInterface;
31
use TechDivision\Import\Utils\StoreViewCodes;
32
33
/**
34
 * The subject implementation that handles the business logic to persist products.
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
class BunchSubject extends AbstractProductSubject
43
{
44
45
    /**
46
     * The mapping for the supported backend types (for the product entity) => persist methods.
47
     *
48
     * @var array
49
     */
50
    protected $backendTypes = array(
51
        'datetime' => 'persistProductDatetimeAttribute',
52
        'decimal'  => 'persistProductDecimalAttribute',
53
        'int'      => 'persistProductIntAttribute',
54
        'text'     => 'persistProductTextAttribute',
55
        'varchar'  => 'persistProductVarcharAttribute'
56
    );
57
58
    /**
59
     * Mappings for attribute code => CSV column header.
60
     *
61
     * @var array
62
     */
63
    protected $headerMappings = array(
64
        'status' => 'product_online',
65
        'tax_class_id' => 'tax_class_name',
66
        'price_type'  => 'bundle_price_type',
67
        'sku_type' => 'bundle_sku_type',
68
        'price_view' => 'bundle_price_view',
69
        'weight_type' => 'bundle_weight_type',
70
        'image' => 'base_image',
71
        'image_label' => 'base_image_label',
72
        'thumbnail' => 'thumbnail_image',
73
        'thumbnail_label' => 'thumbnail_image_label'
74
    );
75
76
    /**
77
     * Mappings for the table column => CSV column header.
78
     *
79
     * @var array
80
     */
81
    protected $headerStockMappings = array(
82
        'qty'                         => array('qty', 'float'),
83
        'min_qty'                     => array('out_of_stock_qty', 'float'),
84
        'use_config_min_qty'          => array('use_config_min_qty', 'int'),
85
        'is_qty_decimal'              => array('is_qty_decimal', 'int'),
86
        'backorders'                  => array('allow_backorders', 'int'),
87
        'use_config_backorders'       => array('use_config_backorders', 'int'),
88
        'min_sale_qty'                => array('min_cart_qty', 'float'),
89
        'use_config_min_sale_qty'     => array('use_config_min_sale_qty', 'int'),
90
        'max_sale_qty'                => array('max_cart_qty', 'float'),
91
        'use_config_max_sale_qty'     => array('use_config_max_sale_qty', 'int'),
92
        'is_in_stock'                 => array('is_in_stock', 'int'),
93
        'notify_stock_qty'            => array('notify_on_stock_below', 'float'),
94
        'use_config_notify_stock_qty' => array('use_config_notify_stock_qty', 'int'),
95
        'manage_stock'                => array('manage_stock', 'int'),
96
        'use_config_manage_stock'     => array('use_config_manage_stock', 'int'),
97
        'use_config_qty_increments'   => array('use_config_qty_increments', 'int'),
98
        'qty_increments'              => array('qty_increments', 'float'),
99
        'use_config_enable_qty_inc'   => array('use_config_enable_qty_inc', 'int'),
100
        'enable_qty_increments'       => array('enable_qty_increments', 'int'),
101
        'is_decimal_divided'          => array('is_decimal_divided', 'int'),
102
    );
103
104
    /**
105
     * The array with the available visibility keys.
106
     *
107
     * @var array
108
     */
109
    protected $availableVisibilities = array(
110
        'Not Visible Individually' => VisibilityKeys::VISIBILITY_NOT_VISIBLE,
111
        'Catalog'                  => VisibilityKeys::VISIBILITY_IN_CATALOG,
112
        'Search'                   => VisibilityKeys::VISIBILITY_IN_SEARCH,
113
        'Catalog, Search'          => VisibilityKeys::VISIBILITY_BOTH
114
    );
115
116
    /**
117
     * The attribute set of the product that has to be created.
118
     *
119
     * @var array
120
     */
121
    protected $attributeSet = array();
122
123
    /**
124
     * The array containing the data for product type configuration (configurables, bundles, etc).
125
     *
126
     * @var array
127
     */
128
    protected $artefacs = array();
129
130
    /**
131
     * The mapping for the SKUs to the created entity IDs.
132
     *
133
     * @var array
134
     */
135
    protected $skuEntityIdMapping = array();
136
137
    /**
138
     * The category IDs the product is related with.
139
     *
140
     * @var array
141
     */
142
    protected $productCategoryIds = array();
143
144
    /**
145
     * Set's the attribute set of the product that has to be created.
146
     *
147
     * @param array $attributeSet The attribute set
148
     *
149
     * @return void
150
     */
151
    public function setAttributeSet(array $attributeSet)
152
    {
153
        $this->attributeSet = $attributeSet;
154
    }
155
156
    /**
157
     * Return's the attribute set of the product that has to be created.
158
     *
159
     * @return array The attribute set
160
     */
161
    public function getAttributeSet()
162
    {
163
        return $this->attributeSet;
164
    }
165
166
    /**
167
     * Clean up the global data after importing the bunch.
168
     *
169
     * @return void
170
     */
171
    public function tearDown()
172
    {
173
174
        // invoke parent method
175
        parent::tearDown();
176
177
        // export the artefacts
178
        $this->exportArtefacts();
179
180
        // load the registry processor
181
        $registryProcessor = $this->getRegistryProcessor();
182
183
        // update the status with the SKU => entity ID mapping
184
        $registryProcessor->mergeAttributesRecursive(
185
            $this->getSerial(),
186
            array(RegistryKeys::SKU_ENTITY_ID_MAPPING => $this->skuEntityIdMapping)
187
        );
188
    }
189
190
    /**
191
     * Export's the artefacts to CSV files.
192
     *
193
     * @return void
194
     */
195
    public function exportArtefacts()
196
    {
197
198
        // load the target directory and the actual timestamp
199
        $targetDir = $this->getConfiguration()->getTargetDir();
200
        $timestamp = date('Ymd-His');
201
202
        // initialize the counter
203
        $counter = 0;
204
205
        // iterate over the artefacts and export them
206
        foreach ($this->getArtefacts() as $artefactType => $artefacts) {
207
            foreach ($artefacts as $entityArtefacts) {
208
                // initialize the the exporter
209
                $exporter = new Exporter($this->getExportConfig());
210
211
                // initialize the bunch
212
                $bunch = array();
213
214
                // set the bunch header and append the artefact data
215
                $first = reset($entityArtefacts);
216
                $second = reset($first);
217
                $bunch[] = array_keys($second);
218
219
                // export the artefacts
220
                foreach ($entityArtefacts as $entityArtefact) {
221
                    $bunch = array_merge($bunch, $entityArtefact);
222
                }
223
224
                // export the artefact (bunch)
225
                $exporter->export(sprintf('%s/%s-%s_%d.csv', $targetDir, $artefactType, $timestamp, $counter++), $bunch);
226
            }
227
        }
228
    }
229
230
    /**
231
     * Initialize and return the exporter configuration.
232
     *
233
     * @return \Goodby\CSV\Export\Standard\ExporterConfig The exporter configuration
234
     */
235
    protected function getExportConfig()
236
    {
237
238
        // initialize the lexer configuration
239
        $config = new ExporterConfig();
240
241
        // query whether or not a delimiter character has been configured
242
        if ($delimiter = $this->getConfiguration()->getDelimiter()) {
243
            $config->setDelimiter($delimiter);
244
        }
245
246
        // query whether or not a custom escape character has been configured
247
        if ($escape = $this->getConfiguration()->getEscape()) {
248
            $config->setEscape($escape);
249
        }
250
251
        // query whether or not a custom enclosure character has been configured
252
        if ($enclosure = $this->getConfiguration()->getEnclosure()) {
253
            $config->setEnclosure($enclosure);
254
        }
255
256
        // query whether or not a custom source charset has been configured
257
        if ($fromCharset = $this->getConfiguration()->getFromCharset()) {
258
            $config->setFromCharset($fromCharset);
259
        }
260
261
        // query whether or not a custom target charset has been configured
262
        if ($toCharset = $this->getConfiguration()->getToCharset()) {
263
            $config->setToCharset($toCharset);
264
        }
265
266
        // query whether or not a custom file mode has been configured
267
        if ($fileMode = $this->getConfiguration()->getFileMode()) {
268
            $config->setFileMode($fileMode);
269
        }
270
271
        // return the lexer configuratio
272
        return $config;
273
    }
274
275
    /**
276
     * Cast's the passed value based on the backend type information.
277
     *
278
     * @param string $backendType The backend type to cast to
279
     * @param mixed  $value       The value to be casted
280
     *
281
     * @return mixed The casted value
282
     */
283
    public function castValueByBackendType($backendType, $value)
284
    {
285
286
        // cast the value to a valid timestamp
287
        if ($backendType === 'datetime') {
288
            return \DateTime::createFromFormat($this->getSourceDateFormat(), $value)->format('Y-m-d H:i:s');
289
        }
290
291
        // cast the value to a float value
292
        if ($backendType === 'float') {
293
            return (float) $value;
294
        }
295
296
        // cast the value to an integer
297
        if ($backendType === 'int') {
298
            return (int) $value;
299
        }
300
301
        // we don't need to cast strings
302
        return $value;
303
    }
304
305
    /**
306
     * Return's the mappings for the table column => CSV column header.
307
     *
308
     * @return array The header stock mappings
309
     */
310
    public function getHeaderStockMappings()
311
    {
312
        return $this->headerStockMappings;
313
    }
314
315
    /**
316
     * Return's mapping for the supported backend types (for the product entity) => persist methods.
317
     *
318
     * @return array The mapping for the supported backend types
319
     */
320
    public function getBackendTypes()
321
    {
322
        return $this->backendTypes;
323
    }
324
325
    /**
326
     * Return's the artefacts for post-processing.
327
     *
328
     * @return array The artefacts
329
     */
330
    public function getArtefacts()
331
    {
332
        return $this->artefacs;
333
    }
334
335
    /**
336
     * Return's the visibility key for the passed visibility string.
337
     *
338
     * @param string $visibility The visibility string the return the key for
339
     *
340
     * @return integer The requested visibility key
341
     * @throws \Exception Is thrown, if the requested visibility is not available
342
     */
343
    public function getVisibilityIdByValue($visibility)
344
    {
345
346
        // query whether or not, the requested visibility is available
347
        if (isset($this->availableVisibilities[$visibility])) {
348
            return $this->availableVisibilities[$visibility];
349
        }
350
351
        // throw an exception, if not
352
        throw new \Exception(sprintf('Found invalid visibility %s', $visibility));
353
    }
354
355
    /**
356
     * Map the passed attribute code, if a header mapping exists and return the
357
     * mapped mapping.
358
     *
359
     * @param string $attributeCode The attribute code to map
360
     *
361
     * @return string The mapped attribute code, or the original one
362
     */
363
    public function mapAttributeCodeByHeaderMapping($attributeCode)
364
    {
365
366
        // query weather or not we've a mapping, if yes, map the attribute code
367
        if (isset($this->headerMappings[$attributeCode])) {
368
            $attributeCode = $this->headerMappings[$attributeCode];
369
        }
370
371
        // return the (mapped) attribute code
372
        return $attributeCode;
373
    }
374
375
    /**
376
     * Add the passed product type artefacts to the product with the
377
     * last entity ID.
378
     *
379
     * @param string $type      The artefact type, e. g. configurable
380
     * @param array  $artefacts The product type artefacts
381
     *
382
     * @return void
383
     * @uses \TechDivision\Import\Product\Subjects\BunchSubject::getLastEntityId()
384
     */
385
    public function addArtefacts($type, array $artefacts)
386
    {
387
388
        // query whether or not, any artefacts are available
389
        if (sizeof($artefacts) === 0) {
390
            return;
391
        }
392
393
        // append the artefacts to the stack
394
        $this->artefacs[$type][$this->getLastEntityId()][] = $artefacts;
395
    }
396
397
    /**
398
     * Add the passed SKU => entity ID mapping.
399
     *
400
     * @param string $sku The SKU
401
     *
402
     * @return void
403
     * @uses \Import\Csv\Actions\ProductImportBunchAction::getLastEntityId()
404
     */
405
    public function addSkuEntityIdMapping($sku)
406
    {
407
        $this->skuEntityIdMapping[$sku] = $this->getLastEntityId();
408
    }
409
410
    /**
411
     * Add the passed category ID to the product's category list.
412
     *
413
     * @param integer $categoryId The category ID to add
414
     *
415
     * @return void
416
     */
417
    public function addProductCategoryId($categoryId)
418
    {
419
        $this->productCategoryIds[$this->getLastEntityId()][$categoryId] = $this->getLastEntityId();
420
    }
421
422
    /**
423
     * Return's the list with category IDs the product is related with.
424
     *
425
     * @return array The product's category IDs
426
     */
427
    public function getProductCategoryIds()
428
    {
429
430
        // initialize the array with the product's category IDs
431
        $categoryIds = array();
432
433
        // query whether or not category IDs are available for the actual product entity
434
        if (isset($this->productCategoryIds[$lastEntityId = $this->getLastEntityId()])) {
435
            $categoryIds = $this->productCategoryIds[$lastEntityId];
436
        }
437
438
        // return the array with the product's category IDs
439
        return $categoryIds;
440
    }
441
442
    /**
443
     * Return's the attribute option value with the passed value and store ID.
444
     *
445
     * @param mixed   $value   The option value
446
     * @param integer $storeId The ID of the store
447
     *
448
     * @return array|boolean The attribute option value instance
449
     */
450
    public function getEavAttributeOptionValueByOptionValueAndStoreId($value, $storeId)
451
    {
452
        return $this->getProductProcessor()->getEavAttributeOptionValueByOptionValueAndStoreId($value, $storeId);
453
    }
454
455
    /**
456
     * Return's the URL rewrites for the passed URL entity type and ID.
457
     *
458
     * @param string  $entityType The entity type to load the URL rewrites for
459
     * @param integer $entityId   The entity ID to laod the rewrites for
460
     *
461
     * @return array The URL rewrites
462
     */
463 1
    public function getUrlRewritesByEntityTypeAndEntityId($entityType, $entityId)
464
    {
465 1
        return $this->getProductProcessor()->getUrlRewritesByEntityTypeAndEntityId($entityType, $entityId);
466
    }
467
468
    /**
469
     * Persist's the passed product data and return's the ID.
470
     *
471
     * @param array $product The product data to persist
472
     *
473
     * @return string The ID of the persisted entity
474
     */
475
    public function persistProduct($product)
476
    {
477
        return $this->getProductProcessor()->persistProduct($product);
478
    }
479
480
    /**
481
     * Persist's the passed product varchar attribute.
482
     *
483
     * @param array $attribute The attribute to persist
484
     *
485
     * @return void
486
     */
487
    public function persistProductVarcharAttribute($attribute)
488
    {
489
        $this->getProductProcessor()->persistProductVarcharAttribute($attribute);
490
    }
491
492
    /**
493
     * Persist's the passed product integer attribute.
494
     *
495
     * @param array $attribute The attribute to persist
496
     *
497
     * @return void
498
     */
499
    public function persistProductIntAttribute($attribute)
500
    {
501
        $this->getProductProcessor()->persistProductIntAttribute($attribute);
502
    }
503
504
    /**
505
     * Persist's the passed product decimal attribute.
506
     *
507
     * @param array $attribute The attribute to persist
508
     *
509
     * @return void
510
     */
511
    public function persistProductDecimalAttribute($attribute)
512
    {
513
        $this->getProductProcessor()->persistProductDecimalAttribute($attribute);
514
    }
515
516
    /**
517
     * Persist's the passed product datetime attribute.
518
     *
519
     * @param array $attribute The attribute to persist
520
     *
521
     * @return void
522
     */
523
    public function persistProductDatetimeAttribute($attribute)
524
    {
525
        $this->getProductProcessor()->persistProductDatetimeAttribute($attribute);
526
    }
527
528
    /**
529
     * Persist's the passed product text attribute.
530
     *
531
     * @param array $attribute The attribute to persist
532
     *
533
     * @return void
534
     */
535
    public function persistProductTextAttribute($attribute)
536
    {
537
        $this->getProductProcessor()->persistProductTextAttribute($attribute);
538
    }
539
540
    /**
541
     * Persist's the passed product website data and return's the ID.
542
     *
543
     * @param array $productWebsite The product website data to persist
544
     *
545
     * @return void
546
     */
547
    public function persistProductWebsite($productWebsite)
548
    {
549
        $this->getProductProcessor()->persistProductWebsite($productWebsite);
550
    }
551
552
    /**
553
     * Persist's the passed product category data and return's the ID.
554
     *
555
     * @param array $productCategory The product category data to persist
556
     *
557
     * @return void
558
     */
559
    public function persistProductCategory($productCategory)
560
    {
561
        $this->getProductProcessor()->persistProductCategory($productCategory);
562
    }
563
564
    /**
565
     * Persist's the passed stock item data and return's the ID.
566
     *
567
     * @param array $stockItem The stock item data to persist
568
     *
569
     * @return void
570
     */
571
    public function persistStockItem($stockItem)
572
    {
573
        $this->getProductProcessor()->persistStockItem($stockItem);
574
    }
575
576
    /**
577
     * Persist's the passed stock status data and return's the ID.
578
     *
579
     * @param array $stockStatus The stock status data to persist
580
     *
581
     * @return void
582
     */
583
    public function persistStockStatus($stockStatus)
584
    {
585
        $this->getProductProcessor()->persistStockStatus($stockStatus);
586
    }
587
588
    /**
589
     * Persist's the URL write with the passed data.
590
     *
591
     * @param array $row The URL rewrite to persist
592
     *
593
     * @return void
594
     */
595 1
    public function persistUrlRewrite($row)
596
    {
597 1
        $this->getProductProcessor()->persistUrlRewrite($row);
598 1
    }
599
600
    /**
601
     * Remove's the entity with the passed attributes.
602
     *
603
     * @param array       $row  The attributes of the entity to remove
604
     * @param string|null $name The name of the prepared statement that has to be executed
605
     *
606
     * @return void
607
     */
608
    public function removeProduct($row, $name = null)
609
    {
610
        $this->getProductProcessor()->removeProduct($row, $name);
611
    }
612
613
    /**
614
     * Delete's the URL rewrite(s) with the passed attributes.
615
     *
616
     * @param array       $row  The attributes of the entity to remove
617
     * @param string|null $name The name of the prepared statement that has to be executed
618
     *
619
     * @return void
620
     */
621 1
    public function removeUrlRewrite($row, $name = null)
622
    {
623 1
        $this->getProductProcessor()->removeUrlRewrite($row, $name);
624 1
    }
625
626
    /**
627
     * Delete's the stock item(s) with the passed attributes.
628
     *
629
     * @param array       $row  The attributes of the entity to remove
630
     * @param string|null $name The name of the prepared statement that has to be executed
631
     *
632
     * @return void
633
     */
634
    public function removeStockItem($row, $name = null)
635
    {
636
        $this->getProductProcessor()->removeStockItem($row, $name);
637
    }
638
639
    /**
640
     * Delete's the stock status with the passed attributes.
641
     *
642
     * @param array       $row  The attributes of the entity to remove
643
     * @param string|null $name The name of the prepared statement that has to be executed
644
     *
645
     * @return void
646
     */
647
    public function removeStockStatus($row, $name = null)
648
    {
649
        $this->getProductProcessor()->removeStockStatus($row, $name);
650
    }
651
652
    /**
653
     * Delete's the product website relations with the passed attributes.
654
     *
655
     * @param array       $row  The attributes of the entity to remove
656
     * @param string|null $name The name of the prepared statement that has to be executed
657
     *
658
     * @return void
659
     */
660
    public function removeProductWebsite($row, $name = null)
661
    {
662
        $this->getProductProcessor()->removeProductWebsite($row, $name);
663
    }
664
665
    /**
666
     * Delete's the product category relations with the passed attributes.
667
     *
668
     * @param array       $row  The attributes of the entity to remove
669
     * @param string|null $name The name of the prepared statement that has to be executed
670
     *
671
     * @return void
672
     */
673
    public function removeProductCategory($row, $name = null)
674
    {
675
        $this->getProductProcessor()->removeProductCategory($row, $name);
676
    }
677
}
678