ProductSourceItemObserver   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 185
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 5
Bugs 1 Features 0
Metric Value
eloc 46
c 5
b 1
f 0
dl 0
loc 185
ccs 0
cts 51
cp 0
rs 10
wmc 14

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A newArtefact() 0 3 1
A process() 0 49 6
A createObserver() 0 34 3
A loadDefaultValues() 0 5 1
A addArtefacts() 0 3 1
A getProcessor() 0 3 1
1
<?php
2
3
/**
4
 * TechDivision\Import\Product\Msi\Observers\ProductSourceItemObserver
5
 *
6
 * PHP version 7
7
 *
8
 * @author    Tim Wagner <[email protected]>
9
 * @copyright 2019 TechDivision GmbH <[email protected]>
10
 * @license   https://opensource.org/licenses/MIT
11
 * @link      https://github.com/techdivision/import-product-msi
12
 * @link      http://www.techdivision.com
13
 */
14
15
namespace TechDivision\Import\Product\Msi\Observers;
16
17
use TechDivision\Import\Subjects\SubjectInterface;
18
use TechDivision\Import\Product\Msi\Utils\ColumnKeys;
19
use TechDivision\Import\Product\Msi\Utils\MemberNames;
20
use TechDivision\Import\Observers\ObserverFactoryInterface;
21
use TechDivision\Import\Product\Observers\AbstractProductImportObserver;
22
use TechDivision\Import\Product\Msi\Services\MsiBunchProcessorInterface;
23
24
/**
25
 * Observer that extracts the MSI source item data to a specific CSV file.
26
 *
27
 * @author    Tim Wagner <[email protected]>
28
 * @copyright 2019 TechDivision GmbH <[email protected]>
29
 * @license   https://opensource.org/licenses/MIT
30
 * @link      https://github.com/techdivision/import-product-msi
31
 * @link      http://www.techdivision.com
32
 */
33
class ProductSourceItemObserver extends AbstractProductImportObserver implements ObserverFactoryInterface
34
{
35
36
    /**
37
     * The artefact type.
38
     *
39
     * @var string
40
     */
41
    const ARTEFACT_TYPE = 'inventory-msi';
42
43
    /**
44
     * The bunch processor instance.
45
     *
46
     * @var \TechDivision\Import\Product\Msi\Services\MsiBunchProcessorInterface
47
     */
48
    protected $processor;
49
50
    /**
51
     * The array for the inventory source templates, used if the column with the
52
     * inventory source data is NOT part of the actual file.
53
     *
54
     * @var array
55
     */
56
    protected $templateDefaultValues = array();
57
58
    /**
59
     * Initializes the observer with the bunch processor instance.
60
     *
61
     * @param \TechDivision\Import\Product\Msi\Services\MsiBunchProcessorInterface $processor The bunch processor instance
62
     */
63
    public function __construct(MsiBunchProcessorInterface $processor)
64
    {
65
        $this->processor = $processor;
66
    }
67
68
    /**
69
     * Will be invoked by the observer visitor when a factory has been defined to create the observer instance.
70
     *
71
     * @param \TechDivision\Import\Subjects\SubjectInterface $subject The subject instance
72
     *
73
     * @return \TechDivision\Import\Observers\ObserverInterface The observer instance
74
     */
75
    public function createObserver(SubjectInterface $subject)
76
    {
77
78
        try {
79
            // load the available inventory sources
80
            $inventorySources = $this->getProcessor()->loadInventorySources();
81
        } catch (\Exception $e) {
82
            // prepare a log message
83
            $message = sprintf(
84
                '"%s"',
85
                $e->getMessage()
86
            );
87
            $subject->getSystemLogger()
88
                ->error($subject->appendExceptionSuffix($message));
89
            // set inventorySources as empty
90
            $inventorySources = [];
91
        }
92
93
        // initialize the template for the inventory source
94
        // column, used if the column is NOT part of the file
95
        foreach ($inventorySources as $inventorySource) {
96
            // initialize the default values
97
            $defaultValue = array(
98
                sprintf('%s=%s', ColumnKeys::SOURCE_CODE, $inventorySource[MemberNames::SOURCE_CODE]),
99
                sprintf('%s=1', ColumnKeys::STATUS),
100
                sprintf('%s=%%f', ColumnKeys::QUANTITY),
101
                sprintf('%s=%%s', ColumnKeys::RELATIVE),
102
            );
103
            // concatenate them with the multiple field delimiter and add them to the array with the templates
104
            $this->templateDefaultValues[] = implode($subject->getMultipleFieldDelimiter(), $defaultValue);
105
        }
106
107
        // return the instance itself
108
        return $this;
109
    }
110
111
    /**
112
     *  Return the bunch processor instance.
113
     *
114
     * @return \TechDivision\Import\Product\Msi\Services\MsiBunchProcessorInterface The bunch processor instance
115
     */
116
    protected function getProcessor()
117
    {
118
        return $this->processor;
119
    }
120
121
    /**
122
     * Process the observer's business logic.
123
     *
124
     * @return array The processed row
125
     */
126
    protected function process()
127
    {
128
        if (empty($this->templateDefaultValues)) {
129
            return;
130
        }
131
132
        // query whether or not, we've found a new SKU => means we've found a new product
133
        if ($this->hasBeenProcessed($this->getValue(ColumnKeys::SKU))) {
134
            return;
135
        }
136
137
        // initialize the array for the artefacts
138
        // and the default values for the MSI data
139
        $artefacts = array();
140
        $defaultValues = array();
141
142
        // initialize a default value in case the column with the MSI
143
        // data is NOT available, that looks like
144
        //   source_code=default,status=1,quantity=<value-from-column-qty-if-available>
145
        if ($this->hasHeader(ColumnKeys::INVENTORY_SOURCE_ITEMS) === false) {
146
            $defaultValues = $this->loadDefaultValues($this->getValue(ColumnKeys::QTY, 0), $this->getValue(ColumnKeys::QTY_RELATIVE, 0));
0 ignored issues
show
Bug introduced by
It seems like $this->getValue(TechDivi...ils\ColumnKeys::QTY, 0) can also be of type null; however, parameter $qty of TechDivision\Import\Prod...er::loadDefaultValues() does only seem to accept double, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

146
            $defaultValues = $this->loadDefaultValues(/** @scrutinizer ignore-type */ $this->getValue(ColumnKeys::QTY, 0), $this->getValue(ColumnKeys::QTY_RELATIVE, 0));
Loading history...
Bug introduced by
The constant TechDivision\Import\Prod...olumnKeys::QTY_RELATIVE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
147
        }
148
149
        // unserialize the inventory source item data from the column that looks like
150
        //   source_code=default,quantity=10.0,status=1|source_code=default,quantity=11.0,status=0
151
        $msiInventorySources = $this->getValue(ColumnKeys::INVENTORY_SOURCE_ITEMS, $defaultValues, function ($value) {
152
            return $this->explode($value, '|');
153
        });
154
155
        // iterate over the found inventory source items
156
        foreach ($msiInventorySources as $msiInventorySource) {
157
            // explode the key => values pairs
158
            $extractedColumns = $this->explode($msiInventorySource);
159
            // initialize the array with the column we want to export
160
            $columns = array(ColumnKeys::SKU => $this->getValue(ColumnKeys::SKU));
161
            // append the extracted values to the array
162
            foreach ($extractedColumns as $extractedColumn) {
163
                // extract key => value pair
164
                list ($key, $value) = $this->explode($extractedColumn, '=');
165
                // append the key => value pair
166
                $columns[$key] = $value;
167
            }
168
169
            // create a new artefact with the column information
170
            $artefacts[] = $this->newArtefact($columns, array());
171
        }
172
173
        // append the artefacts that has to be exported to the subject
174
        $this->addArtefacts($artefacts);
175
    }
176
177
    /**
178
     * Process the template and set the passed quantity for each
179
     * configured inventory source and return the default values.
180
     *
181
     * @param float  $qty      The quantity to initialize the template with
182
     * @param string $relative The relative flag to initialize the template with. 1 = relative everything else = absolute
183
     *
184
     * @return array The initialized array with the default values
185
     */
186
    protected function loadDefaultValues(float $qty, $relative = '') : array
187
    {
188
        return array_map(function ($value) use ($qty, $relative) {
189
            return sprintf($value, $qty, $relative);
190
        }, $this->templateDefaultValues);
191
    }
192
193
    /**
194
     * Creates and returns a new empty artefact entity.
195
     *
196
     * @param array $columns             The array with the column data
197
     * @param array $originalColumnNames The array with a mapping from the old to the new column names
198
     *
199
     * @return array The new artefact entity
200
     */
201
    protected function newArtefact(array $columns, array $originalColumnNames)
202
    {
203
        return $this->getSubject()->newArtefact($columns, $originalColumnNames);
204
    }
205
206
    /**
207
     * Add the passed product type artefacts to the product with the
208
     * last entity ID.
209
     *
210
     * @param array $artefacts The product type artefacts
211
     *
212
     * @return void
213
     * @uses \TechDivision\Import\Product\Media\Subjects\MediaSubject::getLastEntityId()
214
     */
215
    protected function addArtefacts(array $artefacts)
216
    {
217
        $this->getSubject()->addArtefacts(ProductSourceItemObserver::ARTEFACT_TYPE, $artefacts, false);
218
    }
219
}
220