PluginProbe
Depicter — Popup & Slider Builder / 1.3.3
Depicter — Popup & Slider Builder v1.3.3
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / vendor / symfony / console / Command / Command.php

Command.php in Depicter — Popup & Slider Builder 1.3.3, at vendor/symfony/console/Command/Command.php

655 lines 18.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Symfony\Component\Console\Command;
13
14 use Symfony\Component\Console\Application;
15 use Symfony\Component\Console\Exception\ExceptionInterface;
16 use Symfony\Component\Console\Exception\InvalidArgumentException;
17 use Symfony\Component\Console\Exception\LogicException;
18 use Symfony\Component\Console\Helper\HelperSet;
19 use Symfony\Component\Console\Input\InputArgument;
20 use Symfony\Component\Console\Input\InputDefinition;
21 use Symfony\Component\Console\Input\InputInterface;
22 use Symfony\Component\Console\Input\InputOption;
23 use Symfony\Component\Console\Output\OutputInterface;
24
25 /**
26 * Base class for all commands.
27 *
28 * @author Fabien Potencier <fabien@symfony.com>
29 */
30 class Command
31 {
32 // see https://tldp.org/LDP/abs/html/exitcodes.html
33 public const SUCCESS = 0;
34 public const FAILURE = 1;
35
36 /**
37 * @var string|null The default command name
38 */
39 protected static $defaultName;
40
41 private $application;
42 private $name;
43 private $processTitle;
44 private $aliases = [];
45 private $definition;
46 private $hidden = false;
47 private $help = '';
48 private $description = '';
49 private $ignoreValidationErrors = false;
50 private $applicationDefinitionMerged = false;
51 private $applicationDefinitionMergedWithArgs = false;
52 private $code;
53 private $synopsis = [];
54 private $usages = [];
55 private $helperSet;
56
57 /**
58 * @return string|null The default command name or null when no default name is set
59 */
60 public static function getDefaultName()
61 {
62 $class = static::class;
63 $r = new \ReflectionProperty($class, 'defaultName');
64
65 return $class === $r->class ? static::$defaultName : null;
66 }
67
68 /**
69 * @param string|null $name The name of the command; passing null means it must be set in configure()
70 *
71 * @throws LogicException When the command name is empty
72 */
73 public function __construct(string $name = null)
74 {
75 $this->definition = new InputDefinition();
76
77 if (null !== $name || null !== $name = static::getDefaultName()) {
78 $this->setName($name);
79 }
80
81 $this->configure();
82 }
83
84 /**
85 * Ignores validation errors.
86 *
87 * This is mainly useful for the help command.
88 */
89 public function ignoreValidationErrors()
90 {
91 $this->ignoreValidationErrors = true;
92 }
93
94 public function setApplication(Application $application = null)
95 {
96 $this->application = $application;
97 if ($application) {
98 $this->setHelperSet($application->getHelperSet());
99 } else {
100 $this->helperSet = null;
101 }
102 }
103
104 public function setHelperSet(HelperSet $helperSet)
105 {
106 $this->helperSet = $helperSet;
107 }
108
109 /**
110 * Gets the helper set.
111 *
112 * @return HelperSet|null A HelperSet instance
113 */
114 public function getHelperSet()
115 {
116 return $this->helperSet;
117 }
118
119 /**
120 * Gets the application instance for this command.
121 *
122 * @return Application|null An Application instance
123 */
124 public function getApplication()
125 {
126 return $this->application;
127 }
128
129 /**
130 * Checks whether the command is enabled or not in the current environment.
131 *
132 * Override this to check for x or y and return false if the command can not
133 * run properly under the current conditions.
134 *
135 * @return bool
136 */
137 public function isEnabled()
138 {
139 return true;
140 }
141
142 /**
143 * Configures the current command.
144 */
145 protected function configure()
146 {
147 }
148
149 /**
150 * Executes the current command.
151 *
152 * This method is not abstract because you can use this class
153 * as a concrete class. In this case, instead of defining the
154 * execute() method, you set the code to execute by passing
155 * a Closure to the setCode() method.
156 *
157 * @return int 0 if everything went fine, or an exit code
158 *
159 * @throws LogicException When this abstract method is not implemented
160 *
161 * @see setCode()
162 */
163 protected function execute(InputInterface $input, OutputInterface $output)
164 {
165 throw new LogicException('You must override the execute() method in the concrete command class.');
166 }
167
168 /**
169 * Interacts with the user.
170 *
171 * This method is executed before the InputDefinition is validated.
172 * This means that this is the only place where the command can
173 * interactively ask for values of missing required arguments.
174 */
175 protected function interact(InputInterface $input, OutputInterface $output)
176 {
177 }
178
179 /**
180 * Initializes the command after the input has been bound and before the input
181 * is validated.
182 *
183 * This is mainly useful when a lot of commands extends one main command
184 * where some things need to be initialized based on the input arguments and options.
185 *
186 * @see InputInterface::bind()
187 * @see InputInterface::validate()
188 */
189 protected function initialize(InputInterface $input, OutputInterface $output)
190 {
191 }
192
193 /**
194 * Runs the command.
195 *
196 * The code to execute is either defined directly with the
197 * setCode() method or by overriding the execute() method
198 * in a sub-class.
199 *
200 * @return int The command exit code
201 *
202 * @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}.
203 *
204 * @see setCode()
205 * @see execute()
206 */
207 public function run(InputInterface $input, OutputInterface $output)
208 {
209 // force the creation of the synopsis before the merge with the app definition
210 $this->getSynopsis(true);
211 $this->getSynopsis(false);
212
213 // add the application arguments and options
214 $this->mergeApplicationDefinition();
215
216 // bind the input against the command specific arguments/options
217 try {
218 $input->bind($this->definition);
219 } catch (ExceptionInterface $e) {
220 if (!$this->ignoreValidationErrors) {
221 throw $e;
222 }
223 }
224
225 $this->initialize($input, $output);
226
227 if (null !== $this->processTitle) {
228 if (\function_exists('cli_set_process_title')) {
229 if (!@cli_set_process_title($this->processTitle)) {
230 if ('Darwin' === \PHP_OS) {
231 $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
232 } else {
233 cli_set_process_title($this->processTitle);
234 }
235 }
236 } elseif (\function_exists('setproctitle')) {
237 setproctitle($this->processTitle);
238 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
239 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
240 }
241 }
242
243 if ($input->isInteractive()) {
244 $this->interact($input, $output);
245 }
246
247 // The command name argument is often omitted when a command is executed directly with its run() method.
248 // It would fail the validation if we didn't make sure the command argument is present,
249 // since it's required by the application.
250 if ($input->hasArgument('command') && null === $input->getArgument('command')) {
251 $input->setArgument('command', $this->getName());
252 }
253
254 $input->validate();
255
256 if ($this->code) {
257 $statusCode = ($this->code)($input, $output);
258 } else {
259 $statusCode = $this->execute($input, $output);
260
261 if (!\is_int($statusCode)) {
262 throw new \TypeError(sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, get_debug_type($statusCode)));
263 }
264 }
265
266 return is_numeric($statusCode) ? (int) $statusCode : 0;
267 }
268
269 /**
270 * Sets the code to execute when running this command.
271 *
272 * If this method is used, it overrides the code defined
273 * in the execute() method.
274 *
275 * @param callable $code A callable(InputInterface $input, OutputInterface $output)
276 *
277 * @return $this
278 *
279 * @throws InvalidArgumentException
280 *
281 * @see execute()
282 */
283 public function setCode(callable $code)
284 {
285 if ($code instanceof \Closure) {
286 $r = new \ReflectionFunction($code);
287 if (null === $r->getClosureThis()) {
288 set_error_handler(static function () {});
289 try {
290 if ($c = \Closure::bind($code, $this)) {
291 $code = $c;
292 }
293 } finally {
294 restore_error_handler();
295 }
296 }
297 }
298
299 $this->code = $code;
300
301 return $this;
302 }
303
304 /**
305 * Merges the application definition with the command definition.
306 *
307 * This method is not part of public API and should not be used directly.
308 *
309 * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
310 */
311 public function mergeApplicationDefinition(bool $mergeArgs = true)
312 {
313 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
314 return;
315 }
316
317 $this->definition->addOptions($this->application->getDefinition()->getOptions());
318
319 $this->applicationDefinitionMerged = true;
320
321 if ($mergeArgs) {
322 $currentArguments = $this->definition->getArguments();
323 $this->definition->setArguments($this->application->getDefinition()->getArguments());
324 $this->definition->addArguments($currentArguments);
325
326 $this->applicationDefinitionMergedWithArgs = true;
327 }
328 }
329
330 /**
331 * Sets an array of argument and option instances.
332 *
333 * @param array|InputDefinition $definition An array of argument and option instances or a definition instance
334 *
335 * @return $this
336 */
337 public function setDefinition($definition)
338 {
339 if ($definition instanceof InputDefinition) {
340 $this->definition = $definition;
341 } else {
342 $this->definition->setDefinition($definition);
343 }
344
345 $this->applicationDefinitionMerged = false;
346
347 return $this;
348 }
349
350 /**
351 * Gets the InputDefinition attached to this Command.
352 *
353 * @return InputDefinition An InputDefinition instance
354 */
355 public function getDefinition()
356 {
357 if (null === $this->definition) {
358 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class));
359 }
360
361 return $this->definition;
362 }
363
364 /**
365 * Gets the InputDefinition to be used to create representations of this Command.
366 *
367 * Can be overridden to provide the original command representation when it would otherwise
368 * be changed by merging with the application InputDefinition.
369 *
370 * This method is not part of public API and should not be used directly.
371 *
372 * @return InputDefinition An InputDefinition instance
373 */
374 public function getNativeDefinition()
375 {
376 return $this->getDefinition();
377 }
378
379 /**
380 * Adds an argument.
381 *
382 * @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
383 * @param string|string[]|null $default The default value (for InputArgument::OPTIONAL mode only)
384 *
385 * @throws InvalidArgumentException When argument mode is not valid
386 *
387 * @return $this
388 */
389 public function addArgument(string $name, int $mode = null, string $description = '', $default = null)
390 {
391 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
392
393 return $this;
394 }
395
396 /**
397 * Adds an option.
398 *
399 * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
400 * @param int|null $mode The option mode: One of the InputOption::VALUE_* constants
401 * @param string|string[]|int|bool|null $default The default value (must be null for InputOption::VALUE_NONE)
402 *
403 * @throws InvalidArgumentException If option mode is invalid or incompatible
404 *
405 * @return $this
406 */
407 public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null)
408 {
409 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
410
411 return $this;
412 }
413
414 /**
415 * Sets the name of the command.
416 *
417 * This method can set both the namespace and the name if
418 * you separate them by a colon (:)
419 *
420 * $command->setName('foo:bar');
421 *
422 * @return $this
423 *
424 * @throws InvalidArgumentException When the name is invalid
425 */
426 public function setName(string $name)
427 {
428 $this->validateName($name);
429
430 $this->name = $name;
431
432 return $this;
433 }
434
435 /**
436 * Sets the process title of the command.
437 *
438 * This feature should be used only when creating a long process command,
439 * like a daemon.
440 *
441 * @return $this
442 */
443 public function setProcessTitle(string $title)
444 {
445 $this->processTitle = $title;
446
447 return $this;
448 }
449
450 /**
451 * Returns the command name.
452 *
453 * @return string|null
454 */
455 public function getName()
456 {
457 return $this->name;
458 }
459
460 /**
461 * @param bool $hidden Whether or not the command should be hidden from the list of commands
462 * The default value will be true in Symfony 6.0
463 *
464 * @return Command The current instance
465 *
466 * @final since Symfony 5.1
467 */
468 public function setHidden(bool $hidden /*= true*/)
469 {
470 $this->hidden = $hidden;
471
472 return $this;
473 }
474
475 /**
476 * @return bool whether the command should be publicly shown or not
477 */
478 public function isHidden()
479 {
480 return $this->hidden;
481 }
482
483 /**
484 * Sets the description for the command.
485 *
486 * @return $this
487 */
488 public function setDescription(string $description)
489 {
490 $this->description = $description;
491
492 return $this;
493 }
494
495 /**
496 * Returns the description for the command.
497 *
498 * @return string The description for the command
499 */
500 public function getDescription()
501 {
502 return $this->description;
503 }
504
505 /**
506 * Sets the help for the command.
507 *
508 * @return $this
509 */
510 public function setHelp(string $help)
511 {
512 $this->help = $help;
513
514 return $this;
515 }
516
517 /**
518 * Returns the help for the command.
519 *
520 * @return string The help for the command
521 */
522 public function getHelp()
523 {
524 return $this->help;
525 }
526
527 /**
528 * Returns the processed help for the command replacing the %command.name% and
529 * %command.full_name% patterns with the real values dynamically.
530 *
531 * @return string The processed help for the command
532 */
533 public function getProcessedHelp()
534 {
535 $name = $this->name;
536 $isSingleCommand = $this->application && $this->application->isSingleCommand();
537
538 $placeholders = [
539 '%command.name%',
540 '%command.full_name%',
541 ];
542 $replacements = [
543 $name,
544 $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'].' '.$name,
545 ];
546
547 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
548 }
549
550 /**
551 * Sets the aliases for the command.
552 *
553 * @param string[] $aliases An array of aliases for the command
554 *
555 * @return $this
556 *
557 * @throws InvalidArgumentException When an alias is invalid
558 */
559 public function setAliases(iterable $aliases)
560 {
561 foreach ($aliases as $alias) {
562 $this->validateName($alias);
563 }
564
565 $this->aliases = $aliases;
566
567 return $this;
568 }
569
570 /**
571 * Returns the aliases for the command.
572 *
573 * @return array An array of aliases for the command
574 */
575 public function getAliases()
576 {
577 return $this->aliases;
578 }
579
580 /**
581 * Returns the synopsis for the command.
582 *
583 * @param bool $short Whether to show the short version of the synopsis (with options folded) or not
584 *
585 * @return string The synopsis
586 */
587 public function getSynopsis(bool $short = false)
588 {
589 $key = $short ? 'short' : 'long';
590
591 if (!isset($this->synopsis[$key])) {
592 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
593 }
594
595 return $this->synopsis[$key];
596 }
597
598 /**
599 * Add a command usage example, it'll be prefixed with the command name.
600 *
601 * @return $this
602 */
603 public function addUsage(string $usage)
604 {
605 if (0 !== strpos($usage, $this->name)) {
606 $usage = sprintf('%s %s', $this->name, $usage);
607 }
608
609 $this->usages[] = $usage;
610
611 return $this;
612 }
613
614 /**
615 * Returns alternative usages of the command.
616 *
617 * @return array
618 */
619 public function getUsages()
620 {
621 return $this->usages;
622 }
623
624 /**
625 * Gets a helper instance by name.
626 *
627 * @return mixed The helper value
628 *
629 * @throws LogicException if no HelperSet is defined
630 * @throws InvalidArgumentException if the helper is not defined
631 */
632 public function getHelper(string $name)
633 {
634 if (null === $this->helperSet) {
635 throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
636 }
637
638 return $this->helperSet->get($name);
639 }
640
641 /**
642 * Validates a command name.
643 *
644 * It must be non-empty and parts can optionally be separated by ":".
645 *
646 * @throws InvalidArgumentException When the name is invalid
647 */
648 private function validateName(string $name)
649 {
650 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
651 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
652 }
653 }
654 }
655