PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 1.8.1
Tutor LMS – eLearning and online course solution v1.8.1
3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 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.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.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / classes / Tutor_List_Table.php
tutor / classes Last commit date
Addons.php 5 years ago Admin.php 5 years ago Ajax.php 5 years ago Assets.php 5 years ago Course.php 5 years ago Course_Filter.php 5 years ago Course_Settings_Tabs.php 5 years ago Course_Widget.php 5 years ago Custom_Validation.php 5 years ago Dashboard.php 5 years ago Delete_Enrollment_With_Order.php 5 years ago Email.php 5 years ago FormHandler.php 5 years ago Frontend.php 5 years ago Gutenberg.php 5 years ago Instructor.php 5 years ago Instructors_List.php 5 years ago Lesson.php 5 years ago Options.php 5 years ago Post_types.php 5 years ago Private_Course_Access.php 5 years ago Q_and_A.php 5 years ago Question_Answers_List.php 5 years ago Quiz.php 5 years ago Quiz_Attempts_List.php 5 years ago RestAPI.php 5 years ago Rewrite_Rules.php 5 years ago Shortcode.php 5 years ago Student.php 5 years ago Students_List.php 5 years ago Taxonomies.php 5 years ago Template.php 5 years ago Theme_Compatibility.php 5 years ago Tools.php 5 years ago Tutor.php 5 years ago TutorEDD.php 5 years ago Tutor_Base.php 5 years ago Tutor_List_Table.php 5 years ago Tutor_Setup.php 5 years ago Upgrader.php 5 years ago User.php 5 years ago Utils.php 5 years ago Video_Stream.php 5 years ago Withdraw.php 5 years ago Withdraw_Requests_List.php 5 years ago WooCommerce.php 5 years ago
Tutor_List_Table.php
1392 lines
1 <?php
2 /**
3 * Created by PhpStorm.
4 * User: themeum
5 * Date: 24/9/18
6 * Time: 12:03 PM
7 */
8
9
10 if ( ! defined( 'ABSPATH' ) )
11 exit;
12
13 /**
14 * Base class for displaying a list of items in an ajaxified HTML table.
15 *
16 * @since 3.1.0
17 * @access private
18 */
19 class Tutor_List_Table {
20
21 /**
22 * The current list of items.
23 *
24 * @since 3.1.0
25 * @var array
26 */
27 public $items;
28
29 /**
30 * Various information about the current table.
31 *
32 * @since 3.1.0
33 * @var array
34 */
35 protected $_args;
36
37 /**
38 * Various information needed for displaying the pagination.
39 *
40 * @since 3.1.0
41 * @var array
42 */
43 protected $_pagination_args = array();
44
45 /**
46 * The current screen.
47 *
48 * @since 3.1.0
49 * @var object
50 */
51 protected $screen;
52
53 /**
54 * Cached bulk actions.
55 *
56 * @since 3.1.0
57 * @var array
58 */
59 private $_actions;
60
61 /**
62 * Cached pagination output.
63 *
64 * @since 3.1.0
65 * @var string
66 */
67 private $_pagination;
68
69 /**
70 * The view switcher modes.
71 *
72 * @since 4.1.0
73 * @var array
74 */
75 protected $modes = array();
76
77 /**
78 * Stores the value returned by ->get_column_info().
79 *
80 * @since 4.1.0
81 * @var array
82 */
83 protected $_column_headers;
84
85 /**
86 * {@internal Missing Summary}
87 *
88 * @var array
89 */
90 protected $compat_fields = array( '_args', '_pagination_args', 'screen', '_actions', '_pagination' );
91
92 /**
93 * {@internal Missing Summary}
94 *
95 * @var array
96 */
97 protected $compat_methods = array( 'set_pagination_args', 'get_views', 'get_bulk_actions', 'bulk_actions',
98 'row_actions', 'months_dropdown', 'view_switcher', 'comments_bubble', 'get_items_per_page', 'pagination',
99 'get_sortable_columns', 'get_column_info', 'get_table_classes', 'display_tablenav', 'extra_tablenav',
100 'single_row_columns' );
101
102 /**
103 * Constructor.
104 *
105 * The child class should call this constructor from its own constructor to override
106 * the default $args.
107 *
108 * @since 3.1.0
109 *
110 * @param array|string $args {
111 * Array or string of arguments.
112 *
113 * @type string $plural Plural value used for labels and the objects being listed.
114 * This affects things such as CSS class-names and nonces used
115 * in the list table, e.g. 'posts'. Default empty.
116 * @type string $singular Singular label for an object being listed, e.g. 'post'.
117 * Default empty
118 * @type bool $ajax Whether the list table supports Ajax. This includes loading
119 * and sorting data, for example. If true, the class will call
120 * the _js_vars() method in the footer to provide variables
121 * to any scripts handling Ajax events. Default false.
122 * @type string $screen String containing the hook name used to determine the current
123 * screen. If left null, the current screen will be automatically set.
124 * Default null.
125 * }
126 */
127 public function __construct( $args = array() ) {
128 $args = wp_parse_args( $args, array(
129 'plural' => '',
130 'singular' => '',
131 'ajax' => false,
132 'screen' => null,
133 ) );
134
135 $this->screen = convert_to_screen( $args['screen'] );
136
137 add_filter( "manage_{$this->screen->id}_columns", array( $this, 'get_columns' ), 0 );
138
139 if ( !$args['plural'] )
140 $args['plural'] = $this->screen->base;
141
142 $args['plural'] = sanitize_key( $args['plural'] );
143 $args['singular'] = sanitize_key( $args['singular'] );
144
145 $this->_args = $args;
146
147 if ( $args['ajax'] ) {
148 // wp_enqueue_script( 'list-table' );
149 add_action( 'admin_footer', array( $this, '_js_vars' ) );
150 }
151
152 if ( empty( $this->modes ) ) {
153 $this->modes = array(
154 'list' => __( 'List View' ),
155 'excerpt' => __( 'Excerpt View' )
156 );
157 }
158 }
159
160 /**
161 * Make private properties readable for backward compatibility.
162 *
163 * @since 4.0.0
164 *
165 * @param string $name Property to get.
166 * @return mixed Property.
167 */
168 public function __get( $name ) {
169 if ( in_array( $name, $this->compat_fields ) ) {
170 return $this->$name;
171 }
172 }
173
174 /**
175 * Make private properties settable for backward compatibility.
176 *
177 * @since 4.0.0
178 *
179 * @param string $name Property to check if set.
180 * @param mixed $value Property value.
181 * @return mixed Newly-set property.
182 */
183 public function __set( $name, $value ) {
184 if ( in_array( $name, $this->compat_fields ) ) {
185 return $this->$name = $value;
186 }
187 }
188
189 /**
190 * Make private properties checkable for backward compatibility.
191 *
192 * @since 4.0.0
193 *
194 * @param string $name Property to check if set.
195 * @return bool Whether the property is set.
196 */
197 public function __isset( $name ) {
198 if ( in_array( $name, $this->compat_fields ) ) {
199 return isset( $this->$name );
200 }
201 }
202
203 /**
204 * Make private properties un-settable for backward compatibility.
205 *
206 * @since 4.0.0
207 *
208 * @param string $name Property to unset.
209 */
210 public function __unset( $name ) {
211 if ( in_array( $name, $this->compat_fields ) ) {
212 unset( $this->$name );
213 }
214 }
215
216 /**
217 * Make private/protected methods readable for backward compatibility.
218 *
219 * @since 4.0.0
220 *
221 * @param callable $name Method to call.
222 * @param array $arguments Arguments to pass when calling.
223 * @return mixed|bool Return value of the callback, false otherwise.
224 */
225 public function __call( $name, $arguments ) {
226 if ( in_array( $name, $this->compat_methods ) ) {
227 return call_user_func_array( array( $this, $name ), $arguments );
228 }
229 return false;
230 }
231
232 /**
233 * Checks the current user's permissions
234 *
235 * @since 3.1.0
236 * @abstract
237 */
238 public function ajax_user_can() {
239 die( 'function Tutor_List_Table::ajax_user_can() must be over-ridden in a sub-class.' );
240 }
241
242 /**
243 * Prepares the list of items for displaying.
244 * @uses Tutor_List_Table::set_pagination_args()
245 *
246 * @since 3.1.0
247 * @abstract
248 */
249 public function prepare_items() {
250 die( 'function Tutor_List_Table::prepare_items() must be over-ridden in a sub-class.' );
251 }
252
253 /**
254 * An internal method that sets all the necessary pagination arguments
255 *
256 * @since 3.1.0
257 *
258 * @param array|string $args Array or string of arguments with information about the pagination.
259 */
260 protected function set_pagination_args( $args ) {
261 $args = wp_parse_args( $args, array(
262 'total_items' => 0,
263 'total_pages' => 0,
264 'per_page' => 0,
265 ) );
266
267 if ( !$args['total_pages'] && $args['per_page'] > 0 )
268 $args['total_pages'] = ceil( $args['total_items'] / $args['per_page'] );
269
270 // Redirect if page number is invalid and headers are not already sent.
271 if ( ! headers_sent() && ! wp_doing_ajax() && $args['total_pages'] > 0 && $this->get_pagenum() > $args['total_pages'] ) {
272 wp_redirect( add_query_arg( 'paged', $args['total_pages'] ) );
273 exit;
274 }
275
276 $this->_pagination_args = $args;
277 }
278
279 /**
280 * Access the pagination args.
281 *
282 * @since 3.1.0
283 *
284 * @param string $key Pagination argument to retrieve. Common values include 'total_items',
285 * 'total_pages', 'per_page', or 'infinite_scroll'.
286 * @return int Number of items that correspond to the given pagination argument.
287 */
288 public function get_pagination_arg( $key ) {
289 if ( 'page' === $key ) {
290 return $this->get_pagenum();
291 }
292
293 if ( isset( $this->_pagination_args[$key] ) ) {
294 return $this->_pagination_args[$key];
295 }
296 }
297
298 /**
299 * Whether the table has items to display or not
300 *
301 * @since 3.1.0
302 *
303 * @return bool
304 */
305 public function has_items() {
306 return !empty( $this->items );
307 }
308
309 /**
310 * Message to be displayed when there are no items
311 *
312 * @since 3.1.0
313 */
314 public function no_items() {
315 _e( 'No items found.' );
316 }
317
318 /**
319 * Displays the search box.
320 *
321 * @since 3.1.0
322 *
323 * @param string $text The 'submit' button label.
324 * @param string $input_id ID attribute value for the search input field.
325 */
326 public function search_box( $text, $input_id ) {
327 if ( empty( $_REQUEST['s'] ) && !$this->has_items() )
328 return;
329
330 $input_id = $input_id . '-search-input';
331
332 if ( ! empty( $_REQUEST['orderby'] ) )
333 echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
334 if ( ! empty( $_REQUEST['order'] ) )
335 echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
336 if ( ! empty( $_REQUEST['post_mime_type'] ) )
337 echo '<input type="hidden" name="post_mime_type" value="' . esc_attr( $_REQUEST['post_mime_type'] ) . '" />';
338 if ( ! empty( $_REQUEST['detached'] ) )
339 echo '<input type="hidden" name="detached" value="' . esc_attr( $_REQUEST['detached'] ) . '" />';
340 ?>
341 <p class="search-box">
342 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo $text; ?>:</label>
343 <input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>" />
344 <?php submit_button( $text, '', '', false, array( 'id' => 'search-submit' ) ); ?>
345 </p>
346 <?php
347 }
348
349 /**
350 * @since 1.8.0
351 * get course list
352 * @param $selected | optional
353 */
354 public function course_dropdown($selected = ''){
355 $courses = (current_user_can('administrator')) ? tutils()->get_courses() : tutils()->get_courses_by_instructor();
356 $markup = '
357 <div class="alignright">
358 <label>'.__('Course', 'tutor-pro').'</label>
359 <select class="tutor-assignment-course-sorting">
360 <option value="0">'.__('All','tutor').'</option>
361 OPTIONS_PLACEHOLDER
362 </select>
363 </div>
364 ';
365 $options = '';
366 foreach($courses as $course){
367 $options .= '<option value="'.$course->ID.'" '.selected($selected,$course->ID,false).'> '.$course->post_title.' </option>';
368 }
369
370 $content = str_replace('OPTIONS_PLACEHOLDER', $options, $markup);
371 echo $content;
372 }
373
374 /**
375 * @since 1.8.0
376 * get sort by param
377 * @param $selected | optional
378 */
379
380 public function sorting_order($selected='DESC'){
381 $orders = ['DESC','ASC'];
382 $markup = '
383 <div class="alignright">
384 <label>'.__('Sort By', 'tutor').'</label>
385 <select class="tutor-assignment-order-sorting">
386 OPTION_PLACEHOLDER
387 </select>
388 </div>
389 ';
390 $options = '';
391 foreach($orders as $order){
392 $options .= '<option value="'.$order.'" '.selected($selected,$order,false).'> '.$order.' </option>';
393 }
394 $content = str_replace('OPTION_PLACEHOLDER', $options, $markup);
395 echo $content;
396 }
397 /**
398 * @since 1.8.0
399 * get sort by param
400 * @param $selected | optional
401 */
402
403 public function sorting_date($selected = ''){
404 $markup = '
405 <div class="alignright assignment-date-box">
406 <label>'.__('Date', 'tutor').'</label>
407 <input type="" id="tutor_assignment_calender" class=" tutor-assignment-date-sorting" value="'.$selected.'">
408 <i class="tutor-icon-calendar"></i>
409 </div>
410 ';
411 echo $markup;
412 }
413
414 /**
415 * Get an associative array ( id => link ) with the list
416 * of views available on this table.
417 *
418 * @since 3.1.0
419 *
420 * @return array
421 */
422 protected function get_views() {
423 return array();
424 }
425
426 /**
427 * Display the list of views available on this table.
428 *
429 * @since 3.1.0
430 */
431 public function views() {
432 $views = $this->get_views();
433 /**
434 * Filters the list of available list table views.
435 *
436 * The dynamic portion of the hook name, `$this->screen->id`, refers
437 * to the ID of the current screen, usually a string.
438 *
439 * @since 3.5.0
440 *
441 * @param array $views An array of available list table views.
442 */
443 $views = apply_filters( "views_{$this->screen->id}", $views );
444
445 if ( empty( $views ) )
446 return;
447
448 $this->screen->render_screen_reader_content( 'heading_views' );
449
450 echo "<ul class='subsubsub'>\n";
451 foreach ( $views as $class => $view ) {
452 $views[ $class ] = "\t<li class='$class'>$view";
453 }
454 echo implode( " |</li>\n", $views ) . "</li>\n";
455 echo "</ul>";
456 }
457
458 /**
459 * Get an associative array ( option_name => option_title ) with the list
460 * of bulk actions available on this table.
461 *
462 * @since 3.1.0
463 *
464 * @return array
465 */
466 protected function get_bulk_actions() {
467 return array();
468 }
469
470 /**
471 * Display the bulk actions dropdown.
472 *
473 * @since 3.1.0
474 *
475 * @param string $which The location of the bulk actions: 'top' or 'bottom'.
476 * This is designated as optional for backward compatibility.
477 */
478 protected function bulk_actions( $which = '' ) {
479 if ( is_null( $this->_actions ) ) {
480 $this->_actions = $this->get_bulk_actions();
481 /**
482 * Filters the list table Bulk Actions drop-down.
483 *
484 * The dynamic portion of the hook name, `$this->screen->id`, refers
485 * to the ID of the current screen, usually a string.
486 *
487 * This filter can currently only be used to remove bulk actions.
488 *
489 * @since 3.5.0
490 *
491 * @param array $actions An array of the available bulk actions.
492 */
493 $this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions );
494 $two = '';
495 } else {
496 $two = '2';
497 }
498
499 if ( empty( $this->_actions ) )
500 return;
501
502 echo '<label for="bulk-action-selector-' . esc_attr( $which ) . '" class="screen-reader-text">' . __( 'Select bulk action' ) . '</label>';
503 echo '<select name="action' . $two . '" id="bulk-action-selector-' . esc_attr( $which ) . "\">\n";
504 echo '<option value="-1">' . __( 'Bulk Actions', 'tutor' ) . "</option>\n";
505
506 foreach ( $this->_actions as $name => $title ) {
507 $class = 'edit' === $name ? ' class="hide-if-no-js"' : '';
508
509 echo "\t" . '<option value="' . $name . '"' . $class . '>' . $title . "</option>\n";
510 }
511
512 echo "</select>\n";
513
514 submit_button( __( 'Apply' ), 'action', '', false, array( 'id' => "doaction$two" ) );
515 echo "\n";
516 }
517
518 /**
519 * Get the current action selected from the bulk actions dropdown.
520 *
521 * @since 3.1.0
522 *
523 * @return string|false The action name or False if no action was selected
524 */
525 public function current_action() {
526 if ( isset( $_REQUEST['filter_action'] ) && ! empty( $_REQUEST['filter_action'] ) )
527 return false;
528
529 if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] )
530 return $_REQUEST['action'];
531
532 if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] )
533 return $_REQUEST['action2'];
534
535 return false;
536 }
537
538 /**
539 * Generate row actions div
540 *
541 * @since 3.1.0
542 *
543 * @param array $actions The list of actions
544 * @param bool $always_visible Whether the actions should be always visible
545 * @return string
546 */
547 protected function row_actions( $actions, $always_visible = false ) {
548 $action_count = count( $actions );
549 $i = 0;
550
551 if ( !$action_count )
552 return '';
553
554 $out = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';
555 foreach ( $actions as $action => $link ) {
556 ++$i;
557 ( $i == $action_count ) ? $sep = '' : $sep = ' | ';
558 $out .= "<span class='$action'>$link$sep</span>";
559 }
560 $out .= '</div>';
561
562 $out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>';
563
564 return $out;
565 }
566
567 /**
568 * Display a monthly dropdown for filtering items
569 *
570 * @since 3.1.0
571 *
572 * @global wpdb $wpdb
573 * @global WP_Locale $wp_locale
574 *
575 * @param string $post_type
576 */
577 protected function months_dropdown( $post_type ) {
578 global $wpdb, $wp_locale;
579
580 /**
581 * Filters whether to remove the 'Months' drop-down from the post list table.
582 *
583 * @since 4.2.0
584 *
585 * @param bool $disable Whether to disable the drop-down. Default false.
586 * @param string $post_type The post type.
587 */
588 if ( apply_filters( 'disable_months_dropdown', false, $post_type ) ) {
589 return;
590 }
591
592 $extra_checks = "AND post_status != 'auto-draft'";
593 if ( ! isset( $_GET['post_status'] ) || 'trash' !== $_GET['post_status'] ) {
594 $extra_checks .= " AND post_status != 'trash'";
595 } elseif ( isset( $_GET['post_status'] ) ) {
596 $extra_checks = $wpdb->prepare( ' AND post_status = %s', $_GET['post_status'] );
597 }
598
599 $months = $wpdb->get_results( $wpdb->prepare( "
600 SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
601 FROM $wpdb->posts
602 WHERE post_type = %s
603 $extra_checks
604 ORDER BY post_date DESC
605 ", $post_type ) );
606
607 /**
608 * Filters the 'Months' drop-down results.
609 *
610 * @since 3.7.0
611 *
612 * @param object $months The months drop-down query results.
613 * @param string $post_type The post type.
614 */
615 $months = apply_filters( 'months_dropdown_results', $months, $post_type );
616
617 $month_count = count( $months );
618
619 if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) )
620 return;
621
622 $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
623 ?>
624 <label for="filter-by-date" class="screen-reader-text"><?php _e( 'Filter by date' ); ?></label>
625 <select name="m" id="filter-by-date">
626 <option<?php selected( $m, 0 ); ?> value="0"><?php _e( 'All dates' ); ?></option>
627 <?php
628 foreach ( $months as $arc_row ) {
629 if ( 0 == $arc_row->year )
630 continue;
631
632 $month = zeroise( $arc_row->month, 2 );
633 $year = $arc_row->year;
634
635 printf( "<option %s value='%s'>%s</option>\n",
636 selected( $m, $year . $month, false ),
637 esc_attr( $arc_row->year . $month ),
638 /* translators: 1: month name, 2: 4-digit year */
639 sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year )
640 );
641 }
642 ?>
643 </select>
644 <?php
645 }
646
647 /**
648 * Display a view switcher
649 *
650 * @since 3.1.0
651 *
652 * @param string $current_mode
653 */
654 protected function view_switcher( $current_mode ) {
655 ?>
656 <input type="hidden" name="mode" value="<?php echo esc_attr( $current_mode ); ?>" />
657 <div class="view-switch">
658 <?php
659 foreach ( $this->modes as $mode => $title ) {
660 $classes = array( 'view-' . $mode );
661 if ( $current_mode === $mode )
662 $classes[] = 'current';
663 printf(
664 "<a href='%s' class='%s' id='view-switch-$mode'><span class='screen-reader-text'>%s</span></a>\n",
665 esc_url( add_query_arg( 'mode', $mode ) ),
666 implode( ' ', $classes ),
667 $title
668 );
669 }
670 ?>
671 </div>
672 <?php
673 }
674
675 /**
676 * Display a comment count bubble
677 *
678 * @since 3.1.0
679 *
680 * @param int $post_id The post ID.
681 * @param int $pending_comments Number of pending comments.
682 */
683 protected function comments_bubble( $post_id, $pending_comments ) {
684 $approved_comments = get_comments_number();
685
686 $approved_comments_number = number_format_i18n( $approved_comments );
687 $pending_comments_number = number_format_i18n( $pending_comments );
688
689 $approved_only_phrase = sprintf( _n( '%s comment', '%s comments', $approved_comments ), $approved_comments_number );
690 $approved_phrase = sprintf( _n( '%s approved comment', '%s approved comments', $approved_comments ), $approved_comments_number );
691 $pending_phrase = sprintf( _n( '%s pending comment', '%s pending comments', $pending_comments ), $pending_comments_number );
692
693 // No comments at all.
694 if ( ! $approved_comments && ! $pending_comments ) {
695 printf( '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">%s</span>',
696 __( 'No comments' )
697 );
698 // Approved comments have different display depending on some conditions.
699 } elseif ( $approved_comments ) {
700 printf( '<a href="%s" class="post-com-count post-com-count-approved"><span class="comment-count-approved" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
701 esc_url( add_query_arg( array( 'p' => $post_id, 'comment_status' => 'approved' ), admin_url( 'edit-comments.php' ) ) ),
702 $approved_comments_number,
703 $pending_comments ? $approved_phrase : $approved_only_phrase
704 );
705 } else {
706 printf( '<span class="post-com-count post-com-count-no-comments"><span class="comment-count comment-count-no-comments" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></span>',
707 $approved_comments_number,
708 $pending_comments ? __( 'No approved comments' ) : __( 'No comments' )
709 );
710 }
711
712 if ( $pending_comments ) {
713 printf( '<a href="%s" class="post-com-count post-com-count-pending"><span class="comment-count-pending" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
714 esc_url( add_query_arg( array( 'p' => $post_id, 'comment_status' => 'moderated' ), admin_url( 'edit-comments.php' ) ) ),
715 $pending_comments_number,
716 $pending_phrase
717 );
718 } else {
719 printf( '<span class="post-com-count post-com-count-pending post-com-count-no-pending"><span class="comment-count comment-count-no-pending" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></span>',
720 $pending_comments_number,
721 $approved_comments ? __( 'No pending comments' ) : __( 'No comments' )
722 );
723 }
724 }
725
726 /**
727 * Get the current page number
728 *
729 * @since 3.1.0
730 *
731 * @return int
732 */
733 public function get_pagenum() {
734 $pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0;
735
736 if ( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] )
737 $pagenum = $this->_pagination_args['total_pages'];
738
739 return max( 1, $pagenum );
740 }
741
742 /**
743 * Get number of items to display on a single page
744 *
745 * @since 3.1.0
746 *
747 * @param string $option
748 * @param int $default
749 * @return int
750 */
751 protected function get_items_per_page( $option, $default = 20 ) {
752 $per_page = (int) get_user_option( $option );
753 if ( empty( $per_page ) || $per_page < 1 )
754 $per_page = $default;
755
756 /**
757 * Filters the number of items to be displayed on each page of the list table.
758 *
759 * The dynamic hook name, $option, refers to the `per_page` option depending
760 * on the type of list table in use. Possible values include: 'edit_comments_per_page',
761 * 'sites_network_per_page', 'site_themes_network_per_page', 'themes_network_per_page',
762 * 'users_network_per_page', 'edit_post_per_page', 'edit_page_per_page',
763 * 'edit_{$post_type}_per_page', etc.
764 *
765 * @since 2.9.0
766 *
767 * @param int $per_page Number of items to be displayed. Default 20.
768 */
769 return (int) apply_filters( "{$option}", $per_page );
770 }
771
772 /**
773 * Display the pagination.
774 *
775 * @since 3.1.0
776 *
777 * @param string $which
778 */
779 protected function pagination( $which ) {
780 if ( empty( $this->_pagination_args ) ) {
781 return;
782 }
783
784 $total_items = $this->_pagination_args['total_items'];
785 $total_pages = $this->_pagination_args['total_pages'];
786 $infinite_scroll = false;
787 if ( isset( $this->_pagination_args['infinite_scroll'] ) ) {
788 $infinite_scroll = $this->_pagination_args['infinite_scroll'];
789 }
790
791 if ( 'top' === $which && $total_pages > 1 ) {
792 $this->screen->render_screen_reader_content( 'heading_pagination' );
793 }
794
795 $output = '<span class="displaying-num">' . sprintf( _n( '%s item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . '</span>';
796
797 $current = $this->get_pagenum();
798 $removable_query_args = wp_removable_query_args();
799
800 $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
801
802 $current_url = remove_query_arg( $removable_query_args, $current_url );
803
804 $page_links = array();
805
806 $total_pages_before = '<span class="paging-input">';
807 $total_pages_after = '</span></span>';
808
809 $disable_first = $disable_last = $disable_prev = $disable_next = false;
810
811 if ( $current == 1 ) {
812 $disable_first = true;
813 $disable_prev = true;
814 }
815 if ( $current == 2 ) {
816 $disable_first = true;
817 }
818 if ( $current == $total_pages ) {
819 $disable_last = true;
820 $disable_next = true;
821 }
822 if ( $current == $total_pages - 1 ) {
823 $disable_last = true;
824 }
825
826 if ( $disable_first ) {
827 $page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&laquo;</span>';
828 } else {
829 $page_links[] = sprintf( "<a class='first-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
830 esc_url( remove_query_arg( 'paged', $current_url ) ),
831 __( 'First page' ),
832 '&laquo;'
833 );
834 }
835
836 if ( $disable_prev ) {
837 $page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&lsaquo;</span>';
838 } else {
839 $page_links[] = sprintf( "<a class='prev-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
840 esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ),
841 __( 'Previous page' ),
842 '&lsaquo;'
843 );
844 }
845
846 if ( 'bottom' === $which ) {
847 $html_current_page = $current;
848 $total_pages_before = '<span class="screen-reader-text">' . __( 'Current Page' ) . '</span><span id="table-paging" class="paging-input"><span class="tablenav-paging-text">';
849 } else {
850 $html_current_page = sprintf( "%s<input class='current-page' id='current-page-selector' type='text' name='paged' value='%s' size='%d' aria-describedby='table-paging' /><span class='tablenav-paging-text'>",
851 '<label for="current-page-selector" class="screen-reader-text">' . __( 'Current Page' ) . '</label>',
852 $current,
853 strlen( $total_pages )
854 );
855 }
856 $html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
857 $page_links[] = $total_pages_before . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . $total_pages_after;
858
859 if ( $disable_next ) {
860 $page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&rsaquo;</span>';
861 } else {
862 $page_links[] = sprintf( "<a class='next-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
863 esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ),
864 __( 'Next page' ),
865 '&rsaquo;'
866 );
867 }
868
869 if ( $disable_last ) {
870 $page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&raquo;</span>';
871 } else {
872 $page_links[] = sprintf( "<a class='last-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
873 esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
874 __( 'Last page' ),
875 '&raquo;'
876 );
877 }
878
879 $pagination_links_class = 'pagination-links';
880 if ( ! empty( $infinite_scroll ) ) {
881 $pagination_links_class .= ' hide-if-js';
882 }
883 $output .= "\n<span class='$pagination_links_class'>" . join( "\n", $page_links ) . '</span>';
884
885 if ( $total_pages ) {
886 $page_class = $total_pages < 2 ? ' one-page' : '';
887 } else {
888 $page_class = ' no-pages';
889 }
890 $this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";
891
892 echo $this->_pagination;
893 }
894
895 /**
896 * Get a list of columns. The format is:
897 * 'internal-name' => 'Title'
898 *
899 * @since 3.1.0
900 * @abstract
901 *
902 * @return array
903 */
904 public function get_columns() {
905 die( 'function Tutor_List_Table::get_columns() must be over-ridden in a sub-class.' );
906 }
907
908 /**
909 * Get a list of sortable columns. The format is:
910 * 'internal-name' => 'orderby'
911 * or
912 * 'internal-name' => array( 'orderby', true )
913 *
914 * The second format will make the initial sorting order be descending
915 *
916 * @since 3.1.0
917 *
918 * @return array
919 */
920 protected function get_sortable_columns() {
921 return array();
922 }
923
924 /**
925 * Gets the name of the default primary column.
926 *
927 * @since 4.3.0
928 *
929 * @return string Name of the default primary column, in this case, an empty string.
930 */
931 protected function get_default_primary_column_name() {
932 $columns = $this->get_columns();
933 $column = '';
934
935 if ( empty( $columns ) ) {
936 return $column;
937 }
938
939 // We need a primary defined so responsive views show something,
940 // so let's fall back to the first non-checkbox column.
941 foreach ( $columns as $col => $column_name ) {
942 if ( 'cb' === $col ) {
943 continue;
944 }
945
946 $column = $col;
947 break;
948 }
949
950 return $column;
951 }
952
953 /**
954 * Public wrapper for Tutor_List_Table::get_default_primary_column_name().
955 *
956 * @since 4.4.0
957 *
958 * @return string Name of the default primary column.
959 */
960 public function get_primary_column() {
961 return $this->get_primary_column_name();
962 }
963
964 /**
965 * Gets the name of the primary column.
966 *
967 * @since 4.3.0
968 *
969 * @return string The name of the primary column.
970 */
971 protected function get_primary_column_name() {
972 $columns = get_column_headers( $this->screen );
973 $default = $this->get_default_primary_column_name();
974
975 // If the primary column doesn't exist fall back to the
976 // first non-checkbox column.
977 if ( ! isset( $columns[ $default ] ) ) {
978 $default = Tutor_List_Table::get_default_primary_column_name();
979 }
980
981 /**
982 * Filters the name of the primary column for the current list table.
983 *
984 * @since 4.3.0
985 *
986 * @param string $default Column name default for the specific list table, e.g. 'name'.
987 * @param string $context Screen ID for specific list table, e.g. 'plugins'.
988 */
989 $column = apply_filters( 'list_table_primary_column', $default, $this->screen->id );
990
991 if ( empty( $column ) || ! isset( $columns[ $column ] ) ) {
992 $column = $default;
993 }
994
995 return $column;
996 }
997
998 /**
999 * Get a list of all, hidden and sortable columns, with filter applied
1000 *
1001 * @since 3.1.0
1002 *
1003 * @return array
1004 */
1005 protected function get_column_info() {
1006 // $_column_headers is already set / cached
1007 if ( isset( $this->_column_headers ) && is_array( $this->_column_headers ) ) {
1008 // Back-compat for list tables that have been manually setting $_column_headers for horse reasons.
1009 // In 4.3, we added a fourth argument for primary column.
1010 $column_headers = array( array(), array(), array(), $this->get_primary_column_name() );
1011 foreach ( $this->_column_headers as $key => $value ) {
1012 $column_headers[ $key ] = $value;
1013 }
1014
1015 return $column_headers;
1016 }
1017
1018 $columns = get_column_headers( $this->screen );
1019 $hidden = get_hidden_columns( $this->screen );
1020
1021 $sortable_columns = $this->get_sortable_columns();
1022 /**
1023 * Filters the list table sortable columns for a specific screen.
1024 *
1025 * The dynamic portion of the hook name, `$this->screen->id`, refers
1026 * to the ID of the current screen, usually a string.
1027 *
1028 * @since 3.5.0
1029 *
1030 * @param array $sortable_columns An array of sortable columns.
1031 */
1032 $_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $sortable_columns );
1033
1034 $sortable = array();
1035 foreach ( $_sortable as $id => $data ) {
1036 if ( empty( $data ) )
1037 continue;
1038
1039 $data = (array) $data;
1040 if ( !isset( $data[1] ) )
1041 $data[1] = false;
1042
1043 $sortable[$id] = $data;
1044 }
1045
1046 $primary = $this->get_primary_column_name();
1047 $this->_column_headers = array( $columns, $hidden, $sortable, $primary );
1048
1049 return $this->_column_headers;
1050 }
1051
1052 /**
1053 * Return number of visible columns
1054 *
1055 * @since 3.1.0
1056 *
1057 * @return int
1058 */
1059 public function get_column_count() {
1060 list ( $columns, $hidden ) = $this->get_column_info();
1061 $hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) );
1062 return count( $columns ) - count( $hidden );
1063 }
1064
1065 /**
1066 * Print column headers, accounting for hidden and sortable columns.
1067 *
1068 * @since 3.1.0
1069 *
1070 * @staticvar int $cb_counter
1071 *
1072 * @param bool $with_id Whether to set the id attribute or not
1073 */
1074 public function print_column_headers( $with_id = true ) {
1075 list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
1076
1077 $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
1078 $current_url = remove_query_arg( 'paged', $current_url );
1079
1080 if ( isset( $_GET['orderby'] ) ) {
1081 $current_orderby = $_GET['orderby'];
1082 } else {
1083 $current_orderby = '';
1084 }
1085
1086 if ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) {
1087 $current_order = 'desc';
1088 } else {
1089 $current_order = 'asc';
1090 }
1091
1092 if ( ! empty( $columns['cb'] ) ) {
1093 static $cb_counter = 1;
1094 $columns['cb'] = '<label class="screen-reader-text" for="cb-select-all-' . $cb_counter . '">' . __( 'Select All' ) . '</label>'
1095 . '<input id="cb-select-all-' . $cb_counter . '" type="checkbox" />';
1096 $cb_counter++;
1097 }
1098
1099 foreach ( $columns as $column_key => $column_display_name ) {
1100 $class = array( 'manage-column', "column-$column_key" );
1101
1102 if ( in_array( $column_key, $hidden ) ) {
1103 $class[] = 'hidden';
1104 }
1105
1106 if ( 'cb' === $column_key )
1107 $class[] = 'check-column';
1108 elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) )
1109 $class[] = 'num';
1110
1111 if ( $column_key === $primary ) {
1112 $class[] = 'column-primary';
1113 }
1114
1115 if ( isset( $sortable[$column_key] ) ) {
1116 list( $orderby, $desc_first ) = $sortable[$column_key];
1117
1118 if ( $current_orderby === $orderby ) {
1119 $order = 'asc' === $current_order ? 'desc' : 'asc';
1120 $class[] = 'sorted';
1121 $class[] = $current_order;
1122 } else {
1123 $order = $desc_first ? 'desc' : 'asc';
1124 $class[] = 'sortable';
1125 $class[] = $desc_first ? 'asc' : 'desc';
1126 }
1127
1128 $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>';
1129 }
1130
1131 $tag = ( 'cb' === $column_key ) ? 'td' : 'th';
1132 $scope = ( 'th' === $tag ) ? 'scope="col"' : '';
1133 $id = $with_id ? "id='$column_key'" : '';
1134
1135 if ( !empty( $class ) )
1136 $class = "class='" . join( ' ', $class ) . "'";
1137
1138 echo "<$tag $scope $id $class>$column_display_name</$tag>";
1139 }
1140 }
1141
1142 /**
1143 * Display the table
1144 *
1145 * @since 3.1.0
1146 */
1147 public function display() {
1148 $singular = $this->_args['singular'];
1149
1150 $this->display_tablenav( 'top' );
1151
1152 $this->screen->render_screen_reader_content( 'heading_list' );
1153 ?>
1154 <table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
1155 <thead>
1156 <tr>
1157 <?php $this->print_column_headers(); ?>
1158 </tr>
1159 </thead>
1160
1161 <tbody id="the-list"<?php
1162 if ( $singular ) {
1163 echo " data-wp-lists='list:$singular'";
1164 } ?>>
1165 <?php $this->display_rows_or_placeholder(); ?>
1166 </tbody>
1167
1168 <tfoot>
1169 <tr>
1170 <?php $this->print_column_headers( false ); ?>
1171 </tr>
1172 </tfoot>
1173
1174 </table>
1175 <?php
1176 $this->display_tablenav( 'bottom' );
1177 }
1178
1179 /**
1180 * Get a list of CSS classes for the Tutor_List_Table table tag.
1181 *
1182 * @since 3.1.0
1183 *
1184 * @return array List of CSS classes for the table tag.
1185 */
1186 protected function get_table_classes() {
1187 return array( 'widefat', 'fixed', 'striped', $this->_args['plural'] );
1188 }
1189
1190 /**
1191 * Generate the table navigation above or below the table
1192 *
1193 * @since 3.1.0
1194 * @param string $which
1195 */
1196 protected function display_tablenav( $which ) {
1197 if ( 'top' === $which ) {
1198 wp_nonce_field( 'bulk-' . $this->_args['plural'] );
1199 }
1200 ?>
1201 <div class="tablenav <?php echo esc_attr( $which ); ?>">
1202
1203 <?php if ( $this->has_items() ): ?>
1204 <div class="alignleft actions bulkactions">
1205 <?php $this->bulk_actions( $which ); ?>
1206 </div>
1207 <?php endif;
1208 $this->extra_tablenav( $which );
1209 $this->pagination( $which );
1210 ?>
1211
1212 <br class="clear" />
1213 </div>
1214 <?php
1215 }
1216
1217 /**
1218 * Extra controls to be displayed between bulk actions and pagination
1219 *
1220 * @since 3.1.0
1221 *
1222 * @param string $which
1223 */
1224 protected function extra_tablenav( $which ) {}
1225
1226 /**
1227 * Generate the tbody element for the list table.
1228 *
1229 * @since 3.1.0
1230 */
1231 public function display_rows_or_placeholder() {
1232 if ( $this->has_items() ) {
1233 $this->display_rows();
1234 } else {
1235 echo '<tr class="no-items"><td class="colspanchange" colspan="' . $this->get_column_count() . '">';
1236 $this->no_items();
1237 echo '</td></tr>';
1238 }
1239 }
1240
1241 /**
1242 * Generate the table rows
1243 *
1244 * @since 3.1.0
1245 */
1246 public function display_rows() {
1247 foreach ( $this->items as $item )
1248 $this->single_row( $item );
1249 }
1250
1251 /**
1252 * Generates content for a single row of the table
1253 *
1254 * @since 3.1.0
1255 *
1256 * @param object $item The current item
1257 */
1258 public function single_row( $item ) {
1259 echo '<tr>';
1260 $this->single_row_columns( $item );
1261 echo '</tr>';
1262 }
1263
1264 /**
1265 *
1266 * @param object $item
1267 * @param string $column_name
1268 */
1269 protected function column_default( $item, $column_name ) {}
1270
1271 /**
1272 *
1273 * @param object $item
1274 */
1275 protected function column_cb( $item ) {}
1276
1277 /**
1278 * Generates the columns for a single row of the table
1279 *
1280 * @since 3.1.0
1281 *
1282 * @param object $item The current item
1283 */
1284 protected function single_row_columns( $item ) {
1285 list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
1286
1287 foreach ( $columns as $column_name => $column_display_name ) {
1288 $classes = "$column_name column-$column_name";
1289 if ( $primary === $column_name ) {
1290 $classes .= ' has-row-actions column-primary';
1291 }
1292
1293 if ( in_array( $column_name, $hidden ) ) {
1294 $classes .= ' hidden';
1295 }
1296
1297 // Comments column uses HTML in the display name with screen reader text.
1298 // Instead of using esc_attr(), we strip tags to get closer to a user-friendly string.
1299 $data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"';
1300
1301 $attributes = "class='$classes' $data";
1302
1303 if ( 'cb' === $column_name ) {
1304 echo '<th scope="row" class="check-column">';
1305 echo $this->column_cb( $item );
1306 echo '</th>';
1307 } elseif ( method_exists( $this, '_column_' . $column_name ) ) {
1308 echo call_user_func(
1309 array( $this, '_column_' . $column_name ),
1310 $item,
1311 $classes,
1312 $data,
1313 $primary
1314 );
1315 } elseif ( method_exists( $this, 'column_' . $column_name ) ) {
1316 echo "<td $attributes>";
1317 echo call_user_func( array( $this, 'column_' . $column_name ), $item );
1318 echo $this->handle_row_actions( $item, $column_name, $primary );
1319 echo "</td>";
1320 } else {
1321 echo "<td $attributes>";
1322 echo $this->column_default( $item, $column_name );
1323 echo $this->handle_row_actions( $item, $column_name, $primary );
1324 echo "</td>";
1325 }
1326 }
1327 }
1328
1329 /**
1330 * Generates and display row actions links for the list table.
1331 *
1332 * @since 4.3.0
1333 *
1334 * @param object $item The item being acted upon.
1335 * @param string $column_name Current column name.
1336 * @param string $primary Primary column name.
1337 * @return string The row actions HTML, or an empty string if the current column is the primary column.
1338 */
1339 protected function handle_row_actions( $item, $column_name, $primary ) {
1340 return $column_name === $primary ? '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>' : '';
1341 }
1342
1343 /**
1344 * Handle an incoming ajax request (called from admin-ajax.php)
1345 *
1346 * @since 3.1.0
1347 */
1348 public function ajax_response() {
1349 $this->prepare_items();
1350
1351 ob_start();
1352 if ( ! empty( $_REQUEST['no_placeholder'] ) ) {
1353 $this->display_rows();
1354 } else {
1355 $this->display_rows_or_placeholder();
1356 }
1357
1358 $rows = ob_get_clean();
1359
1360 $response = array( 'rows' => $rows );
1361
1362 if ( isset( $this->_pagination_args['total_items'] ) ) {
1363 $response['total_items_i18n'] = sprintf(
1364 _n( '%s item', '%s items', $this->_pagination_args['total_items'] ),
1365 number_format_i18n( $this->_pagination_args['total_items'] )
1366 );
1367 }
1368 if ( isset( $this->_pagination_args['total_pages'] ) ) {
1369 $response['total_pages'] = $this->_pagination_args['total_pages'];
1370 $response['total_pages_i18n'] = number_format_i18n( $this->_pagination_args['total_pages'] );
1371 }
1372
1373 die( wp_json_encode( $response ) );
1374 }
1375
1376 /**
1377 * Send required variables to JavaScript land
1378 *
1379 */
1380 public function _js_vars() {
1381 $args = array(
1382 'class' => get_class( $this ),
1383 'screen' => array(
1384 'id' => $this->screen->id,
1385 'base' => $this->screen->base,
1386 )
1387 );
1388
1389 printf( "<script type='text/javascript'>list_args = %s;</script>\n", wp_json_encode( $args ) );
1390 }
1391 }
1392