Completed
Push — master ( e17409...9d6c1e )
by Sergey
04:06
created

TypifiedValue   F

Complexity

Total Complexity 64

Size/Duplication

Total Lines 188
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 19

Test Coverage

Coverage 99.24%

Importance

Changes 0
Metric Value
wmc 64
lcom 0
cbo 19
dl 0
loc 188
ccs 131
cts 132
cp 0.9924
rs 2.4812
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
D decode() 0 44 18
D encode() 0 47 19
C guess() 0 73 27

How to fix   Complexity   

Complex Class

Complex classes like TypifiedValue 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 TypifiedValue, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace ButterAMQP\Value;
4
5
use ButterAMQP\Buffer;
6
use ButterAMQP\Exception\AMQP\NotImplementedException;
7
use ButterAMQP\Value;
8
9
class TypifiedValue extends AbstractValue
10
{
11
    /**
12
     * @param Buffer $data
13
     *
14
     * @return mixed
15
     */
16 44
    public static function decode(Buffer $data)
17
    {
18 44
        $hint = $data->read(1);
19
20
        switch ($hint) {
21 44
            case 't':
22 20
                return Value\BooleanValue::decode($data);
23 42
            case 'b':
24 1
                return Value\OctetValue::decode($data);
25 41
            case 'B':
26 1
                return Value\UnsignedOctetValue::decode($data);
27 40
            case 'U':
28 1
                return Value\ShortValue::decode($data);
29 39
            case 'u':
30 1
                return Value\UnsignedShortValue::decode($data);
31 38
            case 'I':
32 8
                return Value\LongValue::decode($data);
33 36
            case 'i':
34 1
                return Value\UnsignedLongValue::decode($data);
35 35
            case 'L':
36 1
                return Value\LongLongValue::decode($data);
37 34
            case 'l':
38 1
                return Value\UnsignedLongLongValue::decode($data);
39 33
            case 'f':
40 2
                return Value\FloatValue::decode($data);
41 31
            case 'd':
42 1
                return Value\DoubleValue::decode($data);
43 30
            case 's':
44 1
                return Value\ShortStringValue::decode($data);
45 29
            case 'S':
46 26
                return Value\LongStringValue::decode($data);
47 25
            case 'A':
48 2
                return Value\ArrayValue::decode($data);
49 23
            case 'T':
50 1
                return Value\TimestampValue::decode($data);
51 22
            case 'F':
52 20
                return Value\TableValue::decode($data);
53 2
            case 'V':
54 1
                return null;
55
            // todo: implement decimals 'D'
56
        }
57
58 1
        throw new \InvalidArgumentException(sprintf('Invalid type hint "%s"', $hint));
59
    }
60
61
    /**
62
     * param mixed $value.
63
     *
64
     * @return string
65
     *
66
     * @throws NotImplementedException
67
     */
68 44
    public static function encode($value)
69
    {
70 44
        $hint = self::guess($value);
71
72 43
        if ($value instanceof AbstractValue) {
73 16
            $value = $value->getValue();
74 16
        }
75
76
        switch ($hint) {
77 43
            case 't':
78 20
                return 't'.Value\BooleanValue::encode((bool) $value);
79 41
            case 'b':
80 1
                return 'b'.Value\OctetValue::encode((int) $value);
81 40
            case 'B':
82 1
                return 'B'.Value\UnsignedOctetValue::encode((int) $value);
83 39
            case 'U':
84 1
                return 'U'.Value\ShortValue::encode((int) $value);
85 38
            case 'u':
86 1
                return 'u'.Value\UnsignedShortValue::encode((int) $value);
87 37
            case 'I':
88 8
                return 'I'.Value\LongValue::encode((int) $value);
89 35
            case 'i':
90 1
                return 'i'.Value\UnsignedLongValue::encode((int) $value);
91 34
            case 'L':
92 1
                return 'L'.Value\LongLongValue::encode((int) $value);
93 33
            case 'l':
94 1
                return 'l'.Value\UnsignedLongLongValue::encode((int) $value);
95 32
            case 'f':
96 2
                return 'f'.Value\FloatValue::encode((float) $value);
97 30
            case 'd':
98 1
                return 'd'.Value\DoubleValue::encode((float) $value);
99 29
            case 's':
100 1
                return 's'.Value\ShortStringValue::encode((string) $value);
101 28
            case 'S':
102 26
                return 'S'.Value\LongStringValue::encode((string) $value);
103 24
            case 'A':
104 2
                return 'A'.Value\ArrayValue::encode((array) $value);
105 22
            case 'T':
106 1
                return 'T'.Value\TimestampValue::encode((int) $value);
107 21
            case 'F':
108 20
                return 'F'.Value\TableValue::encode((array) $value);
109 1
            case 'D':
110
                throw new NotImplementedException('Decimal is not implemented');
111
        }
112
113 1
        return 'V';
114
    }
115
116
    /**
117
     * Guess value type hint.
118
     *
119
     * @param mixed $value
120
     *
121
     * @return string
122
     */
123 44
    private static function guess($value)
124
    {
125 44
        if ($value === null) {
126 1
            return 'V';
127
        }
128
129 43
        if (is_string($value)) {
130 25
            return 'S';
131
        }
132
133 42
        if (is_array($value) && isset($value[0])) {
134 1
            return 'A';
135
        }
136
137 42
        if (is_array($value)) {
138 19
            return 'F';
139
        }
140
141 42
        if (is_bool($value)) {
142 19
            return 't';
143
        }
144
145 23
        if (is_int($value)) {
146 7
            return 'I';
147
        }
148
149 18
        if (is_float($value)) {
150 1
            return 'f';
151
        }
152
153 17
        if (is_object($value)) {
154 17
            switch (get_class($value)) {
155 17
                case Value\BooleanValue::class:
156 1
                    return 't';
157 16
                case Value\OctetValue::class:
158 1
                    return 'b';
159 15
                case Value\UnsignedOctetValue::class:
160 1
                    return 'B';
161 14
                case Value\ShortValue::class:
162 1
                    return 'U';
163 13
                case Value\UnsignedShortValue::class:
164 1
                    return 'u';
165 12
                case Value\LongValue::class:
166 1
                    return 'I';
167 11
                case Value\UnsignedLongValue::class:
168 1
                    return 'i';
169 10
                case Value\LongLongValue::class:
170 1
                    return 'L';
171 9
                case Value\UnsignedLongLongValue::class:
172 1
                    return 'l';
173 8
                case Value\FloatValue::class:
174 1
                    return 'f';
175 7
                case Value\DoubleValue::class:
176 1
                    return 'd';
177 6
                case Value\ShortStringValue::class:
178 1
                    return 's';
179 5
                case Value\LongStringValue::class:
180 1
                    return 'S';
181 4
                case Value\ArrayValue::class:
182 1
                    return 'A';
183 3
                case Value\TimestampValue::class:
184 1
                    return 'T';
185 2
                case Value\TableValue::class:
186 1
                    return 'F';
187
                // @todo: implement "decimal"
188 1
            }
189 1
        }
190
191 1
        throw new \InvalidArgumentException(sprintf(
192 1
            'Invalid value type "%s"',
193 1
            is_object($value) ? get_class($value) : gettype($value)
194 1
        ));
195
    }
196
}
197