Passed
Push — nln-php7 ( 5c4f20...6ce259 )
by Nicolas
03:34
created

ConfigureActionCommand   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 228
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 5

Test Coverage

Coverage 98.25%

Importance

Changes 0
Metric Value
wmc 25
lcom 2
cbo 5
dl 0
loc 228
ccs 112
cts 114
cp 0.9825
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 1
A configure() 0 19 1
A execute() 0 10 1
B processInputs() 0 64 9
launchConfigurationAction() 0 1 ?
getProcessor() 0 1 ?
A configureProcessor() 0 22 4
A parseOptionWithAssignments() 0 35 5
A processOverridenVariables() 0 18 2
A processCustomData() 0 16 2
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Karma\Console;
6
7
use Karma\Command;
8
use Symfony\Component\Console\Input\InputArgument;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Karma\Application;
13
use Karma\Configuration\FilterInputVariable;
14
use Karma\ConfigurableProcessor;
15
16
abstract class ConfigureActionCommand extends Command
17
{
18
    use FilterInputVariable;
19
20
    private const
21
        ENV_DEV = 'dev',
22
        OPTION_ASSIGNMENT = '=';
23
24
    private
25
        $dryRun,
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
26
        $isBackupEnabled,
27
        $systemEnvironment,
28
        $name,
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
29
        $description,
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
30
        $outputTitle;
31
32
    protected
33
        $environment;
34
35 36
    public function __construct(Application $app, $name, $description, $outputTitle)
36
    {
37 36
        $this->name = $name;
38 36
        $this->description = $description;
39 36
        $this->outputTitle = $outputTitle;
40
41 36
        parent::__construct($app);
42
43 36
        $this->dryRun = false;
44 36
        $this->isBackupEnabled = false;
45
46 36
        $this->environment = self::ENV_DEV;
47 36
        $this->systemEnvironment = null;
48 36
    }
49
50 36
    protected function configure()
51
    {
52 36
        parent::configure();
53
54
        $this
55 36
            ->setName($this->name)
56 36
            ->setDescription($this->description)
57
58 36
            ->addArgument('sourcePath', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'source path to hydrate/generate')
59
60 36
            ->addOption('targetPath', 't', InputOption::VALUE_REQUIRED, 'target path to hydrate/generate', null)
61 36
            ->addOption('env', 'e', InputOption::VALUE_REQUIRED, 'Target environment', self::ENV_DEV)
62 36
            ->addOption('system', 's', InputOption::VALUE_REQUIRED, 'Target environment for system variables', null)
63 36
            ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Simulation mode')
64 36
            ->addOption('backup', 'b', InputOption::VALUE_NONE, 'Backup overwritten files')
65 36
            ->addOption('override', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Override variable values', array())
66 36
            ->addOption('data', 'd', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Custom data values', array())
67
        ;
68 36
    }
69
70 27
    protected function execute(InputInterface $input, OutputInterface $output)
71
    {
72 27
        parent::execute($input, $output);
73
74 27
        $this->processInputs($input);
75
76 17
        $processor = $this->getProcessor();
77 17
        $this->configureProcessor($processor);
78 17
        $this->launchConfigurationAction($processor);
79 17
    }
80
81 27
    private function processInputs(InputInterface $input): void
82
    {
83 27
        $this->environment = $input->getOption('env');
84 27
        $this->systemEnvironment = $input->getOption('system');
85
86 27
        if($input->getOption('dry-run'))
87
        {
88 2
            $this->dryRun = true;
89 2
            $this->output->writeln("<fg=cyan>Run in dry-run mode</fg=cyan>");
90
        }
91
92 27
        if($input->getOption('backup'))
93
        {
94 2
            $this->isBackupEnabled = true;
95 2
            $this->output->writeln("<fg=cyan>Backup enabled</fg=cyan>");
96
        }
97
98 27
        $profile = $this->app['profile'];
99 27
        $sourcePath = $input->getArgument('sourcePath');
100 27
        if(empty($sourcePath))
101
        {
102 5
            if($profile->hasSourcePath() !== true)
103
            {
104 2
                throw new \RuntimeException('Missing argument sourcePath');
105
            }
106
107 3
            $sourcePath = $profile->getSourcePath();
108
        }
109
110 25
        if(! is_array($sourcePath))
111
        {
112 22
            $sourcePath = [$sourcePath];
113
        }
114
115 25
        $targetPath = $input->getOption('targetPath');
116
117 25
        if(is_array($targetPath))
118
        {
119
            throw new \RuntimeException('Invalid argument targetPath : could not be mutiple (single path required as string)');
120
        }
121
122 25
        if(empty($targetPath) && $profile->hasTargetPath() === true)
123
        {
124
            $targetPath = $profile->getTargetPath();
125
        }
126
127 25
        $this->output->writeln(sprintf(
128 25
            "<info>%s <comment>%s</comment> with <comment>%s</comment> values</info>",
129 25
            $this->outputTitle,
130 25
            implode(' ', $sourcePath),
131 25
            $this->environment
132
        ));
133 25
        $this->output->writeln('');
134
135 25
        $this->app['sources.path'] = $sourcePath;
136 25
        $this->app['target.path'] = $targetPath;
137
138 25
        $this->processOverridenVariables(
139 25
            $this->parseOptionWithAssignments($input, 'override')
140
        );
141 21
        $this->processCustomData(
142 21
            $this->parseOptionWithAssignments($input, 'data')
143
        );
144 17
    }
145
146
    abstract protected function launchConfigurationAction(ConfigurableProcessor $processor): void;
147
    abstract protected function getProcessor(): ConfigurableProcessor;
148
149 17
    private function configureProcessor(ConfigurableProcessor $processor)
150
    {
151 17
        if($this->dryRun === true)
152
        {
153 2
            $processor->setDryRun();
154
        }
155
156 17
        if($this->isBackupEnabled === true)
157
        {
158 2
            $processor->enableBackup();
159
        }
160
161 17
        if($this->systemEnvironment !== null)
162
        {
163 2
            $processor->setSystemEnvironment($this->systemEnvironment);
164
165 2
             $this->app['logger']->info(sprintf(
166 2
                'Hydrate <important>system</important> variables with <important>%s</important> values',
167 2
                $this->systemEnvironment
168
            ));
169
        }
170 17
    }
171
172 25
    private function parseOptionWithAssignments(InputInterface $input, $optionName)
173
    {
174 25
        $strings = $input->getOption($optionName);
175
176 25
        if(! is_array($strings))
177
        {
178 4
            $strings = [$strings];
179
        }
180
181 25
        $data = [];
182
183 25
        foreach($strings as $string)
184
        {
185 15
            if(stripos($string, self::OPTION_ASSIGNMENT) === false)
186
            {
187 4
                throw new \InvalidArgumentException(sprintf(
188 4
                    '%s option must contain %c : --%s <variable>=<value>',
189 4
                    $optionName,
190 4
                    self::OPTION_ASSIGNMENT,
191 4
                    $optionName
192
                ));
193
            }
194
195 11
            list($variable, $value) = explode(self::OPTION_ASSIGNMENT, $string, 2);
196
197 11
            if(array_key_exists($variable, $data))
198
            {
199 4
                throw new \InvalidArgumentException("Duplicated %s option value : $variable");
200
            }
201
202 11
            $data[$variable] = $value;
203
        }
204
205 21
        return $data;
206
    }
207
208 21
    private function processOverridenVariables(array $overrides): void
209
    {
210 21
        $reader = $this->app['configuration'];
211 21
        $logger = $this->app['logger'];
212
213 21
        foreach($overrides as $variable => $value)
214
        {
215 5
            $logger->info(sprintf(
216 5
               'Override <important>%s</important> with value <important>%s</important>',
217 5
               $variable,
218 5
               $value
219
            ));
220
221 5
            $value = $this->parseList($value);
222
223 5
            $reader->overrideVariable($variable, $this->filterValue($value));
224
        }
225 21
    }
226
227 17
    private function processCustomData(array $data): void
228
    {
229 17
        $reader = $this->app['configuration'];
230 17
        $logger = $this->app['logger'];
231
232 17
        foreach($data as $variable => $value)
233
        {
234 2
            $logger->info(sprintf(
235 2
               'Set custom data <important>%s</important> with value <important>%s</important>',
236 2
               $variable,
237 2
               $value
238
            ));
239
240 2
            $reader->setCustomData($variable, $this->filterValue($value));
241
        }
242 17
    }
243
}
244