CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.7 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.7
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • Arguments
  • Command
  • CommandCollection
  • CommandFactory
  • CommandRunner
  • ConsoleErrorHandler
  • ConsoleInput
  • ConsoleInputArgument
  • ConsoleInputOption
  • ConsoleInputSubcommand
  • ConsoleIo
  • ConsoleOptionParser
  • ConsoleOutput
  • Helper
  • HelperRegistry
  • HelpFormatter
  • Shell
  • ShellDispatcher
  • TaskRegistry

Interfaces

  • CommandCollectionAwareInterface
  • CommandFactoryInterface
   1: <?php
   2: /**
   3:  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
   4:  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
   5:  *
   6:  * Licensed under The MIT License
   7:  * For full copyright and license information, please see the LICENSE.txt
   8:  * Redistributions of files must retain the above copyright notice.
   9:  *
  10:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11:  * @link          https://cakephp.org CakePHP(tm) Project
  12:  * @since         2.0.0
  13:  * @license       https://opensource.org/licenses/mit-license.php MIT License
  14:  */
  15: namespace Cake\Console;
  16: 
  17: use Cake\Console\Exception\ConsoleException;
  18: use Cake\Utility\Inflector;
  19: use LogicException;
  20: 
  21: /**
  22:  * Handles parsing the ARGV in the command line and provides support
  23:  * for GetOpt compatible option definition. Provides a builder pattern implementation
  24:  * for creating shell option parsers.
  25:  *
  26:  * ### Options
  27:  *
  28:  * Named arguments come in two forms, long and short. Long arguments are preceded
  29:  * by two - and give a more verbose option name. i.e. `--version`. Short arguments are
  30:  * preceded by one - and are only one character long. They usually match with a long option,
  31:  * and provide a more terse alternative.
  32:  *
  33:  * ### Using Options
  34:  *
  35:  * Options can be defined with both long and short forms. By using `$parser->addOption()`
  36:  * you can define new options. The name of the option is used as its long form, and you
  37:  * can supply an additional short form, with the `short` option. Short options should
  38:  * only be one letter long. Using more than one letter for a short option will raise an exception.
  39:  *
  40:  * Calling options can be done using syntax similar to most *nix command line tools. Long options
  41:  * cane either include an `=` or leave it out.
  42:  *
  43:  * `cake myshell command --connection default --name=something`
  44:  *
  45:  * Short options can be defined singly or in groups.
  46:  *
  47:  * `cake myshell command -cn`
  48:  *
  49:  * Short options can be combined into groups as seen above. Each letter in a group
  50:  * will be treated as a separate option. The previous example is equivalent to:
  51:  *
  52:  * `cake myshell command -c -n`
  53:  *
  54:  * Short options can also accept values:
  55:  *
  56:  * `cake myshell command -c default`
  57:  *
  58:  * ### Positional arguments
  59:  *
  60:  * If no positional arguments are defined, all of them will be parsed. If you define positional
  61:  * arguments any arguments greater than those defined will cause exceptions. Additionally you can
  62:  * declare arguments as optional, by setting the required param to false.
  63:  *
  64:  * ```
  65:  * $parser->addArgument('model', ['required' => false]);
  66:  * ```
  67:  *
  68:  * ### Providing Help text
  69:  *
  70:  * By providing help text for your positional arguments and named arguments, the ConsoleOptionParser
  71:  * can generate a help display for you. You can view the help for shells by using the `--help` or `-h` switch.
  72:  */
  73: class ConsoleOptionParser
  74: {
  75: 
  76:     /**
  77:      * Description text - displays before options when help is generated
  78:      *
  79:      * @see \Cake\Console\ConsoleOptionParser::description()
  80:      * @var string
  81:      */
  82:     protected $_description;
  83: 
  84:     /**
  85:      * Epilog text - displays after options when help is generated
  86:      *
  87:      * @see \Cake\Console\ConsoleOptionParser::epilog()
  88:      * @var string
  89:      */
  90:     protected $_epilog;
  91: 
  92:     /**
  93:      * Option definitions.
  94:      *
  95:      * @see \Cake\Console\ConsoleOptionParser::addOption()
  96:      * @var \Cake\Console\ConsoleInputOption[]
  97:      */
  98:     protected $_options = [];
  99: 
 100:     /**
 101:      * Map of short -> long options, generated when using addOption()
 102:      *
 103:      * @var array
 104:      */
 105:     protected $_shortOptions = [];
 106: 
 107:     /**
 108:      * Positional argument definitions.
 109:      *
 110:      * @see \Cake\Console\ConsoleOptionParser::addArgument()
 111:      * @var \Cake\Console\ConsoleInputArgument[]
 112:      */
 113:     protected $_args = [];
 114: 
 115:     /**
 116:      * Subcommands for this Shell.
 117:      *
 118:      * @see \Cake\Console\ConsoleOptionParser::addSubcommand()
 119:      * @var \Cake\Console\ConsoleInputSubcommand[]
 120:      */
 121:     protected $_subcommands = [];
 122: 
 123:     /**
 124:      * Subcommand sorting option
 125:      *
 126:      * @var bool
 127:      */
 128:     protected $_subcommandSort = true;
 129: 
 130:     /**
 131:      * Command name.
 132:      *
 133:      * @var string
 134:      */
 135:     protected $_command = '';
 136: 
 137:     /**
 138:      * Array of args (argv).
 139:      *
 140:      * @var array
 141:      */
 142:     protected $_tokens = [];
 143: 
 144:     /**
 145:      * Root alias used in help output
 146:      *
 147:      * @see \Cake\Console\HelpFormatter::setAlias()
 148:      * @var string
 149:      */
 150:     protected $rootName = 'cake';
 151: 
 152:     /**
 153:      * Construct an OptionParser so you can define its behavior
 154:      *
 155:      * @param string|null $command The command name this parser is for. The command name is used for generating help.
 156:      * @param bool $defaultOptions Whether you want the verbose and quiet options set. Setting
 157:      *  this to false will prevent the addition of `--verbose` & `--quiet` options.
 158:      */
 159:     public function __construct($command = null, $defaultOptions = true)
 160:     {
 161:         $this->setCommand($command);
 162: 
 163:         $this->addOption('help', [
 164:             'short' => 'h',
 165:             'help' => 'Display this help.',
 166:             'boolean' => true
 167:         ]);
 168: 
 169:         if ($defaultOptions) {
 170:             $this->addOption('verbose', [
 171:                 'short' => 'v',
 172:                 'help' => 'Enable verbose output.',
 173:                 'boolean' => true
 174:             ])->addOption('quiet', [
 175:                 'short' => 'q',
 176:                 'help' => 'Enable quiet output.',
 177:                 'boolean' => true
 178:             ]);
 179:         }
 180:     }
 181: 
 182:     /**
 183:      * Static factory method for creating new OptionParsers so you can chain methods off of them.
 184:      *
 185:      * @param string|null $command The command name this parser is for. The command name is used for generating help.
 186:      * @param bool $defaultOptions Whether you want the verbose and quiet options set.
 187:      * @return static
 188:      */
 189:     public static function create($command, $defaultOptions = true)
 190:     {
 191:         return new static($command, $defaultOptions);
 192:     }
 193: 
 194:     /**
 195:      * Build a parser from an array. Uses an array like
 196:      *
 197:      * ```
 198:      * $spec = [
 199:      *      'description' => 'text',
 200:      *      'epilog' => 'text',
 201:      *      'arguments' => [
 202:      *          // list of arguments compatible with addArguments.
 203:      *      ],
 204:      *      'options' => [
 205:      *          // list of options compatible with addOptions
 206:      *      ],
 207:      *      'subcommands' => [
 208:      *          // list of subcommands to add.
 209:      *      ]
 210:      * ];
 211:      * ```
 212:      *
 213:      * @param array $spec The spec to build the OptionParser with.
 214:      * @param bool $defaultOptions Whether you want the verbose and quiet options set.
 215:      * @return static
 216:      */
 217:     public static function buildFromArray($spec, $defaultOptions = true)
 218:     {
 219:         $parser = new static($spec['command'], $defaultOptions);
 220:         if (!empty($spec['arguments'])) {
 221:             $parser->addArguments($spec['arguments']);
 222:         }
 223:         if (!empty($spec['options'])) {
 224:             $parser->addOptions($spec['options']);
 225:         }
 226:         if (!empty($spec['subcommands'])) {
 227:             $parser->addSubcommands($spec['subcommands']);
 228:         }
 229:         if (!empty($spec['description'])) {
 230:             $parser->setDescription($spec['description']);
 231:         }
 232:         if (!empty($spec['epilog'])) {
 233:             $parser->setEpilog($spec['epilog']);
 234:         }
 235: 
 236:         return $parser;
 237:     }
 238: 
 239:     /**
 240:      * Returns an array representation of this parser.
 241:      *
 242:      * @return array
 243:      */
 244:     public function toArray()
 245:     {
 246:         $result = [
 247:             'command' => $this->_command,
 248:             'arguments' => $this->_args,
 249:             'options' => $this->_options,
 250:             'subcommands' => $this->_subcommands,
 251:             'description' => $this->_description,
 252:             'epilog' => $this->_epilog
 253:         ];
 254: 
 255:         return $result;
 256:     }
 257: 
 258:     /**
 259:      * Get or set the command name for shell/task.
 260:      *
 261:      * @param array|\Cake\Console\ConsoleOptionParser $spec ConsoleOptionParser or spec to merge with.
 262:      * @return $this
 263:      */
 264:     public function merge($spec)
 265:     {
 266:         if ($spec instanceof ConsoleOptionParser) {
 267:             $spec = $spec->toArray();
 268:         }
 269:         if (!empty($spec['arguments'])) {
 270:             $this->addArguments($spec['arguments']);
 271:         }
 272:         if (!empty($spec['options'])) {
 273:             $this->addOptions($spec['options']);
 274:         }
 275:         if (!empty($spec['subcommands'])) {
 276:             $this->addSubcommands($spec['subcommands']);
 277:         }
 278:         if (!empty($spec['description'])) {
 279:             $this->setDescription($spec['description']);
 280:         }
 281:         if (!empty($spec['epilog'])) {
 282:             $this->setEpilog($spec['epilog']);
 283:         }
 284: 
 285:         return $this;
 286:     }
 287: 
 288:     /**
 289:      * Sets the command name for shell/task.
 290:      *
 291:      * @param string $text The text to set.
 292:      * @return $this
 293:      */
 294:     public function setCommand($text)
 295:     {
 296:         $this->_command = Inflector::underscore($text);
 297: 
 298:         return $this;
 299:     }
 300: 
 301:     /**
 302:      * Gets the command name for shell/task.
 303:      *
 304:      * @return string The value of the command.
 305:      */
 306:     public function getCommand()
 307:     {
 308:         return $this->_command;
 309:     }
 310: 
 311:     /**
 312:      * Gets or sets the command name for shell/task.
 313:      *
 314:      * @deprecated 3.4.0 Use setCommand()/getCommand() instead.
 315:      * @param string|null $text The text to set, or null if you want to read
 316:      * @return string|$this If reading, the value of the command. If setting $this will be returned.
 317:      */
 318:     public function command($text = null)
 319:     {
 320:         deprecationWarning(
 321:             'ConsoleOptionParser::command() is deprecated. ' .
 322:             'Use ConsoleOptionParser::setCommand()/getCommand() instead.'
 323:         );
 324:         if ($text !== null) {
 325:             return $this->setCommand($text);
 326:         }
 327: 
 328:         return $this->getCommand();
 329:     }
 330: 
 331:     /**
 332:      * Sets the description text for shell/task.
 333:      *
 334:      * @param string|array $text The text to set. If an array the
 335:      *   text will be imploded with "\n".
 336:      * @return $this
 337:      */
 338:     public function setDescription($text)
 339:     {
 340:         if (is_array($text)) {
 341:             $text = implode("\n", $text);
 342:         }
 343:         $this->_description = $text;
 344: 
 345:         return $this;
 346:     }
 347: 
 348:     /**
 349:      * Gets the description text for shell/task.
 350:      *
 351:      * @return string The value of the description
 352:      */
 353:     public function getDescription()
 354:     {
 355:         return $this->_description;
 356:     }
 357: 
 358:     /**
 359:      * Get or set the description text for shell/task.
 360:      *
 361:      * @deprecated 3.4.0 Use setDescription()/getDescription() instead.
 362:      * @param string|array|null $text The text to set, or null if you want to read. If an array the
 363:      *   text will be imploded with "\n".
 364:      * @return string|$this If reading, the value of the description. If setting $this will be returned.
 365:      */
 366:     public function description($text = null)
 367:     {
 368:         deprecationWarning(
 369:             'ConsoleOptionParser::description() is deprecated. ' .
 370:             'Use ConsoleOptionParser::setDescription()/getDescription() instead.'
 371:         );
 372:         if ($text !== null) {
 373:             return $this->setDescription($text);
 374:         }
 375: 
 376:         return $this->getDescription();
 377:     }
 378: 
 379:     /**
 380:      * Sets an epilog to the parser. The epilog is added to the end of
 381:      * the options and arguments listing when help is generated.
 382:      *
 383:      * @param string|array $text The text to set. If an array the text will
 384:      *   be imploded with "\n".
 385:      * @return $this
 386:      */
 387:     public function setEpilog($text)
 388:     {
 389:         if (is_array($text)) {
 390:             $text = implode("\n", $text);
 391:         }
 392:         $this->_epilog = $text;
 393: 
 394:         return $this;
 395:     }
 396: 
 397:     /**
 398:      * Gets the epilog.
 399:      *
 400:      * @return string The value of the epilog.
 401:      */
 402:     public function getEpilog()
 403:     {
 404:         return $this->_epilog;
 405:     }
 406: 
 407:     /**
 408:      * Gets or sets an epilog to the parser. The epilog is added to the end of
 409:      * the options and arguments listing when help is generated.
 410:      *
 411:      * @deprecated 3.4.0 Use setEpilog()/getEpilog() instead.
 412:      * @param string|array|null $text Text when setting or null when reading. If an array the text will
 413:      *   be imploded with "\n".
 414:      * @return string|$this If reading, the value of the epilog. If setting $this will be returned.
 415:      */
 416:     public function epilog($text = null)
 417:     {
 418:         deprecationWarning(
 419:             'ConsoleOptionParser::epliog() is deprecated. ' .
 420:             'Use ConsoleOptionParser::setEpilog()/getEpilog() instead.'
 421:         );
 422:         if ($text !== null) {
 423:             return $this->setEpilog($text);
 424:         }
 425: 
 426:         return $this->getEpilog();
 427:     }
 428: 
 429:     /**
 430:      * Enables sorting of subcommands
 431:      *
 432:      * @param bool $value Whether or not to sort subcommands
 433:      * @return $this
 434:      */
 435:     public function enableSubcommandSort($value = true)
 436:     {
 437:         $this->_subcommandSort = (bool)$value;
 438: 
 439:         return $this;
 440:     }
 441: 
 442:     /**
 443:      * Checks whether or not sorting is enabled for subcommands.
 444:      *
 445:      * @return bool
 446:      */
 447:     public function isSubcommandSortEnabled()
 448:     {
 449:         return $this->_subcommandSort;
 450:     }
 451: 
 452:     /**
 453:      * Add an option to the option parser. Options allow you to define optional or required
 454:      * parameters for your console application. Options are defined by the parameters they use.
 455:      *
 456:      * ### Options
 457:      *
 458:      * - `short` - The single letter variant for this option, leave undefined for none.
 459:      * - `help` - Help text for this option. Used when generating help for the option.
 460:      * - `default` - The default value for this option. Defaults are added into the parsed params when the
 461:      *    attached option is not provided or has no value. Using default and boolean together will not work.
 462:      *    are added into the parsed parameters when the option is undefined. Defaults to null.
 463:      * - `boolean` - The option uses no value, it's just a boolean switch. Defaults to false.
 464:      *    If an option is defined as boolean, it will always be added to the parsed params. If no present
 465:      *    it will be false, if present it will be true.
 466:      * - `multiple` - The option can be provided multiple times. The parsed option
 467:      *   will be an array of values when this option is enabled.
 468:      * - `choices` A list of valid choices for this option. If left empty all values are valid..
 469:      *   An exception will be raised when parse() encounters an invalid value.
 470:      *
 471:      * @param \Cake\Console\ConsoleInputOption|string $name The long name you want to the value to be parsed out as when options are parsed.
 472:      *   Will also accept an instance of ConsoleInputOption
 473:      * @param array $options An array of parameters that define the behavior of the option
 474:      * @return $this
 475:      */
 476:     public function addOption($name, array $options = [])
 477:     {
 478:         if ($name instanceof ConsoleInputOption) {
 479:             $option = $name;
 480:             $name = $option->name();
 481:         } else {
 482:             $defaults = [
 483:                 'name' => $name,
 484:                 'short' => null,
 485:                 'help' => '',
 486:                 'default' => null,
 487:                 'boolean' => false,
 488:                 'choices' => []
 489:             ];
 490:             $options += $defaults;
 491:             $option = new ConsoleInputOption($options);
 492:         }
 493:         $this->_options[$name] = $option;
 494:         asort($this->_options);
 495:         if ($option->short() !== null) {
 496:             $this->_shortOptions[$option->short()] = $name;
 497:             asort($this->_shortOptions);
 498:         }
 499: 
 500:         return $this;
 501:     }
 502: 
 503:     /**
 504:      * Remove an option from the option parser.
 505:      *
 506:      * @param string $name The option name to remove.
 507:      * @return $this
 508:      */
 509:     public function removeOption($name)
 510:     {
 511:         unset($this->_options[$name]);
 512: 
 513:         return $this;
 514:     }
 515: 
 516:     /**
 517:      * Add a positional argument to the option parser.
 518:      *
 519:      * ### Params
 520:      *
 521:      * - `help` The help text to display for this argument.
 522:      * - `required` Whether this parameter is required.
 523:      * - `index` The index for the arg, if left undefined the argument will be put
 524:      *   onto the end of the arguments. If you define the same index twice the first
 525:      *   option will be overwritten.
 526:      * - `choices` A list of valid choices for this argument. If left empty all values are valid..
 527:      *   An exception will be raised when parse() encounters an invalid value.
 528:      *
 529:      * @param \Cake\Console\ConsoleInputArgument|string $name The name of the argument.
 530:      *   Will also accept an instance of ConsoleInputArgument.
 531:      * @param array $params Parameters for the argument, see above.
 532:      * @return $this
 533:      */
 534:     public function addArgument($name, array $params = [])
 535:     {
 536:         if ($name instanceof ConsoleInputArgument) {
 537:             $arg = $name;
 538:             $index = count($this->_args);
 539:         } else {
 540:             $defaults = [
 541:                 'name' => $name,
 542:                 'help' => '',
 543:                 'index' => count($this->_args),
 544:                 'required' => false,
 545:                 'choices' => []
 546:             ];
 547:             $options = $params + $defaults;
 548:             $index = $options['index'];
 549:             unset($options['index']);
 550:             $arg = new ConsoleInputArgument($options);
 551:         }
 552:         foreach ($this->_args as $k => $a) {
 553:             if ($a->isEqualTo($arg)) {
 554:                 return $this;
 555:             }
 556:             if (!empty($options['required']) && !$a->isRequired()) {
 557:                 throw new LogicException('A required argument cannot follow an optional one');
 558:             }
 559:         }
 560:         $this->_args[$index] = $arg;
 561:         ksort($this->_args);
 562: 
 563:         return $this;
 564:     }
 565: 
 566:     /**
 567:      * Add multiple arguments at once. Take an array of argument definitions.
 568:      * The keys are used as the argument names, and the values as params for the argument.
 569:      *
 570:      * @param array $args Array of arguments to add.
 571:      * @see \Cake\Console\ConsoleOptionParser::addArgument()
 572:      * @return $this
 573:      */
 574:     public function addArguments(array $args)
 575:     {
 576:         foreach ($args as $name => $params) {
 577:             if ($params instanceof ConsoleInputArgument) {
 578:                 $name = $params;
 579:                 $params = [];
 580:             }
 581:             $this->addArgument($name, $params);
 582:         }
 583: 
 584:         return $this;
 585:     }
 586: 
 587:     /**
 588:      * Add multiple options at once. Takes an array of option definitions.
 589:      * The keys are used as option names, and the values as params for the option.
 590:      *
 591:      * @param array $options Array of options to add.
 592:      * @see \Cake\Console\ConsoleOptionParser::addOption()
 593:      * @return $this
 594:      */
 595:     public function addOptions(array $options)
 596:     {
 597:         foreach ($options as $name => $params) {
 598:             if ($params instanceof ConsoleInputOption) {
 599:                 $name = $params;
 600:                 $params = [];
 601:             }
 602:             $this->addOption($name, $params);
 603:         }
 604: 
 605:         return $this;
 606:     }
 607: 
 608:     /**
 609:      * Append a subcommand to the subcommand list.
 610:      * Subcommands are usually methods on your Shell, but can also be used to document Tasks.
 611:      *
 612:      * ### Options
 613:      *
 614:      * - `help` - Help text for the subcommand.
 615:      * - `parser` - A ConsoleOptionParser for the subcommand. This allows you to create method
 616:      *    specific option parsers. When help is generated for a subcommand, if a parser is present
 617:      *    it will be used.
 618:      *
 619:      * @param \Cake\Console\ConsoleInputSubcommand|string $name Name of the subcommand. Will also accept an instance of ConsoleInputSubcommand
 620:      * @param array $options Array of params, see above.
 621:      * @return $this
 622:      */
 623:     public function addSubcommand($name, array $options = [])
 624:     {
 625:         if ($name instanceof ConsoleInputSubcommand) {
 626:             $command = $name;
 627:             $name = $command->name();
 628:         } else {
 629:             $name = Inflector::underscore($name);
 630:             $defaults = [
 631:                 'name' => $name,
 632:                 'help' => '',
 633:                 'parser' => null
 634:             ];
 635:             $options += $defaults;
 636: 
 637:             $command = new ConsoleInputSubcommand($options);
 638:         }
 639:         $this->_subcommands[$name] = $command;
 640:         if ($this->_subcommandSort) {
 641:             asort($this->_subcommands);
 642:         }
 643: 
 644:         return $this;
 645:     }
 646: 
 647:     /**
 648:      * Remove a subcommand from the option parser.
 649:      *
 650:      * @param string $name The subcommand name to remove.
 651:      * @return $this
 652:      */
 653:     public function removeSubcommand($name)
 654:     {
 655:         unset($this->_subcommands[$name]);
 656: 
 657:         return $this;
 658:     }
 659: 
 660:     /**
 661:      * Add multiple subcommands at once.
 662:      *
 663:      * @param array $commands Array of subcommands.
 664:      * @return $this
 665:      */
 666:     public function addSubcommands(array $commands)
 667:     {
 668:         foreach ($commands as $name => $params) {
 669:             if ($params instanceof ConsoleInputSubcommand) {
 670:                 $name = $params;
 671:                 $params = [];
 672:             }
 673:             $this->addSubcommand($name, $params);
 674:         }
 675: 
 676:         return $this;
 677:     }
 678: 
 679:     /**
 680:      * Gets the arguments defined in the parser.
 681:      *
 682:      * @return \Cake\Console\ConsoleInputArgument[]
 683:      */
 684:     public function arguments()
 685:     {
 686:         return $this->_args;
 687:     }
 688: 
 689:     /**
 690:      * Get the list of argument names.
 691:      *
 692:      * @return string[]
 693:      */
 694:     public function argumentNames()
 695:     {
 696:         $out = [];
 697:         foreach ($this->_args as $arg) {
 698:             $out[] = $arg->name();
 699:         }
 700: 
 701:         return $out;
 702:     }
 703: 
 704:     /**
 705:      * Get the defined options in the parser.
 706:      *
 707:      * @return \Cake\Console\ConsoleInputOption[]
 708:      */
 709:     public function options()
 710:     {
 711:         return $this->_options;
 712:     }
 713: 
 714:     /**
 715:      * Get the array of defined subcommands
 716:      *
 717:      * @return \Cake\Console\ConsoleInputSubcommand[]
 718:      */
 719:     public function subcommands()
 720:     {
 721:         return $this->_subcommands;
 722:     }
 723: 
 724:     /**
 725:      * Parse the argv array into a set of params and args. If $command is not null
 726:      * and $command is equal to a subcommand that has a parser, that parser will be used
 727:      * to parse the $argv
 728:      *
 729:      * @param array $argv Array of args (argv) to parse.
 730:      * @return array [$params, $args]
 731:      * @throws \Cake\Console\Exception\ConsoleException When an invalid parameter is encountered.
 732:      */
 733:     public function parse($argv)
 734:     {
 735:         $command = isset($argv[0]) ? Inflector::underscore($argv[0]) : null;
 736:         if (isset($this->_subcommands[$command])) {
 737:             array_shift($argv);
 738:         }
 739:         if (isset($this->_subcommands[$command]) && $this->_subcommands[$command]->parser()) {
 740:             return $this->_subcommands[$command]->parser()->parse($argv);
 741:         }
 742:         $params = $args = [];
 743:         $this->_tokens = $argv;
 744:         while (($token = array_shift($this->_tokens)) !== null) {
 745:             if (isset($this->_subcommands[$token])) {
 746:                 continue;
 747:             }
 748:             if (substr($token, 0, 2) === '--') {
 749:                 $params = $this->_parseLongOption($token, $params);
 750:             } elseif (substr($token, 0, 1) === '-') {
 751:                 $params = $this->_parseShortOption($token, $params);
 752:             } else {
 753:                 $args = $this->_parseArg($token, $args);
 754:             }
 755:         }
 756:         foreach ($this->_args as $i => $arg) {
 757:             if ($arg->isRequired() && !isset($args[$i]) && empty($params['help'])) {
 758:                 throw new ConsoleException(
 759:                     sprintf('Missing required arguments. %s is required.', $arg->name())
 760:                 );
 761:             }
 762:         }
 763:         foreach ($this->_options as $option) {
 764:             $name = $option->name();
 765:             $isBoolean = $option->isBoolean();
 766:             $default = $option->defaultValue();
 767: 
 768:             if ($default !== null && !isset($params[$name]) && !$isBoolean) {
 769:                 $params[$name] = $default;
 770:             }
 771:             if ($isBoolean && !isset($params[$name])) {
 772:                 $params[$name] = false;
 773:             }
 774:         }
 775: 
 776:         return [$params, $args];
 777:     }
 778: 
 779:     /**
 780:      * Gets formatted help for this parser object.
 781:      *
 782:      * Generates help text based on the description, options, arguments, subcommands and epilog
 783:      * in the parser.
 784:      *
 785:      * @param string|null $subcommand If present and a valid subcommand that has a linked parser.
 786:      *    That subcommands help will be shown instead.
 787:      * @param string $format Define the output format, can be text or xml
 788:      * @param int $width The width to format user content to. Defaults to 72
 789:      * @return string Generated help.
 790:      */
 791:     public function help($subcommand = null, $format = 'text', $width = 72)
 792:     {
 793:         if ($subcommand === null) {
 794:             $formatter = new HelpFormatter($this);
 795:             $formatter->setAlias($this->rootName);
 796: 
 797:             if ($format === 'text') {
 798:                 return $formatter->text($width);
 799:             }
 800:             if ($format === 'xml') {
 801:                 return (string)$formatter->xml();
 802:             }
 803:         }
 804: 
 805:         if (isset($this->_subcommands[$subcommand])) {
 806:             $command = $this->_subcommands[$subcommand];
 807:             $subparser = $command->parser();
 808: 
 809:             // Generate a parser as the subcommand didn't define one.
 810:             if (!($subparser instanceof self)) {
 811:                 // $subparser = clone $this;
 812:                 $subparser = new self($subcommand);
 813:                 $subparser
 814:                     ->setDescription($command->getRawHelp())
 815:                     ->addOptions($this->options())
 816:                     ->addArguments($this->arguments());
 817:             }
 818:             if (strlen($subparser->getDescription()) === 0) {
 819:                 $subparser->setDescription($command->getRawHelp());
 820:             }
 821:             $subparser->setCommand($this->getCommand() . ' ' . $subcommand);
 822:             $subparser->setRootName($this->rootName);
 823: 
 824:             return $subparser->help(null, $format, $width);
 825:         }
 826: 
 827:         return $this->getCommandError($subcommand);
 828:     }
 829: 
 830:     /**
 831:      * Set the alias used in the HelpFormatter
 832:      *
 833:      * @param string $alias The alias
 834:      * @return void
 835:      * @deprecated 3.5.0 Use setRootName() instead.
 836:      */
 837:     public function setHelpAlias($alias)
 838:     {
 839:         deprecationWarning(
 840:             'ConsoleOptionParser::setHelpAlias() is deprecated. ' .
 841:             'Use ConsoleOptionParser::setRootName() instead.'
 842:         );
 843:         $this->rootName = $alias;
 844:     }
 845: 
 846:     /**
 847:      * Set the root name used in the HelpFormatter
 848:      *
 849:      * @param string $name The root command name
 850:      * @return $this
 851:      */
 852:     public function setRootName($name)
 853:     {
 854:         $this->rootName = (string)$name;
 855: 
 856:         return $this;
 857:     }
 858: 
 859:     /**
 860:      * Get the message output in the console stating that the command can not be found and tries to guess what the user
 861:      * wanted to say. Output a list of available subcommands as well.
 862:      *
 863:      * @param string $command Unknown command name trying to be dispatched.
 864:      * @return string The message to be displayed in the console.
 865:      */
 866:     protected function getCommandError($command)
 867:     {
 868:         $rootCommand = $this->getCommand();
 869:         $subcommands = array_keys((array)$this->subcommands());
 870:         $bestGuess = $this->findClosestItem($command, $subcommands);
 871: 
 872:         $out = [
 873:             sprintf(
 874:                 'Unable to find the `%s %s` subcommand. See `bin/%s %s --help`.',
 875:                 $rootCommand,
 876:                 $command,
 877:                 $this->rootName,
 878:                 $rootCommand
 879:             ),
 880:             ''
 881:         ];
 882: 
 883:         if ($bestGuess !== null) {
 884:             $out[] = sprintf('Did you mean : `%s %s` ?', $rootCommand, $bestGuess);
 885:             $out[] = '';
 886:         }
 887:         $out[] = sprintf('Available subcommands for the `%s` command are : ', $rootCommand);
 888:         $out[] = '';
 889:         foreach ($subcommands as $subcommand) {
 890:             $out[] = ' - ' . $subcommand;
 891:         }
 892: 
 893:         return implode("\n", $out);
 894:     }
 895: 
 896:     /**
 897:      * Get the message output in the console stating that the option can not be found and tries to guess what the user
 898:      * wanted to say. Output a list of available options as well.
 899:      *
 900:      * @param string $option Unknown option name trying to be used.
 901:      * @return string The message to be displayed in the console.
 902:      */
 903:     protected function getOptionError($option)
 904:     {
 905:         $availableOptions = array_keys($this->_options);
 906:         $bestGuess = $this->findClosestItem($option, $availableOptions);
 907:         $out = [
 908:             sprintf('Unknown option `%s`.', $option),
 909:             ''
 910:         ];
 911: 
 912:         if ($bestGuess !== null) {
 913:             $out[] = sprintf('Did you mean `%s` ?', $bestGuess);
 914:             $out[] = '';
 915:         }
 916: 
 917:         $out[] = 'Available options are :';
 918:         $out[] = '';
 919:         foreach ($availableOptions as $availableOption) {
 920:             $out[] = ' - ' . $availableOption;
 921:         }
 922: 
 923:         return implode("\n", $out);
 924:     }
 925: 
 926:     /**
 927:      * Get the message output in the console stating that the short option can not be found. Output a list of available
 928:      * short options and what option they refer to as well.
 929:      *
 930:      * @param string $option Unknown short option name trying to be used.
 931:      * @return string The message to be displayed in the console.
 932:      */
 933:     protected function getShortOptionError($option)
 934:     {
 935:         $out = [sprintf('Unknown short option `%s`', $option)];
 936:         $out[] = '';
 937:         $out[] = 'Available short options are :';
 938:         $out[] = '';
 939: 
 940:         foreach ($this->_shortOptions as $short => $long) {
 941:             $out[] = sprintf(' - `%s` (short for `--%s`)', $short, $long);
 942:         }
 943: 
 944:         return implode("\n", $out);
 945:     }
 946: 
 947:     /**
 948:      * Tries to guess the item name the user originally wanted using the some regex pattern and the levenshtein
 949:      * algorithm.
 950:      *
 951:      * @param string $needle Unknown item (either a subcommand name or an option for instance) trying to be used.
 952:      * @param string[] $haystack List of items available for the type $needle belongs to.
 953:      * @return string|null The closest name to the item submitted by the user.
 954:      */
 955:     protected function findClosestItem($needle, $haystack)
 956:     {
 957:         $bestGuess = null;
 958:         foreach ($haystack as $item) {
 959:             if (preg_match('/^' . $needle . '/', $item)) {
 960:                 return $item;
 961:             }
 962:         }
 963: 
 964:         foreach ($haystack as $item) {
 965:             if (preg_match('/' . $needle . '/', $item)) {
 966:                 return $item;
 967:             }
 968: 
 969:             $score = levenshtein($needle, $item);
 970: 
 971:             if (!isset($bestScore) || $score < $bestScore) {
 972:                 $bestScore = $score;
 973:                 $bestGuess = $item;
 974:             }
 975:         }
 976: 
 977:         return $bestGuess;
 978:     }
 979: 
 980:     /**
 981:      * Parse the value for a long option out of $this->_tokens. Will handle
 982:      * options with an `=` in them.
 983:      *
 984:      * @param string $option The option to parse.
 985:      * @param array $params The params to append the parsed value into
 986:      * @return array Params with $option added in.
 987:      */
 988:     protected function _parseLongOption($option, $params)
 989:     {
 990:         $name = substr($option, 2);
 991:         if (strpos($name, '=') !== false) {
 992:             list($name, $value) = explode('=', $name, 2);
 993:             array_unshift($this->_tokens, $value);
 994:         }
 995: 
 996:         return $this->_parseOption($name, $params);
 997:     }
 998: 
 999:     /**
1000:      * Parse the value for a short option out of $this->_tokens
1001:      * If the $option is a combination of multiple shortcuts like -otf
1002:      * they will be shifted onto the token stack and parsed individually.
1003:      *
1004:      * @param string $option The option to parse.
1005:      * @param array $params The params to append the parsed value into
1006:      * @return array Params with $option added in.
1007:      * @throws \Cake\Console\Exception\ConsoleException When unknown short options are encountered.
1008:      */
1009:     protected function _parseShortOption($option, $params)
1010:     {
1011:         $key = substr($option, 1);
1012:         if (strlen($key) > 1) {
1013:             $flags = str_split($key);
1014:             $key = $flags[0];
1015:             for ($i = 1, $len = count($flags); $i < $len; $i++) {
1016:                 array_unshift($this->_tokens, '-' . $flags[$i]);
1017:             }
1018:         }
1019:         if (!isset($this->_shortOptions[$key])) {
1020:             throw new ConsoleException($this->getShortOptionError($key));
1021:         }
1022:         $name = $this->_shortOptions[$key];
1023: 
1024:         return $this->_parseOption($name, $params);
1025:     }
1026: 
1027:     /**
1028:      * Parse an option by its name index.
1029:      *
1030:      * @param string $name The name to parse.
1031:      * @param array $params The params to append the parsed value into
1032:      * @return array Params with $option added in.
1033:      * @throws \Cake\Console\Exception\ConsoleException
1034:      */
1035:     protected function _parseOption($name, $params)
1036:     {
1037:         if (!isset($this->_options[$name])) {
1038:             throw new ConsoleException($this->getOptionError($name));
1039:         }
1040:         $option = $this->_options[$name];
1041:         $isBoolean = $option->isBoolean();
1042:         $nextValue = $this->_nextToken();
1043:         $emptyNextValue = (empty($nextValue) && $nextValue !== '0');
1044:         if (!$isBoolean && !$emptyNextValue && !$this->_optionExists($nextValue)) {
1045:             array_shift($this->_tokens);
1046:             $value = $nextValue;
1047:         } elseif ($isBoolean) {
1048:             $value = true;
1049:         } else {
1050:             $value = $option->defaultValue();
1051:         }
1052:         if ($option->validChoice($value)) {
1053:             if ($option->acceptsMultiple()) {
1054:                 $params[$name][] = $value;
1055:             } else {
1056:                 $params[$name] = $value;
1057:             }
1058: 
1059:             return $params;
1060:         }
1061: 
1062:         return [];
1063:     }
1064: 
1065:     /**
1066:      * Check to see if $name has an option (short/long) defined for it.
1067:      *
1068:      * @param string $name The name of the option.
1069:      * @return bool
1070:      */
1071:     protected function _optionExists($name)
1072:     {
1073:         if (substr($name, 0, 2) === '--') {
1074:             return isset($this->_options[substr($name, 2)]);
1075:         }
1076:         if ($name{0} === '-' && $name{1} !== '-') {
1077:             return isset($this->_shortOptions[$name{1}]);
1078:         }
1079: 
1080:         return false;
1081:     }
1082: 
1083:     /**
1084:      * Parse an argument, and ensure that the argument doesn't exceed the number of arguments
1085:      * and that the argument is a valid choice.
1086:      *
1087:      * @param string $argument The argument to append
1088:      * @param array $args The array of parsed args to append to.
1089:      * @return string[] Args
1090:      * @throws \Cake\Console\Exception\ConsoleException
1091:      */
1092:     protected function _parseArg($argument, $args)
1093:     {
1094:         if (empty($this->_args)) {
1095:             $args[] = $argument;
1096: 
1097:             return $args;
1098:         }
1099:         $next = count($args);
1100:         if (!isset($this->_args[$next])) {
1101:             throw new ConsoleException('Too many arguments.');
1102:         }
1103: 
1104:         if ($this->_args[$next]->validChoice($argument)) {
1105:             $args[] = $argument;
1106: 
1107:             return $args;
1108:         }
1109:     }
1110: 
1111:     /**
1112:      * Find the next token in the argv set.
1113:      *
1114:      * @return string next token or ''
1115:      */
1116:     protected function _nextToken()
1117:     {
1118:         return isset($this->_tokens[0]) ? $this->_tokens[0] : '';
1119:     }
1120: }
1121: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs