ProcessExecutor::execute()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.1406

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 1
dl 0
loc 17
ccs 6
cts 8
cp 0.75
crap 3.1406
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Kaliop\eZMigrationBundle\Core\Executor;
4
5
use Kaliop\eZMigrationBundle\API\Exception\InvalidStepDefinitionException;
6
use Kaliop\eZMigrationBundle\API\Exception\MigrationBundleException;
7
use Kaliop\eZMigrationBundle\API\ReferenceResolverBagInterface;
8
use Kaliop\eZMigrationBundle\API\Value\MigrationStep;
9
use Kaliop\eZMigrationBundle\Core\Process\ProcessBuilder;
10
use Symfony\Component\Process\Process;
11
12
/**
13
 * @property ReferenceResolverBagInterface $referenceResolver
14
 */
15
class ProcessExecutor extends AbstractExecutor
16
{
17
    use IgnorableStepExecutorTrait;
0 ignored issues
show
Bug introduced by
The trait Kaliop\eZMigrationBundle...orableStepExecutorTrait requires the property $dsl which is not provided by Kaliop\eZMigrationBundle...xecutor\ProcessExecutor.
Loading history...
18
    use ReferenceSetterTrait;
19
20
    protected $supportedStepTypes = array('process');
21
    protected $supportedActions = array('run');
22
23
    protected $defaultTimeout = 86400;
24
25
    /**
26
     * @param ReferenceResolverBagInterface $referenceResolver
27 149
     */
28
    public function __construct(ReferenceResolverBagInterface $referenceResolver)
29 149
    {
30 149
        $this->referenceResolver = $referenceResolver;
31
    }
32
33
    /**
34
     * @param MigrationStep $step
35
     * @return mixed
36
     * @throws \Exception
37 2
     */
38
    public function execute(MigrationStep $step)
39 2
    {
40
        parent::execute($step);
41 2
42
        if (!isset($step->dsl['mode'])) {
43
            throw new InvalidStepDefinitionException("Invalid step definition: missing 'mode'");
44
        }
45 2
46
        $action = $step->dsl['mode'];
47 2
48
        if (!in_array($action, $this->supportedActions)) {
49
            throw new InvalidStepDefinitionException("Invalid step definition: value '$action' is not allowed for 'mode'");
50
        }
51 2
52
        $this->skipStepIfNeeded($step);
53 2
54
        return $this->$action($step->dsl, $step->context);
55
    }
56
57
    /**
58
     * @param $dsl
59
     * @param array|null $context
60
     * @return \Symfony\Component\Process\Process
61
     * @throws \Exception
62
     * @todo add more options supported by Sf Process
63 2
     */
64
    protected function run($dsl, $context)
65 2
    {
66
        if (!isset($dsl['command'])) {
67
            throw new InvalidStepDefinitionException("Can not run process: command missing");
68
        }
69 2
70
        $builder = new ProcessBuilder();
71
72 2
        // mandatory args and options
73
        $builderArgs = array($this->resolveReference($dsl['command']));
74 2
75 1
        if (isset($dsl['arguments'])) {
76
            foreach ($dsl['arguments'] as $arg) {
77 1
                /// @todo should this be recursive?
78
                $builderArgs[] = $this->resolveReference($arg);
79
            }
80
        }
81
82 2
        $process = $builder
83 2
            ->setArguments($builderArgs)
84
            ->getProcess();
85
86 2
        // allow long migrations processes by default
87 2
        $timeout = $this->defaultTimeout;
88
        if (isset($dsl['timeout'])) {
89
            $timeout = $this->resolveReference($dsl['timeout']);
90 2
        }
91
        $process->setTimeout($timeout);
92 2
93 1
        if (isset($dsl['working_directory'])) {
94
            $process->setWorkingDirectory($this->resolveReference($dsl['working_directory']));
95
        }
96
97 2
        /// @todo should we support false/true ?
98
        if (isset($dsl['disable_output'])) {
99
            $process->disableOutput();
0 ignored issues
show
Bug introduced by
The method disableOutput() does not exist on Kaliop\eZMigrationBundle\Core\Process\Process. ( Ignorable by Annotation )

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

99
            $process->/** @scrutinizer ignore-call */ 
100
                      disableOutput();

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...
100
        }
101 2
102 1
        if (isset($dsl['environment'])) {
103
            $process->setEnv($this->resolveReference($dsl['environment']));
104
        }
105 2
106
        $process->run();
107 2
108 1
        if (isset($dsl['fail_on_error']) && $this->resolveReference($dsl['fail_on_error'])) {
109 1
            if (($exitCode = $process->getExitCode()) != 0) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $exitCode = $process->getExitCode() of type integer|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
110
                throw new MigrationBundleException("Process failed with exit code: $exitCode", $exitCode);
111
            }
112
        }
113 1
114
        $this->setReferences($process, $dsl);
115 1
116
        return $process;
117
    }
118
119
    /**
120
     * @param Process $process
121
     * @param $dsl
122
     * @return bool
123
     * @throws InvalidStepDefinitionException
124 1
     */
125
    protected function setReferences(Process $process, $dsl)
126 1
    {
127
        if (!array_key_exists('references', $dsl) || !count($dsl['references'])) {
128
            return false;
129
        }
130 1
131 1
        foreach ($dsl['references'] as $key => $reference) {
132 1
            $reference = $this->parseReferenceDefinition($key, $reference);
133 1
            switch ($reference['attribute']) {
134 1
                case 'error_output':
135 1
                    $value = rtrim($process->getErrorOutput(), "\r\n");
136 1
                    break;
137 1
                case 'exit_code':
138 1
                    $value = $process->getExitCode();
139 1
                    break;
140 1
                case 'output':
141 1
                    $value = rtrim($process->getOutput(), "\r\n");
142
                    break;
143
                default:
144
                    throw new InvalidStepDefinitionException('Process executor does not support setting references for attribute ' . $reference['attribute']);
145
            }
146 1
147 1
            $overwrite = false;
148
            if (isset($reference['overwrite'])) {
149
                $overwrite = $reference['overwrite'];
150 1
            }
151
            $this->addReference($reference['identifier'], $value, $overwrite);
152
        }
153 1
154
        return true;
155
    }
156
}
157