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
Push — master ( 8abffd...754ed9 )
by Charlotte
03:13
created

PromiseCommand   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 272
Duplicated Lines 0 %

Test Coverage

Coverage 67.96%

Importance

Changes 0
Metric Value
eloc 97
dl 0
loc 272
ccs 70
cts 103
cp 0.6796
rs 9.84
c 0
b 0
f 0
wmc 32

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getPromise() 0 2 1
A setParserState() 0 2 1
A __construct() 0 13 1
A onError() 0 16 2
A parseColumnDefinition() 0 29 1
A hasFinished() 0 2 1
A onComplete() 0 3 1
A handleQueryOnNextCallerColumns() 0 33 5
A waitForCompletion() 0 2 1
C stdDecodeValue() 0 30 15
A parseResultsetRow() 0 19 3
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
 * Abstract command which has a promise.
14
 * @internal
15
 */
16
abstract class PromiseCommand implements CommandInterface {
17
    use \Evenement\EventEmitterTrait;
18
    
19
    /**
20
     * @var \Plasma\DriverInterface
21
     */
22
    protected $driver;
23
    
24
    /**
25
     * @var \React\Promise\Deferred
26
     */
27
    protected $deferred;
28
    
29
    /**
30
     * @var mixed
31
     */
32
    protected $resolveValue;
33
    
34
    /**
35
     * @var bool
36
     */
37
    protected $finished = false;
38
    
39
    /**
40
     * @var int|null
41
     */
42
    protected $fieldsCount;
43
    
44
    /**
45
     * Constructor.
46
     * @param \Plasma\DriverInterface  $driver
47
     */
48 54
    function __construct(\Plasma\DriverInterface $driver) {
49 54
        $this->driver = $driver;
50 54
        $this->deferred = new \React\Promise\Deferred();
51
        
52
        $this->once('error', function (\Throwable $error) {
53
            $this->deferred->reject($error);
54 54
        });
55
        
56
        $this->once('end', function () {
57
            // Let the event loop read the stream buffer before resolving
58
            $this->driver->getLoop()->futureTick(function () {
59 41
                $this->deferred->resolve($this->resolveValue);
60 41
                $this->resolveValue = null;
61 41
            });
62 54
        });
63 54
    }
64
    
65
    /**
66
     * Get the encoded message for writing to the database connection.
67
     * @return string
68
     */
69
    abstract function getEncodedMessage(): string;
70
    
71
    /**
72
     * Get the promise.
73
     * @return \React\Promise\PromiseInterface
74
     */
75 48
    function getPromise(): \React\Promise\PromiseInterface {
76 48
        return $this->deferred->promise();
77
    }
78
    
79
    /**
80
     * Sets the parser state, if necessary. If not, return `-1`.
81
     * @return int
82
     */
83 45
    function setParserState(): int {
84 45
        return -1;
85
    }
86
    
87
    /**
88
     * Sets the command as completed. This state gets reported back to the user.
89
     * @return void
90
     */
91 41
    function onComplete(): void {
92 41
        $this->finished = true;
93 41
        $this->emit('end');
94 41
    }
95
    
96
    /**
97
     * Sets the command as errored. This state gets reported back to the user.
98
     * @param \Throwable  $throwable
99
     * @return void
100
     */
101
    function onError(\Throwable $throwable): void {
102
        $this->finished = true;
103
        
104
        if($this->resolveValue !== null) {
105
            // Let the event loop read the stream buffer and resolve the promise before emitting
106
            // Works around a race condition, where the promise resolves
107
            // after receiving an error response packet
108
            // and therefore the user misses the error event
109
            $this->driver->getLoop()->futureTick(function () use (&$throwable) {
110
                $this->emit('error', array($throwable));
111
            });
112
            
113
            return;
114
        }
115
        
116
        $this->emit('error', array($throwable));
117
    }
118
    
119
    /**
120
     * Sends the next received value into the command.
121
     * @param mixed  $value
122
     * @return void
123
     */
124
    abstract function onNext($value): void;
125
    
126
    /**
127
     * Whether the command has finished.
128
     * @return bool
129
     */
130 41
    function hasFinished(): bool {
131 41
        return $this->finished;
132
    }
133
    
134
    /**
135
     * Whether this command sets the connection as busy.
136
     * @return bool
137
     */
138 45
    function waitForCompletion(): bool {
139 45
        return true;
140
    }
141
    
142
    /**
143
     * Whether the sequence ID should be resetted.
144
     * @return bool
145
     */
146
    abstract function resetSequence(): bool;
147
    
148
    /**
149
     * Handles the column definitions of query commands on next caller.
150
     * @param \Plasma\BinaryBuffer                  $buffer
151
     * @param \Plasma\Drivers\MySQL\ProtocolParser  $parser
152
     * @return \Plasma\ColumnDefinitionInterface|null
153
     */
154 37
    function handleQueryOnNextCallerColumns(\Plasma\BinaryBuffer $buffer, \Plasma\Drivers\MySQL\ProtocolParser $parser): ?\Plasma\ColumnDefinitionInterface {
155 37
        if($this->fieldsCount === null) {
156 37
            $fieldCount = $buffer->readIntLength();
157
            
158 37
            if($fieldCount === 0x00) {
159
                $this->driver->getLoop()->futureTick(function () use (&$buffer, &$parser) {
160
                    $msg = new \Plasma\Drivers\MySQL\Messages\OkResponseMessage($parser);
161
                    $parser->handleMessage($buffer, $msg);
162
                });
163
                
164
                return null;
165 37
            } elseif($fieldCount === 0xFB) {
166
                // Handle it on future tick, so we can cleanly finish the buffer of this call
167
                $this->driver->getLoop()->futureTick(function () use (&$buffer, &$parser) {
168
                    $msg = new \Plasma\Drivers\MySQL\Messages\LocalInFileRequestMessage($parser);
169
                    $parser->handleMessage($buffer, $msg);
170
                });
171
                
172
                return null;
173 37
            } elseif($fieldCount === 0xFF) {
174
                $this->driver->getLoop()->futureTick(function () use (&$buffer, &$parser) {
175
                    $msg = new \Plasma\Drivers\MySQL\Messages\ErrResponseMessage($parser);
176
                    $parser->handleMessage($buffer, $msg);
177
                });
178
                
179
                return null;
180
            }
181
            
182 37
            $this->fieldsCount = $fieldCount;
183 37
            return null;
184
        }
185
        
186 37
        return static::parseColumnDefinition($buffer);
187
    }
188
    
189
    /**
190
     * Parses the column definition.
191
     * @param \Plasma\BinaryBuffer  $buffer
192
     * @return \Plasma\ColumnDefinitionInterface
193
     */
194 37
    static function parseColumnDefinition(\Plasma\BinaryBuffer $buffer): \Plasma\ColumnDefinitionInterface {
195 37
        $buffer->readStringLength(); // catalog - always "def"
196 37
        $database = $buffer->readStringLength();
197
        
198 37
        $table = $buffer->readStringLength();
199 37
        $buffer->readStringLength(); // orgTable
200
        
201 37
        $name = $buffer->readStringLength();
202 37
        $buffer->readStringLength(); // orgName
203
        
204 37
        $buffer->read(1); // 0x0C
205
        
206 37
        $charset = $buffer->readInt2();
207 37
        $length = $buffer->readInt4();
208 37
        $type = $buffer->readInt1();
209 37
        $flags = $buffer->readInt2();
210 37
        $decimals = $buffer->readInt1();
211
        
212 37
        $buffer->read(2); // fillers
213
        
214
        /*if($this instanceof COM_FIELD_LIST) {
215
            $buffer->readStringLength();
216
        }*/
217
        
218 37
        $charset = \Plasma\Drivers\MySQL\CharacterSetFlags::CHARSET_MAP[$charset] ?? 'Unknown charset "'.$charset.'"';
219 37
        $type = \Plasma\Drivers\MySQL\FieldFlags::TYPE_MAP[$type] ?? 'Unknown type "'.$type.'"';
220 37
        $nullable = (($flags & \Plasma\Drivers\MySQL\FieldFlags::NOT_NULL_FLAG) === 0);
221
        
222 37
        return (new \Plasma\ColumnDefinition($database, $table, $name, $type, $charset, $length, $nullable, $flags, $decimals));
223
    }
224
    
225
    /**
226
     * Parses the text resultset row and returns the row.
227
     * @param \Plasma\BinaryBuffer  $buffer
228
     * @return array
229
     */
230 3
    protected function parseResultsetRow(\Plasma\BinaryBuffer $buffer): array {
231 3
        $row = array();
232
        
233
        /** @var \Plasma\ColumnDefinitionInterface  $column */
234 3
        foreach($this->fields as $column) {
235 3
            $rawValue = $buffer->readStringLength();
236
            
237
            try {
238 3
                $value = \Plasma\Types\TypeExtensionsManager::getManager('driver-mysql')
239
                    ->decodeType($column->getType(), $rawValue)
240
                    ->getValue();
241 3
            } catch (\Plasma\Exception $e) {
242 3
                $value = $this->stdDecodeValue($column, $rawValue);
243
            }
244
            
245 3
            $row[$column->getName()] = $value;
246
        }
247
        
248 3
        return $row;
249
    }
250
    
251
    /**
252
     * Standard decode value, if type extensions failed.
253
     * @param \Plasma\ColumnDefinitionInterface  $column
254
     * @param string|null                        $param
255
     * @return mixed
256
     * @throws \Plasma\Exception
257
     */
258 3
    protected function stdDecodeValue(\Plasma\ColumnDefinitionInterface $column, $param) {
259 3
        $flags = $column->getFlags();
260
        
261 3
        if($param !== null && ($flags & \Plasma\Drivers\MySQL\FieldFlags::ZEROFILL_FLAG) === 0) {
262 3
            switch($column->getType()) {
263 3
                case \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_LONG:
264
                    if(($flags & \Plasma\Drivers\MySQL\FieldFlags::UNSIGNED_FLAG) === 0 || \PHP_INT_SIZE > 4) {
265
                        $param = (int) $param;
266
                    }
267
                break;
268 3
                case \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_LONGLONG:
269
                    if(($flags & \Plasma\Drivers\MySQL\FieldFlags::UNSIGNED_FLAG) === 0 && \PHP_INT_SIZE > 4) {
270
                        $param = (int) $param;
271
                    }
272
                break;
273 3
                case \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_TINY:
274 3
                case \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_SHORT:
275 3
                case \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_INT24:
276 3
                case \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_TIMESTAMP:
277
                    $param = (int) $param;
278
                break;
279 3
                case \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_FLOAT:
280 3
                case \Plasma\Drivers\MySQL\FieldFlags::FIELD_TYPE_DOUBLE:
281
                    $param = (float) $param;
282
                break;
283
                // Other types are taken as string
284
            }
285
        }
286
        
287 3
        return $param;
288
    }
289
}
290