configureOptionResolver()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 0
loc 9
ccs 7
cts 7
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Darkilliant\ProcessBundle\Step;
6
7
use Darkilliant\ProcessBundle\State\ProcessState;
8
use Symfony\Component\Console\ConsoleEvents;
9
use Symfony\Component\Console\Event\ConsoleEvent;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
12
use Symfony\Component\OptionsResolver\OptionsResolver;
13
use Symfony\Component\Process\PhpExecutableFinder;
14
use Symfony\Component\Process\ProcessBuilder;
15
16
class LaunchIsolateProcessStep extends AbstractConfigurableStep implements EventSubscriberInterface
17
{
18
    private $processCollection = [];
19
    private $verbosity;
20
    private $environment;
21
22 8
    public function __construct($environment)
23
    {
24 8
        $this->environment = $environment;
25 8
    }
26
27
    /**
28
     * @codeCoverageIgnore
29
     */
30
    public static function getSubscribedEvents()
31
    {
32
        return [
33
            ConsoleEvents::COMMAND => ['onCommand', 255],
34
        ];
35
    }
36
37 6
    public function onCommand(ConsoleEvent $event)
38
    {
39 6
        $this->verbosity = $event->getOutput()->getVerbosity();
40 6
    }
41
42 1
    public function configureOptionResolver(OptionsResolver $resolver): OptionsResolver
43
    {
44 1
        $resolver->setRequired(['process_name', 'max_concurency', 'context', 'data', 'timeout', 'bin_console_path']);
45 1
        $resolver->setDefault('context', []);
46 1
        $resolver->setDefault('data', []);
47 1
        $resolver->setDefault('max_concurency', 1);
48 1
        $resolver->setDefault('timeout', 60 * 20);
49
50 1
        return parent::configureOptionResolver($resolver);
51
    }
52
53 7
    public function execute(ProcessState $state)
54
    {
55 7
        $processName = $state->getOptions()['process_name'];
56 7
        $maxConcurency = $state->getOptions()['max_concurency'];
57 7
        $context = $state->getOptions()['context'];
58 7
        $data = $state->getOptions()['data'];
59
60 7
        $processBuilder = $this->getProcessBuilder();
61 7
        $phpFinder = $this->getPhpExecutableFinder();
62
63
        $arguments = [
64 7
            $phpFinder->find(),
65 7
            $state->getOptions()['bin_console_path'],
66 7
            'process:run',
67 7
            '--env='.$this->environment,
68 7
            '--input-from-stdin',
69 7
            '--force-color',
70
        ];
71
72 7
        $verbosityParameter = $this->getVerbosityParameter();
73 7
        if ($verbosityParameter) {
74 5
            $arguments[] = $verbosityParameter;
75
        }
76
77 7
        foreach ($context as $key => $value) {
78 7
            $arguments[] = sprintf('--context=%s=%s', $key, $value);
79
        }
80
81 7
        if ($state->isDryRun()) {
82 1
            $arguments[] = '--dry-run';
83
        }
84
85 7
        $arguments[] = '--';
86 7
        $arguments[] = $processName;
87 7
        $processBuilder->setArguments($arguments);
88
89 7
        $processBuilder->setInput(json_encode($data));
90 7
        $processBuilder->setTimeout($state->getOptions()['timeout']);
91 7
        $process = $processBuilder->getProcess();
92
93 7
        $this->processCollection[] = $process;
94
95 7
        if (count($this->processCollection) >= $maxConcurency) {
96 7
            $this->wait();
97
        }
98 7
    }
99
100 7
    public function finalize(ProcessState $state)
101
    {
102 7
        $this->wait();
103 7
    }
104
105
    /**
106
     * @codeCoverageIgnore
107
     */
108
    protected function getProcessBuilder(): ProcessBuilder
109
    {
110
        return new ProcessBuilder();
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Process\ProcessBuilder has been deprecated: since version 3.4, to be removed in 4.0. Use the Process class instead. ( Ignorable by Annotation )

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

110
        return /** @scrutinizer ignore-deprecated */ new ProcessBuilder();
Loading history...
111
    }
112
113
    /**
114
     * @codeCoverageIgnore
115
     */
116
    protected function getPhpExecutableFinder(): PhpExecutableFinder
117
    {
118
        return new PhpExecutableFinder();
119
    }
120
121 7
    protected function getVerbosityParameter()
122
    {
123 7
        if (!$this->verbosity) {
124 1
            return '-vv';
125
        }
126 6
        switch ($this->verbosity) {
127 6
            case OutputInterface::VERBOSITY_QUIET:
128 1
                return '-q';
129 5
            case OutputInterface::VERBOSITY_VERBOSE:
130 1
                return '-v';
131 4
            case OutputInterface::VERBOSITY_VERY_VERBOSE:
132 1
                return '-vv';
133 3
            case OutputInterface::VERBOSITY_DEBUG:
134 1
                return '-vvv';
135
        }
136
137 2
        return null;
138
    }
139
140 7
    private function wait()
141
    {
142 7
        while (count($this->processCollection) > 0) {
143 7
            foreach ($this->processCollection as $i => $process) {
144 7
                if (!$process->isStarted()) {
145 7
                    echo "Process starts\n";
146
147 7
                    $process->start();
148
149 7
                    continue;
150
                }
151
152 7
                echo $process->getIncrementalOutput();
153 7
                echo $process->getIncrementalErrorOutput();
154
155 7
                if (!$process->isRunning()) {
156 7
                    echo "Process stopped\n";
157
158 7
                    unset($this->processCollection[$i]);
159
                }
160
            }
161
162 7
            sleep(1);
163
        }
164 7
        $this->processCollection = [];
165 7
    }
166
}
167