PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 7.9.8
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v7.9.8
8.0.4 8.0.3 8.0.1 8.0.2 8.0.0 7.9.9.7 7.9.9.6 7.9.9.5 7.9.9.4 7.9.9.3 7.9.9.2 7.9.9.1 7.9.9 7.9.8 7.9.7 7.9.6 7.9.5 7.9.4 7.9.3 7.9.2 7.9.1 7.9.0 7.8.9 7.8.8 7.8.7 All 46 releases
gamipress / libraries / ct / includes / class-ct-list-table.php

class-ct-list-table.php in GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI 7.9.8, at libraries/ct/includes/class-ct-list-table.php

461 lines 17.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * List Table class
4 *
5 * Based on WP_Posts_List_Table class
6 *
7 * @author GamiPress <[email protected]>, Ruben Garcia <[email protected]>
8 *
9 * @since 1.0.0
10 */
11 // Exit if accessed directly
12 defined( 'ABSPATH' ) || exit;
13
14 if ( ! class_exists( 'CT_List_Table' ) ) :
15
16 class CT_List_Table extends WP_List_Table {
17
18 /**
19 * Get things started
20 *
21 * @access public
22 * @since 1.0.0
23 *
24 * @param array $args Optional. Arbitrary display and query arguments to pass through
25 * the list table. Default empty array.
26 */
27 public function __construct( $args = array() ) {
28 global $ct_table;
29
30 parent::__construct( array(
31 'singular' => $ct_table->labels->singular_name,
32 'plural' => $ct_table->labels->plural_name,
33 'screen' => convert_to_screen( $ct_table->labels->plural_name )
34 ) );
35 }
36
37 /**
38 * Show the search field
39 *
40 * @since 1.0.0
41 *
42 * @param string $text Label for the search box
43 * @param string $input_id ID of the search box
44 *
45 * @return void
46 */
47 public function search_box( $text, $input_id ) {
48 if ( empty( $_REQUEST['s'] ) && !$this->has_items() )
49 return;
50
51 $input_id = $input_id . '-search-input';
52
53 if ( ! empty( $_REQUEST['orderby'] ) ) {
54 if ( is_array( $_REQUEST['orderby'] ) ) {
55 foreach ( $_REQUEST['orderby'] as $key => $value ) {
56 echo '<input type="hidden" name="orderby[' . esc_attr( $key ) . ']" value="' . esc_attr( $value ) . '" />';
57 }
58 } else {
59 echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
60 }
61 }
62
63 if ( ! empty( $_REQUEST['order'] ) ) {
64 echo '<input type="hidden" name="order" value="' . esc_attr( sanitize_text_field( $_REQUEST['order'] ) ) . '" />';
65 }
66 ?>
67 <p class="search-box">
68 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo $text; ?>:</label>
69 <input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>" />
70 <?php submit_button( $text, 'button', false, false, array( 'id' => 'search-submit' ) ); ?>
71 </p>
72 <?php
73 }
74
75 /**
76 * Retrieve the view types
77 *
78 * @access public
79 * @since 1.0.0
80 *
81 * @return array $views All the views available
82 */
83 public function get_views() {
84
85 global $wpdb, $ct_table;
86
87 /**
88 * Utility filter to generate views based on a given field
89 *
90 * @since 1.0.0
91 *
92 * @param string $field_id The field id to generate the views
93 *
94 * @return string
95 */
96 $field_id = apply_filters( "ct_list_{$ct_table->name}_views_field", '' );
97
98 /**
99 * Labels for the filed id
100 *
101 * @since 1.0.0
102 *
103 * @param array $field_labels Field labels in format array( 'field_value' => 'Field Label' )
104 * Field values that are not listed here won't get displayed
105 *
106 * @return array
107 */
108 $field_labels = apply_filters( "ct_list_{$ct_table->name}_views_field_labels", array() );
109
110 $views = array();
111
112 // Check if field ID and labels has been passed and also is field is registered on the table (not as meta)
113 if( ! empty( $field_id ) && ! empty( $field_labels ) && isset( $ct_table->db->schema->fields[$field_id] ) ) {
114
115 // Get the number of entries per each different field value
116 $results = $wpdb->get_results( "SELECT {$field_id}, COUNT( * ) AS num_entries FROM {$ct_table->db->table_name} GROUP BY {$field_id}", ARRAY_A );
117 $counts = array();
118
119 // Loop them to build the counts array
120 foreach( $results as $result ) {
121 $counts[$result[$field_id]] = absint( $result['num_entries'] );
122 }
123
124 $list_link = ct_get_list_link( $ct_table->name );
125 $list_link = add_query_arg( '_ctviewnonce', wp_create_nonce( 'ct_views_filter' ), $list_link );
126 $current = '';
127
128 if( isset( $_GET['_ctviewnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash ( $_GET['_ctviewnonce'] ) ), 'ct_views_filter' ) ) {
129 $current = isset( $_GET[$field_id] ) ? sanitize_text_field( $_GET[$field_id] ) : '';
130 }
131
132 // Setup the 'All' view
133 $all_count = absint( $wpdb->get_var( "SELECT COUNT( * ) FROM {$ct_table->db->table_name}" ) );
134 $views['all'] = '<a href="' . esc_attr( $list_link ) . '" class="' . ( empty( $current ) ? 'current' : '' ) . '">' . esc_html__( 'All', 'ct' ) . ' <span class="count">(' . $all_count . ')</span></a>';
135
136 foreach( $counts as $value => $count ) {
137
138 // Skip fields that are not intended to being displayed
139 if( ! isset( $field_labels[$value] ) ) {
140 continue;
141 }
142
143 $label = $field_labels[$value];
144 $url = $list_link . '&' . $field_id . '=' . $value;
145
146 $views[$value] = '<a href="' . esc_attr( $url ) . '" class="' . ( $current === $value ? 'current' : '' ) . '">' . $label . ' <span class="count">(' . $count . ')</span>' . '</a>';
147 }
148
149 }
150
151 /**
152 * Available filter to past custom views
153 *
154 * @since 1.0.0
155 *
156 * @param array $views An array of views links.
157 * Array format: array( 'link_id' => 'link' )
158 * Link format: '<a href="#">{label} <span class="count">({count})</span></a>'
159 */
160 $views = apply_filters( "{$ct_table->name}_get_views", $views );
161
162 return $views;
163 }
164
165 /**
166 *
167 * @return array
168 */
169 protected function get_bulk_actions() {
170
171 global $ct_table;
172
173 $actions = array();
174
175 if ( current_user_can( $ct_table->cap->delete_items ) ) {
176 $actions['delete'] = __( 'Delete Permanently' );
177 }
178
179 $actions = apply_filters( "{$ct_table->name}_bulk_actions", $actions );
180
181 return $actions;
182 }
183
184 /**
185 * Displays extra controls between bulk actions and pagination.
186 *
187 * @since 1.0.0
188 *
189 * @param string $which
190 */
191 protected function extra_tablenav( $which ) {
192
193 global $ct_table;
194
195 /**
196 * Extra table nav
197 *
198 * @since 1.0.0
199 *
200 * @param string $which The location of the extra table nav markup: 'top' or 'bottom'.
201 */
202 do_action( "manage_{$ct_table->name}_extra_tablenav", $which );
203
204 }
205
206 /**
207 *
208 * @return array
209 */
210 protected function get_table_classes() {
211 global $ct_table;
212
213 return array( 'widefat', 'fixed', 'striped', $ct_table->name );
214 }
215
216 /**
217 * Retrieve the table columns
218 *
219 * @access public
220 * @since 1.0.0
221 * @return array $columns Array of all the list table columns
222 */
223 public function get_columns() {
224 global $ct_table;
225
226 $columns = array();
227 $bulk_actions = $this->get_bulk_actions();
228
229 if( ! empty( $bulk_actions ) ) {
230 $columns['cb'] = '<input type="checkbox" />';
231 }
232
233 /**
234 * Filters the columns displayed in the list table of a specific CT table.
235 *
236 * @since 1.0.0
237 *
238 * @param array $posts_columns An array of column names.
239 * @param CT_Table $ct_table The table object.
240 */
241 return apply_filters( "manage_{$ct_table->name}_columns", $columns, $ct_table );
242 }
243
244 /**
245 * Retrieve the table's sortable columns
246 *
247 * @access public
248 * @since 1.0.0
249 * @return array Array of all the sortable columns
250 */
251 public function get_sortable_columns() {
252 global $ct_table;
253
254 $sortable_columns = array();
255
256 /**
257 * Filters the sortable columns in the list table of a specific CT table.
258 *
259 * Format:
260 * 'internal-name' => 'orderby'
261 * or
262 * 'internal-name' => array( 'orderby', true )
263 * The second format will make the initial sorting order be descending
264 *
265 * @since 1.0.0
266 *
267 * @param array $sortable_columns An array of column names.
268 * @param CT_Table $ct_table The table object.
269 */
270 return apply_filters( "manage_{$ct_table->name}_sortable_columns", $sortable_columns, $ct_table );
271 }
272
273 /**
274 * This function renders most of the columns in the list table.
275 *
276 * @access public
277 * @since 1.0.0
278 *
279 * @param stdClass $item The current object.
280 * @param string $column_name The name of the column
281 * @return string The column value.
282 */
283 public function column_default( $item, $column_name ) {
284 global $ct_table;
285
286 $value = isset( $item->$column_name ) ? $item->$column_name : '';
287
288 $primary_key = $ct_table->db->primary_key;
289
290 ob_start();
291 /**
292 * Fires for each custom column of a specific CT table in the list table.
293 *
294 * The dynamic portion of the hook name, `$ct_table->name`, refers to the CT table name.
295 *
296 * @since 1.0.0
297 *
298 * @param string $column_name The name of the column to display.
299 * @param int $object_id The current object ID.
300 * @param stdClass $object The current object.
301 * @param CT_Table $ct_table The CT table object.
302 */
303 do_action( "manage_{$ct_table->name}_custom_column", $column_name, $item->$primary_key, $item, $ct_table );
304 $custom_output = ob_get_clean();
305
306 if( ! empty( $custom_output ) ) {
307 return $custom_output;
308 }
309
310 $bulk_actions = $this->get_bulk_actions();
311
312 $first_column_index = ( ! empty( $bulk_actions ) ) ? 1 : 0;
313
314 $can_edit_item = current_user_can( $ct_table->cap->edit_item, $item->$primary_key );
315 $columns = $this->get_columns();
316 $columns_keys = array_keys( $columns );
317
318 if( $column_name === $columns_keys[$first_column_index] && $can_edit_item ) {
319
320 // Turns first column into a text link with url to edit the item
321 $value = sprintf( '<strong><a href="%s" aria-label="%s">%s</a></strong>',
322 esc_attr( ct_get_edit_link( $ct_table->name, $item->$primary_key ) ),
323 esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $value ) ),
324 $value
325 );
326
327 // Small screens toggle
328 $value .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . esc_html__( 'Show more details' ) . '</span></button>';
329
330 }
331
332 return $value;
333 }
334
335 /**
336 * Generates and displays row action links.
337 *
338 * @since 4.3.0
339 * @access protected
340 *
341 * @param object $item The item being acted upon.
342 * @param string $column_name Current column name.
343 * @param string $primary Primary column name.
344 *
345 * @return string Row actions output for posts.
346 */
347 protected function handle_row_actions( $item, $column_name, $primary ) {
348 if ( $primary !== $column_name ) {
349 return '';
350 }
351
352 global $ct_table;
353
354 $primary_key = $ct_table->db->primary_key;
355 $actions = array();
356
357 if ( $ct_table->views->edit && current_user_can( $ct_table->cap->edit_item, $item->$primary_key ) ) {
358 $actions['edit'] = sprintf(
359 '<a href="%s" aria-label="%s">%s</a>',
360 esc_attr( ct_get_edit_link( $ct_table->name, $item->$primary_key ) ),
361 esc_attr( __( 'Edit' ) ),
362 esc_html__( 'Edit' )
363 );
364 }
365
366 if ( current_user_can( $ct_table->cap->delete_item, $item->$primary_key ) ) {
367 $actions['delete'] = sprintf(
368 '<a href="%s" class="submitdelete" onclick="%s" aria-label="%s">%s</a>',
369 ct_get_delete_link( $ct_table->name, $item->$primary_key ),
370 "return confirm('" .
371 esc_attr( ct_get_table_label( $ct_table->name, 'delete_item_confirm' ) ) .
372 "');",
373 esc_attr( __( 'Delete permanently' ) ),
374 esc_html__( 'Delete Permanently' )
375 );
376 }
377
378 /**
379 * Filters the array of row action links on the Posts list table.
380 *
381 * The filter is evaluated only for non-hierarchical post types.
382 *
383 * @since 2.8.0
384 *
385 * @param array $actions An array of row action links. Defaults are
386 * 'Edit', 'Quick Edit', 'Restore, 'Trash',
387 * 'Delete Permanently', 'Preview', and 'View'.
388 * @param WP_Post $post The post object.
389 */
390 $actions = apply_filters( "{$ct_table->name}_row_actions", $actions, $item );
391
392 return $this->row_actions( $actions );
393 }
394
395 /**
396 * Handles the checkbox column output.
397 *
398 * @since 1.0.0
399 *
400 * @param WP_Post $item The current WP_Post object.
401 */
402 public function column_cb( $item ) {
403 global $ct_table;
404
405 $primary_key = $ct_table->db->primary_key;
406
407 if ( current_user_can( $ct_table->cap->edit_items ) ): ?>
408 <label class="screen-reader-text" for="cb-select-<?php echo esc_attr( $item->$primary_key ); ?>"><?php
409 echo sprintf( __( 'Select Item #%d' ), $item->$primary_key );
410 ?></label>
411 <input id="cb-select-<?php echo esc_attr( $item->$primary_key ); ?>" type="checkbox" name="item[]" value="<?php echo esc_attr( $item->$primary_key ); ?>" />
412 <div class="locked-indicator">
413 <span class="locked-indicator-icon" aria-hidden="true"></span>
414 <span class="screen-reader-text"><?php
415 echo esc_html( sprintf(
416 /* translators: %d: item ID */
417 __( '&#8220;Item #%d&#8221; is locked' ),
418 $item->$primary_key
419 ) );
420 ?></span>
421 </div>
422 <?php endif;
423 }
424
425 /**
426 * Renders the message to be displayed when there are no results.
427 *
428 * @since 1.0.0
429 */
430 function no_items() {
431 global $ct_table;
432
433 echo $ct_table->labels->not_found;
434 }
435
436 public function prepare_items() {
437
438 global $ct_table, $ct_query;
439
440 // Get per page setting
441 $per_page = $this->get_items_per_page( 'edit_' . $ct_table->name . '_per_page' );
442
443 // Update query vars based on settings
444 $ct_query->query_vars['items_per_page'] = $per_page;
445
446 // Get query results
447 $this->items = $ct_query->get_results();
448
449 $total_items = $ct_query->found_results;
450
451 // Setup pagination args based on items found and per page settings
452 $this->set_pagination_args( array(
453 'total_items' => $total_items,
454 'per_page' => $per_page,
455 'total_pages' => ceil( $total_items / $per_page )
456 ) );
457 }
458
459 }
460
461 endif;