Completed
Push — master ( b387a6...344a76 )
by jean
09:35
created

StepRunner::setNotifier()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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