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 WP_Media_List_Table 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 WP_Media_List_Table, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class WP_Media_List_Table extends WP_List_Table { |
||
19 | /** |
||
20 | * Holds the number of pending comments for each post. |
||
21 | * |
||
22 | * @since 4.4.0 |
||
23 | * @var array |
||
24 | * @access protected |
||
25 | */ |
||
26 | protected $comment_pending_count = array(); |
||
27 | |||
28 | private $detached; |
||
29 | |||
30 | private $is_trash; |
||
31 | |||
32 | /** |
||
33 | * Constructor. |
||
34 | * |
||
35 | * @since 3.1.0 |
||
36 | * @access public |
||
37 | * |
||
38 | * @see WP_List_Table::__construct() for more information on default arguments. |
||
39 | * |
||
40 | * @param array $args An associative array of arguments. |
||
41 | */ |
||
42 | public function __construct( $args = array() ) { |
||
55 | |||
56 | /** |
||
57 | * |
||
58 | * @return bool |
||
59 | */ |
||
60 | public function ajax_user_can() { |
||
63 | |||
64 | /** |
||
65 | * |
||
66 | * @global WP_Query $wp_query |
||
67 | * @global array $post_mime_types |
||
68 | * @global array $avail_post_mime_types |
||
69 | * @global string $mode |
||
70 | */ |
||
71 | public function prepare_items() { |
||
86 | |||
87 | /** |
||
88 | * @global array $post_mime_types |
||
89 | * @global array $avail_post_mime_types |
||
90 | * @return array |
||
|
|||
91 | */ |
||
92 | protected function get_views() { |
||
135 | |||
136 | /** |
||
137 | * |
||
138 | * @return array |
||
139 | */ |
||
140 | protected function get_bulk_actions() { |
||
158 | |||
159 | /** |
||
160 | * @param string $which |
||
161 | */ |
||
162 | protected function extra_tablenav( $which ) { |
||
163 | if ( 'bar' !== $which ) { |
||
164 | return; |
||
165 | } |
||
166 | ?> |
||
167 | <div class="actions"> |
||
168 | <?php |
||
169 | if ( ! is_singular() ) { |
||
170 | if ( ! $this->is_trash ) { |
||
171 | $this->months_dropdown( 'attachment' ); |
||
172 | } |
||
173 | |||
174 | /** This action is documented in wp-admin/includes/class-wp-posts-list-table.php */ |
||
175 | do_action( 'restrict_manage_posts', $this->screen->post_type, $which ); |
||
176 | |||
177 | submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) ); |
||
178 | } |
||
179 | |||
180 | if ( $this->is_trash && current_user_can( 'edit_others_posts' ) && $this->has_items() ) { |
||
181 | submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false ); |
||
182 | } ?> |
||
183 | </div> |
||
184 | <?php |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * |
||
189 | * @return string |
||
190 | */ |
||
191 | public function current_action() { |
||
203 | |||
204 | /** |
||
205 | * |
||
206 | * @return bool |
||
207 | */ |
||
208 | public function has_items() { |
||
211 | |||
212 | /** |
||
213 | * @access public |
||
214 | */ |
||
215 | public function no_items() { |
||
218 | |||
219 | /** |
||
220 | * Override parent views so we can use the filter bar display. |
||
221 | * |
||
222 | * @global string $mode List table view mode. |
||
223 | */ |
||
224 | public function views() { |
||
269 | |||
270 | /** |
||
271 | * |
||
272 | * @return array |
||
273 | */ |
||
274 | public function get_columns() { |
||
325 | |||
326 | /** |
||
327 | * |
||
328 | * @return array |
||
329 | */ |
||
330 | View Code Duplication | protected function get_sortable_columns() { |
|
339 | |||
340 | /** |
||
341 | * Handles the checkbox column output. |
||
342 | * |
||
343 | * @since 4.3.0 |
||
344 | * @access public |
||
345 | * |
||
346 | * @param WP_Post $post The current WP_Post object. |
||
347 | */ |
||
348 | public function column_cb( $post ) { |
||
356 | |||
357 | /** |
||
358 | * Handles the title column output. |
||
359 | * |
||
360 | * @since 4.3.0 |
||
361 | * @access public |
||
362 | * |
||
363 | * @param WP_Post $post The current WP_Post object. |
||
364 | */ |
||
365 | public function column_title( $post ) { |
||
403 | |||
404 | /** |
||
405 | * Handles the author column output. |
||
406 | * |
||
407 | * @since 4.3.0 |
||
408 | * @access public |
||
409 | * |
||
410 | * @param WP_Post $post The current WP_Post object. |
||
411 | */ |
||
412 | public function column_author( $post ) { |
||
418 | |||
419 | /** |
||
420 | * Handles the description column output. |
||
421 | * |
||
422 | * @since 4.3.0 |
||
423 | * @access public |
||
424 | * |
||
425 | * @param WP_Post $post The current WP_Post object. |
||
426 | */ |
||
427 | public function column_desc( $post ) { |
||
430 | |||
431 | /** |
||
432 | * Handles the date column output. |
||
433 | * |
||
434 | * @since 4.3.0 |
||
435 | * @access public |
||
436 | * |
||
437 | * @param WP_Post $post The current WP_Post object. |
||
438 | */ |
||
439 | public function column_date( $post ) { |
||
458 | |||
459 | /** |
||
460 | * Handles the parent column output. |
||
461 | * |
||
462 | * @since 4.3.0 |
||
463 | * @access public |
||
464 | * |
||
465 | * @param WP_Post $post The current WP_Post object. |
||
466 | */ |
||
467 | public function column_parent( $post ) { |
||
468 | $user_can_edit = current_user_can( 'edit_post', $post->ID ); |
||
469 | |||
470 | if ( $post->post_parent > 0 ) { |
||
471 | $parent = get_post( $post->post_parent ); |
||
472 | } else { |
||
473 | $parent = false; |
||
474 | } |
||
475 | |||
476 | if ( $parent ) { |
||
477 | $title = _draft_or_post_title( $post->post_parent ); |
||
478 | $parent_type = get_post_type_object( $parent->post_type ); |
||
479 | |||
480 | if ( $parent_type && $parent_type->show_ui && current_user_can( 'edit_post', $post->post_parent ) ) { |
||
481 | ?> |
||
482 | <strong><a href="<?php echo get_edit_post_link( $post->post_parent ); ?>"> |
||
483 | <?php echo $title ?></a></strong><?php |
||
484 | } elseif ( $parent_type && current_user_can( 'read_post', $post->post_parent ) ) { |
||
485 | ?> |
||
486 | <strong><?php echo $title ?></strong><?php |
||
487 | } else { |
||
488 | _e( '(Private post)' ); |
||
489 | } |
||
490 | |||
491 | if ( $user_can_edit ): |
||
492 | $detach_url = add_query_arg( array( |
||
493 | 'parent_post_id' => $post->post_parent, |
||
494 | 'media[]' => $post->ID, |
||
495 | '_wpnonce' => wp_create_nonce( 'bulk-' . $this->_args['plural'] ) |
||
496 | ), 'upload.php' ); |
||
497 | printf( |
||
498 | '<br /><a href="%s" class="hide-if-no-js detach-from-parent" aria-label="%s">%s</a>', |
||
499 | $detach_url, |
||
500 | /* translators: %s: title of the post the attachment is attached to */ |
||
501 | esc_attr( sprintf( __( 'Detach from “%s”' ), $title ) ), |
||
502 | __( 'Detach' ) |
||
503 | ); |
||
504 | endif; |
||
505 | } else { |
||
506 | _e( '(Unattached)' ); ?> |
||
507 | <?php if ( $user_can_edit ) { |
||
508 | $title = _draft_or_post_title( $post->post_parent ); |
||
509 | printf( |
||
510 | '<br /><a href="#the-list" onclick="findPosts.open( \'media[]\', \'%s\' ); return false;" class="hide-if-no-js aria-button-if-js" aria-label="%s">%s</a>', |
||
511 | $post->ID, |
||
512 | /* translators: %s: attachment title */ |
||
513 | esc_attr( sprintf( __( 'Attach “%s” to existing content' ), $title ) ), |
||
514 | __( 'Attach' ) |
||
515 | ); |
||
516 | } |
||
517 | } |
||
518 | } |
||
519 | |||
520 | /** |
||
521 | * Handles the comments column output. |
||
522 | * |
||
523 | * @since 4.3.0 |
||
524 | * @access public |
||
525 | * |
||
526 | * @param WP_Post $post The current WP_Post object. |
||
527 | */ |
||
528 | public function column_comments( $post ) { |
||
541 | |||
542 | /** |
||
543 | * Handles output for the default column. |
||
544 | * |
||
545 | * @since 4.3.0 |
||
546 | * @access public |
||
547 | * |
||
548 | * @param WP_Post $post The current WP_Post object. |
||
549 | * @param string $column_name Current column name. |
||
550 | */ |
||
551 | public function column_default( $post, $column_name ) { |
||
597 | |||
598 | /** |
||
599 | * |
||
600 | * @global WP_Post $post |
||
601 | */ |
||
602 | public function display_rows() { |
||
627 | |||
628 | /** |
||
629 | * Gets the name of the default primary column. |
||
630 | * |
||
631 | * @since 4.3.0 |
||
632 | * @access protected |
||
633 | * |
||
634 | * @return string Name of the default primary column, in this case, 'title'. |
||
635 | */ |
||
636 | protected function get_default_primary_column_name() { |
||
639 | |||
640 | /** |
||
641 | * @param WP_Post $post |
||
642 | * @param string $att_title |
||
643 | * |
||
644 | * @return array |
||
645 | */ |
||
646 | private function _get_row_actions( $post, $att_title ) { |
||
647 | $actions = array(); |
||
648 | |||
649 | if ( $this->detached ) { |
||
650 | View Code Duplication | if ( current_user_can( 'edit_post', $post->ID ) ) { |
|
651 | $actions['edit'] = sprintf( |
||
652 | '<a href="%s" aria-label="%s">%s</a>', |
||
653 | get_edit_post_link( $post->ID ), |
||
654 | /* translators: %s: attachment title */ |
||
655 | esc_attr( sprintf( __( 'Edit “%s”' ), $att_title ) ), |
||
656 | __( 'Edit' ) |
||
657 | ); |
||
658 | } |
||
659 | if ( current_user_can( 'delete_post', $post->ID ) ) { |
||
660 | if ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) { |
||
661 | $actions['trash'] = sprintf( |
||
662 | '<a href="%s" class="submitdelete aria-button-if-js" aria-label="%s">%s</a>', |
||
663 | wp_nonce_url( "post.php?action=trash&post=$post->ID", 'trash-post_' . $post->ID ), |
||
664 | /* translators: %s: attachment title */ |
||
665 | esc_attr( sprintf( __( 'Move “%s” to the Trash' ), $att_title ) ), |
||
666 | _x( 'Trash', 'verb' ) |
||
667 | ); |
||
668 | } else { |
||
669 | $delete_ays = ! MEDIA_TRASH ? " onclick='return showNotice.warn();'" : ''; |
||
670 | $actions['delete'] = sprintf( |
||
671 | '<a href="%s" class="submitdelete aria-button-if-js"%s aria-label="%s">%s</a>', |
||
672 | wp_nonce_url( "post.php?action=delete&post=$post->ID", 'delete-post_' . $post->ID ), |
||
673 | $delete_ays, |
||
674 | /* translators: %s: attachment title */ |
||
675 | esc_attr( sprintf( __( 'Delete “%s” permanently' ), $att_title ) ), |
||
676 | __( 'Delete Permanently' ) |
||
677 | ); |
||
678 | } |
||
679 | } |
||
680 | $actions['view'] = sprintf( |
||
681 | '<a href="%s" aria-label="%s" rel="bookmark">%s</a>', |
||
682 | get_permalink( $post->ID ), |
||
683 | /* translators: %s: attachment title */ |
||
684 | esc_attr( sprintf( __( 'View “%s”' ), $att_title ) ), |
||
685 | __( 'View' ) |
||
686 | ); |
||
687 | |||
688 | View Code Duplication | if ( current_user_can( 'edit_post', $post->ID ) ) { |
|
689 | $actions['attach'] = sprintf( |
||
690 | '<a href="#the-list" onclick="findPosts.open( \'media[]\', \'%s\' ); return false;" class="hide-if-no-js aria-button-if-js" aria-label="%s">%s</a>', |
||
691 | $post->ID, |
||
692 | /* translators: %s: attachment title */ |
||
693 | esc_attr( sprintf( __( 'Attach “%s” to existing content' ), $att_title ) ), |
||
694 | __( 'Attach' ) |
||
695 | ); |
||
696 | } |
||
697 | } |
||
698 | else { |
||
699 | View Code Duplication | if ( current_user_can( 'edit_post', $post->ID ) && !$this->is_trash ) { |
|
700 | $actions['edit'] = sprintf( |
||
701 | '<a href="%s" aria-label="%s">%s</a>', |
||
702 | get_edit_post_link( $post->ID ), |
||
703 | /* translators: %s: attachment title */ |
||
704 | esc_attr( sprintf( __( 'Edit “%s”' ), $att_title ) ), |
||
705 | __( 'Edit' ) |
||
706 | ); |
||
707 | } |
||
708 | if ( current_user_can( 'delete_post', $post->ID ) ) { |
||
709 | if ( $this->is_trash ) { |
||
710 | $actions['untrash'] = sprintf( |
||
711 | '<a href="%s" class="submitdelete aria-button-if-js" aria-label="%s">%s</a>', |
||
712 | wp_nonce_url( "post.php?action=untrash&post=$post->ID", 'untrash-post_' . $post->ID ), |
||
713 | /* translators: %s: attachment title */ |
||
714 | esc_attr( sprintf( __( 'Restore “%s” from the Trash' ), $att_title ) ), |
||
715 | __( 'Restore' ) |
||
716 | ); |
||
717 | View Code Duplication | } elseif ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) { |
|
718 | $actions['trash'] = sprintf( |
||
719 | '<a href="%s" class="submitdelete aria-button-if-js" aria-label="%s">%s</a>', |
||
720 | wp_nonce_url( "post.php?action=trash&post=$post->ID", 'trash-post_' . $post->ID ), |
||
721 | /* translators: %s: attachment title */ |
||
722 | esc_attr( sprintf( __( 'Move “%s” to the Trash' ), $att_title ) ), |
||
723 | _x( 'Trash', 'verb' ) |
||
724 | ); |
||
725 | } |
||
726 | if ( $this->is_trash || ! EMPTY_TRASH_DAYS || ! MEDIA_TRASH ) { |
||
727 | $delete_ays = ( !$this->is_trash && !MEDIA_TRASH ) ? " onclick='return showNotice.warn();'" : ''; |
||
728 | $actions['delete'] = sprintf( |
||
729 | '<a href="%s" class="submitdelete aria-button-if-js"%s aria-label="%s">%s</a>', |
||
730 | wp_nonce_url( "post.php?action=delete&post=$post->ID", 'delete-post_' . $post->ID ), |
||
731 | $delete_ays, |
||
732 | /* translators: %s: attachment title */ |
||
733 | esc_attr( sprintf( __( 'Delete “%s” permanently' ), $att_title ) ), |
||
734 | __( 'Delete Permanently' ) |
||
735 | ); |
||
736 | } |
||
737 | } |
||
738 | if ( ! $this->is_trash ) { |
||
739 | $actions['view'] = sprintf( |
||
740 | '<a href="%s" aria-label="%s" rel="bookmark">%s</a>', |
||
741 | get_permalink( $post->ID ), |
||
742 | /* translators: %s: attachment title */ |
||
743 | esc_attr( sprintf( __( 'View “%s”' ), $att_title ) ), |
||
744 | __( 'View' ) |
||
745 | ); |
||
746 | } |
||
747 | } |
||
748 | |||
749 | /** |
||
750 | * Filters the action links for each attachment in the Media list table. |
||
751 | * |
||
752 | * @since 2.8.0 |
||
753 | * |
||
754 | * @param array $actions An array of action links for each attachment. |
||
755 | * Default 'Edit', 'Delete Permanently', 'View'. |
||
756 | * @param WP_Post $post WP_Post object for the current attachment. |
||
757 | * @param bool $detached Whether the list table contains media not attached |
||
758 | * to any posts. Default true. |
||
759 | */ |
||
760 | return apply_filters( 'media_row_actions', $actions, $post, $this->detached ); |
||
761 | } |
||
762 | |||
763 | /** |
||
764 | * Generates and displays row action links. |
||
765 | * |
||
766 | * @since 4.3.0 |
||
767 | * @access protected |
||
768 | * |
||
769 | * @param object $post Attachment being acted upon. |
||
770 | * @param string $column_name Current column name. |
||
771 | * @param string $primary Primary column name. |
||
772 | * @return string Row actions output for media attachments. |
||
773 | */ |
||
774 | protected function handle_row_actions( $post, $column_name, $primary ) { |
||
782 | } |
||
783 |
This check looks for the generic type
array
as a return type and suggests a more specific type. This type is inferred from the actual code.