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_REST_Product_Attributes_Controller 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_REST_Product_Attributes_Controller, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 23 | class WC_REST_Product_Attributes_Controller extends WC_REST_Controller { |
||
| 24 | |||
| 25 | /** |
||
| 26 | * Endpoint namespace. |
||
| 27 | * |
||
| 28 | * @var string |
||
| 29 | */ |
||
| 30 | protected $namespace = 'wc/v1'; |
||
| 31 | |||
| 32 | /** |
||
| 33 | * Route base. |
||
| 34 | * |
||
| 35 | * @var string |
||
| 36 | */ |
||
| 37 | protected $rest_base = 'products/attributes'; |
||
| 38 | |||
| 39 | /** |
||
| 40 | * Attribute name. |
||
| 41 | * |
||
| 42 | * @var string |
||
| 43 | */ |
||
| 44 | protected $attribute = ''; |
||
| 45 | |||
| 46 | /** |
||
| 47 | * Register the routes for product attributes. |
||
| 48 | */ |
||
| 49 | View Code Duplication | public function register_routes() { |
|
| 50 | register_rest_route( $this->namespace, '/' . $this->rest_base, array( |
||
| 51 | array( |
||
| 52 | 'methods' => WP_REST_Server::READABLE, |
||
| 53 | 'callback' => array( $this, 'get_items' ), |
||
| 54 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), |
||
| 55 | 'args' => $this->get_collection_params(), |
||
| 56 | ), |
||
| 57 | array( |
||
| 58 | 'methods' => WP_REST_Server::CREATABLE, |
||
| 59 | 'callback' => array( $this, 'create_item' ), |
||
| 60 | 'permission_callback' => array( $this, 'create_item_permissions_check' ), |
||
| 61 | 'args' => array_merge( $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), array( |
||
| 62 | 'name' => array( |
||
| 63 | 'required' => true, |
||
| 64 | ), |
||
| 65 | ) ), |
||
| 66 | ), |
||
| 67 | 'schema' => array( $this, 'get_public_item_schema' ), |
||
| 68 | )); |
||
| 69 | |||
| 70 | register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array( |
||
| 71 | array( |
||
| 72 | 'methods' => WP_REST_Server::READABLE, |
||
| 73 | 'callback' => array( $this, 'get_item' ), |
||
| 74 | 'permission_callback' => array( $this, 'get_item_permissions_check' ), |
||
| 75 | 'args' => array( |
||
| 76 | 'context' => $this->get_context_param( array( 'default' => 'view' ) ), |
||
| 77 | ), |
||
| 78 | ), |
||
| 79 | array( |
||
| 80 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 81 | 'callback' => array( $this, 'update_item' ), |
||
| 82 | 'permission_callback' => array( $this, 'update_item_permissions_check' ), |
||
| 83 | 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), |
||
| 84 | ), |
||
| 85 | array( |
||
| 86 | 'methods' => WP_REST_Server::DELETABLE, |
||
| 87 | 'callback' => array( $this, 'delete_item' ), |
||
| 88 | 'permission_callback' => array( $this, 'delete_item_permissions_check' ), |
||
| 89 | 'args' => array( |
||
| 90 | 'force' => array( |
||
| 91 | 'default' => false, |
||
| 92 | 'description' => __( 'Required to be true, as resource does not support trashing.', 'woocommerce' ), |
||
| 93 | ), |
||
| 94 | ), |
||
| 95 | ), |
||
| 96 | 'schema' => array( $this, 'get_public_item_schema' ), |
||
| 97 | ) ); |
||
| 98 | |||
| 99 | register_rest_route( $this->namespace, '/' . $this->rest_base . '/batch', array( |
||
| 100 | array( |
||
| 101 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 102 | 'callback' => array( $this, 'batch_items' ), |
||
| 103 | 'permission_callback' => array( $this, 'batch_items_permissions_check' ), |
||
| 104 | 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), |
||
| 105 | ), |
||
| 106 | 'schema' => array( $this, 'get_public_batch_schema' ), |
||
| 107 | ) ); |
||
| 108 | } |
||
| 109 | |||
| 110 | /** |
||
| 111 | * Check if a given request has access to read the attributes. |
||
| 112 | * |
||
| 113 | * @param WP_REST_Request $request Full details about the request. |
||
| 114 | * @return WP_Error|boolean |
||
| 115 | */ |
||
| 116 | View Code Duplication | public function get_items_permissions_check( $request ) { |
|
| 123 | |||
| 124 | /** |
||
| 125 | * Check if a given request has access to create a attribute. |
||
| 126 | * |
||
| 127 | * @param WP_REST_Request $request Full details about the request. |
||
| 128 | * @return WP_Error|boolean |
||
| 129 | */ |
||
| 130 | View Code Duplication | public function create_item_permissions_check( $request ) { |
|
| 137 | |||
| 138 | /** |
||
| 139 | * Check if a given request has access to read a attribute. |
||
| 140 | * |
||
| 141 | * @param WP_REST_Request $request Full details about the request. |
||
| 142 | * @return WP_Error|boolean |
||
| 143 | */ |
||
| 144 | View Code Duplication | public function get_item_permissions_check( $request ) { |
|
| 155 | |||
| 156 | /** |
||
| 157 | * Check if a given request has access to update a attribute. |
||
| 158 | * |
||
| 159 | * @param WP_REST_Request $request Full details about the request. |
||
| 160 | * @return WP_Error|boolean |
||
| 161 | */ |
||
| 162 | View Code Duplication | public function update_item_permissions_check( $request ) { |
|
| 173 | |||
| 174 | /** |
||
| 175 | * Check if a given request has access to delete a attribute. |
||
| 176 | * |
||
| 177 | * @param WP_REST_Request $request Full details about the request. |
||
| 178 | * @return WP_Error|boolean |
||
| 179 | */ |
||
| 180 | View Code Duplication | public function delete_item_permissions_check( $request ) { |
|
| 191 | |||
| 192 | /** |
||
| 193 | * Check if a given request has access batch create, update and delete items. |
||
| 194 | * |
||
| 195 | * @param WP_REST_Request $request Full details about the request. |
||
| 196 | * @return boolean |
||
| 197 | */ |
||
| 198 | View Code Duplication | public function batch_items_permissions_check( $request ) { |
|
| 205 | |||
| 206 | /** |
||
| 207 | * Get all attributes. |
||
| 208 | * |
||
| 209 | * @param WP_REST_Request $request |
||
| 210 | * @return array |
||
| 211 | */ |
||
| 212 | public function get_items( $request ) { |
||
| 223 | |||
| 224 | /** |
||
| 225 | * Create a single attribute. |
||
| 226 | * |
||
| 227 | * @param WP_REST_Request $request Full details about the request. |
||
| 228 | * @return WP_REST_Request|WP_Error |
||
| 229 | */ |
||
| 230 | public function create_item( $request ) { |
||
| 293 | |||
| 294 | /** |
||
| 295 | * Get a single attribute. |
||
| 296 | * |
||
| 297 | * @param WP_REST_Request $request Full details about the request. |
||
| 298 | * @return WP_REST_Request|WP_Error |
||
| 299 | */ |
||
| 300 | public function get_item( $request ) { |
||
| 313 | |||
| 314 | /** |
||
| 315 | * Update a single term from a taxonomy. |
||
| 316 | * |
||
| 317 | * @param WP_REST_Request $request Full details about the request. |
||
| 318 | * @return WP_REST_Request|WP_Error |
||
| 319 | */ |
||
| 320 | public function update_item( $request ) { |
||
| 392 | |||
| 393 | /** |
||
| 394 | * Delete a single attribute. |
||
| 395 | * |
||
| 396 | * @param WP_REST_Request $request Full details about the request. |
||
| 397 | * @return WP_REST_Response|WP_Error |
||
| 398 | */ |
||
| 399 | public function delete_item( $request ) { |
||
| 455 | |||
| 456 | /** |
||
| 457 | * Prepare a single product attribute output for response. |
||
| 458 | * |
||
| 459 | * @param obj $item Term object. |
||
| 460 | * @param WP_REST_Request $request |
||
| 461 | * @return WP_REST_Response $response |
||
| 462 | */ |
||
| 463 | public function prepare_item_for_response( $item, $request ) { |
||
| 492 | |||
| 493 | /** |
||
| 494 | * Prepare links for the request. |
||
| 495 | * |
||
| 496 | * @param object $attribute Attribute object. |
||
| 497 | * @param WP_REST_Request $request Full details about the request. |
||
| 498 | * @return array Links for the given attribute. |
||
| 499 | */ |
||
| 500 | protected function prepare_links( $attribute ) { |
||
| 513 | |||
| 514 | /** |
||
| 515 | * Get the Attribute's schema, conforming to JSON Schema. |
||
| 516 | * |
||
| 517 | * @return array |
||
| 518 | */ |
||
| 519 | public function get_item_schema() { |
||
| 572 | |||
| 573 | /** |
||
| 574 | * Get the query params for collections |
||
| 575 | * |
||
| 576 | * @return array |
||
| 577 | */ |
||
| 578 | public function get_collection_params() { |
||
| 584 | |||
| 585 | /** |
||
| 586 | * Get attribute name. |
||
| 587 | * |
||
| 588 | * @param WP_REST_Request $request Full details about the request. |
||
| 589 | * @return int|WP_Error |
||
| 590 | */ |
||
| 591 | protected function get_taxonomy( $request ) { |
||
| 604 | |||
| 605 | /** |
||
| 606 | * Get attribute data. |
||
| 607 | * |
||
| 608 | * @param int $id Attribute ID. |
||
| 609 | * @return stdClass|WP_Error |
||
| 610 | */ |
||
| 611 | protected function get_attribute( $id ) { |
||
| 626 | |||
| 627 | /** |
||
| 628 | * Validate attribute slug. |
||
| 629 | * |
||
| 630 | * @param string $slug |
||
| 631 | * @param bool $new_data |
||
| 632 | * @return bool|WP_Error |
||
| 633 | */ |
||
| 634 | protected function validate_attribute_slug( $slug, $new_data = true ) { |
||
| 645 | } |
||
| 646 |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.