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
@param
annotations 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.