PluginProbe
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI / 8.0.3
GamiPress – Gamification plugin to reward points, badges & ranks in WordPress, now with AI v8.0.3
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 8.0.3, at libraries/ct/includes/class-ct-list-table.php

468 lines 17.7 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( sanitize_text_field( wp_unslash( $key ) ) ) . ']" value="' . esc_attr( sanitize_text_field( wp_unslash( $value ) ) ) . '" />';
57 }
58 } else {
59 echo '<input type="hidden" name="orderby" value="' . esc_attr( sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) ) . '" />';
60 }
61 }
62
63 if ( ! empty( $_REQUEST['order'] ) ) {
64 echo '<input type="hidden" name="order" value="' . esc_attr( sanitize_text_field( wp_unslash( $_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( wp_unslash( $_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( "ct_manage_{$ct_table->name}_extra_tablenav", $which );
203 // Backward compatibility
204 do_action( "manage_{$ct_table->name}_extra_tablenav", $which );
205
206 }
207
208 /**
209 *
210 * @return array
211 */
212 protected function get_table_classes() {
213 global $ct_table;
214
215 return array( 'widefat', 'fixed', 'striped', $ct_table->name );
216 }
217
218 /**
219 * Retrieve the table columns
220 *
221 * @access public
222 * @since 1.0.0
223 * @return array $columns Array of all the list table columns
224 */
225 public function get_columns() {
226 global $ct_table;
227
228 $columns = array();
229 $bulk_actions = $this->get_bulk_actions();
230
231 if( ! empty( $bulk_actions ) ) {
232 $columns['cb'] = '<input type="checkbox" />';
233 }
234
235 /**
236 * Filters the columns displayed in the list table of a specific CT table.
237 *
238 * @since 1.0.0
239 *
240 * @param array $posts_columns An array of column names.
241 * @param CT_Table $ct_table The table object.
242 */
243 // Backward Compatibility
244 $columns = apply_filters( "manage_{$ct_table->name}_columns", $columns, $ct_table );
245 return apply_filters( "ct_manage_{$ct_table->name}_columns", $columns, $ct_table );
246 }
247
248 /**
249 * Retrieve the table's sortable columns
250 *
251 * @access public
252 * @since 1.0.0
253 * @return array Array of all the sortable columns
254 */
255 public function get_sortable_columns() {
256 global $ct_table;
257
258 $sortable_columns = array();
259
260 /**
261 * Filters the sortable columns in the list table of a specific CT table.
262 *
263 * Format:
264 * 'internal-name' => 'orderby'
265 * or
266 * 'internal-name' => array( 'orderby', true )
267 * The second format will make the initial sorting order be descending
268 *
269 * @since 1.0.0
270 *
271 * @param array $sortable_columns An array of column names.
272 * @param CT_Table $ct_table The table object.
273 */
274 // Backward Compatibility
275 $sortable_columns = apply_filters( "manage_{$ct_table->name}_sortable_columns", $sortable_columns, $ct_table );
276 return apply_filters( "ct_manage_{$ct_table->name}_sortable_columns", $sortable_columns, $ct_table );
277 }
278
279 /**
280 * This function renders most of the columns in the list table.
281 *
282 * @access public
283 * @since 1.0.0
284 *
285 * @param stdClass $item The current object.
286 * @param string $column_name The name of the column
287 * @return string The column value.
288 */
289 public function column_default( $item, $column_name ) {
290 global $ct_table;
291
292 $value = isset( $item->$column_name ) ? $item->$column_name : '';
293
294 $primary_key = $ct_table->db->primary_key;
295
296 ob_start();
297 /**
298 * Fires for each custom column of a specific CT table in the list table.
299 *
300 * The dynamic portion of the hook name, `$ct_table->name`, refers to the CT table name.
301 *
302 * @since 1.0.0
303 *
304 * @param string $column_name The name of the column to display.
305 * @param int $object_id The current object ID.
306 * @param stdClass $object The current object.
307 * @param CT_Table $ct_table The CT table object.
308 */
309 do_action( "ct_manage_{$ct_table->name}_custom_column", $column_name, $item->$primary_key, $item, $ct_table );
310 // Backward Compatibility
311 do_action( "manage_{$ct_table->name}_custom_column", $column_name, $item->$primary_key, $item, $ct_table );
312 $custom_output = ob_get_clean();
313
314 if( ! empty( $custom_output ) ) {
315 return $custom_output;
316 }
317
318 $bulk_actions = $this->get_bulk_actions();
319
320 $first_column_index = ( ! empty( $bulk_actions ) ) ? 1 : 0;
321
322 $can_edit_item = current_user_can( $ct_table->cap->edit_item, $item->$primary_key );
323 $columns = $this->get_columns();
324 $columns_keys = array_keys( $columns );
325
326 if( $column_name === $columns_keys[$first_column_index] && $can_edit_item ) {
327
328 // Turns first column into a text link with url to edit the item
329 $value = sprintf( '<strong><a href="%s" aria-label="%s">%s</a></strong>',
330 esc_attr( ct_get_edit_link( $ct_table->name, $item->$primary_key ) ),
331 // translators: %s: value
332 esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $value ) ),
333 $value
334 );
335
336 // Small screens toggle
337 $value .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . esc_html__( 'Show more details' ) . '</span></button>';
338
339 }
340
341 return $value;
342 }
343
344 /**
345 * Generates and displays row action links.
346 *
347 * @since 4.3.0
348 * @access protected
349 *
350 * @param object $item The item being acted upon.
351 * @param string $column_name Current column name.
352 * @param string $primary Primary column name.
353 *
354 * @return string Row actions output for posts.
355 */
356 protected function handle_row_actions( $item, $column_name, $primary ) {
357 if ( $primary !== $column_name ) {
358 return '';
359 }
360
361 global $ct_table;
362
363 $primary_key = $ct_table->db->primary_key;
364 $actions = array();
365
366 if ( $ct_table->views->edit && current_user_can( $ct_table->cap->edit_item, $item->$primary_key ) ) {
367 $actions['edit'] = sprintf(
368 '<a href="%s" aria-label="%s">%s</a>',
369 esc_attr( ct_get_edit_link( $ct_table->name, $item->$primary_key ) ),
370 esc_attr( __( 'Edit' ) ),
371 esc_html__( 'Edit' )
372 );
373 }
374
375 if ( current_user_can( $ct_table->cap->delete_item, $item->$primary_key ) ) {
376 $actions['delete'] = sprintf(
377 '<a href="%s" class="submitdelete" onclick="%s" aria-label="%s">%s</a>',
378 ct_get_delete_link( $ct_table->name, $item->$primary_key ),
379 "return confirm('" .
380 esc_attr( ct_get_table_label( $ct_table->name, 'delete_item_confirm' ) ) .
381 "');",
382 esc_attr( __( 'Delete permanently' ) ),
383 esc_html__( 'Delete Permanently' )
384 );
385 }
386
387 /**
388 * Filters the array of row action links on the Posts list table.
389 *
390 * The filter is evaluated only for non-hierarchical post types.
391 *
392 * @since 2.8.0
393 *
394 * @param array $actions An array of row action links. Defaults are
395 * 'Edit', 'Quick Edit', 'Restore, 'Trash',
396 * 'Delete Permanently', 'Preview', and 'View'.
397 * @param WP_Post $post The post object.
398 */
399 $actions = apply_filters( "{$ct_table->name}_row_actions", $actions, $item );
400
401 return $this->row_actions( $actions );
402 }
403
404 /**
405 * Handles the checkbox column output.
406 *
407 * @since 1.0.0
408 *
409 * @param WP_Post $item The current WP_Post object.
410 */
411 public function column_cb( $item ) {
412 global $ct_table;
413
414 $primary_key = $ct_table->db->primary_key;
415
416 if ( current_user_can( $ct_table->cap->edit_items ) ): ?>
417 <label class="screen-reader-text" for="cb-select-<?php echo esc_attr( $item->$primary_key ); ?>"><?php
418 // translators: %d: item ID
419 echo esc_html( sprintf( ct_get_table_label( $ct_table->name, 'select_item' ), $item->$primary_key ) );
420 ?></label>
421 <input id="cb-select-<?php echo esc_attr( $item->$primary_key ); ?>" type="checkbox" name="item[]" value="<?php echo esc_attr( $item->$primary_key ); ?>" />
422 <div class="locked-indicator">
423 <span class="locked-indicator-icon" aria-hidden="true"></span>
424 <span class="screen-reader-text"><?php
425 /* translators: %d: item ID */
426 echo esc_html( sprintf( ct_get_table_label( $ct_table->name, 'item_locked' ), $item->$primary_key ) );
427 ?></span>
428 </div>
429 <?php endif;
430 }
431
432 /**
433 * Renders the message to be displayed when there are no results.
434 *
435 * @since 1.0.0
436 */
437 function no_items() {
438 global $ct_table;
439
440 echo $ct_table->labels->not_found;
441 }
442
443 public function prepare_items() {
444
445 global $ct_table, $ct_query;
446
447 // Get per page setting
448 $per_page = $this->get_items_per_page( 'edit_' . $ct_table->name . '_per_page' );
449
450 // Update query vars based on settings
451 $ct_query->query_vars['items_per_page'] = $per_page;
452
453 // Get query results
454 $this->items = $ct_query->get_results();
455
456 $total_items = $ct_query->found_results;
457
458 // Setup pagination args based on items found and per page settings
459 $this->set_pagination_args( array(
460 'total_items' => $total_items,
461 'per_page' => $per_page,
462 'total_pages' => ceil( $total_items / $per_page )
463 ) );
464 }
465
466 }
467
468 endif;