Completed
Pull Request — 16.x (#167)
by Jitendra
05:11
created

AttributeObserverTrait   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 505
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 87.5%

Importance

Changes 0
Metric Value
wmc 32
lcom 1
cbo 1
dl 0
loc 505
ccs 84
cts 96
cp 0.875
rs 9.84
c 0
b 0
f 0

27 Methods

Rating   Name   Duplication   Size   Complexity  
A getAttributeCode() 0 4 1
A getAttributeValue() 0 4 1
B clearRow() 0 33 9
A getPrimaryKeyValue() 0 4 1
A prepareAttributes() 0 30 2
A initializeAttribute() 0 4 1
A getCallbacksByType() 0 4 1
A getBackendTypes() 0 4 1
A getAttributes() 0 4 1
getAttributesByPrimaryKeyAndStoreId() 0 1 ?
getSystemLogger() 0 1 ?
getPrimaryKey() 0 1 ?
getPrimaryKeyMemberName() 0 1 ?
getPrimaryKeyColumnName() 0 1 ?
storeViewHasBeenProcessed() 0 1 ?
persistVarcharAttribute() 0 1 ?
persistIntAttribute() 0 1 ?
persistDecimalAttribute() 0 1 ?
persistDatetimeAttribute() 0 1 ?
persistTextAttribute() 0 1 ?
deleteDatetimeAttribute() 0 1 ?
deleteDecimalAttribute() 0 1 ?
deleteIntAttribute() 0 1 ?
deleteTextAttribute() 0 1 ?
deleteVarcharAttribute() 0 1 ?
hasChanges() 0 1 ?
C process() 0 148 14
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
     */
75
    protected $cleanUpEmptyColumnKeys;
76
77
    /**
78
     * The entity's existing attribues.
79
     *
80
     * @var array
81
     */
82
    protected $attributes;
83
84
    /**
85
     * The attribute code that has to be processed.
86
     *
87
     * @return string The attribute code
88
     */
89 1
    public function getAttributeCode()
90
    {
91 1
        return $this->attributeCode;
92
    }
93
94
    /**
95
     * The attribute value that has to be processed.
96
     *
97
     * @return string The attribute value
98
     */
99 1
    public function getAttributeValue()
100
    {
101 1
        return $this->attributeValue;
102
    }
103
104
    /**
105
     * Remove all the empty values from the row and return the cleared row.
106
     *
107
     * @return array The cleared row
108
     */
109 7
    protected function clearRow()
110
    {
111
112
        // query whether or not the column keys has been initialized
113 7
        if ($this->cleanUpEmptyColumnKeys === null) {
114
            // initialize the array with the column keys that has to be cleaned-up
115 7
            $this->cleanUpEmptyColumnKeys = array();
116
117
            // query whether or not column names that has to be cleaned up have been configured
118 7
            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...
126
                    }
127
                }
128
            }
129
        }
130
131
        // remove all the empty values from the row, expected the columns has to be cleaned-up
132 7
        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...
133
            // query whether or not the value is empty AND the column has NOT to be cleaned-up
134 7
            if (($value === null || $value === '') && in_array($key, $this->cleanUpEmptyColumnKeys) === false) {
135 1
                unset($this->row[$key]);
136
            }
137
        }
138
139
        // finally return the clean row
140 7
        return $this->row;
141
    }
142
143
    /**
144
     * Returns the value(s) of the primary key column(s). As the primary key column can
145
     * also consist of two columns, the return value can be an array also.
146
     *
147
     * @return mixed The primary key value(s)
148
     */
149 7
    protected function getPrimaryKeyValue()
150
    {
151 7
        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...
152
    }
153
154
    /**
155
     * Process the observer's business logic.
156
     *
157
     * @return void
158
     */
159 7
    protected function process()
160
    {
161
162
        // initialize the store view code
163 7
        $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...
164
165
        // load the store ID, use the admin store if NO store view code has been set
166 7
        $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...
167
168
        // load the entity's existing attributes
169 7
        $this->getAttributesByPrimaryKeyAndStoreId($this->getPrimaryKey(), $storeId);
170
171
        // load the store view - if no store view has been set, we assume the admin
172
        // store view, which will contain the default (fallback) attribute values
173 7
        $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...
174
175
        // query whether or not the row has already been processed
176 7
        if ($this->storeViewHasBeenProcessed($pk = $this->getPrimaryKeyValue(), $storeViewCode)) {
177
            // log a message
178
            $this->getSystemLogger()->warning(
179
                $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...
180
                    sprintf(
181
                        'Attributes for %s "%s" + store view code "%s" has already been processed',
182
                        $this->getPrimaryKeyColumnName(),
183
                        $pk,
184
                        $storeViewCode
185
                    )
186
                )
187
            );
188
189
            // return immediately
190
            return;
191
        }
192
193
        // load the attributes by the found attribute set and the backend types
194 7
        $attributes = $this->getAttributes();
195 7
        $backendTypes = $this->getBackendTypes();
196
197
        // load the header keys
198 7
        $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...
199
200
        // remove all the empty values from the row
201 7
        $row = $this->clearRow();
202
203
        // iterate over the attributes and append them to the row
204 7
        foreach ($row as $key => $attributeValue) {
205
            // query whether or not attribute with the found code exists
206 6
            if (!isset($attributes[$attributeCode = $headers[$key]])) {
207
                // log a message in debug mode
208 1
                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...
209 1
                    $this->getSystemLogger()->debug(
210 1
                        $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...
211 1
                            sprintf(
212 1
                                'Can\'t find attribute with attribute code %s',
213
                                $attributeCode
214
                            )
215
                        )
216
                    );
217
                }
218
219
                // stop processing
220 1
                continue;
221
            } else {
222
                // log a message in debug mode
223 5
                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...
224
                // log a message in debug mode
225 2
                    $this->getSystemLogger()->debug(
226 2
                        $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...
227 2
                            sprintf(
228 2
                                'Found attribute with attribute code %s',
229
                                $attributeCode
230
                            )
231
                        )
232
                    );
233
                }
234
            }
235
236
            // if yes, load the attribute by its code
237 5
            $attribute = $attributes[$attributeCode];
238
239
            // load the backend type => to find the apropriate entity
240 5
            $backendType = $attribute[MemberNames::BACKEND_TYPE];
241 5
            if ($backendType === null) {
242
                // log a message in debug mode
243 1
                $this->getSystemLogger()->warning(
244 1
                    $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...
245 1
                        sprintf(
246 1
                            'Found EMTPY backend type for attribute %s',
247
                            $attributeCode
248
                        )
249
                    )
250
                );
251
                // stop processing
252 1
                continue;
253
            }
254
255
            // do nothing on static backend type
256 4
            if ($backendType === BackendTypeKeys::BACKEND_TYPE_STATIC) {
257 1
                continue;
258
            }
259
260
            // query whether or not we've found a supported backend type
261 3
            if (isset($backendTypes[$backendType])) {
262
                // initialize attribute ID/code and backend type
263 2
                $this->attributeId = $attribute[MemberNames::ATTRIBUTE_ID];
264 2
                $this->attributeCode = $attributeCode;
265 2
                $this->backendType = $backendType;
266
267
                // initialize the persist method for the found backend type
268 2
                list ($persistMethod, , $deleteMethod) = $backendTypes[$backendType];
269
270
                // set the attribute value
271 2
                $this->attributeValue = $attributeValue;
272
273
                // prepare the attribute vale and query whether or not it has to be persisted
274 2
                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...
275
                    // query whether or not the entity's value has to be persisted or deleted. if the value is
276
                    // an empty string and the status is UPDATE, then the value exists and has to be deleted
277
                    // We need to user $attributeValue instead of $value[MemberNames::VALUE] in cases where
278
                    // value was casted by attribute type. E.g. special_price = 0 if value is empty string in CSV
279 2
                    if ($attributeValue === '' && $value[EntityStatus::MEMBER_NAME] === EntityStatus::STATUS_UPDATE) {
280
                        $this->$deleteMethod(array(MemberNames::VALUE_ID => $value[MemberNames::VALUE_ID]));
281 2
                    } elseif ($attributeValue !== '' && $value[MemberNames::VALUE] !== null) {
282 1
                        $this->$persistMethod($value);
283
                    } else {
284
                        // log a debug message, because this should never happen
285 2
                        $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...
286
                    }
287
                } else {
288
                    $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...
289
                }
290
291
                // continue with the next value
292 2
                continue;
293
            }
294
295
            // log the debug message
296 1
            $this->getSystemLogger()->debug(
297 1
                $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...
298 1
                    sprintf(
299 1
                        'Found invalid backend type %s for attribute %s',
300
                        $backendType,
301
                        $attributeCode
302
                    )
303
                )
304
            );
305
        }
306 7
    }
307
308
    /**
309
     * Prepare the attributes of the entity that has to be persisted.
310
     *
311
     * @return array|null The prepared attributes
312
     */
313 2
    protected function prepareAttributes()
314
    {
315
316
        // laod the callbacks for the actual attribute code
317 2
        $callbacks = $this->getCallbacksByType($this->attributeCode);
318
319
        // invoke the pre-cast callbacks
320 2
        foreach ($callbacks as $callback) {
321 1
            $this->attributeValue = $callback->handle($this);
322
        }
323
324
        // load the ID of the product that has been created recently
325 2
        $lastEntityId = $this->getPrimaryKey();
326
327
        // load the store ID, use the admin store if NO store view code has been set
328 2
        $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...
329
330
        // cast the value based on the backend type
331 2
        $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...
332
333
        // prepare the attribute values
334 2
        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...
335
            array(
336 2
               $this->getPrimaryKeyMemberName() => $lastEntityId,
337 2
                MemberNames::ATTRIBUTE_ID       => $this->attributeId,
338 2
                MemberNames::STORE_ID           => $storeId,
339 2
                MemberNames::VALUE              => $castedValue
340
            )
341
        );
342
    }
343
344
    /**
345
     * Initialize the category product with the passed attributes and returns an instance.
346
     *
347
     * @param array $attr The category product attributes
348
     *
349
     * @return array The initialized category product
350
     */
351 2
    protected function initializeAttribute(array $attr)
352
    {
353 2
        return $attr;
354
    }
355
356
    /**
357
     * Return's the array with callbacks for the passed type.
358
     *
359
     * @param string $type The type of the callbacks to return
360
     *
361
     * @return array The callbacks
362
     */
363 2
    protected function getCallbacksByType($type)
364
    {
365 2
        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...
366
    }
367
368
    /**
369
     * Return's mapping for the supported backend types (for the product entity) => persist methods.
370
     *
371
     * @return array The mapping for the supported backend types
372
     */
373 7
    protected function getBackendTypes()
374
    {
375 7
        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...
376
    }
377
378
    /**
379
     * Return's the attributes for the attribute set of the product that has to be created.
380
     *
381
     * @return array The attributes
382
     * @throws \Exception
383
     */
384 7
    protected function getAttributes()
385
    {
386 7
        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...
387
    }
388
389
    /**
390
     * Intializes the existing attributes for the entity with the passed primary key.
391
     *
392
     * @param string  $pk      The primary key of the entity to load the attributes for
393
     * @param integer $storeId The ID of the store view to load the attributes for
394
     *
395
     * @return array The entity attributes
396
     */
397
    abstract protected function getAttributesByPrimaryKeyAndStoreId($pk, $storeId);
398
399
    /**
400
     * Return's the logger with the passed name, by default the system logger.
401
     *
402
     * @param string $name The name of the requested system logger
403
     *
404
     * @return \Psr\Log\LoggerInterface The logger instance
405
     * @throws \Exception Is thrown, if the requested logger is NOT available
406
     */
407
    abstract protected function getSystemLogger($name = LoggerKeys::SYSTEM);
408
409
    /**
410
     * Return's the PK to create the product => attribute relation.
411
     *
412
     * @return integer The PK to create the relation with
413
     */
414
    abstract protected function getPrimaryKey();
415
416
    /**
417
     * Return's the PK column name to create the product => attribute relation.
418
     *
419
     * @return string The PK column name
420
     */
421
    abstract protected function getPrimaryKeyMemberName();
422
423
    /**
424
     * Return's the column name that contains the primary key.
425
     *
426
     * @return string the column name that contains the primary key
427
     */
428
    abstract protected function getPrimaryKeyColumnName();
429
430
    /**
431
     * Queries whether or not the passed PK and store view code has already been processed.
432
     *
433
     * @param string $pk            The PK to check been processed
434
     * @param string $storeViewCode The store view code to check been processed
435
     *
436
     * @return boolean TRUE if the PK and store view code has been processed, else FALSE
437
     */
438
    abstract protected function storeViewHasBeenProcessed($pk, $storeViewCode);
439
440
    /**
441
     * Persist's the passed varchar attribute.
442
     *
443
     * @param array $attribute The attribute to persist
444
     *
445
     * @return void
446
     */
447
    abstract protected function persistVarcharAttribute($attribute);
448
449
    /**
450
     * Persist's the passed integer attribute.
451
     *
452
     * @param array $attribute The attribute to persist
453
     *
454
     * @return void
455
     */
456
    abstract protected function persistIntAttribute($attribute);
457
458
    /**
459
     * Persist's the passed decimal attribute.
460
     *
461
     * @param array $attribute The attribute to persist
462
     *
463
     * @return void
464
     */
465
    abstract protected function persistDecimalAttribute($attribute);
466
467
    /**
468
     * Persist's the passed datetime attribute.
469
     *
470
     * @param array $attribute The attribute to persist
471
     *
472
     * @return void
473
     */
474
    abstract protected function persistDatetimeAttribute($attribute);
475
476
    /**
477
     * Persist's the passed text attribute.
478
     *
479
     * @param array $attribute The attribute to persist
480
     *
481
     * @return void
482
     */
483
    abstract protected function persistTextAttribute($attribute);
484
485
    /**
486
     * Delete's the datetime attribute with the passed value ID.
487
     *
488
     * @param array       $row  The attributes of the entity to delete
489
     * @param string|null $name The name of the prepared statement that has to be executed
490
     *
491
     * @return void
492
     */
493
    abstract protected function deleteDatetimeAttribute(array $row, $name = null);
494
495
    /**
496
     * Delete's the decimal attribute with the passed value ID.
497
     *
498
     * @param array       $row  The attributes of the entity to delete
499
     * @param string|null $name The name of the prepared statement that has to be executed
500
     *
501
     * @return void
502
     */
503
    abstract protected function deleteDecimalAttribute(array $row, $name = null);
504
505
    /**
506
     * Delete's the integer attribute with the passed value ID.
507
     *
508
     * @param array       $row  The attributes of the entity to delete
509
     * @param string|null $name The name of the prepared statement that has to be executed
510
     *
511
     * @return void
512
     */
513
    abstract protected function deleteIntAttribute(array $row, $name = null);
514
515
    /**
516
     * Delete's the text attribute with the passed value ID.
517
     *
518
     * @param array       $row  The attributes of the entity to delete
519
     * @param string|null $name The name of the prepared statement that has to be executed
520
     *
521
     * @return void
522
     */
523
    abstract protected function deleteTextAttribute(array $row, $name = null);
524
525
    /**
526
     * Delete's the varchar attribute with the passed value ID.
527
     *
528
     * @param array       $row  The attributes of the entity to delete
529
     * @param string|null $name The name of the prepared statement that has to be executed
530
     *
531
     * @return void
532
     */
533
    abstract protected function deleteVarcharAttribute(array $row, $name = null);
534
535
    /**
536
     * Query whether or not the entity has to be processed.
537
     *
538
     * @param array $entity The entity to query for
539
     *
540
     * @return boolean TRUE if the entity has to be processed, else FALSE
541
     */
542
    abstract protected function hasChanges(array $entity);
543
}
544