PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 2.0.7
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v2.0.7
4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 All 340 releases
profile-builder / features / class-list-table.php

class-list-table.php in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 2.0.7, at features/class-list-table.php

967 lines 23.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Base class for displaying a list of items in an ajaxified HTML table.
5 *
6 * @package WordPress
7 * @subpackage List_Table
8 * @since 3.1.0
9 * @access private
10 */
11 class PB_WP_List_Table {
12
13 /**
14 * The current list of items
15 *
16 * @since 3.1.0
17 * @var array
18 * @access protected
19 */
20 var $items;
21
22 /**
23 * Various information about the current table
24 *
25 * @since 3.1.0
26 * @var array
27 * @access private
28 */
29 var $_args;
30
31 /**
32 * Various information needed for displaying the pagination
33 *
34 * @since 3.1.0
35 * @var array
36 * @access private
37 */
38 var $_pagination_args = array();
39
40 /**
41 * The current screen
42 *
43 * @since 3.1.0
44 * @var object
45 * @access protected
46 */
47 var $screen;
48
49 /**
50 * Cached bulk actions
51 *
52 * @since 3.1.0
53 * @var array
54 * @access private
55 */
56 var $_actions;
57
58 /**
59 * Cached pagination output
60 *
61 * @since 3.1.0
62 * @var string
63 * @access private
64 */
65 var $_pagination;
66
67 /**
68 * Constructor. The child class should call this constructor from its own constructor
69 *
70 * @param array $args An associative array with information about the current table
71 * @access protected
72 */
73 function __construct( $args = array() ) {
74 $args = wp_parse_args( $args, array(
75 'plural' => '',
76 'singular' => '',
77 'ajax' => false,
78 'screen' => null,
79 ) );
80
81 $this->screen = convert_to_screen( $args['screen'] );
82
83 add_filter( "manage_{$this->screen->id}_columns", array( $this, 'get_columns' ), 0 );
84
85 if ( !$args['plural'] )
86 $args['plural'] = $this->screen->base;
87
88 $args['plural'] = sanitize_key( $args['plural'] );
89 $args['singular'] = sanitize_key( $args['singular'] );
90
91 $this->_args = $args;
92
93 if ( $args['ajax'] ) {
94 // wp_enqueue_script( 'list-table' );
95 add_action( 'admin_footer', array( $this, '_js_vars' ) );
96 }
97 }
98
99 /**
100 * Checks the current user's permissions
101 * @uses wp_die()
102 *
103 * @since 3.1.0
104 * @access public
105 * @abstract
106 */
107 function ajax_user_can() {
108 die( 'function WP_List_Table::ajax_user_can() must be over-ridden in a sub-class.' );
109 }
110
111 /**
112 * Prepares the list of items for displaying.
113 * @uses WP_List_Table::set_pagination_args()
114 *
115 * @since 3.1.0
116 * @access public
117 * @abstract
118 */
119 function prepare_items() {
120 die( 'function WP_List_Table::prepare_items() must be over-ridden in a sub-class.' );
121 }
122
123 /**
124 * An internal method that sets all the necessary pagination arguments
125 *
126 * @param array $args An associative array with information about the pagination
127 * @access protected
128 */
129 function set_pagination_args( $args ) {
130 $args = wp_parse_args( $args, array(
131 'total_items' => 0,
132 'total_pages' => 0,
133 'per_page' => 0,
134 ) );
135
136 if ( !$args['total_pages'] && $args['per_page'] > 0 )
137 $args['total_pages'] = ceil( $args['total_items'] / $args['per_page'] );
138
139 // redirect if page number is invalid and headers are not already sent
140 if ( ! headers_sent() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) && $args['total_pages'] > 0 && $this->get_pagenum() > $args['total_pages'] ) {
141 wp_redirect( add_query_arg( 'paged', $args['total_pages'] ) );
142 exit;
143 }
144
145 $this->_pagination_args = $args;
146 }
147
148 /**
149 * Access the pagination args
150 *
151 * @since 3.1.0
152 * @access public
153 *
154 * @param string $key
155 * @return array
156 */
157 function get_pagination_arg( $key ) {
158 if ( 'page' == $key )
159 return $this->get_pagenum();
160
161 if ( isset( $this->_pagination_args[$key] ) )
162 return $this->_pagination_args[$key];
163 }
164
165 /**
166 * Whether the table has items to display or not
167 *
168 * @since 3.1.0
169 * @access public
170 *
171 * @return bool
172 */
173 function has_items() {
174 return !empty( $this->items );
175 }
176
177 /**
178 * Message to be displayed when there are no items
179 *
180 * @since 3.1.0
181 * @access public
182 */
183 function no_items() {
184 _e( 'No items found.' );
185 }
186
187 /**
188 * Display the search box.
189 *
190 * @since 3.1.0
191 * @access public
192 *
193 * @param string $text The search button text
194 * @param string $input_id The search input id
195 */
196 function search_box( $text, $input_id ) {
197 if ( empty( $_REQUEST['s'] ) && !$this->has_items() )
198 return;
199
200 $input_id = $input_id . '-search-input';
201
202 if ( ! empty( $_REQUEST['orderby'] ) )
203 echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
204 if ( ! empty( $_REQUEST['order'] ) )
205 echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
206 if ( ! empty( $_REQUEST['post_mime_type'] ) )
207 echo '<input type="hidden" name="post_mime_type" value="' . esc_attr( $_REQUEST['post_mime_type'] ) . '" />';
208 if ( ! empty( $_REQUEST['detached'] ) )
209 echo '<input type="hidden" name="detached" value="' . esc_attr( $_REQUEST['detached'] ) . '" />';
210 ?>
211 <p class="search-box">
212 <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
213 <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>" />
214 <?php submit_button( $text, 'button', false, false, array('id' => 'search-submit') ); ?>
215 </p>
216 <?php
217 }
218
219 /**
220 * Get an associative array ( id => link ) with the list
221 * of views available on this table.
222 *
223 * @since 3.1.0
224 * @access protected
225 *
226 * @return array
227 */
228 function get_views() {
229 return array();
230 }
231
232 /**
233 * Display the list of views available on this table.
234 *
235 * @since 3.1.0
236 * @access public
237 */
238 function views() {
239 $views = $this->get_views();
240 /**
241 * Filter the list of available list table views.
242 *
243 * The dynamic portion of the hook name, $this->screen->id, refers
244 * to the ID of the current screen, usually a string.
245 *
246 * @since 3.5.0
247 *
248 * @param array $views An array of available list table views.
249 */
250 $views = apply_filters( "views_{$this->screen->id}", $views );
251
252 if ( empty( $views ) )
253 return;
254
255 echo "<ul class='subsubsub'>\n";
256 foreach ( $views as $class => $view ) {
257 $views[ $class ] = "\t<li class='$class'>$view";
258 }
259 echo implode( " |</li>\n", $views ) . "</li>\n";
260 echo "</ul>";
261 }
262
263 /**
264 * Get an associative array ( option_name => option_title ) with the list
265 * of bulk actions available on this table.
266 *
267 * @since 3.1.0
268 * @access protected
269 *
270 * @return array
271 */
272 function get_bulk_actions() {
273 return array();
274 }
275
276 /**
277 * Display the bulk actions dropdown.
278 *
279 * @since 3.1.0
280 * @access public
281 */
282 function bulk_actions() {
283 if ( is_null( $this->_actions ) ) {
284 $no_new_actions = $this->_actions = $this->get_bulk_actions();
285 /**
286 * Filter the list table Bulk Actions drop-down.
287 *
288 * The dynamic portion of the hook name, $this->screen->id, refers
289 * to the ID of the current screen, usually a string.
290 *
291 * This filter can currently only be used to remove bulk actions.
292 *
293 * @since 3.5.0
294 *
295 * @param array $actions An array of the available bulk actions.
296 */
297 $this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions );
298 $this->_actions = array_intersect_assoc( $this->_actions, $no_new_actions );
299 $two = '';
300 } else {
301 $two = '2';
302 }
303
304 if ( empty( $this->_actions ) )
305 return;
306
307 echo "<select name='action$two'>\n";
308 echo "<option value='-1' selected='selected'>" . __( 'Bulk Actions' ) . "</option>\n";
309
310 foreach ( $this->_actions as $name => $title ) {
311 $class = 'edit' == $name ? ' class="hide-if-no-js"' : '';
312
313 echo "\t<option value='$name'$class>$title</option>\n";
314 }
315
316 echo "</select>\n";
317
318 submit_button( __( 'Apply' ), 'action', false, false, array( 'id' => "doaction$two" ) );
319 echo "\n";
320 }
321
322 /**
323 * Get the current action selected from the bulk actions dropdown.
324 *
325 * @since 3.1.0
326 * @access public
327 *
328 * @return string|bool The action name or False if no action was selected
329 */
330 function current_action() {
331 if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] )
332 return $_REQUEST['action'];
333
334 if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] )
335 return $_REQUEST['action2'];
336
337 return false;
338 }
339
340 /**
341 * Generate row actions div
342 *
343 * @since 3.1.0
344 * @access protected
345 *
346 * @param array $actions The list of actions
347 * @param bool $always_visible Whether the actions should be always visible
348 * @return string
349 */
350 function row_actions( $actions, $always_visible = false ) {
351 $action_count = count( $actions );
352 $i = 0;
353
354 if ( !$action_count )
355 return '';
356
357 $out = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';
358 foreach ( $actions as $action => $link ) {
359 ++$i;
360 ( $i == $action_count ) ? $sep = '' : $sep = ' | ';
361 $out .= "<span class='$action'>$link$sep</span>";
362 }
363 $out .= '</div>';
364
365 return $out;
366 }
367
368 /**
369 * Display a monthly dropdown for filtering items
370 *
371 * @since 3.1.0
372 * @access protected
373 */
374 function months_dropdown( $post_type ) {
375 global $wpdb, $wp_locale;
376
377 $months = $wpdb->get_results( $wpdb->prepare( "
378 SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
379 FROM $wpdb->posts
380 WHERE post_type = %s
381 ORDER BY post_date DESC
382 ", $post_type ) );
383
384 /**
385 * Filter the 'Months' drop-down results.
386 *
387 * @since 3.7.0
388 *
389 * @param object $months The months drop-down query results.
390 * @param string $post_type The post type.
391 */
392 $months = apply_filters( 'months_dropdown_results', $months, $post_type );
393
394 $month_count = count( $months );
395
396 if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) )
397 return;
398
399 $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
400 ?>
401 <select name='m'>
402 <option<?php selected( $m, 0 ); ?> value='0'><?php _e( 'Show all dates' ); ?></option>
403 <?php
404 foreach ( $months as $arc_row ) {
405 if ( 0 == $arc_row->year )
406 continue;
407
408 $month = zeroise( $arc_row->month, 2 );
409 $year = $arc_row->year;
410
411 printf( "<option %s value='%s'>%s</option>\n",
412 selected( $m, $year . $month, false ),
413 esc_attr( $arc_row->year . $month ),
414 /* translators: 1: month name, 2: 4-digit year */
415 sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year )
416 );
417 }
418 ?>
419 </select>
420 <?php
421 }
422
423 /**
424 * Display a view switcher
425 *
426 * @since 3.1.0
427 * @access protected
428 */
429 function view_switcher( $current_mode ) {
430 $modes = array(
431 'list' => __( 'List View' ),
432 'excerpt' => __( 'Excerpt View' )
433 );
434
435 ?>
436 <input type="hidden" name="mode" value="<?php echo esc_attr( $current_mode ); ?>" />
437 <div class="view-switch">
438 <?php
439 foreach ( $modes as $mode => $title ) {
440 $class = ( $current_mode == $mode ) ? 'class="current"' : '';
441 echo "<a href='" . esc_url( add_query_arg( 'mode', $mode, $_SERVER['REQUEST_URI'] ) ) . "' $class><img id='view-switch-$mode' src='" . esc_url( includes_url( 'images/blank.gif' ) ) . "' width='20' height='20' title='$title' alt='$title' /></a>\n";
442 }
443 ?>
444 </div>
445 <?php
446 }
447
448 /**
449 * Display a comment count bubble
450 *
451 * @since 3.1.0
452 * @access protected
453 *
454 * @param int $post_id
455 * @param int $pending_comments
456 */
457 function comments_bubble( $post_id, $pending_comments ) {
458 $pending_phrase = sprintf( __( '%s pending' ), number_format( $pending_comments ) );
459
460 if ( $pending_comments )
461 echo '<strong>';
462
463 echo "<a href='" . esc_url( add_query_arg( 'p', $post_id, admin_url( 'edit-comments.php' ) ) ) . "' title='" . esc_attr( $pending_phrase ) . "' class='post-com-count'><span class='comment-count'>" . number_format_i18n( get_comments_number() ) . "</span></a>";
464
465 if ( $pending_comments )
466 echo '</strong>';
467 }
468
469 /**
470 * Get the current page number
471 *
472 * @since 3.1.0
473 * @access protected
474 *
475 * @return int
476 */
477 function get_pagenum() {
478 $pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0;
479
480 if( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] )
481 $pagenum = $this->_pagination_args['total_pages'];
482
483 return max( 1, $pagenum );
484 }
485
486 /**
487 * Get number of items to display on a single page
488 *
489 * @since 3.1.0
490 * @access protected
491 *
492 * @return int
493 */
494 function get_items_per_page( $option, $default = 20 ) {
495 $per_page = (int) get_user_option( $option );
496 if ( empty( $per_page ) || $per_page < 1 )
497 $per_page = $default;
498
499 /**
500 * Filter the number of items to be displayed on each page of the list table.
501 *
502 * The dynamic hook name, $option, refers to the per page option depending
503 * on the type of list table in use. Possible values may include:
504 * 'edit_comments_per_page', 'sites_network_per_page', 'site_themes_network_per_page',
505 * 'themes_netework_per_page', 'users_network_per_page', 'edit_{$post_type}', etc.
506 *
507 * @since 2.9.0
508 *
509 * @param int $per_page Number of items to be displayed. Default 20.
510 */
511 return (int) apply_filters( $option, $per_page );
512 }
513
514 /**
515 * Display the pagination.
516 *
517 * @since 3.1.0
518 * @access protected
519 */
520 function pagination( $which ) {
521 if ( empty( $this->_pagination_args ) )
522 return;
523
524 extract( $this->_pagination_args, EXTR_SKIP );
525
526 $output = '<span class="displaying-num">' . sprintf( _n( '1 item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . '</span>';
527
528 $current = $this->get_pagenum();
529
530 $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
531
532 $current_url = remove_query_arg( array( 'hotkeys_highlight_last', 'hotkeys_highlight_first' ), $current_url );
533
534 $page_links = array();
535
536 $disable_first = $disable_last = '';
537 if ( $current == 1 )
538 $disable_first = ' disabled';
539 if ( $current == $total_pages )
540 $disable_last = ' disabled';
541
542 $page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
543 'first-page' . $disable_first,
544 esc_attr__( 'Go to the first page' ),
545 esc_url( remove_query_arg( 'paged', $current_url ) ),
546 '&laquo;'
547 );
548
549 $page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
550 'prev-page' . $disable_first,
551 esc_attr__( 'Go to the previous page' ),
552 esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ),
553 '&lsaquo;'
554 );
555
556 if ( 'bottom' == $which )
557 $html_current_page = $current;
558 else
559 $html_current_page = sprintf( "<input class='current-page' title='%s' type='text' name='paged' value='%s' size='%d' />",
560 esc_attr__( 'Current page' ),
561 $current,
562 strlen( $total_pages )
563 );
564
565 $html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
566 $page_links[] = '<span class="paging-input">' . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . '</span>';
567
568 $page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
569 'next-page' . $disable_last,
570 esc_attr__( 'Go to the next page' ),
571 esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ),
572 '&rsaquo;'
573 );
574
575 $page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
576 'last-page' . $disable_last,
577 esc_attr__( 'Go to the last page' ),
578 esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
579 '&raquo;'
580 );
581
582 $pagination_links_class = 'pagination-links';
583 if ( ! empty( $infinite_scroll ) )
584 $pagination_links_class = ' hide-if-js';
585 $output .= "\n<span class='$pagination_links_class'>" . join( "\n", $page_links ) . '</span>';
586
587 if ( $total_pages )
588 $page_class = $total_pages < 2 ? ' one-page' : '';
589 else
590 $page_class = ' no-pages';
591
592 $this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";
593
594 echo $this->_pagination;
595 }
596
597 /**
598 * Get a list of columns. The format is:
599 * 'internal-name' => 'Title'
600 *
601 * @since 3.1.0
602 * @access protected
603 * @abstract
604 *
605 * @return array
606 */
607 function get_columns() {
608 die( 'function WP_List_Table::get_columns() must be over-ridden in a sub-class.' );
609 }
610
611 /**
612 * Get a list of sortable columns. The format is:
613 * 'internal-name' => 'orderby'
614 * or
615 * 'internal-name' => array( 'orderby', true )
616 *
617 * The second format will make the initial sorting order be descending
618 *
619 * @since 3.1.0
620 * @access protected
621 *
622 * @return array
623 */
624 function get_sortable_columns() {
625 return array();
626 }
627
628 /**
629 * Get a list of all, hidden and sortable columns, with filter applied
630 *
631 * @since 3.1.0
632 * @access protected
633 *
634 * @return array
635 */
636 function get_column_info() {
637 if ( isset( $this->_column_headers ) )
638 return $this->_column_headers;
639
640 $columns = get_column_headers( $this->screen );
641 $hidden = get_hidden_columns( $this->screen );
642
643 $sortable_columns = $this->get_sortable_columns();
644 /**
645 * Filter the list table sortable columns for a specific screen.
646 *
647 * The dynamic portion of the hook name, $this->screen->id, refers
648 * to the ID of the current screen, usually a string.
649 *
650 * @since 3.5.0
651 *
652 * @param array $sortable_columns An array of sortable columns.
653 */
654 $_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $sortable_columns );
655
656 $sortable = array();
657 foreach ( $_sortable as $id => $data ) {
658 if ( empty( $data ) )
659 continue;
660
661 $data = (array) $data;
662 if ( !isset( $data[1] ) )
663 $data[1] = false;
664
665 $sortable[$id] = $data;
666 }
667
668 $this->_column_headers = array( $columns, $hidden, $sortable );
669
670 return $this->_column_headers;
671 }
672
673 /**
674 * Return number of visible columns
675 *
676 * @since 3.1.0
677 * @access public
678 *
679 * @return int
680 */
681 function get_column_count() {
682 list ( $columns, $hidden ) = $this->get_column_info();
683 $hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) );
684 return count( $columns ) - count( $hidden );
685 }
686
687 /**
688 * Print column headers, accounting for hidden and sortable columns.
689 *
690 * @since 3.1.0
691 * @access protected
692 *
693 * @param bool $with_id Whether to set the id attribute or not
694 */
695 function print_column_headers( $with_id = true ) {
696 list( $columns, $hidden, $sortable ) = $this->get_column_info();
697
698 $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
699 $current_url = remove_query_arg( 'paged', $current_url );
700
701 if ( isset( $_GET['orderby'] ) )
702 $current_orderby = $_GET['orderby'];
703 else
704 $current_orderby = '';
705
706 if ( isset( $_GET['order'] ) && 'desc' == $_GET['order'] )
707 $current_order = 'desc';
708 else
709 $current_order = 'asc';
710
711 if ( ! empty( $columns['cb'] ) ) {
712 static $cb_counter = 1;
713 $columns['cb'] = '<label class="screen-reader-text" for="cb-select-all-' . $cb_counter . '">' . __( 'Select All' ) . '</label>'
714 . '<input id="cb-select-all-' . $cb_counter . '" type="checkbox" />';
715 $cb_counter++;
716 }
717
718 foreach ( $columns as $column_key => $column_display_name ) {
719 $class = array( 'manage-column', "column-$column_key" );
720
721 $style = '';
722 if ( in_array( $column_key, $hidden ) )
723 $style = 'display:none;';
724
725 $style = ' style="' . $style . '"';
726
727 if ( 'cb' == $column_key )
728 $class[] = 'check-column';
729 elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) )
730 $class[] = 'num';
731
732 if ( isset( $sortable[$column_key] ) ) {
733 list( $orderby, $desc_first ) = $sortable[$column_key];
734
735 if ( $current_orderby == $orderby ) {
736 $order = 'asc' == $current_order ? 'desc' : 'asc';
737 $class[] = 'sorted';
738 $class[] = $current_order;
739 } else {
740 $order = $desc_first ? 'desc' : 'asc';
741 $class[] = 'sortable';
742 $class[] = $desc_first ? 'asc' : 'desc';
743 }
744
745 $column_display_name = '<a href="' . esc_url( add_query_arg( compact( 'orderby', 'order' ), $current_url ) ) . '"><span>' . $column_display_name . '</span><span class="sorting-indicator"></span></a>';
746 }
747
748 $id = $with_id ? "id='$column_key'" : '';
749
750 if ( !empty( $class ) )
751 $class = "class='" . join( ' ', $class ) . "'";
752
753 echo "<th scope='col' $id $class $style>$column_display_name</th>";
754 }
755 }
756
757 /**
758 * Display the table
759 *
760 * @since 3.1.0
761 * @access public
762 */
763 function display() {
764 extract( $this->_args );
765
766 $this->display_tablenav( 'top' );
767
768 ?>
769 <table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>" cellspacing="0">
770 <thead>
771 <tr>
772 <?php $this->print_column_headers(); ?>
773 </tr>
774 </thead>
775
776 <tfoot>
777 <tr>
778 <?php $this->print_column_headers( false ); ?>
779 </tr>
780 </tfoot>
781
782 <tbody id="the-list"<?php if ( $singular ) echo " data-wp-lists='list:$singular'"; ?>>
783 <?php $this->display_rows_or_placeholder(); ?>
784 </tbody>
785 </table>
786 <?php
787 $this->display_tablenav( 'bottom' );
788 }
789
790 /**
791 * Get a list of CSS classes for the <table> tag
792 *
793 * @since 3.1.0
794 * @access protected
795 *
796 * @return array
797 */
798 function get_table_classes() {
799 return array( 'widefat', 'fixed', $this->_args['plural'] );
800 }
801
802 /**
803 * Generate the table navigation above or below the table
804 *
805 * @since 3.1.0
806 * @access protected
807 */
808 function display_tablenav( $which ) {
809 if ( 'top' == $which )
810 wp_nonce_field( 'bulk-' . $this->_args['plural'] );
811 ?>
812 <div class="tablenav <?php echo esc_attr( $which ); ?>">
813
814 <div class="alignleft actions bulkactions">
815 <?php $this->bulk_actions(); ?>
816 </div>
817 <?php
818 $this->extra_tablenav( $which );
819 $this->pagination( $which );
820 ?>
821
822 <br class="clear" />
823 </div>
824 <?php
825 }
826
827 /**
828 * Extra controls to be displayed between bulk actions and pagination
829 *
830 * @since 3.1.0
831 * @access protected
832 */
833 function extra_tablenav( $which ) {}
834
835 /**
836 * Generate the <tbody> part of the table
837 *
838 * @since 3.1.0
839 * @access protected
840 */
841 function display_rows_or_placeholder() {
842 if ( $this->has_items() ) {
843 $this->display_rows();
844 } else {
845 list( $columns, $hidden ) = $this->get_column_info();
846 echo '<tr class="no-items"><td class="colspanchange" colspan="' . $this->get_column_count() . '">';
847 $this->no_items();
848 echo '</td></tr>';
849 }
850 }
851
852 /**
853 * Generate the table rows
854 *
855 * @since 3.1.0
856 * @access protected
857 */
858 function display_rows() {
859 foreach ( $this->items as $item )
860 $this->single_row( $item );
861 }
862
863 /**
864 * Generates content for a single row of the table
865 *
866 * @since 3.1.0
867 * @access protected
868 *
869 * @param object $item The current item
870 */
871 function single_row( $item ) {
872 static $row_class = '';
873 $row_class = ( $row_class == '' ? ' class="alternate"' : '' );
874
875 echo '<tr' . $row_class . '>';
876 $this->single_row_columns( $item );
877 echo '</tr>';
878 }
879
880 /**
881 * Generates the columns for a single row of the table
882 *
883 * @since 3.1.0
884 * @access protected
885 *
886 * @param object $item The current item
887 */
888 function single_row_columns( $item ) {
889 list( $columns, $hidden ) = $this->get_column_info();
890
891 foreach ( $columns as $column_name => $column_display_name ) {
892 $class = "class='$column_name column-$column_name'";
893
894 $style = '';
895 if ( in_array( $column_name, $hidden ) )
896 $style = ' style="display:none;"';
897
898 $attributes = "$class$style";
899
900 if ( 'cb' == $column_name ) {
901 echo '<th scope="row" class="check-column">';
902 echo $this->column_cb( $item );
903 echo '</th>';
904 }
905 elseif ( method_exists( $this, 'column_' . $column_name ) ) {
906 echo "<td $attributes>";
907 echo call_user_func( array( $this, 'column_' . $column_name ), $item );
908 echo "</td>";
909 }
910 else {
911 echo "<td $attributes>";
912 echo $this->column_default( $item, $column_name );
913 echo "</td>";
914 }
915 }
916 }
917
918 /**
919 * Handle an incoming ajax request (called from admin-ajax.php)
920 *
921 * @since 3.1.0
922 * @access public
923 */
924 function ajax_response() {
925 $this->prepare_items();
926
927 extract( $this->_args );
928 extract( $this->_pagination_args, EXTR_SKIP );
929
930 ob_start();
931 if ( ! empty( $_REQUEST['no_placeholder'] ) )
932 $this->display_rows();
933 else
934 $this->display_rows_or_placeholder();
935
936 $rows = ob_get_clean();
937
938 $response = array( 'rows' => $rows );
939
940 if ( isset( $total_items ) )
941 $response['total_items_i18n'] = sprintf( _n( '1 item', '%s items', $total_items ), number_format_i18n( $total_items ) );
942
943 if ( isset( $total_pages ) ) {
944 $response['total_pages'] = $total_pages;
945 $response['total_pages_i18n'] = number_format_i18n( $total_pages );
946 }
947
948 die( json_encode( $response ) );
949 }
950
951 /**
952 * Send required variables to JavaScript land
953 *
954 * @access private
955 */
956 function _js_vars() {
957 $args = array(
958 'class' => get_class( $this ),
959 'screen' => array(
960 'id' => $this->screen->id,
961 'base' => $this->screen->base,
962 )
963 );
964
965 printf( "<script type='text/javascript'>list_args = %s;</script>\n", json_encode( $args ) );
966 }
967 }