Completed
Push — master ( fe3dbd...6d023a )
by jean
03:47
created

StepRunner   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 174
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 174
ccs 79
cts 79
cp 1
rs 10
c 0
b 0
f 0
wmc 21

9 Methods

Rating   Name   Duplication   Size   Complexity  
A run() 0 9 1
A setOutput() 0 3 1
A runSteps() 0 18 4
B runStep() 0 35 5
A buildConfigurationProcess() 0 11 2
A __construct() 0 9 1
A configureOptions() 0 8 1
A finalizeStep() 0 11 2
A finalizeSteps() 0 18 4
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
    /**
62
     * @param string $processName
63
     *
64
     * @throws \Exception
65
     *
66
     * @return ConfigurationProcess
67
     */
68 7
    public function buildConfigurationProcess(string $processName): ConfigurationProcess
69
    {
70 7
        if (empty($this->configuration['process'][$processName])) {
71 1
            throw new \Exception(sprintf(
72 1
                'process %s not found, available (%s)',
73 1
                $processName,
74 1
                implode(', ', array_keys($this->configuration['process']))
75
            ));
76
        }
77
78 6
        return ConfigurationProcess::create($this->configuration['process'][$processName]);
79
    }
80
81 6
    public function run(ConfigurationProcess $process, array $context = [])
82
    {
83 6
        $processState = new ProcessState(
84 6
            $context,
85 6
            $this->loggerRegistry->resolveService($process->getLogger()),
86 6
            $this
87
        );
88
89 6
        $this->runSteps($processState, $process->getSteps());
90 6
    }
91
92 3
    public function finalizeStep(ProcessState $processState, $step)
93
    {
94 3
        $processState->markSuccess();
95
96 3
        $this->registry->resolveService($step->getService())->finalize($processState);
97
98 2
        if (ProcessState::RESULT_OK !== $processState->getResult()) {
99 1
            return false;
100
        }
101
102 1
        return true;
103
    }
104
105 6
    public function runSteps(ProcessState $processState, array $steps)
106
    {
107 6
        foreach ($steps as $step) {
108
            try {
109 6
                if (!$this->runStep($processState, $step)) {
110 5
                    return false;
111
                }
112 1
            } catch (\Exception $exception) {
113 1
                $this->logger->error('fail step', array_merge([
114 1
                    'message' => $exception->getMessage(),
115 1
                    'step' => $step->getService(),
116 1
                ], $processState->getRawContext()));
117
118 5
                return false;
119
            }
120
        }
121
122 4
        return true;
123
    }
124
125 5
    protected function configureOptions(StepInterface $service, ConfigurationStep $step, ProcessState $processState): ProcessState
126
    {
127 5
        return $processState->setOptions(
128 5
            $this->dynamicValueResolver->resolve(
129 5
                $service->configureOptionResolver(new OptionsResolver())->resolve($step->getOptions()),
130
                [
131 5
                    'data' => $processState->getData(),
132 5
                    'context' => $processState->getRawContext(),
133
                ]
134
            )
135
        );
136
    }
137
138 6
    protected function runStep(ProcessState $processState, ConfigurationStep $step): int
139
    {
140 6
        $processState->markSuccess();
141
142
        /**
143
         * @var ConfigurationStep
144
         */
145 6
        $service = $this->registry->resolveService($step->getService());
146
147 6
        $service->execute(
148 6
            $this->configureOptions($service, $step, $processState)
149
        );
150
151 5
        if (ProcessState::RESULT_OK !== $processState->getResult()) {
152 1
            return false;
153
        }
154 4
        if ($service instanceof IterableStepInterface) {
155 3
            $this->notifier->onStartProcess($processState, $service);
156 3
            $iterator = $processState->getIterator();
157
158 3
            while ($service->valid($processState)) {
159 3
                $service->next($processState);
160 3
                $this->notifier->onUpdateProcess($processState, $service);
161
162 3
                if ($this->runSteps($processState, $step->getChildren())) {
163 3
                    $this->logger->info('successful', $processState->getRawContext());
164
                }
165 3
                $processState->setIterator($iterator);
166
            }
167 3
            $this->notifier->onEndProcess($processState, $service);
168
169 3
            $this->finalizeSteps($processState, $step->getChildren());
170
        }
171
172 4
        return true;
173
    }
174
175 3
    private function finalizeSteps(ProcessState $processState, array $steps)
176
    {
177 3
        foreach ($steps as $step) {
178
            try {
179 3
                if (!$this->finalizeStep($processState, $step)) {
180 2
                    return false;
181
                }
182 1
            } catch (\Exception $exception) {
183 1
                $this->logger->error('fail step', array_merge([
184 1
                    'message' => $exception->getMessage(),
185 1
                    'step' => $step->getService(),
186 1
                ], $processState->getRawContext()));
187
188 2
                return false;
189
            }
190
        }
191
192 1
        return true;
193
    }
194
}
195