PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.5
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
← All changes | admin/class-bulk-editor-list-table.php +108 -59 18.428.5 View file →
@@ -7,8 +7,11 @@
7 7 */
8 8
9 9 /**
10 10 * Implements table for bulk editing.
11 + *
12 + * @deprecated 28.1
13 + * @codeCoverageIgnore
11 14 */
12 15 class WPSEO_Bulk_List_Table extends WP_List_Table {
13 16
14 17 /**
@@ -110,13 +113,24 @@
110 113 */
111 114 protected $input_fields = [];
112 115
113 116 /**
117 + * The field in the database where meta field is saved.
118 + *
119 + * Should be set in the child class.
120 + *
121 + * @var string
122 + */
123 + protected $target_db_field = '';
124 +
125 + /**
114 126 * Class constructor.
115 127 *
116 128 * @param array $args The arguments.
117 129 */
118 130 public function __construct( $args = [] ) {
131 + _deprecated_function( __METHOD__, 'Yoast SEO 28.1' );
132 +
119 133 parent::__construct( $this->settings );
120 134
121 135 $args = wp_parse_args(
122 136 $args,
@@ -122,9 +136,9 @@
122 136 $args,
123 137 [
124 138 'nonce' => '',
125 139 'input_fields' => [],
126 - ]
140 + ],
127 141 );
128 142
129 143 $this->input_fields = $args['input_fields'];
130 144 if ( isset( $_SERVER['REQUEST_URI'] ) ) {
@@ -146,8 +160,10 @@
146 160 }
147 161
148 162 /**
149 163 * Prepares the data and renders the page.
164 + *
165 + * @return void
150 166 */
151 167 public function show_page() {
152 168 $this->prepare_page_navigation();
153 169 $this->prepare_items();
@@ -157,8 +173,10 @@
157 173 }
158 174
159 175 /**
160 176 * Used in the constructor to build a reference list of post types the current user can edit.
177 + *
178 + * @return void
161 179 */
162 180 protected function populate_editable_post_types() {
163 181 $post_types = get_post_types(
164 182 [
@@ -164,9 +182,9 @@
164 182 [
165 183 'public' => true,
166 184 'exclude_from_search' => false,
167 185 ],
168 - 'object'
186 + 'object',
169 187 );
170 188
171 189 $this->all_posts = [];
172 190 $this->own_posts = [];
@@ -187,31 +205,38 @@
187 205 }
188 206 }
189 207
190 208 /**
191 - * Will show the navigation for the table like pagenavigation and pagefilter.
209 + * Will show the navigation for the table like page navigation and page filter.
192 210 *
193 211 * @param string $which Table nav location (such as top).
212 + *
213 + * @return void
194 214 */
195 215 public function display_tablenav( $which ) {
196 - $post_status = sanitize_text_field( filter_input( INPUT_GET, 'post_status' ) );
216 + // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
217 + $post_status = isset( $_GET['post_status'] ) && is_string( $_GET['post_status'] ) ? sanitize_text_field( wp_unslash( $_GET['post_status'] ) ) : '';
218 + $order_by = isset( $_GET['orderby'] ) && is_string( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : '';
219 + $order = isset( $_GET['order'] ) && is_string( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : '';
220 + $post_type_filter = isset( $_GET['post_type_filter'] ) && is_string( $_GET['post_type_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type_filter'] ) ) : '';
221 + // phpcs:enable WordPress.Security.NonceVerification.Recommended;
197 222 ?>
198 223 <div class="tablenav <?php echo esc_attr( $which ); ?>">
199 224
200 225 <?php if ( $which === 'top' ) { ?>
201 226 <form id="posts-filter" action="" method="get">
202 - <input type="hidden" name="nonce" value="<?php echo esc_attr( $this->nonce ); ?>"/>
203 - <input type="hidden" name="page" value="wpseo_tools"/>
204 - <input type="hidden" name="tool" value="bulk-editor"/>
205 - <input type="hidden" name="type" value="<?php echo esc_attr( $this->page_type ); ?>"/>
227 + <input type="hidden" name="nonce" value="<?php echo esc_attr( $this->nonce ); ?>" />
228 + <input type="hidden" name="page" value="wpseo_tools" />
229 + <input type="hidden" name="tool" value="bulk-editor" />
230 + <input type="hidden" name="type" value="<?php echo esc_attr( $this->page_type ); ?>" />
206 231 <input type="hidden" name="orderby"
207 - value="<?php echo esc_attr( filter_input( INPUT_GET, 'orderby' ) ); ?>"/>
232 + value="<?php echo esc_attr( $order_by ); ?>" />
208 233 <input type="hidden" name="order"
209 - value="<?php echo esc_attr( filter_input( INPUT_GET, 'order' ) ); ?>"/>
234 + value="<?php echo esc_attr( $order ); ?>" />
210 235 <input type="hidden" name="post_type_filter"
211 - value="<?php echo esc_attr( filter_input( INPUT_GET, 'post_type_filter' ) ); ?>"/>
236 + value="<?php echo esc_attr( $post_type_filter ); ?>" />
212 237 <?php if ( ! empty( $post_status ) ) { ?>
213 - <input type="hidden" name="post_status" value="<?php echo esc_attr( $post_status ); ?>"/>
238 + <input type="hidden" name="post_status" value="<?php echo esc_attr( $post_status ); ?>" />
214 239 <?php } ?>
215 240 <?php } ?>
216 241
217 242 <?php
@@ -273,21 +298,21 @@
273 298
274 299 $total_posts = $wpdb->get_var(
275 300 $wpdb->prepare(
276 301 "SELECT COUNT(ID) FROM {$subquery}
277 - WHERE post_status IN (" .
278 - implode( ', ', array_fill( 0, count( $states ), '%s' ) ) .
279 - ')',
280 - $states
281 - )
302 + WHERE post_status IN ("
303 + . implode( ', ', array_fill( 0, count( $states ), '%s' ) )
304 + . ')',
305 + $states,
306 + ),
282 307 );
283 308
284 - $post_status = filter_input( INPUT_GET, 'post_status' );
309 + $post_status = isset( $_GET['post_status'] ) && is_string( $_GET['post_status'] ) ? sanitize_text_field( wp_unslash( $_GET['post_status'] ) ) : '';
285 310 $current_link_attributes = empty( $post_status ) ? ' class="current" aria-current="page"' : '';
286 311 $localized_text = sprintf(
287 312 /* translators: %s expands to the number of posts in localized format. */
288 313 _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_posts, 'posts', 'wordpress-seo' ),
289 - number_format_i18n( $total_posts )
314 + number_format_i18n( $total_posts ),
290 315 );
291 316
292 317 $status_links['all'] = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor' . $this->page_url ) ) . '"' . $current_link_attributes . '>' . $localized_text . '</a>';
293 318
@@ -302,10 +327,10 @@
302 327 "
303 328 SELECT COUNT(ID) FROM {$subquery}
304 329 WHERE post_status = %s
305 330 ",
306 - $status_name
307 - )
331 + $status_name,
332 + ),
308 333 );
309 334
310 335 if ( $total === 0 ) {
311 336 continue;
@@ -323,9 +348,9 @@
323 348
324 349 $trashed_posts = $wpdb->get_var(
325 350 "SELECT COUNT(ID) FROM {$subquery}
326 351 WHERE post_status IN ('trash')
327 - "
352 + ",
328 353 );
329 354
330 355 $current_link_attributes = '';
331 356 if ( $post_status === 'trash' ) {
@@ -334,9 +359,9 @@
334 359
335 360 $localized_text = sprintf(
336 361 /* translators: %s expands to the number of trashed posts in localized format. */
337 362 _nx( 'Trash <span class="count">(%s)</span>', 'Trash <span class="count">(%s)</span>', $trashed_posts, 'posts', 'wordpress-seo' ),
338 - number_format_i18n( $trashed_posts )
363 + number_format_i18n( $trashed_posts ),
339 364 );
340 365
341 366 $status_links['trash'] = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor&post_status=trash' . $this->page_url ) ) . '"' . $current_link_attributes . '>' . $localized_text . '</a>';
342 367
@@ -346,8 +371,10 @@
346 371 /**
347 372 * Outputs extra table navigation.
348 373 *
349 374 * @param string $which Table nav location (such as top).
375 + *
376 + * @return void
350 377 */
351 378 public function extra_tablenav( $which ) {
352 379
353 380 if ( $which === 'top' ) {
@@ -354,9 +381,9 @@
354 381 $post_types = get_post_types(
355 382 [
356 383 'public' => true,
357 384 'exclude_from_search' => false,
358 - ]
385 + ],
359 386 );
360 387
361 388 $instance_type = esc_attr( $this->page_type );
362 389
@@ -375,17 +402,17 @@
375 402
376 403 $post_types = $wpdb->get_results(
377 404 $wpdb->prepare(
378 405 "SELECT DISTINCT post_type FROM {$subquery}
379 - WHERE post_status IN (" .
380 - implode( ', ', array_fill( 0, count( $states ), '%s' ) ) .
381 - ') ORDER BY post_type ASC',
382 - $states
383 - )
406 + WHERE post_status IN ("
407 + . implode( ', ', array_fill( 0, count( $states ), '%s' ) )
408 + . ') ORDER BY post_type ASC',
409 + $states,
410 + ),
384 411 );
385 412
386 - $post_type_filter = filter_input( INPUT_GET, 'post_type_filter' );
387 - $selected = ( ! empty( $post_type_filter ) ) ? sanitize_text_field( $post_type_filter ) : '-1';
413 + $post_type_filter = isset( $_GET['post_type_filter'] ) && is_string( $_GET['post_type_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type_filter'] ) ) : '';
414 + $selected = ( ! empty( $post_type_filter ) ) ? $post_type_filter : '-1';
388 415
389 416 $options = '<option value="-1">' . esc_html__( 'Show All Content Types', 'wordpress-seo' ) . '</option>';
390 417
391 418 if ( is_array( $post_types ) && $post_types !== [] ) {
@@ -394,9 +421,9 @@
394 421 $options .= sprintf(
395 422 '<option value="%2$s" %3$s>%1$s</option>',
396 423 esc_html( $obj->labels->name ),
397 424 esc_attr( $post_type->post_type ),
398 - selected( $selected, $post_type->post_type, false )
425 + selected( $selected, $post_type->post_type, false ),
399 426 );
400 427 }
401 428 }
402 429
@@ -402,15 +429,16 @@
402 429
403 430 printf(
404 431 '<label for="%1$s" class="screen-reader-text">%2$s</label>',
405 432 esc_attr( 'post-type-filter-' . $instance_type ),
406 - esc_html__( 'Filter by content type', 'wordpress-seo' )
433 + /* translators: Hidden accessibility text. */
434 + esc_html__( 'Filter by content type', 'wordpress-seo' ),
407 435 );
408 436 printf(
409 437 '<select name="post_type_filter" id="%2$s">%1$s</select>',
410 438 // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $options is properly escaped above.
411 439 $options,
412 - esc_attr( 'post-type-filter-' . $instance_type )
440 + esc_attr( 'post-type-filter-' . $instance_type ),
413 441 );
414 442
415 443 submit_button( esc_html__( 'Filter', 'wordpress-seo' ), 'button', false, false, [ 'id' => 'post-query-submit' ] );
416 444 echo '</div>';
@@ -434,8 +462,10 @@
434 462 }
435 463
436 464 /**
437 465 * Sets the correct pagenumber and pageurl for the navigation.
466 + *
467 + * @return void
438 468 */
439 469 public function prepare_page_navigation() {
440 470
441 471 $request_url = $this->request_url . $this->page_url;
@@ -478,8 +508,10 @@
478 508 }
479 509
480 510 /**
481 511 * Preparing the requested pagerows and setting the needed variables.
512 + *
513 + * @return void
482 514 */
483 515 public function prepare_items() {
484 516
485 517 $post_type_clause = $this->get_post_type_clause();
@@ -511,8 +543,10 @@
511 543 }
512 544
513 545 /**
514 546 * Setting the column headers.
547 + *
548 + * @return void
515 549 */
516 550 protected function set_column_headers() {
517 551 $columns = $this->get_columns();
518 552 $hidden = [];
@@ -535,9 +569,9 @@
535 569 return (int) $wpdb->get_var(
536 570 "SELECT COUNT(ID) FROM {$subquery}
537 571 WHERE post_status IN ({$all_states})
538 572 {$post_type_clause}
539 - "
573 + ",
540 574 );
541 575 }
542 576
543 577 /**
@@ -546,14 +580,13 @@
546 580 * @return string
547 581 */
548 582 protected function get_post_type_clause() {
549 583 // Filter Block.
550 - $post_types = null;
551 584 $post_type_clause = '';
552 - $post_type_filter = filter_input( INPUT_GET, 'post_type_filter' );
585 + $post_type_filter = isset( $_GET['post_type_filter'] ) && is_string( $_GET['post_type_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type_filter'] ) ) : '';
553 586
554 - if ( ! empty( $post_type_filter ) && get_post_type_object( sanitize_text_field( $post_type_filter ) ) ) {
555 - $post_types = esc_sql( sanitize_text_field( $post_type_filter ) );
587 + if ( ! empty( $post_type_filter ) && get_post_type_object( $post_type_filter ) ) {
588 + $post_types = esc_sql( $post_type_filter );
556 589 $post_type_clause = "AND post_type IN ('{$post_types}')";
557 590 }
558 591
559 592 return $post_type_clause;
@@ -564,25 +597,33 @@
564 597 *
565 598 * Total items is the number of all visible items.
566 599 *
567 600 * @param int $total_items Total items counts.
601 + *
602 + * @return void
568 603 */
569 604 protected function set_pagination( $total_items ) {
570 -
571 605 // Calculate items per page.
572 606 $per_page = $this->get_items_per_page( 'wpseo_posts_per_page', 10 );
573 - $paged = esc_sql( sanitize_text_field( filter_input( INPUT_GET, 'paged' ) ) );
607 + $paged = isset( $_GET['paged'] ) && is_string( $_GET['paged'] ) ? esc_sql( sanitize_text_field( wp_unslash( $_GET['paged'] ) ) ) : '';
574 608
575 - if ( empty( $paged ) || ! is_numeric( $paged ) || $paged <= 0 ) {
609 + if ( empty( $paged ) || ! is_numeric( $paged ) ) {
576 610 $paged = 1;
577 611 }
612 + else {
613 + $paged = (int) $paged;
614 + }
578 615
616 + if ( $paged <= 0 ) {
617 + $paged = 1;
618 + }
619 +
579 620 $this->set_pagination_args(
580 621 [
581 622 'total_items' => $total_items,
582 623 'total_pages' => ceil( $total_items / $per_page ),
583 624 'per_page' => $per_page,
584 - ]
625 + ],
585 626 );
586 627
587 628 $this->pagination = [
588 629 'per_page' => $per_page,
@@ -603,16 +644,16 @@
603 644 * @return string
604 645 */
605 646 protected function parse_item_query( $subquery, $all_states, $post_type_clause ) {
606 647 // Order By block.
607 - $orderby = filter_input( INPUT_GET, 'orderby' );
648 + $orderby = isset( $_GET['orderby'] ) && is_string( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : '';
608 649
609 - $orderby = ! empty( $orderby ) ? esc_sql( sanitize_text_field( $orderby ) ) : 'post_title';
650 + $orderby = ! empty( $orderby ) ? esc_sql( $orderby ) : 'post_title';
610 651 $orderby = $this->sanitize_orderby( $orderby );
611 652
612 653 // Order clause.
613 - $order = filter_input( INPUT_GET, 'order' );
614 - $order = ! empty( $order ) ? esc_sql( strtoupper( sanitize_text_field( $order ) ) ) : 'ASC';
654 + $order = isset( $_GET['order'] ) && is_string( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : '';
655 + $order = ! empty( $order ) ? esc_sql( strtoupper( $order ) ) : 'ASC';
615 656 $order = $this->sanitize_order( $order );
616 657
617 658 // Get all needed results.
618 659 $query = "
@@ -667,8 +708,10 @@
667 708 /**
668 709 * Getting all the items.
669 710 *
670 711 * @param string $query SQL query to use.
712 + *
713 + * @return void
671 714 */
672 715 protected function get_items( $query ) {
673 716 global $wpdb;
674 717
@@ -675,10 +718,10 @@
675 718 $this->items = $wpdb->get_results(
676 719 $wpdb->prepare(
677 720 $query,
678 721 $this->pagination['offset'],
679 - $this->pagination['per_page']
680 - )
722 + $this->pagination['per_page'],
723 + ),
681 724 );
682 725 }
683 726
684 727 /**
@@ -704,14 +747,16 @@
704 747 }
705 748
706 749 return $wpdb->prepare(
707 750 implode( ', ', array_fill( 0, count( $states ), '%s' ) ),
708 - $states
751 + $states,
709 752 );
710 753 }
711 754
712 755 /**
713 756 * Based on $this->items and the defined columns, the table rows will be displayed.
757 + *
758 + * @return void
714 759 */
715 760 public function display_rows() {
716 761
717 762 $records = $this->items;
@@ -798,11 +843,11 @@
798 843 if ( $can_edit_post && $rec->post_status !== 'trash' ) {
799 844 $actions['edit'] = sprintf(
800 845 '<a href="%s" aria-label="%s">%s</a>',
801 846 esc_url( get_edit_post_link( $rec->ID, true ) ),
802 - /* translators: %s: post title */
847 + /* translators: Hidden accessibility text; %s: post title. */
803 848 esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;', 'wordpress-seo' ), $title ) ),
804 - __( 'Edit', 'wordpress-seo' )
849 + __( 'Edit', 'wordpress-seo' ),
805 850 );
806 851 }
807 852
808 853 if ( $post_type_object->public ) {
@@ -810,11 +855,11 @@
810 855 if ( $can_edit_post ) {
811 856 $actions['view'] = sprintf(
812 857 '<a href="%s" aria-label="%s">%s</a>',
813 858 esc_url( add_query_arg( 'preview', 'true', get_permalink( $rec->ID ) ) ),
814 - /* translators: %s: post title */
859 + /* translators: Hidden accessibility text; %s: post title. */
815 860 esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;', 'wordpress-seo' ), $title ) ),
816 - __( 'Preview', 'wordpress-seo' )
861 + __( 'Preview', 'wordpress-seo' ),
817 862 );
818 863 }
819 864 }
820 865 elseif ( $rec->post_status !== 'trash' ) {
@@ -820,11 +865,11 @@
820 865 elseif ( $rec->post_status !== 'trash' ) {
821 866 $actions['view'] = sprintf(
822 867 '<a href="%s" aria-label="%s" rel="bookmark">%s</a>',
823 868 esc_url( get_permalink( $rec->ID ) ),
824 - /* translators: %s: post title */
869 + /* translators: Hidden accessibility text; %s: post title. */
825 870 esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'wordpress-seo' ), $title ) ),
826 - __( 'View', 'wordpress-seo' )
871 + __( 'View', 'wordpress-seo' ),
827 872 );
828 873 }
829 874 }
830 875
@@ -878,9 +923,9 @@
878 923 $column_value = sprintf(
879 924 '<a href="#" role="button" class="wpseo-save" data-id="%1$s">%2$s</a> <span aria-hidden="true">|</span> <a href="#" role="button" class="wpseo-save-all">%3$s</a>',
880 925 $rec->ID,
881 926 esc_html__( 'Save', 'wordpress-seo' ),
882 - esc_html__( 'Save all', 'wordpress-seo' )
927 + esc_html__( 'Save all', 'wordpress-seo' ),
883 928 );
884 929 break;
885 930 }
886 931
@@ -919,8 +964,10 @@
919 964 * Method for setting the meta data, which belongs to the records that will be shown on the current page.
920 965 *
921 966 * This method will loop through the current items ($this->items) for getting the post_id. With this data
922 967 * ($needed_ids) the method will query the meta-data table for getting the title.
968 + *
969 + * @return void
923 970 */
924 971 protected function get_meta_data() {
925 972
926 973 $post_ids = $this->get_post_ids();
@@ -957,9 +1004,9 @@
957 1004 global $wpdb;
958 1005
959 1006 $where = $wpdb->prepare(
960 1007 'post_id IN (' . implode( ', ', array_fill( 0, count( $post_ids ), '%d' ) ) . ')',
961 - $post_ids
1008 + $post_ids,
962 1009 );
963 1010
964 1011 $where .= $wpdb->prepare( ' AND meta_key = %s', WPSEO_Meta::$meta_prefix . $this->target_db_field );
965 1012
@@ -970,8 +1017,10 @@
970 1017 /**
971 1018 * Setting $this->meta_data.
972 1019 *
973 1020 * @param array $meta_data Meta data set.
1021 + *
1022 + * @return void
974 1023 */
975 1024 protected function parse_meta_data( $meta_data ) {
976 1025
977 1026 foreach ( $meta_data as $row ) {
@@ -994,9 +1043,9 @@
994 1043 'col_post_status' => __( 'Post Status', 'wordpress-seo' ),
995 1044 'col_post_date' => __( 'Publication date', 'wordpress-seo' ),
996 1045 'col_page_slug' => __( 'Page URL/Slug', 'wordpress-seo' ),
997 1046 ],
998 - $columns
1047 + $columns,
999 1048 );
1000 1049
1001 1050 $columns['col_row_action'] = __( 'Action', 'wordpress-seo' );
1002 1051