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/FrmFormsListHelper.php +396 -77 6.26 → trunk View file →
@@ -11,8 +11,11 @@
11 11 public $status = '';
12 12
13 13 public $total_items = 0;
14 14
15 + /**
16 + * @param array $args
17 + */
15 18 public function __construct( $args ) {
16 19 $this->status = self::get_param( array( 'param' => 'form_type' ) );
17 20
18 21 parent::__construct( $args );
@@ -26,19 +29,20 @@
26 29 /**
27 30 * @return void
28 31 */
29 32 public function prepare_items() {
30 - global $wpdb, $per_page, $mode;
33 + global $per_page, $mode;
31 34
32 35 $page = $this->get_pagenum();
33 36 $per_page = $this->get_items_per_page( 'formidable_page_formidable_per_page' );
34 37
35 - $mode = self::get_param(
38 + $mode = self::get_param(
36 39 array(
37 40 'param' => 'mode',
38 41 'default' => 'list',
39 42 )
40 43 );
44 +
41 45 $orderby = self::get_param(
42 46 array(
43 47 'param' => 'orderby',
44 48 'default' => 'name',
@@ -52,9 +56,9 @@
52 56 );
53 57
54 58 FrmAppController::apply_saved_sort_preference( $orderby, $order );
55 59
56 - $start = self::get_param(
60 + $start = self::get_param(
57 61 array(
58 62 'param' => 'start',
59 63 'default' => ( $page - 1 ) * $per_page,
60 64 )
@@ -87,9 +91,9 @@
87 91 'sanitize' => 'sanitize_text_field',
88 92 )
89 93 );
90 94
91 - if ( $s != '' ) {
95 + if ( $s !== '' ) {
92 96 preg_match_all( '/".*?("|$)|((?<=[\\s",+])|^)[^\\s",+]+/', $s, $matches );
93 97 $search_terms = array_map( 'trim', $matches[0] );
94 98
95 99 foreach ( $search_terms as $term ) {
@@ -120,16 +124,42 @@
120 124 /**
121 125 * @return void
122 126 */
123 127 public function no_items() {
128 + $s = self::get_param(
129 + array(
130 + 'param' => 's',
131 + 'sanitize' => 'sanitize_text_field',
132 + )
133 + );
134 +
135 + if ( $s !== '' ) {
136 + $current_url = set_url_scheme(
137 + 'http://' . FrmAppHelper::get_server_value( 'HTTP_HOST' ) . FrmAppHelper::get_server_value( 'REQUEST_URI' )
138 + );
139 + $clear_url = remove_query_arg( 's', $current_url );
140 +
141 + echo '<p>';
142 + printf(
143 + /* translators: %1$s: Start link HTML, %2$s: End link HTML */
144 + esc_html__( 'No forms match your search. %1$sClear search%2$s', 'formidable' ),
145 + '<a href="' . esc_url( $clear_url ) . '">',
146 + '</a>'
147 + );
148 + echo '</p>';
149 + return;
150 + }
151 +
124 152 if ( $this->status === 'trash' ) {
125 153 echo '<p>';
126 154 esc_html_e( 'No forms found in the trash.', 'formidable' );
155 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
127 156 ?>
128 157 <a href="<?php echo esc_url( admin_url( 'admin.php?page=formidable' ) ); ?>">
129 158 <?php esc_html_e( 'See all forms.', 'formidable' ); ?>
130 159 </a>
131 160 <?php
161 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
132 162 echo '</p>';
133 163 } else {
134 164 $title = __( 'No Forms Found', 'formidable' );
135 165 include FrmAppHelper::plugin_path() . '/classes/views/frm-forms/_no_forms.php';
@@ -165,15 +195,19 @@
165 195 if ( 'top' !== $which ) {
166 196 return;
167 197 }
168 198
169 - if ( 'trash' === $this->status && current_user_can( 'frm_delete_forms' ) ) {
170 - ?>
171 - <div class="alignleft actions frm_visible_overflow">
172 - <?php submit_button( __( 'Empty Trash', 'formidable' ), 'apply', 'delete_all', false ); ?>
173 - </div>
174 - <?php
199 + if ( 'trash' !== $this->status || ! current_user_can( 'frm_delete_forms' ) ) {
200 + return;
175 201 }
202 +
203 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
204 + ?>
205 + <div class="alignleft actions frm_visible_overflow">
206 + <?php submit_button( __( 'Empty Trash', 'formidable' ), 'apply', 'delete_all', false ); ?>
207 + </div>
208 + <?php
209 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
176 210 }
177 211
178 212 /**
179 213 * @return array
@@ -200,18 +234,13 @@
200 234 )
201 235 );
202 236
203 237 foreach ( $statuses as $status => $name ) {
238 + $class = $status == $form_type ? ' class="current"' : ''; // phpcs:ignore Universal.Operators.StrictComparisons
204 239
205 - if ( $status == $form_type ) {
206 - $class = ' class="current"';
207 - } else {
208 - $class = '';
209 - }
210 -
211 240 if ( $counts->{$status} || 'draft' !== $status ) {
212 241 /* translators: %1$s: Status, %2$s: Number of items */
213 - $links[ $status ] = '<a href="' . esc_url( '?page=formidable&form_type=' . $status ) . '" ' . $class . '>' . sprintf( __( '%1$s <span class="count">(%2$s)</span>', 'formidable' ), $name, number_format_i18n( $counts->{$status} ) ) . '</a>';
242 + $links[ $status ] = '<a href="' . esc_url( '?page=formidable&form_type=' . $status ) . '" ' . $class . '>' . sprintf( __( '%1$s <span class="count">(%2$s)</span>', 'formidable' ), $name, number_format_i18n( $counts->{$status} ) ) . '</a>'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
214 243 }
215 244
216 245 unset( $status, $name );
217 246 }
@@ -219,23 +248,8 @@
219 248 return $links;
220 249 }
221 250
222 251 /**
223 - * @param string $which
224 - *
225 - * @return void
226 - */
227 - public function pagination( $which ) {
228 - global $mode;
229 -
230 - parent::pagination( $which );
231 -
232 - if ( 'top' === $which ) {
233 - $this->view_switcher( $mode );
234 - }
235 - }
236 -
237 - /**
238 252 * @param stdClass $item
239 253 * @param string $style
240 254 *
241 255 * @return string
@@ -240,9 +254,9 @@
240 254 *
241 255 * @return string
242 256 */
243 257 public function single_row( $item, $style = '' ) {
244 - global $frm_vars, $mode;
258 + global $mode;
245 259
246 260 // Set up the hover actions for this user
247 261 $actions = array();
248 262 $edit_link = FrmForm::get_edit_link( $item->id );
@@ -249,21 +263,11 @@
249 263
250 264 $this->get_actions( $actions, $item, $edit_link );
251 265
252 266 $action_links = $this->row_actions( $actions );
267 + $checkbox = $this->get_row_checkbox( $item );
268 + $r = '<tr id="item-action-' . absint( $item->id ) . '"' . $style . '>';
253 269
254 - // Set up the checkbox ( because the user is editable, otherwise its empty )
255 - $checkbox = '<input type="checkbox" name="item-action[]" id="cb-item-action-' . absint( $item->id ) . '" value="' . esc_attr( $item->id ) . '" />';
256 - $checkbox_label_text = sprintf(
257 - // translators: Form title
258 - __( 'Select %s', 'formidable' ),
259 - ! empty( $item->name ) ? $item->name : FrmFormsHelper::get_no_title_text()
260 - );
261 -
262 - $checkbox .= '<label for="cb-item-action-' . absint( $item->id ) . '"><span class="screen-reader-text">' . esc_html( $checkbox_label_text ) . '</span></label>';
263 -
264 - $r = '<tr id="item-action-' . absint( $item->id ) . '"' . $style . '>';
265 -
266 270 list( $columns, $hidden ) = $this->get_column_info();
267 271
268 272 $format = 'Y/m/d';
269 273
@@ -272,13 +276,12 @@
272 276 }
273 277
274 278 foreach ( $columns as $column_name => $column_display_name ) {
275 279 $class = $column_name . ' column-' . $column_name . ( 'name' === $column_name ? ' post-title page-title column-title' : '' );
276 -
277 280 $style = '';
278 281
279 282 if ( in_array( $column_name, $hidden, true ) ) {
280 - $class .= ' frm_hidden';
283 + $class .= ' hidden';
281 284 }
282 285
283 286 if ( $column_name === 'name' ) {
284 287 $class .= ' column-primary';
@@ -283,11 +286,10 @@
283 286 if ( $column_name === 'name' ) {
284 287 $class .= ' column-primary';
285 288 }
286 289
287 - $class = 'class="' . esc_attr( $class ) . '"';
288 - $data_colname = ' data-colname="' . esc_attr( $column_display_name ) . '"';
289 - $attributes = $class . $style . $data_colname;
290 + $class = 'class="' . esc_attr( $class ) . '"';
291 + $attributes = $class . $style . $this->get_column_data_attr( $column_name, $column_display_name );
290 292
291 293 switch ( $column_name ) {
292 294 case 'cb':
293 295 $r .= '<th scope="row" class="check-column">' . $checkbox . '</th>';
@@ -304,21 +306,9 @@
304 306 $date = gmdate( $format, strtotime( $item->created_at ) );
305 307 $val = '<abbr title="' . esc_attr( gmdate( 'Y/m/d g:i:s A', strtotime( $item->created_at ) ) ) . '">' . $date . '</abbr>';
306 308 break;
307 309 case 'entries':
308 - if ( isset( $item->options['no_save'] ) && $item->options['no_save'] ) {
309 - $val = FrmAppHelper::icon_by_class(
310 - 'frmfont frm_forbid_icon frm_bstooltip',
311 - array(
312 - 'title' => __( 'Saving entries is disabled for this form', 'formidable' ),
313 - 'echo' => false,
314 - )
315 - );
316 - } else {
317 - $text = FrmEntry::getRecordCount( $item->id );
318 - $val = current_user_can( 'frm_view_entries' ) ? '<a href="' . esc_url( admin_url( 'admin.php?page=formidable-entries&form=' . $item->id ) ) . '">' . $text . '</a>' : $text;
319 - unset( $text );
320 - }
310 + $val = $this->get_entries_column_value( $item );
321 311 break;
322 312 default:
323 313 if ( method_exists( $this, 'column_' . $column_name ) ) {
324 314 $val = call_user_func( array( $this, 'column_' . $column_name ), $item ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -332,18 +322,67 @@
332 322 $r .= '</td>';
333 323 }
334 324 unset( $val );
335 325 }//end foreach
336 - $r .= '</tr>';
326 + return $r . '</tr>';
327 + }
337 328
338 - return $r;
329 + /**
330 + * @param string $column_name
331 + * @param string $column_display_name
332 + *
333 + * @return string
334 + */
335 + private function get_column_data_attr( $column_name, $column_display_name ) {
336 + if ( 'settings' === $column_name ) {
337 + return ' data-colname="' . esc_attr( trim( strip_tags( $column_display_name ) ) ) . '"';
338 + }
339 + return ' data-colname="' . esc_attr( $column_display_name ) . '"';
339 340 }
340 341
341 342 /**
343 + * @param object $item
344 + *
345 + * @return string
346 + */
347 + private function get_entries_column_value( $item ) {
348 + if ( ! empty( $item->options['no_save'] ) ) {
349 + return (string) FrmAppHelper::icon_by_class(
350 + 'frmfont frm_forbid_icon frm_bstooltip',
351 + array(
352 + 'title' => __( 'Saving entries is disabled for this form', 'formidable' ),
353 + 'echo' => false,
354 + )
355 + );
356 + }
357 +
358 + $text = intval( FrmEntry::getRecordCount( $item->id ) );
359 + return current_user_can( 'frm_view_entries' ) ? '<a href="' . esc_url( admin_url( 'admin.php?page=formidable-entries&form=' . $item->id ) ) . '">' . $text . '</a>' : (string) $text; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
360 + }
361 +
362 + /**
363 + * @param object $item
364 + *
365 + * @return string
366 + */
367 + private function get_row_checkbox( $item ) {
368 + // Set up the checkbox (because the user is editable, otherwise it's empty).
369 + $checkbox = '<input type="checkbox" name="item-action[]" id="cb-item-action-' . absint( $item->id ) . '" value="' . esc_attr( $item->id ) . '" />';
370 + $checkbox_label_text = sprintf(
371 + // translators: Form title
372 + __( 'Select %s', 'formidable' ),
373 + ! empty( $item->name ) ? $item->name : FrmFormsHelper::get_no_title_text()
374 + );
375 +
376 + return $checkbox . '<label for="cb-item-action-' . absint( $item->id ) . '"><span class="screen-reader-text">' . esc_html( $checkbox_label_text ) . '</span></label>';
377 + }
378 +
379 + /**
342 380 * Get the HTML for the Actions column in the form list.
343 381 * This includes multiple icons for triggering the embed modal, the visual styler, and an active landing page.
344 382 *
345 383 * @since 6.0
384 + * @deprecated 6.32 We moved these actions to other places. This column will show if there is a filter added to the hook.
346 385 *
347 386 * @param stdClass $form
348 387 *
349 388 * @return string
@@ -348,16 +387,15 @@
348 387 *
349 388 * @return string
350 389 */
351 390 protected function column_shortcode( $form ) {
352 - $val = '<a href="#" class="frm-embed-form" role="button" aria-label="' . esc_attr__( 'Embed Form', 'formidable' ) . '">' . FrmAppHelper::icon_by_class( 'frmfont frm_code_icon', array( 'echo' => false ) ) . '</a>';
391 + $val = '<a href="#" class="frm-embed-form" role="button" aria-label="' . esc_attr__( 'Embed Form', 'formidable' ) . '">' . FrmAppHelper::icon_by_class( 'frmfont frm_code_icon', array( 'echo' => false ) ) . '</a>'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
353 392 $val .= $this->column_style( $form );
354 393 $val .= $this->column_views( $form );
355 394 $val = apply_filters( 'frm_form_list_actions', $val, array( 'form' => $form ) );
356 395 // Remove the space hard coded in Landing pages.
357 396 $val = str_replace( '&nbsp;', '', $val );
358 - $val = '<div>' . $val . '</div>';
359 - return $val;
397 + return '<div>' . $val . '</div>';
360 398 }
361 399
362 400 /**
363 401 * Get the HTML for the Style column in the form list.
@@ -385,9 +423,9 @@
385 423 $style = $frm_style->get_one();
386 424 }
387 425
388 426 $href = FrmStylesHelper::get_edit_url( $style, $form->id );
389 - return '<a href="' . esc_url( $href ) . '" title="' . esc_attr( $style->post_title ) . '">' . FrmAppHelper::icon_by_class( 'frmfont frm_pallet_icon', array( 'echo' => false ) ) . '</a>';
427 + return '<a href="' . esc_url( $href ) . '" title="' . esc_attr( $style->post_title ) . '">' . FrmAppHelper::icon_by_class( 'frmfont frm_pallet_icon', array( 'echo' => false ) ) . '</a>'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
390 428 }
391 429
392 430 /**
393 431 * Generate the HTML for the form Views page.
@@ -404,14 +442,34 @@
404 442 'title' => __( 'Link to list of all views for this form.', 'formidable' ),
405 443 'target' => '_blank',
406 444 );
407 445
446 + if ( class_exists( 'FrmViewsDisplay' ) ) {
447 + $view_ids = FrmViewsDisplay::get_display_ids_by_form( $form->id );
448 + $view_count = $view_ids ? count( $view_ids ) : 0;
449 + } else {
450 + $view_count = 0;
451 + }
452 +
453 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
408 454 return '<a ' . FrmAppHelper::array_to_html_params( $attributes ) . '>
409 - ' . FrmAppHelper::icon_by_class( 'frmfont frm_eye_icon', array( 'echo' => false ) ) .
455 + ' . intval( $view_count ) .
410 456 '</a>';
457 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
411 458 }
412 459
413 460 /**
461 + * Get the HTML for the Settings column in the form list.
462 + *
463 + * @since 6.32
464 + *
465 + * @return string
466 + */
467 + protected function column_settings() {
468 + return '&nbsp;';
469 + }
470 +
471 + /**
414 472 * @param array $actions
415 473 * @param object $item
416 474 * @param string $edit_link
417 475 *
@@ -429,14 +487,15 @@
429 487 return;
430 488 }
431 489
432 490 if ( current_user_can( 'frm_edit_forms' ) ) {
433 - $actions['frm_edit'] = '<a href="' . esc_url( $edit_link ) . '">' . __( 'Edit', 'formidable' ) . '</a>';
434 - $actions['frm_settings'] = '<a href="' . esc_url( '?page=formidable&frm_action=settings&id=' . $item->id ) . '">' . __( 'Settings', 'formidable' ) . '</a>';
491 + $actions['frm_edit'] = '<a href="' . esc_url( $edit_link ) . '">' . esc_html__( 'Edit', 'formidable' ) . '</a>';
492 + $actions['frm_settings'] = '<a href="' . esc_url( '?page=formidable&frm_action=settings&id=' . $item->id ) . '">' . esc_html__( 'Settings', 'formidable' ) . '</a>';
435 493 }
436 494
437 - $actions = array_merge( $actions, $new_actions );
438 - $actions['view'] = '<a href="' . esc_url( FrmFormsHelper::get_direct_link( $item->form_key, $item ) ) . '" target="_blank">' . __( 'Preview', 'formidable' ) . '</a>';
495 + $actions = array_merge( $actions, $new_actions );
496 + $actions['embed'] = '<a href="#" class="frm-embed-form" role="button" aria-label="' . esc_attr__( 'Embed Form', 'formidable' ) . '">' . esc_html__( 'Embed', 'formidable' ) . '</a>'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
497 + $actions['view'] = '<a href="' . esc_url( FrmFormsHelper::get_direct_link( $item->form_key, $item ) ) . '" target="_blank">' . esc_html__( 'Preview', 'formidable' ) . '</a>'; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
439 498 }
440 499
441 500 /**
442 501 * @param object $item
@@ -454,9 +513,9 @@
454 513 }
455 514
456 515 $form_name = FrmAppHelper::kses( $form_name );
457 516
458 - if ( 'excerpt' != $mode ) {
517 + if ( 'excerpt' !== $mode ) {
459 518 $form_name = FrmAppHelper::truncate( $form_name, 50 );
460 519 }
461 520
462 521 $val = '<strong>';
@@ -463,9 +522,9 @@
463 522
464 523 if ( 'trash' === $this->status ) {
465 524 $val .= $form_name;
466 525 } else {
467 - $val .= '<a href="' . esc_url( isset( $actions['frm_edit'] ) ? $edit_link : FrmFormsHelper::get_direct_link( $item->form_key, $item ) ) . '" class="row-title">' . FrmAppHelper::kses( $form_name ) . '</a> ';
526 + $val .= '<a href="' . esc_url( isset( $actions['frm_edit'] ) ? $edit_link : FrmFormsHelper::get_direct_link( $item->form_key, $item ) ) . '" class="row-title">' . FrmAppHelper::kses( $form_name ) . '</a> '; // phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong
468 527 }
469 528
470 529 $this->add_draft_label( $item, $val );
471 530 $val .= '</strong>';
@@ -481,9 +540,9 @@
481 540 *
482 541 * @return void
483 542 */
484 543 private function add_draft_label( $item, &$val ) {
485 - if ( 'draft' === $item->status && 'draft' != $this->status ) {
544 + if ( 'draft' === $item->status && 'draft' !== $this->status ) {
486 545 $val .= ' - <span class="post-state">' . esc_html__( 'Draft', 'formidable' ) . '</span>';
487 546 }
488 547 }
489 548
@@ -505,6 +564,266 @@
505 564 * @return string
506 565 */
507 566 protected function confirm_bulk_delete() {
508 567 return __( 'ALL selected forms and their entries will be permanently deleted. Want to proceed?', 'formidable' );
568 + }
569 +
570 + /**
571 + * @param stdClass $form
572 + *
573 + * @return string
574 + */
575 + public function column_embeds( $form ) {
576 + if ( $this->column_is_hidden( 'embeds' ) ) {
577 + // Locating embeds means scanning post_content, so skip it when the column is hidden.
578 + return '';
579 + }
580 +
581 + $posts = $this->get_posts_contain_form( $form );
582 +
583 + if ( ! $posts ) {
584 + return '<span class="frm-forms-list-embeds-zero">0</span>';
585 + }
586 +
587 + return FrmAppHelper::clip(
588 + function () use ( $posts ) {
589 + ?>
590 + <a href="#" class="frm-forms-list-embeds-btn" data-posts="<?php echo esc_attr( wp_json_encode( $posts ) ); ?>">
591 + <?php
592 + FrmAppHelper::icon_by_class( 'frmfont frm_arrowdown6_icon' );
593 + echo intval( count( $posts ) );
594 + ?>
595 + </a>
596 + <?php
597 + }
598 + );
599 + }
600 +
601 + /**
602 + * Checks if a column is hidden with Screen Options.
603 + *
604 + * @since 6.35
605 + *
606 + * @param string $column_name Column name.
607 + *
608 + * @return bool
609 + */
610 + private function column_is_hidden( $column_name ) {
611 + $column_info = $this->get_column_info();
612 +
613 + if ( ! isset( $column_info[1] ) || ! is_array( $column_info[1] ) ) {
614 + return false;
615 + }
616 +
617 + return in_array( $column_name, $column_info[1], true );
618 + }
619 +
620 + /**
621 + * Gets posts or pages that contain the form shortcode.
622 + *
623 + * @since 6.32
624 + *
625 + * @param stdClass $form Form object.
626 + *
627 + * @return array
628 + */
629 + private function get_posts_contain_form( $form ) {
630 + $cached_posts = FrmFormEmbedsHelper::get_cached_posts();
631 +
632 + if ( ! isset( $cached_posts[ $form->id ] ) || ! is_array( $cached_posts[ $form->id ] ) ) {
633 + // A single scan covers every form listed on this page, not just this one.
634 + $cached_posts = $this->fill_embed_posts_cache( $form );
635 + }
636 +
637 + if ( ! isset( $cached_posts[ $form->id ] ) || ! is_array( $cached_posts[ $form->id ] ) ) {
638 + return array();
639 + }
640 +
641 + // Links and title fallbacks are derived at render time, not stored. get_edit_post_link()
642 + // depends on the current user, so caching it in a shared transient would hand one user's
643 + // edit link to another, and a permalink cached now goes stale on any slug change.
644 + return FrmFormEmbedsHelper::prepare_posts( $cached_posts[ $form->id ] );
645 + }
646 +
647 + /**
648 + * Scans for embeds once and caches the result for every form listed on the current page.
649 + *
650 + * @since 6.35
651 + *
652 + * @param stdClass $form The form whose column is currently rendering.
653 + *
654 + * @return array Embed posts keyed by form ID.
655 + */
656 + private function fill_embed_posts_cache( $form ) {
657 + $cached_posts = FrmFormEmbedsHelper::get_cached_posts();
658 + $search_map = array();
659 + $forms = array();
660 +
661 + foreach ( $this->get_forms_to_scan( $form ) as $form_id => $form_to_scan ) {
662 + if ( isset( $cached_posts[ $form_id ] ) && is_array( $cached_posts[ $form_id ] ) ) {
663 + continue;
664 + }
665 +
666 + $search_map[ $form_id ] = $this->get_search_strings_for_form( $form_id );
667 + $forms[ $form_id ] = $form_to_scan;
668 + }
669 +
670 + if ( ! $forms ) {
671 + return $cached_posts;
672 + }
673 +
674 + $matched = FrmFormEmbedsHelper::match_candidate_posts( $search_map );
675 +
676 + foreach ( $forms as $form_id => $form_to_scan ) {
677 + $posts = $this->filter_embed_posts( $matched[ $form_id ], $form_to_scan );
678 + $cached_posts[ $form_id ] = FrmFormEmbedsHelper::slim_posts( $posts );
679 + }
680 +
681 + FrmFormEmbedsHelper::save_cached_posts( $cached_posts );
682 +
683 + return $cached_posts;
684 + }
685 +
686 + /**
687 + * Gets every form rendered on the current list page, keyed by form ID.
688 + *
689 + * @since 6.35
690 + *
691 + * @param stdClass $form The form whose column is currently rendering.
692 + *
693 + * @return array
694 + */
695 + private function get_forms_to_scan( $form ) {
696 + $forms = array( $form->id => $form );
697 +
698 + if ( ! is_array( $this->items ) ) {
699 + return $forms;
700 + }
701 +
702 + foreach ( $this->items as $item ) {
703 + if ( is_object( $item ) && isset( $item->id ) ) {
704 + $forms[ $item->id ] = $item;
705 + }
706 + }
707 +
708 + return $forms;
709 + }
710 +
711 + /**
712 + * Applies the frm_get_posts_contain_form filter to a form's embed posts.
713 + *
714 + * @since 6.35
715 + *
716 + * @param array $posts Posts that embed the form.
717 + * @param stdClass $form Form object.
718 + *
719 + * @return array
720 + */
721 + private function filter_embed_posts( $posts, $form ) {
722 + /**
723 + * @since 6.32
724 + *
725 + * @param stdClass[] $posts
726 + * @param array $args
727 + */
728 + $filtered_posts = apply_filters( 'frm_get_posts_contain_form', $posts, compact( 'form' ) );
729 +
730 + if ( ! is_array( $filtered_posts ) ) {
731 + _doing_it_wrong( 'frm_get_posts_contain_form', 'Filter should return an array.', '6.32' );
732 + return $posts;
733 + }
734 +
735 + return $filtered_posts;
736 + }
737 +
738 + /**
739 + * Gets search strings for a form inside a post.
740 + *
741 + * @since 6.32
742 + *
743 + * @param int $form_id Form ID.
744 + *
745 + * @return string[]
746 + */
747 + protected function get_search_strings_for_form( $form_id ) {
748 + return $this->get_base_search_strings_for_form( $form_id );
749 + }
750 +
751 + /**
752 + * Gets the base search strings for a form inside a post.
753 + *
754 + * @since 6.32
755 + *
756 + * @param int $form_id Form ID.
757 + *
758 + * @return string[]
759 + */
760 + protected function get_base_search_strings_for_form( $form_id ) {
761 + $strings = array(
762 + '<!-- wp:formidable/simple-form {"formId":"' . $form_id . '"',
763 + );
764 +
765 + // The shortcode renders a form from its key just as happily as from its ID, in either
766 + // attribute, so all four spellings have to be searched or those pages never count.
767 + $identifiers = array( $form_id );
768 + $form_key = FrmForm::get_key_by_id( $form_id );
769 +
770 + if ( $form_key && $form_key !== (string) $form_id ) {
771 + $identifiers[] = $form_key;
772 + }
773 +
774 + foreach ( $identifiers as $identifier ) {
775 + foreach ( array( 'id', 'key' ) as $att ) {
776 + $strings[] = '[formidable ' . $att . '=' . $identifier . ']';
777 + $strings[] = '[formidable ' . $att . '=' . $identifier . ' ';
778 + $strings[] = '[formidable ' . $att . '="' . $identifier . '"';
779 + $strings[] = '[formidable ' . $att . "='" . $identifier . "'";
780 + }
781 + }
782 +
783 + return $strings;
784 + }
785 +
786 + /**
787 + * Maybe clear the embed posts transient when a post is inserted.
788 + *
789 + * @since 6.32
790 + *
791 + * @param int $post_id Post ID.
792 + * @param WP_Post $post Post object.
793 + * @param bool $update True when an existing post was updated rather than created.
794 + *
795 + * @return void
796 + */
797 + public static function maybe_clear_embed_posts_transient( $post_id, $post, $update = false ) {
798 + FrmFormEmbedsHelper::maybe_clear_on_insert( $post_id, $post, $update );
799 + }
800 +
801 + /**
802 + * Maybe clear the embed posts transient when a post is updated.
803 + *
804 + * @since 6.35
805 + *
806 + * @param int $post_id Post ID.
807 + * @param WP_Post $post_after Post object after the update.
808 + * @param WP_Post $post_before Post object before the update.
809 + *
810 + * @return void
811 + */
812 + public static function maybe_clear_embed_posts_transient_on_update( $post_id, $post_after, $post_before ) {
813 + FrmFormEmbedsHelper::maybe_clear_on_update( $post_id, $post_after, $post_before );
814 + }
815 +
816 + /**
817 + * Maybe clear the embed posts transient when a post is trashed, untrashed or deleted.
818 + *
819 + * @since 6.35
820 + *
821 + * @param int $post_id Post ID.
822 + * @param WP_Post|null $post Post object, when the hook provides one.
823 + *
824 + * @return void
825 + */
826 + public static function clear_embed_posts_transient_for_post( $post_id, $post = null ) {
827 + FrmFormEmbedsHelper::maybe_clear_for_post( $post_id, $post );
509 828 }
510 829 }