GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Branch master (8ad259)
by Charlotte
02:15
created

StatementExecuteCommand::stdEncodeValue()   B

Complexity

Conditions 11
Paths 12

Size

Total Lines 42
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 12.5763

Importance

Changes 0
Metric Value
cc 11
eloc 35
nc 12
nop 1
dl 0
loc 42
ccs 26
cts 34
cp 0.7647
crap 12.5763
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity   

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
 * Plasma Driver MySQL component
4
 * Copyright 2018 PlasmaPHP, All Rights Reserved
5
 *
6
 * Website: https://github.com/PlasmaPHP
7
 * License: https://github.com/PlasmaPHP/driver-mysql/blob/master/LICENSE
8
*/
9
10
namespace Plasma\Drivers\MySQL\Commands;
11
12
/**
13
 * Statement Execute command.
14
 * @internal
15
 */
16
class StatementExecuteCommand extends QueryCommand {
17
    /**
18
     * The identifier for this command.
19
     * @var int
20
     * @source
21
     */
22
    const COMMAND_ID = 0x17;
23
    
24
    /**
25
     * @var mixed
26
     */
27
    protected $id;
28
    
29
    /**
30
     * @var array
31
     */
32
    protected $params;
33
    
34
    /**
35
     * Constructor.
36
     * @param \Plasma\DriverInterface  $driver
37
     * @param mixed                    $id
38
     * @param string                   $query
39
     * @param array                    $params
40
     */
41 37
    function __construct(\Plasma\DriverInterface $driver, $id, string $query, array $params) {
42 37
        parent::__construct($driver, $query);
43
        
44 37
        $this->id = $id;
45 37
        $this->params = $params;
46 37
    }
47
    
48
    /**
49
     * Get the encoded message for writing to the database connection.
50
     * @return string
51
     */
52 36
    function getEncodedMessage(): string {
53 36
        $packet = \chr(static::COMMAND_ID);
54 36
        $packet .= \Plasma\BinaryBuffer::writeInt4($this->id);
55
        
56 36
        $packet .= "\x00"; // Cursor type flag
57 36
        $packet .= \Plasma\BinaryBuffer::writeInt4(1); // Iteration count is always 1
58
        
59 36
        $bitmapOffset = \strlen($packet);
60 36
        $packet .= \str_repeat("\x00", ((\count($this->params) + 7) >> 3));
61
        
62 36
        $bound = 0;
63
        
64 36
        $types = '';
65 36
        $values = '';
66
        
67 36
        foreach($this->params as $id => $param) {
68 36
            if($param === null) {
69 1
                $offset = $bitmapOffset + ($id >> 3);
70 1
                $packet[$offset] = $packet[$offset] | \chr((1 << ($id % 8)));
71
            } else {
72 36
                $bound = 1;
73
            }
74
            
75
            try {
76 36
                $manager = \Plasma\Types\TypeExtensionsManager::getManager('driver-mysql');
77
                $encode = $manager->encodeType($param);
78
                
79
                $unsigned = $encode->isUnsigned();
80
                $type = $encode->getSQLType();
81
                $value = $encode->getValue();
82 36
            } catch (\Plasma\Exception $e) {
83 36
                [ $unsigned, $type, $value ] = $this->stdEncodeValue($param);
84
            }
85
            
86 35
            $types .= \chr($type).($unsigned ? "\x80" : "\x00");
87 35
            $values .= $value;
88
        }
89
        
90 35
        $packet .= \chr($bound);
91
        
92 35
        if($bound) {
93 35
            $packet .= $types;
94 35
            $packet .= $values;
95
        }
96
        
97 35
        return $packet;
98
    }
99
    
100
    /**
101
     * Whether the sequence ID should be resetted.
102
     * @return bool
103
     */
104 36
    function resetSequence(): bool {
105 36
        return true;
106
    }
107
    
108
    /**
109
     * Parses the binary resultset row and returns the row.
110
     * @param \Plasma\BinaryBuffer  $buffer
111
     * @return array
112
     */
113 35
    protected function parseResultsetRow(\Plasma\BinaryBuffer $buffer): array {
114 35
        $buffer->read(1); // remove packet header
115
        
116 35
        $nullRow = array();
117 35
        $i = 0;
118
        
119
        /** @var \Plasma\ColumnDefinitionInterface  $column */
120 35
        foreach($this->fields as $column) { // Handle NULL-bitmap
121 35
            if((\ord($buffer[(($i + 2) >> 3)]) & (1 << (($i + 2) % 8))) !== 0) {
122 2
                $nullRow[$column->getName()] = null;
123
            }
124
            
125 35
            $i++;
126
        }
127
        
128 35
        $buffer->read(((\count($this->fields) + 9) >> 3)); // Remove NULL-bitmap
129 35
        $row = array();
130
        
131
        /** @var \Plasma\ColumnDefinitionInterface  $column */
132 35
        foreach($this->fields as $column) {
133 35
            if(\array_key_exists($column->getName(), $nullRow)) {
134 2
                $row[$column->getName()] = null;
135 2
                continue;
136
            }
137
            
138 35
            $value = $this->stdDecodeBinaryValue($column, $buffer);
139 35
            $parsedValue = $column->parseValue($value);
140
            
141 35
            if($value !== $parsedValue) {
142
                $value = $parsedValue;
143
            }
144
            
145 35
            $row[$column->getName()] = $value;
146
        }
147
        
148 35
        return $row;
149
    }
150
    
151
    /**
152
     * Standard encode value, if type extensions failed.
153
     * @param mixed  $param
154
     * @return array
155
     * @throws \Plasma\Exception
156
     */
157 36
    protected function stdEncodeValue($param): array {
158 36
        $unsigned = false;
159
        
160 36
        switch(\gettype($param)) {
161
            case 'boolean':
162 1
                $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_TINY;
163 1
                $value = ($param ? "\x01" : "\0");
164 1
            break;
165
            case 'integer':
166 7
                if($param >= 0) {
167 7
                    $unsigned = true;
168
                }
169
                
170 7
                if($param >= 0 && $param < (1 << 15)) {
171 7
                    $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_SHORT;
172 7
                    $value = \Plasma\BinaryBuffer::writeInt2($param);
173 3
                } elseif(\PHP_INT_SIZE === 4) {
174
                    $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_LONG;
175
                    $value = \Plasma\BinaryBuffer::writeInt4($param);
176
                } else {
177 3
                    $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_LONGLONG;
178 3
                    $value = \Plasma\BinaryBuffer::writeInt8($param);
179
                }
180 7
            break;
181
            case 'double':
182 2
                $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_DOUBLE;
183 2
                $value = \Plasma\BinaryBuffer::writeDouble($param);
184 2
            break;
185
            case 'string':
186 26
                $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_LONG_BLOB;
187 26
                $value = \Plasma\BinaryBuffer::writeStringLength($param);
188 26
            break;
189
            case 'NULL':
190 1
                $type = \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_NULL;
191 1
                $value = '';
192 1
            break;
193
            default:
194 1
                throw new \Plasma\Exception('Unexpected type for binding parameter: '.\gettype($param));
195
            break;
196
        }
197
        
198 35
        return array($unsigned, $type, $value);
199
    }
200
    
201
    /**
202
     * Standard decode value, if type extensions failed.
203
     * @param \Plasma\ColumnDefinitionInterface  $column
204
     * @param \Plasma\BinaryBuffer               $buffer
205
     * @return mixed
206
     * @throws \Plasma\Exception
207
     */
208 35
    protected function stdDecodeBinaryValue(\Plasma\ColumnDefinitionInterface $column, \Plasma\BinaryBuffer $buffer) {
209 35
        $flags = $column->getFlags();
210 35
        $type = $column->getType();
211
        
212
        switch(true) {
213 35
            case $this->isTypeString($type):
214 18
                $value = $buffer->readStringLength();
215 18
            break;
216 17
            case ($type === 'TINY'):
217 7
                $value = $buffer->readInt1();
218 7
                $value = $this->zeroFillInts($column, $value);
219 7
            break;
220 17
            case $this->isTypeShortOrYear($type):
221 7
                $value = $buffer->readInt2();
222 7
                $value = $this->zeroFillInts($column, $value);
223 7
            break;
224 17
            case $this->isTypeInt24orLong($type):
225 7
                $value = $buffer->readInt4();
226
                
227 7
                if(($flags & \Plasma\Drivers\MySQL\FieldFlags::UNSIGNED_FLAG) !== 0 && \PHP_INT_SIZE <= 4) {
228
                    $value = \bcadd($value, '18446744073709551616');
229
                }
230
                
231 7
                $value = $this->zeroFillInts($column, $value);
232 7
            break;
233 17
            case ($type === 'LONGLONG'):
234 7
                $value = $buffer->readInt8();
235
                
236 7
                if(($flags & \Plasma\Drivers\MySQL\FieldFlags::UNSIGNED_FLAG) !== 0) {
237
                    $value = \bcadd($value, '18446744073709551616');
238 7
                } elseif(\PHP_INT_SIZE > 4) {
239 7
                    $value = (int) $value;
240
                }
241
                
242 7
                $value = $this->zeroFillInts($column, $value);
243 7
            break;
244 10
            case ($type === 'FLOAT'):
245 2
                $value = $buffer->readFloat();
246 2
            break;
247 10
            case ($type === 'DOUBLE'):
248 2
                $value = $buffer->readDouble();
249 2
            break;
250 8
            case $this->isTypeDate($type):
251 8
                $length = $buffer->readIntLength();
252 8
                if($length > 0) {
253 1
                    $year = $buffer->readInt2();
254 1
                    $month = $buffer->readInt1();
255 1
                    $day = $buffer->readInt1();
256
                    
257 1
                    $value = \sprintf('%04d-%02d-%02d', $year, $month, $day);
258
                } else {
259 7
                    $value = '0000-00-00';
260
                }
261 8
            break;
262 8
            case $this->isTypeDateTime($type):
263 8
                $length = $buffer->readIntLength();
264 8
                if($length > 0) {
265 2
                    $year = $buffer->readInt2();
266 2
                    $month = $buffer->readInt1();
267 2
                    $day = $buffer->readInt1();
268
                    
269 2
                    if($length > 4) {
270 1
                        $hour = $buffer->readInt1();
271 1
                        $min = $buffer->readInt1();
272 1
                        $sec = $buffer->readInt1();
273
                    } else {
274 1
                        $hour = 0;
275 1
                        $min = 0;
276 1
                        $sec = 0;
277
                    }
278
                    
279 2
                    if($length > 7) {
280
                        $microI = $buffer->readInt4();
281
                    } else {
282 2
                        $microI = 0;
283
                    }
284
                    
285 2
                    $micro = \str_pad($microI, 6, '0', \STR_PAD_LEFT);
286 2
                    $micro = \substr($micro, 0, 3).' '.\substr($micro, 3);
287
                    
288 2
                    $value = \sprintf('%04d-%02d-%02d %02d:%02d:%02d'.($microI > 0 ? '.%s' : ''), $year, $month, $day, $hour, $min, $sec, $micro);
289
                    
290 2
                    if($type === 'TIMESTAMP') {
291 2
                        $value = \DateTime::createFromFormat('Y-m-d H:i:s'.($microI > 0 ? '.u' : ''), $value)->getTimestamp();
292
                    }
293
                } else {
294 8
                    $value = '0000-00-00 00:00:00.000 000';
295
                }
296 8
            break;
297 8
            case ($type === 'TIME'):
298 8
                $length = $buffer->readIntLength();
299 8
                if($length > 1) {
300 1
                    $sign = $buffer->readInt1();
301 1
                    $days = $buffer->readInt4();
302
                    
303 1
                    if($sign === 1) {
304
                        $days *= -1;
305
                    }
306
                    
307 1
                    $hour = $buffer->readInt1();
308 1
                    $min = $buffer->readInt1();
309 1
                    $sec = $buffer->readInt1();
310
                    
311 1
                    if($length > 8) {
312
                        $microI = $buffer->readInt4();
313
                    } else {
314 1
                        $microI = 0;
315
                    }
316
                    
317 1
                    $micro = \str_pad($microI, 6, '0', \STR_PAD_LEFT);
318 1
                    $micro = \substr($micro, 0, 3).' '.\substr($micro, 3);
319
                    
320 1
                    $value = \sprintf('%dd %02d:%02d:%02d'.($microI > 0 ? '.%s' : ''), $days, $hour, $min, $sec, $micro);
321
                } else {
322 7
                    $value = '0d 00:00:00';
323
                }
324 8
            break;
325
            default:
326
                throw new \InvalidArgumentException('Unknown column type (flags: '.$flags.', type: '.$column->getType().')');
327
            break;
328
        }
329
        
330 35
        return $value;
331
    }
332
    
333
    /**
334
     * @param string  $type
335
     * @return bool
336
     */
337 35
    protected function isTypeString(string $type): bool {
338
        $types = array(
339 35
            'STRING', 'VARCHAR', 'VARSTRING', 'ENUM', 'SET', 'LONGBLOB',
340
            'MEDIUMBLOB', 'BLOB', 'TINYBLOB', 'GEMOTERY', 'BIT', 'DECIMAL',
341
            'NEWDECIMAL', 'JSON'
342
        );
343
        
344 35
        return \in_array($type, $types, true);
345
    }
346
    
347
    /**
348
     * @param string  $type
349
     * @return bool
350
     */
351 17
    protected function isTypeShortOrYear(string $type): bool {
352 17
        $types = array('SHORT', 'YEAR');
353 17
        return \in_array($type, $types, true);
354
    }
355
    
356
    /**
357
     * @param string  $type
358
     * @return bool
359
     */
360 17
    protected function isTypeInt24orLong(string $type): bool {
361 17
        $types = array('INT24', 'LONG');
362 17
        return \in_array($type, $types, true);
363
    }
364
    
365
    /**
366
     * @param string  $type
367
     * @return bool
368
     */
369 8
    protected function isTypeDate(string $type): bool {
370 8
        $types = array('DATE', 'NEWDATE');
371 8
        return \in_array($type, $types, true);
372
    }
373
    
374
    /**
375
     * @param string  $type
376
     * @return bool
377
     */
378 8
    protected function isTypeDateTime(string $type): bool {
379 8
        $types = array('DATETIME', 'TIMESTAMP');
380 8
        return \in_array($type, $types, true);
381
    }
382
    
383
    /**
384
     * @param \Plasma\ColumnDefinitionInterface  $column
385
     * @param string|int                         $value
386
     * @return string|int
387
     */
388 7
    protected function zeroFillInts(\Plasma\ColumnDefinitionInterface $column, $value) {
389 7
        $flags = $column->getFlags();
390
        
391 7
        if(($flags & \Plasma\Drivers\MySQL\FieldFlags::ZEROFILL_FLAG) !== 0) {
392 7
            $value = \str_pad(((string) $value), $column->getLength(), '0', \STR_PAD_LEFT);
393
        }
394
        
395 7
        return $value;
396
    }
397
}
398