Total Complexity | 46 |
Total Lines | 267 |
Duplicated Lines | 0 % |
Coverage | 93.79% |
Changes | 0 |
Complex classes like BinaryProtocolValues 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 BinaryProtocolValues, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
16 | class BinaryProtocolValues { |
||
17 | /** |
||
18 | * Standard encode value, if type extensions failed. |
||
19 | * @param mixed $param |
||
20 | * @return array |
||
21 | * @throws \Plasma\Exception |
||
22 | */ |
||
23 | 36 | static function encode($param): array { |
|
24 | 36 | $unsigned = false; |
|
25 | |||
26 | 36 | switch(\gettype($param)) { |
|
27 | 36 | case 'boolean': |
|
28 | 1 | $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_TINY; |
|
29 | 1 | $value = ($param ? "\x01" : "\0"); |
|
30 | 1 | break; |
|
31 | 36 | case 'integer': |
|
32 | 7 | if($param >= 0) { |
|
33 | 7 | $unsigned = true; |
|
34 | } |
||
35 | |||
36 | 7 | if($param >= 0 && $param < (1 << 15)) { |
|
37 | 7 | $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_SHORT; |
|
38 | 7 | $value = \Plasma\BinaryBuffer::writeInt2($param); |
|
39 | 3 | } elseif(\PHP_INT_SIZE === 4) { |
|
40 | $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_LONG; |
||
41 | $value = \Plasma\BinaryBuffer::writeInt4($param); |
||
42 | } else { |
||
43 | 3 | $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_LONGLONG; |
|
44 | 3 | $value = \Plasma\BinaryBuffer::writeInt8($param); |
|
45 | } |
||
46 | 7 | break; |
|
47 | 29 | case 'double': |
|
48 | 2 | $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_DOUBLE; |
|
49 | 2 | $value = \Plasma\BinaryBuffer::writeDouble($param); |
|
50 | 2 | break; |
|
51 | 27 | case 'string': |
|
52 | 26 | $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_LONG_BLOB; |
|
53 | 26 | $value = \Plasma\BinaryBuffer::writeStringLength($param); |
|
54 | 26 | break; |
|
55 | 2 | case 'NULL': |
|
56 | 1 | $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_NULL; |
|
57 | 1 | $value = ''; |
|
58 | 1 | break; |
|
59 | default: |
||
60 | 1 | throw new \Plasma\Exception('Unexpected type for binding parameter: '.\gettype($param)); |
|
61 | break; |
||
62 | } |
||
63 | |||
64 | 35 | return array($unsigned, $type, $value); |
|
65 | } |
||
66 | |||
67 | /** |
||
68 | * Standard decode value, if type extensions failed. |
||
69 | * @param \Plasma\ColumnDefinitionInterface $column |
||
70 | * @param \Plasma\BinaryBuffer $buffer |
||
71 | * @return mixed |
||
72 | * @throws \Plasma\Exception |
||
73 | */ |
||
74 | 35 | static function decode(\Plasma\ColumnDefinitionInterface $column, \Plasma\BinaryBuffer $buffer) { |
|
75 | 35 | $flags = $column->getFlags(); |
|
76 | 35 | $type = $column->getType(); |
|
77 | |||
78 | switch(true) { |
||
79 | 35 | case static::isTypeString($type): |
|
80 | 18 | $value = $buffer->readStringLength(); |
|
81 | 18 | break; |
|
82 | 17 | case ($type === 'TINY'): |
|
83 | 7 | $value = $buffer->readInt1(); |
|
84 | 7 | $value = static::zeroFillInts($column, $value); |
|
85 | 7 | break; |
|
86 | 17 | case static::isTypeShortOrYear($type): |
|
87 | 7 | $value = $buffer->readInt2(); |
|
88 | 7 | $value = static::zeroFillInts($column, $value); |
|
89 | 7 | break; |
|
90 | 17 | case static::isTypeInt24orLong($type): |
|
91 | 7 | $value = $buffer->readInt4(); |
|
92 | |||
93 | 7 | if($column->isUnsigned() && \PHP_INT_SIZE <= 4) { |
|
1 ignored issue
–
show
|
|||
94 | $value = \bcadd($value, '18446744073709551616'); |
||
95 | } |
||
96 | |||
97 | 7 | $value = static::zeroFillInts($column, $value); |
|
98 | 7 | break; |
|
99 | 17 | case ($type === 'LONGLONG'): |
|
100 | 7 | $value = $buffer->readInt8(); |
|
101 | |||
102 | 7 | if($column->isUnsigned()) { |
|
1 ignored issue
–
show
|
|||
103 | $value = \bcadd($value, '18446744073709551616'); |
||
104 | 7 | } elseif(\PHP_INT_SIZE > 4) { |
|
105 | 7 | $value = (int) $value; |
|
106 | } |
||
107 | |||
108 | 7 | $value = static::zeroFillInts($column, $value); |
|
109 | 7 | break; |
|
110 | 10 | case ($type === 'FLOAT'): |
|
111 | 2 | $value = $buffer->readFloat(); |
|
112 | 2 | break; |
|
113 | 10 | case ($type === 'DOUBLE'): |
|
114 | 2 | $value = $buffer->readDouble(); |
|
115 | 2 | break; |
|
116 | 8 | case static::isTypeDate($type): |
|
117 | 8 | $length = $buffer->readIntLength(); |
|
118 | 8 | if($length > 0) { |
|
119 | 1 | $year = $buffer->readInt2(); |
|
120 | 1 | $month = $buffer->readInt1(); |
|
121 | 1 | $day = $buffer->readInt1(); |
|
122 | |||
123 | 1 | $value = \sprintf('%04d-%02d-%02d', $year, $month, $day); |
|
124 | } else { |
||
125 | 7 | $value = '0000-00-00'; |
|
126 | } |
||
127 | 8 | break; |
|
128 | 8 | case static::isTypeDateTime($type): |
|
129 | 8 | $value = static::parseDateTime($type, $buffer); |
|
130 | 8 | break; |
|
131 | 8 | case ($type === 'TIME'): |
|
132 | 8 | $value = static::parseTime($buffer); |
|
133 | 8 | break; |
|
134 | default: |
||
135 | throw new \InvalidArgumentException('Unknown column type (flags: '.$flags.', type: '.$type.')'); |
||
136 | break; |
||
137 | } |
||
138 | |||
139 | 35 | return $value; |
|
140 | } |
||
141 | |||
142 | /** |
||
143 | * @param string $type |
||
144 | * @return bool |
||
145 | */ |
||
146 | 35 | static function isTypeString(string $type): bool { |
|
147 | $types = array( |
||
148 | 35 | 'STRING', 'VARCHAR', 'VARSTRING', 'ENUM', 'SET', 'LONGBLOB', |
|
149 | 'MEDIUMBLOB', 'BLOB', 'TINYBLOB', 'GEMOTERY', 'BIT', 'DECIMAL', |
||
150 | 'NEWDECIMAL', 'JSON' |
||
151 | ); |
||
152 | |||
153 | 35 | return \in_array($type, $types, true); |
|
154 | } |
||
155 | |||
156 | /** |
||
157 | * @param string $type |
||
158 | * @return bool |
||
159 | */ |
||
160 | 17 | static function isTypeShortOrYear(string $type): bool { |
|
161 | 17 | $types = array('SHORT', 'YEAR'); |
|
162 | 17 | return \in_array($type, $types, true); |
|
163 | } |
||
164 | |||
165 | /** |
||
166 | * @param string $type |
||
167 | * @return bool |
||
168 | */ |
||
169 | 17 | static function isTypeInt24orLong(string $type): bool { |
|
170 | 17 | $types = array('INT24', 'LONG'); |
|
171 | 17 | return \in_array($type, $types, true); |
|
172 | } |
||
173 | |||
174 | /** |
||
175 | * @param string $type |
||
176 | * @return bool |
||
177 | */ |
||
178 | 8 | static function isTypeDate(string $type): bool { |
|
179 | 8 | $types = array('DATE', 'NEWDATE'); |
|
180 | 8 | return \in_array($type, $types, true); |
|
181 | } |
||
182 | |||
183 | /** |
||
184 | * @param string $type |
||
185 | * @return bool |
||
186 | */ |
||
187 | 8 | static function isTypeDateTime(string $type): bool { |
|
188 | 8 | $types = array('DATETIME', 'TIMESTAMP'); |
|
189 | 8 | return \in_array($type, $types, true); |
|
190 | } |
||
191 | |||
192 | /** |
||
193 | * Parses a DATETIME or TIMESTAMP value. |
||
194 | * @param string $type |
||
195 | * @param \Plasma\BinaryBuffer $buffer |
||
196 | * @return mixed |
||
197 | */ |
||
198 | 8 | static function parseDateTime(string $type, \Plasma\BinaryBuffer $buffer) { |
|
199 | 8 | $length = $buffer->readIntLength(); |
|
200 | 8 | if($length > 0) { |
|
201 | 2 | $year = $buffer->readInt2(); |
|
202 | 2 | $month = $buffer->readInt1(); |
|
203 | 2 | $day = $buffer->readInt1(); |
|
204 | |||
205 | 2 | if($length > 4) { |
|
206 | 1 | $hour = $buffer->readInt1(); |
|
207 | 1 | $min = $buffer->readInt1(); |
|
208 | 1 | $sec = $buffer->readInt1(); |
|
209 | } else { |
||
210 | 1 | $hour = 0; |
|
211 | 1 | $min = 0; |
|
212 | 1 | $sec = 0; |
|
213 | } |
||
214 | |||
215 | 2 | if($length > 7) { |
|
216 | $microI = $buffer->readInt4(); |
||
217 | } else { |
||
218 | 2 | $microI = 0; |
|
219 | } |
||
220 | |||
221 | 2 | $micro = \str_pad($microI, 6, '0', \STR_PAD_LEFT); |
|
222 | 2 | $micro = \substr($micro, 0, 3).' '.\substr($micro, 3); |
|
223 | |||
224 | 2 | $value = \sprintf('%04d-%02d-%02d %02d:%02d:%02d'.($microI > 0 ? '.%s' : ''), $year, $month, $day, $hour, $min, $sec, $micro); |
|
225 | |||
226 | 2 | if($type === 'TIMESTAMP') { |
|
227 | 2 | $value = \DateTime::createFromFormat('Y-m-d H:i:s'.($microI > 0 ? '.u' : ''), $value)->getTimestamp(); |
|
228 | } |
||
229 | } else { |
||
230 | 8 | $value = '0000-00-00 00:00:00.000 000'; |
|
231 | } |
||
232 | |||
233 | 8 | return $value; |
|
234 | } |
||
235 | |||
236 | /** |
||
237 | * Parses a TIME value. |
||
238 | * @param \Plasma\BinaryBuffer $buffer |
||
239 | * @return mixed |
||
240 | */ |
||
241 | 8 | static function parseTime(\Plasma\BinaryBuffer $buffer) { |
|
270 | } |
||
271 | |||
272 | /** |
||
273 | * @param \Plasma\ColumnDefinitionInterface $column |
||
274 | * @param string|int $value |
||
275 | * @return string|int |
||
276 | */ |
||
277 | 7 | static function zeroFillInts(\Plasma\ColumnDefinitionInterface $column, $value) { |
|
278 | 7 | if($column->isZerofilled()) { |
|
285 |