Completed
Push — http-client-refactoring ( e04523 )
by Vasily
04:19
created

Connection   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 245
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 245
rs 10
wmc 17
lcom 1
cbo 3

7 Methods

Rating   Name   Duplication   Size   Complexity  
B onRead() 0 29 4
A onReady() 0 10 3
A sendEcho() 0 4 1
B submitJob() 0 20 5
A getStatus() 0 3 1
A setConnectionOption() 0 3 1
A sendCommand() 0 12 2
1
<?php
2
namespace PHPDaemon\Clients\Gearman;
3
4
use PHPDaemon\Network\ClientConnection;
5
use PHPDaemon\Utils\Crypt;
6
7
8
/**
9
 * Class Connection
10
 * @protocol http://gearman.org/protocol/
11
 */
12
class  Connection extends ClientConnection {
0 ignored issues
show
Coding Style introduced by
Expected 1 space between class keyword and class name; 2 found
Loading history...
13
14
    /**
15
     * Magic code for request
16
     */
17
    const MAGIC_REQUEST         = "\0REQ";
18
19
    /**
20
     * Magic code for response
21
     */
22
    const MAGIC_RESPONSE        = "\0RES";
23
24
    /*
25
     * Byte length of header
26
     */
27
    const HEADER_LENGTH         = 12;
28
29
    /**
30
     * Header binary format
31
     */
32
    const HEADER_WRITE_FORMAT   = "a4NN";
33
34
    /**
35
     * Header read format
36
     */
37
    const HEADER_READ_FORMAT    = "a4magic/Ntype/Nsize";
38
39
    /**
40
     * Delimeter for function arguments
41
     */
42
    const ARGS_DELIMITER        = "\0";
43
44
45
46
    /**
47
     * Request codes
48
     *
49
     * @var array
50
     */
51
    protected static $requestCommandList = [
52
        'CAN_DO' => 1,
53
        'CANT_DO' => 2,
54
        'RESET_ABILITIES' => 3,
55
        'PRE_SLEEP' => 4,
56
        'SUBMIT_JOB' => 7,
57
        'GRAB_JOB' => 9,
58
        'WORK_STATUS' => 12,
59
        'WORK_COMPLETE' => 13,
60
        'WORK_FAIL' => 14,
61
        'GET_STATUS' => 15,
62
        'ECHO_REQ' => 16,
63
        'SUBMIT_JOB_BG' => 18,
64
        'SUBMIT_JOB_HIGH' => 21,
65
        'SET_CLIENT_ID' => 22,
66
        'CAN_DO_TIMEOUT' => 23,
67
        'ALL_YOURS' => 24,
68
        'WORK_EXCEPTION' => 25,
69
        'OPTION_REQ' => 26,
70
        'OPTION_RES' => 27,
71
        'WORK_DATA' => 28,
72
        'WORK_WARNING' => 29,
73
        'GRAB_JOB_UNIQ' => 30,
74
        'SUBMIT_JOB_HIGH_BG' => 32,
75
        'SUBMIT_JOB_LOW' => 33,
76
        'SUBMIT_JOB_LOW_BG' => 34,
77
        'SUBMIT_JOB_SCHED' => 35,
78
        'SUBMIT_JOB_EPOCH' => 36,
79
    ];
80
    protected static $requestCommandListFlipped;
81
82
    /**
83
     * Response codes
84
     *
85
     * @var array
86
     */
87
    protected static $responseCommandList = [
88
        'NOOP' => 6,
89
        'JOB_CREATED' => 8,
90
        'NO_JOB' => 10,
91
        'JOB_ASSIGN' => 11,
92
        'WORK_STATUS' => 12,
93
        'WORK_COMPLETE' => 13,
94
        'WORK_FAIL' => 14,
95
        'ECHO_RES' => 17,
96
        'ERROR' => 19,
97
        'STATUS_RES' => 20,
98
        'WORK_EXCEPTION' => 25,
99
        'OPTION_RES' => 27,
100
        'WORK_WARNING' => 29,
101
        'JOB_ASSIGN_UNIQ' => 31,
102
    ];
103
104
    protected static $responseCommandListFlipped;
105
106
    /**
107
     * @var mixed
108
     */
109
    public $response;
110
111
    /**
112
     * @var string
113
     */
114
    public $responseType;
115
116
    /**
117
     * @var string
118
     */
119
    public $responseCommand;
120
121
    /**
122
     * Called when new data received
123
     *
124
     * @return void
125
     */
126
    public function onRead()
127
    {
128
        if (($head = $this->lookExact(static::HEADER_LENGTH)) === false) {
129
            return;
130
        }
131
132
        list($magic, $typeInt, $size) = unpack(static::HEADER_READ_FORMAT, $head);
133
134
        if ($this->getInputLength() < static::HEADER_LENGTH + $size) {
135
            return;
136
        }
137
138
        $this->drain(static::HEADER_LENGTH);
139
        $pct = $this->read($size);
140
141
        if ($magic === static::MAGIC_RESPONSE) {
142
            $this->responseType = static::responseCommandListFlipped[$typeInt];
143
            $this->response = explode(static::ARGS_DELIMITER, $pct);
144
            $this->onResponse->executeOne($this);
145
            $this->responseType = null;
146
            $this->responseCommand = null;
147
            $this->responseType = null;
148
            $this->checkFree();
149
            return;
150
        } else {
151
            $type = static::$requestCommandListFlipped[$typeInt];
0 ignored issues
show
Unused Code introduced by
$type is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
152
            // @TODO
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
153
        }
154
    }
155
    
156
    /**
157
     * Called when the connection is handshaked (at low-level), and peer is ready to recv. data
158
     * @return void
159
     */
160
    public function onReady()
161
    {
162
        if (static::$requestCommandListFlipped === null) {
163
            static::$requestCommandListFlipped = array_flip(static::$requestCommandList);
164
        }
165
        if (static::$responseCommandListFlipped === null) {
166
            static::$responseCommandListFlipped = array_flip(static::$responseCommandList);
167
        }
168
        parent::onReady();
169
    }
170
171
172
    /**
173
     * Function send ECHO
174
     *
175
     * @param $payload
176
     * @param callable|null $cb
177
     */
178
    public function sendEcho ($payload, $cb = null)
179
    {
180
        $this->sendCommand('ECHO_REQ', $payload, $cb);
181
    }
182
183
    /**
184
     * Function run task and wait result in callback
185
     *
186
     * @param $params
187
     * @param callable $cb = null
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
188
     * @param boolean $unique
0 ignored issues
show
Bug introduced by
There is no parameter named $unique. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
189
     */
190
    public function submitJob($params, $cb = null)
191
    {
192
        $closure = function () use (&$params, $cb)
193
        {
194
            $this->sendCommand('SUBMIT_JOB'
195
                . (isset($params['pri']) ? '_ ' . strtoupper($params['pri']) : '')
196
                . (isset($params['bg']) && $params['bg'] ? '_BG' : ''),
197
                [$params['function'], $params['unique'], $params['payload']],
198
                $cb
199
            );
200
        };
201
        if (isset($params['unique'])) {
202
            $closure();
203
        } else {
204
            Crypt::randomString(10, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', function($random) use ($closure) {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 136 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
205
                $params['unique'] = $random;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $params = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
206
                $closure();
207
            });
208
        }
209
    }
210
211
    /**
212
     * Get job status
213
     * 
214
     * @param mixed $jobHandle Job handle that was given in JOB_CREATED packet.
215
     * @param callable $cb = null
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
216
     *
217
     */
218
    public function getStatus($jobHandle, $cb = null) {
219
        $this->sendCommand('GET_STATUS', [$jobHandle], $cb);
220
    }
221
222
    /**
223
     * Function set settings for current connection
224
     * Available settings
225
     * 'exceptions' - Forward WORK_EXCEPTION packets to the client.
226
     *
227
     * @url http://gearman.org/protocol/
228
     *
229
     *
230
     * @param int $optionName
231
     * @param callable $cb = null
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
232
     */
233
    public function setConnectionOption($optionName, $cb = null) {
234
        $this->sendCommand('OPTION_RES', [$optionName], $cb);
235
    }
236
237
    /**
238
     * Send a command
239
     *
240
     * @param $commandName
241
     * @param $payload
242
     * @param callable $cb = null
0 ignored issues
show
Documentation introduced by
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
243
     */
244
    public function sendCommand($commandName, $payload, $cb = null) {
245
246
        $pct = implode(
247
            static::ARGS_DELIMITER,
248
            array_map(function($item){ return !is_scalar($item) ? serialize($item) : $item; }, (array) $payload)
249
        );
250
        $this->onResponse->push($cb);
0 ignored issues
show
Bug introduced by
It seems like $cb defined by parameter $cb on line 244 can also be of type null; however, PHPDaemon\Structures\StackCallbacks::push() does only seem to accept callable, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
251
        $this->write(pack(
252
            static::HEADER_WRITE_FORMAT,
253
            static::MAGIC_REQUEST, $this->requestCommandList[$commandName], mb_orig_strlen($pct)));
254
        $this->write($pct);
255
    }
256
}