PluginProbe
Contact Forms by Cimatti / 2.3.5
Contact Forms by Cimatti v2.3.5
2.3.6 2.3.5 2.3.0 2.2.32 2.2.4 2.2.0 2.1.2 2.1.1 trunk 1.0 1.1 1.2 1.2.1 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 All 62 releases
contact-forms / admin / class-fields-list-table.php

class-fields-list-table.php in Contact Forms by Cimatti 2.3.5, at admin/class-fields-list-table.php

226 lines 7.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) exit;
3
4 if ( ! class_exists( 'WP_List_Table' ) ) {
5 require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
6 }
7
8 class Accua_Forms_Fields_List_Table extends WP_List_Table {
9
10 private $field_types = array();
11
12 /** The current search term, read once in prepare_items(). */
13 private $search = '';
14
15 function __construct() {
16 parent::__construct( array(
17 'singular' => 'field',
18 'plural' => 'fields',
19 'ajax' => false,
20 ) );
21 $this->field_types = accua_forms_fields_get_types();
22 }
23
24 function get_columns() {
25 return array(
26 'cb' => '<input type="checkbox" />',
27 'name' => __( 'Label', 'contact-forms' ),
28 'slug' => __( 'Slug', 'contact-forms' ),
29 'type' => __( 'Type', 'contact-forms' ),
30 'forms' => __( 'Forms', 'contact-forms' ),
31 'description' => __( 'Description', 'contact-forms' ),
32 );
33 }
34
35 function get_sortable_columns() {
36 return array(
37 'name' => array( 'name', false ),
38 'slug' => array( 'slug', false ),
39 'type' => array( 'type', false ),
40 'forms' => array( 'forms', false ),
41 );
42 }
43
44 function get_bulk_actions() {
45 return array(
46 'delete' => __( 'Delete', 'contact-forms' ),
47 );
48 }
49
50 function column_cb( $item ) {
51 return sprintf(
52 '<input type="checkbox" name="fields[]" value="%s" />',
53 esc_attr( $item['slug'] )
54 );
55 }
56
57 function column_default( $item, $column_name ) {
58 if ( isset( $item[ $column_name ] ) ) {
59 return esc_html( $item[ $column_name ] );
60 }
61 return '';
62 }
63
64 function column_name( $item ) {
65 $edit_url = admin_url( 'admin.php?page=accua_forms_fields&edit-fid=' . urlencode( $item['slug'] ) );
66 $delete_url = wp_nonce_url(
67 admin_url( 'admin.php?page=accua_forms_fields&delete-fid=' . urlencode( $item['slug'] ) ),
68 'delete_form_field_' . $item['slug']
69 );
70 $actions = array(
71 'edit' => sprintf(
72 '<a href="%s">%s</a>',
73 esc_url( $edit_url ),
74 esc_html__( 'Edit', 'contact-forms' )
75 ),
76 'delete' => sprintf(
77 '<a href="%s" class="delete-tag" onclick="return confirm(\'%s\');">%s</a>',
78 esc_url( $delete_url ),
79 esc_js( __( 'Are you sure you want to delete this field?', 'contact-forms' ) ),
80 esc_html__( 'Delete', 'contact-forms' )
81 ),
82 );
83 return sprintf(
84 '<strong><a class="row-title" href="%s">%s</a></strong>%s',
85 esc_url( $edit_url ),
86 esc_html( $item['name'] ),
87 $this->row_actions( $actions )
88 );
89 }
90
91 function column_type( $item ) {
92 $type_key = $item['type'];
93 if ( isset( $this->field_types[ $type_key ] ) ) {
94 return esc_html( $this->field_types[ $type_key ] );
95 }
96 return esc_html( $type_key );
97 }
98
99 function column_forms( $item ) {
100 $count = $item['forms'];
101 if ( $count > 0 ) {
102 return '<span>' . (int) $count . '</span>';
103 }
104 return '0';
105 }
106
107 /**
108 * Whether a row matches the current search.
109 *
110 * Searches the text the table actually shows: label, slug, type and
111 * description. The type is matched on its human-readable label as well as
112 * its key, so "Casella di controllo" finds a checkbox field on an Italian
113 * install just as "checkbox" does on an English one.
114 */
115 private function matches_search( $item ) {
116 $type_label = isset( $this->field_types[ $item['type'] ] ) ? $this->field_types[ $item['type'] ] : '';
117
118 $haystack = implode( ' ', array(
119 $item['name'],
120 $item['slug'],
121 $item['type'],
122 $type_label,
123 $item['description'],
124 ) );
125
126 // mb_stripos keeps the match case-insensitive for accented characters;
127 // mbstring is not guaranteed to be installed, hence the fallback.
128 if ( function_exists( 'mb_stripos' ) ) {
129 return false !== mb_stripos( $haystack, $this->search );
130 }
131 return false !== stripos( $haystack, $this->search );
132 }
133
134 function no_items() {
135 if ( '' !== $this->search ) {
136 esc_html_e( 'No fields match your search.', 'contact-forms' );
137 return;
138 }
139 esc_html_e( 'No fields found.', 'contact-forms' );
140 }
141
142 function prepare_items() {
143 $columns = $this->get_columns();
144 $hidden = array();
145 $sortable = $this->get_sortable_columns();
146
147 $this->_column_headers = array( $columns, $hidden, $sortable );
148
149 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only search parameter
150 $this->search = isset( $_REQUEST['s'] ) ? trim( sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ) ) : '';
151
152 $avail_fields = get_option( 'accua_forms_avail_fields', array() );
153 $saved_forms = get_option( 'accua_forms_saved_forms', array() );
154
155 // Count how many forms use each field
156 $field_usage = array();
157 foreach ( $saved_forms as $form ) {
158 if ( ! empty( $form['fields'] ) && is_array( $form['fields'] ) ) {
159 foreach ( array_keys( $form['fields'] ) as $field_slug ) {
160 if ( ! isset( $field_usage[ $field_slug ] ) ) {
161 $field_usage[ $field_slug ] = 0;
162 }
163 $field_usage[ $field_slug ]++;
164 }
165 }
166 }
167
168 $data = array();
169 foreach ( $avail_fields as $id => $field ) {
170 $data[] = array(
171 'slug' => $id,
172 'name' => $field['name'] ?? $field['label'] ?? $id,
173 'type' => $field['type'] ?? '',
174 'forms' => $field_usage[ $id ] ?? 0,
175 'description' => $field['description'] ?? '',
176 );
177 }
178
179 // Search first, so the count, the order and the paging are all those of
180 // the result set rather than of the whole list.
181 if ( '' !== $this->search ) {
182 $data = array_values( array_filter( $data, array( $this, 'matches_search' ) ) );
183 }
184
185 // Sorting
186 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only sort parameter
187 $orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : 'slug';
188 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only sort parameter
189 $order = isset( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : 'asc';
190
191 $valid_columns = array( 'name', 'slug', 'type', 'forms' );
192 if ( ! in_array( $orderby, $valid_columns, true ) ) {
193 $orderby = 'slug';
194 }
195 $order_asc = ( 'desc' !== strtolower( $order ) );
196
197 usort( $data, function ( $a, $b ) use ( $orderby, $order_asc ) {
198 if ( $orderby === 'forms' ) {
199 $result = $a['forms'] - $b['forms'];
200 } else {
201 $result = strcasecmp( $a[ $orderby ], $b[ $orderby ] );
202 }
203 return $order_asc ? $result : -$result;
204 } );
205
206 // Paging. Mostly this is what puts the "N items" count above the table,
207 // which is the feedback a search needs; the list is short enough on a
208 // normal install that the page links never appear.
209 $per_page = $this->get_items_per_page( 'accua_forms_fields_per_page', 50 );
210 $total_items = count( $data );
211 $current_page = $this->get_pagenum();
212
213 $this->set_pagination_args( array(
214 'total_items' => $total_items,
215 'per_page' => $per_page,
216 'total_pages' => (int) ceil( $total_items / max( 1, $per_page ) ),
217 ) );
218
219 $this->items = array_slice( $data, ( $current_page - 1 ) * $per_page, $per_page );
220 }
221
222 protected function get_default_primary_column_name() {
223 return 'name';
224 }
225 }
226