Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like ArgsFormatBuilder often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ArgsFormatBuilder, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 61 | class ArgsFormatBuilder |
||
| 62 | { |
||
| 63 | /** |
||
| 64 | * @var ArgsFormat |
||
| 65 | */ |
||
| 66 | private $baseFormat; |
||
| 67 | |||
| 68 | /** |
||
| 69 | * @var CommandName[] |
||
| 70 | */ |
||
| 71 | private $commandNames = array(); |
||
| 72 | |||
| 73 | /** |
||
| 74 | * @var Option[] |
||
| 75 | */ |
||
| 76 | private $commandOptions = array(); |
||
| 77 | |||
| 78 | /** |
||
| 79 | * @var Option[] |
||
| 80 | */ |
||
| 81 | private $commandOptionsByShortName = array(); |
||
| 82 | |||
| 83 | /** |
||
| 84 | * @var Argument[] |
||
| 85 | */ |
||
| 86 | private $arguments = array(); |
||
| 87 | |||
| 88 | /** |
||
| 89 | * @var Option[] |
||
| 90 | */ |
||
| 91 | private $options = array(); |
||
| 92 | |||
| 93 | /** |
||
| 94 | * @var Option[] |
||
| 95 | */ |
||
| 96 | private $optionsByShortName = array(); |
||
| 97 | |||
| 98 | /** |
||
| 99 | * @var bool |
||
| 100 | */ |
||
| 101 | private $hasMultiValuedArg = false; |
||
| 102 | |||
| 103 | /** |
||
| 104 | * @var bool |
||
| 105 | */ |
||
| 106 | private $hasOptionalArg = false; |
||
| 107 | |||
| 108 | /** |
||
| 109 | * Creates a new builder. |
||
| 110 | * |
||
| 111 | * You can optionally pass a base format. The built format inherits all the |
||
| 112 | * arguments and options from the base format. |
||
| 113 | * |
||
| 114 | * @param ArgsFormat $baseFormat The base format. |
||
|
|
|||
| 115 | */ |
||
| 116 | 777 | public function __construct(ArgsFormat $baseFormat = null) |
|
| 120 | |||
| 121 | /** |
||
| 122 | * Returns the base format. |
||
| 123 | * |
||
| 124 | * @return ArgsFormat The base format. |
||
| 125 | */ |
||
| 126 | 586 | public function getBaseFormat() |
|
| 130 | |||
| 131 | /** |
||
| 132 | * Sets the command names of the built format. |
||
| 133 | * |
||
| 134 | * @param CommandName[] $commandNames The command names. |
||
| 135 | * |
||
| 136 | * @return static The current instance. |
||
| 137 | */ |
||
| 138 | 1 | public function setCommandNames(array $commandNames) |
|
| 139 | { |
||
| 140 | 1 | $this->commandNames = array(); |
|
| 141 | |||
| 142 | 1 | $this->addCommandNames($commandNames); |
|
| 143 | |||
| 144 | 1 | return $this; |
|
| 145 | } |
||
| 146 | |||
| 147 | /** |
||
| 148 | * Adds command names to the built format. |
||
| 149 | * |
||
| 150 | * @param CommandName[] $commandNames The command names to add. |
||
| 151 | * |
||
| 152 | * @return static The current instance. |
||
| 153 | */ |
||
| 154 | 2 | public function addCommandNames(array $commandNames) |
|
| 155 | { |
||
| 156 | 2 | foreach ($commandNames as $commandName) { |
|
| 157 | 2 | $this->addCommandName($commandName); |
|
| 158 | } |
||
| 159 | |||
| 160 | 2 | return $this; |
|
| 161 | } |
||
| 162 | |||
| 163 | /** |
||
| 164 | * Adds a command name to the built format. |
||
| 165 | * |
||
| 166 | * @param CommandName $commandName The command name to add. |
||
| 167 | * |
||
| 168 | * @return static The current instance. |
||
| 169 | */ |
||
| 170 | 277 | public function addCommandName(CommandName $commandName) |
|
| 171 | { |
||
| 172 | 277 | $this->commandNames[] = $commandName; |
|
| 173 | |||
| 174 | 277 | return $this; |
|
| 175 | } |
||
| 176 | |||
| 177 | /** |
||
| 178 | * Returns whether the builder contains any command names. |
||
| 179 | * |
||
| 180 | * @param bool $includeBase Whether to consider command names of the base |
||
| 181 | * format. |
||
| 182 | * |
||
| 183 | * @return bool Returns `true` if the builder contains any command names and |
||
| 184 | * `false` otherwise. |
||
| 185 | */ |
||
| 186 | 3 | public function hasCommandNames($includeBase = true) |
|
| 200 | |||
| 201 | /** |
||
| 202 | * Returns all command names added to the builder. |
||
| 203 | * |
||
| 204 | * @param bool $includeBase Whether to include command names of the base |
||
| 205 | * format in the result. |
||
| 206 | * |
||
| 207 | * @return CommandName[] The command names. |
||
| 208 | */ |
||
| 209 | 586 | View Code Duplication | public function getCommandNames($includeBase = true) |
| 210 | { |
||
| 211 | 586 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 212 | |||
| 213 | 586 | $commandNames = $this->commandNames; |
|
| 214 | |||
| 215 | 586 | if ($includeBase && $this->baseFormat) { |
|
| 216 | 5 | $commandNames = array_merge($this->baseFormat->getCommandNames(), $commandNames); |
|
| 217 | } |
||
| 218 | |||
| 219 | 586 | return $commandNames; |
|
| 220 | } |
||
| 221 | |||
| 222 | /** |
||
| 223 | * Sets the command options of the built format. |
||
| 224 | * |
||
| 225 | * Any existing command options are removed when this method is called. |
||
| 226 | * |
||
| 227 | * @param CommandOption[] $commandOptions The command options of the built |
||
| 228 | * format. |
||
| 229 | * |
||
| 230 | * @return static The current instance. |
||
| 231 | * |
||
| 232 | * @throws CannotAddOptionException If an option cannot be added. |
||
| 233 | * |
||
| 234 | * @see addCommandOption() |
||
| 235 | */ |
||
| 236 | 1 | public function setCommandOptions(array $commandOptions) |
|
| 237 | { |
||
| 238 | 1 | $this->commandOptions = array(); |
|
| 239 | 1 | $this->commandOptionsByShortName = array(); |
|
| 240 | |||
| 241 | 1 | $this->addCommandOptions($commandOptions); |
|
| 242 | |||
| 243 | 1 | return $this; |
|
| 244 | } |
||
| 245 | |||
| 246 | /** |
||
| 247 | * Adds command options to the builder. |
||
| 248 | * |
||
| 249 | * The existing command options stored in the builder are preserved. |
||
| 250 | * |
||
| 251 | * @param CommandOption[] $commandOptions The command options to add. |
||
| 252 | * |
||
| 253 | * @return static The current instance. |
||
| 254 | * |
||
| 255 | * @throws CannotAddOptionException If an option cannot be added. |
||
| 256 | * |
||
| 257 | * @see addCommandOption() |
||
| 258 | */ |
||
| 259 | 2 | public function addCommandOptions(array $commandOptions) |
|
| 260 | { |
||
| 261 | 2 | foreach ($commandOptions as $commandOption) { |
|
| 262 | 2 | $this->addCommandOption($commandOption); |
|
| 263 | } |
||
| 264 | |||
| 265 | 2 | return $this; |
|
| 266 | } |
||
| 267 | |||
| 268 | /** |
||
| 269 | * Adds a command option to the builder. |
||
| 270 | * |
||
| 271 | * The existing command options stored in the builder are preserved. |
||
| 272 | * |
||
| 273 | * @param CommandOption $commandOption The command option to add. |
||
| 274 | * |
||
| 275 | * @return static The current instance. |
||
| 276 | * |
||
| 277 | * @throws CannotAddOptionException If the option cannot be added. |
||
| 278 | * |
||
| 279 | * @see addCommandOptions() |
||
| 280 | */ |
||
| 281 | 89 | public function addCommandOption(CommandOption $commandOption) |
|
| 282 | { |
||
| 283 | 89 | $longName = $commandOption->getLongName(); |
|
| 284 | 89 | $shortName = $commandOption->getShortName(); |
|
| 285 | 89 | $longAliases = $commandOption->getLongAliases(); |
|
| 286 | 89 | $shortAliases = $commandOption->getShortAliases(); |
|
| 287 | |||
| 288 | 89 | if ($this->hasOption($longName) || $this->hasCommandOption($longName)) { |
|
| 289 | 3 | throw CannotAddOptionException::existsAlready($longName); |
|
| 290 | } |
||
| 291 | |||
| 292 | 87 | foreach ($longAliases as $shortAlias) { |
|
| 293 | 4 | if ($this->hasOption($shortAlias) || $this->hasCommandOption($shortAlias)) { |
|
| 294 | 4 | throw CannotAddOptionException::existsAlready($shortAlias); |
|
| 295 | } |
||
| 296 | } |
||
| 297 | |||
| 298 | 86 | if ($shortName && ($this->hasOption($shortName) || $this->hasCommandOption($shortName))) { |
|
| 299 | 3 | throw CannotAddOptionException::existsAlready($shortName); |
|
| 300 | } |
||
| 301 | |||
| 302 | 84 | foreach ($shortAliases as $shortAlias) { |
|
| 303 | 3 | if ($this->hasOption($shortAlias) || $this->hasCommandOption($shortAlias)) { |
|
| 304 | 3 | throw CannotAddOptionException::existsAlready($shortAlias); |
|
| 305 | } |
||
| 306 | } |
||
| 307 | |||
| 308 | 83 | $this->commandOptions[$longName] = $commandOption; |
|
| 309 | |||
| 310 | 83 | if ($shortName) { |
|
| 311 | 57 | $this->commandOptionsByShortName[$shortName] = $commandOption; |
|
| 312 | } |
||
| 313 | |||
| 314 | 83 | foreach ($longAliases as $longAlias) { |
|
| 315 | 3 | $this->commandOptions[$longAlias] = $commandOption; |
|
| 316 | } |
||
| 317 | |||
| 318 | 83 | foreach ($shortAliases as $shortAlias) { |
|
| 319 | 2 | $this->commandOptionsByShortName[$shortAlias] = $commandOption; |
|
| 320 | } |
||
| 321 | |||
| 322 | 83 | return $this; |
|
| 323 | } |
||
| 324 | |||
| 325 | /** |
||
| 326 | * Returns whether the builder contains a specific command option. |
||
| 327 | * |
||
| 328 | * You can either pass the long or the short name of the command option. |
||
| 329 | * |
||
| 330 | * @param string $name The long or short option name. |
||
| 331 | * @param bool $includeBase Whether to include command options in the base |
||
| 332 | * format in the search. |
||
| 333 | * |
||
| 334 | * @return bool Returns `true` if the command option with the given name |
||
| 335 | * could be found and `false` otherwise. |
||
| 336 | */ |
||
| 337 | 270 | View Code Duplication | public function hasCommandOption($name, $includeBase = true) |
| 338 | { |
||
| 339 | 270 | Assert::string($name, 'The option name must be a string or an integer. Got: %s'); |
|
| 340 | 268 | Assert::notEmpty($name, 'The option name must not be empty.'); |
|
| 341 | 267 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 342 | |||
| 343 | 266 | if (isset($this->commandOptions[$name]) || isset($this->commandOptionsByShortName[$name])) { |
|
| 344 | 8 | return true; |
|
| 345 | } |
||
| 346 | |||
| 347 | 266 | if ($includeBase && $this->baseFormat) { |
|
| 348 | 149 | return $this->baseFormat->hasCommandOption($name); |
|
| 349 | } |
||
| 350 | |||
| 351 | 225 | return false; |
|
| 352 | } |
||
| 353 | |||
| 354 | /** |
||
| 355 | * Returns whether the builder contains any command options. |
||
| 356 | * |
||
| 357 | * @param bool $includeBase Whether to include command options in the base |
||
| 358 | * format in the search. |
||
| 359 | * |
||
| 360 | * @return bool Returns `true` if the builder contains command options and |
||
| 361 | * `false` otherwise. |
||
| 362 | */ |
||
| 363 | 3 | public function hasCommandOptions($includeBase = true) |
|
| 377 | |||
| 378 | /** |
||
| 379 | * Returns a command option by its long or short name. |
||
| 380 | * |
||
| 381 | * @param string $name The long or short option name. |
||
| 382 | * @param bool $includeBase Whether to include command options in the base |
||
| 383 | * format in the search. |
||
| 384 | * |
||
| 385 | * @return CommandOption The command option. |
||
| 386 | * |
||
| 387 | * @throws NoSuchOptionException If the command option with the given name |
||
| 388 | * does not not exist. |
||
| 389 | */ |
||
| 390 | 10 | View Code Duplication | public function getCommandOption($name, $includeBase = true) |
| 391 | { |
||
| 392 | 10 | Assert::string($name, 'The option name must be a string. Got: %s'); |
|
| 393 | 8 | Assert::notEmpty($name, 'The option name must not be empty.'); |
|
| 394 | 7 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 395 | |||
| 396 | 6 | if (isset($this->commandOptions[$name])) { |
|
| 397 | 1 | return $this->commandOptions[$name]; |
|
| 398 | } |
||
| 399 | |||
| 400 | 5 | if (isset($this->commandOptionsByShortName[$name])) { |
|
| 401 | 1 | return $this->commandOptionsByShortName[$name]; |
|
| 402 | } |
||
| 403 | |||
| 404 | 4 | if ($includeBase && $this->baseFormat) { |
|
| 405 | 3 | return $this->baseFormat->getCommandOption($name); |
|
| 406 | } |
||
| 407 | |||
| 408 | 1 | throw NoSuchOptionException::forOptionName($name); |
|
| 409 | } |
||
| 410 | |||
| 411 | /** |
||
| 412 | * Returns all command options added to the builder. |
||
| 413 | * |
||
| 414 | * @param bool $includeBase Whether to include command options of the base |
||
| 415 | * format in the result. |
||
| 416 | * |
||
| 417 | * @return CommandOption[] The command options. |
||
| 418 | */ |
||
| 419 | 586 | View Code Duplication | public function getCommandOptions($includeBase = true) |
| 420 | { |
||
| 421 | 586 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 422 | |||
| 423 | 586 | $commandOptions = array_values($this->commandOptions); |
|
| 424 | |||
| 425 | 586 | if ($includeBase && $this->baseFormat) { |
|
| 426 | // prepend base command options |
||
| 427 | 6 | $commandOptions = array_merge($this->baseFormat->getCommandOptions(), $commandOptions); |
|
| 428 | } |
||
| 429 | |||
| 430 | 586 | return $commandOptions; |
|
| 431 | } |
||
| 432 | |||
| 433 | /** |
||
| 434 | * Sets the arguments of the built format. |
||
| 435 | * |
||
| 436 | * Any existing arguments are removed when this method is called. |
||
| 437 | * |
||
| 438 | * @param Argument[] $arguments The arguments of the built format. |
||
| 439 | * |
||
| 440 | * @return static The current instance. |
||
| 441 | * |
||
| 442 | * @throws CannotAddArgumentException If an argument cannot be added. |
||
| 443 | * |
||
| 444 | * @see addArgument() |
||
| 445 | */ |
||
| 446 | 1 | public function setArguments(array $arguments) |
|
| 447 | { |
||
| 448 | 1 | $this->arguments = array(); |
|
| 449 | 1 | $this->hasOptionalArg = false; |
|
| 450 | 1 | $this->hasMultiValuedArg = false; |
|
| 451 | |||
| 452 | 1 | $this->addArguments($arguments); |
|
| 453 | |||
| 454 | 1 | return $this; |
|
| 455 | } |
||
| 456 | |||
| 457 | /** |
||
| 458 | * Adds arguments at the end of the argument list. |
||
| 459 | * |
||
| 460 | * The existing arguments stored in the builder are preserved. |
||
| 461 | * |
||
| 462 | * @param Argument[] $arguments The arguments to add. |
||
| 463 | * |
||
| 464 | * @return static The current instance. |
||
| 465 | * |
||
| 466 | * @throws CannotAddArgumentException If an argument cannot be added. |
||
| 467 | * |
||
| 468 | * @see addArgument() |
||
| 469 | */ |
||
| 470 | 235 | public function addArguments(array $arguments) |
|
| 471 | { |
||
| 472 | 235 | foreach ($arguments as $argument) { |
|
| 473 | 96 | $this->addArgument($argument); |
|
| 474 | } |
||
| 475 | |||
| 476 | 235 | return $this; |
|
| 477 | } |
||
| 478 | |||
| 479 | /** |
||
| 480 | * Adds an argument at the end of the argument list. |
||
| 481 | * |
||
| 482 | * The existing arguments stored in the builder are preserved. |
||
| 483 | * |
||
| 484 | * You cannot add arguments after adding a multi-valued argument. If you do |
||
| 485 | * so, this method throws an exception. |
||
| 486 | * |
||
| 487 | * Adding required arguments after optional arguments is not supported. |
||
| 488 | * Also in this case an exception is thrown. |
||
| 489 | * |
||
| 490 | * @param Argument $argument The argument to add. |
||
| 491 | * |
||
| 492 | * @return static The current instance. |
||
| 493 | * |
||
| 494 | * @throws CannotAddArgumentException If the argument cannot be added. |
||
| 495 | */ |
||
| 496 | 228 | public function addArgument(Argument $argument) |
|
| 497 | { |
||
| 498 | 228 | $name = $argument->getName(); |
|
| 499 | |||
| 500 | 228 | if ($this->hasArgument($name)) { |
|
| 501 | 2 | throw CannotAddArgumentException::existsAlready($name); |
|
| 502 | } |
||
| 503 | |||
| 504 | 228 | if ($this->hasMultiValuedArgument()) { |
|
| 505 | 4 | throw CannotAddArgumentException::cannotAddAfterMultiValued(); |
|
| 506 | } |
||
| 507 | |||
| 508 | 228 | if ($argument->isRequired() && $this->hasOptionalArgument()) { |
|
| 509 | 2 | throw CannotAddArgumentException::cannotAddRequiredAfterOptional(); |
|
| 510 | } |
||
| 511 | |||
| 512 | 228 | if ($argument->isMultiValued()) { |
|
| 513 | 34 | $this->hasMultiValuedArg = true; |
|
| 514 | } |
||
| 515 | |||
| 516 | 228 | if ($argument->isOptional()) { |
|
| 517 | 215 | $this->hasOptionalArg = true; |
|
| 518 | } |
||
| 519 | |||
| 520 | 228 | $this->arguments[$name] = $argument; |
|
| 521 | |||
| 522 | 228 | return $this; |
|
| 523 | } |
||
| 524 | |||
| 525 | /** |
||
| 526 | * Returns whether the builder contains a specific argument. |
||
| 527 | * |
||
| 528 | * You can either pass the name of the argument or the 0-based position of |
||
| 529 | * the argument. |
||
| 530 | * |
||
| 531 | * @param string|int $name The argument name or its 0-based position |
||
| 532 | * in the argument list. |
||
| 533 | * @param bool $includeBase Whether to include arguments in the base |
||
| 534 | * format in the search. |
||
| 535 | * |
||
| 536 | * @return bool Returns `true` if the argument with the given name or |
||
| 537 | * position could be found and `false` otherwise. |
||
| 538 | */ |
||
| 539 | 232 | View Code Duplication | public function hasArgument($name, $includeBase = true) |
| 540 | { |
||
| 541 | 232 | if (!is_int($name)) { |
|
| 542 | 232 | Assert::string($name, 'The argument name must be a string or an integer. Got: %s'); |
|
| 543 | 230 | Assert::notEmpty($name, 'The argument name must not be empty.'); |
|
| 544 | } |
||
| 545 | |||
| 546 | 229 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 547 | |||
| 548 | 228 | $arguments = is_int($name) |
|
| 549 | 2 | ? array_values($this->getArguments($includeBase)) |
|
| 550 | 228 | : $this->getArguments($includeBase); |
|
| 551 | |||
| 552 | 228 | return isset($arguments[$name]); |
|
| 553 | } |
||
| 554 | |||
| 555 | /** |
||
| 556 | * Returns whether the builder contains a multi-valued argument. |
||
| 557 | * |
||
| 558 | * @param bool $includeBase Whether to include arguments in the base format |
||
| 559 | * in the search. |
||
| 560 | * |
||
| 561 | * @return bool Returns `true` if the builder contains a multi-valued |
||
| 562 | * argument and `false` otherwise. |
||
| 563 | */ |
||
| 564 | 587 | public function hasMultiValuedArgument($includeBase = true) |
|
| 578 | |||
| 579 | /** |
||
| 580 | * Returns whether the builder contains an optional argument. |
||
| 581 | * |
||
| 582 | * @param bool $includeBase Whether to include arguments in the base format |
||
| 583 | * in the search. |
||
| 584 | * |
||
| 585 | * @return bool Returns `true` if the builder contains an optional argument |
||
| 586 | * and `false` otherwise. |
||
| 587 | */ |
||
| 588 | 587 | public function hasOptionalArgument($includeBase = true) |
|
| 602 | |||
| 603 | /** |
||
| 604 | * Returns whether the builder contains a required argument. |
||
| 605 | * |
||
| 606 | * @param bool $includeBase Whether to include arguments in the base format |
||
| 607 | * in the search. |
||
| 608 | * |
||
| 609 | * @return bool Returns `true` if the builder contains a required argument |
||
| 610 | * and `false` otherwise. |
||
| 611 | */ |
||
| 612 | 3 | View Code Duplication | public function hasRequiredArgument($includeBase = true) |
| 613 | { |
||
| 614 | 3 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 615 | |||
| 616 | 2 | if (!$this->hasOptionalArg && count($this->arguments) > 0) { |
|
| 617 | 1 | return true; |
|
| 618 | } |
||
| 619 | |||
| 620 | 2 | if ($includeBase && $this->baseFormat) { |
|
| 621 | 2 | return $this->baseFormat->hasRequiredArgument(); |
|
| 622 | } |
||
| 623 | |||
| 624 | 2 | return false; |
|
| 625 | } |
||
| 626 | |||
| 627 | /** |
||
| 628 | * Returns whether the builder contains any argument. |
||
| 629 | * |
||
| 630 | * @param bool $includeBase Whether to include arguments in the base format |
||
| 631 | * in the search. |
||
| 632 | * |
||
| 633 | * @return bool Returns `true` if the builder contains any argument and |
||
| 634 | * `false` otherwise. |
||
| 635 | */ |
||
| 636 | 3 | public function hasArguments($includeBase = true) |
|
| 650 | |||
| 651 | /** |
||
| 652 | * Returns an argument by its name or position. |
||
| 653 | * |
||
| 654 | * You can either pass the name of the argument or the 0-based position of |
||
| 655 | * the argument. |
||
| 656 | * |
||
| 657 | * @param string|int $name The argument name or its 0-based position |
||
| 658 | * in the argument list. |
||
| 659 | * @param bool $includeBase Whether to include arguments in the base |
||
| 660 | * format in the search. |
||
| 661 | * |
||
| 662 | * @return Argument The argument. |
||
| 663 | * |
||
| 664 | * @throws NoSuchArgumentException If the argument with the given name or |
||
| 665 | * position does not exist. |
||
| 666 | */ |
||
| 667 | 11 | View Code Duplication | public function getArgument($name, $includeBase = true) |
| 668 | { |
||
| 669 | 11 | if (!is_int($name)) { |
|
| 670 | 8 | Assert::string($name, 'The argument name must be a string or integer. Got: %s'); |
|
| 671 | 6 | Assert::notEmpty($name, 'The argument name must not be empty.'); |
|
| 672 | } |
||
| 673 | |||
| 674 | 8 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 675 | |||
| 676 | 7 | if (is_int($name)) { |
|
| 677 | 3 | $arguments = array_values($this->getArguments($includeBase)); |
|
| 678 | |||
| 679 | 3 | if (!isset($arguments[$name])) { |
|
| 680 | 3 | throw NoSuchArgumentException::forPosition($name); |
|
| 681 | } |
||
| 682 | } else { |
||
| 683 | 4 | $arguments = $this->getArguments($includeBase); |
|
| 684 | |||
| 685 | 4 | if (!isset($arguments[$name])) { |
|
| 686 | 2 | throw NoSuchArgumentException::forArgumentName($name); |
|
| 687 | } |
||
| 688 | } |
||
| 689 | |||
| 690 | 4 | return $arguments[$name]; |
|
| 691 | } |
||
| 692 | |||
| 693 | /** |
||
| 694 | * Returns all arguments added to the builder. |
||
| 695 | * |
||
| 696 | * @param bool $includeBase Whether to include arguments of the base format |
||
| 697 | * in the result. |
||
| 698 | * |
||
| 699 | * @return Argument[] The arguments. |
||
| 700 | */ |
||
| 701 | 589 | View Code Duplication | public function getArguments($includeBase = true) |
| 702 | { |
||
| 703 | 589 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 704 | |||
| 705 | 589 | $arguments = $this->arguments; |
|
| 706 | |||
| 707 | 589 | if ($includeBase && $this->baseFormat) { |
|
| 708 | // prepend base arguments |
||
| 709 | 130 | $arguments = array_replace($this->baseFormat->getArguments(), $arguments); |
|
| 710 | } |
||
| 711 | |||
| 712 | 589 | return $arguments; |
|
| 713 | } |
||
| 714 | |||
| 715 | /** |
||
| 716 | * Sets the options of the built format. |
||
| 717 | * |
||
| 718 | * Any existing options are removed when this method is called. |
||
| 719 | * |
||
| 720 | * @param Option[] $options The options of the built format. |
||
| 721 | * |
||
| 722 | * @return static The current instance. |
||
| 723 | * |
||
| 724 | * @throws CannotAddOptionException If an option cannot be added. |
||
| 725 | * |
||
| 726 | * @see addOption() |
||
| 727 | */ |
||
| 728 | 1 | public function setOptions(array $options) |
|
| 729 | { |
||
| 730 | 1 | $this->options = array(); |
|
| 731 | 1 | $this->optionsByShortName = array(); |
|
| 732 | |||
| 733 | 1 | $this->addOptions($options); |
|
| 734 | |||
| 735 | 1 | return $this; |
|
| 736 | } |
||
| 737 | |||
| 738 | /** |
||
| 739 | * Adds options at the end of the options list. |
||
| 740 | * |
||
| 741 | * The existing options stored in the builder are preserved. |
||
| 742 | * |
||
| 743 | * @param Option[] $options The options to add. |
||
| 744 | * |
||
| 745 | * @return static The current instance. |
||
| 746 | * |
||
| 747 | * @throws CannotAddOptionException If an option cannot be added. |
||
| 748 | * |
||
| 749 | * @see addOption() |
||
| 750 | */ |
||
| 751 | 241 | public function addOptions(array $options) |
|
| 752 | { |
||
| 753 | 241 | foreach ($options as $option) { |
|
| 754 | 102 | $this->addOption($option); |
|
| 755 | } |
||
| 756 | |||
| 757 | 241 | return $this; |
|
| 758 | } |
||
| 759 | |||
| 760 | /** |
||
| 761 | * Adds an option at the end of the options list. |
||
| 762 | * |
||
| 763 | * The existing options stored in the builder are preserved. |
||
| 764 | * |
||
| 765 | * @param Option $option The option to add. |
||
| 766 | * |
||
| 767 | * @return static The current instance. |
||
| 768 | * |
||
| 769 | * @throws CannotAddOptionException If the option cannot be added. |
||
| 770 | * |
||
| 771 | * @see addOptions() |
||
| 772 | */ |
||
| 773 | 200 | public function addOption(Option $option) |
|
| 774 | { |
||
| 775 | 200 | $longName = $option->getLongName(); |
|
| 776 | 200 | $shortName = $option->getShortName(); |
|
| 777 | |||
| 778 | 200 | if ($this->hasOption($longName) || $this->hasCommandOption($longName)) { |
|
| 779 | 4 | throw CannotAddOptionException::existsAlready($longName); |
|
| 780 | } |
||
| 781 | |||
| 782 | 198 | if ($shortName && ($this->hasOption($shortName) || $this->hasCommandOption($shortName))) { |
|
| 783 | 4 | throw CannotAddOptionException::existsAlready($shortName); |
|
| 784 | } |
||
| 785 | |||
| 786 | 196 | $this->options[$longName] = $option; |
|
| 787 | |||
| 788 | 196 | if ($shortName) { |
|
| 789 | 138 | $this->optionsByShortName[$shortName] = $option; |
|
| 790 | } |
||
| 791 | |||
| 792 | 196 | return $this; |
|
| 793 | } |
||
| 794 | |||
| 795 | /** |
||
| 796 | * Returns whether the builder contains a specific option. |
||
| 797 | * |
||
| 798 | * You can either pass the long or the short name of the option. |
||
| 799 | * |
||
| 800 | * @param string $name The long or short option name. |
||
| 801 | * @param bool $includeBase Whether to include options in the base format |
||
| 802 | * in the search. |
||
| 803 | * |
||
| 804 | * @return bool Returns `true` if the option with the given name could be |
||
| 805 | * found and `false` otherwise. |
||
| 806 | */ |
||
| 807 | 270 | View Code Duplication | public function hasOption($name, $includeBase = true) |
| 808 | { |
||
| 809 | 270 | Assert::string($name, 'The option name must be a string or an integer. Got: %s'); |
|
| 810 | 268 | Assert::notEmpty($name, 'The option name must not be empty.'); |
|
| 811 | 267 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 812 | |||
| 813 | 266 | if (isset($this->options[$name]) || isset($this->optionsByShortName[$name])) { |
|
| 814 | 8 | return true; |
|
| 815 | } |
||
| 816 | |||
| 817 | 266 | if ($includeBase && $this->baseFormat) { |
|
| 818 | 151 | return $this->baseFormat->hasOption($name); |
|
| 819 | } |
||
| 820 | |||
| 821 | 225 | return false; |
|
| 822 | } |
||
| 823 | |||
| 824 | /** |
||
| 825 | * Returns whether the builder contains any option. |
||
| 826 | * |
||
| 827 | * @param bool $includeBase Whether to include options in the base format |
||
| 828 | * in the search. |
||
| 829 | * |
||
| 830 | * @return bool Returns `true` if the builder contains any option and |
||
| 831 | * `false` otherwise. |
||
| 832 | */ |
||
| 833 | 3 | public function hasOptions($includeBase = true) |
|
| 847 | |||
| 848 | /** |
||
| 849 | * Returns an option by its long or short name. |
||
| 850 | * |
||
| 851 | * @param string $name The long or short option name. |
||
| 852 | * @param bool $includeBase Whether to include options in the base format |
||
| 853 | * in the search. |
||
| 854 | * |
||
| 855 | * @return Option The option. |
||
| 856 | * |
||
| 857 | * @throws NoSuchOptionException If the option with the given name does not |
||
| 858 | * not exist. |
||
| 859 | */ |
||
| 860 | 10 | View Code Duplication | public function getOption($name, $includeBase = true) |
| 861 | { |
||
| 862 | 10 | Assert::string($name, 'The option name must be a string. Got: %s'); |
|
| 863 | 8 | Assert::notEmpty($name, 'The option name must not be empty.'); |
|
| 864 | 7 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 865 | |||
| 866 | 6 | if (isset($this->options[$name])) { |
|
| 867 | 1 | return $this->options[$name]; |
|
| 868 | } |
||
| 869 | |||
| 870 | 5 | if (isset($this->optionsByShortName[$name])) { |
|
| 871 | 1 | return $this->optionsByShortName[$name]; |
|
| 872 | } |
||
| 873 | |||
| 874 | 4 | if ($includeBase && $this->baseFormat) { |
|
| 875 | 3 | return $this->baseFormat->getOption($name); |
|
| 876 | } |
||
| 877 | |||
| 878 | 1 | throw NoSuchOptionException::forOptionName($name); |
|
| 879 | } |
||
| 880 | |||
| 881 | /** |
||
| 882 | * Returns all options added to the builder. |
||
| 883 | * |
||
| 884 | * @param bool $includeBase Whether to include options of the base format |
||
| 885 | * in the result. |
||
| 886 | * |
||
| 887 | * @return Option[] The options. |
||
| 888 | */ |
||
| 889 | 589 | View Code Duplication | public function getOptions($includeBase = true) |
| 890 | { |
||
| 891 | 589 | Assert::boolean($includeBase, 'The parameter $includeBase must be a boolean. Got: %s'); |
|
| 892 | |||
| 893 | 589 | $options = $this->options; |
|
| 894 | |||
| 895 | 589 | if ($includeBase && $this->baseFormat) { |
|
| 896 | // append base options |
||
| 897 | 6 | $options = array_replace($options, $this->baseFormat->getOptions()); |
|
| 898 | } |
||
| 899 | |||
| 900 | 589 | return $options; |
|
| 901 | } |
||
| 902 | |||
| 903 | /** |
||
| 904 | * Builds a format with the arguments and options added to the builder. |
||
| 905 | * |
||
| 906 | * @return ArgsFormat The built format. |
||
| 907 | */ |
||
| 908 | 366 | public function getFormat() |
|
| 912 | } |
||
| 913 |
This check looks for
@paramannotations where the type inferred by our type inference engine differs from the declared type.It makes a suggestion as to what type it considers more descriptive.
Most often this is a case of a parameter that can be null in addition to its declared types.