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 Post_Meta_Container 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 Post_Meta_Container, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
14 | class Post_Meta_Container extends Container { |
||
15 | /** |
||
16 | * ID of the post the container is working with |
||
17 | * |
||
18 | * @see init() |
||
19 | * @var int |
||
20 | */ |
||
21 | protected $post_id; |
||
22 | |||
23 | /** |
||
24 | * List of default container settings |
||
25 | * |
||
26 | * @see init() |
||
27 | * @var array |
||
28 | */ |
||
29 | public $settings = array( |
||
30 | 'post_type' => array( 'post' ), |
||
31 | 'panel_context' => 'normal', |
||
32 | 'panel_priority' => 'high', |
||
33 | 'show_on' => array( |
||
34 | 'category' => null, |
||
35 | 'template_names' => array(), |
||
36 | 'not_in_template_names' => array(), |
||
37 | 'post_formats' => array(), |
||
38 | 'level_limit' => null, |
||
39 | 'tax_term_id' => null, |
||
40 | 'page_id' => null, |
||
41 | 'parent_page_id' => null, |
||
42 | 'post_path' => null, |
||
43 | ), |
||
44 | ); |
||
45 | |||
46 | /** |
||
47 | * Create a new post meta fields container |
||
48 | * |
||
49 | * @param string $title Unique title of the container |
||
50 | **/ |
||
51 | public function __construct( $title ) { |
||
58 | |||
59 | /** |
||
60 | * Check if all required container settings have been specified |
||
61 | * |
||
62 | * @param array $settings Container settings |
||
63 | **/ |
||
64 | public function check_setup_settings( &$settings = array() ) { |
||
99 | |||
100 | /** |
||
101 | * Create DataStore instance, set post ID to operate with (if such exists). |
||
102 | * Bind attach() and save() to the appropriate WordPress actions. |
||
103 | **/ |
||
104 | public function init( $id = '' ) { |
||
125 | |||
126 | /** |
||
127 | * Perform save operation after successful is_valid_save() check. |
||
128 | * The call is propagated to all fields in the container. |
||
129 | * |
||
130 | * @param int $post_id ID of the post against which save() is ran |
||
131 | **/ |
||
132 | View Code Duplication | public function save( $post_id ) { |
|
146 | |||
147 | /** |
||
148 | * Perform checks whether the current save() request is valid |
||
149 | * Possible errors are triggering save() for autosave requests |
||
150 | * or performing post save outside of the post edit page (like Quick Edit) |
||
151 | * |
||
152 | * @see is_valid_save_conditions() |
||
153 | * @param int $post_id ID of the post against which save() is ran |
||
154 | * @return bool |
||
155 | **/ |
||
156 | public function is_valid_save( $post_id = 0 ) { |
||
167 | |||
168 | /** |
||
169 | * Perform checks whether the current save() request is valid |
||
170 | * Possible errors are triggering save() for autosave requests |
||
171 | * or performing post save outside of the post edit page (like Quick Edit) |
||
172 | * |
||
173 | * @param int $post_id ID of the post against which save() is ran |
||
174 | * @return bool |
||
175 | **/ |
||
176 | public function is_valid_save_conditions( $post_id ) { |
||
282 | |||
283 | /** |
||
284 | * Add meta box for each of the container post types |
||
285 | **/ |
||
286 | public function attach() { |
||
302 | |||
303 | /** |
||
304 | * Classes to add to the post meta box |
||
305 | */ |
||
306 | public function postbox_classes( $classes ) { |
||
310 | |||
311 | /** |
||
312 | * Perform checks whether the container should be attached during the current request |
||
313 | * |
||
314 | * @return bool True if the container is allowed to be attached |
||
315 | **/ |
||
316 | public function is_valid_attach() { |
||
363 | |||
364 | /** |
||
365 | * Revert the result of attach() |
||
366 | **/ |
||
367 | View Code Duplication | public function detach() { |
|
380 | |||
381 | /** |
||
382 | * Output the container markup |
||
383 | **/ |
||
384 | public function render() { |
||
387 | |||
388 | /** |
||
389 | * Set the post ID the container will operate with. |
||
390 | * |
||
391 | * @param int $post_id |
||
392 | **/ |
||
393 | public function set_post_id( $post_id ) { |
||
397 | |||
398 | /** |
||
399 | * Show the container only on pages whose parent is referenced by $parent_page_path. |
||
400 | * |
||
401 | * @param string $parent_page_path |
||
402 | * @return object $this |
||
403 | **/ |
||
404 | 1 | public function show_on_page_children( $parent_page_path ) { |
|
417 | |||
418 | /** |
||
419 | * Show the container only on particular page referenced by it's path. |
||
420 | * |
||
421 | * @param int|string $page page ID or page path |
||
422 | * @return object $this |
||
423 | **/ |
||
424 | 4 | public function show_on_page( $page ) { |
|
443 | |||
444 | /** |
||
445 | * Show the container only on posts from the specified category. |
||
446 | * |
||
447 | * @see show_on_taxonomy_term() |
||
448 | * |
||
449 | * @param string $category_slug |
||
450 | * @return object $this |
||
451 | **/ |
||
452 | public function show_on_category( $category_slug ) { |
||
457 | |||
458 | /** |
||
459 | * Show the container only on pages whose template has filename $template_path. |
||
460 | * |
||
461 | * @param string|array $template_path |
||
462 | * @return object $this |
||
463 | **/ |
||
464 | 2 | public function show_on_template( $template_path ) { |
|
482 | |||
483 | /** |
||
484 | * Hide the container from pages whose template has filename $template_path. |
||
485 | * |
||
486 | * @param string|array $template_path |
||
487 | * @return object $this |
||
488 | **/ |
||
489 | public function hide_on_template( $template_path ) { |
||
501 | |||
502 | /** |
||
503 | * Show the container only on hierarchical posts of level $level. |
||
504 | * Levels start from 1 (top level post) |
||
505 | * |
||
506 | * @param int $level |
||
507 | * @return object $this |
||
508 | **/ |
||
509 | public function show_on_level( $level ) { |
||
518 | |||
519 | /** |
||
520 | * Show the container only on posts which have term $term_slug from the $taxonomy_slug taxonomy. |
||
521 | * |
||
522 | * @param string $taxonomy_slug |
||
523 | * @param string $term_slug |
||
524 | * @return object $this |
||
525 | **/ |
||
526 | public function show_on_taxonomy_term( $term_slug, $taxonomy_slug ) { |
||
535 | |||
536 | /** |
||
537 | * Show the container only on posts from the specified format. |
||
538 | * Learn more about {@link http://codex.wordpress.org/Post_Formats Post Formats (Codex)} |
||
539 | * |
||
540 | * @param string|array $post_format Name of the format as listed on Codex |
||
541 | * @return object $this |
||
542 | **/ |
||
543 | public function show_on_post_format( $post_format ) { |
||
559 | |||
560 | /** |
||
561 | * Show the container only on posts from the specified type(s). |
||
562 | * |
||
563 | * @param string|array $post_types |
||
564 | * @return object $this |
||
565 | **/ |
||
566 | public function show_on_post_type( $post_types ) { |
||
573 | |||
574 | /** |
||
575 | * Sets the meta box container context |
||
576 | * |
||
577 | * @see https://codex.wordpress.org/Function_Reference/add_meta_box |
||
578 | * @param string $context ('normal', 'advanced' or 'side') |
||
579 | */ |
||
580 | public function set_context( $context ) { |
||
585 | |||
586 | /** |
||
587 | * Sets the meta box container priority |
||
588 | * |
||
589 | * @see https://codex.wordpress.org/Function_Reference/add_meta_box |
||
590 | * @param string $priority ('high', 'core', 'default' or 'low') |
||
591 | */ |
||
592 | public function set_priority( $priority ) { |
||
597 | } // END Post_Meta_Container |
||
598 |
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.