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 WC_CLI_Tax 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 WC_CLI_Tax, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 11 | class WC_CLI_Tax extends WC_CLI_Command { |
||
| 12 | |||
| 13 | /** |
||
| 14 | * Create a tax rate. |
||
| 15 | * |
||
| 16 | * ## OPTIONS |
||
| 17 | * |
||
| 18 | * [--<field>=<value>] |
||
| 19 | * : Associative args for the new tax rate. |
||
| 20 | * |
||
| 21 | * [--porcelain] |
||
| 22 | * : Outputs just the new tax rate id. |
||
| 23 | * |
||
| 24 | * ## AVAILABLE FIELDS |
||
| 25 | * |
||
| 26 | * These fields are available for create command: |
||
| 27 | * |
||
| 28 | * * country |
||
| 29 | * * state |
||
| 30 | * * postcode |
||
| 31 | * * city |
||
| 32 | * * rate |
||
| 33 | * * name |
||
| 34 | * * priority |
||
| 35 | * * compound |
||
| 36 | * * shipping |
||
| 37 | * * class |
||
| 38 | * * order |
||
| 39 | * |
||
| 40 | * ## EXAMPLES |
||
| 41 | * |
||
| 42 | * wp wc tax create --country=US --rate=5 --class=standard --type=percent |
||
| 43 | * |
||
| 44 | * @since 2.5.0 |
||
| 45 | */ |
||
| 46 | public function create( $__, $assoc_args ) { |
||
| 97 | |||
| 98 | /** |
||
| 99 | * Create a tax class. |
||
| 100 | * |
||
| 101 | * ## OPTIONS |
||
| 102 | * |
||
| 103 | * [--<field>=<value>] |
||
| 104 | * : Associative args for the new tax class. |
||
| 105 | * |
||
| 106 | * [--porcelain] |
||
| 107 | * : Outputs just the new tax class slug. |
||
| 108 | * |
||
| 109 | * ## AVAILABLE FIELDS |
||
| 110 | * |
||
| 111 | * These fields are available for create command: |
||
| 112 | * |
||
| 113 | * * name |
||
| 114 | * |
||
| 115 | * ## EXAMPLES |
||
| 116 | * |
||
| 117 | * wp wc tax create_class --name="Reduced Rate" |
||
| 118 | * |
||
| 119 | * @since 2.5.0 |
||
| 120 | */ |
||
| 121 | public function create_class( $__, $assoc_args ) { |
||
| 167 | |||
| 168 | /** |
||
| 169 | * Delete one or more tax rates. |
||
| 170 | * |
||
| 171 | * ## OPTIONS |
||
| 172 | * |
||
| 173 | * <id>... |
||
| 174 | * : The tax rate ID to delete. |
||
| 175 | * |
||
| 176 | * ## EXAMPLES |
||
| 177 | * |
||
| 178 | * wp wc tax delete 123 |
||
| 179 | * |
||
| 180 | * wp wc tax delete $(wp wc tax list --format=ids) |
||
| 181 | * |
||
| 182 | * @since 2.5.0 |
||
| 183 | */ |
||
| 184 | public function delete( $args, $assoc_args ) { |
||
| 204 | |||
| 205 | /** |
||
| 206 | * Delete one or more tax classes. |
||
| 207 | * |
||
| 208 | * ## OPTIONS |
||
| 209 | * |
||
| 210 | * <slug>... |
||
| 211 | * : The tax class slug to delete. |
||
| 212 | * |
||
| 213 | * ## EXAMPLES |
||
| 214 | * |
||
| 215 | * wp wc tax delete_class reduced-rate |
||
| 216 | * |
||
| 217 | * wp wc tax delete_class $(wp wc tax list_class --format=ids) |
||
| 218 | * |
||
| 219 | * @since 2.5.0 |
||
| 220 | */ |
||
| 221 | public function delete_class( $args, $assoc_args ) { |
||
| 249 | |||
| 250 | /** |
||
| 251 | * Get a tax rate. |
||
| 252 | * |
||
| 253 | * ## OPTIONS |
||
| 254 | * |
||
| 255 | * <id> |
||
| 256 | * : Tax rate ID |
||
| 257 | * |
||
| 258 | * [--field=<field>] |
||
| 259 | * : Instead of returning the whole tax rate fields, returns the value of a single fields. |
||
| 260 | * |
||
| 261 | * [--fields=<fields>] |
||
| 262 | * : Get a specific subset of the tax rates fields. |
||
| 263 | * |
||
| 264 | * [--format=<format>] |
||
| 265 | * : Accepted values: table, json, csv. Default: table. |
||
| 266 | * |
||
| 267 | * ## AVAILABLE FIELDS |
||
| 268 | * |
||
| 269 | * These fields are available for get command: |
||
| 270 | * |
||
| 271 | * * id |
||
| 272 | * * country |
||
| 273 | * * state |
||
| 274 | * * postcode |
||
| 275 | * * city |
||
| 276 | * * rate |
||
| 277 | * * name |
||
| 278 | * * priority |
||
| 279 | * * compound |
||
| 280 | * * shipping |
||
| 281 | * * order |
||
| 282 | * * class |
||
| 283 | * |
||
| 284 | * ## EXAMPLES |
||
| 285 | * |
||
| 286 | * wp wc tax get 123 --field=rate |
||
| 287 | * |
||
| 288 | * wp wc tax get 321 --format=json > rate321.json |
||
| 289 | * |
||
| 290 | * @since 2.5.0 |
||
| 291 | */ |
||
| 292 | public function get( $args, $assoc_args ) { |
||
| 315 | |||
| 316 | /** |
||
| 317 | * List taxes. |
||
| 318 | * |
||
| 319 | * ## OPTIONS |
||
| 320 | * |
||
| 321 | * [--<field>=<value>] |
||
| 322 | * : Filter tax based on tax property. |
||
| 323 | * |
||
| 324 | * [--field=<field>] |
||
| 325 | * : Prints the value of a single field for each tax. |
||
| 326 | * |
||
| 327 | * [--fields=<fields>] |
||
| 328 | * : Limit the output to specific tax fields. |
||
| 329 | * |
||
| 330 | * [--format=<format>] |
||
| 331 | * : Acceptec values: table, csv, json, count, ids. Default: table. |
||
| 332 | * |
||
| 333 | * ## AVAILABLE FIELDS |
||
| 334 | * |
||
| 335 | * These fields will be displayed by default for each tax: |
||
| 336 | * |
||
| 337 | * * id |
||
| 338 | * * country |
||
| 339 | * * state |
||
| 340 | * * postcode |
||
| 341 | * * city |
||
| 342 | * * rate |
||
| 343 | * * name |
||
| 344 | * * priority |
||
| 345 | * * compound |
||
| 346 | * * shipping |
||
| 347 | * * class |
||
| 348 | * |
||
| 349 | * These fields are optionally available: |
||
| 350 | * |
||
| 351 | * * order |
||
| 352 | * |
||
| 353 | * Fields for filtering query result also available: |
||
| 354 | * |
||
| 355 | * * class Sort by tax class. |
||
| 356 | * * page Page number. |
||
| 357 | * |
||
| 358 | * ## EXAMPLES |
||
| 359 | * |
||
| 360 | * wp wc tax list |
||
| 361 | * |
||
| 362 | * wp wc tax list --field=id |
||
| 363 | * |
||
| 364 | * wp wc tax list --fields=id,rate,class --format=json |
||
| 365 | * |
||
| 366 | * @since 2.5.0 |
||
| 367 | * @subcommand list |
||
| 368 | */ |
||
| 369 | public function list_( $__, $assoc_args ) { |
||
| 386 | |||
| 387 | /** |
||
| 388 | * List tax classes. |
||
| 389 | * |
||
| 390 | * ## OPTIONS |
||
| 391 | * |
||
| 392 | * [--<field>=<value>] |
||
| 393 | * : Filter tax class based on tax class property. |
||
| 394 | * |
||
| 395 | * [--field=<field>] |
||
| 396 | * : Prints the value of a single field for each tax class. |
||
| 397 | * |
||
| 398 | * [--fields=<fields>] |
||
| 399 | * : Limit the output to specific tax class fields. |
||
| 400 | * |
||
| 401 | * [--format=<format>] |
||
| 402 | * : Acceptec values: table, csv, json, count, ids. Default: table. |
||
| 403 | * |
||
| 404 | * ## AVAILABLE FIELDS |
||
| 405 | * |
||
| 406 | * These fields will be displayed by default for each tax class: |
||
| 407 | * |
||
| 408 | * * slug |
||
| 409 | * * name |
||
| 410 | * |
||
| 411 | * ## EXAMPLES |
||
| 412 | * |
||
| 413 | * wp wc tax list_class |
||
| 414 | * |
||
| 415 | * wp wc tax list_class --field=slug |
||
| 416 | * |
||
| 417 | * wp wc tax list_class --format=json |
||
| 418 | * |
||
| 419 | * @since 2.5.0 |
||
| 420 | * @subcommand list_class |
||
| 421 | */ |
||
| 422 | public function list_class( $__, $assoc_args ) { |
||
| 456 | |||
| 457 | /** |
||
| 458 | * Update a tax rate. |
||
| 459 | * |
||
| 460 | * ## OPTIONS |
||
| 461 | * |
||
| 462 | * <id> |
||
| 463 | * : The ID of the tax rate to update. |
||
| 464 | * |
||
| 465 | * [--<field>=<value>] |
||
| 466 | * : One or more fields to update. |
||
| 467 | * |
||
| 468 | * ## AVAILABLE FIELDS |
||
| 469 | * |
||
| 470 | * These fields are available for update command: |
||
| 471 | * |
||
| 472 | * * country |
||
| 473 | * * state |
||
| 474 | * * postcode |
||
| 475 | * * city |
||
| 476 | * * rate |
||
| 477 | * * name |
||
| 478 | * * priority |
||
| 479 | * * compound |
||
| 480 | * * shipping |
||
| 481 | * * class |
||
| 482 | * |
||
| 483 | * ## EXAMPLES |
||
| 484 | * |
||
| 485 | * wp wc tax update 123 --rate=5 |
||
| 486 | * |
||
| 487 | * @since 2.5.0 |
||
| 488 | */ |
||
| 489 | public function update( $args, $assoc_args ) { |
||
| 554 | |||
| 555 | /** |
||
| 556 | * Add common cli arguments to argument list before $wpdb->get_results() is run. |
||
| 557 | * |
||
| 558 | * @since 2.5.0 |
||
| 559 | * @param array $base_args Required arguments for the query (e.g. `limit`, etc) |
||
| 560 | * @param array $assoc_args Arguments provided in when invoking the command |
||
| 561 | * @return array |
||
| 562 | */ |
||
| 563 | protected function merge_tax_query_args( $base_args, $assoc_args ) { |
||
| 582 | |||
| 583 | /** |
||
| 584 | * Helper method to get tax rates objects |
||
| 585 | * |
||
| 586 | * @since 2.5.0 |
||
| 587 | * |
||
| 588 | * @param array $args |
||
| 589 | * |
||
| 590 | * @return array |
||
| 591 | */ |
||
| 592 | protected function query_tax_rates( $args ) { |
||
| 617 | |||
| 618 | /** |
||
| 619 | * Get default format fields that will be used in `list` and `get` subcommands. |
||
| 620 | * |
||
| 621 | * @since 2.5.0 |
||
| 622 | * @return string |
||
| 623 | */ |
||
| 624 | protected function get_default_format_fields() { |
||
| 627 | |||
| 628 | /** |
||
| 629 | * Format taxes from query result to items in which each item contain |
||
| 630 | * common properties of item, for instance `tax_rate_id` will be `id`. |
||
| 631 | * |
||
| 632 | * @since 2.5.0 |
||
| 633 | * @param array $taxes Array of tax rate. |
||
| 634 | * @return array Items |
||
| 635 | */ |
||
| 636 | protected function format_taxes_to_items( $taxes ) { |
||
| 685 | } |
||
| 686 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.