Overview

Namespaces

  • Contrib
    • Bundle
      • CoverallsBundle
        • Console
        • Entity
      • CoverallsV1Bundle
        • Api
        • Collector
        • Command
        • Config
        • Entity
          • Git
    • Component
      • File
      • Log
      • System
        • Git
  • Guzzle
    • Batch
      • Exception
    • Cache
    • Common
      • Exception
    • Http
      • Curl
      • Exception
      • Message
      • QueryAggregator
    • Inflection
    • Iterator
    • Log
    • Parser
      • Cookie
      • Message
      • UriTemplate
      • Url
    • Plugin
      • Async
      • Backoff
      • Cache
      • Cookie
        • CookieJar
        • Exception
      • CurlAuth
      • ErrorResponse
        • Exception
      • History
      • Log
      • Md5
      • Mock
      • Oauth
    • Service
      • Builder
      • Command
        • Factory
        • LocationVisitor
          • Request
          • Response
      • Description
      • Exception
      • Resource
    • Stream
  • PHP
  • Psr
    • Log
  • Symfony
    • Component
      • Config
        • Definition
          • Builder
          • Exception
        • Exception
        • Loader
        • Resource
        • Util
      • Console
        • Command
        • Formatter
        • Helper
        • Input
        • Output
        • Tester
      • EventDispatcher
        • Debug
      • Finder
        • Adapter
        • Comparator
        • Exception
        • Expression
        • Iterator
        • Shell
      • Stopwatch
      • Yaml
        • Exception

Classes

  • Command
  • HelpCommand
  • ListCommand
  • Overview
  • Namespace
  • Class
  • Tree
  • Todo
  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\Input\InputDefinition;
 15: use Symfony\Component\Console\Input\InputOption;
 16: use Symfony\Component\Console\Input\InputArgument;
 17: use Symfony\Component\Console\Input\InputInterface;
 18: use Symfony\Component\Console\Output\OutputInterface;
 19: use Symfony\Component\Console\Application;
 20: use Symfony\Component\Console\Helper\HelperSet;
 21: 
 22: /**
 23:  * Base class for all commands.
 24:  *
 25:  * @author Fabien Potencier <fabien@symfony.com>
 26:  *
 27:  * @api
 28:  */
 29: class Command
 30: {
 31:     private $application;
 32:     private $name;
 33:     private $aliases;
 34:     private $definition;
 35:     private $help;
 36:     private $description;
 37:     private $ignoreValidationErrors;
 38:     private $applicationDefinitionMerged;
 39:     private $code;
 40:     private $synopsis;
 41:     private $helperSet;
 42: 
 43:     /**
 44:      * Constructor.
 45:      *
 46:      * @param string $name The name of the command
 47:      *
 48:      * @throws \LogicException When the command name is empty
 49:      *
 50:      * @api
 51:      */
 52:     public function __construct($name = null)
 53:     {
 54:         $this->definition = new InputDefinition();
 55:         $this->ignoreValidationErrors = false;
 56:         $this->applicationDefinitionMerged = false;
 57:         $this->aliases = array();
 58: 
 59:         if (null !== $name) {
 60:             $this->setName($name);
 61:         }
 62: 
 63:         $this->configure();
 64: 
 65:         if (!$this->name) {
 66:             throw new \LogicException('The command name cannot be empty.');
 67:         }
 68:     }
 69: 
 70:     /**
 71:      * Ignores validation errors.
 72:      *
 73:      * This is mainly useful for the help command.
 74:      */
 75:     public function ignoreValidationErrors()
 76:     {
 77:         $this->ignoreValidationErrors = true;
 78:     }
 79: 
 80:     /**
 81:      * Sets the application instance for this command.
 82:      *
 83:      * @param Application $application An Application instance
 84:      *
 85:      * @api
 86:      */
 87:     public function setApplication(Application $application = null)
 88:     {
 89:         $this->application = $application;
 90:         if ($application) {
 91:             $this->setHelperSet($application->getHelperSet());
 92:         } else {
 93:             $this->helperSet = null;
 94:         }
 95:     }
 96: 
 97:     /**
 98:      * Sets the helper set.
 99:      *
100:      * @param HelperSet $helperSet A HelperSet instance
101:      */
102:     public function setHelperSet(HelperSet $helperSet)
103:     {
104:         $this->helperSet = $helperSet;
105:     }
106: 
107:     /**
108:      * Gets the helper set.
109:      *
110:      * @return HelperSet A HelperSet instance
111:      */
112:     public function getHelperSet()
113:     {
114:         return $this->helperSet;
115:     }
116: 
117:     /**
118:      * Gets the application instance for this command.
119:      *
120:      * @return Application An Application instance
121:      *
122:      * @api
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 Boolean
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:      * @param InputInterface  $input  An InputInterface instance
158:      * @param OutputInterface $output An OutputInterface instance
159:      *
160:      * @return null|integer null or 0 if everything went fine, or an error code
161:      *
162:      * @throws \LogicException When this abstract method is not implemented
163:      * @see    setCode()
164:      */
165:     protected function execute(InputInterface $input, OutputInterface $output)
166:     {
167:         throw new \LogicException('You must override the execute() method in the concrete command class.');
168:     }
169: 
170:     /**
171:      * Interacts with the user.
172:      *
173:      * @param InputInterface  $input  An InputInterface instance
174:      * @param OutputInterface $output An OutputInterface instance
175:      */
176:     protected function interact(InputInterface $input, OutputInterface $output)
177:     {
178:     }
179: 
180:     /**
181:      * Initializes the command just after the input has been 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:      * @param InputInterface  $input  An InputInterface instance
187:      * @param OutputInterface $output An OutputInterface instance
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:      * @param InputInterface  $input  An InputInterface instance
201:      * @param OutputInterface $output An OutputInterface instance
202:      *
203:      * @return integer The command exit code
204:      *
205:      * @throws \Exception
206:      *
207:      * @see setCode()
208:      * @see execute()
209:      *
210:      * @api
211:      */
212:     public function run(InputInterface $input, OutputInterface $output)
213:     {
214:         // force the creation of the synopsis before the merge with the app definition
215:         $this->getSynopsis();
216: 
217:         // add the application arguments and options
218:         $this->mergeApplicationDefinition();
219: 
220:         // bind the input against the command specific arguments/options
221:         try {
222:             $input->bind($this->definition);
223:         } catch (\Exception $e) {
224:             if (!$this->ignoreValidationErrors) {
225:                 throw $e;
226:             }
227:         }
228: 
229:         $this->initialize($input, $output);
230: 
231:         if ($input->isInteractive()) {
232:             $this->interact($input, $output);
233:         }
234: 
235:         $input->validate();
236: 
237:         if ($this->code) {
238:             $statusCode = call_user_func($this->code, $input, $output);
239:         } else {
240:             $statusCode = $this->execute($input, $output);
241:         }
242: 
243:         return is_numeric($statusCode) ? $statusCode : 0;
244:     }
245: 
246:     /**
247:      * Sets the code to execute when running this command.
248:      *
249:      * If this method is used, it overrides the code defined
250:      * in the execute() method.
251:      *
252:      * @param callable $code A callable(InputInterface $input, OutputInterface $output)
253:      *
254:      * @return Command The current instance
255:      *
256:      * @throws \InvalidArgumentException
257:      *
258:      * @see execute()
259:      *
260:      * @api
261:      */
262:     public function setCode($code)
263:     {
264:         if (!is_callable($code)) {
265:             throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.');
266:         }
267: 
268:         $this->code = $code;
269: 
270:         return $this;
271:     }
272: 
273:     /**
274:      * Merges the application definition with the command definition.
275:      *
276:      * @param Boolean $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
277:      */
278:     private function mergeApplicationDefinition($mergeArgs = true)
279:     {
280:         if (null === $this->application || true === $this->applicationDefinitionMerged) {
281:             return;
282:         }
283: 
284:         if ($mergeArgs) {
285:             $currentArguments = $this->definition->getArguments();
286:             $this->definition->setArguments($this->application->getDefinition()->getArguments());
287:             $this->definition->addArguments($currentArguments);
288:         }
289: 
290:         $this->definition->addOptions($this->application->getDefinition()->getOptions());
291: 
292:         $this->applicationDefinitionMerged = true;
293:     }
294: 
295:     /**
296:      * Sets an array of argument and option instances.
297:      *
298:      * @param array|InputDefinition $definition An array of argument and option instances or a definition instance
299:      *
300:      * @return Command The current instance
301:      *
302:      * @api
303:      */
304:     public function setDefinition($definition)
305:     {
306:         if ($definition instanceof InputDefinition) {
307:             $this->definition = $definition;
308:         } else {
309:             $this->definition->setDefinition($definition);
310:         }
311: 
312:         $this->applicationDefinitionMerged = false;
313: 
314:         return $this;
315:     }
316: 
317:     /**
318:      * Gets the InputDefinition attached to this Command.
319:      *
320:      * @return InputDefinition An InputDefinition instance
321:      *
322:      * @api
323:      */
324:     public function getDefinition()
325:     {
326:         return $this->definition;
327:     }
328: 
329:     /**
330:      * Gets the InputDefinition to be used to create XML and Text representations of this Command.
331:      *
332:      * Can be overridden to provide the original command representation when it would otherwise
333:      * be changed by merging with the application InputDefinition.
334:      *
335:      * @return InputDefinition An InputDefinition instance
336:      */
337:     protected function getNativeDefinition()
338:     {
339:         return $this->getDefinition();
340:     }
341: 
342:     /**
343:      * Adds an argument.
344:      *
345:      * @param string  $name        The argument name
346:      * @param integer $mode        The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
347:      * @param string  $description A description text
348:      * @param mixed   $default     The default value (for InputArgument::OPTIONAL mode only)
349:      *
350:      * @return Command The current instance
351:      *
352:      * @api
353:      */
354:     public function addArgument($name, $mode = null, $description = '', $default = null)
355:     {
356:         $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
357: 
358:         return $this;
359:     }
360: 
361:     /**
362:      * Adds an option.
363:      *
364:      * @param string  $name        The option name
365:      * @param string  $shortcut    The shortcut (can be null)
366:      * @param integer $mode        The option mode: One of the InputOption::VALUE_* constants
367:      * @param string  $description A description text
368:      * @param mixed   $default     The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE)
369:      *
370:      * @return Command The current instance
371:      *
372:      * @api
373:      */
374:     public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
375:     {
376:         $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
377: 
378:         return $this;
379:     }
380: 
381:     /**
382:      * Sets the name of the command.
383:      *
384:      * This method can set both the namespace and the name if
385:      * you separate them by a colon (:)
386:      *
387:      *     $command->setName('foo:bar');
388:      *
389:      * @param string $name The command name
390:      *
391:      * @return Command The current instance
392:      *
393:      * @throws \InvalidArgumentException When command name given is empty
394:      *
395:      * @api
396:      */
397:     public function setName($name)
398:     {
399:         $this->validateName($name);
400: 
401:         $this->name = $name;
402: 
403:         return $this;
404:     }
405: 
406:     /**
407:      * Returns the command name.
408:      *
409:      * @return string The command name
410:      *
411:      * @api
412:      */
413:     public function getName()
414:     {
415:         return $this->name;
416:     }
417: 
418:     /**
419:      * Sets the description for the command.
420:      *
421:      * @param string $description The description for the command
422:      *
423:      * @return Command The current instance
424:      *
425:      * @api
426:      */
427:     public function setDescription($description)
428:     {
429:         $this->description = $description;
430: 
431:         return $this;
432:     }
433: 
434:     /**
435:      * Returns the description for the command.
436:      *
437:      * @return string The description for the command
438:      *
439:      * @api
440:      */
441:     public function getDescription()
442:     {
443:         return $this->description;
444:     }
445: 
446:     /**
447:      * Sets the help for the command.
448:      *
449:      * @param string $help The help for the command
450:      *
451:      * @return Command The current instance
452:      *
453:      * @api
454:      */
455:     public function setHelp($help)
456:     {
457:         $this->help = $help;
458: 
459:         return $this;
460:     }
461: 
462:     /**
463:      * Returns the help for the command.
464:      *
465:      * @return string The help for the command
466:      *
467:      * @api
468:      */
469:     public function getHelp()
470:     {
471:         return $this->help;
472:     }
473: 
474:     /**
475:      * Returns the processed help for the command replacing the %command.name% and
476:      * %command.full_name% patterns with the real values dynamically.
477:      *
478:      * @return string  The processed help for the command
479:      */
480:     public function getProcessedHelp()
481:     {
482:         $name = $this->name;
483: 
484:         $placeholders = array(
485:             '%command.name%',
486:             '%command.full_name%'
487:         );
488:         $replacements = array(
489:             $name,
490:             $_SERVER['PHP_SELF'].' '.$name
491:         );
492: 
493:         return str_replace($placeholders, $replacements, $this->getHelp());
494:     }
495: 
496:     /**
497:      * Sets the aliases for the command.
498:      *
499:      * @param array $aliases An array of aliases for the command
500:      *
501:      * @return Command The current instance
502:      *
503:      * @api
504:      */
505:     public function setAliases($aliases)
506:     {
507:         foreach ($aliases as $alias) {
508:             $this->validateName($alias);
509:         }
510: 
511:         $this->aliases = $aliases;
512: 
513:         return $this;
514:     }
515: 
516:     /**
517:      * Returns the aliases for the command.
518:      *
519:      * @return array An array of aliases for the command
520:      *
521:      * @api
522:      */
523:     public function getAliases()
524:     {
525:         return $this->aliases;
526:     }
527: 
528:     /**
529:      * Returns the synopsis for the command.
530:      *
531:      * @return string The synopsis
532:      */
533:     public function getSynopsis()
534:     {
535:         if (null === $this->synopsis) {
536:             $this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis()));
537:         }
538: 
539:         return $this->synopsis;
540:     }
541: 
542:     /**
543:      * Gets a helper instance by name.
544:      *
545:      * @param string $name The helper name
546:      *
547:      * @return mixed The helper value
548:      *
549:      * @throws \InvalidArgumentException if the helper is not defined
550:      *
551:      * @api
552:      */
553:     public function getHelper($name)
554:     {
555:         return $this->helperSet->get($name);
556:     }
557: 
558:     /**
559:      * Returns a text representation of the command.
560:      *
561:      * @return string A string representing the command
562:      */
563:     public function asText()
564:     {
565:         if ($this->application && !$this->applicationDefinitionMerged) {
566:             $this->getSynopsis();
567:             $this->mergeApplicationDefinition(false);
568:         }
569: 
570:         $messages = array(
571:             '<comment>Usage:</comment>',
572:             ' '.$this->getSynopsis(),
573:             '',
574:         );
575: 
576:         if ($this->getAliases()) {
577:             $messages[] = '<comment>Aliases:</comment> <info>'.implode(', ', $this->getAliases()).'</info>';
578:         }
579: 
580:         $messages[] = $this->getNativeDefinition()->asText();
581: 
582:         if ($help = $this->getProcessedHelp()) {
583:             $messages[] = '<comment>Help:</comment>';
584:             $messages[] = ' '.str_replace("\n", "\n ", $help)."\n";
585:         }
586: 
587:         return implode("\n", $messages);
588:     }
589: 
590:     /**
591:      * Returns an XML representation of the command.
592:      *
593:      * @param Boolean $asDom Whether to return a DOM or an XML string
594:      *
595:      * @return string|DOMDocument An XML string representing the command
596:      */
597:     public function asXml($asDom = false)
598:     {
599:         if ($this->application && !$this->applicationDefinitionMerged) {
600:             $this->getSynopsis();
601:             $this->mergeApplicationDefinition(false);
602:         }
603: 
604:         $dom = new \DOMDocument('1.0', 'UTF-8');
605:         $dom->formatOutput = true;
606:         $dom->appendChild($commandXML = $dom->createElement('command'));
607:         $commandXML->setAttribute('id', $this->name);
608:         $commandXML->setAttribute('name', $this->name);
609: 
610:         $commandXML->appendChild($usageXML = $dom->createElement('usage'));
611:         $usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), '')));
612: 
613:         $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
614:         $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $this->getDescription())));
615: 
616:         $commandXML->appendChild($helpXML = $dom->createElement('help'));
617:         $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $this->getProcessedHelp())));
618: 
619:         $commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
620:         foreach ($this->getAliases() as $alias) {
621:             $aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
622:             $aliasXML->appendChild($dom->createTextNode($alias));
623:         }
624: 
625:         $definition = $this->getNativeDefinition()->asXml(true);
626:         $commandXML->appendChild($dom->importNode($definition->getElementsByTagName('arguments')->item(0), true));
627:         $commandXML->appendChild($dom->importNode($definition->getElementsByTagName('options')->item(0), true));
628: 
629:         return $asDom ? $dom : $dom->saveXml();
630:     }
631: 
632:     private function validateName($name)
633:     {
634:         if (!preg_match('/^[^\:]+(\:[^\:]+)*$/', $name)) {
635:             throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
636:         }
637:     }
638: }
639: 
php-coveralls API documentation generated by ApiGen 2.8.0