PluginProbe
Float menu – awesome floating side menu / 7.0.4
Float menu – awesome floating side menu v7.0.4
7.2.5 trunk 2.1 2.2 3.0.1 3.1 3.2.2 3.3.1 3.5 3.5.1 3.5.2 3.5.3. 3.5.4 4.0 4.1 4.1.1 4.2 4.3 4.3.1 4.3.2 5.0 5.0.1 5.0.2 5.0.3 5.1 All 57 releases
float-menu / classes / Admin / ListTable.php

ListTable.php in Float menu – awesome floating side menu 7.0.4, at classes/Admin/ListTable.php

376 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class ListTable
5 *
6 * @package WowPlugin
7 * @subpackage Admin
8 * @author Dmytro Lobov <dev@wow-company.com>, Wow-Company
9 * @copyright 2024 Dmytro Lobov
10 * @license GPL-2.0+
11 *
12 * @see https://developer.wordpress.org/reference/classes/wp_list_table/
13 */
14
15 namespace FloatMenuLite\Admin;
16
17 defined( 'ABSPATH' ) || exit;
18
19 use WP_List_Table;
20 use FloatMenuLite\WOWP_Plugin;
21
22 class ListTable extends WP_List_Table {
23
24 public int $per_page = 30;
25
26 public function __construct() {
27 // Set parent defaults
28 parent::__construct( array(
29 'ajax' => false,
30 ) );
31 $this->process_bulk_action();
32 }
33
34 public function column_default( $item, $column_name ) {
35 return $item[ $column_name ];
36 }
37
38 // phpcs:disable WordPress.Security.NonceVerification.Recommended
39 public function search_box( $text, $input_id ): void {
40 $input_id .= '-search-input';
41 if ( ! empty( $_REQUEST['orderby'] ) ) {
42 $orderby = sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) );
43 echo '<input type="hidden" name="orderby" value="' . esc_attr( $orderby ) . '" />';
44 }
45
46 if ( ! empty( $_REQUEST['order'] ) ) {
47 $order = sanitize_text_field( wp_unslash( $_REQUEST['order'] ) );
48 echo '<input type="hidden" name="order" value="' . esc_attr( $order ) . '" />';
49 }
50 ?>
51 <p class="search-box">
52 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ) ?>">
53 <?php echo esc_attr( $text ); ?>:
54 </label>
55 <input type="search" id="<?php echo esc_attr( $input_id ) ?>" name="s"
56 value="<?php _admin_search_query(); ?>"/>
57 <?php submit_button( $text, 'button', false, false, array( 'ID' => 'search-submit' ) ); ?>
58 </p>
59 <?php
60 }
61
62 // phpcs:enable
63
64 public function column_title( $item ): string {
65 $title = ! empty( $item['title'] ) ? $item['title'] : __( 'Untitled', 'float-menu' );
66 $param = DBManager::get_param_id( $item['ID'] );
67 $actions = [
68 'id' => '#' . $item['ID'],
69 'edit' => '<a href="' . esc_url( Link::edit( $item['ID'] ) ) . '">' . esc_attr__( 'Edit',
70 'float-menu' ) . '</a>',
71 'duplicate' => '<a href="' . esc_url( Link::duplicate( $item['ID'] ) ) . '">' . esc_attr__( 'Duplicate',
72 'float-menu' ) . '</a>',
73 'delete' => '<a href="' . esc_url( Link::remove( $item['ID'] ) ) . '" >' . esc_attr__( 'Delete',
74 'float-menu' ) . '</a>',
75 'export' => '<a href="' . esc_url( Link::export( $item['ID'] ) ) . '" >' . esc_attr__( 'Export',
76 'float-menu' ) . '</a>',
77 ];
78 if ( ! empty( $param['link'] ) ) {
79 $actions['view'] = '<a href="' . esc_url( $param['link'] ) . '" target="_blank">' . esc_attr__( 'View',
80 'float-menu' ) . '</a>';
81 }
82
83
84 return $title . $this->row_actions( $actions );
85 }
86
87 public function prepare_items(): void {
88 $columns = $this->get_columns();
89 $hidden = $this->get_hidden_columns();
90 $sortable = $this->get_sortable_columns();
91 $data = $this->table_data();
92 $perPage = 30;
93 $currentPage = $this->get_pagenum();
94 if ( $data ) {
95 usort( $data, [ &$this, 'sort_data' ] );
96 $data = array_slice( $data, ( ( $currentPage - 1 ) * $perPage ), $perPage );
97 }
98 $totalItems = $this->list_count();
99 $this->_column_headers = [ $columns, $hidden, $sortable ];
100 $this->items = $data;
101 $this->set_pagination_args( [
102 'total_items' => $totalItems,
103 'per_page' => $perPage,
104 'total_pages' => ceil( $totalItems / $perPage ),
105 ] );
106 }
107
108 public function get_columns(): array {
109 return [
110 'cb' => '<input type="checkbox" />',
111 'title' => __( 'Title', 'float-menu' ),
112 'code' => __( 'Shortcode', 'float-menu' ),
113 'tag' => __( 'Tag', 'float-menu' ),
114 'mode' => __( 'Test mode',
115 'float-menu' ) . '<sup class="has-tooltip" data-tooltip="' . __( 'The item will only be displayed for administrators.',
116 'float-menu' ) . '">ℹ</sup>',
117 'status' => __( 'Status',
118 'float-menu' ) . '<sup class="has-tooltip" data-tooltip="' . __( 'The item will only be displayed for administrators.',
119 'float-menu' ) . '">ℹ</sup>',
120 ];
121 }
122
123 public function get_hidden_columns(): array {
124 return [];
125 }
126
127 public function get_sortable_columns(): array {
128 return [
129 'ID' => [ 'ID', false ],
130 ];
131 }
132
133 private function table_data(): array {
134 $data = [];
135 $paged = $this->get_paged();
136 $offset = $this->per_page * ( $paged - 1 );
137
138 $result = $this->get_results();
139
140 $slug = WOWP_Plugin::SLUG;
141 $shortcode = WOWP_Plugin::SHORTCODE;
142
143 if ( empty( $result ) ) {
144 return $data;
145 }
146
147 $main_link = add_query_arg( [
148 'page' => $slug,
149 'tab' => 'settings',
150 'action' => 'update'
151 ], admin_url( 'admin.php' ) );
152 foreach ( $result as $key => $value ) {
153 $title = ! empty( $value->title ) ? $value->title : __( 'UnTitle', 'float-menu' );
154 $tooltip_off = esc_attr__( 'Click for Deactivate.', 'float-menu' );
155 $tooltip_on = esc_attr__( 'Click for Activate.', 'float-menu' );
156 $status_off = '<a href="' . esc_url( Link::activate_url( $value->id ) ) . '" class="wpie-toogle is-off" data-tooltip="' . esc_attr( $tooltip_on ) . '"><span>' . esc_attr__( 'OFF',
157 'float-menu' ) . '</span></a>';
158 $status_on = '<a href="' . esc_url( Link::deactivate_url( $value->id ) ) . '" class="wpie-toogle is-on" data-tooltip="' . esc_attr( $tooltip_off ) . '"><span>' . esc_attr__( 'ON',
159 'float-menu' ) . '</span></a>';
160 $status = ! empty( $value->status ) ? $status_off : $status_on;
161
162 $mode_tooltip_off = esc_attr__( 'Click for OFF.', 'float-menu' );
163 $mode_tooltip_on = esc_attr__( 'Click for ON.', 'float-menu' );
164
165 $mode_off = '<a href="' . esc_url( Link::activate_mode( $value->id ) ) . '" class="wpie-toogle is-off" data-tooltip="' . esc_attr( $mode_tooltip_on ) . '"><span>' . esc_attr__( 'OFF',
166 'float-menu' ) . '</span></a>';
167 $mode_on = '<a href="' . esc_url( Link::deactivate_mode( $value->id ) ) . '" class="wpie-toogle is-on" data-tooltip="' . esc_attr( $mode_tooltip_off ) . '"><span>' . esc_attr__( 'ON',
168 'float-menu' ) . '</span></a>';
169
170 $mode = empty( $value->mode ) ? $mode_off : $mode_on;
171
172 $tag = '';
173 if ( isset( $value->tag ) ) {
174 $tag_url = add_query_arg( [
175 'page' => WOWP_Plugin::SLUG,
176 'tag' => $value->tag
177 ], admin_url( 'admin.php' ) );
178 $tag = '<a href="' . esc_url( $tag_url ) . '">' . esc_attr( $value->tag ) . '</a>';
179 }
180
181 $link = add_query_arg( [ 'id' => $value->id ], $main_link );
182 $data[] = array(
183 'ID' => $value->id,
184 'title' => '<a href="' . esc_url( $link ) . '">' . esc_attr( $title ) . '</a>',
185 'code' => '<input type="text" value="[' . esc_attr( $shortcode ) . ' id=\'' . absint( $value->id ) . '\']" readonly>',
186 'tag' => $tag,
187 'mode' => $mode,
188 'status' => $status,
189 );
190 }
191
192 return $data;
193 }
194
195 public function column_cb( $item ) {
196 return sprintf( '<input type="checkbox" name="%1$s[]" value="%2$s" />', 'ID', $item['ID'] );
197 }
198
199 public function get_paged(): int {
200 return isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
201 }
202
203 public function get_search() {
204 $verify = AdminActions::verify( WOWP_Plugin::PREFIX . '_list_action' );
205
206 if ( ! $verify ) {
207 return false;
208 }
209
210 // phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verification is handled elsewhere.
211 return ! empty( $_POST['s'] ) ? urldecode( trim( sanitize_text_field( wp_unslash( $_POST['s'] ) ) ) ) : false;
212 // phpcs:enable
213 }
214
215 public function list_count(): int {
216 $result = $this->get_results();
217
218 if ( empty( $result ) ) {
219 return 0;
220 }
221 $count = count( $result );
222
223 return (int) $count;
224 }
225
226 public function get_results() {
227 global $wpdb;
228
229 $search = $this->get_search();
230
231 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
232 $tag_search = ( ! empty( $_REQUEST['tag'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST ['tag'] ) ) : '';
233 $tag_search = ( $tag_search === 'all' ) ? '' : $tag_search;
234
235
236 $result = '';
237
238 $table = esc_sql($wpdb->prefix . WOWP_Plugin::PREFIX);
239
240 // Table name is sanitized elsewhere.
241 if ( empty( $search ) ) {
242 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
243 $result = $wpdb->get_results( "SELECT * FROM {$table} ORDER BY id DESC" );
244 if ( ! empty( $tag_search ) ) {
245 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
246 $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$table} WHERE tag=%s ORDER BY id DESC",
247 $tag_search ) );
248 }
249 } elseif ( trim( $search ) === 'UnTitle' ) {
250 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
251 $result = $wpdb->get_results( "SELECT * FROM {$table} WHERE title='' ORDER BY id DESC" );
252 if ( ! empty( $tag_search ) ) {
253 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
254 $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$table} WHERE title='' AND tag=%s ORDER BY id DESC",
255 $tag_search ) );
256 }
257 } elseif ( is_numeric( $search ) ) {
258 if ( ! empty( $tag_search ) ) {
259 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
260 $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$table} WHERE id=%d AND tag=%s ORDER BY id DESC",
261 absint( $search ), $tag_search ) );
262 } else {
263 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
264 $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$table} WHERE id=%d ORDER BY id DESC",
265 absint( $search ) ) );
266 }
267 } else {
268 $wild = '%';
269 $find = sanitize_text_field( $search );
270 $like = $wild . $wpdb->esc_like( $find ) . $wild;
271 if ( ! empty( $tag_search ) ) {
272 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
273 $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$table} WHERE title LIKE %s AND tag=%s ORDER BY id DESC",
274 $like, $tag_search ) );
275 } else {
276 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
277 $result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$table} WHERE title LIKE %s ORDER BY id DESC",
278 $like ) );
279 }
280 }
281
282 return $result;
283 }
284
285
286 public function get_bulk_actions(): array {
287 $actions = [
288 'delete' => __( 'Delate', 'float-menu' ),
289 'activate' => __( 'Activate', 'float-menu' ),
290 'deactivate' => __( 'Deactivate', 'float-menu' ),
291 'test_on' => __( 'Test mode ON', 'float-menu' ),
292 'test_off' => __( 'Test mode OFF', 'float-menu' ),
293 ];
294
295 return $actions;
296 }
297
298 public function process_bulk_action() {
299 $verify = AdminActions::verify( WOWP_Plugin::PREFIX . '_list_action' );
300
301 if ( ! $verify ) {
302 return false;
303 }
304 // phpcs:ignore WordPress.Security.NonceVerification.Missing
305 $ids = isset( $_POST['ID'] ) ? ( map_deep( $_POST['ID'], 'absint' ) ) : false;
306 $action = $this->current_action();
307 if ( ! is_array( $ids ) ) {
308 $ids = [ $ids ];
309 }
310 if ( empty( $action ) ) {
311 return false;
312 }
313
314 foreach ( $ids as $id ) {
315 if ( 'delete' === $this->current_action() ) {
316 DBManager::delete( $id );
317 }
318 if ( 'activate' === $this->current_action() ) {
319 Settings::activate_item( $id );
320 }
321 if ( 'deactivate' === $this->current_action() ) {
322 Settings::deactivate_item( $id );
323 }
324 if ( 'test_on' === $this->current_action() ) {
325 Settings::activate_mode( $id );
326 }
327 if ( 'test_off' === $this->current_action() ) {
328 Settings::deactivate_mode( $id );
329 }
330 }
331 }
332
333 protected function extra_tablenav( $which ): void {
334 if ( 'top' === $which ) {
335 $tags = DBManager::get_tags_from_table();
336
337 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
338 $tag_search = ( ! empty( $_REQUEST['tag'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['tag'] ) ) : '';
339 $tag_search = ( $tag_search === 'all' ) ? '' : $tag_search;
340
341 echo '<div class="alignleft actions"><label for="filter-by-tag" class="screen-reader-text">' . esc_html__( 'Filter by tag',
342 'float-menu' ) . '</label>';
343 echo '<select name="tag" id="filter-by-tag">';
344 echo '<option value="all"' . selected( 'all', $tag_search, false ) . '>' . esc_html__( 'All',
345 'float-menu' ) . '</option>';
346
347 if ( ! empty( $tags ) ) {
348 foreach ( $tags as $tag ) {
349 if ( empty( $tag['tag'] ) ) {
350 continue;
351 }
352 echo '<option value="' . esc_attr( trim( $tag['tag'] ) ) . '"' . selected( $tag['tag'], $tag_search,
353 false ) . '>' . esc_html( $tag['tag'] ) . '</option>';
354 }
355 }
356 echo '</select>';
357 submit_button( __( 'Filter', 'float-menu' ), 'secondary', 'action', false );
358 echo '</div>';
359 }
360 }
361
362 private function sort_data( $a, $b ): int {
363 // If no sort, default to title
364 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
365 $orderby = ( ! empty( $_GET['orderby'] ) ) ? sanitize_text_field( wp_unslash($_GET['orderby']) ) : 'ID';
366 // If no order, default to asc
367 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
368 $order = ( ! empty( $_GET['order'] ) ) ? sanitize_text_field( wp_unslash($_GET['order']) ) : 'desc';
369 // Determine sort order
370 $result = strnatcmp( $a[ $orderby ], $b[ $orderby ] );
371
372 // Send final sort direction to usort
373 return ( $order === 'asc' ) ? $result : - $result;
374 }
375
376 }