BackgroundTask::startProcess()   C
last analyzed

Complexity

Conditions 8
Paths 41

Size

Total Lines 38
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 38
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 21
nc 41
nop 1
1
<?php
2
3
/**
4
 * This file is part of Bldr.io
5
 *
6
 * (c) Aaron Scherer <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE
10
 */
11
12
namespace Bldr\Block\Execute\Task;
13
14
use Bldr\Block\Execute\Service\BackgroundService;
15
use Bldr\Block\Core\Task\AbstractTask;
16
use Bldr\Exception\TaskRuntimeException;
17
use Symfony\Component\Console\Output\OutputInterface;
18
use Symfony\Component\Console\Output\StreamOutput;
19
use Symfony\Component\Process\ProcessBuilder;
20
21
/**
22
 * @author Aaron Scherer <[email protected]>
23
 */
24
class BackgroundTask extends AbstractTask
25
{
26
    /**
27
     * @var BackgroundService $background
28
     */
29
    private $background;
30
31
    /**
32
     * @param BackgroundService $background
33
     */
34
    public function __construct(BackgroundService $background)
35
    {
36
        $this->background = $background;
37
    }
38
39
    /**
40
     * Configures the Task
41
     */
42
    public function configure()
43
    {
44
        $this->setName('background')
45
            ->setDescription('Executes the given options using the executable in the background')
46
            ->addParameter('executable', true, 'Executable to run')
47
            ->addParameter('arguments', false, 'Arguments to run on the executable', [])
48
            ->addParameter('cwd', false, 'Sets the working directory for the executable')
49
            ->addParameter('output', false, 'Sets the location to output to')
50
            ->addParameter('append', false, 'If output is set, should it append?', false)
51
            ->addParameter('kill', false, 'Are we killing the task?', false)
52
        ;
53
    }
54
55
    /**
56
     * {@inheritDoc}
57
     */
58
    public function run(OutputInterface $output)
59
    {
60
        if ($this->getParameter('kill') === false) {
61
            $this->startProcess($output);
62
63
            return true;
64
        }
65
66
        $this->endProcess();
67
68
        return true;
69
    }
70
71
    /**
72
     * Creates the given process
73
     *
74
     * @throws \Exception
75
     */
76
    private function startProcess(OutputInterface $output)
77
    {
78
        $arguments = $this->resolveProcessArgs();
79
        $name = sha1(serialize($arguments));
80
        if ($this->background->hasProcess($name)) {
81
            throw new \RuntimeException("Service is already running.");
82
        }
83
84
        $builder = new ProcessBuilder($arguments);
85
86
        if ($this->hasParameter('cwd')) {
87
            $builder->setWorkingDirectory($this->getParameter('cwd'));
0 ignored issues
show
Bug introduced by
It seems like $this->getParameter('cwd') targeting Bldr\Block\Core\Task\AbstractTask::getParameter() can also be of type array; however, Symfony\Component\Proces...::setWorkingDirectory() does only seem to accept null|string, maybe add an additional type check?

This check looks at variables that 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...
88
        }
89
90
        $process = $builder->getProcess();
91
92
        if ($output->getVerbosity() === OutputInterface::VERBOSITY_VERBOSE) {
93
            $output->writeln($process->getCommandLine());
94
        }
95
96
        if ($this->hasParameter('output')) {
97
            $append = $this->hasParameter('append') && $this->getParameter('append') ? 'a' : 'w';
98
            $stream = fopen($this->getParameter('output'), $append);
99
            $output = new StreamOutput($stream, StreamOutput::VERBOSITY_NORMAL, true);
100
        }
101
102
        $process->start(
103
            function ($type, $buffer) use ($output) {
104
                $output->write($buffer);
105
            }
106
        );
107
108
        $this->background->addProcess($name, $process);
109
110
        if (!in_array($process->getExitCode(), $this->getParameter('successCodes'))) {
111
            throw new TaskRuntimeException($this->getName(), $process->getErrorOutput());
112
        }
113
    }
114
115
    /**
116
     * Kills the given process
117
     */
118
    private function endProcess()
119
    {
120
        $arguments = $this->resolveProcessArgs();
121
        $name = sha1(serialize($arguments));
122
        if ($this->background->hasProcess($name)) {
123
            $this->background->getProcess($name)->stop();
124
            $this->background->removeProcess($name);
125
        }
126
    }
127
128
    /**
129
     * Resolves the Executable and Arguments and returns a merged array
130
     *
131
     * @return array
132
     */
133
    protected function resolveProcessArgs()
134
    {
135
        return array_merge(
136
            [$this->getParameter('executable')],
137
            $this->getParameter('arguments')
138
        );
139
    }
140
}
141