Completed
Pull Request — master (#33)
by Tim
05:20
created

ProductAttributeObserver::getAttributes()   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 4
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\Observers\ProductAttributeObserver
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\Observers;
22
23
use TechDivision\Import\Utils\StoreViewCodes;
24
use TechDivision\Import\Product\Utils\ColumnKeys;
25
use TechDivision\Import\Product\Utils\MemberNames;
26
use TechDivision\Import\Product\Observers\AbstractProductImportObserver;
27
28
/**
29
 * Observer that creates/updates the product's attributes.
30
 *
31
 * @author    Tim Wagner <[email protected]>
32
 * @copyright 2016 TechDivision GmbH <[email protected]>
33
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
34
 * @link      https://github.com/techdivision/import-product
35
 * @link      http://www.techdivision.com
36
 */
37
class ProductAttributeObserver extends AbstractProductImportObserver
38
{
39
40
    /**
41
     * The ID of the attribute to create the values for.
42
     *
43
     * @var integer
44
     */
45
    protected $attributeId;
46
47
    /**
48
     * The attribute code of the attribute to create the values for.
49
     *
50
     * @var string
51
     */
52
    protected $attributeCode;
53
54
    /**
55
     * The backend type of the attribute to create the values for.
56
     *
57
     * @var string
58
     */
59
    protected $backendType;
60
61
    /**
62
     * The attribute value to process.
63
     *
64
     * @var mixed
65
     */
66
    protected $attributeValue;
67
68
    /**
69
     * Process the observer's business logic.
70
     *
71
     * @return void
72
     */
73
    protected function process()
74
    {
75
76
        // initialize the store view code
77
        $this->prepareStoreViewCode();
78
79
        // load the attributes by the found attribute set and the backend types
80
        $attributes = $this->getAttributes();
81
        $backendTypes = $this->getBackendTypes();
82
83
        // remove all the empty values from the row
84
        $row = array_filter(
85
            $this->row,
86
            function ($value, $key) { return ($value !== null && $value !== ''); },
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
Opening brace must be the last content on the line
Loading history...
87
            ARRAY_FILTER_USE_BOTH
88
        );
89
90
        // load the header keys
91
        $headers = array_flip($this->getHeaders());
92
93
        // iterate over the attributes and append them to the row
94
        foreach ($row as $key => $attributeValue) {
95
            // query whether or not we've a attribute value found
96
            if ($attributeValue === null) {
97
                continue;
98
            }
99
100
            // query whether or not attribute with the found code exists
101
            if (!isset($attributes[$attributeCode = $headers[$key]])) {
102
                continue;
103
            }
104
105
            // if yes, load the attribute by its code
106
            $attribute = $attributes[$attributeCode];
107
108
            // load the backend type => to find the apropriate entity
109
            $backendType = $attribute[MemberNames::BACKEND_TYPE];
110
            if ($backendType == null) {
111
                $this->getSystemLogger()->warning(sprintf('Found EMTPY backend type for attribute %s', $attributeCode));
112
                continue;
113
            }
114
115
            // do nothing on static backend type
116
            if ($backendType === 'static') {
117
                continue;
118
            }
119
120
            // query whether or not we've found a supported backend type
121
            if (isset($backendTypes[$backendType])) {
122
                // initialize attribute ID/code and backend type
123
                $this->attributeId = $attribute[MemberNames::ATTRIBUTE_ID];
124
                $this->attributeCode = $attributeCode;
125
                $this->backendType = $backendType;
126
127
                // initialize the persist method for the found backend type
128
                list ($persistMethod, ) = $backendTypes[$backendType];
129
130
                // set the attribute value
131
                $this->attributeValue = $attributeValue;
132
133
                // load the prepared values
134
                $entity = $this->initializeAttribute($this->prepareAttributes());
135
136
                // persist the attribute and continue
137
                $this->$persistMethod($entity);
138
                continue;
139
            }
140
141
            // log the debug message
142
            $this->getSystemLogger()->debug(
143
                sprintf(
144
                    'Found invalid backend type %s for attribute %s in file %s on line %s',
145
                    $this->backendType,
146
                    $this->attributeCode,
147
                    $this->getFilename(),
148
                    $this->getLineNumber()
149
                )
150
            );
151
        }
152
    }
153
154
    /**
155
     * Prepare the attributes of the entity that has to be persisted.
156
     *
157
     * @return array The prepared attributes
158
     */
159
    protected function prepareAttributes()
160
    {
161
162
        // laod the callbacks for the actual attribute code
163
        $callbacks = $this->getCallbacksByType($this->attributeCode);
164
165
        // invoke the pre-cast callbacks
166
        foreach ($callbacks as $callback) {
167
            $this->attributeValue = $callback->handle($this->attributeValue);
168
        }
169
170
        // load the ID of the product that has been created recently
171
        $lastEntityId = $this->getPrimaryKey();
172
173
        // load the store ID
174
        $storeId = $this->getRowStoreId(StoreViewCodes::ADMIN);
175
176
        // cast the value based on the backend type
177
        $castedValue = $this->castValueByBackendType($this->backendType, $this->attributeValue);
178
179
        // prepare the attribute values
180
        return $this->initializeEntity(
181
            array(
182
                MemberNames::ENTITY_ID    => $lastEntityId,
183
                MemberNames::ATTRIBUTE_ID => $this->attributeId,
184
                MemberNames::STORE_ID     => $storeId,
185
                MemberNames::VALUE        => $castedValue
186
            )
187
        );
188
    }
189
190
    /**
191
     * Initialize the category product with the passed attributes and returns an instance.
192
     *
193
     * @param array $attr The category product attributes
194
     *
195
     * @return array The initialized category product
196
     */
197
    protected function initializeAttribute(array $attr)
198
    {
199
        return $attr;
200
    }
201
202
    /**
203
     * Return's the PK to create the product => attribute relation.
204
     *
205
     * @return integer The PK to create the relation with
206
     */
207
    protected function getPrimaryKey()
208
    {
209
        return $this->getLastEntityId();
210
    }
211
212
    /**
213
     * Map the passed attribute code, if a header mapping exists and return the
214
     * mapped mapping.
215
     *
216
     * @param string $attributeCode The attribute code to map
217
     *
218
     * @return string The mapped attribute code, or the original one
219
     */
220
    protected function mapAttributeCodeByHeaderMapping($attributeCode)
221
    {
222
        return $this->getSubject()->mapAttributeCodeByHeaderMapping($attributeCode);
223
    }
224
225
    /**
226
     * Return's the array with callbacks for the passed type.
227
     *
228
     * @param string $type The type of the callbacks to return
229
     *
230
     * @return array The callbacks
231
     */
232
    protected function getCallbacksByType($type)
233
    {
234
        return $this->getSubject()->getCallbacksByType($type);
235
    }
236
237
    /**
238
     * Return's mapping for the supported backend types (for the product entity) => persist methods.
239
     *
240
     * @return array The mapping for the supported backend types
241
     */
242
    protected function getBackendTypes()
243
    {
244
        return $this->getSubject()->getBackendTypes();
245
    }
246
247
    /**
248
     * Return's the attributes for the attribute set of the product that has to be created.
249
     *
250
     * @return array The attributes
251
     * @throws \Exception
252
     */
253
    protected function getAttributes()
254
    {
255
        return $this->getSubject()->getAttributes();
256
    }
257
258
    /**
259
     * Return's the store ID of the actual row, or of the default store
260
     * if no store view code is set in the CSV file.
261
     *
262
     * @param string|null $default The default store view code to use, if no store view code is set in the CSV file
263
     *
264
     * @return integer The ID of the actual store
265
     * @throws \Exception Is thrown, if the store with the actual code is not available
266
     */
267
    protected function getRowStoreId($default = null)
268
    {
269
        return $this->getSubject()->getRowStoreId($default);
270
    }
271
272
    /**
273
     * Persist's the passed product varchar attribute.
274
     *
275
     * @param array $attribute The attribute to persist
276
     *
277
     * @return void
278
     */
279
    protected function persistProductVarcharAttribute($attribute)
280
    {
281
        $this->getSubject()->persistProductVarcharAttribute($attribute);
282
    }
283
284
    /**
285
     * Persist's the passed product integer attribute.
286
     *
287
     * @param array $attribute The attribute to persist
288
     *
289
     * @return void
290
     */
291
    protected function persistProductIntAttribute($attribute)
292
    {
293
        $this->getSubject()->persistProductIntAttribute($attribute);
294
    }
295
296
    /**
297
     * Persist's the passed product decimal attribute.
298
     *
299
     * @param array $attribute The attribute to persist
300
     *
301
     * @return void
302
     */
303
    protected function persistProductDecimalAttribute($attribute)
304
    {
305
        $this->getSubject()->persistProductDecimalAttribute($attribute);
306
    }
307
308
    /**
309
     * Persist's the passed product datetime attribute.
310
     *
311
     * @param array $attribute The attribute to persist
312
     *
313
     * @return void
314
     */
315
    protected function persistProductDatetimeAttribute($attribute)
316
    {
317
        $this->getSubject()->persistProductDatetimeAttribute($attribute);
318
    }
319
320
    /**
321
     * Persist's the passed product text attribute.
322
     *
323
     * @param array $attribute The attribute to persist
324
     *
325
     * @return void
326
     */
327
    protected function persistProductTextAttribute($attribute)
328
    {
329
        $this->getSubject()->persistProductTextAttribute($attribute);
330
    }
331
}
332