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 CMB2_hookup 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 CMB2_hookup, and based on these observations, apply Extract Interface, too.
| 1 | <?php | ||
| 14 | class CMB2_hookup extends CMB2_Hookup_Base { | ||
|  | |||
| 15 | |||
| 16 | /** | ||
| 17 | * Only allow JS registration once | ||
| 18 | * @var bool | ||
| 19 | * @since 2.0.7 | ||
| 20 | */ | ||
| 21 | protected static $js_registration_done = false; | ||
| 22 | |||
| 23 | /** | ||
| 24 | * Only allow CSS registration once | ||
| 25 | * @var bool | ||
| 26 | * @since 2.0.7 | ||
| 27 | */ | ||
| 28 | protected static $css_registration_done = false; | ||
| 29 | |||
| 30 | /** | ||
| 31 | * CMB taxonomies array for term meta | ||
| 32 | * @var array | ||
| 33 | * @since 2.2.0 | ||
| 34 | */ | ||
| 35 | protected $taxonomies = array(); | ||
| 36 | |||
| 37 | /** | ||
| 38 | * Custom field columns. | ||
| 39 | * @var array | ||
| 40 | * @since 2.2.2 | ||
| 41 | */ | ||
| 42 | protected $columns = array(); | ||
| 43 | |||
| 44 | /** | ||
| 45 | * Constructor | ||
| 46 | * @since 2.0.0 | ||
| 47 | * @param CMB2 $cmb The CMB2 object to hookup | ||
| 48 | */ | ||
| 49 | 	public function __construct( CMB2 $cmb ) { | ||
| 50 | $this->cmb = $cmb; | ||
| 51 | $this->object_type = $this->cmb->mb_object_type(); | ||
| 52 | |||
| 53 | $this->universal_hooks(); | ||
| 54 | |||
| 55 | 		if ( is_admin() ) { | ||
| 56 | |||
| 57 | 			switch ( $this->object_type ) { | ||
| 58 | case 'post': | ||
| 59 | return $this->post_hooks(); | ||
| 60 | case 'comment': | ||
| 61 | return $this->comment_hooks(); | ||
| 62 | case 'user': | ||
| 63 | return $this->user_hooks(); | ||
| 64 | case 'term': | ||
| 65 | return $this->term_hooks(); | ||
| 66 | } | ||
| 67 | |||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | 	public function universal_hooks() { | ||
| 72 | 		foreach ( get_class_methods( 'CMB2_Show_Filters' ) as $filter ) { | ||
| 73 | add_filter( 'cmb2_show_on', array( 'CMB2_Show_Filters', $filter ), 10, 3 ); | ||
| 74 | } | ||
| 75 | |||
| 76 | 		if ( is_admin() ) { | ||
| 77 | // register our scripts and styles for cmb | ||
| 78 | $this->once( 'admin_enqueue_scripts', array( __CLASS__, 'register_scripts' ), 8 ); | ||
| 79 | $this->once( 'admin_enqueue_scripts', array( $this, 'do_scripts' ) ); | ||
| 80 | |||
| 81 | $this->maybe_enqueue_column_display_styles(); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | 	public function post_hooks() { | ||
| 98 | |||
| 99 | 	public function comment_hooks() { | ||
| 108 | |||
| 109 | 	public function user_hooks() { | ||
| 110 | $priority = $this->get_priority(); | ||
| 111 | |||
| 112 | add_action( 'show_user_profile', array( $this, 'user_metabox' ), $priority ); | ||
| 113 | add_action( 'edit_user_profile', array( $this, 'user_metabox' ), $priority ); | ||
| 114 | add_action( 'user_new_form', array( $this, 'user_new_metabox' ), $priority ); | ||
| 115 | |||
| 116 | add_action( 'personal_options_update', array( $this, 'save_user' ) ); | ||
| 117 | add_action( 'edit_user_profile_update', array( $this, 'save_user' ) ); | ||
| 118 | add_action( 'user_register', array( $this, 'save_user' ) ); | ||
| 119 | |||
| 120 | View Code Duplication | 		if ( $this->cmb->has_columns ) { | |
| 121 | add_filter( 'manage_users_columns', array( $this, 'register_column_headers' ) ); | ||
| 122 | add_filter( 'manage_users_custom_column', array( $this, 'return_column_display' ), 10, 3 ); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | 	public function term_hooks() { | ||
| 127 | 		if ( ! function_exists( 'get_term_meta' ) ) { | ||
| 128 | wp_die( __( 'Term Metadata is a WordPress > 4.4 feature. Please upgrade your WordPress install.', 'cmb2' ) ); | ||
| 129 | } | ||
| 130 | |||
| 131 | 		if ( ! $this->cmb->prop( 'taxonomies' ) ) { | ||
| 132 | wp_die( __( 'Term metaboxes configuration requires a \'taxonomies\' parameter', 'cmb2' ) ); | ||
| 133 | } | ||
| 134 | |||
| 135 | $this->taxonomies = (array) $this->cmb->prop( 'taxonomies' ); | ||
| 136 | $show_on_term_add = $this->cmb->prop( 'new_term_section' ); | ||
| 137 | $priority = $this->get_priority( 8 ); | ||
| 138 | |||
| 139 | 		foreach ( $this->taxonomies as $taxonomy ) { | ||
| 140 | // Display our form data | ||
| 141 | 			add_action( "{$taxonomy}_edit_form", array( $this, 'term_metabox' ), $priority, 2 ); | ||
| 142 | |||
| 143 | $show_on_add = is_array( $show_on_term_add ) | ||
| 144 | ? in_array( $taxonomy, $show_on_term_add ) | ||
| 145 | : (bool) $show_on_term_add; | ||
| 146 | |||
| 147 | 			$show_on_add = apply_filters( "cmb2_show_on_term_add_form_{$this->cmb->cmb_id}", $show_on_add, $this->cmb ); | ||
| 148 | |||
| 149 | // Display form in add-new section (unless specified not to) | ||
| 150 | 			if ( $show_on_add ) { | ||
| 151 | 				add_action( "{$taxonomy}_add_form_fields", array( $this, 'term_metabox' ), $priority, 2 ); | ||
| 152 | } | ||
| 153 | |||
| 154 | View Code Duplication | 			if ( $this->cmb->has_columns ) { | |
| 155 | 				add_filter( "manage_edit-{$taxonomy}_columns", array( $this, 'register_column_headers' ) ); | ||
| 156 | 				add_filter( "manage_{$taxonomy}_custom_column", array( $this, 'return_column_display'  ), 10, 3 ); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | add_action( 'created_term', array( $this, 'save_term' ), 10, 3 ); | ||
| 161 | add_action( 'edited_terms', array( $this, 'save_term' ), 10, 2 ); | ||
| 162 | add_action( 'delete_term', array( $this, 'delete_term' ), 10, 3 ); | ||
| 163 | |||
| 164 | } | ||
| 165 | |||
| 166 | /** | ||
| 167 | * Registers styles for CMB2 | ||
| 168 | * @since 2.0.7 | ||
| 169 | */ | ||
| 170 | 1 | 	protected static function register_styles() { | |
| 171 | 1 | 		if ( self::$css_registration_done ) { | |
| 172 | return; | ||
| 173 | } | ||
| 174 | |||
| 175 | // Only use minified files if SCRIPT_DEBUG is off | ||
| 176 | 1 | $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; | |
| 177 | 1 | $front = is_admin() ? '' : '-front'; | |
| 178 | 1 | $rtl = is_rtl() ? '-rtl' : ''; | |
| 179 | |||
| 180 | // Filter required styles and register stylesheet | ||
| 181 | 1 | $dependencies = apply_filters( 'cmb2_style_dependencies', array() ); | |
| 182 | 1 | 		wp_register_style( 'cmb2-styles', cmb2_utils()->url( "css/cmb2{$front}{$rtl}{$min}.css" ), $dependencies ); | |
| 183 | 1 | 		wp_register_style( 'cmb2-display-styles', cmb2_utils()->url( "css/cmb2-display{$rtl}{$min}.css" ), $dependencies ); | |
| 184 | |||
| 185 | 1 | self::$css_registration_done = true; | |
| 186 | 1 | } | |
| 187 | |||
| 188 | /** | ||
| 189 | * Registers scripts for CMB2 | ||
| 190 | * @since 2.0.7 | ||
| 191 | */ | ||
| 192 | 1 | 	protected static function register_js() { | |
| 202 | |||
| 203 | /** | ||
| 204 | * Registers scripts and styles for CMB2 | ||
| 205 | * @since 1.0.0 | ||
| 206 | */ | ||
| 207 | 	public static function register_scripts() { | ||
| 211 | |||
| 212 | /** | ||
| 213 | * Enqueues scripts and styles for CMB2 in admin_head. | ||
| 214 | * @since 1.0.0 | ||
| 215 | */ | ||
| 216 | 	public function do_scripts( $hook ) { | ||
| 240 | |||
| 241 | /** | ||
| 242 | * Register the CMB2 field column headers. | ||
| 243 | * @since 2.2.2 | ||
| 244 | */ | ||
| 245 | 	public function register_column_headers( $columns ) { | ||
| 272 | |||
| 273 | /** | ||
| 274 | * The CMB2 field column display output. | ||
| 275 | * @since 2.2.2 | ||
| 276 | */ | ||
| 277 | 	public function column_display( $column_name, $object_id ) { | ||
| 289 | |||
| 290 | /** | ||
| 291 | * Returns the column display. | ||
| 292 | * @since 2.2.2 | ||
| 293 | */ | ||
| 294 | 	public function return_column_display( $empty, $custom_column, $object_id ) { | ||
| 301 | |||
| 302 | /** | ||
| 303 | * Add metaboxes (to 'post' or 'comment' object types) | ||
| 304 | * @since 1.0.0 | ||
| 305 | */ | ||
| 306 | 	public function add_metaboxes() { | ||
| 342 | |||
| 343 | /** | ||
| 344 | * Add 'closed' class to metabox | ||
| 345 | * @since 2.0.0 | ||
| 346 | * @param array $classes Array of classes | ||
| 347 | * @return array Modified array of classes | ||
| 348 | */ | ||
| 349 | 	public function close_metabox_class( $classes ) { | ||
| 353 | |||
| 354 | /** | ||
| 355 | * Display metaboxes for a post or comment object | ||
| 356 | * @since 1.0.0 | ||
| 357 | */ | ||
| 358 | 	public function metabox_callback() { | ||
| 362 | |||
| 363 | /** | ||
| 364 | * Display metaboxes for new user page | ||
| 365 | * @since 1.0.0 | ||
| 366 | */ | ||
| 367 | 	public function user_new_metabox( $section ) { | ||
| 374 | |||
| 375 | /** | ||
| 376 | * Display metaboxes for a user object | ||
| 377 | * @since 1.0.0 | ||
| 378 | */ | ||
| 379 | 	public function user_metabox() { | ||
| 382 | |||
| 383 | /** | ||
| 384 | * Display metaboxes for a taxonomy term object | ||
| 385 | * @since 2.2.0 | ||
| 386 | */ | ||
| 387 | 	public function term_metabox() { | ||
| 390 | |||
| 391 | /** | ||
| 392 | * Display metaboxes for an object type | ||
| 393 | * @since 2.2.0 | ||
| 394 | * @param string $type Object type | ||
| 395 | * @return void | ||
| 396 | */ | ||
| 397 | 	public function show_form_for_type( $type ) { | ||
| 415 | |||
| 416 | /** | ||
| 417 | * Determines if metabox should be shown in current context | ||
| 418 | * @since 2.0.0 | ||
| 419 | * @return bool Whether metabox should be added/shown | ||
| 420 | */ | ||
| 421 | 	public function show_on() { | ||
| 436 | |||
| 437 | /** | ||
| 438 | * Get the CMB priority property set to numeric hook priority. | ||
| 439 | * @since 2.2.0 | ||
| 440 | * @param integer $default Default display hook priority. | ||
| 441 | * @return integer Hook priority. | ||
| 442 | */ | ||
| 443 | 	public function get_priority( $default = 10 ) { | ||
| 465 | |||
| 466 | /** | ||
| 467 | * Save data from post metabox | ||
| 468 | * @since 1.0.0 | ||
| 469 | * @param int $post_id Post ID | ||
| 470 | * @param mixed $post Post object | ||
| 471 | * @return null | ||
| 472 | */ | ||
| 473 | 	public function save_post( $post_id, $post = false ) { | ||
| 492 | |||
| 493 | /** | ||
| 494 | * Save data from comment metabox | ||
| 495 | * @since 2.0.9 | ||
| 496 | * @param int $comment_id Comment ID | ||
| 497 | * @return null | ||
| 498 | */ | ||
| 499 | 	public function save_comment( $comment_id ) { | ||
| 507 | |||
| 508 | /** | ||
| 509 | * Save data from user fields | ||
| 510 | * @since 1.0.x | ||
| 511 | * @param int $user_id User ID | ||
| 512 | * @return null | ||
| 513 | */ | ||
| 514 | 	public function save_user( $user_id ) { | ||
| 520 | |||
| 521 | /** | ||
| 522 | * Save data from term fields | ||
| 523 | * @since 2.2.0 | ||
| 524 | * @param int $term_id Term ID | ||
| 525 | * @param int $tt_id Term Taxonomy ID | ||
| 526 | * @param string $taxonomy Taxonomy | ||
| 527 | * @return null | ||
| 528 | */ | ||
| 529 | 	public function save_term( $term_id, $tt_id, $taxonomy = '' ) { | ||
| 537 | |||
| 538 | /** | ||
| 539 | * Delete term meta when a term is deleted. | ||
| 540 | * @since 2.2.0 | ||
| 541 | * @param int $term_id Term ID | ||
| 542 | * @param int $tt_id Term Taxonomy ID | ||
| 543 | * @param string $taxonomy Taxonomy | ||
| 544 | * @return null | ||
| 545 | */ | ||
| 546 | 	public function delete_term( $term_id, $tt_id, $taxonomy = '' ) { | ||
| 556 | |||
| 557 | /** | ||
| 558 | * Determines if the current object is able to be saved | ||
| 559 | * @since 2.0.9 | ||
| 560 | * @param string $type Current post_type or comment_type | ||
| 561 | * @return bool Whether object can be saved | ||
| 562 | */ | ||
| 563 | 	public function can_save( $type = '' ) { | ||
| 575 | |||
| 576 | /** | ||
| 577 | * Determine if taxonomy of term being modified is cmb2-editable. | ||
| 578 | * @since 2.2.0 | ||
| 579 | * @param string $taxonomy Taxonomy of term being modified. | ||
| 580 | * @return bool Whether taxonomy is editable. | ||
| 581 | */ | ||
| 582 | 	public function taxonomy_can_save( $taxonomy ) { | ||
| 595 | |||
| 596 | /** | ||
| 597 | * Enqueues the 'cmb2-display-styles' if the conditions match (has columns, on the right page, etc). | ||
| 598 | * @since 2.2.2.1 | ||
| 599 | */ | ||
| 600 | 	protected function maybe_enqueue_column_display_styles() { | ||
| 611 | |||
| 612 | /** | ||
| 613 | * Includes CMB2 styles | ||
| 614 | * @since 2.0.0 | ||
| 615 | */ | ||
| 616 | 1 | 	public static function enqueue_cmb_css( $handle = 'cmb2-styles' ) { | |
| 629 | |||
| 630 | /** | ||
| 631 | * Includes CMB2 JS | ||
| 632 | * @since 2.0.0 | ||
| 633 | */ | ||
| 634 | 1 | 	public static function enqueue_cmb_js() { | |
| 642 | |||
| 643 | } | ||
| 644 | 
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.