Passed
Push — master ( 344a76...0f8f50 )
by jean
02:53
created

StepRunner::setOutput()   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
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Darkilliant\ProcessBundle\Runner;
4
5
use Psr\Log\LoggerInterface;
6
use Symfony\Component\OptionsResolver\OptionsResolver;
7
use Darkilliant\ProcessBundle\Configuration\ConfigurationProcess;
8
use Darkilliant\ProcessBundle\Configuration\ConfigurationStep;
9
use Darkilliant\ProcessBundle\Registry\LoggerRegistry;
10
use Darkilliant\ProcessBundle\Registry\StepRegistry;
11
use Darkilliant\ProcessBundle\Resolver\OptionDynamicValueResolver;
12
use Darkilliant\ProcessBundle\State\ProcessState;
13
use Darkilliant\ProcessBundle\Step\IterableStepInterface;
14
use Darkilliant\ProcessBundle\Step\StepInterface;
15
use Darkilliant\ProcessBundle\ProcessNotifier\ProgressBarProcessNotifier;
16
17
class StepRunner
18
{
19
    /** @var LoggerInterface */
20
    protected $logger;
21
22
    /** @var StepRegistry */
23
    protected $registry;
24
25
    /** @var LoggerRegistry */
26
    protected $loggerRegistry;
27
28
    /** @var OptionDynamicValueResolver */
29
    protected $dynamicValueResolver;
30
31
    /** @var array */
32
    protected $configuration;
33
34
    /** @var ProgressBarProcessNotifier */
35
    protected $notifier;
36
37
    /**
38
     * @internal
39
     */
40 11
    public function __construct(LoggerRegistry $loggerRegistry, StepRegistry $registry, OptionDynamicValueResolver $dynamicValueResolver, array $configuration, LoggerInterface $logger, ProgressBarProcessNotifier $notifier)
41
    {
42 11
        $this->configuration = $configuration;
43 11
        $this->logger = $logger;
44 11
        $this->dynamicValueResolver = $dynamicValueResolver;
45 11
        $this->registry = $registry;
46 11
        $this->loggerRegistry = $loggerRegistry;
47 11
        $this->notifier = $notifier;
48 11
    }
49
50 1
    public function setNotifier($notifier)
51
    {
52 1
        $this->notifier = $notifier;
53 1
    }
54
55
    /**
56
     * @param string $processName
57
     *
58
     * @throws \Exception
59
     *
60
     * @return ConfigurationProcess
61
     */
62 10
    public function buildConfigurationProcess(string $processName, string $logger = null): ConfigurationProcess
63
    {
64 10
        if (empty($this->configuration['process'][$processName])) {
65 2
            throw new \Exception(sprintf(
66 2
                'process %s not found, available (%s)',
67 2
                $processName,
68 2
                implode(', ', array_keys($this->configuration['process']))
69
            ));
70
        }
71
72 8
        if (null !== $logger) {
73 2
            $this->configuration['process'][$processName]['logger'] = $logger;
74
        }
75
76 8
        return ConfigurationProcess::create($this->configuration['process'][$processName]);
77
    }
78
79 6
    public function run(ConfigurationProcess $process, array $context = [])
80
    {
81 6
        $processState = new ProcessState(
82 6
            $context,
83 6
            $this->loggerRegistry->resolveService($process->getLogger()),
84 6
            $this
85
        );
86
87 6
        $this->runSteps($processState, $process->getSteps());
88 6
    }
89
90 3
    public function finalizeStep(ProcessState $processState, $step)
91
    {
92 3
        $processState->markSuccess();
93
94 3
        $this->registry->resolveService($step->getService())->finalize($processState);
95
96 2
        if (ProcessState::RESULT_OK !== $processState->getResult()) {
97 1
            return false;
98
        }
99
100 1
        return true;
101
    }
102
103 6
    public function runSteps(ProcessState $processState, array $steps)
104
    {
105 6
        foreach ($steps as $step) {
106
            try {
107 6
                if (!$this->runStep($processState, $step)) {
108 5
                    return false;
109
                }
110 1
            } catch (\Throwable $exception) {
111 1
                $processState->getLogger()->error('fail step', array_merge([
112 1
                    'message' => $exception->getMessage(),
113 1
                    'step' => $step->getService(),
114 1
                ], $processState->getRawContext()));
115
116 5
                return false;
117
            }
118
        }
119
120 4
        return true;
121
    }
122
123 5
    protected function configureOptions(StepInterface $service, ConfigurationStep $step, ProcessState $processState): ProcessState
124
    {
125 5
        return $processState->setOptions(
126 5
            $this->dynamicValueResolver->resolve(
127 5
                $service->configureOptionResolver(new OptionsResolver())->resolve($step->getOptions()),
128
                [
129 5
                    'data' => $processState->getData(),
130 5
                    'context' => $processState->getRawContext(),
131
                ]
132
            )
133
        );
134
    }
135
136 6
    protected function runStep(ProcessState $processState, ConfigurationStep $step): int
137
    {
138 6
        $processState->markSuccess();
139
140
        /**
141
         * @var ConfigurationStep
142
         */
143 6
        $service = $this->registry->resolveService($step->getService());
144
145 6
        $processState = $this->configureOptions($service, $step, $processState);
146 6
        $options = $processState->getOptions();
147
148 6
        $service->execute($processState);
149
150 5
        if (ProcessState::RESULT_OK !== $processState->getResult()) {
151 1
            return false;
152
        }
153 4
        if ($service instanceof IterableStepInterface) {
154 3
            $this->notifier->onStartProcess($processState, $service);
155 3
            $iterator = $processState->getIterator();
156
157 3
            while ($service->valid($processState)) {
158 3
                $service->next($processState);
159 3
                $this->notifier->onUpdateProcess($processState, $service);
160
161 3
                if ($this->runSteps($processState, $step->getChildren())) {
162 3
                    $processState->getLogger()->info('successful', $processState->getRawContext());
163
                }
164
165 3
                $processState->setIterator($iterator);
166 3
                $processState->setOptions($options);
167
            }
168 3
            $this->notifier->onEndProcess($processState, $service);
169
170 3
            $this->finalizeSteps($processState, $step->getChildren());
171
        }
172
173 4
        return true;
174
    }
175
176 3
    private function finalizeSteps(ProcessState $processState, array $steps)
177
    {
178 3
        foreach ($steps as $step) {
179
            try {
180 3
                if (!$this->finalizeStep($processState, $step)) {
181 2
                    return false;
182
                }
183 1
            } catch (\Exception $exception) {
184 1
                $processState->getLogger()->error('fail step', array_merge([
185 1
                    'message' => $exception->getMessage(),
186 1
                    'step' => $step->getService(),
187 1
                ], $processState->getRawContext()));
188
189 2
                return false;
190
            }
191
        }
192
193 1
        return true;
194
    }
195
}
196