Completed
Pull Request — master (#311)
by Coroliov
63:34
created

CKEditorInstallerCommand::title()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 8
cts 8
cp 1
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
crap 1
1
<?php
2
3
/*
4
 * This file is part of the Ivory CKEditor package.
5
 *
6
 * (c) Eric GELOEN <[email protected]>
7
 *
8
 * For the full copyright and license information, please read the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Ivory\CKEditorBundle\Command;
13
14
use Ivory\CKEditorBundle\Installer\CKEditorInstaller;
15
use Symfony\Component\Console\Command\Command;
16
use Symfony\Component\Console\Helper\ProgressBar;
17
use Symfony\Component\Console\Helper\ProgressHelper;
18
use Symfony\Component\Console\Helper\QuestionHelper;
19
use Symfony\Component\Console\Input\InputArgument;
20
use Symfony\Component\Console\Input\InputInterface;
21
use Symfony\Component\Console\Input\InputOption;
22
use Symfony\Component\Console\Output\OutputInterface;
23
use Symfony\Component\Console\Question\ChoiceQuestion;
24
25
/**
26
 * @author GeLo <[email protected]>
27
 */
28
class CKEditorInstallerCommand extends Command
29
{
30
    /**
31
     * @var CKEditorInstaller
32
     */
33
    private $installer;
34
35
    /**
36
     * @param CKEditorInstaller|null $installer
37
     */
38 12
    public function __construct(CKEditorInstaller $installer = null)
39
    {
40 12
        parent::__construct();
41
42 12
        $this->installer = $installer ?: new CKEditorInstaller();
43 12
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 12
    protected function configure()
49
    {
50 10
        $this
51 12
            ->setName('ckeditor:install')
52 12
            ->setDescription('Install CKEditor')
53 12
            ->addArgument('path', InputArgument::OPTIONAL, 'Where to install CKEditor')
54 12
            ->addOption('release', null, InputOption::VALUE_OPTIONAL, 'CKEditor release (basic, standard or full)')
55 12
            ->addOption('tag', null, InputOption::VALUE_OPTIONAL, 'CKEditor tag (x.y.z or latest)')
56 12
            ->addOption(
57 12
                'clear',
58 12
                null,
59 12
                InputOption::VALUE_OPTIONAL,
60 2
                'How to clear previous CKEditor installation (drop, keep or skip)'
61 10
            )
62 12
            ->addOption(
63 12
                'exclude',
64 12
                null,
65 12
                InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL,
66 2
                'Path to exclude when extracting CKEditor'
67 10
            )
68 12
            ->setHelp(<<<'EOF'
69 1
The <info>%command.name%</info> command install CKEditor in your application:
70
71
  <info>php %command.full_name%</info>
72
  
73
You can install it at a specific path (absolute):
74
75
  <info>php %command.full_name% path</info>
76
  
77
You can install a specific release (basic, standard or full):
78
79
  <info>php %command.full_name% --release=full</info>
80
  
81
You can install a specific version:
82
83
  <info>php %command.full_name% --tag=4.7.0</info>
84
85
If there is a previous CKEditor installation detected, 
86
you can control how it should be handled in non-interactive mode:
87
88
  <info>php %command.full_name% --clear=drop</info>
89
  <info>php %command.full_name% --clear=keep</info>
90
  <info>php %command.full_name% --clear=skip</info>
91
  
92
You can exclude path(s) when extracting CKEditor:
93
94 1
  <info>php %command.full_name% --exclude=samples --exclude=adapters</info>
95
EOF
96 10
            );
97 12
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102 12
    protected function execute(InputInterface $input, OutputInterface $output)
103
    {
104 12
        $this->title($output);
105
106 12
        $success = $this->installer->install($this->createOptions($input, $output));
107
108 12
        if ($success) {
109 12
            $this->success('CKEditor has been successfully installed...', $output);
110 10
        } else {
111
            $this->info('CKEditor installation has been skipped...', $output);
112
        }
113 12
    }
114
115
    /**
116
     * @param InputInterface  $input
117
     * @param OutputInterface $output
118
     *
119
     * @return mixed[]
120
     */
121 12
    private function createOptions(InputInterface $input, OutputInterface $output)
122
    {
123 12
        $options = ['notifier' => $this->createNotifier($input, $output)];
124
125 12
        if ($input->hasArgument('path')) {
126 12
            $options['path'] = $input->getArgument('path');
127 10
        }
128
129 12
        if ($input->hasOption('release')) {
130 12
            $options['release'] = $input->getOption('release');
131 10
        }
132
133 12
        if ($input->hasOption('tag')) {
134 12
            $options['version'] = $input->getOption('tag');
135 10
        }
136
137 12
        if ($input->hasOption('exclude')) {
138 12
            $options['excludes'] = $input->getOption('exclude');
139 10
        }
140
141 12
        if ($input->hasOption('clear')) {
142 12
            $options['clear'] = $input->getOption('clear');
143 10
        }
144
145 12
        return $options;
146
    }
147
148
    /**
149
     * @param InputInterface  $input
150
     * @param OutputInterface $output
151
     *
152
     * @return \Closure
153
     */
154 12
    private function createNotifier(InputInterface $input, OutputInterface $output)
155
    {
156 12
        $clear = $this->createProgressBar($output);
157 12
        $download = $this->createProgressBar($output);
158 12
        $extract = $this->createProgressBar($output);
159
160 12
        return function ($type, $data) use ($input, $output, $clear, $download, $extract) {
161
            switch ($type) {
162 12
                case CKEditorInstaller::NOTIFY_CLEAR:
163 2
                    $result = $this->choice(
164
                        [
165 2
                            sprintf('CKEditor is already installed in "%s"...', $data),
166 2
                            '',
167 2
                            'What do you want to do?',
168 2
                        ],
169
                        $choices = [
170 2
                            CKEditorInstaller::CLEAR_DROP => 'Drop the directory & reinstall CKEditor',
171 2
                            CKEditorInstaller::CLEAR_KEEP => 'Keep the directory & reinstall CKEditor by overriding files',
172 2
                            CKEditorInstaller::CLEAR_SKIP => 'Skip installation',
173 2
                        ],
174 2
                        CKEditorInstaller::CLEAR_DROP,
175 2
                        $input,
176
                        $output
177 2
                    );
178
179 2
                    if (($key = array_search($result, $choices, true)) !== false) {
180
                        $result = $key;
181
                    }
182
183 2
                    if ($result === CKEditorInstaller::CLEAR_DROP) {
184 2
                        $this->comment(sprintf('Dropping CKEditor from "%s"', $data), $output);
185 2
                    }
186
187 2
                    return $result;
188
189 12
                case CKEditorInstaller::NOTIFY_CLEAR_ARCHIVE:
190 12
                    $this->comment(sprintf('Dropping CKEditor ZIP archive "%s"', $data), $output);
191 12
                    break;
192
193 12
                case CKEditorInstaller::NOTIFY_CLEAR_COMPLETE:
194 2
                    $this->finishProgressBar($clear, $output);
195 2
                    break;
196
197 12
                case CKEditorInstaller::NOTIFY_CLEAR_PROGRESS:
198 2
                    $clear->advance();
199 2
                    break;
200
201 12
                case CKEditorInstaller::NOTIFY_CLEAR_SIZE:
202 2
                    $this->startProgressBar($clear, $output, $data);
203 2
                    break;
204
205 12
                case CKEditorInstaller::NOTIFY_DOWNLOAD:
206 12
                    $this->comment(sprintf('Downloading CKEditor ZIP archive from "%s"', $data), $output);
207 12
                    break;
208
209 12
                case CKEditorInstaller::NOTIFY_DOWNLOAD_COMPLETE:
210 12
                    $this->finishProgressBar($download, $output);
211 12
                    break;
212
213 12
                case CKEditorInstaller::NOTIFY_DOWNLOAD_PROGRESS:
214 12
                    $this->advanceProgressBar($download, $data);
215 12
                    break;
216
217 12
                case CKEditorInstaller::NOTIFY_DOWNLOAD_SIZE:
218 11
                    $this->startProgressBar($download, $output, $data);
219 11
                    break;
220
221 12
                case CKEditorInstaller::NOTIFY_EXTRACT:
222 12
                    $this->comment(sprintf('Extracting CKEditor ZIP archive to "%s"', $data), $output);
223 12
                    break;
224
225 12
                case CKEditorInstaller::NOTIFY_EXTRACT_COMPLETE:
226 12
                    $this->finishProgressBar($extract, $output);
227 12
                    break;
228
229 12
                case CKEditorInstaller::NOTIFY_EXTRACT_PROGRESS:
230 12
                    $extract->advance();
231 12
                    break;
232
233 12
                case CKEditorInstaller::NOTIFY_EXTRACT_SIZE:
234 12
                    $this->startProgressBar($extract, $output, $data);
235 12
                    break;
236
            }
237 12
        };
238
    }
239
240
    /**
241
     * @param OutputInterface $output
242
     */
243 12
    private function title(OutputInterface $output)
244
    {
245 12
        $output->writeln([
246 12
            '----------------------',
247 10
            '| CKEditor Installer |',
248 10
            '----------------------',
249 10
            '',
250 10
        ]);
251 12
    }
252
253
    /**
254
     * @param string|string[] $message
255
     * @param OutputInterface $output
256
     */
257 12
    private function comment($message, OutputInterface $output)
258
    {
259 12
        $output->writeln(' // '.$message);
260 12
        $output->writeln('');
261 12
    }
262
263
    /**
264
     * @param string          $message
265
     * @param OutputInterface $output
266
     */
267 12
    private function success($message, OutputInterface $output)
268
    {
269 12
        $this->block('[OK] - '.$message, $output, 'green', 'black');
270 12
    }
271
272
    /**
273
     * @param string          $message
274
     * @param OutputInterface $output
275
     */
276
    p
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
277
        tputInterface $output)
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...
Coding Style introduced by
The visibility should be declared for property $output.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
278
    {
279
        $this->block('[INFO] - '.$message, $output, 'yellow', 'black');
280
    }
281
282
    /**
283
     * @param string          $message
284
     * @param OutputInterface $output
285
     * @param string          $background
286
     * @param string          $font
287 12
     */
288
    private function block($message, OutputInterface $output, $background = null, $font = null)
289 12
    {
290
        $options = [];
291 12
292 12
        if ($background !== null) {
293 10
            $options[] = 'bg='.$background;
294
        }
295 12
296 12
        if ($font !== null) {
297 10
            $options[] = 'fg='.$font;
298
        }
299 12
300
        $pattern = ' %s ';
301 12
302 12
        if (!empty($options)) {
303 10
            $pattern = '<'.implode(';', $options).'>'.$pattern.'</>';
304
        }
305 12
306 12
        $output->writeln($block = sprintf($pattern, str_repeat(' ', strlen($message))));
307 12
        $output->writeln(sprintf($pattern, $message));
308 12
        $output->writeln($block);
309
    }
310
311
    /**
312
     * @param string|string[] $question
313
     * @param string[]        $choices
314
     * @param string          $default
315
     * @param InputInterface  $input
316
     * @param OutputInterface $output
317
     *
318
     * @return string|null
319 2
     */
320
    private function choice($question, array $choices, $default, InputInterface $input, OutputInterface $output)
321 2
    {
322
        $helper = new QuestionHelper();
323 2
324 2
        $result = $helper->ask($input, $output, new ChoiceQuestion(
325 2
            $question,
326 2
            $choices,
327 2
            $choices[$default]
328
        ));
329 2
330
        $output->writeln('');
331 2
332
        return $result;
333
    }
334
335
    /**
336
     * @param OutputInterface $output
337
     *
338
     * @return ProgressBar|ProgressHelper
339 12
     */
340
    private function createProgressBar(OutputInterface $output)
341 12
    {
342
        return class_exists(ProgressBar::class) ? new ProgressBar($output) : new ProgressHelper();
343
    }
344
345
    /**
346
     * @param ProgressBar|ProgressHelper $progress
347
     * @param OutputInterface            $output
348
     * @param int|null                   $max
349 12
     */
350
    private function startProgressBar($progress, OutputInterface $output, $max = null)
351 12
    {
352 12
        class_exists(ProgressBar::class) ? $progress->start($max) : $progress->start($output, $max);
353
    }
354
355
    /**
356
     * @param ProgressBar|ProgressHelper $progress
357
     * @param int                        $current
358 12
     */
359
    private function advanceProgressBar($progress, $current)
360 12
    {
361 12
        class_exists(ProgressBar::class) ? $progress->setProgress($current) : $progress->setCurrent($current);
362
    }
363
364
    /**
365
     * @param ProgressBar|ProgressHelper $progress
366
     * @param OutputInterface            $output
367 12
     */
368
    private function finishProgressBar($progress, OutputInterface $output)
369 12
    {
370 12
        $progress->finish();
371 12
        $output->writeln(['', '']);
372
    }
373
}
374