Yasr – Yet Another Stars Rating - Version 1.5.8

Version Description

  • NEW FEATURE: Logs Page: is now possible to see log page and delete user ratings!
  • TWEAKED: Yasr settings page has now it's own top level page instead under the WordPress Settings section
Download this release

Release Info

Developer Dudo
Plugin Icon 128x128 Yasr – Yet Another Stars Rating
Version 1.5.8
Comparing to
See all releases

Code changes from version 1.5.7 to 1.5.8

lib/class-wp-list-table.php ADDED
@@ -0,0 +1,1387 @@
1
+ <?php
2
+ /**
3
+ * Base class for displaying a list of items in an ajaxified HTML table.
4
+ *
5
+ * @since 3.1.0
6
+ * @access private
7
+ */
8
+ class YASR_WP_List_Table {
9
+
10
+ /**
11
+ * The current list of items.
12
+ *
13
+ * @since 3.1.0
14
+ * @var array
15
+ */
16
+ public $items;
17
+
18
+ /**
19
+ * Various information about the current table.
20
+ *
21
+ * @since 3.1.0
22
+ * @var array
23
+ */
24
+ protected $_args;
25
+
26
+ /**
27
+ * Various information needed for displaying the pagination.
28
+ *
29
+ * @since 3.1.0
30
+ * @var array
31
+ */
32
+ protected $_pagination_args = array();
33
+
34
+ /**
35
+ * The current screen.
36
+ *
37
+ * @since 3.1.0
38
+ * @var object
39
+ */
40
+ protected $screen;
41
+
42
+ /**
43
+ * Cached bulk actions.
44
+ *
45
+ * @since 3.1.0
46
+ * @var array
47
+ */
48
+ private $_actions;
49
+
50
+ /**
51
+ * Cached pagination output.
52
+ *
53
+ * @since 3.1.0
54
+ * @var string
55
+ */
56
+ private $_pagination;
57
+
58
+ /**
59
+ * The view switcher modes.
60
+ *
61
+ * @since 4.1.0
62
+ * @var array
63
+ */
64
+ protected $modes = array();
65
+
66
+ /**
67
+ * Stores the value returned by ->get_column_info().
68
+ *
69
+ * @since 4.1.0
70
+ * @var array
71
+ */
72
+ protected $_column_headers;
73
+
74
+ /**
75
+ * {@internal Missing Summary}
76
+ *
77
+ * @var array
78
+ */
79
+ protected $compat_fields = array( '_args', '_pagination_args', 'screen', '_actions', '_pagination' );
80
+
81
+ /**
82
+ * {@internal Missing Summary}
83
+ *
84
+ * @var array
85
+ */
86
+ protected $compat_methods = array(
87
+ 'set_pagination_args',
88
+ 'get_views',
89
+ 'get_bulk_actions',
90
+ 'bulk_actions',
91
+ 'row_actions',
92
+ 'months_dropdown',
93
+ 'view_switcher',
94
+ 'comments_bubble',
95
+ 'get_items_per_page',
96
+ 'pagination',
97
+ 'get_sortable_columns',
98
+ 'get_column_info',
99
+ 'get_table_classes',
100
+ 'display_tablenav',
101
+ 'extra_tablenav',
102
+ 'single_row_columns',
103
+ );
104
+
105
+ /**
106
+ * Constructor.
107
+ *
108
+ * The child class should call this constructor from its own constructor to override
109
+ * the default $args.
110
+ *
111
+ * @since 3.1.0
112
+ *
113
+ * @param array|string $args {
114
+ * Array or string of arguments.
115
+ *
116
+ * @type string $plural Plural value used for labels and the objects being listed.
117
+ * This affects things such as CSS class-names and nonces used
118
+ * in the list table, e.g. 'posts'. Default empty.
119
+ * @type string $singular Singular label for an object being listed, e.g. 'post'.
120
+ * Default empty
121
+ * @type bool $ajax Whether the list table supports Ajax. This includes loading
122
+ * and sorting data, for example. If true, the class will call
123
+ * the _js_vars() method in the footer to provide variables
124
+ * to any scripts handling Ajax events. Default false.
125
+ * @type string $screen String containing the hook name used to determine the current
126
+ * screen. If left null, the current screen will be automatically set.
127
+ * Default null.
128
+ * }
129
+ */
130
+ public function __construct( $args = array() ) {
131
+ $args = wp_parse_args(
132
+ $args, array(
133
+ 'plural' => '',
134
+ 'singular' => '',
135
+ 'ajax' => false,
136
+ 'screen' => null,
137
+ )
138
+ );
139
+
140
+ $this->screen = convert_to_screen( $args['screen'] );
141
+
142
+ add_filter( "manage_{$this->screen->id}_columns", array( $this, 'get_columns' ), 0 );
143
+
144
+ if ( ! $args['plural'] ) {
145
+ $args['plural'] = $this->screen->base;
146
+ }
147
+
148
+ $args['plural'] = sanitize_key( $args['plural'] );
149
+ $args['singular'] = sanitize_key( $args['singular'] );
150
+
151
+ $this->_args = $args;
152
+
153
+ if ( $args['ajax'] ) {
154
+ // wp_enqueue_script( 'list-table' );
155
+ add_action( 'admin_footer', array( $this, '_js_vars' ) );
156
+ }
157
+
158
+ if ( empty( $this->modes ) ) {
159
+ $this->modes = array(
160
+ 'list' => __( 'List View' ),
161
+ 'excerpt' => __( 'Excerpt View' ),
162
+ );
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Make private properties readable for backward compatibility.
168
+ *
169
+ * @since 4.0.0
170
+ *
171
+ * @param string $name Property to get.
172
+ * @return mixed Property.
173
+ */
174
+ public function __get( $name ) {
175
+ if ( in_array( $name, $this->compat_fields ) ) {
176
+ return $this->$name;
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Make private properties settable for backward compatibility.
182
+ *
183
+ * @since 4.0.0
184
+ *
185
+ * @param string $name Property to check if set.
186
+ * @param mixed $value Property value.
187
+ * @return mixed Newly-set property.
188
+ */
189
+ public function __set( $name, $value ) {
190
+ if ( in_array( $name, $this->compat_fields ) ) {
191
+ return $this->$name = $value;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Make private properties checkable for backward compatibility.
197
+ *
198
+ * @since 4.0.0
199
+ *
200
+ * @param string $name Property to check if set.
201
+ * @return bool Whether the property is set.
202
+ */
203
+ public function __isset( $name ) {
204
+ if ( in_array( $name, $this->compat_fields ) ) {
205
+ return isset( $this->$name );
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Make private properties un-settable for backward compatibility.
211
+ *
212
+ * @since 4.0.0
213
+ *
214
+ * @param string $name Property to unset.
215
+ */
216
+ public function __unset( $name ) {
217
+ if ( in_array( $name, $this->compat_fields ) ) {
218
+ unset( $this->$name );
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Make private/protected methods readable for backward compatibility.
224
+ *
225
+ * @since 4.0.0
226
+ *
227
+ * @param string $name Method to call.
228
+ * @param array $arguments Arguments to pass when calling.
229
+ * @return mixed|bool Return value of the callback, false otherwise.
230
+ */
231
+ public function __call( $name, $arguments ) {
232
+ if ( in_array( $name, $this->compat_methods ) ) {
233
+ return call_user_func_array( array( $this, $name ), $arguments );
234
+ }
235
+ return false;
236
+ }
237
+
238
+ /**
239
+ * Checks the current user's permissions
240
+ *
241
+ * @since 3.1.0
242
+ * @abstract
243
+ */
244
+ public function ajax_user_can() {
245
+ die( 'function WP_List_Table::ajax_user_can() must be over-ridden in a sub-class.' );
246
+ }
247
+
248
+ /**
249
+ * Prepares the list of items for displaying.
250
+ *
251
+ * @uses WP_List_Table::set_pagination_args()
252
+ *
253
+ * @since 3.1.0
254
+ * @abstract
255
+ */
256
+ public function prepare_items() {
257
+ die( 'function WP_List_Table::prepare_items() must be over-ridden in a sub-class.' );
258
+ }
259
+
260
+ /**
261
+ * An internal method that sets all the necessary pagination arguments
262
+ *
263
+ * @since 3.1.0
264
+ *
265
+ * @param array|string $args Array or string of arguments with information about the pagination.
266
+ */
267
+ protected function set_pagination_args( $args ) {
268
+ $args = wp_parse_args(
269
+ $args, array(
270
+ 'total_items' => 0,
271
+ 'total_pages' => 0,
272
+ 'per_page' => 0,
273
+ )
274
+ );
275
+
276
+ if ( ! $args['total_pages'] && $args['per_page'] > 0 ) {
277
+ $args['total_pages'] = ceil( $args['total_items'] / $args['per_page'] );
278
+ }
279
+
280
+ // Redirect if page number is invalid and headers are not already sent.
281
+ if ( ! headers_sent() && ! wp_doing_ajax() && $args['total_pages'] > 0 && $this->get_pagenum() > $args['total_pages'] ) {
282
+ wp_redirect( add_query_arg( 'paged', $args['total_pages'] ) );
283
+ exit;
284
+ }
285
+
286
+ $this->_pagination_args = $args;
287
+ }
288
+
289
+ /**
290
+ * Access the pagination args.
291
+ *
292
+ * @since 3.1.0
293
+ *
294
+ * @param string $key Pagination argument to retrieve. Common values include 'total_items',
295
+ * 'total_pages', 'per_page', or 'infinite_scroll'.
296
+ * @return int Number of items that correspond to the given pagination argument.
297
+ */
298
+ public function get_pagination_arg( $key ) {
299
+ if ( 'page' === $key ) {
300
+ return $this->get_pagenum();
301
+ }
302
+
303
+ if ( isset( $this->_pagination_args[ $key ] ) ) {
304
+ return $this->_pagination_args[ $key ];
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Whether the table has items to display or not
310
+ *
311
+ * @since 3.1.0
312
+ *
313
+ * @return bool
314
+ */
315
+ public function has_items() {
316
+ return ! empty( $this->items );
317
+ }
318
+
319
+ /**
320
+ * Message to be displayed when there are no items
321
+ *
322
+ * @since 3.1.0
323
+ */
324
+ public function no_items() {
325
+ _e( 'No items found.' );
326
+ }
327
+
328
+ /**
329
+ * Displays the search box.
330
+ *
331
+ * @since 3.1.0
332
+ *
333
+ * @param string $text The 'submit' button label.
334
+ * @param string $input_id ID attribute value for the search input field.
335
+ */
336
+ public function search_box( $text, $input_id ) {
337
+ if ( empty( $_REQUEST['s'] ) && ! $this->has_items() ) {
338
+ return;
339
+ }
340
+
341
+ $input_id = $input_id . '-search-input';
342
+
343
+ if ( ! empty( $_REQUEST['orderby'] ) ) {
344
+ echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
345
+ }
346
+ if ( ! empty( $_REQUEST['order'] ) ) {
347
+ echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
348
+ }
349
+ if ( ! empty( $_REQUEST['post_mime_type'] ) ) {
350
+ echo '<input type="hidden" name="post_mime_type" value="' . esc_attr( $_REQUEST['post_mime_type'] ) . '" />';
351
+ }
352
+ if ( ! empty( $_REQUEST['detached'] ) ) {
353
+ echo '<input type="hidden" name="detached" value="' . esc_attr( $_REQUEST['detached'] ) . '" />';
354
+ }
355
+ ?>
356
+ <p class="search-box">
357
+ <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo $text; ?>:</label>
358
+ <input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>" />
359
+ <?php submit_button( $text, '', '', false, array( 'id' => 'search-submit' ) ); ?>
360
+ </p>
361
+ <?php
362
+ }
363
+
364
+ /**
365
+ * Get an associative array ( id => link ) with the list
366
+ * of views available on this table.
367
+ *
368
+ * @since 3.1.0
369
+ *
370
+ * @return array
371
+ */
372
+ protected function get_views() {
373
+ return array();
374
+ }
375
+
376
+ /**
377
+ * Display the list of views available on this table.
378
+ *
379
+ * @since 3.1.0
380
+ */
381
+ public function views() {
382
+ $views = $this->get_views();
383
+ /**
384
+ * Filters the list of available list table views.
385
+ *
386
+ * The dynamic portion of the hook name, `$this->screen->id`, refers
387
+ * to the ID of the current screen, usually a string.
388
+ *
389
+ * @since 3.5.0
390
+ *
391
+ * @param array $views An array of available list table views.
392
+ */
393
+ $views = apply_filters( "views_{$this->screen->id}", $views );
394
+
395
+ if ( empty( $views ) ) {
396
+ return;
397
+ }
398
+
399
+ $this->screen->render_screen_reader_content( 'heading_views' );
400
+
401
+ echo "<ul class='subsubsub'>\n";
402
+ foreach ( $views as $class => $view ) {
403
+ $views[ $class ] = "\t<li class='$class'>$view";
404
+ }
405
+ echo implode( " |</li>\n", $views ) . "</li>\n";
406
+ echo '</ul>';
407
+ }
408
+
409
+ /**
410
+ * Get an associative array ( option_name => option_title ) with the list
411
+ * of bulk actions available on this table.
412
+ *
413
+ * @since 3.1.0
414
+ *
415
+ * @return array
416
+ */
417
+ protected function get_bulk_actions() {
418
+ return array();
419
+ }
420
+
421
+ /**
422
+ * Display the bulk actions dropdown.
423
+ *
424
+ * @since 3.1.0
425
+ *
426
+ * @param string $which The location of the bulk actions: 'top' or 'bottom'.
427
+ * This is designated as optional for backward compatibility.
428
+ */
429
+ protected function bulk_actions( $which = '' ) {
430
+ if ( is_null( $this->_actions ) ) {
431
+ $this->_actions = $this->get_bulk_actions();
432
+ /**
433
+ * Filters the list table Bulk Actions drop-down.
434
+ *
435
+ * The dynamic portion of the hook name, `$this->screen->id`, refers
436
+ * to the ID of the current screen, usually a string.
437
+ *
438
+ * This filter can currently only be used to remove bulk actions.
439
+ *
440
+ * @since 3.5.0
441
+ *
442
+ * @param array $actions An array of the available bulk actions.
443
+ */
444
+ $this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions );
445
+ $two = '';
446
+ } else {
447
+ $two = '2';
448
+ }
449
+
450
+ if ( empty( $this->_actions ) ) {
451
+ return;
452
+ }
453
+
454
+ echo '<label for="bulk-action-selector-' . esc_attr( $which ) . '" class="screen-reader-text">' . __( 'Select bulk action' ) . '</label>';
455
+ echo '<select name="action' . $two . '" id="bulk-action-selector-' . esc_attr( $which ) . "\">\n";
456
+ echo '<option value="-1">' . __( 'Bulk Actions' ) . "</option>\n";
457
+
458
+ foreach ( $this->_actions as $name => $title ) {
459
+ $class = 'edit' === $name ? ' class="hide-if-no-js"' : '';
460
+
461
+ echo "\t" . '<option value="' . $name . '"' . $class . '>' . $title . "</option>\n";
462
+ }
463
+
464
+ echo "</select>\n";
465
+
466
+ submit_button( __( 'Apply' ), 'action', '', false, array( 'id' => "doaction$two" ) );
467
+ echo "\n";
468
+ }
469
+
470
+ /**
471
+ * Get the current action selected from the bulk actions dropdown.
472
+ *
473
+ * @since 3.1.0
474
+ *
475
+ * @return string|false The action name or False if no action was selected
476
+ */
477
+ public function current_action() {
478
+ if ( isset( $_REQUEST['filter_action'] ) && ! empty( $_REQUEST['filter_action'] ) ) {
479
+ return false;
480
+ }
481
+
482
+ if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] ) {
483
+ return $_REQUEST['action'];
484
+ }
485
+
486
+ if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] ) {
487
+ return $_REQUEST['action2'];
488
+ }
489
+
490
+ return false;
491
+ }
492
+
493
+ /**
494
+ * Generate row actions div
495
+ *
496
+ * @since 3.1.0
497
+ *
498
+ * @param array $actions The list of actions
499
+ * @param bool $always_visible Whether the actions should be always visible
500
+ * @return string
501
+ */
502
+ protected function row_actions( $actions, $always_visible = false ) {
503
+ $action_count = count( $actions );
504
+ $i = 0;
505
+
506
+ if ( ! $action_count ) {
507
+ return '';
508
+ }
509
+
510
+ $out = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';
511
+ foreach ( $actions as $action => $link ) {
512
+ ++$i;
513
+ ( $i == $action_count ) ? $sep = '' : $sep = ' | ';
514
+ $out .= "<span class='$action'>$link$sep</span>";
515
+ }
516
+ $out .= '</div>';
517
+
518
+ $out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>';
519
+
520
+ return $out;
521
+ }
522
+
523
+ /**
524
+ * Display a monthly dropdown for filtering items
525
+ *
526
+ * @since 3.1.0
527
+ *
528
+ * @global wpdb $wpdb
529
+ * @global WP_Locale $wp_locale
530
+ *
531
+ * @param string $post_type
532
+ */
533
+ protected function months_dropdown( $post_type ) {
534
+ global $wpdb, $wp_locale;
535
+
536
+ /**
537
+ * Filters whether to remove the 'Months' drop-down from the post list table.
538
+ *
539
+ * @since 4.2.0
540
+ *
541
+ * @param bool $disable Whether to disable the drop-down. Default false.
542
+ * @param string $post_type The post type.
543
+ */
544
+ if ( apply_filters( 'disable_months_dropdown', false, $post_type ) ) {
545
+ return;
546
+ }
547
+
548
+ $extra_checks = "AND post_status != 'auto-draft'";
549
+ if ( ! isset( $_GET['post_status'] ) || 'trash' !== $_GET['post_status'] ) {
550
+ $extra_checks .= " AND post_status != 'trash'";
551
+ } elseif ( isset( $_GET['post_status'] ) ) {
552
+ $extra_checks = $wpdb->prepare( ' AND post_status = %s', $_GET['post_status'] );
553
+ }
554
+
555
+ $months = $wpdb->get_results(
556
+ $wpdb->prepare(
557
+ "
558
+ SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
559
+ FROM $wpdb->posts
560
+ WHERE post_type = %s
561
+ $extra_checks
562
+ ORDER BY post_date DESC
563
+ ", $post_type
564
+ )
565
+ );
566
+
567
+ /**
568
+ * Filters the 'Months' drop-down results.
569
+ *
570
+ * @since 3.7.0
571
+ *
572
+ * @param object $months The months drop-down query results.
573
+ * @param string $post_type The post type.
574
+ */
575
+ $months = apply_filters( 'months_dropdown_results', $months, $post_type );
576
+
577
+ $month_count = count( $months );
578
+
579
+ if ( ! $month_count || ( 1 == $month_count && 0 == $months[0]->month ) ) {
580
+ return;
581
+ }
582
+
583
+ $m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
584
+ ?>
585
+ <label for="filter-by-date" class="screen-reader-text"><?php _e( 'Filter by date' ); ?></label>
586
+ <select name="m" id="filter-by-date">
587
+ <option<?php selected( $m, 0 ); ?> value="0"><?php _e( 'All dates' ); ?></option>
588
+ <?php
589
+ foreach ( $months as $arc_row ) {
590
+ if ( 0 == $arc_row->year ) {
591
+ continue;
592
+ }
593
+
594
+ $month = zeroise( $arc_row->month, 2 );
595
+ $year = $arc_row->year;
596
+
597
+ printf(
598
+ "<option %s value='%s'>%s</option>\n",
599
+ selected( $m, $year . $month, false ),
600
+ esc_attr( $arc_row->year . $month ),
601
+ /* translators: 1: month name, 2: 4-digit year */
602
+ sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year )
603
+ );
604
+ }
605
+ ?>
606
+ </select>
607
+ <?php
608
+ }
609
+
610
+ /**
611
+ * Display a view switcher
612
+ *
613
+ * @since 3.1.0
614
+ *
615
+ * @param string $current_mode
616
+ */
617
+ protected function view_switcher( $current_mode ) {
618
+ ?>
619
+ <input type="hidden" name="mode" value="<?php echo esc_attr( $current_mode ); ?>" />
620
+ <div class="view-switch">
621
+ <?php
622
+ foreach ( $this->modes as $mode => $title ) {
623
+ $classes = array( 'view-' . $mode );
624
+ if ( $current_mode === $mode ) {
625
+ $classes[] = 'current';
626
+ }
627
+ printf(
628
+ "<a href='%s' class='%s' id='view-switch-$mode'><span class='screen-reader-text'>%s</span></a>\n",
629
+ esc_url( add_query_arg( 'mode', $mode ) ),
630
+ implode( ' ', $classes ),
631
+ $title
632
+ );
633
+ }
634
+ ?>
635
+ </div>
636
+ <?php
637
+ }
638
+
639
+ /**
640
+ * Display a comment count bubble
641
+ *
642
+ * @since 3.1.0
643
+ *
644
+ * @param int $post_id The post ID.
645
+ * @param int $pending_comments Number of pending comments.
646
+ */
647
+ protected function comments_bubble( $post_id, $pending_comments ) {
648
+ $approved_comments = get_comments_number();
649
+
650
+ $approved_comments_number = number_format_i18n( $approved_comments );
651
+ $pending_comments_number = number_format_i18n( $pending_comments );
652
+
653
+ $approved_only_phrase = sprintf( _n( '%s comment', '%s comments', $approved_comments ), $approved_comments_number );
654
+ $approved_phrase = sprintf( _n( '%s approved comment', '%s approved comments', $approved_comments ), $approved_comments_number );
655
+ $pending_phrase = sprintf( _n( '%s pending comment', '%s pending comments', $pending_comments ), $pending_comments_number );
656
+
657
+ // No comments at all.
658
+ if ( ! $approved_comments && ! $pending_comments ) {
659
+ printf(
660
+ '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">%s</span>',
661
+ __( 'No comments' )
662
+ );
663
+ // Approved comments have different display depending on some conditions.
664
+ } elseif ( $approved_comments ) {
665
+ printf(
666
+ '<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>',
667
+ esc_url(
668
+ add_query_arg(
669
+ array(
670
+ 'p' => $post_id,
671
+ 'comment_status' => 'approved',
672
+ ), admin_url( 'edit-comments.php' )
673
+ )
674
+ ),
675
+ $approved_comments_number,
676
+ $pending_comments ? $approved_phrase : $approved_only_phrase
677
+ );
678
+ } else {
679
+ printf(
680
+ '<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>',
681
+ $approved_comments_number,
682
+ $pending_comments ? __( 'No approved comments' ) : __( 'No comments' )
683
+ );
684
+ }
685
+
686
+ if ( $pending_comments ) {
687
+ printf(
688
+ '<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>',
689
+ esc_url(
690
+ add_query_arg(
691
+ array(
692
+ 'p' => $post_id,
693
+ 'comment_status' => 'moderated',
694
+ ), admin_url( 'edit-comments.php' )
695
+ )
696
+ ),
697
+ $pending_comments_number,
698
+ $pending_phrase
699
+ );
700
+ } else {
701
+ printf(
702
+ '<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>',
703
+ $pending_comments_number,
704
+ $approved_comments ? __( 'No pending comments' ) : __( 'No comments' )
705
+ );
706
+ }
707
+ }
708
+
709
+ /**
710
+ * Get the current page number
711
+ *
712
+ * @since 3.1.0
713
+ *
714
+ * @return int
715
+ */
716
+ public function get_pagenum() {
717
+ $pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0;
718
+
719
+ if ( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] ) {
720
+ $pagenum = $this->_pagination_args['total_pages'];
721
+ }
722
+
723
+ return max( 1, $pagenum );
724
+ }
725
+
726
+ /**
727
+ * Get number of items to display on a single page
728
+ *
729
+ * @since 3.1.0
730
+ *
731
+ * @param string $option
732
+ * @param int $default
733
+ * @return int
734
+ */
735
+ protected function get_items_per_page( $option, $default = 20 ) {
736
+ $per_page = (int) get_user_option( $option );
737
+ if ( empty( $per_page ) || $per_page < 1 ) {
738
+ $per_page = $default;
739
+ }
740
+
741
+ /**
742
+ * Filters the number of items to be displayed on each page of the list table.
743
+ *
744
+ * The dynamic hook name, $option, refers to the `per_page` option depending
745
+ * on the type of list table in use. Possible values include: 'edit_comments_per_page',
746
+ * 'sites_network_per_page', 'site_themes_network_per_page', 'themes_network_per_page',
747
+ * 'users_network_per_page', 'edit_post_per_page', 'edit_page_per_page',
748
+ * 'edit_{$post_type}_per_page', etc.
749
+ *
750
+ * @since 2.9.0
751
+ *
752
+ * @param int $per_page Number of items to be displayed. Default 20.
753
+ */
754
+ return (int) apply_filters( "{$option}", $per_page );
755
+ }
756
+
757
+ /**
758
+ * Display the pagination.
759
+ *
760
+ * @since 3.1.0
761
+ *
762
+ * @param string $which
763
+ */
764
+ protected function pagination( $which ) {
765
+ if ( empty( $this->_pagination_args ) ) {
766
+ return;
767
+ }
768
+
769
+ $total_items = $this->_pagination_args['total_items'];
770
+ $total_pages = $this->_pagination_args['total_pages'];
771
+ $infinite_scroll = false;
772
+ if ( isset( $this->_pagination_args['infinite_scroll'] ) ) {
773
+ $infinite_scroll = $this->_pagination_args['infinite_scroll'];
774
+ }
775
+
776
+ if ( 'top' === $which && $total_pages > 1 ) {
777
+ $this->screen->render_screen_reader_content( 'heading_pagination' );
778
+ }
779
+
780
+ $output = '<span class="displaying-num">' . sprintf( _n( '%s item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . '</span>';
781
+
782
+ $current = $this->get_pagenum();
783
+ $removable_query_args = wp_removable_query_args();
784
+
785
+ $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
786
+
787
+ $current_url = remove_query_arg( $removable_query_args, $current_url );
788
+
789
+ $page_links = array();
790
+
791
+ $total_pages_before = '<span class="paging-input">';
792
+ $total_pages_after = '</span></span>';
793
+
794
+ $disable_first = $disable_last = $disable_prev = $disable_next = false;
795
+
796
+ if ( $current == 1 ) {
797
+ $disable_first = true;
798
+ $disable_prev = true;
799
+ }
800
+ if ( $current == 2 ) {
801
+ $disable_first = true;
802
+ }
803
+ if ( $current == $total_pages ) {
804
+ $disable_last = true;
805
+ $disable_next = true;
806
+ }
807
+ if ( $current == $total_pages - 1 ) {
808
+ $disable_last = true;
809
+ }
810
+
811
+ if ( $disable_first ) {
812
+ $page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&laquo;</span>';
813
+ } else {
814
+ $page_links[] = sprintf(
815
+ "<a class='first-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
816
+ esc_url( remove_query_arg( 'paged', $current_url ) ),
817
+ __( 'First page' ),
818
+ '&laquo;'
819
+ );
820
+ }
821
+
822
+ if ( $disable_prev ) {
823
+ $page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&lsaquo;</span>';
824
+ } else {
825
+ $page_links[] = sprintf(
826
+ "<a class='prev-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
827
+ esc_url( add_query_arg( 'paged', max( 1, $current - 1 ), $current_url ) ),
828
+ __( 'Previous page' ),
829
+ '&lsaquo;'
830
+ );
831
+ }
832
+
833
+ if ( 'bottom' === $which ) {
834
+ $html_current_page = $current;
835
+ $total_pages_before = '<span class="screen-reader-text">' . __( 'Current Page' ) . '</span><span id="table-paging" class="paging-input"><span class="tablenav-paging-text">';
836
+ } else {
837
+ $html_current_page = sprintf(
838
+ "%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'>",
839
+ '<label for="current-page-selector" class="screen-reader-text">' . __( 'Current Page' ) . '</label>',
840
+ $current,
841
+ strlen( $total_pages )
842
+ );
843
+ }
844
+ $html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
845
+ $page_links[] = $total_pages_before . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . $total_pages_after;
846
+
847
+ if ( $disable_next ) {
848
+ $page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&rsaquo;</span>';
849
+ } else {
850
+ $page_links[] = sprintf(
851
+ "<a class='next-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
852
+ esc_url( add_query_arg( 'paged', min( $total_pages, $current + 1 ), $current_url ) ),
853
+ __( 'Next page' ),
854
+ '&rsaquo;'
855
+ );
856
+ }
857
+
858
+ if ( $disable_last ) {
859
+ $page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&raquo;</span>';
860
+ } else {
861
+ $page_links[] = sprintf(
862
+ "<a class='last-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
863
+ esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
864
+ __( 'Last page' ),
865
+ '&raquo;'
866
+ );
867
+ }
868
+
869
+ $pagination_links_class = 'pagination-links';
870
+ if ( ! empty( $infinite_scroll ) ) {
871
+ $pagination_links_class .= ' hide-if-js';
872
+ }
873
+ $output .= "\n<span class='$pagination_links_class'>" . join( "\n", $page_links ) . '</span>';
874
+
875
+ if ( $total_pages ) {
876
+ $page_class = $total_pages < 2 ? ' one-page' : '';
877
+ } else {
878
+ $page_class = ' no-pages';
879
+ }
880
+ $this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";
881
+
882
+ echo $this->_pagination;
883
+ }
884
+
885
+ /**
886
+ * Get a list of columns. The format is:
887
+ * 'internal-name' => 'Title'
888
+ *
889
+ * @since 3.1.0
890
+ * @abstract
891
+ *
892
+ * @return array
893
+ */
894
+ public function get_columns() {
895
+ die( 'function WP_List_Table::get_columns() must be over-ridden in a sub-class.' );
896
+ }
897
+
898
+ /**
899
+ * Get a list of sortable columns. The format is:
900
+ * 'internal-name' => 'orderby'
901
+ * or
902
+ * 'internal-name' => array( 'orderby', true )
903
+ *
904
+ * The second format will make the initial sorting order be descending
905
+ *
906
+ * @since 3.1.0
907
+ *
908
+ * @return array
909
+ */
910
+ protected function get_sortable_columns() {
911
+ return array();
912
+ }
913
+
914
+ /**
915
+ * Gets the name of the default primary column.
916
+ *
917
+ * @since 4.3.0
918
+ *
919
+ * @return string Name of the default primary column, in this case, an empty string.
920
+ */
921
+ protected function get_default_primary_column_name() {
922
+ $columns = $this->get_columns();
923
+ $column = '';
924
+
925
+ if ( empty( $columns ) ) {
926
+ return $column;
927
+ }
928
+
929
+ // We need a primary defined so responsive views show something,
930
+ // so let's fall back to the first non-checkbox column.
931
+ foreach ( $columns as $col => $column_name ) {
932
+ if ( 'cb' === $col ) {
933
+ continue;
934
+ }
935
+
936
+ $column = $col;
937
+ break;
938
+ }
939
+
940
+ return $column;
941
+ }
942
+
943
+ /**
944
+ * Public wrapper for WP_List_Table::get_default_primary_column_name().
945
+ *
946
+ * @since 4.4.0
947
+ *
948
+ * @return string Name of the default primary column.
949
+ */
950
+ public function get_primary_column() {
951
+ return $this->get_primary_column_name();
952
+ }
953
+
954
+ /**
955
+ * Gets the name of the primary column.
956
+ *
957
+ * @since 4.3.0
958
+ *
959
+ * @return string The name of the primary column.
960
+ */
961
+ protected function get_primary_column_name() {
962
+ $columns = get_column_headers( $this->screen );
963
+ $default = $this->get_default_primary_column_name();
964
+
965
+ // If the primary column doesn't exist fall back to the
966
+ // first non-checkbox column.
967
+ if ( ! isset( $columns[ $default ] ) ) {
968
+ $default = YASR_WP_List_Table::get_default_primary_column_name();
969
+ }
970
+
971
+ /**
972
+ * Filters the name of the primary column for the current list table.
973
+ *
974
+ * @since 4.3.0
975
+ *
976
+ * @param string $default Column name default for the specific list table, e.g. 'name'.
977
+ * @param string $context Screen ID for specific list table, e.g. 'plugins'.
978
+ */
979
+ $column = apply_filters( 'list_table_primary_column', $default, $this->screen->id );
980
+
981
+ if ( empty( $column ) || ! isset( $columns[ $column ] ) ) {
982
+ $column = $default;
983
+ }
984
+
985
+ return $column;
986
+ }
987
+
988
+ /**
989
+ * Get a list of all, hidden and sortable columns, with filter applied
990
+ *
991
+ * @since 3.1.0
992
+ *
993
+ * @return array
994
+ */
995
+ protected function get_column_info() {
996
+ // $_column_headers is already set / cached
997
+ if ( isset( $this->_column_headers ) && is_array( $this->_column_headers ) ) {
998
+ // Back-compat for list tables that have been manually setting $_column_headers for horse reasons.
999
+ // In 4.3, we added a fourth argument for primary column.
1000
+ $column_headers = array( array(), array(), array(), $this->get_primary_column_name() );
1001
+ foreach ( $this->_column_headers as $key => $value ) {
1002
+ $column_headers[ $key ] = $value;
1003
+ }
1004
+
1005
+ return $column_headers;
1006
+ }
1007
+
1008
+ $columns = get_column_headers( $this->screen );
1009
+ $hidden = get_hidden_columns( $this->screen );
1010
+
1011
+ $sortable_columns = $this->get_sortable_columns();
1012
+ /**
1013
+ * Filters the list table sortable columns for a specific screen.
1014
+ *
1015
+ * The dynamic portion of the hook name, `$this->screen->id`, refers
1016
+ * to the ID of the current screen, usually a string.
1017
+ *
1018
+ * @since 3.5.0
1019
+ *
1020
+ * @param array $sortable_columns An array of sortable columns.
1021
+ */
1022
+ $_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $sortable_columns );
1023
+
1024
+ $sortable = array();
1025
+ foreach ( $_sortable as $id => $data ) {
1026
+ if ( empty( $data ) ) {
1027
+ continue;
1028
+ }
1029
+
1030
+ $data = (array) $data;
1031
+ if ( ! isset( $data[1] ) ) {
1032
+ $data[1] = false;
1033
+ }
1034
+
1035
+ $sortable[ $id ] = $data;
1036
+ }
1037
+
1038
+ $primary = $this->get_primary_column_name();
1039
+ $this->_column_headers = array( $columns, $hidden, $sortable, $primary );
1040
+
1041
+ return $this->_column_headers;
1042
+ }
1043
+
1044
+ /**
1045
+ * Return number of visible columns
1046
+ *
1047
+ * @since 3.1.0
1048
+ *
1049
+ * @return int
1050
+ */
1051
+ public function get_column_count() {
1052
+ list ( $columns, $hidden ) = $this->get_column_info();
1053
+ $hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) );
1054
+ return count( $columns ) - count( $hidden );
1055
+ }
1056
+
1057
+ /**
1058
+ * Print column headers, accounting for hidden and sortable columns.
1059
+ *
1060
+ * @since 3.1.0
1061
+ *
1062
+ * @staticvar int $cb_counter
1063
+ *
1064
+ * @param bool $with_id Whether to set the id attribute or not
1065
+ */
1066
+ public function print_column_headers( $with_id = true ) {
1067
+ list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
1068
+
1069
+ $current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
1070
+ $current_url = remove_query_arg( 'paged', $current_url );
1071
+
1072
+ if ( isset( $_GET['orderby'] ) ) {
1073
+ $current_orderby = $_GET['orderby'];
1074
+ } else {
1075
+ $current_orderby = '';
1076
+ }
1077
+
1078
+ if ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) {
1079
+ $current_order = 'desc';
1080
+ } else {
1081
+ $current_order = 'asc';
1082
+ }
1083
+
1084
+ if ( ! empty( $columns['cb'] ) ) {
1085
+ static $cb_counter = 1;
1086
+ $columns['cb'] = '<label class="screen-reader-text" for="cb-select-all-' . $cb_counter . '">' . __( 'Select All' ) . '</label>'
1087
+ . '<input id="cb-select-all-' . $cb_counter . '" type="checkbox" />';
1088
+ $cb_counter++;
1089
+ }
1090
+
1091
+ foreach ( $columns as $column_key => $column_display_name ) {
1092
+ $class = array( 'manage-column', "column-$column_key" );
1093
+
1094
+ if ( in_array( $column_key, $hidden ) ) {
1095
+ $class[] = 'hidden';
1096
+ }
1097
+
1098
+ if ( 'cb' === $column_key ) {
1099
+ $class[] = 'check-column';
1100
+ } elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) ) {
1101
+ $class[] = 'num';
1102
+ }
1103
+
1104
+ if ( $column_key === $primary ) {
1105
+ $class[] = 'column-primary';
1106
+ }
1107
+
1108
+ if ( isset( $sortable[ $column_key ] ) ) {
1109
+ list( $orderby, $desc_first ) = $sortable[ $column_key ];
1110
+
1111
+ if ( $current_orderby === $orderby ) {
1112
+ $order = 'asc' === $current_order ? 'desc' : 'asc';
1113
+ $class[] = 'sorted';
1114
+ $class[] = $current_order;
1115
+ } else {
1116
+ $order = $desc_first ? 'desc' : 'asc';
1117
+ $class[] = 'sortable';
1118
+ $class[] = $desc_first ? 'asc' : 'desc';
1119
+ }
1120
+
1121
+ $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>';
1122
+ }
1123
+
1124
+ $tag = ( 'cb' === $column_key ) ? 'td' : 'th';
1125
+ $scope = ( 'th' === $tag ) ? 'scope="col"' : '';
1126
+ $id = $with_id ? "id='$column_key'" : '';
1127
+
1128
+ if ( ! empty( $class ) ) {
1129
+ $class = "class='" . join( ' ', $class ) . "'";
1130
+ }
1131
+
1132
+ echo "<$tag $scope $id $class>$column_display_name</$tag>";
1133
+ }
1134
+ }
1135
+
1136
+ /**
1137
+ * Display the table
1138
+ *
1139
+ * @since 3.1.0
1140
+ */
1141
+ public function display() {
1142
+ $singular = $this->_args['singular'];
1143
+
1144
+ $this->display_tablenav( 'top' );
1145
+
1146
+ $this->screen->render_screen_reader_content( 'heading_list' );
1147
+ ?>
1148
+ <table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
1149
+ <thead>
1150
+ <tr>
1151
+ <?php $this->print_column_headers(); ?>
1152
+ </tr>
1153
+ </thead>
1154
+
1155
+ <tbody id="the-list"
1156
+ <?php
1157
+ if ( $singular ) {
1158
+ echo " data-wp-lists='list:$singular'";
1159
+ }
1160
+ ?>
1161
+ >
1162
+ <?php $this->display_rows_or_placeholder(); ?>
1163
+ </tbody>
1164
+
1165
+ <tfoot>
1166
+ <tr>
1167
+ <?php $this->print_column_headers( false ); ?>
1168
+ </tr>
1169
+ </tfoot>
1170
+
1171
+ </table>
1172
+ <?php
1173
+ $this->display_tablenav( 'bottom' );
1174
+ }
1175
+
1176
+ /**
1177
+ * Get a list of CSS classes for the WP_List_Table table tag.
1178
+ *
1179
+ * @since 3.1.0
1180
+ *
1181
+ * @return array List of CSS classes for the table tag.
1182
+ */
1183
+ protected function get_table_classes() {
1184
+ return array( 'widefat', 'fixed', 'striped', $this->_args['plural'] );
1185
+ }
1186
+
1187
+ /**
1188
+ * Generate the table navigation above or below the table
1189
+ *
1190
+ * @since 3.1.0
1191
+ * @param string $which
1192
+ */
1193
+ protected function display_tablenav( $which ) {
1194
+ if ( 'top' === $which ) {
1195
+ wp_nonce_field( 'bulk-' . $this->_args['plural'] );
1196
+ }
1197
+ ?>
1198
+ <div class="tablenav <?php echo esc_attr( $which ); ?>">
1199
+
1200
+ <?php if ( $this->has_items() ) : ?>
1201
+ <div class="alignleft actions bulkactions">
1202
+ <?php $this->bulk_actions( $which ); ?>
1203
+ </div>
1204
+ <?php
1205
+ endif;
1206
+ $this->extra_tablenav( $which );
1207
+ $this->pagination( $which );
1208
+ ?>
1209
+
1210
+ <br class="clear" />
1211
+ </div>
1212
+ <?php
1213
+ }
1214
+
1215
+ /**
1216
+ * Extra controls to be displayed between bulk actions and pagination
1217
+ *
1218
+ * @since 3.1.0
1219
+ *
1220
+ * @param string $which
1221
+ */
1222
+ protected function extra_tablenav( $which ) {}
1223
+
1224
+ /**
1225
+ * Generate the tbody element for the list table.
1226
+ *
1227
+ * @since 3.1.0
1228
+ */
1229
+ public function display_rows_or_placeholder() {
1230
+ if ( $this->has_items() ) {
1231
+ $this->display_rows();
1232
+ } else {
1233
+ echo '<tr class="no-items"><td class="colspanchange" colspan="' . $this->get_column_count() . '">';
1234
+ $this->no_items();
1235
+ echo '</td></tr>';
1236
+ }
1237
+ }
1238
+
1239
+ /**
1240
+ * Generate the table rows
1241
+ *
1242
+ * @since 3.1.0
1243
+ */
1244
+ public function display_rows() {
1245
+ foreach ( $this->items as $item ) {
1246
+ $this->single_row( $item );
1247
+ }
1248
+ }
1249
+
1250
+ /**
1251
+ * Generates content for a single row of the table
1252
+ *
1253
+ * @since 3.1.0
1254
+ *
1255
+ * @param object $item The current item
1256
+ */
1257
+ public function single_row( $item ) {
1258
+ echo '<tr>';
1259
+ $this->single_row_columns( $item );
1260
+ echo '</tr>';
1261
+ }
1262
+
1263
+ /**
1264
+ * @param object $item
1265
+ * @param string $column_name
1266
+ */
1267
+ protected function column_default( $item, $column_name ) {}
1268
+
1269
+ /**
1270
+ * @param object $item
1271
+ */
1272
+ protected function column_cb( $item ) {}
1273
+
1274
+ /**
1275
+ * Generates the columns for a single row of the table
1276
+ *
1277
+ * @since 3.1.0
1278
+ *
1279
+ * @param object $item The current item
1280
+ */
1281
+ protected function single_row_columns( $item ) {
1282
+ list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
1283
+
1284
+ foreach ( $columns as $column_name => $column_display_name ) {
1285
+ $classes = "$column_name column-$column_name";
1286
+ if ( $primary === $column_name ) {
1287
+ $classes .= ' has-row-actions column-primary';
1288
+ }
1289
+
1290
+ if ( in_array( $column_name, $hidden ) ) {
1291
+ $classes .= ' hidden';
1292
+ }
1293
+
1294
+ // Comments column uses HTML in the display name with screen reader text.
1295
+ // Instead of using esc_attr(), we strip tags to get closer to a user-friendly string.
1296
+ $data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"';
1297
+
1298
+ $attributes = "class='$classes' $data";
1299
+
1300
+ if ( 'cb' === $column_name ) {
1301
+ echo '<th scope="row" class="check-column">';
1302
+ echo $this->column_cb( $item );
1303
+ echo '</th>';
1304
+ } elseif ( method_exists( $this, '_column_' . $column_name ) ) {
1305
+ echo call_user_func(
1306
+ array( $this, '_column_' . $column_name ),
1307
+ $item,
1308
+ $classes,
1309
+ $data,
1310
+ $primary
1311
+ );
1312
+ } elseif ( method_exists( $this, 'column_' . $column_name ) ) {
1313
+ echo "<td $attributes>";
1314
+ echo call_user_func( array( $this, 'column_' . $column_name ), $item );
1315
+ echo $this->handle_row_actions( $item, $column_name, $primary );
1316
+ echo '</td>';
1317
+ } else {
1318
+ echo "<td $attributes>";
1319
+ echo $this->column_default( $item, $column_name );
1320
+ echo $this->handle_row_actions( $item, $column_name, $primary );
1321
+ echo '</td>';
1322
+ }
1323
+ }
1324
+ }
1325
+
1326
+ /**
1327
+ * Generates and display row actions links for the list table.
1328
+ *
1329
+ * @since 4.3.0
1330
+ *
1331
+ * @param object $item The item being acted upon.
1332
+ * @param string $column_name Current column name.
1333
+ * @param string $primary Primary column name.
1334
+ * @return string The row actions HTML, or an empty string if the current column is the primary column.
1335
+ */
1336
+ protected function handle_row_actions( $item, $column_name, $primary ) {
1337
+ return $column_name === $primary ? '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>' : '';
1338
+ }
1339
+
1340
+ /**
1341
+ * Handle an incoming ajax request (called from admin-ajax.php)
1342
+ *
1343
+ * @since 3.1.0
1344
+ */
1345
+ public function ajax_response() {
1346
+ $this->prepare_items();
1347
+
1348
+ ob_start();
1349
+ if ( ! empty( $_REQUEST['no_placeholder'] ) ) {
1350
+ $this->display_rows();
1351
+ } else {
1352
+ $this->display_rows_or_placeholder();
1353
+ }
1354
+
1355
+ $rows = ob_get_clean();
1356
+
1357
+ $response = array( 'rows' => $rows );
1358
+
1359
+ if ( isset( $this->_pagination_args['total_items'] ) ) {
1360
+ $response['total_items_i18n'] = sprintf(
1361
+ _n( '%s item', '%s items', $this->_pagination_args['total_items'] ),
1362
+ number_format_i18n( $this->_pagination_args['total_items'] )
1363
+ );
1364
+ }
1365
+ if ( isset( $this->_pagination_args['total_pages'] ) ) {
1366
+ $response['total_pages'] = $this->_pagination_args['total_pages'];
1367
+ $response['total_pages_i18n'] = number_format_i18n( $this->_pagination_args['total_pages'] );
1368
+ }
1369
+
1370
+ die( wp_json_encode( $response ) );
1371
+ }
1372
+
1373
+ /**
1374
+ * Send required variables to JavaScript land
1375
+ */
1376
+ public function _js_vars() {
1377
+ $args = array(
1378
+ 'class' => get_class( $this ),
1379
+ 'screen' => array(
1380
+ 'id' => $this->screen->id,
1381
+ 'base' => $this->screen->base,
1382
+ ),
1383
+ );
1384
+
1385
+ printf( "<script type='text/javascript'>list_args = %s;</script>\n", wp_json_encode( $args ) );
1386
+ }
1387
+ }
lib/yasr-functions.php CHANGED
@@ -203,35 +203,61 @@ function yasr_css_stars_set() {
203
204
/****** Create a new Page in Administration Menu ******/
205
206
- /* Hook to admin_menu the yasr_add_pages function above */
207
- add_action( 'admin_menu', 'yasr_add_pages' );
208
209
- function yasr_add_pages() {
210
211
- global $yasr_settings_page;
212
213
- //Add Settings Page
214
- $yasr_settings_page = add_options_page(
215
- __( 'Yet Another Stars Rating: Settings', 'yet-another-stars-rating' ), //Page Title
216
- __( 'Yet Another Stars Rating: Settings', 'yet-another-stars-rating' ), //Menu Title
217
- 'manage_options', //capability
218
- 'yasr_settings_page', //menu slug
219
- 'yasr_settings_page_callback' //The function to be called to output the content for this page.
220
- );
221
- }
222
223
224
- // Settings Page Content
225
- function yasr_settings_page_callback () {
226
227
- if ( ! current_user_can( 'manage_options' ) ) {
228
- wp_die( __( 'You do not have sufficient permissions to access this page.', 'yet-another-stars-rating' ) );
229
- }
230
231
- include(YASR_ABSOLUTE_PATH . '/yasr-settings-page.php');
232
233
- } //End yasr_settings_page_content
234
235
236
237
/****** Create 2 metaboxes in post and pages ******/
203
204
/****** Create a new Page in Administration Menu ******/
205
206
+ /* Hook to admin_menu the yasr_add_pages function above */
207
+ add_action( 'admin_menu', 'yasr_add_pages' );
208
209
+ function yasr_add_pages() {
210
211
+ global $yasr_settings_page;
212
213
+ //Add Settings Page
214
+ $yasr_settings_page = add_menu_page(
215
+ __( 'Yet Another Stars Rating: settings', 'yet-another-stars-rating' ), //Page Title
216
+ __( 'Yet Another Stars Rating', 'yet-another-stars-rating' ), //Menu Title
217
+ 'manage_options', //capability
218
+ 'yasr_settings_page', //menu slug
219
+ 'yasr_settings_page_callback', //The function to be called to output the content for this page.
220
+ 'dashicons-star-filled'
221
+ );
222
+
223
+ add_submenu_page('yasr_settings_page',
224
+ 'Yet Another Stars Rating: settings',
225
+ 'Settings',
226
+ 'manage_options',
227
+ 'yasr_settings_page'
228
+ );
229
230
+ add_submenu_page('yasr_settings_page',
231
+ 'Yet Another Stars Rating: All Rating',
232
+ 'Logs',
233
+ 'manage_options',
234
+ 'yasr_stats_page',
235
+ 'yasr_stats_page_callback'
236
+ );
237
+ }
238
239
240
+ // Settings Page Content
241
+ function yasr_settings_page_callback () {
242
+
243
+ if ( ! current_user_can( 'manage_options' ) ) {
244
+ wp_die( __( 'You do not have sufficient permissions to access this page.', 'yet-another-stars-rating' ) );
245
+ }
246
+
247
+ include(YASR_ABSOLUTE_PATH . '/yasr-settings-page.php');
248
+
249
+ } //End yasr_settings_page_content
250
251
252
+ function yasr_stats_page_callback () {
253
254
+ if ( ! current_user_can( 'manage_options' ) ) {
255
+ wp_die( __( 'You do not have sufficient permissions to access this page.', 'yet-another-stars-rating' ) );
256
+ }
257
+
258
+ include( YASR_ABSOLUTE_PATH . '/yasr-stats-page.php' );
259
+
260
+ }
261
262
263
/****** Create 2 metaboxes in post and pages ******/
lib/yasr-stats-functions.php ADDED
@@ -0,0 +1,262 @@
1
+ <?php
2
+
3
+ /*
4
+
5
+ Copyright 2014 Dario Curvino (email : d.curvino@tiscali.it)
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 2 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see <http://www.gnu.org/licenses/>
19
+ */
20
+
21
+ if ( ! defined( 'ABSPATH' ) ) exit('You\'re not allowed to see this page'); // Exit if accessed directly
22
+
23
+ function yasr_stats_tabs($active_tab) {
24
+
25
+ ?>
26
+
27
+ <h2 class="nav-tab-wrapper yasr-no-underline">
28
+
29
+ <a href="?page=yasr_stats_page&tab=logs" class="nav-tab <?php if ($active_tab === 'logs') echo 'nav-tab-active'; ?>" >
30
+ <?php _e("Logs", 'yet-another-stars-rating'); ?>
31
+ </a>
32
+ <?php do_action( 'yasr_add_stats_tab', $active_tab ); ?>
33
+ <a href="?page=yasr_settings_page&tab=extensions" class="nav-tab <?php if ($active_tab == 'extensions') echo 'nav-tab-active'; ?>" >
34
+ <?php _e("Extensions", 'yet-another-stars-rating'); ?> </a>
35
+
36
+ </a>
37
+
38
+
39
+ </h2>
40
+
41
+ <?php
42
+
43
+ }
44
+
45
+
46
+ /**
47
+ * Create a new table class that will extend the WP_List_Table
48
+ */
49
+ class YASR_Stats_Log_List_Table extends YASR_WP_List_Table
50
+ {
51
+ /**
52
+ * Prepare the items for the table to process
53
+ *
54
+ * @return Void
55
+ */
56
+ public function prepare_items()
57
+ {
58
+ $columns = $this->get_columns();
59
+ $hidden = $this->get_hidden_columns();
60
+ $sortable = $this->get_sortable_columns();
61
+
62
+ //print bulk_Actions
63
+ $this->get_bulk_actions();
64
+
65
+ $this->process_bulk_action();
66
+
67
+
68
+
69
+ global $wpdb;
70
+ $data = $wpdb->get_results ("SELECT * FROM ". YASR_LOG_TABLE . " ORDER BY date ASC", ARRAY_A);
71
+
72
+
73
+ usort( $data, array( &$this, 'sort_data' ) );
74
+
75
+ $perPage = 15;
76
+ $currentPage = $this->get_pagenum();
77
+ $totalItems = count($data);
78
+
79
+ $this->set_pagination_args( array(
80
+ 'total_items' => $totalItems,
81
+ 'per_page' => $perPage
82
+ ) );
83
+
84
+ $data = array_slice($data,(($currentPage-1)*$perPage),$perPage);
85
+
86
+ $this->_column_headers = array($columns, $hidden, $sortable);
87
+ $this->items = $data;
88
+
89
+ }
90
+
91
+ /**
92
+ * Override the parent columns method. Defines the columns to use in your listing table
93
+ *
94
+ * @return Array
95
+ */
96
+ public function get_columns()
97
+ {
98
+ $columns = array(
99
+ 'cb' => '<input type="checkbox" />',
100
+ 'id' => 'ID',
101
+ 'post_id' => 'Title',
102
+ 'multi_set_id' => 'Description',
103
+ 'user_id' => 'User ID',
104
+ 'vote' => 'Vote',
105
+ 'date' => 'Date',
106
+ 'ip' => 'IP',
107
+ );
108
+
109
+ return $columns;
110
+ }
111
+
112
+ /**
113
+ * Define which columns are hidden
114
+ *
115
+ * @return Array
116
+ */
117
+ public function get_hidden_columns()
118
+ {
119
+ return array('id', 'multi_set_id');
120
+ }
121
+
122
+ /**
123
+ * Define the sortable columns
124
+ *
125
+ * @return Array
126
+ */
127
+ public function get_sortable_columns()
128
+ {
129
+ return array(
130
+ 'user_id' => array('user_id', FALSE),
131
+ 'vote' => array('vote', FALSE),
132
+ 'date' => array('date', FALSE),
133
+ 'ip' => array('ip', FALSE)
134
+ );
135
+ }
136
+
137
+ /**
138
+ * Define what data to show on each column of the table
139
+ *
140
+ * @param Array $item Data
141
+ * @param String $column_name - Current column name
142
+ *
143
+ * @return Mixed
144
+ */
145
+ protected function column_default( $item, $column_name )
146
+ {
147
+
148
+ switch( $column_name ) {
149
+ case 'post_id':
150
+
151
+ $post_id = $item[$column_name];
152
+
153
+ $title_post = get_the_title( $post_id );
154
+ $link = get_permalink( $post_id );
155
+
156
+ $yasr_title_link = '<a href="'. $link .'">' . $title_post .'</a>';
157
+
158
+ return $yasr_title_link;
159
+
160
+ case 'user_id':
161
+
162
+ $user_id = $item[$column_name];
163
+
164
+ $user = get_user_by( 'id', $user_id );
165
+
166
+ //If ! user means that the vote are anonymous
167
+ if ($user == FALSE) {
168
+
169
+ $user = (object) array('user_login');
170
+ $user->user_login = __('anonymous');
171
+
172
+ }
173
+
174
+ return $user->user_login;
175
+
176
+ //All other columns must return their content
177
+ case 'vote':
178
+ case 'date':
179
+ case 'ip':
180
+ return $item[$column_name];
181
+
182
+ //default:
183
+ //return print_r($item) ;
184
+ }
185
+
186
+ }
187
+
188
+ /**
189
+ * Allows you to sort the data by the variables set in the $_GET
190
+ *
191
+ * @return Mixed
192
+ */
193
+ protected function sort_data( $a, $b ) {
194
+
195
+ // Set defaults (just need to avoid undefined variable at first load,
196
+ // it is already ordered with the query
197
+ $orderby = 'date';
198
+ $order = 'desc';
199
+
200
+ // If orderby is set, use this as the sort column
201
+ if(!empty($_GET['orderby']))
202
+ {
203
+ $orderby = $_GET['orderby'];
204
+ }
205
+
206
+ // If order is set use this as the order
207
+ if(!empty($_GET['order']))
208
+ {
209
+ $order = $_GET['order'];
210
+ }
211
+
212
+
213
+ $result = strcmp( $a[$orderby], $b[$orderby] );
214
+
215
+ if($order === 'asc')
216
+ {
217
+ return $result;
218
+ }
219
+
220
+ return -$result;
221
+ }
222
+
223
+
224
+ protected function get_bulk_actions() {
225
+ $actions = array(
226
+ 'delete' => 'Delete'
227
+ );
228
+ return $actions;
229
+ }
230
+
231
+ protected function column_cb( $item ) {
232
+
233
+ return sprintf(
234
+ "<input type='checkbox' name='yasr_logs_votes_to_delete[]' id='{$item['id']}' value='{$item['id']}' />"
235
+ );
236
+ }
237
+
238
+ //process bulk action
239
+ protected function process_bulk_action() {
240
+
241
+ if ($this->current_action() === 'delete') {
242
+
243
+ check_admin_referer( 'yasr-delete-stats-logs', 'yasr-nonce-delete-stats-logs' );
244
+
245
+ global $wpdb;
246
+
247
+ foreach ($_POST['yasr_logs_votes_to_delete'] as $log_id) {
248
+
249
+ $wpdb->delete(
250
+ YASR_LOG_TABLE,
251
+ array(
252
+ 'id' => $log_id
253
+ ),
254
+ array('%d')
255
+ );
256
+
257
+ }
258
+ }
259
+
260
+ }
261
+
262
+ }
readme.txt CHANGED
@@ -1,18 +1,19 @@
1
=== Yasr - Yet Another Stars Rating ===
2
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=AXE284FYMNWDC
3
- Tags: 5 star, admin, administrator, AJAX, five-star, javascript, jquery, post rating, posts, rate, rating, rating platform, rating system, ratings, review, reviews, rich snippets, seo, star, star rating, stars, vote, Votes, voting, voting contest, schema, serp
4
Requires at least: 4.3.0
5
Contributors: Dudo
6
- Tested up to: 4.9.4
7
- Stable tag: 1.5.7
8
License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
10
- Yet Another Stars Rating is a simple plugin which allows you and / or your visitor to rate a post or element. Ideal for review's website
11
-
12
== Description ==
13
- Yet Another Stars Rating (YASR) is a new system review based on jquery plugin RateIT.
14
- With YASR you can make your own review or let your visitors vote, and you can even create multiple sets (a set of stars for each aspect to
15
- rate). Review scores or visitor ratings will be indexed by search engines through snippets .
16
17
= How To use =
18
@@ -107,6 +108,10 @@ Of course not: you can easily add it on the visual editor just by clicking the "
107
108
The full changelog can be found in the plugin's directory. Recent entries:
109
110
= 1.5.7 =
111
* FIXED: star disappear after user rating in some circumstances
112
* FIXED: javascript noticies
@@ -130,58 +135,7 @@ The full changelog can be found in the plugin's directory. Recent entries:
130
= 1.5.1 =
131
* FIXED: when a post/page was removed from trash
132
133
- = 1.5.0 =
134
- * Updated rateit to version 1.1.0
135
-
136
- = 1.4.9 =
137
- * Added support to litespeed caching plugin (kudos to pako69)
138
-
139
- = 1.4.8 =
140
- * Minor changes (Thx to pako69)
141
-
142
- = 1.4.7 =
143
- * Removed freemius sdk.
144
-
145
- = 1.4.6 =
146
- * Jquery ui css is now loaded locally
147
-
148
- = 1.4.4 =
149
- * Added freemius sdk.
150
-
151
- = 1.4.3 =
152
- * If Blogposting is selected as itemtpye, and no featured image is set, use the logo url
153
-
154
- = 1.4.2 =
155
- * TWEAKED: progressbars and tooltip classes have been fixed
156
-
157
- = 1.4.1 =
158
- * TWEAKED: Yasr now supports ajax added content
159
- * TWEAKED: RateIt updated to version 1.0.24
160
-
161
- = 1.4.0 =
162
- * Fixed post title get echeod
163
-
164
- = 1.3.9 =
165
- * Dropped import support for old gd star
166
-
167
- = 1.3.8 =
168
- * FIXED: Shortcode creator finally works even in text mode
169
- * TWEAKED: Added a link to the settings in the plugin list under the plugin name
170
- * TWEAKED: minor changes
171
-
172
- = 1.3.7 =
173
- * FIXED: Rankings yasr_top_ten_highest_rated, yasr_most_or_highest_rated_posts and yasr_top_5_reviewers has been fixed (broken in version 1.3.6)
174
- * FIXED: js errors on yasr-front.js, thanks to jg88
175
-
176
- = 1.3.6 =
177
- * TWEAKED: yasr_visitor_votes doesn't use anymore yasr_votes table. It use only yasr_log instead. From this version, yasr_votes is not created anymore. If after this update everything is ok, if you wish you can drop yasr_votes table
178
- * TWEAKED: add the link to the post on yasr recent ratings widget
179
- * TWEAKED: huge code cleanup
180
181
- = 1.3.5 =
182
- * TWEAKED: READ CAREFULLY: this is the first step of an important yasr database change: the main goal is to switch from yasr_votes table to wordpress default post_meta.
183
- A database backup is strongly suggested.
184
- * NEW FEATURE: new widget that shows the last 5 recent ratings.
185
186
187
1
=== Yasr - Yet Another Stars Rating ===
2
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=AXE284FYMNWDC
3
+ Tags: ratings, rating, postrating, google rating, 5 star, review, reviews, star rating, vote, votes
4
Requires at least: 4.3.0
5
Contributors: Dudo
6
+ Tested up to: 4.9.5
7
+ Stable tag: 1.5.8
8
License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
10
== Description ==
11
+
12
+ Boost the way people interact with your website, e-commerce or blog with an easy and intuitive WordPress rating system!
13
+
14
+ Improving the user experience (UX) with your website is a top priority for everyone who cares about their online activity, as it promotes familiarity and loyalty with your brand, and enhances visibility of your activity.
15
+
16
+ Yasr - Yet Another Stars Rating is a powerful way to add SEO-friendly user-generated reviews and testimonials to your website posts, pages and CPC, without affecting its speed.
17
18
= How To use =
19
108
109
The full changelog can be found in the plugin's directory. Recent entries:
110
111
+ = 1.5.8 =
112
+ * NEW FEATURE: Logs Page: is now possible to see log page and delete user ratings!
113
+ * TWEAKED: Yasr settings page has now it's own top level page instead under the WordPress Settings section
114
+
115
= 1.5.7 =
116
* FIXED: star disappear after user rating in some circumstances
117
* FIXED: javascript noticies
135
= 1.5.1 =
136
* FIXED: when a post/page was removed from trash
137
138
139
140
141
yasr-stats-page.php ADDED
@@ -0,0 +1,105 @@
1
+ <?php
2
+
3
+ /*
4
+
5
+ Copyright 2014 Dario Curvino (email : d.curvino@tiscali.it)
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 2 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see <http://www.gnu.org/licenses/>
19
+ */
20
+
21
+ if ( ! defined( 'ABSPATH' ) ) exit('You\'re not allowed to see this page'); // Exit if accessed directly
22
+
23
+ if ( !current_user_can( 'manage_options' ) ) {
24
+ wp_die( __( 'You do not have sufficient permissions to access this page.', 'yet-another-stars-rating' ));
25
+ }
26
+
27
+ require (YASR_ABSOLUTE_PATH . '/lib/yasr-stats-functions.php');
28
+
29
+ $ajax_nonce_hide_ask_rating = wp_create_nonce( "yasr_nonce_hide_ask_rating" );
30
+
31
+ yasr_include_fb_sdk ();
32
+
33
+
34
+ ?>
35
+
36
+ <div class="wrap">
37
+
38
+ <h2>Yet Another Stars Rating: <?php _e("Logs", 'yet-another-stars-rating'); ?></h2>
39
+
40
+ <?php
41
+
42
+ if (isset($_GET['tab'])) {
43
+ $active_tab = $_GET[ 'tab' ];
44
+ }
45
+
46
+ else {
47
+ $active_tab = 'logs';
48
+ }
49
+
50
+ //Do the settings tab
51
+ yasr_stats_tabs($active_tab);
52
+
53
+ if ($active_tab == 'logs' || $active_tab == '') {
54
+
55
+ ?>
56
+
57
+ <div class="yasr-settingsdiv">
58
+ <form action="#" id="" method="POST">
59
+ <?php
60
+ wp_nonce_field( 'yasr-delete-stats-logs', 'yasr-nonce-delete-stats-logs' );
61
+ $yasr_stats_log_table = new YASR_Stats_Log_List_Table();
62
+ $yasr_stats_log_table->prepare_items();
63
+ $yasr_stats_log_table->display();
64
+ ?>
65
+ </form>
66
+ </div>
67
+
68
+ <?php
69
+
70
+ yasr_fb_box ();
71
+ yasr_ask_rating ();
72
+
73
+ ?>
74
+
75
+ <div class="yasr-space-settings-div">
76
+ </div>
77
+
78
+ <?php
79
+
80
+
81
+ } //End if tab 'general_settings'
82
+
83
+ do_action( 'yasr_settings_check_active_tab', $active_tab );
84
+
85
+
86
+ yasr_fb_box("bottom");
87
+ yasr_ask_rating ("bottom");
88
+
89
+ ?>
90
+
91
+ <!--End div wrap-->
92
+ </div>
93
+
94
+
95
+ <script type="text/javascript">
96
+
97
+ jQuery( document ).ready(function() {
98
+
99
+ var nonceHideAskRating = <?php echo (json_encode("$ajax_nonce_hide_ask_rating")); ?>
100
+
101
+ YasrAsk5Stars(nonceHideAskRating);
102
+
103
+ }); //End jquery document ready
104
+
105
+ </script>
yet-another-stars-rating.php CHANGED
@@ -3,7 +3,7 @@
3
* Plugin Name: Yet Another Stars Rating
4
* Plugin URI: http://wordpress.org/plugins/yet-another-stars-rating/
5
* Description: Yet Another Stars Rating turn your WordPress into a complete review website.
6
- * Version: 1.5.7
7
* Author: Dario Curvino
8
* Author URI: https://yetanotherstarsrating.com/
9
* Text Domain: yet-another-stars-rating
@@ -31,7 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
31
32
if ( ! defined( 'ABSPATH' ) ) exit('You\'re not allowed to see this page'); // Exit if accessed directly
33
34
- define('YASR_VERSION_NUM', '1.5.7');
35
36
//Plugin relative path
37
define( "YASR_ABSOLUTE_PATH", dirname(__FILE__) );
@@ -226,6 +226,12 @@ require (YASR_ABSOLUTE_PATH . '/lib/yasr-shortcode-functions.php');
226
227
require (YASR_ABSOLUTE_PATH . '/lib/yasr-widgets.php');
228
229
global $wpdb;
230
231
define ("YASR_VOTES_TABLE", $wpdb->prefix . 'yasr_votes'); //Used in background
3
* Plugin Name: Yet Another Stars Rating
4
* Plugin URI: http://wordpress.org/plugins/yet-another-stars-rating/
5
* Description: Yet Another Stars Rating turn your WordPress into a complete review website.
6
+ * Version: 1.5.8
7
* Author: Dario Curvino
8
* Author URI: https://yetanotherstarsrating.com/
9
* Text Domain: yet-another-stars-rating
31
32
if ( ! defined( 'ABSPATH' ) ) exit('You\'re not allowed to see this page'); // Exit if accessed directly
33
34
+ define('YASR_VERSION_NUM', '1.5.8');
35
36
//Plugin relative path
37
define( "YASR_ABSOLUTE_PATH", dirname(__FILE__) );
226
227
require (YASR_ABSOLUTE_PATH . '/lib/yasr-widgets.php');
228
229
+ if (is_admin()) {
230
+
231
+ require (YASR_ABSOLUTE_PATH . '/lib/class-wp-list-table.php');
232
+
233
+ }
234
+
235
global $wpdb;
236
237
define ("YASR_VOTES_TABLE", $wpdb->prefix . 'yasr_votes'); //Used in background