PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 1.3
Advanced Ads – Ad Manager & AdSense v1.3
2.0.25 2.0.24 2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / admin / includes / class-list-table.php
advanced-ads / admin / includes Last commit date
class-ad-groups-list-table.php 11 years ago class-display-condition-callbacks.php 11 years ago class-list-table.php 12 years ago index.php 12 years ago
class-list-table.php
970 lines
1 <?php
2 /**
3 * Base class for displaying a list of items in an ajaxified HTML table.
4 *
5 * Derrived from WP_List_Table WordPress 3.9
6 * @link http://codex.wordpress.org/Class_Reference/WP_List_Table
7 *
8 * @package WordPress
9 * @subpackage List_Table
10 * @since 3.1.0
11 */
12
13 class AdvAds_List_Table {
14
15 /**
16 * The current list of items
17 *
18 * @since 3.1.0
19 * @var array
20 * @access protected
21 */
22 var $items;
23
24 /**
25 * Various information about the current table
26 *
27 * @since 3.1.0
28 * @var array
29 * @access private
30 */
31 var $_args;
32
33 /**
34 * Various information needed for displaying the pagination
35 *
36 * @since 3.1.0
37 * @var array
38 * @access private
39 */
40 var $_pagination_args = array();
41
42 /**
43 * The current screen
44 *
45 * @since 3.1.0
46 * @var object
47 * @access protected
48 */
49 var $screen;
50
51 /**
52 * Cached bulk actions
53 *
54 * @since 3.1.0
55 * @var array
56 * @access private
57 */
58 var $_actions;
59
60 /**
61 * Cached pagination output
62 *
63 * @since 3.1.0
64 * @var string
65 * @access private
66 */
67 var $_pagination;
68
69 /**
70 * Constructor. The child class should call this constructor from its own constructor
71 *
72 * @param array $args An associative array with information about the current table
73 * @access protected
74 */
75 function __construct( $args = array() ) {
76 $args = wp_parse_args( $args, array(
77 'plural' => '',
78 'singular' => '',
79 'ajax' => false,
80 'screen' => null,
81 ) );
82
83 $this->screen = convert_to_screen( $args['screen'] );
84
85 add_filter( "manage_{$this->screen->id}_columns", array( $this, 'get_columns' ), 0 );
86
87 if ( !$args['plural'] )
88 $args['plural'] = $this->screen->base;
89
90 $args['plural'] = sanitize_key( $args['plural'] );
91 $args['singular'] = sanitize_key( $args['singular'] );
92
93 $this->_args = $args;
94
95 if ( $args['ajax'] ) {
96 // wp_enqueue_script( 'list-table' );
97 add_action( 'admin_footer', array( $this, '_js_vars' ) );
98 }
99 }
100
101 /**
102 * Checks the current user's permissions
103 * @uses wp_die()
104 *
105 * @since 3.1.0
106 * @access public
107 * @abstract
108 */
109 function ajax_user_can() {
110 die( 'function WP_List_Table::ajax_user_can() must be over-ridden in a sub-class.' );
111 }
112
113 /**
114 * Prepares the list of items for displaying.
115 * @uses WP_List_Table::set_pagination_args()
116 *
117 * @since 3.1.0
118 * @access public
119 * @abstract
120 */
121 function prepare_items() {
122 die( 'function WP_List_Table::prepare_items() must be over-ridden in a sub-class.' );
123 }
124
125 /**
126 * An internal method that sets all the necessary pagination arguments
127 *
128 * @param array $args An associative array with information about the pagination
129 * @access protected
130 */
131 function set_pagination_args( $args ) {
132 $args = wp_parse_args( $args, array(
133 'total_items' => 0,
134 'total_pages' => 0,
135 'per_page' => 0,
136 ) );
137
138 if ( !$args['total_pages'] && $args['per_page'] > 0 )
139 $args['total_pages'] = ceil( $args['total_items'] / $args['per_page'] );
140
141 // redirect if page number is invalid and headers are not already sent
142 if ( ! headers_sent() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) && $args['total_pages'] > 0 && $this->get_pagenum() > $args['total_pages'] ) {
143 wp_redirect( add_query_arg( 'paged', $args['total_pages'] ) );
144 exit;
145 }
146
147 $this->_pagination_args = $args;
148 }
149
150 /**
151 * Access the pagination args
152 *
153 * @since 3.1.0
154 * @access public
155 *
156 * @param string $key
157 * @return array
158 */
159 function get_pagination_arg( $key ) {
160 if ( 'page' == $key )
161 return $this->get_pagenum();
162
163 if ( isset( $this->_pagination_args[$key] ) )
164 return $this->_pagination_args[$key];
165 }
166
167 /**
168 * Whether the table has items to display or not
169 *
170 * @since 3.1.0
171 * @access public
172 *
173 * @return bool
174 */
175 function has_items() {
176 return !empty( $this->items );
177 }
178
179 /**
180 * Message to be displayed when there are no items
181 *
182 * @since 3.1.0
183 * @access public
184 */
185 function no_items() {
186 _e( 'No items found.' );
187 }
188
189 /**
190 * Display the search box.
191 *
192 * @since 3.1.0
193 * @access public
194 *
195 * @param string $text The search button text
196 * @param string $input_id The search input id
197 */
198 function search_box( $text, $input_id ) {
199 if ( empty( $_REQUEST['s'] ) && !$this->has_items() )
200 return;
201
202 $input_id = $input_id . '-search-input';
203
204 if ( ! empty( $_REQUEST['orderby'] ) )
205 echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
206 if ( ! empty( $_REQUEST['order'] ) )
207 echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
208 if ( ! empty( $_REQUEST['post_mime_type'] ) )
209 echo '<input type="hidden" name="post_mime_type" value="' . esc_attr( $_REQUEST['post_mime_type'] ) . '" />';
210 if ( ! empty( $_REQUEST['detached'] ) )
211 echo '<input type="hidden" name="detached" value="' . esc_attr( $_REQUEST['detached'] ) . '" />';
212 ?>
213 <p class="search-box">
214 <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
215 <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>" />
216 <?php submit_button( $text, 'button', false, false, array('id' => 'search-submit') ); ?>
217 </p>
218 <?php
219 }
220
221 /**
222 * Get an associative array ( id => link ) with the list
223 * of views available on this table.
224 *
225 * @since 3.1.0
226 * @access protected
227 *
228 * @return array
229 */
230 function get_views() {
231 return array();
232 }
233
234 /**
235 * Display the list of views available on this table.
236 *
237 * @since 3.1.0
238 * @access public
239 */
240 function views() {
241 $views = $this->get_views();
242 /**
243 * Filter the list of available list table views.
244 *
245 * The dynamic portion of the hook name, $this->screen->id, refers
246 * to the ID of the current screen, usually a string.
247 *
248 * @since 3.5.0
249 *
250 * @param array $views An array of available list table views.
251 */
252 $views = apply_filters( "views_{$this->screen->id}", $views );
253
254 if ( empty( $views ) )
255 return;
256
257 echo "<ul class='subsubsub'>\n";
258 foreach ( $views as $class => $view ) {
259 $views[ $class ] = "\t<li class='$class'>$view";
260 }
261 echo implode( " |</li>\n", $views ) . "</li>\n";
262 echo "</ul>";
263 }
264
265 /**
266 * Get an associative array ( option_name => option_title ) with the list
267 * of bulk actions available on this table.
268 *
269 * @since 3.1.0
270 * @access protected
271 *
272 * @return array
273 */
274 function get_bulk_actions() {
275 return array();
276 }
277
278 /**
279 * Display the bulk actions dropdown.
280 *
281 * @since 3.1.0
282 * @access public
283 */
284 function bulk_actions() {
285 if ( is_null( $this->_actions ) ) {
286 $no_new_actions = $this->_actions = $this->get_bulk_actions();
287 /**
288 * Filter the list table Bulk Actions drop-down.
289 *
290 * The dynamic portion of the hook name, $this->screen->id, refers
291 * to the ID of the current screen, usually a string.
292 *
293 * This filter can currently only be used to remove bulk actions.
294 *
295 * @since 3.5.0
296 *
297 * @param array $actions An array of the available bulk actions.
298 */
299 $this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions );
300 $this->_actions = array_intersect_assoc( $this->_actions, $no_new_actions );
301 $two = '';
302 } else {
303 $two = '2';
304 }
305
306 if ( empty( $this->_actions ) )
307 return;
308
309 echo "<select name='action$two'>\n";
310 echo "<option value='-1' selected='selected'>" . __( 'Bulk Actions' ) . "</option>\n";
311
312 foreach ( $this->_actions as $name => $title ) {
313 $class = 'edit' == $name ? ' class="hide-if-no-js"' : '';
314
315 echo "\t<option value='$name'$class>$title</option>\n";
316 }
317
318 echo "</select>\n";
319
320 submit_button( __( 'Apply' ), 'action', false, false, array( 'id' => "doaction$two" ) );
321 echo "\n";
322 }
323
324 /**
325 * Get the current action selected from the bulk actions dropdown.
326 *
327 * @since 3.1.0
328 * @access public
329 *
330 * @return string|bool The action name or False if no action was selected
331 */
332 function current_action() {
333 if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] )
334 return $_REQUEST['action'];
335
336 if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] )
337 return $_REQUEST['action2'];
338
339 return false;
340 }
341
342 /**
343 * Generate row actions div
344 *
345 * @since 3.1.0
346 * @access protected
347 *
348 * @param array $actions The list of actions
349 * @param bool $always_visible Whether the actions should be always visible
350 * @return string
351 */
352 function row_actions( $actions, $always_visible = false ) {
353 $action_count = count( $actions );
354 $i = 0;
355
356 if ( !$action_count )
357 return '';
358
359 $out = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';
360 foreach ( $actions as $action => $link ) {
361 ++$i;
362 ( $i == $action_count ) ? $sep = '' : $sep = ' | ';
363 $out .= "<span class='$action'>$link$sep</span>";
364 }
365 $out .= '</div>';
366
367 return $out;
368 }
369
370 /**
371 * Display a monthly dropdown for filtering items
372 *
373 * @since 3.1.0
374 * @access protected
375 */
376 function months_dropdown( $post_type ) {
377 global $wpdb, $wp_locale;
378
379 $months = $wpdb->get_results( $wpdb->prepare( "
380 SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
381 FROM $wpdb->posts
382 WHERE post_type = %s
383 ORDER BY post_date DESC
384 ", $post_type ) );
385
386 /**
387 * Filter the 'Months' drop-down results.
388 *
389 * @since 3.7.0
390 *
391 * @param object $months The months drop-down query results.
392 * @param string $post_type The post type.
393 */
394 $months = apply_filters( 'months_dropdown_results', $months, $post_type );
395
396 $month_count = count( $months );
397
398 if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) )
399 return;
400
401 $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
402 ?>
403 <select name='m'>
404 <option<?php selected( $m, 0 ); ?> value='0'><?php _e( 'Show all dates' ); ?></option>
405 <?php
406 foreach ( $months as $arc_row ) {
407 if ( 0 == $arc_row->year )
408 continue;
409
410 $month = zeroise( $arc_row->month, 2 );
411 $year = $arc_row->year;
412
413 printf( "<option %s value='%s'>%s</option>\n",
414 selected( $m, $year . $month, false ),
415 esc_attr( $arc_row->year . $month ),
416 /* translators: 1: month name, 2: 4-digit year */
417 sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year )
418 );
419 }
420 ?>
421 </select>
422 <?php
423 }
424
425 /**
426 * Display a view switcher
427 *
428 * @since 3.1.0
429 * @access protected
430 */
431 function view_switcher( $current_mode ) {
432 $modes = array(
433 'list' => __( 'List View' ),
434 'excerpt' => __( 'Excerpt View' )
435 );
436
437 ?>
438 <input type="hidden" name="mode" value="<?php echo esc_attr( $current_mode ); ?>" />
439 <div class="view-switch">
440 <?php
441 foreach ( $modes as $mode => $title ) {
442 $class = ( $current_mode == $mode ) ? 'class="current"' : '';
443 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";
444 }
445 ?>
446 </div>
447 <?php
448 }
449
450 /**
451 * Display a comment count bubble
452 *
453 * @since 3.1.0
454 * @access protected
455 *
456 * @param int $post_id
457 * @param int $pending_comments
458 */
459 function comments_bubble( $post_id, $pending_comments ) {
460 $pending_phrase = sprintf( __( '%s pending' ), number_format( $pending_comments ) );
461
462 if ( $pending_comments )
463 echo '<strong>';
464
465 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>";
466
467 if ( $pending_comments )
468 echo '</strong>';
469 }
470
471 /**
472 * Get the current page number
473 *
474 * @since 3.1.0
475 * @access protected
476 *
477 * @return int
478 */
479 function get_pagenum() {
480 $pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0;
481
482 if( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] )
483 $pagenum = $this->_pagination_args['total_pages'];
484
485 return max( 1, $pagenum );
486 }
487
488 /**
489 * Get number of items to display on a single page
490 *
491 * @since 3.1.0
492 * @access protected
493 *
494 * @return int
495 */
496 function get_items_per_page( $option, $default = 20 ) {
497 $per_page = (int) get_user_option( $option );
498 if ( empty( $per_page ) || $per_page < 1 )
499 $per_page = $default;
500
501 /**
502 * Filter the number of items to be displayed on each page of the list table.
503 *
504 * The dynamic hook name, $option, refers to the per page option depending
505 * on the type of list table in use. Possible values may include:
506 * 'edit_comments_per_page', 'sites_network_per_page', 'site_themes_network_per_page',
507 * 'themes_netework_per_page', 'users_network_per_page', 'edit_{$post_type}', etc.
508 *
509 * @since 2.9.0
510 *
511 * @param int $per_page Number of items to be displayed. Default 20.
512 */
513 return (int) apply_filters( $option, $per_page );
514 }
515
516 /**
517 * Display the pagination.
518 *
519 * @since 3.1.0
520 * @access protected
521 */
522 function pagination( $which ) {
523 if ( empty( $this->_pagination_args ) )
524 return;
525
526 extract( $this->_pagination_args, EXTR_SKIP );
527
528 $output = '<span class="displaying-num">' . sprintf( _n( '1 item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . '</span>';
529
530 $current = $this->get_pagenum();
531
532 $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
533
534 $current_url = remove_query_arg( array( 'hotkeys_highlight_last', 'hotkeys_highlight_first' ), $current_url );
535
536 $page_links = array();
537
538 $disable_first = $disable_last = '';
539 if ( $current == 1 )
540 $disable_first = ' disabled';
541 if ( $current == $total_pages )
542 $disable_last = ' disabled';
543
544 $page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
545 'first-page' . $disable_first,
546 esc_attr__( 'Go to the first page' ),
547 esc_url( remove_query_arg( 'paged', $current_url ) ),
548 '&laquo;'
549 );
550
551 $page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
552 'prev-page' . $disable_first,
553 esc_attr__( 'Go to the previous page' ),
554 esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ),
555 '&lsaquo;'
556 );
557
558 if ( 'bottom' == $which )
559 $html_current_page = $current;
560 else
561 $html_current_page = sprintf( "<input class='current-page' title='%s' type='text' name='paged' value='%s' size='%d' />",
562 esc_attr__( 'Current page' ),
563 $current,
564 strlen( $total_pages )
565 );
566
567 $html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
568 $page_links[] = '<span class="paging-input">' . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . '</span>';
569
570 $page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
571 'next-page' . $disable_last,
572 esc_attr__( 'Go to the next page' ),
573 esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ),
574 '&rsaquo;'
575 );
576
577 $page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
578 'last-page' . $disable_last,
579 esc_attr__( 'Go to the last page' ),
580 esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
581 '&raquo;'
582 );
583
584 $pagination_links_class = 'pagination-links';
585 if ( ! empty( $infinite_scroll ) )
586 $pagination_links_class = ' hide-if-js';
587 $output .= "\n<span class='$pagination_links_class'>" . join( "\n", $page_links ) . '</span>';
588
589 if ( $total_pages )
590 $page_class = $total_pages < 2 ? ' one-page' : '';
591 else
592 $page_class = ' no-pages';
593
594 $this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";
595
596 echo $this->_pagination;
597 }
598
599 /**
600 * Get a list of columns. The format is:
601 * 'internal-name' => 'Title'
602 *
603 * @since 3.1.0
604 * @access protected
605 * @abstract
606 *
607 * @return array
608 */
609 function get_columns() {
610 die( 'function WP_List_Table::get_columns() must be over-ridden in a sub-class.' );
611 }
612
613 /**
614 * Get a list of sortable columns. The format is:
615 * 'internal-name' => 'orderby'
616 * or
617 * 'internal-name' => array( 'orderby', true )
618 *
619 * The second format will make the initial sorting order be descending
620 *
621 * @since 3.1.0
622 * @access protected
623 *
624 * @return array
625 */
626 function get_sortable_columns() {
627 return array();
628 }
629
630 /**
631 * Get a list of all, hidden and sortable columns, with filter applied
632 *
633 * @since 3.1.0
634 * @access protected
635 *
636 * @return array
637 */
638 function get_column_info() {
639 if ( isset( $this->_column_headers ) )
640 return $this->_column_headers;
641
642 $columns = get_column_headers( $this->screen );
643 $hidden = get_hidden_columns( $this->screen );
644
645 $sortable_columns = $this->get_sortable_columns();
646 /**
647 * Filter the list table sortable columns for a specific screen.
648 *
649 * The dynamic portion of the hook name, $this->screen->id, refers
650 * to the ID of the current screen, usually a string.
651 *
652 * @since 3.5.0
653 *
654 * @param array $sortable_columns An array of sortable columns.
655 */
656 $_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $sortable_columns );
657
658 $sortable = array();
659 foreach ( $_sortable as $id => $data ) {
660 if ( empty( $data ) )
661 continue;
662
663 $data = (array) $data;
664 if ( !isset( $data[1] ) )
665 $data[1] = false;
666
667 $sortable[$id] = $data;
668 }
669
670 $this->_column_headers = array( $columns, $hidden, $sortable );
671
672 return $this->_column_headers;
673 }
674
675 /**
676 * Return number of visible columns
677 *
678 * @since 3.1.0
679 * @access public
680 *
681 * @return int
682 */
683 function get_column_count() {
684 list ( $columns, $hidden ) = $this->get_column_info();
685 $hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) );
686 return count( $columns ) - count( $hidden );
687 }
688
689 /**
690 * Print column headers, accounting for hidden and sortable columns.
691 *
692 * @since 3.1.0
693 * @access protected
694 *
695 * @param bool $with_id Whether to set the id attribute or not
696 */
697 function print_column_headers( $with_id = true ) {
698 list( $columns, $hidden, $sortable ) = $this->get_column_info();
699
700 $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
701 $current_url = remove_query_arg( 'paged', $current_url );
702
703 if ( isset( $_GET['orderby'] ) )
704 $current_orderby = $_GET['orderby'];
705 else
706 $current_orderby = '';
707
708 if ( isset( $_GET['order'] ) && 'desc' == $_GET['order'] )
709 $current_order = 'desc';
710 else
711 $current_order = 'asc';
712
713 if ( ! empty( $columns['cb'] ) ) {
714 static $cb_counter = 1;
715 $columns['cb'] = '<label class="screen-reader-text" for="cb-select-all-' . $cb_counter . '">' . __( 'Select All' ) . '</label>'
716 . '<input id="cb-select-all-' . $cb_counter . '" type="checkbox" />';
717 $cb_counter++;
718 }
719
720 foreach ( $columns as $column_key => $column_display_name ) {
721 $class = array( 'manage-column', "column-$column_key" );
722
723 $style = '';
724 if ( in_array( $column_key, $hidden ) )
725 $style = 'display:none;';
726
727 $style = ' style="' . $style . '"';
728
729 if ( 'cb' == $column_key )
730 $class[] = 'check-column';
731 elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) )
732 $class[] = 'num';
733
734 if ( isset( $sortable[$column_key] ) ) {
735 list( $orderby, $desc_first ) = $sortable[$column_key];
736
737 if ( $current_orderby == $orderby ) {
738 $order = 'asc' == $current_order ? 'desc' : 'asc';
739 $class[] = 'sorted';
740 $class[] = $current_order;
741 } else {
742 $order = $desc_first ? 'desc' : 'asc';
743 $class[] = 'sortable';
744 $class[] = $desc_first ? 'asc' : 'desc';
745 }
746
747 $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>';
748 }
749
750 $id = $with_id ? "id='$column_key'" : '';
751
752 if ( !empty( $class ) )
753 $class = "class='" . join( ' ', $class ) . "'";
754
755 echo "<th scope='col' $id $class $style>$column_display_name</th>";
756 }
757 }
758
759 /**
760 * Display the table
761 *
762 * @since 3.1.0
763 * @access public
764 */
765 function display() {
766 extract( $this->_args );
767
768 $this->display_tablenav( 'top' );
769
770 ?>
771 <table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>" cellspacing="0">
772 <thead>
773 <tr>
774 <?php $this->print_column_headers(); ?>
775 </tr>
776 </thead>
777
778 <tfoot>
779 <tr>
780 <?php $this->print_column_headers( false ); ?>
781 </tr>
782 </tfoot>
783
784 <tbody id="the-list"<?php if ( $singular ) echo " data-wp-lists='list:$singular'"; ?>>
785 <?php $this->display_rows_or_placeholder(); ?>
786 </tbody>
787 </table>
788 <?php
789 $this->display_tablenav( 'bottom' );
790 }
791
792 /**
793 * Get a list of CSS classes for the <table> tag
794 *
795 * @since 3.1.0
796 * @access protected
797 *
798 * @return array
799 */
800 function get_table_classes() {
801 return array( 'widefat', 'fixed', $this->_args['plural'] );
802 }
803
804 /**
805 * Generate the table navigation above or below the table
806 *
807 * @since 3.1.0
808 * @access protected
809 */
810 function display_tablenav( $which ) {
811 if ( 'top' == $which )
812 wp_nonce_field( 'bulk-' . $this->_args['plural'] );
813 ?>
814 <div class="tablenav <?php echo esc_attr( $which ); ?>">
815
816 <div class="alignleft actions bulkactions">
817 <?php $this->bulk_actions(); ?>
818 </div>
819 <?php
820 $this->extra_tablenav( $which );
821 $this->pagination( $which );
822 ?>
823
824 <br class="clear" />
825 </div>
826 <?php
827 }
828
829 /**
830 * Extra controls to be displayed between bulk actions and pagination
831 *
832 * @since 3.1.0
833 * @access protected
834 */
835 function extra_tablenav( $which ) {}
836
837 /**
838 * Generate the <tbody> part of the table
839 *
840 * @since 3.1.0
841 * @access protected
842 */
843 function display_rows_or_placeholder() {
844 if ( $this->has_items() ) {
845 $this->display_rows();
846 } else {
847 list( $columns, $hidden ) = $this->get_column_info();
848 echo '<tr class="no-items"><td class="colspanchange" colspan="' . $this->get_column_count() . '">';
849 $this->no_items();
850 echo '</td></tr>';
851 }
852 }
853
854 /**
855 * Generate the table rows
856 *
857 * @since 3.1.0
858 * @access protected
859 */
860 function display_rows() {
861 foreach ( $this->items as $item )
862 $this->single_row( $item );
863 }
864
865 /**
866 * Generates content for a single row of the table
867 *
868 * @since 3.1.0
869 * @access protected
870 *
871 * @param object $item The current item
872 */
873 function single_row( $item ) {
874 static $row_class = '';
875 $row_class = ( $row_class == '' ? ' class="alternate"' : '' );
876
877 echo '<tr' . $row_class . '>';
878 $this->single_row_columns( $item );
879 echo '</tr>';
880 }
881
882 /**
883 * Generates the columns for a single row of the table
884 *
885 * @since 3.1.0
886 * @access protected
887 *
888 * @param object $item The current item
889 */
890 function single_row_columns( $item ) {
891 list( $columns, $hidden ) = $this->get_column_info();
892
893 foreach ( $columns as $column_name => $column_display_name ) {
894 $class = "class='$column_name column-$column_name'";
895
896 $style = '';
897 if ( in_array( $column_name, $hidden ) )
898 $style = ' style="display:none;"';
899
900 $attributes = "$class$style";
901
902 if ( 'cb' == $column_name ) {
903 echo '<th scope="row" class="check-column">';
904 echo $this->column_cb( $item );
905 echo '</th>';
906 }
907 elseif ( method_exists( $this, 'column_' . $column_name ) ) {
908 echo "<td $attributes>";
909 echo call_user_func( array( $this, 'column_' . $column_name ), $item );
910 echo "</td>";
911 }
912 else {
913 echo "<td $attributes>";
914 echo $this->column_default( $item, $column_name );
915 echo "</td>";
916 }
917 }
918 }
919
920 /**
921 * Handle an incoming ajax request (called from admin-ajax.php)
922 *
923 * @since 3.1.0
924 * @access public
925 */
926 function ajax_response() {
927 $this->prepare_items();
928
929 extract( $this->_args );
930 extract( $this->_pagination_args, EXTR_SKIP );
931
932 ob_start();
933 if ( ! empty( $_REQUEST['no_placeholder'] ) )
934 $this->display_rows();
935 else
936 $this->display_rows_or_placeholder();
937
938 $rows = ob_get_clean();
939
940 $response = array( 'rows' => $rows );
941
942 if ( isset( $total_items ) )
943 $response['total_items_i18n'] = sprintf( _n( '1 item', '%s items', $total_items ), number_format_i18n( $total_items ) );
944
945 if ( isset( $total_pages ) ) {
946 $response['total_pages'] = $total_pages;
947 $response['total_pages_i18n'] = number_format_i18n( $total_pages );
948 }
949
950 die( json_encode( $response ) );
951 }
952
953 /**
954 * Send required variables to JavaScript land
955 *
956 * @access private
957 */
958 function _js_vars() {
959 $args = array(
960 'class' => get_class( $this ),
961 'screen' => array(
962 'id' => $this->screen->id,
963 'base' => $this->screen->base,
964 )
965 );
966
967 printf( "<script type='text/javascript'>list_args = %s;</script>\n", json_encode( $args ) );
968 }
969 }
970