[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * List Table API: WP_Privacy_Requests_Table class 4 * 5 * @package WordPress 6 * @subpackage Administration 7 * @since 4.9.6 8 */ 9 10 abstract class WP_Privacy_Requests_Table extends WP_List_Table { 11 12 /** 13 * Action name for the requests this table will work with. Classes 14 * which inherit from WP_Privacy_Requests_Table should define this. 15 * 16 * Example: 'export_personal_data'. 17 * 18 * @since 4.9.6 19 * 20 * @var string $request_type Name of action. 21 */ 22 protected $request_type = 'INVALID'; 23 24 /** 25 * Post type to be used. 26 * 27 * @since 4.9.6 28 * 29 * @var string $post_type The post type. 30 */ 31 protected $post_type = 'INVALID'; 32 33 /** 34 * Get columns to show in the list table. 35 * 36 * @since 4.9.6 37 * 38 * @return string[] Array of column titles keyed by their column name. 39 */ 40 public function get_columns() { 41 $columns = array( 42 'cb' => '<input type="checkbox" />', 43 'email' => __( 'Requester' ), 44 'status' => __( 'Status' ), 45 'created_timestamp' => __( 'Requested' ), 46 'next_steps' => __( 'Next steps' ), 47 ); 48 return $columns; 49 } 50 51 /** 52 * Normalize the admin URL to the current page (by request_type). 53 * 54 * @since 5.3.0 55 * 56 * @return string URL to the current admin page. 57 */ 58 protected function get_admin_url() { 59 $pagenow = str_replace( '_', '-', $this->request_type ); 60 61 if ( 'remove-personal-data' === $pagenow ) { 62 $pagenow = 'erase-personal-data'; 63 } 64 65 return admin_url( $pagenow . '.php' ); 66 } 67 68 /** 69 * Get a list of sortable columns. 70 * 71 * @since 4.9.6 72 * 73 * @return array Default sortable columns. 74 */ 75 protected function get_sortable_columns() { 76 /* 77 * The initial sorting is by 'Requested' (post_date) and descending. 78 * With initial sorting, the first click on 'Requested' should be ascending. 79 * With 'Requester' sorting active, the next click on 'Requested' should be descending. 80 */ 81 $desc_first = isset( $_GET['orderby'] ); 82 83 return array( 84 'email' => 'requester', 85 'created_timestamp' => array( 'requested', $desc_first ), 86 ); 87 } 88 89 /** 90 * Default primary column. 91 * 92 * @since 4.9.6 93 * 94 * @return string Default primary column name. 95 */ 96 protected function get_default_primary_column_name() { 97 return 'email'; 98 } 99 100 /** 101 * Count number of requests for each status. 102 * 103 * @since 4.9.6 104 * 105 * @global wpdb $wpdb WordPress database abstraction object. 106 * 107 * @return object Number of posts for each status. 108 */ 109 protected function get_request_counts() { 110 global $wpdb; 111 112 $cache_key = $this->post_type . '-' . $this->request_type; 113 $counts = wp_cache_get( $cache_key, 'counts' ); 114 115 if ( false !== $counts ) { 116 return $counts; 117 } 118 119 $query = " 120 SELECT post_status, COUNT( * ) AS num_posts 121 FROM {$wpdb->posts} 122 WHERE post_type = %s 123 AND post_name = %s 124 GROUP BY post_status"; 125 126 $results = (array) $wpdb->get_results( $wpdb->prepare( $query, $this->post_type, $this->request_type ), ARRAY_A ); 127 $counts = array_fill_keys( get_post_stati(), 0 ); 128 129 foreach ( $results as $row ) { 130 $counts[ $row['post_status'] ] = $row['num_posts']; 131 } 132 133 $counts = (object) $counts; 134 wp_cache_set( $cache_key, $counts, 'counts' ); 135 136 return $counts; 137 } 138 139 /** 140 * Get an associative array ( id => link ) with the list of views available on this table. 141 * 142 * @since 4.9.6 143 * 144 * @return string[] An array of HTML links keyed by their view. 145 */ 146 protected function get_views() { 147 $current_status = isset( $_REQUEST['filter-status'] ) ? sanitize_text_field( $_REQUEST['filter-status'] ) : ''; 148 $statuses = _wp_privacy_statuses(); 149 $views = array(); 150 $counts = $this->get_request_counts(); 151 $total_requests = absint( array_sum( (array) $counts ) ); 152 153 // Normalized admin URL. 154 $admin_url = $this->get_admin_url(); 155 156 $current_link_attributes = empty( $current_status ) ? ' class="current" aria-current="page"' : ''; 157 $status_label = sprintf( 158 /* translators: %s: Number of requests. */ 159 _nx( 160 'All <span class="count">(%s)</span>', 161 'All <span class="count">(%s)</span>', 162 $total_requests, 163 'requests' 164 ), 165 number_format_i18n( $total_requests ) 166 ); 167 168 $views['all'] = sprintf( 169 '<a href="%s"%s>%s</a>', 170 esc_url( $admin_url ), 171 $current_link_attributes, 172 $status_label 173 ); 174 175 foreach ( $statuses as $status => $label ) { 176 $post_status = get_post_status_object( $status ); 177 if ( ! $post_status ) { 178 continue; 179 } 180 181 $current_link_attributes = $status === $current_status ? ' class="current" aria-current="page"' : ''; 182 $total_status_requests = absint( $counts->{$status} ); 183 184 if ( ! $total_status_requests ) { 185 continue; 186 } 187 188 $status_label = sprintf( 189 translate_nooped_plural( $post_status->label_count, $total_status_requests ), 190 number_format_i18n( $total_status_requests ) 191 ); 192 193 $status_link = add_query_arg( 'filter-status', $status, $admin_url ); 194 195 $views[ $status ] = sprintf( 196 '<a href="%s"%s>%s</a>', 197 esc_url( $status_link ), 198 $current_link_attributes, 199 $status_label 200 ); 201 } 202 203 return $views; 204 } 205 206 /** 207 * Get bulk actions. 208 * 209 * @since 4.9.6 210 * 211 * @return array Array of bulk action labels keyed by their action. 212 */ 213 protected function get_bulk_actions() { 214 return array( 215 'resend' => __( 'Resend confirmation requests' ), 216 'complete' => __( 'Mark requests as completed' ), 217 'delete' => __( 'Delete requests' ), 218 ); 219 } 220 221 /** 222 * Process bulk actions. 223 * 224 * @since 4.9.6 225 * @since 5.6.0 Added support for the `complete` action. 226 */ 227 public function process_bulk_action() { 228 $action = $this->current_action(); 229 $request_ids = isset( $_REQUEST['request_id'] ) ? wp_parse_id_list( wp_unslash( $_REQUEST['request_id'] ) ) : array(); 230 231 if ( empty( $request_ids ) ) { 232 return; 233 } 234 235 $count = 0; 236 $failures = 0; 237 238 check_admin_referer( 'bulk-privacy_requests' ); 239 240 switch ( $action ) { 241 case 'resend': 242 foreach ( $request_ids as $request_id ) { 243 $resend = _wp_privacy_resend_request( $request_id ); 244 245 if ( $resend && ! is_wp_error( $resend ) ) { 246 $count++; 247 } else { 248 $failures++; 249 } 250 } 251 252 if ( $failures ) { 253 add_settings_error( 254 'bulk_action', 255 'bulk_action', 256 sprintf( 257 /* translators: %d: Number of requests. */ 258 _n( 259 '%d confirmation request failed to resend.', 260 '%d confirmation requests failed to resend.', 261 $failures 262 ), 263 $failures 264 ), 265 'error' 266 ); 267 } 268 269 if ( $count ) { 270 add_settings_error( 271 'bulk_action', 272 'bulk_action', 273 sprintf( 274 /* translators: %d: Number of requests. */ 275 _n( 276 '%d confirmation request re-sent successfully.', 277 '%d confirmation requests re-sent successfully.', 278 $count 279 ), 280 $count 281 ), 282 'success' 283 ); 284 } 285 286 break; 287 288 case 'complete': 289 foreach ( $request_ids as $request_id ) { 290 $result = _wp_privacy_completed_request( $request_id ); 291 292 if ( $result && ! is_wp_error( $result ) ) { 293 $count++; 294 } 295 } 296 297 add_settings_error( 298 'bulk_action', 299 'bulk_action', 300 sprintf( 301 /* translators: %d: Number of requests. */ 302 _n( 303 '%d request marked as complete.', 304 '%d requests marked as complete.', 305 $count 306 ), 307 $count 308 ), 309 'success' 310 ); 311 break; 312 313 case 'delete': 314 foreach ( $request_ids as $request_id ) { 315 if ( wp_delete_post( $request_id, true ) ) { 316 $count++; 317 } else { 318 $failures++; 319 } 320 } 321 322 if ( $failures ) { 323 add_settings_error( 324 'bulk_action', 325 'bulk_action', 326 sprintf( 327 /* translators: %d: Number of requests. */ 328 _n( 329 '%d request failed to delete.', 330 '%d requests failed to delete.', 331 $failures 332 ), 333 $failures 334 ), 335 'error' 336 ); 337 } 338 339 if ( $count ) { 340 add_settings_error( 341 'bulk_action', 342 'bulk_action', 343 sprintf( 344 /* translators: %d: Number of requests. */ 345 _n( 346 '%d request deleted successfully.', 347 '%d requests deleted successfully.', 348 $count 349 ), 350 $count 351 ), 352 'success' 353 ); 354 } 355 356 break; 357 } 358 } 359 360 /** 361 * Prepare items to output. 362 * 363 * @since 4.9.6 364 * @since 5.1.0 Added support for column sorting. 365 */ 366 public function prepare_items() { 367 $this->items = array(); 368 $posts_per_page = $this->get_items_per_page( $this->request_type . '_requests_per_page' ); 369 $args = array( 370 'post_type' => $this->post_type, 371 'post_name__in' => array( $this->request_type ), 372 'posts_per_page' => $posts_per_page, 373 'offset' => isset( $_REQUEST['paged'] ) ? max( 0, absint( $_REQUEST['paged'] ) - 1 ) * $posts_per_page : 0, 374 'post_status' => 'any', 375 's' => isset( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : '', 376 ); 377 378 $orderby_mapping = array( 379 'requester' => 'post_title', 380 'requested' => 'post_date', 381 ); 382 383 if ( isset( $_REQUEST['orderby'] ) && isset( $orderby_mapping[ $_REQUEST['orderby'] ] ) ) { 384 $args['orderby'] = $orderby_mapping[ $_REQUEST['orderby'] ]; 385 } 386 387 if ( isset( $_REQUEST['order'] ) && in_array( strtoupper( $_REQUEST['order'] ), array( 'ASC', 'DESC' ), true ) ) { 388 $args['order'] = strtoupper( $_REQUEST['order'] ); 389 } 390 391 if ( ! empty( $_REQUEST['filter-status'] ) ) { 392 $filter_status = isset( $_REQUEST['filter-status'] ) ? sanitize_text_field( $_REQUEST['filter-status'] ) : ''; 393 $args['post_status'] = $filter_status; 394 } 395 396 $requests_query = new WP_Query( $args ); 397 $requests = $requests_query->posts; 398 399 foreach ( $requests as $request ) { 400 $this->items[] = wp_get_user_request( $request->ID ); 401 } 402 403 $this->items = array_filter( $this->items ); 404 405 $this->set_pagination_args( 406 array( 407 'total_items' => $requests_query->found_posts, 408 'per_page' => $posts_per_page, 409 ) 410 ); 411 } 412 413 /** 414 * Checkbox column. 415 * 416 * @since 4.9.6 417 * 418 * @param WP_User_Request $item Item being shown. 419 * @return string Checkbox column markup. 420 */ 421 public function column_cb( $item ) { 422 return sprintf( '<input type="checkbox" name="request_id[]" value="%1$s" /><span class="spinner"></span>', esc_attr( $item->ID ) ); 423 } 424 425 /** 426 * Status column. 427 * 428 * @since 4.9.6 429 * 430 * @param WP_User_Request $item Item being shown. 431 * @return string Status column markup. 432 */ 433 public function column_status( $item ) { 434 $status = get_post_status( $item->ID ); 435 $status_object = get_post_status_object( $status ); 436 437 if ( ! $status_object || empty( $status_object->label ) ) { 438 return '-'; 439 } 440 441 $timestamp = false; 442 443 switch ( $status ) { 444 case 'request-confirmed': 445 $timestamp = $item->confirmed_timestamp; 446 break; 447 case 'request-completed': 448 $timestamp = $item->completed_timestamp; 449 break; 450 } 451 452 echo '<span class="status-label status-' . esc_attr( $status ) . '">'; 453 echo esc_html( $status_object->label ); 454 455 if ( $timestamp ) { 456 echo ' (' . $this->get_timestamp_as_date( $timestamp ) . ')'; 457 } 458 459 echo '</span>'; 460 } 461 462 /** 463 * Convert timestamp for display. 464 * 465 * @since 4.9.6 466 * 467 * @param int $timestamp Event timestamp. 468 * @return string Human readable date. 469 */ 470 protected function get_timestamp_as_date( $timestamp ) { 471 if ( empty( $timestamp ) ) { 472 return ''; 473 } 474 475 $time_diff = time() - $timestamp; 476 477 if ( $time_diff >= 0 && $time_diff < DAY_IN_SECONDS ) { 478 /* translators: %s: Human-readable time difference. */ 479 return sprintf( __( '%s ago' ), human_time_diff( $timestamp ) ); 480 } 481 482 return date_i18n( get_option( 'date_format' ), $timestamp ); 483 } 484 485 /** 486 * Default column handler. 487 * 488 * @since 4.9.6 489 * @since 5.7.0 Added `manage_{$this->screen->id}_custom_column` action. 490 * 491 * @param WP_User_Request $item Item being shown. 492 * @param string $column_name Name of column being shown. 493 */ 494 public function column_default( $item, $column_name ) { 495 /** 496 * Fires for each custom column of a specific request type in the Requests list table. 497 * 498 * Custom columns are registered using the {@see 'manage_export-personal-data_columns'} 499 * and the {@see 'manage_erase-personal-data_columns'} filters. 500 * 501 * @since 5.7.0 502 * 503 * @param string $column_name The name of the column to display. 504 * @param WP_User_Request $item The item being shown. 505 */ 506 do_action( "manage_{$this->screen->id}_custom_column", $column_name, $item ); 507 } 508 509 /** 510 * Created timestamp column. Overridden by children. 511 * 512 * @since 5.7.0 513 * 514 * @param WP_User_Request $item Item being shown. 515 * @return string Human readable date. 516 */ 517 public function column_created_timestamp( $item ) { 518 return $this->get_timestamp_as_date( $item->created_timestamp ); 519 } 520 521 /** 522 * Actions column. Overridden by children. 523 * 524 * @since 4.9.6 525 * 526 * @param WP_User_Request $item Item being shown. 527 * @return string Email column markup. 528 */ 529 public function column_email( $item ) { 530 return sprintf( '<a href="%1$s">%2$s</a> %3$s', esc_url( 'mailto:' . $item->email ), $item->email, $this->row_actions( array() ) ); 531 } 532 533 /** 534 * Next steps column. Overridden by children. 535 * 536 * @since 4.9.6 537 * 538 * @param WP_User_Request $item Item being shown. 539 */ 540 public function column_next_steps( $item ) {} 541 542 /** 543 * Generates content for a single row of the table, 544 * 545 * @since 4.9.6 546 * 547 * @param WP_User_Request $item The current item. 548 */ 549 public function single_row( $item ) { 550 $status = $item->status; 551 552 echo '<tr id="request-' . esc_attr( $item->ID ) . '" class="status-' . esc_attr( $status ) . '">'; 553 $this->single_row_columns( $item ); 554 echo '</tr>'; 555 } 556 557 /** 558 * Embed scripts used to perform actions. Overridden by children. 559 * 560 * @since 4.9.6 561 */ 562 public function embed_scripts() {} 563 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Nov 21 01:00:03 2024 | Cross-referenced by PHPXref 0.7.1 |