Passed
Push — main ( 2bf33d...adc87c )
by Gaetano
08:33
created

Core/Executor/ProcessExecutor.php (1 issue)

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
class ProcessExecutor extends AbstractExecutor
13
{
14
    use IgnorableStepExecutorTrait;
15
16
    protected $supportedStepTypes = array('process');
17
    protected $supportedActions = array('run');
18
19
    protected $defaultTimeout = 86400;
20
21
    /** @var ReferenceResolverBagInterface $referenceResolver */
22
    protected $referenceResolver;
23
24
    /**
25
     * @param ReferenceResolverBagInterface $referenceResolver
26
     */
27 149
    public function __construct(ReferenceResolverBagInterface $referenceResolver)
28
    {
29 149
        $this->referenceResolver = $referenceResolver;
30 149
    }
31
32
    /**
33
     * @param MigrationStep $step
34
     * @return mixed
35
     * @throws \Exception
36
     */
37 2
    public function execute(MigrationStep $step)
38
    {
39 2
        parent::execute($step);
40
41 2
        if (!isset($step->dsl['mode'])) {
42
            throw new InvalidStepDefinitionException("Invalid step definition: missing 'mode'");
43
        }
44
45 2
        $action = $step->dsl['mode'];
46
47 2
        if (!in_array($action, $this->supportedActions)) {
48
            throw new InvalidStepDefinitionException("Invalid step definition: value '$action' is not allowed for 'mode'");
49
        }
50
51 2
        $this->skipStepIfNeeded($step);
52
53 2
        return $this->$action($step->dsl, $step->context);
54
    }
55
56
    /**
57
     * @param $dsl
58
     * @param array|null $context
59
     * @return \Symfony\Component\Process\Process
60
     * @throws \Exception
61
     * @todo add more options supported by Sf Process
62
     */
63 2
    protected function run($dsl, $context)
64
    {
65 2
        if (!isset($dsl['command'])) {
66
            throw new InvalidStepDefinitionException("Can not run process: command missing");
67
        }
68
69 2
        $builder = new ProcessBuilder();
70
71
        // mandatory args and options
72 2
        $builderArgs = array($this->referenceResolver->resolveReference($dsl['command']));
73
74 2
        if (isset($dsl['arguments'])) {
75 1
            foreach ($dsl['arguments'] as $arg) {
76
                /// @todo should this be recursive?
77 1
                $builderArgs[] = $this->referenceResolver->resolveReference($arg);
78
            }
79
        }
80
81
        $process = $builder
82 2
            ->setArguments($builderArgs)
83 2
            ->getProcess();
84
85
        // allow long migrations processes by default
86 2
        $timeout = $this->defaultTimeout;
87 2
        if (isset($dsl['timeout'])) {
88
            $timeout = $this->referenceResolver->resolveReference($dsl['timeout']);
89
        }
90 2
        $process->setTimeout($timeout);
91
92 2
        if (isset($dsl['working_directory'])) {
93 1
            $process->setWorkingDirectory($this->referenceResolver->resolveReference($dsl['working_directory']));
94
        }
95
96
        /// @todo should we support false/true ?
97 2
        if (isset($dsl['disable_output'])) {
98
            $process->disableOutput();
99
        }
100
101 2
        if (isset($dsl['environment'])) {
102 1
            $process->setEnv($this->referenceResolver->resolveReference($dsl['environment']));
103
        }
104
105 2
        $process->run();
106
107 2
        if (isset($dsl['fail_on_error']) && $this->referenceResolver->resolveReference($dsl['fail_on_error'])) {
108 1
            if (($exitCode = $process->getExitCode()) != 0) {
109 1
                throw new MigrationBundleException("Process failed with exit code: $exitCode", $exitCode);
110
            }
111
        }
112
113 1
        $this->setReferences($process, $dsl);
114
115 1
        return $process;
116
    }
117
118
    /**
119
     * @param Process $process
120
     * @param $dsl
121
     * @return bool
122
     * @throws InvalidStepDefinitionException
123
     */
124 1
    protected function setReferences(Process $process, $dsl)
125
    {
126 1
        if (!array_key_exists('references', $dsl) || !count($step->dsl['references'])) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $step seems to be never defined.
Loading history...
127
            return false;
128
        }
129
130 1
        foreach ($dsl['references'] as $key => $reference) {
131 1
            $reference = $this->parseReferenceDefinition($key, $reference);
132 1
            switch ($reference['attribute']) {
133 1
                case 'error_output':
134 1
                    $value = rtrim($process->getErrorOutput(), "\r\n");
135 1
                    break;
136 1
                case 'exit_code':
137 1
                    $value = $process->getExitCode();
138 1
                    break;
139 1
                case 'output':
140 1
                    $value = rtrim($process->getOutput(), "\r\n");
141 1
                    break;
142
                default:
143
                    throw new InvalidStepDefinitionException('Process executor does not support setting references for attribute ' . $reference['attribute']);
144
            }
145
146 1
            $overwrite = false;
147 1
            if (isset($reference['overwrite'])) {
148
                $overwrite = $reference['overwrite'];
149
            }
150 1
            $this->referenceResolver->addReference($reference['identifier'], $value, $overwrite);
151
        }
152
153 1
        return true;
154
    }
155
}
156