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 Remote_Dashboard_Notifications_Client 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 Remote_Dashboard_Notifications_Client, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 29 | final class Remote_Dashboard_Notifications_Client { |
||
| 30 | |||
| 31 | /** |
||
| 32 | * @var Remote_Dashboard_Notifications_Client Holds the unique instance |
||
| 33 | * @since 1.3.0 |
||
| 34 | */ |
||
| 35 | private static $instance; |
||
| 36 | |||
| 37 | /** |
||
| 38 | * Minimum version of WordPress required ot run the plugin |
||
| 39 | * |
||
| 40 | * @since 1.3.0 |
||
| 41 | * @var string |
||
| 42 | */ |
||
| 43 | public $wordpress_version_required = '3.8'; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * Required version of PHP. |
||
| 47 | * |
||
| 48 | * Follow WordPress latest requirements and require |
||
| 49 | * PHP version 5.2 at least. |
||
| 50 | * |
||
| 51 | * @since 1.3.0 |
||
| 52 | * @var string |
||
| 53 | */ |
||
| 54 | public $php_version_required = '5.2'; |
||
| 55 | |||
| 56 | /** |
||
| 57 | * Holds all the registered notifications |
||
| 58 | * |
||
| 59 | * @since 1.3.0 |
||
| 60 | * @var array |
||
| 61 | */ |
||
| 62 | public $notifications = array(); |
||
| 63 | |||
| 64 | /** |
||
| 65 | * Instantiate and return the unique object |
||
| 66 | * |
||
| 67 | * @since 1.2.0 |
||
| 68 | * @return object Remote_Dashboard_Notifications_Client Unique instance |
||
| 69 | */ |
||
| 70 | public static function instance() { |
||
| 80 | |||
| 81 | /** |
||
| 82 | * Instantiate the plugin |
||
| 83 | * |
||
| 84 | * @since 1.3.0 |
||
| 85 | * @return void |
||
| 86 | */ |
||
| 87 | private function init() { |
||
| 114 | |||
| 115 | /** |
||
| 116 | * Throw error on object clone |
||
| 117 | * |
||
| 118 | * The whole idea of the singleton design pattern is that there is a single |
||
| 119 | * object therefore, we don't want the object to be cloned. |
||
| 120 | * |
||
| 121 | * @since 3.2.5 |
||
| 122 | * @return void |
||
| 123 | */ |
||
| 124 | public function __clone() { |
||
| 128 | |||
| 129 | /** |
||
| 130 | * Disable unserializing of the class |
||
| 131 | * |
||
| 132 | * @since 3.2.5 |
||
| 133 | * @return void |
||
| 134 | */ |
||
| 135 | public function __wakeup() { |
||
| 139 | |||
| 140 | /** |
||
| 141 | * Check if the core version is compatible with this addon. |
||
| 142 | * |
||
| 143 | * @since 1.3.0 |
||
| 144 | * @return boolean |
||
| 145 | */ |
||
| 146 | View Code Duplication | private function is_version_compatible() { |
|
| 159 | |||
| 160 | /** |
||
| 161 | * Check if the version of PHP is compatible with this addon. |
||
| 162 | * |
||
| 163 | * @since 1.3.0 |
||
| 164 | * @return boolean |
||
| 165 | */ |
||
| 166 | View Code Duplication | private function is_php_version_enough() { |
|
| 182 | |||
| 183 | /** |
||
| 184 | * Register a new remote notification |
||
| 185 | * |
||
| 186 | * @since 1.3.0 |
||
| 187 | * |
||
| 188 | * @param int $channel_id Channel ID on the remote server |
||
| 189 | * @param string $channel_key Channel key for authentication with the server |
||
| 190 | * @param string $server Notification server URL |
||
| 191 | * @param int $cache Cache lifetime (in hours) |
||
| 192 | * |
||
| 193 | * @return bool|string |
||
| 194 | */ |
||
| 195 | public function add_notification( $channel_id, $channel_key, $server, $cache = 6 ) { |
||
| 222 | |||
| 223 | /** |
||
| 224 | * Remove a registered notification |
||
| 225 | * |
||
| 226 | * @since 1.3.0 |
||
| 227 | * |
||
| 228 | * @param string $notice_id ID of the notice to remove |
||
| 229 | * |
||
| 230 | * @return void |
||
| 231 | */ |
||
| 232 | public function remove_notification( $notice_id ) { |
||
| 237 | |||
| 238 | /** |
||
| 239 | * Get all registered notifications |
||
| 240 | * |
||
| 241 | * @since 1.3.0 |
||
| 242 | * @return array |
||
| 243 | */ |
||
| 244 | public function get_notifications() { |
||
| 247 | |||
| 248 | /** |
||
| 249 | * Get a specific notification |
||
| 250 | * |
||
| 251 | * @since 1.3.0 |
||
| 252 | * |
||
| 253 | * @param string $notice_id ID of the notice to retrieve |
||
| 254 | * |
||
| 255 | * @return bool|array |
||
| 256 | */ |
||
| 257 | public function get_notification( $notice_id ) { |
||
| 265 | |||
| 266 | /** |
||
| 267 | * Adds inline style for non standard notices |
||
| 268 | * |
||
| 269 | * This function will only be called if the notice style is not standard. |
||
| 270 | * |
||
| 271 | * @since 0.1.0 |
||
| 272 | */ |
||
| 273 | public function style() { ?> |
||
| 276 | |||
| 277 | /** |
||
| 278 | * Display all the registered and available notifications |
||
| 279 | * |
||
| 280 | * @since 1.3.0 |
||
| 281 | * @return void |
||
| 282 | */ |
||
| 283 | public function show_notices() { |
||
| 319 | |||
| 320 | /** |
||
| 321 | * Check if the notification has been dismissed |
||
| 322 | * |
||
| 323 | * @since 1.2.0 |
||
| 324 | * |
||
| 325 | * @param string $slug Slug of the notice to check |
||
| 326 | * |
||
| 327 | * @return bool |
||
| 328 | */ |
||
| 329 | protected function is_notice_dismissed( $slug ) { |
||
| 342 | |||
| 343 | /** |
||
| 344 | * Check if the notification can be displayed for the current post type |
||
| 345 | * |
||
| 346 | * @since 1.2.0 |
||
| 347 | * |
||
| 348 | * @param stdClass $notification The notification object |
||
| 349 | * |
||
| 350 | * @return bool |
||
| 351 | */ |
||
| 352 | protected function is_post_type_restricted( $notification ) { |
||
| 374 | |||
| 375 | /** |
||
| 376 | * Check if the notification has started yet |
||
| 377 | * |
||
| 378 | * @since 1.2.0 |
||
| 379 | * |
||
| 380 | * @param stdClass $notification The notification object |
||
| 381 | * |
||
| 382 | * @return bool |
||
| 383 | */ |
||
| 384 | View Code Duplication | protected function is_notification_started( $notification ) { |
|
| 397 | |||
| 398 | /** |
||
| 399 | * Check if the notification has expired |
||
| 400 | * |
||
| 401 | * @since 1.2.0 |
||
| 402 | * |
||
| 403 | * @param stdClass $notification The notification object |
||
| 404 | * |
||
| 405 | * @return bool |
||
| 406 | */ |
||
| 407 | View Code Duplication | protected function has_notification_ended( $notification ) { |
|
| 420 | |||
| 421 | /** |
||
| 422 | * Get the remote notification object |
||
| 423 | * |
||
| 424 | * @since 1.3.0 |
||
| 425 | * |
||
| 426 | * @param array $notification The notification data array |
||
| 427 | * |
||
| 428 | * @return object|false |
||
| 429 | */ |
||
| 430 | protected function get_remote_notification( $notification ) { |
||
| 441 | |||
| 442 | /** |
||
| 443 | * Get the admin notice class attribute |
||
| 444 | * |
||
| 445 | * @since 1.3.0 |
||
| 446 | * |
||
| 447 | * @param string $style Notification style |
||
| 448 | * |
||
| 449 | * @return string |
||
| 450 | */ |
||
| 451 | protected function get_notice_class( $style ) { |
||
| 469 | |||
| 470 | /** |
||
| 471 | * Prepare the dismissal URL for the notice |
||
| 472 | * |
||
| 473 | * @since 1.3.0 |
||
| 474 | * |
||
| 475 | * @param string $slug Notice slug |
||
| 476 | * |
||
| 477 | * @return string |
||
| 478 | */ |
||
| 479 | protected function get_notice_dismissal_url( $slug ) { |
||
| 488 | |||
| 489 | /** |
||
| 490 | * Create the actual admin notice |
||
| 491 | * |
||
| 492 | * @since 1.3.0 |
||
| 493 | * |
||
| 494 | * @param string $contents Notice contents |
||
| 495 | * @param string $class Wrapper class |
||
| 496 | * @param string $dismiss Dismissal link |
||
| 497 | * |
||
| 498 | * @return void |
||
| 499 | */ |
||
| 500 | protected function create_admin_notice( $contents, $class, $dismiss ) { ?> |
||
| 506 | |||
| 507 | /** |
||
| 508 | * Dismiss notice |
||
| 509 | * |
||
| 510 | * When the user dismisses a notice, its slug |
||
| 511 | * is added to the _rn_dismissed entry in the DB options table. |
||
| 512 | * This entry is then used to check if a notie has been dismissed |
||
| 513 | * before displaying it on the dashboard. |
||
| 514 | * |
||
| 515 | * @since 0.1.0 |
||
| 516 | */ |
||
| 517 | public function dismiss() { |
||
| 543 | |||
| 544 | /** |
||
| 545 | * Adds the script that hooks into the Heartbeat API |
||
| 546 | * |
||
| 547 | * @since 1.3.0 |
||
| 548 | * @return void |
||
| 549 | */ |
||
| 550 | public function script() { |
||
| 585 | |||
| 586 | /** |
||
| 587 | * Hook into the Heartbeat API. |
||
| 588 | * |
||
| 589 | * @since 1.3.0 |
||
| 590 | * |
||
| 591 | * @param array $response Heartbeat tick response |
||
| 592 | * @param array $data Heartbeat tick data |
||
| 593 | * |
||
| 594 | * @return array Updated Heartbeat tick response |
||
| 595 | */ |
||
| 596 | function heartbeat( $response, $data ) { |
||
| 627 | |||
| 628 | /** |
||
| 629 | * Triggers the remote requests that fetches notices for this particular instance |
||
| 630 | * |
||
| 631 | * @since 1.3.0 |
||
| 632 | * @return void |
||
| 633 | */ |
||
| 634 | public function remote_get_notice_ajax() { |
||
| 663 | |||
| 664 | /** |
||
| 665 | * Get the remote server URL |
||
| 666 | * |
||
| 667 | * @since 1.2.0 |
||
| 668 | * |
||
| 669 | * @param string $url THe server URL to sanitize |
||
| 670 | * |
||
| 671 | * @return string |
||
| 672 | */ |
||
| 673 | protected function get_remote_url( $url ) { |
||
| 680 | |||
| 681 | /** |
||
| 682 | * Maybe get a notification from the remote server |
||
| 683 | * |
||
| 684 | * @since 1.2.0 |
||
| 685 | * |
||
| 686 | * @param array $notification The notification data array |
||
| 687 | * |
||
| 688 | * @return string|WP_Error |
||
| 689 | */ |
||
| 690 | protected function remote_get_notification( $notification ) { |
||
| 726 | |||
| 727 | /** |
||
| 728 | * Check if the notification returned by the server is an error |
||
| 729 | * |
||
| 730 | * @since 1.2.0 |
||
| 731 | * |
||
| 732 | * @param object $notification Notification returned |
||
| 733 | * |
||
| 734 | * @return bool |
||
| 735 | */ |
||
| 736 | protected function is_notification_error( $notification ) { |
||
| 745 | |||
| 746 | /** |
||
| 747 | * Get the error message returned by the remote server |
||
| 748 | * |
||
| 749 | * @since 1.2.0 |
||
| 750 | * |
||
| 751 | * @param object $notification Notification returned |
||
| 752 | * |
||
| 753 | * @return bool|string |
||
| 754 | */ |
||
| 755 | protected function get_notification_error_message( $notification ) { |
||
| 768 | |||
| 769 | /** |
||
| 770 | * Get the payload required for querying the remote server |
||
| 771 | * |
||
| 772 | * @since 1.2.0 |
||
| 773 | * |
||
| 774 | * @param array $notification The notification data array |
||
| 775 | * |
||
| 776 | * @return string |
||
| 777 | */ |
||
| 778 | protected function get_payload( $notification ) { |
||
| 784 | |||
| 785 | /** |
||
| 786 | * Get the full URL used for the remote get |
||
| 787 | * |
||
| 788 | * @since 1.2.0 |
||
| 789 | * |
||
| 790 | * @param string $url The remote server URL |
||
| 791 | * @param string $payload The encoded payload |
||
| 792 | * |
||
| 793 | * @return string |
||
| 794 | */ |
||
| 795 | protected function build_query_url( $url, $payload ) { |
||
| 801 | |||
| 802 | } |
||
| 803 | |||
| 856 | } |
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.jsonfile (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.jsonto be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
requireorrequire-devsection?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceofchecks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.