Completed
Push — pac-348-global-attributes ( 6effca )
by
unknown
09:53
created

AttributeObserverTrait::deleteVarcharAttribute()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 1
c 0
b 0
f 0
nc 1
1
<?php
2
3
/**
4
 * TechDivision\Import\Observers\AttributeObserverTrait
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
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Observers;
22
23
use TechDivision\Import\Utils\LoggerKeys;
24
use TechDivision\Import\Utils\MemberNames;
25
use TechDivision\Import\Utils\EntityStatus;
26
use TechDivision\Import\Utils\StoreViewCodes;
27
use TechDivision\Import\Utils\BackendTypeKeys;
28
use TechDivision\Import\Utils\ConfigurationKeys;
29
30
/**
31
 * Observer that creates/updates the EAV attributes.
32
 *
33
 * @author    Tim Wagner <[email protected]>
34
 * @copyright 2016 TechDivision GmbH <[email protected]>
35
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
36
 * @link      https://github.com/techdivision/import
37
 * @link      http://www.techdivision.com
38
 */
39
trait AttributeObserverTrait
40
{
41
42
    /**
43
     * The ID of the attribute to create the values for.
44
     *
45
     * @var integer
46
     */
47
    protected $attributeId;
48
49
    /**
50
     * The attribute code of the attribute to create the values for.
51
     *
52
     * @var string
53
     */
54
    protected $attributeCode;
55
56
    /**
57
     * The backend type of the attribute to create the values for.
58
     *
59
     * @var string
60
     */
61
    protected $backendType;
62
63
    /**
64
     * The attribute value to process.
65
     *
66
     * @var mixed
67
     */
68
    protected $attributeValue;
69
70
    /**
71
     * The array with the column keys that has to be cleaned up when their values are empty.
72
     *
73
     * @var array
74
     * @deprecated Will be removed up from version 17.0.0
75
     */
76
    protected $cleanUpEmptyColumnKeys;
77
78
    /**
79
     * The entity's existing attribues.
80
     *
81
     * @var array
82
     */
83
    protected $attributes;
84
85
    /**
86
     * The attribute code that has to be processed.
87
     *
88
     * @return string The attribute code
89
     */
90
    public function getAttributeCode()
91
    {
92
        return $this->attributeCode;
93
    }
94
95
    /**
96
     * The attribute value that has to be processed.
97
     *
98
     * @return string The attribute value
99
     */
100
    public function getAttributeValue()
101
    {
102
        return $this->attributeValue;
103
    }
104
105
    /**
106
     * Remove all the empty values from the row and return the cleared row.
107
     *
108
     * @return array The cleared row
109
     * @todo Move initialization of $this->cleanUpEmptyColumnKeys to createObserver() method and implement ObserverFactoryInterface
110
     */
111
    protected function clearRow()
112
    {
113
114
        // initialize the array with the column keys that has to be cleaned-up
115
        $this->cleanUpEmptyColumnKeys = array();
0 ignored issues
show
Deprecated Code introduced by
The property TechDivision\Import\Obse...$cleanUpEmptyColumnKeys has been deprecated with message: Will be removed up from version 17.0.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
116
117
        // query whether or not column names that has to be cleaned up have been configured
118
        if ($this->getSubject()->getConfiguration()->hasParam(ConfigurationKeys::CLEAN_UP_EMPTY_COLUMNS)) {
0 ignored issues
show
Bug introduced by
It seems like getSubject() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
119
            // if yes, load the column names
120
            $cleanUpEmptyColumns = $this->getSubject()->getCleanUpColumns();
0 ignored issues
show
Bug introduced by
It seems like getSubject() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
121
122
            // translate the column names into column keys
123
            foreach ($cleanUpEmptyColumns as $cleanUpEmptyColumn) {
124
                if ($this->hasHeader($cleanUpEmptyColumn)) {
0 ignored issues
show
Bug introduced by
It seems like hasHeader() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
125
                    $this->cleanUpEmptyColumnKeys[] = $this->getHeader($cleanUpEmptyColumn);
0 ignored issues
show
Bug introduced by
It seems like getHeader() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
Deprecated Code introduced by
The property TechDivision\Import\Obse...$cleanUpEmptyColumnKeys has been deprecated with message: Will be removed up from version 17.0.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
126
                }
127
            }
128
        }
129
130
        // remove all the empty values from the row, expected the columns has to be cleaned-up
131
        foreach ($this->row as $key => $value) {
0 ignored issues
show
Bug introduced by
The property row does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
132
            // query whether or not the value is empty AND the column has NOT to be cleaned-up
133
            if (($value === null || $value === '') && in_array($key, $this->cleanUpEmptyColumnKeys) === false) {
0 ignored issues
show
Deprecated Code introduced by
The property TechDivision\Import\Obse...$cleanUpEmptyColumnKeys has been deprecated with message: Will be removed up from version 17.0.0

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
134
                unset($this->row[$key]);
135
            }
136
        }
137
138
        // finally return the clean row
139
        return $this->row;
140
    }
141
142
    /**
143
     * Returns the value(s) of the primary key column(s). As the primary key column can
144
     * also consist of two columns, the return value can be an array also.
145
     *
146
     * @return mixed The primary key value(s)
147
     */
148
    protected function getPrimaryKeyValue()
149
    {
150
        return $this->getValue($this->getPrimaryKeyColumnName());
0 ignored issues
show
Bug introduced by
It seems like getValue() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
151
    }
152
153
    /**
154
     * Process the observer's business logic.
155
     *
156
     * @return void
157
     */
158
    protected function process()
159
    {
160
161
        // initialize the store view code
162
        $this->prepareStoreViewCode();
0 ignored issues
show
Bug introduced by
It seems like prepareStoreViewCode() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
163
164
        // load the store ID, use the admin store if NO store view code has been set
165
        $storeId = $this->getRowStoreId(StoreViewCodes::ADMIN);
0 ignored issues
show
Bug introduced by
It seems like getRowStoreId() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
166
167
        // load the entity's existing attributes
168
        $this->getAttributesByPrimaryKeyAndStoreId($this->getPrimaryKey(), $storeId);
169
170
        // load the store view - if no store view has been set, we assume the admin
171
        // store view, which will contain the default (fallback) attribute values
172
        $storeViewCode = $this->getSubject()->getStoreViewCode(StoreViewCodes::ADMIN);
0 ignored issues
show
Bug introduced by
It seems like getSubject() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
173
174
        // query whether or not the row has already been processed
175
        if ($this->storeViewHasBeenProcessed($pk = $this->getPrimaryKeyValue(), $storeViewCode)) {
176
            // log a message
177
            $this->getSystemLogger()->warning(
178
                $this->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
It seems like appendExceptionSuffix() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
179
                    sprintf(
180
                        'Attributes for "%s" "%s" + store view code "%s" has already been processed',
181
                        $this->getPrimaryKeyColumnName(),
182
                        $pk,
183
                        $storeViewCode
184
                    )
185
                )
186
            );
187
188
            // return immediately
189
            return;
190
        }
191
192
        // load the attributes by the found attribute set and the backend types
193
        $attributes = $this->getAttributes();
194
        $backendTypes = $this->getBackendTypes();
195
196
        // load the header keys
197
        $headers = array_flip($this->getHeaders());
0 ignored issues
show
Bug introduced by
It seems like getHeaders() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
198
199
        // remove all the empty values from the row
200
        $row = $this->clearRow();
201
202
        // iterate over the attributes and append them to the row
203
        foreach ($row as $key => $attributeValue) {
204
            // query whether or not attribute with the found code exists
205
            if (!isset($attributes[$attributeCode = $headers[$key]])) {
206
                // log a message in debug mode
207
                if ($this->isDebugMode()) {
0 ignored issues
show
Bug introduced by
It seems like isDebugMode() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
208
                    $this->getSystemLogger()->debug(
209
                        $this->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
It seems like appendExceptionSuffix() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
210
                            sprintf(
211
                                'Can\'t find attribute with attribute code "%s"',
212
                                $attributeCode
213
                            )
214
                        )
215
                    );
216
                }
217
218
                // stop processing
219
                continue;
220
            } else {
221
                // log a message in debug mode
222
                if ($this->isDebugMode()) {
0 ignored issues
show
Bug introduced by
It seems like isDebugMode() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
223
                // log a message in debug mode
224
                    $this->getSystemLogger()->debug(
225
                        $this->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
It seems like appendExceptionSuffix() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
226
                            sprintf(
227
                                'Found attribute with attribute code "%s"',
228
                                $attributeCode
229
                            )
230
                        )
231
                    );
232
                }
233
            }
234
235
            // if yes, load the attribute by its code
236
            $attribute = $attributes[$attributeCode];
237
238
            // load the backend type => to find the apropriate entity
239
            $backendType = $attribute[MemberNames::BACKEND_TYPE];
240
            if ($backendType === null) {
241
                // log a message in debug mode
242
                $this->getSystemLogger()->warning(
243
                    $this->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
It seems like appendExceptionSuffix() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
244
                        sprintf(
245
                            'Found EMTPY backend type for attribute "%s"',
246
                            $attributeCode
247
                        )
248
                    )
249
                );
250
                // stop processing
251
                continue;
252
            }
253
254
            // do nothing on static backend type
255
            if ($backendType === BackendTypeKeys::BACKEND_TYPE_STATIC) {
256
                continue;
257
            }
258
259
            // do nothing in non-default stores with global attributes
260
            if ($storeId !== 0 && $attribute[MemberNames::IS_GLOBAL] == 1) {
261
                continue;
262
            }
263
264
            // query whether or not we've found a supported backend type
265
            if (isset($backendTypes[$backendType])) {
266
                // initialize attribute ID/code and backend type
267
                $this->attributeId = $attribute[MemberNames::ATTRIBUTE_ID];
268
                $this->attributeCode = $attributeCode;
269
                $this->backendType = $backendType;
270
271
                // initialize the persist method for the found backend type
272
                list ($persistMethod, , $deleteMethod) = $backendTypes[$backendType];
273
274
                // set the attribute value
275
                $this->attributeValue = $attributeValue;
276
277
                // prepare the attribute vale and query whether or not it has to be persisted
278
                if ($this->hasChanges($value = $this->initializeAttribute($this->prepareAttributes()))) {
0 ignored issues
show
Bug introduced by
It seems like $this->prepareAttributes() targeting TechDivision\Import\Obse...it::prepareAttributes() can also be of type null; however, TechDivision\Import\Obse...::initializeAttribute() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
279
                    // query whether or not the entity's value has to be persisted or deleted. if the value is
280
                    // an empty string and the status is UPDATE, then the value exists and has to be deleted
281
                    // We need to user $attributeValue instead of $value[MemberNames::VALUE] in cases where
282
                    // value was casted by attribute type. E.g. special_price = 0 if value is empty string in CSV
283
                    if ($attributeValue === '' && $value[EntityStatus::MEMBER_NAME] === EntityStatus::STATUS_UPDATE) {
284
                        $this->$deleteMethod(array(MemberNames::VALUE_ID => $value[MemberNames::VALUE_ID]));
285
                    } elseif ($attributeValue !== '' && $value[MemberNames::VALUE] !== null) {
286
                        $this->$persistMethod($value);
287
                    } else {
288
                        // log a debug message, because this should never happen
289
                        $this->getSubject()->getSystemLogger()->debug(sprintf('Found empty value for attribute "%s"', $attributeCode));
0 ignored issues
show
Bug introduced by
It seems like getSubject() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
290
                    }
291
                } else {
292
                    $this->getSubject()->getSystemLogger()->debug(sprintf('Skip to persist value for attribute "%s"', $attributeCode));
0 ignored issues
show
Bug introduced by
It seems like getSubject() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
293
                }
294
295
                // continue with the next value
296
                continue;
297
            }
298
299
            // log the debug message
300
            $this->getSystemLogger()->debug(
301
                $this->getSubject()->appendExceptionSuffix(
0 ignored issues
show
Bug introduced by
It seems like getSubject() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
302
                    sprintf(
303
                        'Found invalid backend type %s for attribute "%s"',
304
                        $backendType,
305
                        $attributeCode
306
                    )
307
                )
308
            );
309
        }
310
    }
311
312
    /**
313
     * Prepare the attributes of the entity that has to be persisted.
314
     *
315
     * @return array|null The prepared attributes
316
     */
317
    protected function prepareAttributes()
318
    {
319
320
        // laod the callbacks for the actual attribute code
321
        $callbacks = $this->getCallbacksByType($this->attributeCode);
322
323
        // invoke the pre-cast callbacks
324
        foreach ($callbacks as $callback) {
325
            $this->attributeValue = $callback->handle($this);
326
        }
327
328
        // load the ID of the product that has been created recently
329
        $lastEntityId = $this->getPrimaryKey();
330
331
        // load the store ID, use the admin store if NO store view code has been set
332
        $storeId = $this->getRowStoreId(StoreViewCodes::ADMIN);
0 ignored issues
show
Bug introduced by
It seems like getRowStoreId() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
333
334
        // cast the value based on the backend type
335
        $castedValue = $this->castValueByBackendType($this->backendType, $this->attributeValue);
0 ignored issues
show
Bug introduced by
It seems like castValueByBackendType() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
336
337
        // prepare the attribute values
338
        return $this->initializeEntity(
0 ignored issues
show
Bug introduced by
It seems like initializeEntity() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
339
            array(
340
               $this->getPrimaryKeyMemberName() => $lastEntityId,
341
                MemberNames::ATTRIBUTE_ID       => $this->attributeId,
342
                MemberNames::STORE_ID           => $storeId,
343
                MemberNames::VALUE              => $castedValue
344
            )
345
        );
346
    }
347
348
    /**
349
     * Initialize the category product with the passed attributes and returns an instance.
350
     *
351
     * @param array $attr The category product attributes
352
     *
353
     * @return array The initialized category product
354
     */
355
    protected function initializeAttribute(array $attr)
356
    {
357
        return $attr;
358
    }
359
360
    /**
361
     * Return's the array with callbacks for the passed type.
362
     *
363
     * @param string $type The type of the callbacks to return
364
     *
365
     * @return array The callbacks
366
     */
367
    protected function getCallbacksByType($type)
368
    {
369
        return $this->getSubject()->getCallbacksByType($type);
0 ignored issues
show
Bug introduced by
It seems like getSubject() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
370
    }
371
372
    /**
373
     * Return's mapping for the supported backend types (for the product entity) => persist methods.
374
     *
375
     * @return array The mapping for the supported backend types
376
     */
377
    protected function getBackendTypes()
378
    {
379
        return $this->getSubject()->getBackendTypes();
0 ignored issues
show
Bug introduced by
It seems like getSubject() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
380
    }
381
382
    /**
383
     * Return's the attributes for the attribute set of the product that has to be created.
384
     *
385
     * @return array The attributes
386
     * @throws \Exception
387
     */
388
    protected function getAttributes()
389
    {
390
        return $this->getSubject()->getAttributes();
0 ignored issues
show
Bug introduced by
It seems like getSubject() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
391
    }
392
393
    /**
394
     * Intializes the existing attributes for the entity with the passed primary key.
395
     *
396
     * @param string  $pk      The primary key of the entity to load the attributes for
397
     * @param integer $storeId The ID of the store view to load the attributes for
398
     *
399
     * @return array The entity attributes
400
     */
401
    abstract protected function getAttributesByPrimaryKeyAndStoreId($pk, $storeId);
402
403
    /**
404
     * Return's the logger with the passed name, by default the system logger.
405
     *
406
     * @param string $name The name of the requested system logger
407
     *
408
     * @return \Psr\Log\LoggerInterface The logger instance
409
     * @throws \Exception Is thrown, if the requested logger is NOT available
410
     */
411
    abstract protected function getSystemLogger($name = LoggerKeys::SYSTEM);
412
413
    /**
414
     * Return's the PK to create the product => attribute relation.
415
     *
416
     * @return integer The PK to create the relation with
417
     */
418
    abstract protected function getPrimaryKey();
419
420
    /**
421
     * Return's the PK column name to create the product => attribute relation.
422
     *
423
     * @return string The PK column name
424
     */
425
    abstract protected function getPrimaryKeyMemberName();
426
427
    /**
428
     * Return's the column name that contains the primary key.
429
     *
430
     * @return string the column name that contains the primary key
431
     */
432
    abstract protected function getPrimaryKeyColumnName();
433
434
    /**
435
     * Queries whether or not the passed PK and store view code has already been processed.
436
     *
437
     * @param string $pk            The PK to check been processed
438
     * @param string $storeViewCode The store view code to check been processed
439
     *
440
     * @return boolean TRUE if the PK and store view code has been processed, else FALSE
441
     */
442
    abstract protected function storeViewHasBeenProcessed($pk, $storeViewCode);
443
444
    /**
445
     * Persist's the passed varchar attribute.
446
     *
447
     * @param array $attribute The attribute to persist
448
     *
449
     * @return void
450
     */
451
    abstract protected function persistVarcharAttribute($attribute);
452
453
    /**
454
     * Persist's the passed integer attribute.
455
     *
456
     * @param array $attribute The attribute to persist
457
     *
458
     * @return void
459
     */
460
    abstract protected function persistIntAttribute($attribute);
461
462
    /**
463
     * Persist's the passed decimal attribute.
464
     *
465
     * @param array $attribute The attribute to persist
466
     *
467
     * @return void
468
     */
469
    abstract protected function persistDecimalAttribute($attribute);
470
471
    /**
472
     * Persist's the passed datetime attribute.
473
     *
474
     * @param array $attribute The attribute to persist
475
     *
476
     * @return void
477
     */
478
    abstract protected function persistDatetimeAttribute($attribute);
479
480
    /**
481
     * Persist's the passed text attribute.
482
     *
483
     * @param array $attribute The attribute to persist
484
     *
485
     * @return void
486
     */
487
    abstract protected function persistTextAttribute($attribute);
488
489
    /**
490
     * Delete's the datetime attribute with the passed value ID.
491
     *
492
     * @param array       $row  The attributes of the entity to delete
493
     * @param string|null $name The name of the prepared statement that has to be executed
494
     *
495
     * @return void
496
     */
497
    abstract protected function deleteDatetimeAttribute(array $row, $name = null);
498
499
    /**
500
     * Delete's the decimal attribute with the passed value ID.
501
     *
502
     * @param array       $row  The attributes of the entity to delete
503
     * @param string|null $name The name of the prepared statement that has to be executed
504
     *
505
     * @return void
506
     */
507
    abstract protected function deleteDecimalAttribute(array $row, $name = null);
508
509
    /**
510
     * Delete's the integer attribute with the passed value ID.
511
     *
512
     * @param array       $row  The attributes of the entity to delete
513
     * @param string|null $name The name of the prepared statement that has to be executed
514
     *
515
     * @return void
516
     */
517
    abstract protected function deleteIntAttribute(array $row, $name = null);
518
519
    /**
520
     * Delete's the text attribute with the passed value ID.
521
     *
522
     * @param array       $row  The attributes of the entity to delete
523
     * @param string|null $name The name of the prepared statement that has to be executed
524
     *
525
     * @return void
526
     */
527
    abstract protected function deleteTextAttribute(array $row, $name = null);
528
529
    /**
530
     * Delete's the varchar attribute with the passed value ID.
531
     *
532
     * @param array       $row  The attributes of the entity to delete
533
     * @param string|null $name The name of the prepared statement that has to be executed
534
     *
535
     * @return void
536
     */
537
    abstract protected function deleteVarcharAttribute(array $row, $name = null);
538
539
    /**
540
     * Query whether or not the entity has to be processed.
541
     *
542
     * @param array $entity The entity to query for
543
     *
544
     * @return boolean TRUE if the entity has to be processed, else FALSE
545
     */
546
    abstract protected function hasChanges(array $entity);
547
}
548