Complex classes like Parameter 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 Parameter, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 9 | class Parameter implements ToArrayInterface |
||
| 10 | { |
||
| 11 | /** |
||
| 12 | * The name of the filter stage that happens before a parameter is |
||
| 13 | * validated, for filtering raw data (e.g. clean-up before validation). |
||
| 14 | */ |
||
| 15 | const FILTER_STAGE_BEFORE_VALIDATION = 'before_validation'; |
||
| 16 | |||
| 17 | /** |
||
| 18 | * The name of the filter stage that happens immediately after a parameter |
||
| 19 | * has been validated but before it is evaluated by location handlers to be |
||
| 20 | * written out on the wire. |
||
| 21 | */ |
||
| 22 | const FILTER_STAGE_AFTER_VALIDATION = 'after_validation'; |
||
| 23 | |||
| 24 | /** |
||
| 25 | * The name of the filter stage that happens right before a validated value |
||
| 26 | * is being written out "on the wire" (e.g. for adjusting the structure or |
||
| 27 | * format of the data before sending it to the server). |
||
| 28 | */ |
||
| 29 | const FILTER_STAGE_REQUEST_WIRE = 'request_wire'; |
||
| 30 | |||
| 31 | /** |
||
| 32 | * The name of the filter stage that happens right after a value has been |
||
| 33 | * read out of a response "on the wire" (e.g. for adjusting the structure or |
||
| 34 | * format of the data after receiving it back from the server). |
||
| 35 | */ |
||
| 36 | const FILTER_STAGE_RESPONSE_WIRE = 'response_wire'; |
||
| 37 | |||
| 38 | /** |
||
| 39 | * A list of all allowed filter stages. |
||
| 40 | */ |
||
| 41 | const FILTER_STAGES = [ |
||
| 42 | self::FILTER_STAGE_BEFORE_VALIDATION, |
||
| 43 | self::FILTER_STAGE_AFTER_VALIDATION, |
||
| 44 | self::FILTER_STAGE_REQUEST_WIRE, |
||
| 45 | self::FILTER_STAGE_RESPONSE_WIRE |
||
| 46 | ]; |
||
| 47 | |||
| 48 | private $originalData; |
||
| 49 | |||
| 50 | /** @var string $name */ |
||
| 51 | private $name; |
||
| 52 | |||
| 53 | /** @var string $description */ |
||
| 54 | private $description; |
||
| 55 | |||
| 56 | /** @var string|array $type */ |
||
| 57 | private $type; |
||
| 58 | |||
| 59 | /** @var bool $required*/ |
||
| 60 | private $required; |
||
| 61 | |||
| 62 | /** @var array|null $enum */ |
||
| 63 | private $enum; |
||
| 64 | |||
| 65 | /** @var string $pattern */ |
||
| 66 | private $pattern; |
||
| 67 | |||
| 68 | /** @var int $minimum*/ |
||
| 69 | private $minimum; |
||
| 70 | |||
| 71 | /** @var int $maximum */ |
||
| 72 | private $maximum; |
||
| 73 | |||
| 74 | /** @var int $minLength */ |
||
| 75 | private $minLength; |
||
| 76 | |||
| 77 | /** @var int $maxLength */ |
||
| 78 | private $maxLength; |
||
| 79 | |||
| 80 | /** @var int $minItems */ |
||
| 81 | private $minItems; |
||
| 82 | |||
| 83 | /** @var int $maxItems */ |
||
| 84 | private $maxItems; |
||
| 85 | |||
| 86 | /** @var mixed $default */ |
||
| 87 | private $default; |
||
| 88 | |||
| 89 | /** @var bool $static */ |
||
| 90 | private $static; |
||
| 91 | |||
| 92 | /** @var array $filters */ |
||
| 93 | private $filters; |
||
| 94 | |||
| 95 | /** @var string $location */ |
||
| 96 | private $location; |
||
| 97 | |||
| 98 | /** @var string $sentAs */ |
||
| 99 | private $sentAs; |
||
| 100 | |||
| 101 | /** @var array $data */ |
||
| 102 | private $data; |
||
| 103 | |||
| 104 | /** @var array $properties */ |
||
| 105 | private $properties = []; |
||
| 106 | |||
| 107 | /** @var array|bool|Parameter $additionalProperties */ |
||
| 108 | private $additionalProperties; |
||
| 109 | |||
| 110 | /** @var array|Parameter $items */ |
||
| 111 | private $items; |
||
| 112 | |||
| 113 | /** @var string $format */ |
||
| 114 | private $format; |
||
| 115 | |||
| 116 | private $propertiesCache = null; |
||
| 117 | |||
| 118 | /** @var Description */ |
||
| 119 | private $serviceDescription; |
||
| 120 | |||
| 121 | /** |
||
| 122 | * Create a new Parameter using an associative array of data. |
||
| 123 | * |
||
| 124 | * The array can contain the following information: |
||
| 125 | * |
||
| 126 | * - name: (string) Unique name of the parameter |
||
| 127 | * |
||
| 128 | * - type: (string|array) Type of variable (string, number, integer, |
||
| 129 | * boolean, object, array, numeric, null, any). Types are used for |
||
| 130 | * validation and determining the structure of a parameter. You can use a |
||
| 131 | * union type by providing an array of simple types. If one of the union |
||
| 132 | * types matches the provided value, then the value is valid. |
||
| 133 | * |
||
| 134 | * - required: (bool) Whether or not the parameter is required |
||
| 135 | * |
||
| 136 | * - default: (mixed) Default value to use if no value is supplied |
||
| 137 | * |
||
| 138 | * - static: (bool) Set to true to specify that the parameter value cannot |
||
| 139 | * be changed from the default. |
||
| 140 | * |
||
| 141 | * - description: (string) Documentation of the parameter |
||
| 142 | * |
||
| 143 | * - location: (string) The location of a request used to apply a parameter. |
||
| 144 | * Custom locations can be registered with a command, but the defaults |
||
| 145 | * are uri, query, header, body, json, xml, formParam, multipart. |
||
| 146 | * |
||
| 147 | * - sentAs: (string) Specifies how the data being modeled is sent over the |
||
| 148 | * wire. For example, you may wish to include certain headers in a |
||
| 149 | * response model that have a normalized casing of FooBar, but the actual |
||
| 150 | * header is x-foo-bar. In this case, sentAs would be set to x-foo-bar. |
||
| 151 | * |
||
| 152 | * - filters: (array) Array of static method names to run a parameter |
||
| 153 | * value through. Each value in the array must be a string containing the |
||
| 154 | * full class path to a static method or an array of complex filter |
||
| 155 | * information. You can specify static methods of classes using the full |
||
| 156 | * namespace class name followed by '::' (e.g. Foo\Bar::baz). Some |
||
| 157 | * filters require arguments in order to properly filter a value. |
||
| 158 | * |
||
| 159 | * For complex filters, use a hash containing a 'method' key pointing to a |
||
| 160 | * static method, an 'args' key containing an array of positional |
||
| 161 | * arguments to pass to the method, and an optional 'stage' key. Arguments |
||
| 162 | * can contain keywords that are replaced when filtering a value: '@value' |
||
| 163 | * is replaced with the value being validated, '@api' is replaced with the |
||
| 164 | * Parameter object, and '@stage' is replaced with the current filter |
||
| 165 | * stage (if any was provided). |
||
| 166 | * |
||
| 167 | * The optional 'stage' key can be provided to control when the filter is |
||
| 168 | * invoked. The key can indicate that a filter should only be invoked |
||
| 169 | * 'before_validation', 'after_validation', when being written out to the |
||
| 170 | * 'request_wire' or being read from the 'response_wire'. |
||
| 171 | * |
||
| 172 | * - properties: When the type is an object, you can specify nested |
||
| 173 | * parameters |
||
| 174 | * |
||
| 175 | * - additionalProperties: (array) This attribute defines a schema for all |
||
| 176 | * properties that are not explicitly defined in an object type |
||
| 177 | * definition. If specified, the value MUST be a schema or a boolean. If |
||
| 178 | 34 | * false is provided, no additional properties are allowed beyond the |
|
| 179 | * properties defined in the schema. The default value is an empty schema |
||
| 180 | 34 | * which allows any value for additional properties. |
|
| 181 | * |
||
| 182 | 34 | * - items: This attribute defines the allowed items in an instance array, |
|
| 183 | 7 | * and MUST be a schema or an array of schemas. The default value is an |
|
| 184 | 7 | * empty schema which allows any value for items in the instance array. |
|
| 185 | 1 | * When this attribute value is a schema and the instance value is an |
|
| 186 | * array, then all the items in the array MUST be valid according to the |
||
| 187 | 6 | * schema. |
|
| 188 | 1 | * |
|
| 189 | 1 | * - pattern: When the type is a string, you can specify the regex pattern |
|
| 190 | 1 | * that a value must match |
|
| 191 | 1 | * |
|
| 192 | * - enum: When the type is a string, you can specify a list of acceptable |
||
| 193 | * values. |
||
| 194 | 1 | * |
|
| 195 | 6 | * - minItems: (int) Minimum number of items allowed in an array |
|
| 196 | * |
||
| 197 | * - maxItems: (int) Maximum number of items allowed in an array |
||
| 198 | * |
||
| 199 | 1 | * - minLength: (int) Minimum length of a string |
|
| 200 | 1 | * |
|
| 201 | 1 | * - maxLength: (int) Maximum length of a string |
|
| 202 | 1 | * |
|
| 203 | 6 | * - minimum: (int) Minimum value of an integer |
|
| 204 | * |
||
| 205 | * - maximum: (int) Maximum value of an integer |
||
| 206 | 33 | * |
|
| 207 | 31 | * - data: (array) Any additional custom data to use when serializing, |
|
| 208 | 33 | * validating, etc |
|
| 209 | * |
||
| 210 | 33 | * - format: (string) Format used to coax a value into the correct format |
|
| 211 | 33 | * when serializing or unserializing. You may specify either an array of |
|
| 212 | * filters OR a format, but not both. Supported values: date-time, date, |
||
| 213 | 33 | * time, timestamp, date-time-http, and boolean-string. |
|
| 214 | 10 | * |
|
| 215 | 9 | * - $ref: (string) String referencing a service description model. The |
|
| 216 | * parameter is replaced by the schema contained in the model. |
||
| 217 | 32 | * |
|
| 218 | 2 | * @param array $data Array of data as seen in service descriptions |
|
| 219 | 2 | * @param array $options Options used when creating the parameter. You can |
|
| 220 | 32 | * specify a Guzzle service description in the 'description' key. |
|
| 221 | * |
||
| 222 | * @throws \InvalidArgumentException |
||
| 223 | */ |
||
| 224 | public function __construct(array $data = [], array $options = []) |
||
| 267 | |||
| 268 | /** |
||
| 269 | * Convert the object to an array |
||
| 270 | 3 | * |
|
| 271 | 1 | * @return array |
|
| 272 | 1 | */ |
|
| 273 | public function toArray() |
||
| 277 | 2 | ||
| 278 | /** |
||
| 279 | 1 | * Get the default or static value of the command based on a value |
|
| 280 | 1 | * |
|
| 281 | 1 | * @param string $value Value that is currently set |
|
| 282 | 1 | * |
|
| 283 | 1 | * @return mixed Returns the value, a static value if one is present, or a default value |
|
| 284 | 1 | */ |
|
| 285 | 1 | public function getValue($value) |
|
| 293 | 2 | ||
| 294 | 2 | /** |
|
| 295 | * Run a value through the filters OR format attribute associated with the |
||
| 296 | 3 | * parameter. |
|
| 297 | * |
||
| 298 | * @param mixed $value Value to filter |
||
| 299 | * @param string $stage An optional specifier of what filter stage to |
||
| 300 | * invoke. If null, then all filters are invoked no matter what stage |
||
| 301 | * they apply to. Otherwise, only filters for the specified stage are |
||
| 302 | * invoked. |
||
| 303 | * |
||
| 304 | 1 | * @return mixed Returns the filtered value |
|
| 305 | * @throws \RuntimeException when trying to format when no service |
||
| 306 | 1 | * description is available. |
|
| 307 | * @throws \InvalidArgumentException if an invalid validation stage is |
||
| 308 | * provided. |
||
| 309 | */ |
||
| 310 | public function filter($value, $stage = null) |
||
| 343 | |||
| 344 | /** |
||
| 345 | 1 | * Get the name of the parameter |
|
| 346 | * |
||
| 347 | 1 | * @return string |
|
| 348 | */ |
||
| 349 | public function getName() |
||
| 353 | |||
| 354 | /** |
||
| 355 | 1 | * Set the name of the parameter |
|
| 356 | * |
||
| 357 | 1 | * @param string $name Name to set |
|
| 358 | */ |
||
| 359 | public function setName($name) |
||
| 363 | |||
| 364 | /** |
||
| 365 | 1 | * Get the key of the parameter, where sentAs will supersede name if it is |
|
| 366 | * set. |
||
| 367 | 1 | * |
|
| 368 | * @return string |
||
| 369 | */ |
||
| 370 | public function getWireName() |
||
| 374 | |||
| 375 | 1 | /** |
|
| 376 | * Get the type(s) of the parameter |
||
| 377 | 1 | * |
|
| 378 | * @return string|array |
||
| 379 | */ |
||
| 380 | public function getType() |
||
| 384 | |||
| 385 | 1 | /** |
|
| 386 | * Get if the parameter is required |
||
| 387 | 1 | * |
|
| 388 | * @return bool |
||
| 389 | */ |
||
| 390 | public function isRequired() |
||
| 394 | |||
| 395 | 1 | /** |
|
| 396 | * Get the default value of the parameter |
||
| 397 | 1 | * |
|
| 398 | * @return string|null |
||
| 399 | */ |
||
| 400 | public function getDefault() |
||
| 404 | |||
| 405 | 1 | /** |
|
| 406 | * Get the description of the parameter |
||
| 407 | 1 | * |
|
| 408 | * @return string|null |
||
| 409 | */ |
||
| 410 | public function getDescription() |
||
| 414 | |||
| 415 | 1 | /** |
|
| 416 | * Get the minimum acceptable value for an integer |
||
| 417 | 1 | * |
|
| 418 | * @return int|null |
||
| 419 | */ |
||
| 420 | public function getMinimum() |
||
| 424 | |||
| 425 | 1 | /** |
|
| 426 | * Get the maximum acceptable value for an integer |
||
| 427 | 1 | * |
|
| 428 | * @return int|null |
||
| 429 | */ |
||
| 430 | public function getMaximum() |
||
| 434 | |||
| 435 | 2 | /** |
|
| 436 | * Get the minimum allowed length of a string value |
||
| 437 | 2 | * |
|
| 438 | * @return int |
||
| 439 | */ |
||
| 440 | public function getMinLength() |
||
| 444 | |||
| 445 | /** |
||
| 446 | 1 | * Get the maximum allowed length of a string value |
|
| 447 | * |
||
| 448 | 1 | * @return int|null |
|
| 449 | */ |
||
| 450 | public function getMaxLength() |
||
| 454 | |||
| 455 | /** |
||
| 456 | * Get the maximum allowed number of items in an array value |
||
| 457 | * |
||
| 458 | * @return int|null |
||
| 459 | */ |
||
| 460 | 1 | public function getMaxItems() |
|
| 464 | 1 | ||
| 465 | 1 | /** |
|
| 466 | 1 | * Get the minimum allowed number of items in an array value |
|
| 467 | 1 | * |
|
| 468 | * @return int |
||
| 469 | */ |
||
| 470 | 1 | public function getMinItems() |
|
| 474 | |||
| 475 | /** |
||
| 476 | * Get the location of the parameter |
||
| 477 | * |
||
| 478 | 1 | * @return string|null |
|
| 479 | */ |
||
| 480 | 1 | public function getLocation() |
|
| 484 | |||
| 485 | /** |
||
| 486 | * Get the sentAs attribute of the parameter that used with locations to |
||
| 487 | * sentAs an attribute when it is being applied to a location. |
||
| 488 | 2 | * |
|
| 489 | * @return string|null |
||
| 490 | 2 | */ |
|
| 491 | public function getSentAs() |
||
| 495 | |||
| 496 | /** |
||
| 497 | * Retrieve a known property from the parameter by name or a data property |
||
| 498 | 1 | * by name. When no specific name value is passed, all data properties |
|
| 499 | * will be returned. |
||
| 500 | 1 | * |
|
| 501 | 1 | * @param string|null $name Specify a particular property name to retrieve |
|
| 502 | 1 | * |
|
| 503 | 1 | * @return array|mixed|null |
|
| 504 | 1 | */ |
|
| 505 | 1 | public function getData($name = null) |
|
| 517 | 1 | ||
| 518 | /** |
||
| 519 | 1 | * Get whether or not the default value can be changed |
|
| 520 | 1 | * |
|
| 521 | * @return bool |
||
| 522 | */ |
||
| 523 | 1 | public function isStatic() |
|
| 527 | 1 | ||
| 528 | 1 | /** |
|
| 529 | 1 | * Get an array of filters used by the parameter |
|
| 530 | * |
||
| 531 | 1 | * @return array |
|
| 532 | */ |
||
| 533 | public function getFilters() |
||
| 537 | |||
| 538 | /** |
||
| 539 | 1 | * Get the properties of the parameter |
|
| 540 | * |
||
| 541 | 1 | * @return Parameter[] |
|
| 542 | 1 | */ |
|
| 543 | 1 | public function getProperties() |
|
| 554 | |||
| 555 | /** |
||
| 556 | 1 | * Get a specific property from the parameter |
|
| 557 | * |
||
| 558 | 1 | * @param string $name Name of the property to retrieve |
|
| 559 | 1 | * |
|
| 560 | 1 | * @return null|Parameter |
|
| 561 | 1 | */ |
|
| 562 | 1 | public function getProperty($name) |
|
| 578 | |||
| 579 | /** |
||
| 580 | * Get the additionalProperties value of the parameter |
||
| 581 | * |
||
| 582 | * @return bool|Parameter|null |
||
| 583 | 1 | */ |
|
| 584 | public function getAdditionalProperties() |
||
| 595 | 4 | ||
| 596 | /** |
||
| 597 | * Get the item data of the parameter |
||
| 598 | * |
||
| 599 | * @return Parameter |
||
| 600 | */ |
||
| 601 | public function getItems() |
||
| 612 | 9 | ||
| 613 | /** |
||
| 614 | * Get the enum of strings that are valid for the parameter |
||
| 615 | * |
||
| 616 | * @return array|null |
||
| 617 | */ |
||
| 618 | public function getEnum() |
||
| 622 | |||
| 623 | 10 | /** |
|
| 624 | * Get the regex pattern that must match a value when the value is a string |
||
| 625 | 10 | * |
|
| 626 | 2 | * @return string |
|
| 627 | 1 | */ |
|
| 628 | public function getPattern() |
||
| 632 | |||
| 633 | 9 | /** |
|
| 634 | 9 | * Get the format attribute of the schema |
|
| 635 | 9 | * |
|
| 636 | 7 | * @return string |
|
| 637 | */ |
||
| 638 | public function getFormat() |
||
| 642 | |||
| 643 | /** |
||
| 644 | * Set the array of filters used by the parameter |
||
| 645 | * |
||
| 646 | * @param array $filters Array of functions to use as filters |
||
| 647 | * |
||
| 648 | 3 | * @return self |
|
| 649 | */ |
||
| 650 | 3 | private function setFilters(array $filters) |
|
| 659 | |||
| 660 | /** |
||
| 661 | * Add a filter to the parameter |
||
| 662 | * |
||
| 663 | * @param string|array $filter Method to filter the value through |
||
| 664 | * |
||
| 665 | * @return self |
||
| 666 | * @throws \InvalidArgumentException |
||
| 667 | */ |
||
| 668 | private function addFilter($filter) |
||
| 697 | |||
| 698 | /** |
||
| 699 | * Check if a parameter has a specific variable and if it set. |
||
| 700 | * |
||
| 701 | * @param string $var |
||
| 702 | * @return bool |
||
| 703 | */ |
||
| 704 | public function has($var) |
||
| 711 | |||
| 712 | /** |
||
| 713 | * Filters the given data using filter methods specified in the config. |
||
| 714 | * |
||
| 715 | * If $stage is provided, only filters that apply to the provided filter |
||
| 716 | * stage will be invoked. To preserve legacy behavior, filters that do not |
||
| 717 | * specify a stage are implicitly invoked only in the pre-validation stage. |
||
| 718 | * |
||
| 719 | * @param mixed $value The value to filter. |
||
| 720 | * @param string $stage An optional specifier of what filter stage to |
||
| 721 | * invoke. If null, then all filters are invoked no matter what stage |
||
| 722 | * they apply to. Otherwise, only filters for the specified stage are |
||
| 723 | * invoked. |
||
| 724 | * |
||
| 725 | * @return mixed The filtered value. |
||
| 726 | */ |
||
| 727 | private function invokeCustomFilters($value, $stage) { |
||
| 742 | |||
| 743 | /** |
||
| 744 | * Invokes a filter that uses value substitution and/or should only be |
||
| 745 | * invoked for a particular filter stage. |
||
| 746 | * |
||
| 747 | * If $stage is provided, and the filter specifies a stage, it is not |
||
| 748 | * invoked unless $stage matches the stage the filter indicates it applies |
||
| 749 | * to. If the filter is not invoked, $value is returned exactly as it was |
||
| 750 | * provided to this method. |
||
| 751 | * |
||
| 752 | * To preserve legacy behavior, if the filter does not specify a stage, it |
||
| 753 | * is implicitly invoked only in the pre-validation stage. |
||
| 754 | * |
||
| 755 | * @param array $filter Information about the filter to invoke. |
||
| 756 | * @param mixed $value The value to filter. |
||
| 757 | * @param string $stage An optional specifier of what filter stage to |
||
| 758 | * invoke. If null, then the filter is invoked no matter what stage it |
||
| 759 | * indicates it applies to. Otherwise, the filter is only invoked if it |
||
| 760 | * matches the specified stage. |
||
| 761 | * |
||
| 762 | * @return mixed The filtered value. |
||
| 763 | */ |
||
| 764 | private function invokeComplexFilter(array $filter, $value, $stage) { |
||
| 784 | |||
| 785 | /** |
||
| 786 | * Replaces any placeholders in filter arguments with values from the |
||
| 787 | * current context. |
||
| 788 | * |
||
| 789 | * @param array $filterArgs The array of arguments to pass to the filter |
||
| 790 | * function. Some of the elements of this array are expected to be |
||
| 791 | * placeholders that will be replaced by this function. |
||
| 792 | * |
||
| 793 | * @return array The array of arguments, with all placeholders replaced. |
||
| 794 | */ |
||
| 795 | function expandFilterArgs(array $filterArgs, $value, $stage) { |
||
| 810 | |||
| 811 | /** |
||
| 812 | * Invokes a filter only provides a function or method name to invoke, |
||
| 813 | * without additional parameters. |
||
| 814 | * |
||
| 815 | * If $stage is provided, the filter is not invoked unless we are in the |
||
| 816 | * pre-validation stage, to preserve legacy behavior. |
||
| 817 | * |
||
| 818 | * @param array $filter Information about the filter to invoke. |
||
| 819 | * @param mixed $value The value to filter. |
||
| 820 | * @param string $stage An optional specifier of what filter stage to |
||
| 821 | * invoke. If null, then the filter is invoked no matter what. |
||
| 822 | * Otherwise, the filter is only invoked if the value is |
||
| 823 | * FILTER_STAGE_AFTER_VALIDATION. |
||
| 824 | * |
||
| 825 | * @return mixed The filtered value. |
||
| 826 | */ |
||
| 827 | private function invokeSimpleFilter($filter, $value, $stage) { |
||
| 834 | } |
||
| 835 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)or! empty(...)instead.