Completed
Push — master ( d5f4e5...716f0e )
by Tim
12s
created

AttributeObserverTrait::process()   D

Complexity

Conditions 9
Paths 11

Size

Total Lines 110
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
dl 0
loc 110
ccs 0
cts 75
cp 0
rs 4.8196
c 0
b 0
f 0
cc 9
eloc 56
nc 11
nop 0
crap 90

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\MemberNames;
24
use TechDivision\Import\Utils\StoreViewCodes;
25
26
/**
27
 * Observer that creates/updates the EAV attributes.
28
 *
29
 * @author    Tim Wagner <[email protected]>
30
 * @copyright 2016 TechDivision GmbH <[email protected]>
31
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
32
 * @link      https://github.com/techdivision/import
33
 * @link      http://www.techdivision.com
34
 */
35
trait AttributeObserverTrait
36
{
37
38
    /**
39
     * The ID of the attribute to create the values for.
40
     *
41
     * @var integer
42
     */
43
    protected $attributeId;
44
45
    /**
46
     * The attribute code of the attribute to create the values for.
47
     *
48
     * @var string
49
     */
50
    protected $attributeCode;
51
52
    /**
53
     * The backend type of the attribute to create the values for.
54
     *
55
     * @var string
56
     */
57
    protected $backendType;
58
59
    /**
60
     * The attribute value to process.
61
     *
62
     * @var mixed
63
     */
64
    protected $attributeValue;
65
66
    /**
67
     * Process the observer's business logic.
68
     *
69
     * @return void
70
     */
71
    protected function process()
72
    {
73
74
        // initialize the store view code
75
        $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...
76
77
        // load the attributes by the found attribute set and the backend types
78
        $attributes = $this->getAttributes();
79
        $backendTypes = $this->getBackendTypes();
80
81
        // remove all the empty values from the row
82
        $row = array_filter(
83
            $this->row,
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...
84
            function ($value, $key) {
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...
85
                return ($value !== null && $value !== '');
86
            },
87
            ARRAY_FILTER_USE_BOTH
88
        );
89
90
        // load the header keys
91
        $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...
92
93
        // iterate over the attributes and append them to the row
94
        foreach ($row as $key => $attributeValue) {
95
            // query whether or not attribute with the found code exists
96
            if (!isset($attributes[$attributeCode = $headers[$key]])) {
97
                // log a message in debug mode
98
                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...
99
                    $this->getSystemLogger()->warning(
0 ignored issues
show
Bug introduced by
It seems like getSystemLogger() 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...
100
                        sprintf(
101
                            'Can\'t find attribute with attribute code %s in file %s on line %d',
102
                            $attributeCode,
103
                            $this->getFilename(),
0 ignored issues
show
Bug introduced by
It seems like getFilename() 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...
104
                            $this->getLineNumber()
0 ignored issues
show
Bug introduced by
It seems like getLineNumber() 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...
105
                        )
106
                    );
107
                }
108
109
                // stop processing
110
                continue;
111
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
112
            } else {
113
                // log a message in debug mode
114
                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...
115
                    $this->getSystemLogger()->debug(
0 ignored issues
show
Bug introduced by
It seems like getSystemLogger() 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...
116
                        sprintf(
117
                            'Found attribute with attribute code %s in file %s on line %d',
118
                            $attributeCode,
119
                            $this->getFilename(),
0 ignored issues
show
Bug introduced by
It seems like getFilename() 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...
120
                            $this->getLineNumber()
0 ignored issues
show
Bug introduced by
It seems like getLineNumber() 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
                    );
123
                }
124
            }
125
126
            // if yes, load the attribute by its code
127
            $attribute = $attributes[$attributeCode];
128
129
            // load the backend type => to find the apropriate entity
130
            $backendType = $attribute[MemberNames::BACKEND_TYPE];
131
            if ($backendType == null) {
132
                $this->getSystemLogger()->warning(
0 ignored issues
show
Bug introduced by
It seems like getSystemLogger() 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...
133
                    sprintf(
134
                        'Found EMTPY backend type for attribute %s in file %s on line %d',
135
                        $attributeCode,
136
                        $this->getFilename(),
0 ignored issues
show
Bug introduced by
It seems like getFilename() 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...
137
                        $this->getLineNumber()
0 ignored issues
show
Bug introduced by
It seems like getLineNumber() 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...
138
                    )
139
                );
140
                continue;
141
            }
142
143
            // do nothing on static backend type
144
            if ($backendType === 'static') {
145
                continue;
146
            }
147
148
            // query whether or not we've found a supported backend type
149
            if (isset($backendTypes[$backendType])) {
150
                // initialize attribute ID/code and backend type
151
                $this->attributeId = $attribute[MemberNames::ATTRIBUTE_ID];
152
                $this->attributeCode = $attributeCode;
153
                $this->backendType = $backendType;
154
155
                // initialize the persist method for the found backend type
156
                list ($persistMethod, ) = $backendTypes[$backendType];
157
158
                // set the attribute value
159
                $this->attributeValue = $attributeValue;
160
161
                // load the prepared values
162
                $entity = $this->initializeAttribute($this->prepareAttributes());
163
164
                // persist the attribute and continue
165
                $this->$persistMethod($entity);
166
                continue;
167
            }
168
169
            // log the debug message
170
            $this->getSystemLogger()->debug(
0 ignored issues
show
Bug introduced by
It seems like getSystemLogger() 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...
171
                sprintf(
172
                    'Found invalid backend type %s for attribute %s in file %s on line %s',
173
                    $this->backendType,
174
                    $this->attributeCode,
175
                    $this->getFilename(),
0 ignored issues
show
Bug introduced by
It seems like getFilename() 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...
176
                    $this->getLineNumber()
0 ignored issues
show
Bug introduced by
It seems like getLineNumber() 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...
177
                )
178
            );
179
        }
180
    }
181
182
    /**
183
     * Prepare the attributes of the entity that has to be persisted.
184
     *
185
     * @return array The prepared attributes
186
     */
187
    protected function prepareAttributes()
188
    {
189
190
        // laod the callbacks for the actual attribute code
191
        $callbacks = $this->getCallbacksByType($this->attributeCode);
192
193
        // invoke the pre-cast callbacks
194
        foreach ($callbacks as $callback) {
195
            $this->attributeValue = $callback->handle($this->attributeValue);
196
        }
197
198
        // load the ID of the product that has been created recently
199
        $lastEntityId = $this->getPrimaryKey();
200
201
        // load the store ID
202
        $storeId = $this->getRowStoreId(StoreViewCodes::ADMIN);
203
204
        // cast the value based on the backend type
205
        $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...
206
207
        // prepare the attribute values
208
        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...
209
            array(
210
                MemberNames::ENTITY_ID    => $lastEntityId,
211
                MemberNames::ATTRIBUTE_ID => $this->attributeId,
212
                MemberNames::STORE_ID     => $storeId,
213
                MemberNames::VALUE        => $castedValue
214
            )
215
        );
216
    }
217
218
    /**
219
     * Initialize the category product with the passed attributes and returns an instance.
220
     *
221
     * @param array $attr The category product attributes
222
     *
223
     * @return array The initialized category product
224
     */
225
    protected function initializeAttribute(array $attr)
226
    {
227
        return $attr;
228
    }
229
230
    /**
231
     * Return's the PK to create the product => attribute relation.
232
     *
233
     * @return integer The PK to create the relation with
234
     */
235
    protected function getPrimaryKey()
236
    {
237
        return $this->getLastEntityId();
0 ignored issues
show
Bug introduced by
It seems like getLastEntityId() 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...
238
    }
239
240
    /**
241
     * Map the passed attribute code, if a header mapping exists and return the
242
     * mapped mapping.
243
     *
244
     * @param string $attributeCode The attribute code to map
245
     *
246
     * @return string The mapped attribute code, or the original one
247
     */
248
    protected function mapAttributeCodeByHeaderMapping($attributeCode)
249
    {
250
        return $this->getSubject()->mapAttributeCodeByHeaderMapping($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...
251
    }
252
253
    /**
254
     * Return's the array with callbacks for the passed type.
255
     *
256
     * @param string $type The type of the callbacks to return
257
     *
258
     * @return array The callbacks
259
     */
260
    protected function getCallbacksByType($type)
261
    {
262
        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...
263
    }
264
265
    /**
266
     * Return's mapping for the supported backend types (for the product entity) => persist methods.
267
     *
268
     * @return array The mapping for the supported backend types
269
     */
270
    protected function getBackendTypes()
271
    {
272
        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...
273
    }
274
275
    /**
276
     * Return's the attributes for the attribute set of the product that has to be created.
277
     *
278
     * @return array The attributes
279
     * @throws \Exception
280
     */
281
    protected function getAttributes()
282
    {
283
        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...
284
    }
285
286
    /**
287
     * Return's the store ID of the actual row, or of the default store
288
     * if no store view code is set in the CSV file.
289
     *
290
     * @param string|null $default The default store view code to use, if no store view code is set in the CSV file
291
     *
292
     * @return integer The ID of the actual store
293
     * @throws \Exception Is thrown, if the store with the actual code is not available
294
     */
295
    protected function getRowStoreId($default = null)
296
    {
297
        return $this->getSubject()->getRowStoreId($default);
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
    }
299
}
300