Attribute   F
last analyzed

Complexity

Total Complexity 71

Size/Duplication

Total Lines 484
Duplicated Lines 0 %

Test Coverage

Coverage 85.19%

Importance

Changes 0
Metric Value
wmc 71
eloc 180
dl 0
loc 484
ccs 161
cts 189
cp 0.8519
rs 2.7199
c 0
b 0
f 0

43 Methods

Rating   Name   Duplication   Size   Complexity  
A guessUnknown() 0 3 2
A guessBool() 0 3 2
A guessTextLike() 0 3 2
A guessNumber() 0 3 2
A getValueAsLocalizedEnumSet() 0 5 1
A getValueAsNestedSet() 0 5 1
A getApiType() 0 14 3
A getValueAsStringSet() 0 5 1
A getValueAsDateTime() 0 5 1
A guessEnum() 0 7 3
A getValueAsTimeSet() 0 5 1
A fieldDefinition() 0 17 5
A getValueAsMoneySet() 0 5 1
A getValueAsEnum() 0 5 1
A hasKeys() 0 7 2
A getValueAsNested() 0 5 1
A getValueAsLocalizedString() 0 5 1
A getValueAsBoolSet() 0 5 1
A setApiType() 0 12 4
A guessSet() 0 7 2
A guessApiType() 0 23 3
A getValueAsBool() 0 5 1
A getValueAsReferenceSet() 0 5 1
A getValueAsNumber() 0 5 1
A initialize() 0 8 2
A getValueAsEnumSet() 0 5 1
A getValueAsString() 0 5 1
A guessLocalizedText() 0 7 3
A getValueAsDateTimeSet() 0 5 1
A getValueAsTime() 0 5 1
A getValueAsLocalizedStringSet() 0 5 1
A guessNested() 0 10 3
A getValueAsNumberSet() 0 5 1
A getValueAsDateSet() 0 5 1
A guessReference() 0 7 2
A setAttributeDefinition() 0 5 1
A getValueAsMoney() 0 5 1
A fieldDefinitions() 0 5 1
A guessMoney() 0 7 2
A getValueAsReference() 0 5 1
A guessLocalizedEnum() 0 7 3
A getValueAsDate() 0 5 1
A getValueAsLocalizedEnum() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Attribute often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Attribute, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @author @jenschude <[email protected]>
4
 * @created: 04.02.15, 17:46
5
 */
6
7
namespace Commercetools\Core\Model\Common;
8
9
use Commercetools\Core\Model\ProductType\AttributeDefinition;
10
use Commercetools\Core\Model\ProductType\AttributeType;
11
use Commercetools\Core\Model\ProductType\SetType;
12
13
/**
14
 * @package Commercetools\Core\Model\Common
15
 * @link https://docs.commercetools.com/http-api-projects-products.html#attribute
16
 * @method string getName()
17
 * @method Attribute setName(string $name = null)
18
 * @method mixed getValue()
19
 * @method Attribute setValue($value = null)
20
 */
21
class Attribute extends JsonObject
22
{
23
    // identifiers for the Api Product Attribute Types:
24
    const T_UNKNOWN = 'unknown';  // zero, should evaluate to false
25
26
    const PROP_VALUE = "value";
27
    const PROP_KEY = "key";
28
    const PROP_NAME = "name";
29
    const PROP_CURRENCY_CODE = "currencyCode";
30
    const PROP_CENT_AMOUNT = "centAmount";
31
    const PROP_TYPE_ID = "typeId";
32
    const PROP_ID = "id";
33
    const PROP_LABEL = "label";
34
35
    const API_BOOL = 'boolean';
36
    const API_NUMBER = 'number';
37
    const API_TEXT = 'text';
38
    const API_LTEXT = 'ltext';
39
    const API_LENUM = 'lenum';
40
    const API_ENUM = 'enum';
41
    const API_MONEY = 'money';
42
    const API_DATE = 'date';
43
    const API_TIME = 'time';
44
    const API_DATETIME = 'datetime';
45
    const API_SET = 'set';
46
    const API_NESTED = 'nested';
47
    const API_REFERENCE = 'reference';
48
49
    protected static $types = [];
50
51 52
    public function fieldDefinitions()
52
    {
53
        return [
54 52
            static::PROP_NAME => [static::TYPE => 'string'],
55 52
            static::PROP_VALUE => [],
56
        ];
57
    }
58
59 50
    public function fieldDefinition($field)
60
    {
61 50
        if ($field == static::PROP_VALUE) {
62 49
            if (isset(static::$types[$this->getName()])) {
63 43
                $fieldDefinition = static::$types[$this->getName()];
64 43
                if (!$fieldDefinition instanceof AttributeDefinition) {
65
                    return null;
66
                }
67 43
                $fieldType = $fieldDefinition->getType();
68 43
                if (!$fieldType instanceof AttributeType) {
0 ignored issues
show
introduced by
$fieldType is always a sub-type of Commercetools\Core\Model\ProductType\AttributeType.
Loading history...
69
                    return null;
70
                }
71 43
                return $fieldType->fieldTypeDefinition();
72
            }
73 7
            return null;
74
        }
75 50
        return parent::fieldDefinition($field);
76
    }
77
78
    /**
79
     * @param $attributeName
80
     * @param $value
81
     * @return mixed
82
     */
83 43
    protected function getApiType($attributeName, $value)
84
    {
85 43
        if (isset(static::$types[$attributeName])) {
86 28
            return static::$types[$attributeName];
87
        }
88
89 15
        $apiType = $this->guessApiType($value);
90 15
        $elementType = null;
91 15
        if ($apiType == static::API_SET) {
92 2
            $elementType = $this->guessApiType(current($value));
93
        }
94 15
        $this->setApiType($attributeName, $apiType, $elementType);
95
96 15
        return static::$types[$attributeName];
97
    }
98
99
    /**
100
     * @param AttributeDefinition $definition
101
     * @return $this
102
     */
103 40
    public function setAttributeDefinition(AttributeDefinition $definition)
104
    {
105 40
        static::$types[$definition->getName()] = $definition;
106
107 40
        return $this;
108
    }
109
110
    /**
111
     * @param string $field
112
     */
113 44
    protected function initialize($field)
114
    {
115 44
        if ($field == static::PROP_VALUE) {
116 43
            $name = $this->getRaw(static::PROP_NAME);
117 43
            $value = $this->getRaw(static::PROP_VALUE);
118 43
            $this->getApiType($name, $value);
119
        }
120 44
        parent::initialize($field);
121 44
    }
122
123 36
    private function setApiType($attributeName, $valueType, $elementType = null)
124
    {
125 36
        if (!isset(static::$types[$attributeName])) {
126 36
            $attributeType = AttributeType::fromArray(['name' => $valueType]);
127 36
            if ($attributeType instanceof SetType && $elementType != null) {
128 13
                $attributeType->setElementType(AttributeType::fromArray(['name' => $elementType]));
129
            }
130
131 36
            $definition = AttributeDefinition::of($this->getContextCallback());
132 36
            $definition->setName($attributeName);
133 36
            $definition->setType($attributeType);
134 36
            $this->setAttributeDefinition($definition);
135
        }
136 36
    }
137
138
    /**
139
     * @return bool
140
     */
141 1
    public function getValueAsBool()
142
    {
143 1
        $attributeName = $this->getName();
144 1
        $this->setApiType($attributeName, static::API_BOOL);
145 1
        return $this->getValue();
146
    }
147
148
    /**
149
     * @return int|float
150
     */
151 2
    public function getValueAsNumber()
152
    {
153 2
        $attributeName = $this->getName();
154 2
        $this->setApiType($attributeName, static::API_NUMBER);
155 2
        return $this->getValue();
156
    }
157
158
    /**
159
     * @return string
160
     */
161 1
    public function getValueAsString()
162
    {
163 1
        $attributeName = $this->getName();
164 1
        $this->setApiType($attributeName, static::API_TEXT);
165 1
        return $this->getValue();
166
    }
167
168
    /**
169
     * @return LocalizedString
170
     */
171 1
    public function getValueAsLocalizedString()
172
    {
173 1
        $attributeName = $this->getName();
174 1
        $this->setApiType($attributeName, static::API_LTEXT);
175 1
        return $this->getValue();
176
    }
177
178
    /**
179
     * @return LocalizedEnum
180
     */
181 1
    public function getValueAsLocalizedEnum()
182
    {
183 1
        $attributeName = $this->getName();
184 1
        $this->setApiType($attributeName, static::API_LENUM);
185 1
        return $this->getValue();
186
    }
187
188
    /**
189
     * @return Enum
190
     */
191 1
    public function getValueAsEnum()
192
    {
193 1
        $attributeName = $this->getName();
194 1
        $this->setApiType($attributeName, static::API_ENUM);
195 1
        return $this->getValue();
196
    }
197
198
    /**
199
     * @return Money
200
     */
201 1
    public function getValueAsMoney()
202
    {
203 1
        $attributeName = $this->getName();
204 1
        $this->setApiType($attributeName, static::API_MONEY);
205 1
        return $this->getValue();
206
    }
207
208
    /**
209
     * @return DateDecorator
210
     */
211
    public function getValueAsDate()
212
    {
213
        $attributeName = $this->getName();
214
        $this->setApiType($attributeName, static::API_DATE);
215
        return $this->getValue();
216
    }
217
218
    /**
219
     * @return TimeDecorator
220
     */
221
    public function getValueAsTime()
222
    {
223
        $attributeName = $this->getName();
224
        $this->setApiType($attributeName, static::API_TIME);
225
        return $this->getValue();
226
    }
227
228
    /**
229
     * @return DateTimeDecorator
230
     */
231
    public function getValueAsDateTime()
232
    {
233
        $attributeName = $this->getName();
234
        $this->setApiType($attributeName, static::API_DATETIME);
235
        return $this->getValue();
236
    }
237
238
    /**
239
     * @return AttributeCollection
240
     */
241 1
    public function getValueAsNested()
242
    {
243 1
        $attributeName = $this->getName();
244 1
        $this->setApiType($attributeName, static::API_NESTED);
245 1
        return $this->getValue();
246
    }
247
248
    /**
249
     * @return Reference
250
     */
251 1
    public function getValueAsReference()
252
    {
253 1
        $attributeName = $this->getName();
254 1
        $this->setApiType($attributeName, static::API_REFERENCE);
255 1
        return $this->getValue();
256
    }
257
258
    /**
259
     * @return Set
260
     */
261 1
    public function getValueAsBoolSet()
262
    {
263 1
        $attributeName = $this->getName();
264 1
        $this->setApiType($attributeName, static::API_SET, static::API_BOOL);
265 1
        return $this->getValue();
266
    }
267
268
    /**
269
     * @return Set
270
     */
271 2
    public function getValueAsNumberSet()
272
    {
273 2
        $attributeName = $this->getName();
274 2
        $this->setApiType($attributeName, static::API_SET, static::API_NUMBER);
275 2
        return $this->getValue();
276
    }
277
278
    /**
279
     * @return Set
280
     */
281 1
    public function getValueAsStringSet()
282
    {
283 1
        $attributeName = $this->getName();
284 1
        $this->setApiType($attributeName, static::API_SET, static::API_TEXT);
285 1
        return $this->getValue();
286
    }
287
288
    /**
289
     * @return Set
290
     */
291 1
    public function getValueAsLocalizedStringSet()
292
    {
293 1
        $attributeName = $this->getName();
294 1
        $this->setApiType($attributeName, static::API_SET, static::API_LTEXT);
295 1
        return $this->getValue();
296
    }
297
298
    /**
299
     * @return Set
300
     */
301 1
    public function getValueAsLocalizedEnumSet()
302
    {
303 1
        $attributeName = $this->getName();
304 1
        $this->setApiType($attributeName, static::API_SET, static::API_LENUM);
305 1
        return $this->getValue();
306
    }
307
308
    /**
309
     * @return Set
310
     */
311 2
    public function getValueAsEnumSet()
312
    {
313 2
        $attributeName = $this->getName();
314 2
        $this->setApiType($attributeName, static::API_SET, static::API_ENUM);
315 2
        return $this->getValue();
316
    }
317
318
    /**
319
     * @return Set
320
     */
321 1
    public function getValueAsMoneySet()
322
    {
323 1
        $attributeName = $this->getName();
324 1
        $this->setApiType($attributeName, static::API_SET, static::API_MONEY);
325 1
        return $this->getValue();
326
    }
327
328
    /**
329
     * @return Set
330
     */
331
    public function getValueAsDateSet()
332
    {
333
        $attributeName = $this->getName();
334
        $this->setApiType($attributeName, static::API_SET, static::API_DATE);
335
        return $this->getValue();
336
    }
337
338
    /**
339
     * @return Set
340
     */
341
    public function getValueAsTimeSet()
342
    {
343
        $attributeName = $this->getName();
344
        $this->setApiType($attributeName, static::API_SET, static::API_TIME);
345
        return $this->getValue();
346
    }
347
348
    /**
349
     * @return Set
350
     */
351
    public function getValueAsDateTimeSet()
352
    {
353
        $attributeName = $this->getName();
354
        $this->setApiType($attributeName, static::API_SET, static::API_DATETIME);
355
        return $this->getValue();
356
    }
357
358
    /**
359
     * @return Set
360
     */
361 1
    public function getValueAsNestedSet()
362
    {
363 1
        $attributeName = $this->getName();
364 1
        $this->setApiType($attributeName, static::API_SET, static::API_NESTED);
365 1
        return $this->getValue();
366
    }
367
368
    /**
369
     * @return Set
370
     */
371 1
    public function getValueAsReferenceSet()
372
    {
373 1
        $attributeName = $this->getName();
374 1
        $this->setApiType($attributeName, static::API_SET, static::API_REFERENCE);
375 1
        return $this->getValue();
376
    }
377
378
    /**
379
     * @param $value
380
     * @return string
381
     */
382 15
    protected function guessApiType($value)
383
    {
384
        $map = [
385 15
            'guessUnknown',
386
            'guessBool',
387
            'guessTextLike',
388
            'guessNumber',
389
            'guessEnum',
390
            'guessLocalizedEnum',
391
            'guessMoney',
392
            'guessReference',
393
            'guessLocalizedText',
394
            'guessNested',
395
            'guessSet',
396
        ];
397
398 15
        foreach ($map as $function) {
399 15
            if ($type = $this->$function($value)) {
400 15
                return $type;
401
            }
402
        }
403
404
        return static::T_UNKNOWN;
405
    }
406
407
    /**
408
     * @param $value
409
     * @param string[] $keys
410
     * @return bool
411
     */
412 9
    protected function hasKeys($value, $keys)
413
    {
414 9
        if (!is_array($value)) {
415 1
            return false;
416
        }
417 9
        $intersect = array_intersect_key(array_flip($keys), $value);
418 9
        return (count($intersect) == count($keys));
419
    }
420
421 15
    protected function guessUnknown($value)
422
    {
423 15
        return (!isset($value) ? static::T_UNKNOWN : null);
424
    }
425
426 13
    protected function guessTextLike($value)
427
    {
428 13
        return is_string($value) ? static::API_TEXT : null;
429
    }
430
431 14
    protected function guessBool($value)
432
    {
433 14
        return is_bool($value) ? static::API_BOOL : null;
434
    }
435
436 11
    protected function guessNumber($value)
437
    {
438 11
        return is_numeric($value) ? static::API_NUMBER : null;
439
    }
440
441 9
    protected function guessEnum($value)
442
    {
443 9
        if ($this->hasKeys($value, [static::PROP_KEY, static::PROP_LABEL]) && is_string($value[static::PROP_LABEL])) {
444 2
            return static::API_ENUM;
445
        }
446
447 8
        return null;
448
    }
449
450 8
    protected function guessLocalizedEnum($value)
451
    {
452 8
        if ($this->hasKeys($value, [static::PROP_KEY, static::PROP_LABEL]) && is_array($value[static::PROP_LABEL])) {
453 1
            return static::API_LENUM;
454
        }
455
456 7
        return null;
457
    }
458
459 7
    protected function guessMoney($value)
460
    {
461 7
        if ($this->hasKeys($value, [static::PROP_CENT_AMOUNT, static::PROP_CURRENCY_CODE])) {
462 1
            return static::API_MONEY;
463
        }
464
465 6
        return null;
466
    }
467
468 6
    protected function guessReference($value)
469
    {
470 6
        if ($this->hasKeys($value, [static::PROP_TYPE_ID, static::PROP_ID])) {
471 2
            return static::API_REFERENCE;
472
        }
473
474 4
        return null;
475
    }
476
477 4
    protected function guessLocalizedText($value)
478
    {
479 4
        if (is_array($value) && !is_numeric(key($value))) {
480 1
            return static::API_LTEXT;
481
        }
482
483 3
        return null;
484
    }
485
486 2
    protected function guessSet($value)
487
    {
488 2
        if (is_array($value)) {
489 2
            return static::API_SET;
490
        }
491
492
        return null;
493
    }
494
495 3
    protected function guessNested($value)
496
    {
497 3
        if (is_array($value)) {
498 3
            $first = reset($value);
499 3
            if ($this->hasKeys($first, [static::PROP_NAME, static::PROP_VALUE])) {
500 1
                return static::API_NESTED;
501
            }
502
        }
503
504 2
        return null;
505
    }
506
}
507