Completed
Push — master ( 84b8e9...9ac9a8 )
by Valentin
03:43
created

Pheanstalk::kill()   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 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 2
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\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
40
    /** @var Connection $connection */
41
    private $connection;
42
43
    /** @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...
44
    private $currentClass;
45
46
    /**
47
     * @param string $host
48
     * @param string $user
49
     * @param string $password
50
     * @param int    $port
51
     * @param int    $connectTimeout
52
     * @param bool   $connectPersistent
53
     */
54 20
    public function __construct($host, $user = null, $password = null, $port = PheanstalkInterface::DEFAULT_PORT, $connectTimeout = null, $connectPersistent = false)
55
    {
56 20
        $this->setConnection(new Connection($host, $user, $password, $port, $connectTimeout, $connectPersistent));
57
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 20
    public function setConnection(Connection $connection)
63
    {
64 20
        $this->connection = $connection;
65
66 20
        return $this;
67
    }
68
69
    /**
70
     * {@inheritdoc}
71
     */
72 2
    public function getConnection()
73
    {
74 2
        return $this->connection;
75
    }
76
77
    /**
78
     * @return PheanstalkInterface
79
     */
80 13
    public function getCurrentClass(): PheanstalkInterface
81
    {
82 13
        return $this->currentClass ?? $this;
83
    }
84
85
    /**
86
     * @param PheanstalkInterface $currentClass
87
     *
88
     * @return Pheanstalk
89
     */
90 1
    public function setCurrentClass(PheanstalkInterface $currentClass): PheanstalkInterface
91
    {
92 1
        $this->currentClass = $currentClass;
93 1
        return $this;
94
    }
95
96
    // ----------------------------------------
97
98
    /**
99
     * {@inheritdoc}
100
     */
101 5
    public function delete(Workflow $workflow)
102
    {
103 5
        return $this->_dispatch(new Command\DeleteCommand($workflow));
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109 1
    public function deleteTube(Tube $tube)
110
    {
111 1
        return $this->_dispatch(new Command\DeleteTubeCommand($tube));
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117 8
    public function workflowExists($name)
118
    {
119 8
        $workflow = $this->_dispatch(new Command\WorkflowExistsCommand($name));
120 7
        if ($workflow instanceof Workflow) {
121 7
            return $this->getCurrentClass()->getWorkflow($workflow);
122
        }
123 1
        return false;
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129 7
    public function getWorkflow(Workflow $workflow)
130
    {
131 7
        return $this->_dispatch(new Command\GetWorkflowCommand($workflow));
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137 4
    public function getWorkflowInstances(?Workflow $workflow, string $status = null)
138
    {
139 4
        $paramsStatus = empty($status) ? GetWorkflowInstancesDetailCommand::FILTERS : [$status];
140 4
        $instances = new ArrayCollection([]);
141 4
        foreach ($paramsStatus as $stat) {
142 4
            $instances[strtolower($stat)] = $this->_dispatch(new Command\GetWorkflowInstancesCommand($workflow, $stat));
143
                /** @var ArrayCollection $workflowCollection */
144 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

144
                /** @scrutinizer ignore-call */ 
145
                $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...
145 4
            if (!empty($workflowCollection)) {
146 3
                foreach ($workflowCollection as $instance) {
147 3
                    $this->getCurrentClass()->getWorkflowInstancesDetails($instance);
148
                }
149
            }
150
        }
151 4
        if (!is_null($status)) {
152 2
            return $instances->get(strtolower($status))->get('workflow_instances');
153
        }
154
155 2
        return $instances;
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161 3
    public function getWorkflowInstancesDetails(WorkflowInstance $workflowInstance)
162
    {
163 3
        return $this->_dispatch(new Command\GetWorkflowInstancesDetailCommand($workflowInstance));
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169 8
    public function tubeExists($name)
170
    {
171 8
        return $this->_dispatch(new Command\TubeExistsCommand($name));
172
    }
173
174
    /**
175
     * {@inheritdoc}
176
     */
177 1
    public function listTubes()
178
    {
179 1
        return $this->_dispatch(new Command\ListTubesCommand());
180
    }
181
182
    /**
183
     * {@inheritdoc}
184
     */
185 1
    public function peek()
186
    {
187 1
        $response = $this->_dispatch(new Command\PeekCommand());
188
189 1
        return $response;
190
    }
191
192
    /**
193
     * {@inheritdoc}
194
     */
195 5
    public function put(Workflow $workflow)
196
    {
197 5
        $response = $this->_dispatch(new Command\PutCommand($workflow));
198
199 5
        return $response['workflow-instance-id'];
200
    }
201
202
    /**
203
     * {@inheritdoc}
204
     */
205 1
    public function statsTube(Tube $tube)
206
    {
207 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...
208
    }
209
210
    /**
211
     * {@inheritdoc}
212
     */
213 1
    public function stats()
214
    {
215 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...
216
    }
217
218
    // ----------------------------------------
219
220
    /**
221
     * Dispatches the specified command to the connection object.
222
     *
223
     * If a SocketException occurs, the connection is reset, and the command is
224
     * re-attempted once.
225
     *
226
     * @throws Exception\ClientException
227
     * @param Command $command
228
     *
229
     * @return mixed
230
     */
231 17
    private function _dispatch($command)
232
    {
233 17
        return $this->connection->dispatchCommand($command);
234
    }
235
236
    /**
237
     * {@inheritdoc}
238
     */
239 5
    public function create(Workflow $workflow, $force = false): Workflow
240
    {
241
        try {
242 5
            $tubes = [];
243
            /** @var Job $job */
244 5
            foreach ($workflow->getJobs() as $job) {
245
                /** @var Task $task */
246 5
                foreach ($job->getTasks() as $task) {
247 5
                    $tubes = array_merge($tubes, [$task->getQueue()]);
248
                }
249
            }
250 5
            foreach ($tubes as $tube) {
251 5
                if (!$this->getCurrentClass()->tubeExists($tube)) {
252 1
                    $this->getCurrentClass()->createTube(new Tube($tube, 1));
253
                };
254
            }
255 5
            $workflow = $this->_dispatch(new Command\CreateCommand($workflow));
256 2
        } catch (ServerDuplicateEntryException $e) {
257 2
            if ($force) {
258 2
                $workflows = $this->_dispatch(new Command\ListWorkflowsCommand());
259
                $workflowToDelete = $workflows->filter(function(Workflow $listedWorkflow) use ($workflow) {
1 ignored issue
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
260 2
                    return $listedWorkflow->getName() === $workflow->getName()
261 2
                        && $listedWorkflow->getGroup() === $workflow->getGroup();
262 2
                })->first();
263 2
                $this->getCurrentClass()->delete($workflowToDelete);
264
265 2
                return $this->getCurrentClass()->create($workflow);
266
            }
267 1
            throw $e;
268
        }
269
270 5
        return $workflow;
271
    }
272
273
    /**
274
     * {@inheritdoc}
275
     */
276 1
    public function update(Workflow $workflow): Workflow
277
    {
278 1
        $workflow = $this->_dispatch(new Command\UpdateCommand($workflow));
279 1
        return $workflow;
280
    }
281
282
    /**
283
     * {@inheritdoc}
284
     */
285 1
    public function createSchedule(Workflow $workflow, TimeSchedule $schedule, $onFailure = CreateScheduleCommand::FAILURE_TYPE_CONTINUE, $active = true, $comment = null)
286
    {
287 1
        $workflowSchedule = $this->_dispatch(
288 1
            new Command\CreateScheduleCommand($workflow, $schedule, $onFailure, $active, $comment)
289
        );
290 1
        return $workflowSchedule;
291
    }
292
293
    /**
294
     * {@inheritdoc}
295
     */
296 4
    public function createTask(string $name, string $group, string $path, $queue = 'default', $useAgent = false, $user = null, $host = null, $comment = null): Workflow
297
    {
298 4
        $task = new Task($path, $queue, $useAgent, $user, $host);
299 4
        $job = new Job(new ArrayCollection([$task]));
300 4
        $workflow = new Workflow($name, $group, new ArrayCollection([$job]), $comment);
301
302 4
        return $this->getCurrentClass()->create($workflow, true);
303
    }
304
305
    /**
306
     * {@inheritDoc}
307
     */
308 1
    public function createTube(Tube $tube): Tube
309
    {
310 1
        return $this->_dispatch(new Command\CreateTubeCommand($tube));
311
    }
312
313
    /**
314
     * {@inheritdoc}
315
     */
316 1
    public function updateTube(Tube $tube): Tube
317
    {
318 1
        return $this->_dispatch(new Command\UpdateTubeCommand($tube));
319
    }
320
321
    /**
322
     * {@inheritdoc}
323
     */
324 1
    public function cancel(WorkflowInstance $workflowInstance)
325
    {
326 1
        return $this->_dispatch(new Command\CancelCommand($workflowInstance));
327
    }
328
329
    /**
330
     * {@inheritdoc}
331
     */
332 1
    public function kill(WorkflowInstance $workflowInstance, TaskInstance $taskInstance)
333
    {
334 1
        return $this->_dispatch(new Command\KillCommand($workflowInstance, $taskInstance));
335
    }
336
}
337