PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | classes/helpers/FrmEntriesListHelper.php +275 -84 6.4.1 → trunk View file →
@@ -3,54 +3,107 @@
3 3 die( 'You are not allowed to call this page directly.' );
4 4 }
5 5
6 6 class FrmEntriesListHelper extends FrmListHelper {
7 +
8 + /**
9 + * @var string|null
10 + */
7 11 protected $column_name;
8 - protected $item;
9 - protected $field;
10 12
11 13 /**
12 14 * @since 4.07
15 + *
16 + * @var bool|int
13 17 */
14 18 public $total_items = 0;
15 19
16 20 /**
21 + * @param array $args
22 + */
23 + public function __construct( $args ) {
24 + parent::__construct( $args );
25 + $this->screen->set_screen_reader_content(
26 + array(
27 + 'heading_list' => esc_html__( 'Entries list', 'formidable' ),
28 + )
29 + );
30 + }
31 +
32 + /**
17 33 * @return void
18 34 */
19 35 public function prepare_items() {
20 - global $per_page;
36 + $this->set_per_page();
37 + $s_query = array();
38 + $join_form_in_query = false;
21 39
22 - $per_page = $this->get_items_per_page( 'formidable_page_formidable_entries_per_page' );
23 - $form_id = $this->params['form'];
40 + $this->items = $this->get_entry_items( $s_query, $join_form_in_query );
41 + $this->set_total_items( $s_query );
42 + $this->prepare_pagination();
43 + }
24 44
25 - $s_query = array();
45 + /**
46 + * @param array $s_query
47 + *
48 + * @return void
49 + */
50 + protected function set_total_items( $s_query ) {
51 + $this->total_items = FrmEntry::getRecordCount( $s_query );
52 + }
26 53
27 - if ( $form_id ) {
28 - $s_query['it.form_id'] = $form_id;
29 - $join_form_in_query = false;
30 - } else {
31 - $s_query[] = array(
32 - 'or' => 1,
33 - 'parent_form_id' => null,
34 - 'parent_form_id <' => 1,
35 - );
36 - $join_form_in_query = true;
37 - }
54 + /**
55 + * Prepares pagination.
56 + *
57 + * @since 6.5.4
58 + *
59 + * @return void
60 + */
61 + protected function prepare_pagination() {
62 + global $per_page;
38 63
39 - $s = self::get_param(
64 + $this->set_pagination_args(
40 65 array(
41 - 'param' => 's',
42 - 'sanitize' => 'sanitize_text_field',
66 + 'total_items' => $this->total_items,
67 + 'per_page' => $per_page,
43 68 )
44 69 );
70 + }
45 71
46 - if ( $s != '' && FrmAppHelper::pro_is_installed() ) {
47 - $fid = self::get_param( array( 'param' => 'fid' ) );
48 - $s_query = FrmProEntriesHelper::get_search_str( $s_query, $s, $form_id, $fid );
49 - }
72 + /**
73 + * Sets the global $per_page variable
74 + *
75 + * @since 6.5.4
76 + *
77 + * @return void
78 + */
79 + protected function set_per_page() {
80 + global $per_page;
81 + $per_page = $this->get_items_per_page( 'formidable_page_formidable_entries_per_page' );
82 + }
50 83
51 - $s_query = apply_filters( 'frm_entries_list_query', $s_query, compact( 'form_id' ) );
84 + /**
85 + * @since 6.5.4
86 + *
87 + * @param array $s_query
88 + * @param bool $join_form_in_query
89 + *
90 + * @return array
91 + */
92 + protected function get_entry_items( &$s_query, &$join_form_in_query ) {
93 + global $per_page;
94 + $s_query = $this->get_search_query( $join_form_in_query );
95 + $limit = $this->get_limit( $per_page );
52 96
97 + return FrmEntry::getAll( $s_query, $this->get_order_by(), $limit, true, $join_form_in_query );
98 + }
99 +
100 + /**
101 + * @since 6.5.4
102 + *
103 + * @return string
104 + */
105 + protected function get_order_by() {
53 106 $orderby = self::get_param(
54 107 array(
55 108 'param' => 'orderby',
56 109 'default' => 'id',
@@ -55,22 +108,36 @@
55 108 'param' => 'orderby',
56 109 'default' => 'id',
57 110 )
58 111 );
59 -
60 - if ( strpos( $orderby, 'meta' ) !== false ) {
61 - $order_field_type = FrmField::get_type( str_replace( 'meta_', '', $orderby ) );
62 - $orderby .= in_array( $order_field_type, array( 'number', 'scale', 'star' ) ) ? '+0' : '';
63 - }
64 -
65 - $order = self::get_param(
112 + $order = self::get_param(
66 113 array(
67 114 'param' => 'order',
68 115 'default' => 'DESC',
69 116 )
70 117 );
71 - $order = FrmDb::esc_order( $orderby . ' ' . $order );
72 118
119 + FrmAppController::apply_saved_sort_preference( $orderby, $order );
120 +
121 + if ( str_contains( $orderby, 'meta' ) ) {
122 + $order_field_type = FrmField::get_type( str_replace( 'meta_', '', $orderby ) );
123 +
124 + if ( in_array( $order_field_type, array( 'number', 'scale', 'star' ), true ) ) {
125 + $orderby .= '+0';
126 + }
127 + }
128 +
129 + return FrmDb::esc_order( $orderby . ' ' . $order );
130 + }
131 +
132 + /**
133 + * @since 6.5.4
134 + *
135 + * @param int $per_page
136 + *
137 + * @return string
138 + */
139 + protected function get_limit( $per_page ) {
73 140 $page = $this->get_pagenum();
74 141 $start = (int) self::get_param(
75 142 array(
76 143 'param' => 'start',
@@ -77,22 +144,61 @@
77 144 'default' => ( $page - 1 ) * $per_page,
78 145 )
79 146 );
80 147
81 - $limit = FrmDb::esc_limit( $start . ',' . $per_page );
82 - $this->items = FrmEntry::getAll( $s_query, $order, $limit, true, $join_form_in_query );
83 - $total_items = FrmEntry::getRecordCount( $s_query );
84 - $this->total_items = $total_items;
148 + return FrmDb::esc_limit( $start . ',' . $per_page );
149 + }
85 150
86 - $this->set_pagination_args(
151 + /**
152 + * @since 6.5.4
153 + *
154 + * @param bool $join_form_in_query
155 + *
156 + * @return array
157 + */
158 + protected function get_search_query( &$join_form_in_query ) {
159 + $form_id = $this->params['form'];
160 + $s_query = array();
161 +
162 + if ( $form_id ) {
163 + $form_ids = $this->get_form_ids( $form_id );
164 + $s_query['it.form_id'] = count( $form_ids ) > 1 ? $form_ids : $form_ids[0];
165 + } else {
166 + $s_query[] = array(
167 + 'or' => 1,
168 + 'parent_form_id' => null,
169 + 'parent_form_id <' => 1,
170 + );
171 + $join_form_in_query = true;
172 + }
173 +
174 + $s = self::get_param(
87 175 array(
88 - 'total_items' => $total_items,
89 - 'per_page' => $per_page,
176 + 'param' => 's',
177 + 'sanitize' => 'sanitize_text_field',
90 178 )
91 179 );
180 +
181 + if ( $s !== '' && FrmAppHelper::pro_is_installed() ) {
182 + $fid = self::get_param( array( 'param' => 'fid' ) );
183 + $s_query = FrmProEntriesHelper::get_search_str( $s_query, $s, $form_id, $fid );
184 + }
185 +
186 + return apply_filters( 'frm_entries_list_query', $s_query, compact( 'form_id' ) );
92 187 }
93 188
94 189 /**
190 + * @since 6.5.4
191 + *
192 + * @param int|string $form_id
193 + *
194 + * @return array<int>
195 + */
196 + protected function get_form_ids( $form_id ) {
197 + return array( (int) $form_id );
198 + }
199 +
200 + /**
95 201 * @return void
96 202 */
97 203 public function no_items() {
98 204 $s = self::get_param(
@@ -100,11 +206,23 @@
100 206 'param' => 's',
101 207 'sanitize' => 'sanitize_text_field',
102 208 )
103 209 );
104 - if ( ! empty( $s ) ) {
105 - esc_html_e( 'No Entries Found', 'formidable' );
106 210
211 + if ( $s !== '' ) {
212 + $current_url = set_url_scheme(
213 + 'http://' . FrmAppHelper::get_server_value( 'HTTP_HOST' ) . FrmAppHelper::get_server_value( 'REQUEST_URI' )
214 + );
215 + $clear_url = remove_query_arg( 's', $current_url );
216 +
217 + echo '<p>';
218 + printf(
219 + /* translators: %1$s: Start link HTML, %2$s: End link HTML */
220 + esc_html__( 'No entries match your search. %1$sClear search%2$s', 'formidable' ),
221 + '<a href="' . esc_url( $clear_url ) . '">',
222 + '</a>'
223 + );
224 + echo '</p>';
107 225 return;
108 226 }
109 227
110 228 $form_id = $this->params['form'];
@@ -112,8 +230,9 @@
112 230
113 231 if ( $form_id ) {
114 232 $form = FrmForm::getOne( $form_id );
115 233 }
234 +
116 235 $has_form = ! empty( $form );
117 236
118 237 if ( ! $has_form ) {
119 238 $has_form = FrmForm::getAll( array(), '', 1 );
@@ -125,8 +244,11 @@
125 244 include FrmAppHelper::plugin_path() . '/classes/views/frm-entries/no_entries.php';
126 245 }
127 246
128 247 /**
248 + * @param string $text Text.
249 + * @param string $input_id Input ID.
250 + *
129 251 * @return void
130 252 */
131 253 public function search_box( $text, $input_id ) {
132 254 // Searching is a pro feature
@@ -132,40 +254,56 @@
132 254 // Searching is a pro feature
133 255 }
134 256
135 257 /**
258 + * @param string $which
259 + *
136 260 * @return void
137 261 */
138 262 protected function display_tablenav( $which ) {
139 - $is_footer = ( $which !== 'top' );
263 + $is_footer = $which !== 'top';
264 +
140 265 if ( $is_footer && ! empty( $this->items ) ) {
266 + $utm = array(
267 + 'campaign' => 'spam-protection',
268 + 'content' => 'entries-list-spam-protection',
269 + );
270 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
141 271 ?>
142 272 <p>
143 273 <?php esc_html_e( 'Getting spam form submissions?', 'formidable' ); ?>
144 - <a href="https://formidableforms.com/knowledgebase/add-spam-protection/" target="_blank">
274 + <a href="<?php echo esc_url( FrmAppHelper::admin_upgrade_link( $utm, 'knowledgebase/add-spam-protection/' ) ); ?>" target="_blank">
145 275 <?php esc_html_e( 'Learn how to prevent them.', 'formidable' ); ?>
146 276 </a>
147 277 </p>
148 278 <?php
279 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
149 280 }
150 281 parent::display_tablenav( $which );
151 282 }
152 283
153 284 /**
285 + * @param string $which
286 + *
154 287 * @return void
155 288 */
156 289 protected function extra_tablenav( $which ) {
157 290 $form_id = FrmAppHelper::simple_get( 'form', 'absint' );
158 - if ( $which === 'top' && ! $form_id ) {
159 - echo '<div class="alignleft actions">';
160 291
161 - // Override the referrer to prevent it from being used for the screen options.
162 - echo '<input type="hidden" name="_wp_http_referer" value="" />';
292 + if ( $which !== 'top' || $form_id ) {
293 + return;
294 + }
163 295
164 - FrmFormsHelper::forms_dropdown( 'form', $form_id, array( 'blank' => __( 'View all forms', 'formidable' ) ) );
165 - submit_button( __( 'Filter', 'formidable' ), 'filter_action action', '', false, array( 'id' => 'post-query-submit' ) );
166 - echo '</div>';
167 - }
296 + echo '<div class="alignleft actions">';
297 +
298 + // Override the referrer to prevent it from being used for the screen options.
299 + echo '<input type="hidden" name="_wp_http_referer" value="" />';
300 +
301 + echo '<label for="form" class="screen-reader-text">' . esc_html__( 'Filter by form', 'formidable' ) . '</label>';
302 +
303 + FrmFormsHelper::forms_dropdown( 'form', $form_id, array( 'blank' => __( 'View all forms', 'formidable' ) ) );
304 + submit_button( __( 'Filter', 'formidable' ), 'filter_action action', '', false, array( 'id' => 'post-query-submit' ) );
305 + echo '</div>';
168 306 }
169 307
170 308 /**
171 309 * Gets the name of the primary column in the Entries screen
@@ -171,18 +309,17 @@
171 309 * Gets the name of the primary column in the Entries screen
172 310 *
173 311 * @since 2.0.14
174 312 *
175 - * @return string $primary_column
313 + * @return string Primary column.
176 314 */
177 315 protected function get_primary_column_name() {
178 - $columns = get_column_headers( $this->screen );
179 - $hidden = get_hidden_columns( $this->screen );
180 -
316 + $columns = get_column_headers( $this->screen );
317 + $hidden = get_hidden_columns( $this->screen );
181 318 $primary_column = '';
182 319
183 320 foreach ( $columns as $column_key => $column_display_name ) {
184 - if ( 'cb' != $column_key && ! in_array( $column_key, $hidden ) ) {
321 + if ( 'cb' !== $column_key && ! in_array( $column_key, $hidden, true ) ) {
185 322 $primary_column = $column_key;
186 323 break;
187 324 }
188 325 }
@@ -190,10 +327,28 @@
190 327 return $primary_column;
191 328 }
192 329
193 330 /**
331 + * @since 6.12
332 + *
333 + * @param object $item
334 + *
194 335 * @return string
195 336 */
337 + private static function get_entry_label( $item ) {
338 + if ( $item->name ) {
339 + return $item->name;
340 + }
341 + /* translators: %d: Entry id */
342 + return sprintf( __( 'Entry %d', 'formidable' ), $item->id );
343 + }
344 +
345 + /**
346 + * @param stdClass $item
347 + * @param string $style
348 + *
349 + * @return string
350 + */
196 351 public function single_row( $item, $style = '' ) {
197 352 // Set up the hover actions for this user
198 353 $actions = array();
199 354 $view_link = '?page=formidable-entries&frm_action=show&id=' . $item->id;
@@ -203,8 +358,10 @@
203 358 $action_links = $this->row_actions( $actions );
204 359
205 360 // Set up the checkbox ( because the user is editable, otherwise its empty )
206 361 $checkbox = "<input type='checkbox' name='item-action[]' id='cb-item-action-{$item->id}' value='{$item->id}' />";
362 + /* translators: %s: Form name */
363 + $checkbox .= "<label for='cb-item-action-{$item->id}'><span class='screen-reader-text'>" . esc_html( sprintf( __( 'Select %s', 'formidable' ), self::get_entry_label( $item ) ) ) . '</span></label>'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
207 364
208 365 $r = "<tr id='item-action-{$item->id}'$style>";
209 366
210 367 list( $columns, $hidden, , $primary ) = $this->get_column_info();
@@ -218,9 +375,9 @@
218 375 $class .= ' column-primary';
219 376 }
220 377
221 378 if ( in_array( $column_name, $hidden, true ) ) {
222 - $class .= ' frm_hidden';
379 + $class .= ' hidden';
223 380 } elseif ( ! $action_col && ! in_array( $column_name, $action_columns, true ) ) {
224 381 $action_col = $column_name;
225 382 }
226 383
@@ -225,10 +382,9 @@
225 382 }
226 383
227 384 $attributes = 'class="' . esc_attr( $class ) . '"';
228 385 unset( $class );
229 - $attributes .= ' data-colname="' . $column_display_name . '"';
230 -
386 + $attributes .= ' data-colname="' . $column_display_name . '"';
231 387 $form_id = $this->params['form'] ? $this->params['form'] : 0;
232 388 $this->column_name = preg_replace( '/^(' . $form_id . '_)/', '', $column_name );
233 389
234 390 if ( $this->column_name === 'cb' ) {
@@ -233,29 +389,25 @@
233 389
234 390 if ( $this->column_name === 'cb' ) {
235 391 $r .= "<th scope='row' class='check-column'>$checkbox</th>";
236 392 } else {
237 - if ( in_array( $column_name, $hidden, true ) ) {
238 - $val = '';
239 - } else {
240 - $val = $this->column_value( $item );
241 - }
393 + $val = in_array( $column_name, $hidden, true ) ? '' : $this->column_value( $item );
394 + $r .= "<td $attributes>";
242 395
243 - $r .= "<td $attributes>";
396 + // phpcs:ignore Universal.Operators.StrictComparisons
244 397 if ( $column_name == $action_col ) {
245 398 $edit_link = admin_url( 'admin.php?page=formidable-entries&frm_action=edit&id=' . $item->id );
246 - $r .= '<a href="' . esc_url( isset( $actions['edit'] ) ? $edit_link : $view_link ) . '" class="row-title" >' . $val . '</a> ';
247 - $r .= $action_links;
399 + $r .= '<a href="' . esc_url( isset( $actions['edit'] ) ? $edit_link : $view_link ) . '" class="row-title" >' . $val . '</a> ';
400 + $r .= $action_links;
248 401 } else {
249 402 $r .= $val;
250 403 }
404 +
251 405 $r .= '</td>';
252 - }
406 + }//end if
253 407 unset( $val );
254 - }
255 - $r .= '</tr>';
256 -
257 - return $r;
408 + }//end foreach
409 + return $r . '</tr>';
258 410 }
259 411
260 412 /**
261 413 * Get the column names that the logged in user can action on
@@ -267,11 +419,13 @@
267 419 }
268 420
269 421 /**
270 422 * @param object $item
423 + *
424 + * @return mixed
271 425 */
272 426 private function column_value( $item ) {
273 - $col_name = $this->column_name;
427 + $col_name = $this->maybe_fix_column_name( $this->column_name );
274 428
275 429 switch ( $col_name ) {
276 430 case 'ip':
277 431 case 'id':
@@ -286,13 +440,19 @@
286 440 $date = FrmAppHelper::get_formatted_time( $item->{$col_name} );
287 441 $val = '<abbr title="' . esc_attr( FrmAppHelper::get_formatted_time( $item->{$col_name}, '', 'g:i:s A' ) ) . '">' . $date . '</abbr>';
288 442 break;
289 443 case 'is_draft':
290 - $val = empty( $item->is_draft ) ? esc_html__( 'No', 'formidable' ) : esc_html__( 'Yes', 'formidable' );
444 + $entry_status = FrmEntriesHelper::get_entry_status_label( $item->is_draft );
445 + $val = sprintf(
446 + '<span class="frm-meta-tag frm-entry-status frm-entry-status-%s">%s</span>',
447 + sanitize_html_class( $item->is_draft ),
448 + esc_html( $entry_status )
449 + );
291 450 break;
292 451 case 'form_id':
293 452 $form_id = $item->form_id;
294 453 $user_can_edit_forms = false === FrmAppHelper::permission_nonce_error( 'frm_edit_forms' );
454 +
295 455 if ( $user_can_edit_forms ) {
296 456 $val = FrmFormsHelper::edit_form_link( $form_id );
297 457 } else {
298 458 $val = FrmFormsHelper::edit_form_link_label( $form_id );
@@ -309,8 +469,9 @@
309 469 $val = $item->parent_item_id;
310 470 break;
311 471 default:
312 472 $val = apply_filters( 'frm_entries_' . $col_name . '_column', false, compact( 'item' ) );
473 +
313 474 if ( $val === false ) {
314 475 $this->get_column_value( $item, $val );
315 476 }
316 477
@@ -322,26 +483,42 @@
322 483 * @param mixed $val Column value.
323 484 * @param array $args Contains `item` and `col_name`.
324 485 */
325 486 $val = apply_filters( 'frm_entries_column_value', $val, compact( 'item', 'col_name' ) );
326 - }
487 + }//end switch
327 488
328 489 return $val;
329 490 }
330 491
331 492 /**
493 + * When a form has entries with the 0 item meta value, the values do not appear properly in the entries list.
494 + *
495 + * @since 6.11.2
496 + *
497 + * @param string $column_name
498 + *
499 + * @return string
500 + */
501 + private function maybe_fix_column_name( $column_name ) {
502 + if ( str_starts_with( $column_name, '0_' ) ) {
503 + return substr( $column_name, 2 );
504 + }
505 + return $column_name;
506 + }
507 +
508 + /**
509 + * @param array $actions
510 + * @param object $item
332 511 * @param string $view_link
333 - * @param array $actions
334 - * @param object $item
335 512 *
336 513 * @return void
337 514 */
338 515 private function get_actions( &$actions, $item, $view_link ) {
339 - $actions['view'] = '<a href="' . esc_url( $view_link ) . '">' . __( 'View', 'formidable' ) . '</a>';
516 + $actions['view'] = '<a href="' . esc_url( $view_link ) . '">' . esc_html__( 'View', 'formidable' ) . '</a>';
340 517
341 518 if ( current_user_can( 'frm_delete_entries' ) ) {
342 519 $delete_link = '?page=formidable-entries&frm_action=destroy&id=' . $item->id . '&form=' . $this->params['form'];
343 - $actions['delete'] = '<a href="' . esc_url( wp_nonce_url( $delete_link ) ) . '" class="submitdelete" data-frmverify="' . esc_attr__( 'Permanently delete this entry?', 'formidable' ) . '" data-frmverify-btn="frm-button-red">' . __( 'Delete', 'formidable' ) . '</a>';
520 + $actions['delete'] = '<a href="' . esc_url( wp_nonce_url( $delete_link ) ) . '" class="submitdelete" data-frmverify="' . esc_attr__( 'Permanently delete this entry?', 'formidable' ) . '" data-frmverify-btn="frm-button-red">' . esc_html__( 'Delete', 'formidable' ) . '</a>'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
344 521 }
345 522
346 523 $actions = apply_filters( 'frm_row_actions', $actions, $item );
347 524 }
@@ -346,9 +523,10 @@
346 523 $actions = apply_filters( 'frm_row_actions', $actions, $item );
347 524 }
348 525
349 526 /**
350 - * @param false $val
527 + * @param object $item
528 + * @param mixed $val
351 529 *
352 530 * @return void
353 531 */
354 532 private function get_column_value( $item, &$val ) {
@@ -353,9 +531,9 @@
353 531 */
354 532 private function get_column_value( $item, &$val ) {
355 533 $col_name = $this->column_name;
356 534
357 - if ( strpos( $col_name, 'frmsep_' ) === 0 ) {
535 + if ( str_starts_with( $col_name, 'frmsep_' ) ) {
358 536 $sep_val = true;
359 537 $col_name = str_replace( 'frmsep_', '', $col_name );
360 538 } else {
361 539 $sep_val = false;
@@ -360,13 +538,14 @@
360 538 } else {
361 539 $sep_val = false;
362 540 }
363 541
364 - if ( strpos( $col_name, '-_-' ) ) {
542 + if ( str_contains( $col_name, '-_-' ) ) {
365 543 list( $col_name, $embedded_field_id ) = explode( '-_-', $col_name );
366 544 }
367 545
368 546 $field = FrmField::getOne( $col_name );
547 +
369 548 if ( ! $field ) {
370 549 return;
371 550 }
372 551
@@ -393,7 +572,19 @@
393 572 /**
394 573 * @return string
395 574 */
396 575 protected function confirm_bulk_delete() {
397 - return __( 'ALL selected entries in this form will be permanently deleted. Want to proceed?', 'formidable' );
576 + return sprintf(
577 + /* translators: %1$s: HTML break line, %2$s: HTML bold text */
578 + esc_html__( 'ALL entries in this form will be permanently deleted.%1$sWant to proceed? Type %2$s below.', 'formidable' ),
579 + '<br/>',
580 + '<b>DELETE ALL</b>'
581 + );
582 + }
583 +
584 + /**
585 + * @return string
586 + */
587 + protected function loaded_from() {
588 + return 'entries-list';
398 589 }
399 590 }