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
|
10 |
|
public function __construct(CKEditorInstaller $installer = null) |
39
|
|
|
{ |
40
|
10 |
|
parent::__construct(); |
41
|
|
|
|
42
|
10 |
|
$this->installer = $installer ?: new CKEditorInstaller(); |
43
|
10 |
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* {@inheritdoc} |
47
|
|
|
*/ |
48
|
10 |
|
protected function configure() |
49
|
|
|
{ |
50
|
8 |
|
$this |
51
|
10 |
|
->setName('ckeditor:install') |
52
|
10 |
|
->setDescription('Install CKEditor') |
53
|
10 |
|
->addArgument('path', InputArgument::OPTIONAL, 'Where to install CKEditor') |
54
|
10 |
|
->addOption('release', null, InputOption::VALUE_OPTIONAL, 'CKEditor release (basic, standard or full)') |
55
|
10 |
|
->addOption('tag', null, InputOption::VALUE_OPTIONAL, 'CKEditor tag (x.y.z or latest)') |
56
|
10 |
|
->addOption( |
57
|
10 |
|
'clear', |
58
|
10 |
|
null, |
59
|
10 |
|
InputOption::VALUE_OPTIONAL, |
60
|
2 |
|
'How to clear previous CKEditor installation (drop, keep or abort)' |
61
|
8 |
|
) |
62
|
10 |
|
->addOption( |
63
|
10 |
|
'exclude', |
64
|
10 |
|
null, |
65
|
10 |
|
InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, |
66
|
2 |
|
'Path to exclude when extracting CKEditor' |
67
|
8 |
|
) |
68
|
10 |
|
->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=abort</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
|
8 |
|
); |
97
|
10 |
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* {@inheritdoc} |
101
|
|
|
*/ |
102
|
10 |
|
protected function execute(InputInterface $input, OutputInterface $output) |
103
|
|
|
{ |
104
|
10 |
|
$this->title($output); |
105
|
|
|
|
106
|
10 |
|
$success = $this->installer->install($this->createOptions($input, $output)); |
107
|
|
|
|
108
|
10 |
|
if ($success) { |
109
|
10 |
|
$this->success('CKEditor has been successfully installed...', $output); |
110
|
8 |
|
} |
111
|
10 |
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* @param InputInterface $input |
115
|
|
|
* @param OutputInterface $output |
116
|
|
|
* |
117
|
|
|
* @return mixed[] |
118
|
|
|
*/ |
119
|
10 |
|
private function createOptions(InputInterface $input, OutputInterface $output) |
120
|
|
|
{ |
121
|
10 |
|
$options = ['notifier' => $this->createNotifier($input, $output)]; |
122
|
|
|
|
123
|
10 |
|
if ($input->hasArgument('path')) { |
124
|
10 |
|
$options['path'] = $input->getArgument('path'); |
125
|
8 |
|
} |
126
|
|
|
|
127
|
10 |
|
if ($input->hasOption('release')) { |
128
|
10 |
|
$options['release'] = $input->getOption('release'); |
129
|
8 |
|
} |
130
|
|
|
|
131
|
10 |
|
if ($input->hasOption('tag')) { |
132
|
10 |
|
$options['version'] = $input->getOption('tag'); |
133
|
8 |
|
} |
134
|
|
|
|
135
|
10 |
|
if ($input->hasOption('exclude')) { |
136
|
10 |
|
$options['excludes'] = $input->getOption('exclude'); |
137
|
8 |
|
} |
138
|
|
|
|
139
|
10 |
|
if ($input->hasOption('clear')) { |
140
|
10 |
|
$options['clear'] = $input->getOption('clear'); |
141
|
8 |
|
} |
142
|
|
|
|
143
|
10 |
|
return $options; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* @param InputInterface $input |
148
|
|
|
* @param OutputInterface $output |
149
|
|
|
* |
150
|
|
|
* @return \Closure |
151
|
|
|
*/ |
152
|
10 |
|
private function createNotifier(InputInterface $input, OutputInterface $output) |
153
|
|
|
{ |
154
|
10 |
|
$clear = $this->createProgressBar($output); |
155
|
10 |
|
$download = $this->createProgressBar($output); |
156
|
10 |
|
$extract = $this->createProgressBar($output); |
157
|
|
|
|
158
|
10 |
|
return function ($type, $data) use ($input, $output, $clear, $download, $extract) { |
159
|
|
|
switch ($type) { |
160
|
10 |
|
case CKEditorInstaller::NOTIFY_CLEAR: |
161
|
1 |
|
$result = $this->choice( |
162
|
|
|
[ |
163
|
1 |
|
sprintf('CKEditor is already installed in "%s"...', $data), |
164
|
1 |
|
'', |
165
|
1 |
|
'What do you want to do?', |
166
|
1 |
|
], |
167
|
|
|
$choices = [ |
168
|
1 |
|
CKEditorInstaller::CLEAR_DROP => 'Drop the directory & reinstall CKEditor', |
169
|
1 |
|
CKEditorInstaller::CLEAR_KEEP => 'Keep the directory & reinstall CKEditor by overriding files', |
170
|
1 |
|
CKEditorInstaller::CLEAR_ABORT => 'Abort installation', |
171
|
1 |
|
], |
172
|
1 |
|
CKEditorInstaller::CLEAR_DROP, |
173
|
1 |
|
$input, |
174
|
|
|
$output |
175
|
1 |
|
); |
176
|
|
|
|
177
|
1 |
|
if (($key = array_search($result, $choices, true)) !== false) { |
178
|
|
|
$result = $key; |
179
|
|
|
} |
180
|
|
|
|
181
|
1 |
|
if ($result === CKEditorInstaller::CLEAR_DROP) { |
182
|
1 |
|
$this->comment(sprintf('Dropping CKEditor from "%s"', $data), $output); |
183
|
1 |
|
} |
184
|
|
|
|
185
|
1 |
|
return $result; |
186
|
|
|
|
187
|
10 |
|
case CKEditorInstaller::NOTIFY_CLEAR_ARCHIVE: |
188
|
10 |
|
$this->comment(sprintf('Dropping CKEditor ZIP archive "%s"', $data), $output); |
189
|
10 |
|
break; |
190
|
|
|
|
191
|
10 |
|
case CKEditorInstaller::NOTIFY_CLEAR_COMPLETE: |
192
|
1 |
|
$this->finishProgressBar($clear, $output); |
193
|
1 |
|
break; |
194
|
|
|
|
195
|
10 |
|
case CKEditorInstaller::NOTIFY_CLEAR_PROGRESS: |
196
|
1 |
|
$clear->advance(); |
197
|
1 |
|
break; |
198
|
|
|
|
199
|
10 |
|
case CKEditorInstaller::NOTIFY_CLEAR_SIZE: |
200
|
1 |
|
$this->startProgressBar($clear, $output, $data); |
201
|
1 |
|
break; |
202
|
|
|
|
203
|
10 |
|
case CKEditorInstaller::NOTIFY_DOWNLOAD: |
204
|
10 |
|
$this->comment(sprintf('Downloading CKEditor ZIP archive from "%s"', $data), $output); |
205
|
10 |
|
break; |
206
|
|
|
|
207
|
10 |
|
case CKEditorInstaller::NOTIFY_DOWNLOAD_COMPLETE: |
208
|
10 |
|
$this->finishProgressBar($download, $output); |
209
|
10 |
|
break; |
210
|
|
|
|
211
|
10 |
|
case CKEditorInstaller::NOTIFY_DOWNLOAD_PROGRESS: |
212
|
10 |
|
$this->advanceProgressBar($download, $data); |
213
|
10 |
|
break; |
214
|
|
|
|
215
|
10 |
|
case CKEditorInstaller::NOTIFY_DOWNLOAD_SIZE: |
216
|
10 |
|
$this->startProgressBar($download, $output, $data); |
217
|
10 |
|
break; |
218
|
|
|
|
219
|
10 |
|
case CKEditorInstaller::NOTIFY_EXTRACT: |
220
|
10 |
|
$this->comment(sprintf('Extracting CKEditor ZIP archive to "%s"', $data), $output); |
221
|
10 |
|
break; |
222
|
|
|
|
223
|
10 |
|
case CKEditorInstaller::NOTIFY_EXTRACT_COMPLETE: |
224
|
10 |
|
$this->finishProgressBar($extract, $output); |
225
|
10 |
|
break; |
226
|
|
|
|
227
|
10 |
|
case CKEditorInstaller::NOTIFY_EXTRACT_PROGRESS: |
228
|
10 |
|
$extract->advance(); |
229
|
10 |
|
break; |
230
|
|
|
|
231
|
10 |
|
case CKEditorInstaller::NOTIFY_EXTRACT_SIZE: |
232
|
10 |
|
$this->startProgressBar($extract, $output, $data); |
233
|
10 |
|
break; |
234
|
|
|
} |
235
|
10 |
|
}; |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
/** |
239
|
|
|
* @param OutputInterface $output |
240
|
|
|
*/ |
241
|
10 |
|
private function title(OutputInterface $output) |
242
|
|
|
{ |
243
|
10 |
|
$output->writeln([ |
244
|
10 |
|
'----------------------', |
245
|
8 |
|
'| CKEditor Installer |', |
246
|
8 |
|
'----------------------', |
247
|
8 |
|
'', |
248
|
8 |
|
]); |
249
|
10 |
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* @param string|string[] $message |
253
|
|
|
* @param OutputInterface $output |
254
|
|
|
*/ |
255
|
10 |
|
private function comment($message, OutputInterface $output) |
256
|
|
|
{ |
257
|
10 |
|
$output->writeln(' // '.$message); |
258
|
10 |
|
$output->writeln(''); |
259
|
10 |
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* @param string $message |
263
|
|
|
* @param OutputInterface $output |
264
|
|
|
*/ |
265
|
10 |
|
private function success($message, OutputInterface $output) |
266
|
|
|
{ |
267
|
10 |
|
$this->block('[OK] - '.$message, $output, 'green', 'black'); |
268
|
10 |
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* @param string $message |
272
|
|
|
* @param OutputInterface $output |
273
|
|
|
* @param string $background |
274
|
|
|
* @param string $font |
275
|
|
|
*/ |
276
|
10 |
|
private function block($message, OutputInterface $output, $background = null, $font = null) |
277
|
|
|
{ |
278
|
10 |
|
$options = []; |
279
|
|
|
|
280
|
10 |
|
if ($background !== null) { |
281
|
10 |
|
$options[] = 'bg='.$background; |
282
|
8 |
|
} |
283
|
|
|
|
284
|
10 |
|
if ($font !== null) { |
285
|
10 |
|
$options[] = 'fg='.$font; |
286
|
8 |
|
} |
287
|
|
|
|
288
|
10 |
|
$pattern = ' %s '; |
289
|
|
|
|
290
|
10 |
|
if (!empty($options)) { |
291
|
10 |
|
$pattern = '<'.implode(';', $options).'>'.$pattern.'</>'; |
292
|
8 |
|
} |
293
|
|
|
|
294
|
10 |
|
$output->writeln($block = sprintf($pattern, str_repeat(' ', strlen($message)))); |
295
|
10 |
|
$output->writeln(sprintf($pattern, $message)); |
296
|
10 |
|
$output->writeln($block); |
297
|
10 |
|
} |
298
|
|
|
|
299
|
|
|
/** |
300
|
|
|
* @param string|string[] $question |
301
|
|
|
* @param string[] $choices |
302
|
|
|
* @param string $default |
303
|
|
|
* @param InputInterface $input |
304
|
|
|
* @param OutputInterface $output |
305
|
|
|
* |
306
|
|
|
* @return string|null |
307
|
|
|
*/ |
308
|
1 |
|
private function choice($question, array $choices, $default, InputInterface $input, OutputInterface $output) |
309
|
|
|
{ |
310
|
1 |
|
$helper = new QuestionHelper(); |
311
|
|
|
|
312
|
1 |
|
$result = $helper->ask($input, $output, new ChoiceQuestion( |
313
|
1 |
|
$question, |
|
|
|
|
314
|
1 |
|
$choices, |
315
|
1 |
|
$choices[$default] |
316
|
1 |
|
)); |
317
|
|
|
|
318
|
1 |
|
$output->writeln(''); |
319
|
|
|
|
320
|
1 |
|
return $result; |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* @param OutputInterface $output |
325
|
|
|
* |
326
|
|
|
* @return ProgressBar|ProgressHelper |
327
|
|
|
*/ |
328
|
10 |
|
private function createProgressBar(OutputInterface $output) |
329
|
|
|
{ |
330
|
10 |
|
return class_exists(ProgressBar::class) ? new ProgressBar($output) : new ProgressHelper(); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
/** |
334
|
|
|
* @param ProgressBar|ProgressHelper $progress |
335
|
|
|
* @param OutputInterface $output |
336
|
|
|
* @param int|null $max |
337
|
|
|
*/ |
338
|
10 |
|
private function startProgressBar($progress, OutputInterface $output, $max = null) |
339
|
|
|
{ |
340
|
10 |
|
class_exists(ProgressBar::class) ? $progress->start($max) : $progress->start($output, $max); |
|
|
|
|
341
|
10 |
|
} |
342
|
|
|
|
343
|
|
|
/** |
344
|
|
|
* @param ProgressBar|ProgressHelper $progress |
345
|
|
|
* @param int $current |
346
|
|
|
*/ |
347
|
10 |
|
private function advanceProgressBar($progress, $current) |
348
|
|
|
{ |
349
|
10 |
|
class_exists(ProgressBar::class) ? $progress->setProgress($current) : $progress->setCurrent($current); |
|
|
|
|
350
|
10 |
|
} |
351
|
|
|
|
352
|
|
|
/** |
353
|
|
|
* @param ProgressBar|ProgressHelper $progress |
354
|
|
|
* @param OutputInterface $output |
355
|
|
|
*/ |
356
|
10 |
|
private function finishProgressBar($progress, OutputInterface $output) |
357
|
|
|
{ |
358
|
10 |
|
$progress->finish(); |
359
|
10 |
|
$output->writeln(['', '']); |
360
|
10 |
|
} |
361
|
|
|
} |
362
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.