Passed
Pull Request — master (#28)
by Valentin
49:48
created

Pheanstalk::getConnection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Pheanstalk;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Pheanstalk\Command\CreateCommand;
7
use Pheanstalk\Command\CreateScheduleCommand;
8
use Pheanstalk\Command\CreateTubeCommand;
9
use Pheanstalk\Command\GetWorkflowCommand;
10
use Pheanstalk\Command\GetWorkflowInstancesCommand;
11
use Pheanstalk\Command\GetWorkflowInstancesDetailCommand;
12
use Pheanstalk\Command\ListWorkflowsCommand;
13
use Pheanstalk\Command\ReleaseCommand;
0 ignored issues
show
Bug introduced by
The type Pheanstalk\Command\ReleaseCommand was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use Pheanstalk\Command\UpdateTubeCommand;
15
use Pheanstalk\Command\WorkflowExistsCommand;
16
use Pheanstalk\Exception\ServerDuplicateEntryException;
17
use Pheanstalk\Structure\Job;
18
use Pheanstalk\Structure\Schedule;
19
use Pheanstalk\Structure\Task;
20
use Pheanstalk\Structure\TaskInstance;
21
use Pheanstalk\Structure\TimeSchedule;
22
use Pheanstalk\Structure\Tube;
23
use Pheanstalk\Structure\Workflow;
24
use Pheanstalk\Structure\WorkflowInstance;
25
26
/**
27
 * Pheanstalk is a PHP client for the beanstalkd workqueue.
28
 *
29
 * The Pheanstalk class is a simple facade for the various underlying components.
30
 *
31
 * @see http://github.com/kr/beanstalkd
32
 * @see http://xph.us/software/beanstalkd/
33
 *
34
 * @author  Paul Annesley
35
 * @package Pheanstalk
36
 * @license http://www.opensource.org/licenses/mit-license.php
37
 */
38
class Pheanstalk implements PheanstalkInterface
39
{
40
41
    /** @var Connection $connection */
42
    private $connection;
43
44
    /** @var PheanstalkInterface $currentClass */
45
    private $currentClass;
46
47
    /**
48
     * @param string $host
49
     * @param string $user
50
     * @param string $password
51
     * @param int    $port
52
     * @param int    $connectTimeout
53
     * @param bool   $connectPersistent
54
     */
55 20
    public function __construct($host, $user = null, $password = null, $port = PheanstalkInterface::DEFAULT_PORT, $connectTimeout = null, $connectPersistent = false)
56
    {
57 20
        $this->setConnection(new Connection($host, $user, $password, $port, $connectTimeout, $connectPersistent));
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 20
    public function setConnection(Connection $connection)
64
    {
65 20
        $this->connection = $connection;
66
67 20
        return $this;
68
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73 2
    public function getConnection()
74
    {
75 2
        return $this->connection;
76
    }
77
78
    /**
79
     * @return PheanstalkInterface
80
     */
81 13
    public function getCurrentClass(): PheanstalkInterface
82
    {
83 13
        return $this->currentClass ?? $this;
84
    }
85
86
    /**
87
     * @param PheanstalkInterface $currentClass
88
     *
89
     * @return Pheanstalk
90
     */
91 1
    public function setCurrentClass(PheanstalkInterface $currentClass): PheanstalkInterface
92
    {
93 1
        $this->currentClass = $currentClass;
94 1
        return $this;
95
    }
96
97
    // ----------------------------------------
98
99
    /**
100
     * {@inheritdoc}
101
     */
102 1
    public function deleteSchedule(Schedule $schedule)
103
    {
104 1
        return $this->_dispatch(new Command\DeleteScheduleCommand($schedule));
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110 5
    public function delete(Workflow $workflow)
111
    {
112 5
        return $this->_dispatch(new Command\DeleteCommand($workflow));
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118 1
    public function deleteTube(Tube $tube)
119
    {
120 1
        return $this->_dispatch(new Command\DeleteTubeCommand($tube));
121
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126 8
    public function workflowExists($name)
127
    {
128 8
        $workflow = $this->_dispatch(new Command\WorkflowExistsCommand($name));
129 7
        if ($workflow instanceof Workflow) {
130 7
            return $this->getCurrentClass()->getWorkflow($workflow);
131
        }
132 1
        return false;
133
    }
134
135
    /**
136
     * {@inheritdoc}
137
     */
138 1
    public function getSchedule(int $scheduleId)
139
    {
140 1
        return $this->_dispatch(new Command\GetScheduleCommand($scheduleId));
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146 7
    public function getWorkflow(Workflow $workflow)
147
    {
148 7
        return $this->_dispatch(new Command\GetWorkflowCommand($workflow));
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154 4
    public function getWorkflowInstances(?Workflow $workflow, string $status = null)
155
    {
156 4
        $paramsStatus = empty($status) ? GetWorkflowInstancesDetailCommand::FILTERS : [$status];
157 4
        $instances = new ArrayCollection([]);
158 4
        foreach ($paramsStatus as $stat) {
159 4
            $instances[strtolower($stat)] = $this->_dispatch(new Command\GetWorkflowInstancesCommand($workflow, $stat));
160
                /** @var ArrayCollection $workflowCollection */
161 4
                $workflowCollection = $instances[strtolower($stat)]->get('workflow_instances');
0 ignored issues
show
Bug introduced by
The method get() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

161
                /** @scrutinizer ignore-call */ 
162
                $workflowCollection = $instances[strtolower($stat)]->get('workflow_instances');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
162 4
            if (!empty($workflowCollection)) {
163 3
                foreach ($workflowCollection as $instance) {
164 3
                    $this->getCurrentClass()->getWorkflowInstancesDetails($instance);
165
                }
166
            }
167
        }
168 4
        if (!is_null($status)) {
169 2
            return $instances->get(strtolower($status))->get('workflow_instances');
170
        }
171
172 2
        return $instances;
173
    }
174
175
    /**
176
     * {@inheritdoc}
177
     */
178 3
    public function getWorkflowInstancesDetails(WorkflowInstance $workflowInstance)
179
    {
180 3
        return $this->_dispatch(new Command\GetWorkflowInstancesDetailCommand($workflowInstance));
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186 8
    public function tubeExists($name)
187
    {
188 8
        return $this->_dispatch(new Command\TubeExistsCommand($name));
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194 1
    public function listTubes()
195
    {
196 1
        return $this->_dispatch(new Command\ListTubesCommand());
197
    }
198
199
    /**
200
     * {@inheritdoc}
201
     */
202 1
    public function peek()
203
    {
204 1
        $response = $this->_dispatch(new Command\PeekCommand());
205
206 1
        return $response;
207
    }
208
209
    /**
210
     * {@inheritdoc}
211
     */
212 5
    public function put(Workflow $workflow)
213
    {
214 5
        $response = $this->_dispatch(new Command\PutCommand($workflow));
215
216 5
        return $response['workflow-instance-id'];
217
    }
218
219
    /**
220
     * {@inheritdoc}
221
     */
222 1
    public function statsTube(Tube $tube)
223
    {
224 1
        return $this->_dispatch(new Command\StatsTubeCommand($tube));
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_dispatch(...tatsTubeCommand($tube)) returns the type array which is incompatible with the return type mandated by Pheanstalk\PheanstalkInterface::statsTube() of object.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
225
    }
226
227
    /**
228
     * {@inheritdoc}
229
     */
230 1
    public function stats()
231
    {
232 1
        return $this->_dispatch(new Command\StatsCommand());
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_dispatch(...Command\StatsCommand()) returns the type array which is incompatible with the return type mandated by Pheanstalk\PheanstalkInterface::stats() of object.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
233
    }
234
235
    // ----------------------------------------
236
237
    /**
238
     * Dispatches the specified command to the connection object.
239
     *
240
     * If a SocketException occurs, the connection is reset, and the command is
241
     * re-attempted once.
242
     *
243
     * @throws Exception\ClientException
244
     * @param Command $command
245
     *
246
     * @return mixed
247
     */
248 17
    private function _dispatch($command)
249
    {
250 17
        return $this->connection->dispatchCommand($command);
251
    }
252
253
    /**
254
     * {@inheritdoc}
255
     */
256 5
    public function create(Workflow $workflow, $force = false): Workflow
257
    {
258
        try {
259 5
            $tubes = [];
260
            /** @var Job $job */
261 5
            foreach ($workflow->getJobs() as $job) {
262
                /** @var Task $task */
263 5
                foreach ($job->getTasks() as $task) {
264 5
                    $tubes = array_merge($tubes, [$task->getQueue()]);
265
                }
266
            }
267 5
            foreach ($tubes as $tube) {
268 5
                if (!$this->getCurrentClass()->tubeExists($tube)) {
269 1
                    $this->getCurrentClass()->createTube(new Tube($tube, 1));
270
                };
271
            }
272 5
            $workflow = $this->_dispatch(new Command\CreateCommand($workflow));
273 2
        } catch (ServerDuplicateEntryException $e) {
274 2
            if ($force) {
275 2
                $workflows = $this->_dispatch(new Command\ListWorkflowsCommand());
276
                $workflowToDelete = $workflows->filter(function(Workflow $listedWorkflow) use ($workflow) {
277 2
                    return $listedWorkflow->getName() === $workflow->getName()
278 2
                        && $listedWorkflow->getGroup() === $workflow->getGroup();
279 2
                })->first();
280 2
                $this->getCurrentClass()->delete($workflowToDelete);
281
282 2
                return $this->getCurrentClass()->create($workflow);
283
            }
284 1
            throw $e;
285
        }
286
287 5
        return $workflow;
288
    }
289
290
    /**
291
     * {@inheritdoc}
292
     */
293 1
    public function update(Workflow $workflow): Workflow
294
    {
295 1
        $workflow = $this->_dispatch(new Command\UpdateCommand($workflow));
296 1
        return $workflow;
297
    }
298
299
    /**
300
     * {@inheritdoc}
301
     */
302 1
    public function createSchedule(Schedule $schedule)
303
    {
304 1
        $workflowSchedule = $this->_dispatch(
305 1
            new Command\CreateScheduleCommand($schedule)
306
        );
307 1
        return $workflowSchedule;
308
    }
309
310
    /**
311
     * {@inheritdoc}
312
     */
313 4
    public function createTask(string $name, string $group, string $path, $queue = 'default', $useAgent = false, $user = null, $host = null, $comment = null): Workflow
314
    {
315 4
        $task = new Task($path, $queue, $useAgent, $user, $host);
316 4
        $job = new Job(new ArrayCollection([$task]));
317 4
        $workflow = new Workflow($name, $group, new ArrayCollection([$job]), $comment);
318
319 4
        return $this->getCurrentClass()->create($workflow, true);
320
    }
321
322
    /**
323
     * {@inheritDoc}
324
     */
325 1
    public function createTube(Tube $tube): Tube
326
    {
327 1
        return $this->_dispatch(new Command\CreateTubeCommand($tube));
328
    }
329
330
    /**
331
     * {@inheritdoc}
332
     */
333 1
    public function updateTube(Tube $tube): Tube
334
    {
335 1
        return $this->_dispatch(new Command\UpdateTubeCommand($tube));
336
    }
337
338
    /**
339
     * {@inheritdoc}
340
     */
341 1
    public function cancel(WorkflowInstance $workflowInstance)
342
    {
343 1
        return $this->_dispatch(new Command\CancelCommand($workflowInstance));
344
    }
345
346
    /**
347
     * {@inheritdoc}
348
     */
349 1
    public function kill(WorkflowInstance $workflowInstance, TaskInstance $taskInstance)
350
    {
351 1
        return $this->_dispatch(new Command\KillCommand($workflowInstance, $taskInstance));
352
    }
353
}
354