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 Wordlift_Entity_Service 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 Wordlift_Entity_Service, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 8 | class Wordlift_Entity_Service { |
||
| 9 | |||
| 10 | /** |
||
| 11 | * The Log service. |
||
| 12 | * |
||
| 13 | * @since 3.2.0 |
||
| 14 | * @access private |
||
| 15 | * @var \Wordlift_Log_Service $log The Log service. |
||
| 16 | */ |
||
| 17 | private $log; |
||
| 18 | |||
| 19 | /** |
||
| 20 | * The UI service. |
||
| 21 | * |
||
| 22 | * @since 3.2.0 |
||
| 23 | * @access private |
||
| 24 | * @var \Wordlift_UI_Service $ui_service The UI service. |
||
| 25 | */ |
||
| 26 | private $ui_service; |
||
| 27 | |||
| 28 | /** |
||
| 29 | * The {@link Wordlift_Relation_Service} instance. |
||
| 30 | * |
||
| 31 | * @since 3.15.0 |
||
| 32 | * @access private |
||
| 33 | * @var \Wordlift_Relation_Service $relation_service The {@link Wordlift_Relation_Service} instance. |
||
| 34 | */ |
||
| 35 | private $relation_service; |
||
| 36 | |||
| 37 | /** |
||
| 38 | * An array of URIs to post ID valid for the current request. |
||
| 39 | * |
||
| 40 | * @since 3.16.1 |
||
| 41 | * @var array $uri_to_post An array of URIs to post ID valid for the current request. |
||
| 42 | */ |
||
| 43 | private $uri_to_post; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * The entity post type name. |
||
| 47 | * |
||
| 48 | * @since 3.1.0 |
||
| 49 | */ |
||
| 50 | const TYPE_NAME = 'entity'; |
||
| 51 | |||
| 52 | /** |
||
| 53 | * The alternative label meta key. |
||
| 54 | * |
||
| 55 | * @since 3.2.0 |
||
| 56 | */ |
||
| 57 | const ALTERNATIVE_LABEL_META_KEY = '_wl_alt_label'; |
||
| 58 | |||
| 59 | /** |
||
| 60 | * The alternative label input template. |
||
| 61 | * |
||
| 62 | * @since 3.2.0 |
||
| 63 | */ |
||
| 64 | // TODO: this should be moved to a class that deals with HTML code. |
||
| 65 | const ALTERNATIVE_LABEL_INPUT_TEMPLATE = '<div class="wl-alternative-label"> |
||
| 66 | <label class="screen-reader-text" id="wl-alternative-label-prompt-text" for="wl-alternative-label">Enter alternative label here</label> |
||
| 67 | <input name="wl_alternative_label[]" size="30" value="%s" id="wl-alternative-label" type="text"> |
||
| 68 | <button class="button wl-delete-button">%s</button> |
||
| 69 | </div>'; |
||
| 70 | |||
| 71 | /** |
||
| 72 | * A singleton instance of the Entity service. |
||
| 73 | * |
||
| 74 | * @since 3.2.0 |
||
| 75 | * @access private |
||
| 76 | * @var \Wordlift_Entity_Service $instance A singleton instance of the Entity service. |
||
| 77 | */ |
||
| 78 | private static $instance; |
||
| 79 | |||
| 80 | /** |
||
| 81 | * Create a Wordlift_Entity_Service instance. |
||
| 82 | * |
||
| 83 | * @since 3.2.0 |
||
| 84 | * |
||
| 85 | * @param \Wordlift_UI_Service $ui_service The UI service. |
||
| 86 | * @param \Wordlift_Relation_Service $relation_service The {@link Wordlift_Relation_Service} instance. |
||
| 87 | */ |
||
| 88 | public function __construct( $ui_service, $relation_service ) { |
||
| 100 | |||
| 101 | /** |
||
| 102 | * Get the singleton instance of the Entity service. |
||
| 103 | * |
||
| 104 | * @since 3.2.0 |
||
| 105 | * @return \Wordlift_Entity_Service The singleton instance of the Entity service. |
||
| 106 | */ |
||
| 107 | public static function get_instance() { |
||
| 111 | |||
| 112 | /** |
||
| 113 | * Determines whether a post is an entity or not. Entity is in this context |
||
| 114 | * something which is not an article. |
||
| 115 | * |
||
| 116 | * @since 3.1.0 |
||
| 117 | * |
||
| 118 | * @param int $post_id A post id. |
||
| 119 | * |
||
| 120 | * @return bool Return true if the post is an entity otherwise false. |
||
| 121 | */ |
||
| 122 | public function is_entity( $post_id ) { |
||
| 137 | |||
| 138 | /** |
||
| 139 | * Get the proper classification scope for a given entity post |
||
| 140 | * |
||
| 141 | * @since 3.5.0 |
||
| 142 | * |
||
| 143 | * @param integer $post_id An entity post id. |
||
| 144 | * |
||
| 145 | * @param string $default The default classification scope, `what` if not |
||
| 146 | * provided. |
||
| 147 | * |
||
| 148 | * @return string Returns a classification scope (e.g. 'what'). |
||
| 149 | */ |
||
| 150 | public function get_classification_scope_for( $post_id, $default = WL_WHAT_RELATION ) { |
||
| 169 | |||
| 170 | /** |
||
| 171 | * Check whether a {@link WP_Post} is used. |
||
| 172 | * |
||
| 173 | * @param int $post_id The {@link WP_Post}'s id. |
||
| 174 | * |
||
| 175 | * @return bool|null Null if it's not an entity, otherwise true if it's used. |
||
| 176 | */ |
||
| 177 | public function is_used( $post_id ) { |
||
| 219 | |||
| 220 | /** |
||
| 221 | * Determines whether a given uri is an internal uri or not. |
||
| 222 | * |
||
| 223 | * @since 3.3.2 |
||
| 224 | * |
||
| 225 | * @param int $uri An uri. |
||
| 226 | * |
||
| 227 | * @return true if the uri internal to the current dataset otherwise false. |
||
| 228 | */ |
||
| 229 | public function is_internal_uri( $uri ) { |
||
| 233 | |||
| 234 | /** |
||
| 235 | * Preload the provided URIs in the local cache. |
||
| 236 | * |
||
| 237 | * This function will populate the local `$uri_to_post` array by running a |
||
| 238 | * single query with all the URIs and returning the mappings in the array. |
||
| 239 | * |
||
| 240 | * @since 3.16.1 |
||
| 241 | * |
||
| 242 | * @param array $uris An array of URIs. |
||
| 243 | */ |
||
| 244 | public function preload_uris( $uris ) { |
||
| 297 | |||
| 298 | /** |
||
| 299 | * Reset the URI to post local cache. |
||
| 300 | * |
||
| 301 | * @since 3.16.1 |
||
| 302 | */ |
||
| 303 | public function reset_uris() { |
||
| 308 | |||
| 309 | /** |
||
| 310 | * Get all the URIs (item id and same as) related to a post. |
||
| 311 | * |
||
| 312 | * @since 3.16.1 |
||
| 313 | * |
||
| 314 | * @param int $post_id The {@link WP_Post) id. |
||
| 315 | * |
||
| 316 | * @return array An array of URIs. |
||
| 317 | */ |
||
| 318 | public function get_uris( $post_id ) { |
||
| 323 | |||
| 324 | |||
| 325 | /** |
||
| 326 | * Find entity posts by the entity URI. Entity as searched by their entity URI or same as. |
||
| 327 | * |
||
| 328 | * @since 3.2.0 |
||
| 329 | * |
||
| 330 | * @param string $uri The entity URI. |
||
| 331 | * |
||
| 332 | * @return WP_Post|null A WP_Post instance or null if not found. |
||
| 333 | */ |
||
| 334 | public function get_entity_post_by_uri( $uri ) { |
||
| 412 | |||
| 413 | /** |
||
| 414 | * Fires once a post has been saved. This function uses the $_REQUEST, therefore |
||
| 415 | * we check that the post we're saving is the current post. |
||
| 416 | * |
||
| 417 | * @see https://github.com/insideout10/wordlift-plugin/issues/363 |
||
| 418 | * |
||
| 419 | * @since 3.2.0 |
||
| 420 | * |
||
| 421 | * @param int $post_id Post ID. |
||
| 422 | * @param WP_Post $post Post object. |
||
| 423 | * @param bool $update Whether this is an existing post being updated or not. |
||
| 424 | */ |
||
| 425 | public function save_post( $post_id, $post, $update ) { |
||
| 449 | |||
| 450 | /** |
||
| 451 | * Set the alternative labels. |
||
| 452 | * |
||
| 453 | * @since 3.2.0 |
||
| 454 | * |
||
| 455 | * @param int $post_id The post id. |
||
| 456 | * @param array $alt_labels An array of labels. |
||
| 457 | */ |
||
| 458 | public function set_alternative_labels( $post_id, $alt_labels ) { |
||
| 478 | |||
| 479 | /** |
||
| 480 | * Retrieve the alternate labels. |
||
| 481 | * |
||
| 482 | * @since 3.2.0 |
||
| 483 | * |
||
| 484 | * @param int $post_id Post id. |
||
| 485 | * |
||
| 486 | * @return mixed An array of alternative labels. |
||
| 487 | */ |
||
| 488 | public function get_alternative_labels( $post_id ) { |
||
| 492 | |||
| 493 | /** |
||
| 494 | * Retrieve the labels for an entity, i.e. the title + the synonyms. |
||
| 495 | * |
||
| 496 | * @since 3.12.0 |
||
| 497 | * |
||
| 498 | * @param int $post_id The entity {@link WP_Post} id. |
||
| 499 | * |
||
| 500 | * @return array An array with the entity title and labels. |
||
| 501 | */ |
||
| 502 | public function get_labels( $post_id ) { |
||
| 506 | |||
| 507 | /** |
||
| 508 | * Fires before the permalink field in the edit form (this event is available in WP from 4.1.0). |
||
| 509 | * |
||
| 510 | * @since 3.2.0 |
||
| 511 | * |
||
| 512 | * @param WP_Post $post Post object. |
||
| 513 | */ |
||
| 514 | public function edit_form_before_permalink( $post ) { |
||
| 535 | |||
| 536 | /** |
||
| 537 | * Get the URI for the entity with the specified post id. |
||
| 538 | * |
||
| 539 | * @since 3.6.0 |
||
| 540 | * |
||
| 541 | * @param int $post_id The entity post id. |
||
| 542 | * |
||
| 543 | * @return null|string The entity URI or NULL if not found or the dataset URI is not configured. |
||
| 544 | */ |
||
| 545 | public function get_uri( $post_id ) { |
||
| 568 | |||
| 569 | |||
| 570 | /** |
||
| 571 | * Get the alternative label input HTML code. |
||
| 572 | * |
||
| 573 | * @since 3.2.0 |
||
| 574 | * |
||
| 575 | * @param string $value The input value. |
||
| 576 | * |
||
| 577 | * @return string The input HTML code. |
||
| 578 | */ |
||
| 579 | private function get_alternative_label_input( $value = '' ) { |
||
| 583 | |||
| 584 | /** |
||
| 585 | * Get the number of entity posts published in this blog. |
||
| 586 | * |
||
| 587 | * @since 3.6.0 |
||
| 588 | * |
||
| 589 | * @return int The number of published entity posts. |
||
| 590 | */ |
||
| 591 | public function count() { |
||
| 600 | |||
| 601 | /** |
||
| 602 | * Add the entity filtering criterias to the arguments for a `get_posts` |
||
| 603 | * call. |
||
| 604 | * |
||
| 605 | * @since 3.15.0 |
||
| 606 | * |
||
| 607 | * @param array $args The arguments for a `get_posts` call. |
||
| 608 | * |
||
| 609 | * @return array The arguments for a `get_posts` call. |
||
| 610 | */ |
||
| 611 | public static function add_criterias( $args ) { |
||
| 623 | |||
| 624 | /** |
||
| 625 | * Get the entity terms IDs which represent an entity. |
||
| 626 | * |
||
| 627 | * @since 3.15.0 |
||
| 628 | * |
||
| 629 | * @return array An array of terms' ids. |
||
| 630 | */ |
||
| 631 | public static function get_entity_terms() { |
||
| 649 | |||
| 650 | /** |
||
| 651 | * Create a new entity. |
||
| 652 | * |
||
| 653 | * @since 3.9.0 |
||
| 654 | * |
||
| 655 | * @param string $name The entity name. |
||
| 656 | * @param string $type_uri The entity's type URI. |
||
| 657 | * @param null $logo The entity logo id (or NULL if none). |
||
| 658 | * @param string $status The post status, by default 'publish'. |
||
| 659 | * |
||
| 660 | * @return int|WP_Error The entity post id or a {@link WP_Error} in case the `wp_insert_post` call fails. |
||
| 661 | */ |
||
| 662 | public function create( $name, $type_uri, $logo = null, $status = 'publish' ) { |
||
| 687 | |||
| 688 | /** |
||
| 689 | * Get the entities related to the one with the specified id. By default only |
||
| 690 | * published entities will be returned. |
||
| 691 | * |
||
| 692 | * @since 3.10.0 |
||
| 693 | * |
||
| 694 | * @param int $id The post id. |
||
| 695 | * @param string $post_status The target post status (default = publish). |
||
| 696 | * |
||
| 697 | * @return array An array of post ids. |
||
| 698 | */ |
||
| 699 | public function get_related_entities( $id, $post_status = 'publish' ) { |
||
| 703 | |||
| 704 | /** |
||
| 705 | * Get the list of entities. |
||
| 706 | * |
||
| 707 | * @since 3.12.2 |
||
| 708 | * |
||
| 709 | * @param array $params Custom parameters for WordPress' own {@link get_posts} function. |
||
| 710 | * |
||
| 711 | * @return array An array of entity posts. |
||
| 712 | */ |
||
| 713 | public function get( $params = array() ) { |
||
| 724 | |||
| 725 | /** |
||
| 726 | * The list of post type names which can be used for entities |
||
| 727 | * |
||
| 728 | * Criteria is that the post type is public. The list of valid post types |
||
| 729 | * can be overridden with a filter. |
||
| 730 | * |
||
| 731 | * @since 3.15.0 |
||
| 732 | * |
||
| 733 | * @return array Array containing the names of the valid post types. |
||
| 734 | */ |
||
| 735 | static function valid_entity_post_types() { |
||
| 742 | |||
| 743 | } |
||
| 744 |
Instead of relying on
globalstate, we recommend one of these alternatives:1. Pass all data via parameters
2. Create a class that maintains your state