Completed
Push — master ( e54759...0c780c )
by Valentin
03:37
created

Pheanstalk   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 298
Duplicated Lines 0 %

Test Coverage

Coverage 35.16%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 38
eloc 73
c 2
b 0
f 0
dl 0
loc 298
ccs 32
cts 91
cp 0.3516
rs 9.36

26 Methods

Rating   Name   Duplication   Size   Complexity  
A put() 0 4 1
A statsJob() 0 3 1
A getWorkflowInstances() 0 18 5
A workflowExists() 0 6 2
A createTask() 0 7 1
A tubeExists() 0 3 1
A setConnection() 0 5 1
A createSchedule() 0 6 1
A setCurrentClass() 0 4 1
A createTube() 0 3 1
A peek() 0 5 1
A _dispatch() 0 3 1
A getWorkflowInstancesDetails() 0 3 1
A getCurrentClass() 0 3 1
A getWorkflow() 0 3 1
A cancel() 0 3 1
A update() 0 4 1
A listTubes() 0 3 1
A kill() 0 3 1
A delete() 0 5 1
A stats() 0 3 1
B create() 0 32 8
A updateTube() 0 3 1
A statsTube() 0 3 1
A __construct() 0 3 1
A getConnection() 0 3 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;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Pheanstalk\Job. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
18
use Pheanstalk\Structure\Task;
19
use Pheanstalk\Structure\TaskInstance;
20
use Pheanstalk\Structure\TimeSchedule;
21
use Pheanstalk\Structure\Tube;
22
use Pheanstalk\Structure\Workflow;
23
use Pheanstalk\Structure\WorkflowInstance;
24
25
/**
26
 * Pheanstalk is a PHP client for the beanstalkd workqueue.
27
 *
28
 * The Pheanstalk class is a simple facade for the various underlying components.
29
 *
30
 * @see http://github.com/kr/beanstalkd
31
 * @see http://xph.us/software/beanstalkd/
32
 *
33
 * @author  Paul Annesley
34
 * @package Pheanstalk
35
 * @license http://www.opensource.org/licenses/mit-license.php
36
 */
37
class Pheanstalk implements PheanstalkInterface
38
{
39
    const VERSION = '3.2.1';
40
41
    private $_connection;
42
    private $_using = PheanstalkInterface::DEFAULT_TUBE;
0 ignored issues
show
introduced by
The private property $_using is not used, and could be removed.
Loading history...
43
    private $_watching = array(PheanstalkInterface::DEFAULT_TUBE => true);
0 ignored issues
show
introduced by
The private property $_watching is not used, and could be removed.
Loading history...
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
44
45
    /** @var $currentClass PheanstalkInterface */
0 ignored issues
show
Documentation Bug introduced by
The doc comment $currentClass at position 0 could not be parsed: Unknown type name '$currentClass' at position 0 in $currentClass.
Loading history...
46
    private $currentClass;
47
48
    /**
49
     * @param string $host
50
     * @param string $user
51
     * @param string $password
52
     * @param int    $port
53
     * @param int    $connectTimeout
54
     * @param bool   $connectPersistent
55
     */
56 3
    public function __construct($host, $user = null, $password = null, $port = PheanstalkInterface::DEFAULT_PORT, $connectTimeout = null, $connectPersistent = false)
57
    {
58 3
        $this->setConnection(new Connection($host, $user, $password, $port, $connectTimeout, $connectPersistent));
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64 3
    public function setConnection(Connection $connection)
65
    {
66 3
        $this->_connection = $connection;
67
68 3
        return $this;
69
    }
70
71
    /**
72
     * {@inheritdoc}
73
     */
74 2
    public function getConnection()
75
    {
76 2
        return $this->_connection;
77
    }
78
79
    /**
80
     * @return PheanstalkInterface
81
     */
82 1
    public function getCurrentClass(): PheanstalkInterface
83
    {
84 1
        return $this->currentClass ?? $this;
85
    }
86
87
    /**
88
     * @param PheanstalkInterface $currentClass
89
     *
90
     * @return Pheanstalk
91
     */
92
    public function setCurrentClass(PheanstalkInterface $currentClass): PheanstalkInterface
93
    {
94
        $this->currentClass = $currentClass;
95
        return $this;
96
    }
97
98
    // ----------------------------------------
99
100
    /**
101
     * {@inheritdoc}
102
     */
103 1
    public function delete(Workflow $workflow)
104
    {
105 1
        $this->_dispatch(new Command\DeleteCommand($workflow));
106
107 1
        return $this;
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113 1
    public function workflowExists($name)
114
    {
115 1
        $workflow = $this->_dispatch(new Command\WorkflowExistsCommand($name));
116
        if ($workflow instanceof Workflow)
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
117
            return $this->getCurrentClass()->getWorkflow($workflow);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getCurrent...>getWorkflow($workflow) returns the type Pheanstalk\Response which is incompatible with the return type mandated by Pheanstalk\PheanstalkInterface::workflowExists() of Pheanstalk\Structure\Workflow|boolean.

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...
118
        return false;
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function getWorkflow(Workflow $workflow)
125
    {
126
        return $this->_dispatch(new Command\GetWorkflowCommand($workflow));
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_dispatch(...flowCommand($workflow)) returns the type Pheanstalk\Response which is incompatible with the return type mandated by Pheanstalk\PheanstalkInterface::getWorkflow() of Pheanstalk\Structure\Workflow|boolean.

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...
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    public function getWorkflowInstances(?Workflow $workflow, string $status = null)
133
    {
134
        $status = empty($status) ? GetWorkflowInstancesDetailCommand::FILTERS : [$status];
135
        $instances = new ArrayCollection([]);
136
        foreach($status as $stat) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after FOREACH keyword; 0 found
Loading history...
137
            $instances[strtolower($stat)] = $this->_dispatch(new Command\GetWorkflowInstancesCommand($workflow, $stat));
138
//            if ($stat === GetWorkflowInstancesCommand::FILTER_EXECUTING) {
139
                /** @var ArrayCollection $workflowCollection */
140
                $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

140
                /** @scrutinizer ignore-call */ 
141
                $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...
141
                if (!empty($workflowCollection)) {
142
                    foreach($workflowCollection as $instance) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after FOREACH keyword; 0 found
Loading history...
143
                        $this->getCurrentClass()->getWorkflowInstancesDetails($instance);
144
                    }
145
                }
146
//            }
147
        }
148
149
        return $instances;
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    public function getWorkflowInstancesDetails(WorkflowInstance $workflowInstance)
156
    {
157
        return $this->_dispatch(new Command\GetWorkflowInstancesDetailCommand($workflowInstance));
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_dispatch(...and($workflowInstance)) returns the type Pheanstalk\Response which is incompatible with the return type mandated by Pheanstalk\PheanstalkInt...kflowInstancesDetails() of Pheanstalk\Structure\WorkflowInstance|false.

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...
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163 1
    public function tubeExists($name)
164
    {
165 1
        return $this->_dispatch(new Command\TubeExistsCommand($name));
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_dispatch(...beExistsCommand($name)) returns the type Pheanstalk\Response which is incompatible with the return type mandated by Pheanstalk\PheanstalkInterface::tubeExists() of Pheanstalk\Structure\Tube|boolean.

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...
166
    }
167
168
    /**
169
     * {@inheritdoc}
170
     */
171
    public function listTubes()
172
    {
173
        return $this->_dispatch(new Command\ListTubesCommand());
174
    }
175
176
    /**
177
     * {@inheritdoc}
178
     */
179
    public function peek()
180
    {
181
        $response = $this->_dispatch(new Command\PeekCommand());
182
183
        return $response;
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189
    public function put(Workflow $workflow) {
190
        $response = $this->_dispatch(new Command\PutCommand($workflow));
191
192
        return $response['workflow-instance-id'];
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198
    public function statsJob($job)
199
    {
200
        return $this->_dispatch(new Command\StatsJobCommand($job));
0 ignored issues
show
Bug introduced by
The type Pheanstalk\Command\StatsJobCommand 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...
201
    }
202
203
    /**
204
     * {@inheritdoc}
205
     */
206
    public function statsTube($tube)
207
    {
208
        return $this->_dispatch(new Command\StatsTubeCommand($tube));
209
    }
210
211
    /**
212
     * {@inheritdoc}
213
     */
214
    public function stats()
215
    {
216
        return $this->_dispatch(new Command\StatsCommand());
217
    }
218
219
    // ----------------------------------------
220
221
    /**
222
     * Dispatches the specified command to the connection object.
223
     *
224
     * If a SocketException occurs, the connection is reset, and the command is
225
     * re-attempted once.
226
     *
227
     * @param Command $command
228
     *
229
     * @return Response
230
     */
231 1
    private function _dispatch($command)
232
    {
233 1
        return $this->_connection->dispatchCommand($command);
234
    }
235
236
    /**
237
     * {@inheritdoc}
238
     */
239 1
    public function create(Workflow $workflow, $force = false): Workflow
240
    {
241
        try{
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after TRY keyword; 0 found
Loading history...
242 1
            $tubes = [];
243
            /** @var Job $job */
244 1
            foreach($workflow->getJobs() as $job) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after FOREACH keyword; 0 found
Loading history...
245
                /** @var Task $task */
246 1
                foreach ($job->getTasks() as $task) {
247 1
                    $tubes = array_merge($tubes, [$task->getQueue()]);
248
                }
249
            }
250 1
            foreach($tubes as $tube) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after FOREACH keyword; 0 found
Loading history...
251 1
                if (!$this->getCurrentClass()->tubeExists($tube)) {
252
                    $this->getCurrentClass()->createTube(new Tube($tube, 1));
253
                };
254
            }
255 1
            $workflow = $this->_dispatch(new Command\CreateCommand($workflow));
256
        } catch(ServerDuplicateEntryException $e) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after CATCH keyword; 0 found
Loading history...
257
            if ($force) {
258
                $workflows = $this->_dispatch(new Command\ListWorkflowsCommand());
259
                $workflowToDelete = $workflows->filter(function(Workflow $listedWorkflow) use ($workflow) {
1 ignored issue
show
Bug introduced by
The method filter() does not exist on Pheanstalk\Response. ( Ignorable by Annotation )

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

259
                $workflowToDelete = $workflows->/** @scrutinizer ignore-call */ filter(function(Workflow $listedWorkflow) use ($workflow) {

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...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
260
                    return $listedWorkflow->getName() === $workflow->getName()
0 ignored issues
show
Bug introduced by
The method getName() does not exist on Pheanstalk\Response. ( Ignorable by Annotation )

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

260
                    return $listedWorkflow->getName() === $workflow->/** @scrutinizer ignore-call */ getName()

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...
261
                        && $listedWorkflow->getGroup() === $workflow->getGroup();
0 ignored issues
show
Bug introduced by
The method getGroup() does not exist on Pheanstalk\Response. ( Ignorable by Annotation )

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

261
                        && $listedWorkflow->getGroup() === $workflow->/** @scrutinizer ignore-call */ getGroup();

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...
262
                })->first();
263
                $this->getCurrentClass()->delete($workflowToDelete);
264
265
                return $this->getCurrentClass()->create($workflow);
0 ignored issues
show
Bug introduced by
It seems like $workflow can also be of type Pheanstalk\Response; however, parameter $workflow of Pheanstalk\Pheanstalk::create() does only seem to accept Pheanstalk\Structure\Workflow, maybe add an additional type check? ( Ignorable by Annotation )

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

265
                return $this->getCurrentClass()->create(/** @scrutinizer ignore-type */ $workflow);
Loading history...
266
            }
267
            throw $e;
268
        }
269
270 1
        return $workflow;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $workflow returns the type Pheanstalk\Response which is incompatible with the type-hinted return Pheanstalk\Structure\Workflow.
Loading history...
271
    }
272
273
    /**
274
     * {@inheritdoc}
275
     */
276
    public function update(Workflow $workflow): Workflow
277
    {
278
        $workflow = $this->_dispatch(new Command\UpdateCommand($workflow));
279
        return $workflow;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $workflow returns the type Pheanstalk\Response which is incompatible with the type-hinted return Pheanstalk\Structure\Workflow.
Loading history...
280
    }
281
282
    /**
283
     * {@inheritdoc}
284
     */
285
    public function createSchedule(Workflow $workflow, TimeSchedule $schedule, $onFailure = CreateScheduleCommand::FAILURE_TYPE_CONTINUE, $active = true, $comment = null)
286
    {
287
        $workflowSchedule = $this->_dispatch(
288
            new Command\CreateScheduleCommand($workflow, $schedule, $onFailure, $active, $comment)
289
        );
290
        return $workflowSchedule;
291
    }
292
293
    /**
294
     * {@inheritdoc}
295
     */
296 1
    public function createTask(string $name, string $group, string $path, $queue = 'default', $useAgent = false, $user = null, $host = null, $comment = null): Workflow
297
    {
298 1
        $task = new Task($path, $queue, $useAgent, $user, $host);
299 1
        $job = new Job(new ArrayCollection([$task]));
300 1
        $workflow = new Workflow($name, $group, new ArrayCollection([$job]), $comment);
301
302 1
        return $this->getCurrentClass()->create($workflow, true);
303
    }
304
305
    /**
306
     * {@inheritDoc}
307
     */
308
    public function createTube(Tube $tube): Tube
309
    {
310
        return $this->_dispatch(new Command\CreateTubeCommand($tube));
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_dispatch(...eateTubeCommand($tube)) returns the type Pheanstalk\Response which is incompatible with the type-hinted return Pheanstalk\Structure\Tube.
Loading history...
311
    }
312
313
    /**
314
     * {@inheritdoc}
315
     */
316
    public function updateTube(Tube $tube): Tube
317
    {
318
        return $this->_dispatch(new Command\UpdateTubeCommand($tube));
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_dispatch(...dateTubeCommand($tube)) returns the type Pheanstalk\Response which is incompatible with the type-hinted return Pheanstalk\Structure\Tube.
Loading history...
319
    }
320
321
    /**
322
     * {@inheritdoc}
323
     */
324
    public function cancel(WorkflowInstance $workflowInstance)
325
    {
326
        return $this->_dispatch(new Command\CancelCommand($workflowInstance));
327
    }
328
329
    /**
330
     * {@inheritdoc}
331
     */
332
    public function kill(WorkflowInstance $workflowInstance, TaskInstance $taskInstance)
333
    {
334
        return $this->_dispatch(new Command\KillCommand($workflowInstance, $taskInstance));
335
    }
336
}
337