PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 0.0.11
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v0.0.11
2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 0.0.2 0.0.3 All 96 releases
sureforms / inc / post-types.php

post-types.php in SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz 0.0.11, at inc/post-types.php

1,316 lines 38.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Post Types Class file.
4 *
5 * @package sureforms.
6 * @since 0.0.1
7 */
8
9 namespace SRFM\Inc;
10
11 use WP_Query;
12 use WP_Admin_Bar;
13 use SRFM\Inc\Traits\Get_Instance;
14 use SRFM\Inc\Generate_Form_Markup;
15 use SRFM\Inc\Helper;
16
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit; // Exit if accessed directly.
19 }
20
21 /**
22 * Post Types Main Class.
23 *
24 * @since 0.0.1
25 */
26 class Post_Types {
27 use Get_Instance;
28
29 /**
30 * Constructor
31 *
32 * @since 0.0.1
33 */
34 public function __construct() {
35 $this->restrict_unwanted_insertions();
36 add_action( 'init', [ $this, 'register_post_types' ] );
37 add_action( 'init', [ $this, 'register_post_metas' ] );
38 add_filter( 'manage_sureforms_form_posts_columns', [ $this, 'custom_form_columns' ] );
39 add_action( 'manage_sureforms_form_posts_custom_column', [ $this, 'custom_form_column_data' ], 10, 2 );
40 add_filter( 'manage_sureforms_entry_posts_columns', [ $this, 'custom_entry_columns' ] );
41 add_action( 'manage_sureforms_entry_posts_custom_column', [ $this, 'custom_entry_column_data' ], 10, 2 );
42 add_shortcode( 'sureforms', [ $this, 'forms_shortcode' ] );
43 add_action( 'add_meta_boxes', [ $this, 'entries_meta_box' ] );
44 add_action( 'restrict_manage_posts', [ $this, 'add_tax_filter' ] );
45 add_action( 'manage_posts_extra_tablenav', [ $this, 'maybe_render_blank_form_state' ] );
46 add_action( 'in_admin_header', [ $this, 'embed_page_header' ] );
47 add_action( 'admin_head', [ $this, 'remove_entries_publishing_actions' ] );
48 add_filter( 'post_row_actions', [ $this, 'modify_entries_list_row_actions' ], 10, 2 );
49 add_filter( 'post_updated_messages', [ $this, 'entries_updated_message' ] );
50 add_filter( 'bulk_actions-edit-sureforms_form', [ $this, 'register_modify_bulk_actions' ], 99 );
51 add_action( 'admin_notices', [ $this, 'import_form_popup' ] );
52 add_action( 'admin_bar_menu', [ $this, 'remove_admin_bar_menu_item' ], 80, 1 );
53 add_action( 'template_redirect', [ $this, 'srfm_instant_form_redirect' ] );}
54
55 /**
56 * Add SureForms menu.
57 *
58 * @param string $title Parent slug.
59 * @param string $subtitle Parent slug.
60 * @param string $image Parent slug.
61 * @param string $button_text Parent slug.
62 * @param string $button_url Parent slug.
63 * @return void
64 * @since 0.0.1
65 */
66 public function get_blank_page_markup( $title, $subtitle, $image, $button_text = '', $button_url = '' ) {
67 echo '<div class="sureform-add-new-form">';
68
69 echo '<p class="sureform-blank-page-title">' . esc_html( $title ) . '</p>';
70
71 echo '<p class="sureform-blank-page-subtitle">' . esc_html( $subtitle ) . '</p>';
72
73 echo '<img src="' . esc_url( SRFM_URL . '/images/' . $image . '.svg' ) . '">';
74
75 if ( ! empty( $button_text ) && ! empty( $button_url ) ) {
76 echo '<div class="sureforms-add-new-form-container"><a class="sf-add-new-form-button" href="' . esc_url( $button_url ) . '"><div class="button-secondary">' . esc_html( $button_text ) . '</div></a></div>';
77 }
78
79 echo '</div>';
80 }
81
82 /**
83 * Render blank state for add new form screen.
84 *
85 * @param string $post_type Post type.
86 * @return void
87 * @since 0.0.1
88 */
89 public function sureforms_render_blank_state( $post_type ) {
90
91 if ( SRFM_FORMS_POST_TYPE === $post_type ) {
92 $page_name = 'add-new-form';
93 $new_form_url = admin_url( 'admin.php?page=' . $page_name );
94
95 $this->get_blank_page_markup(
96 esc_html__( 'Let’s build your first form', 'sureforms' ),
97 esc_html__(
98 'Craft beautiful and functional forms in minutes',
99 'sureforms'
100 ),
101 'add-new-form',
102 esc_html__( 'Add New Form', 'sureforms' ),
103 $new_form_url
104 );
105 }
106
107 if ( SRFM_ENTRIES_POST_TYPE === $post_type ) {
108
109 $this->get_blank_page_markup(
110 esc_html__( 'No records found', 'sureforms' ),
111 esc_html__(
112 'This is where your form entries will appear',
113 'sureforms'
114 ),
115 'blank-entries'
116 );
117 }
118 }
119
120 /**
121 * Registers the forms and submissions post types.
122 *
123 * @return void
124 * @since 0.0.1
125 */
126 public function register_post_types() {
127 $form_labels = [
128 'name' => _x( 'Forms', 'post type general name', 'sureforms' ),
129 'singular_name' => _x( 'Form', 'post type singular name', 'sureforms' ),
130 'menu_name' => _x( 'Forms', 'admin menu', 'sureforms' ),
131 'add_new' => _x( 'Add New', 'form', 'sureforms' ),
132 'add_new_item' => __( 'Add New Form', 'sureforms' ),
133 'new_item' => __( 'New Form', 'sureforms' ),
134 'edit_item' => __( 'Edit Form', 'sureforms' ),
135 'view_item' => __( 'View Form', 'sureforms' ),
136 'view_items' => __( 'View Forms', 'sureforms' ),
137 'all_items' => __( 'Forms', 'sureforms' ),
138 'search_items' => __( 'Search Forms', 'sureforms' ),
139 'parent_item_colon' => __( 'Parent Forms:', 'sureforms' ),
140 'not_found' => __( 'No forms found.', 'sureforms' ),
141 'not_found_in_trash' => __( 'No forms found in Trash.', 'sureforms' ),
142 'item_published' => __( 'Form published.', 'sureforms' ),
143 'item_updated' => __( 'Form updated.', 'sureforms' ),
144 ];
145 register_post_type(
146 SRFM_FORMS_POST_TYPE,
147 [
148 'labels' => $form_labels,
149 'rewrite' => [ 'slug' => 'form' ],
150 'public' => true,
151 'show_in_rest' => true,
152 'has_archive' => false,
153 'show_ui' => true,
154 'supports' => [ 'title', 'author', 'editor', 'custom-fields' ],
155 'show_in_menu' => 'sureforms_menu',
156 'show_in_nav_menus' => true,
157 ]
158 );
159
160 $result_labels = [
161 'name' => _x( 'Entries', 'post type general name', 'sureforms' ),
162 'singular_name' => _x( 'Entry', 'post type singular name', 'sureforms' ),
163 'menu_name' => _x( 'Entries', 'admin menu', 'sureforms' ),
164 'name_admin_bar' => _x( 'Entry', 'add new on admin bar', 'sureforms' ),
165 'add_new' => _x( 'Add New', 'Entry', 'sureforms' ),
166 'add_new_item' => __( 'Add New Entry', 'sureforms' ),
167 'new_item' => __( 'New Entry', 'sureforms' ),
168 'edit_item' => __( 'View Entry', 'sureforms' ),
169 'view_item' => __( 'View Entry', 'sureforms' ),
170 'all_items' => __( 'Entries', 'sureforms' ),
171 'search_items' => __( 'Search Entries', 'sureforms' ),
172 'parent_item_colon' => __( 'Parent Entries:', 'sureforms' ),
173 'not_found' => __( 'No results found.', 'sureforms' ),
174 'not_found_in_trash' => __( 'No results found in Trash.', 'sureforms' ),
175 ];
176 register_post_type(
177 SRFM_ENTRIES_POST_TYPE,
178 [
179 'labels' => $result_labels,
180 'supports' => [ 'title' ],
181 'public' => false,
182 'show_in_rest' => true,
183 'exclude_from_search' => true,
184 'publicly_queryable' => false,
185 'has_archive' => true,
186 'capability_type' => 'post',
187 'capabilities' => [
188 'create_posts' => 'do_not_allow',
189 ],
190 'map_meta_cap' => true,
191 'show_ui' => true,
192 'show_in_menu' => 'sureforms_menu',
193 ]
194 );
195 register_taxonomy(
196 'sureforms_tax',
197 'sureforms_entry',
198 [
199 'label' => __( 'Form ID', 'sureforms' ),
200 'hierarchical' => true,
201 'capabilities' => [
202 'assign_terms' => 'god',
203 'edit_terms' => 'god',
204 'manage_terms' => 'god',
205 ],
206 'public' => false,
207 'show_in_rest' => true,
208 'show_admin_column' => false,
209 'show_in_nav_menus' => false,
210 'show_ui' => false,
211 ]
212 );
213 // will be used later.
214 // register_post_status(
215 // 'unread',
216 // array(
217 // 'label' => _x( 'Unread', 'sureforms', 'sureforms' ),
218 // 'public' => true,
219 // 'exclude_from_search' => false,
220 // 'show_in_admin_all_list' => true,
221 // 'show_in_admin_status_list' => true,
222 // Translators: %s is the number of unread items.
223 // 'label_count' => _n_noop( 'Unread (%s)', 'Unread (%s)', 'sureforms' ),
224 // )
225 // );.
226 }
227
228 /**
229 * Remove add new form menu item.
230 *
231 * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance.
232 *
233 * @return void
234 * @since 0.0.1
235 */
236 public function remove_admin_bar_menu_item( $wp_admin_bar ) {
237 $wp_admin_bar->remove_node( 'new-sureforms_form' );
238 }
239
240 /**
241 * Modify post update message for Entry post type.
242 *
243 * @param string $messages Post type.
244 * @return string
245 * @since 0.0.1
246 */
247 public function entries_updated_message( $messages ) {
248 global $post_ID;
249
250 $post_type = get_post_type( $post_ID );
251
252 if ( SRFM_ENTRIES_POST_TYPE === $post_type ) {
253 // @phpstan-ignore-next-line -- False positive
254 $messages['post'][1] = __( 'Entry updated.', 'sureforms' );
255 }
256
257 return $messages;
258 }
259
260 /**
261 * Remove publishing actions from single entries page.
262 *
263 * @return void
264 * @since 0.0.1
265 */
266 public function remove_entries_publishing_actions() {
267 global $typenow;
268 if ( 'sureforms_entry' === $typenow ) { ?>
269 <style>
270 .misc-pub-post-status {
271 display: none !important;
272 }
273 .misc-pub-visibility {
274 display: none !important;
275 }
276 </style>
277 <?php
278 }
279 }
280
281 /**
282 * Modify list row actions.
283 *
284 * @param array<mixed> $actions An array of row action links.
285 * @param \WP_Post $post The current WP_Post object.
286 *
287 * @return array<mixed> $actions Modified row action links.
288 * @since 0.0.1
289 */
290 public function modify_entries_list_row_actions( $actions, $post ) {
291 if ( 'sureforms_entry' === $post->post_type ) {
292 $actions['edit'] = '<a href="' . get_edit_post_link( $post->ID ) . '">View</a>';
293 }
294 if ( 'sureforms_form' === $post->post_type ) {
295 $actions['export'] = '<a href="#" onclick="exportForm(' . $post->ID . ')">Export</a>';
296 }
297
298 return $actions;
299 }
300
301 /**
302 * Modify list bulk actions.
303 *
304 * @param array<mixed> $bulk_actions An array of bulk action links.
305 * @since 0.0.1
306 * @return array<mixed> $bulk_actions Modified action links.
307 */
308 public function register_modify_bulk_actions( $bulk_actions ) {
309
310 $white_listed_actions = [
311 'edit',
312 'trash',
313 'delete',
314 'untrash',
315 ];
316
317 // remove all actions except white listed actions.
318 $bulk_actions = array_intersect_key( $bulk_actions, array_flip( $white_listed_actions ) );
319
320 // Add export action only if edit and trash actions are present in bulk actions.
321 if ( isset( $bulk_actions['edit'] ) && isset( $bulk_actions['trash'] ) ) {
322 $bulk_actions['export'] = __( 'Export', 'sureforms' );
323 }
324
325 return $bulk_actions;
326 }
327
328 /**
329 * Show blank slate styles.
330 *
331 * @return void
332 * @since 0.0.1
333 */
334 public function get_blank_state_styles() {
335 echo '<style type="text/css">.sf-add-new-form-button:focus { box-shadow:none !important; outline:none !important; } #posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions, .wrap .subsubsub { display: none; } #posts-filter .tablenav.bottom { height: auto; } .sureform-add-new-form{ display: flex; flex-direction: column; gap: 8px; justify-content: center; align-items: center; padding: 24px 0 24px 0; } .sureform-blank-page-title { color: var(--dashboard-heading); font-family: Inter; font-size: 22px; font-style: normal; font-weight: 600; line-height: 28px; margin: 0; } .sureform-blank-page-subtitle { color: var(--dashboard-text); margin: 0; font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: 16px; }</style>';
336 }
337
338 /**
339 * Show blank slate.
340 *
341 * @param string $which String which tablenav is being shown.
342 * @return void
343 * @since 0.0.1
344 */
345 public function maybe_render_blank_form_state( $which ) {
346 $screen = get_current_screen();
347 $post_type = $screen ? $screen->post_type : '';
348
349 if ( SRFM_FORMS_POST_TYPE === $post_type && 'bottom' === $which ) {
350
351 $counts = (array) wp_count_posts( SRFM_FORMS_POST_TYPE );
352 unset( $counts['auto-draft'] );
353 $count = array_sum( $counts );
354
355 if ( 0 < $count ) {
356 return;
357 }
358
359 $this->sureforms_render_blank_state( $post_type );
360
361 $this->get_blank_state_styles();
362
363 }
364
365 if ( SRFM_ENTRIES_POST_TYPE === $post_type && 'bottom' === $which ) {
366
367 $counts = (array) wp_count_posts( SRFM_ENTRIES_POST_TYPE );
368 unset( $counts['auto-draft'] );
369 $count = array_sum( $counts );
370
371 if ( 0 < $count ) {
372 return;
373 }
374
375 $this->sureforms_render_blank_state( $post_type );
376
377 $this->get_blank_state_styles();
378
379 }
380 }
381
382 /**
383 * Set up a div for the header to render into it.
384 *
385 * @return void
386 * @since 0.0.1
387 */
388 public static function embed_page_header() {
389 $screen = get_current_screen();
390 $screen_id = $screen ? $screen->id : '';
391
392 if ( 'edit-' . SRFM_FORMS_POST_TYPE === $screen_id || 'edit-' . SRFM_ENTRIES_POST_TYPE === $screen_id ) {
393 ?>
394 <style>
395 .srfm-page-header {
396 @media screen and ( max-width: 600px ) {
397 padding-top: 46px;
398 }
399 }
400 </style>
401 <div id="srfm-page-header" class="srfm-page-header"></div>
402 <?php
403 }
404 }
405
406 /**
407 * Registers the sureforms metas.
408 *
409 * @return void
410 * @since 0.0.1
411 */
412 public function register_post_metas() {
413 $check_icon = 'data:image/svg+xml;base64,' . base64_encode( strval( file_get_contents( plugin_dir_path( SRFM_FILE ) . 'images/check-icon.svg' ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
414
415 $metas = apply_filters(
416 'srfm_register_post_meta',
417 [
418 // General tab metas.
419 '_srfm_use_label_as_placeholder' => 'boolean',
420 '_srfm_submit_button_text' => 'string',
421 '_srfm_is_inline_button' => 'boolean',
422 // Submit Button.
423 '_srfm_submit_width_backend' => 'string',
424 '_srfm_button_border_radius' => 'integer',
425 '_srfm_submit_alignment' => 'string',
426 '_srfm_submit_alignment_backend' => 'string',
427 '_srfm_submit_width' => 'string',
428 '_srfm_inherit_theme_button' => 'boolean',
429 // Additional Classes.
430 '_srfm_additional_classes' => 'string',
431
432 // Advanced tab metas.
433 // Success Message.
434 '_srfm_submit_type' => 'string',
435 // Security.
436 '_srfm_captcha_security_type' => 'string',
437 '_srfm_form_recaptcha' => 'string',
438 ]
439 );
440
441 // Form Custom CSS meta.
442 register_post_meta(
443 'sureforms_form',
444 '_srfm_form_custom_css',
445 [
446 'show_in_rest' => true,
447 'type' => 'string',
448 'single' => true,
449 'auth_callback' => function() {
450 return current_user_can( 'edit_posts' );
451 },
452 'sanitize_callback' => function( $meta_value ) {
453 return wp_kses_post( $meta_value );
454 },
455 ]
456 );
457
458 foreach ( $metas as $meta => $type ) {
459 register_meta(
460 'post',
461 $meta,
462 [
463 'object_subtype' => SRFM_FORMS_POST_TYPE,
464 'show_in_rest' => true,
465 'single' => true,
466 'type' => $type,
467 'sanitize_callback' => 'sanitize_text_field',
468 'auth_callback' => function() {
469 return current_user_can( 'edit_posts' );
470 },
471 ]
472 );
473 }
474
475 // Registers meta to handle values associated with form styling.
476 register_post_meta(
477 SRFM_FORMS_POST_TYPE,
478 '_srfm_instant_form_settings',
479 [
480 'single' => true,
481 'type' => 'object',
482 'auth_callback' => '__return_true',
483 'show_in_rest' => [
484 'schema' => [
485 'type' => 'object',
486 'properties' => [
487 'site_logo' => [
488 'type' => 'string',
489 ],
490 'site_logo_id' => [
491 'type' => 'integer',
492 ],
493 // Form page banner settings.
494 'cover_type' => [
495 'type' => 'string',
496 ],
497 'cover_color' => [
498 'type' => 'string',
499 ],
500 'cover_image' => [
501 'type' => 'string',
502 ],
503 'cover_image_id' => [
504 'type' => 'integer',
505 ],
506 // Form page background settings.
507 'bg_type' => [
508 'type' => 'string',
509 ],
510 'bg_color' => [
511 'type' => 'string',
512 ],
513 'bg_image' => [
514 'type' => 'string',
515 ],
516 'bg_image_id' => [
517 'type' => 'integer',
518 ],
519 'enable_instant_form' => [
520 'type' => 'boolean',
521 ],
522 'form_container_width' => [
523 'type' => 'integer',
524 ],
525 'single_page_form_title' => [
526 'type' => 'boolean',
527 ],
528 'use_banner_as_page_background' => [
529 'type' => 'boolean',
530 ],
531 ],
532 ],
533 ],
534 'default' => [
535 'bg_type' => 'color',
536 'bg_color' => '#ffffff',
537 'bg_image' => '',
538 'site_logo' => '',
539 'cover_type' => 'color',
540 'cover_color' => '#0C78FB',
541 'cover_image' => '',
542 'enable_instant_form' => false,
543 'form_container_width' => 620,
544 'single_page_form_title' => true,
545 'use_banner_as_page_background' => false,
546 ],
547 ]
548 );
549
550 register_post_meta(
551 SRFM_FORMS_POST_TYPE,
552 '_srfm_forms_styling',
553 [
554 'single' => true,
555 'type' => 'object',
556 'auth_callback' => '__return_true',
557 'show_in_rest' => [
558 'schema' => [
559 'type' => 'object',
560 'properties' => [
561 'primary_color' => [
562 'type' => 'string',
563 ],
564 'text_color' => [
565 'type' => 'string',
566 ],
567 'text_color_on_primary' => [
568 'type' => 'string',
569 ],
570 'field_spacing' => [
571 'type' => 'string',
572 ],
573 'submit_button_alignment' => [
574 'type' => 'string',
575 ],
576 ],
577 ],
578 ],
579 'default' => [
580 'primary_color' => '#0C78FB',
581 'text_color' => '#1E1E1E',
582 'text_color_on_primary' => '#FFFFFF',
583 'field_spacing' => 'medium',
584 'submit_button_alignment' => 'left',
585 ],
586 ]
587 );
588
589 // Email notification Metas.
590 register_post_meta(
591 'sureforms_form',
592 '_srfm_email_notification',
593 [
594 'single' => true,
595 'type' => 'array',
596 'auth_callback' => '__return_true',
597 'show_in_rest' => [
598 'schema' => [
599 'type' => 'array',
600 'items' => [
601 'type' => 'object',
602 'properties' => [
603 'id' => [
604 'type' => 'integer',
605 ],
606 'status' => [
607 'type' => 'boolean',
608 ],
609 'is_raw_format' => [
610 'type' => 'boolean',
611 ],
612 'name' => [
613 'type' => 'string',
614 ],
615 'email_to' => [
616 'type' => 'string',
617 ],
618 'email_reply_to' => [
619 'type' => 'string',
620 ],
621 'email_cc' => [
622 'type' => 'string',
623 ],
624 'email_bcc' => [
625 'type' => 'string',
626 ],
627 'subject' => [
628 'type' => 'string',
629 ],
630 'email_body' => [
631 'type' => 'string',
632 ],
633 ],
634 ],
635 ],
636 ],
637 'default' => [
638 [
639 'id' => 1,
640 'status' => true,
641 'is_raw_format' => false,
642 'name' => 'Admin Notification Email',
643 'email_to' => '{admin_email}',
644 'email_reply_to' => '{admin_email}',
645 'email_cc' => '{admin_email}',
646 'email_bcc' => '{admin_email}',
647 'subject' => 'New Form Submission',
648 'email_body' => '{all_data}',
649 ],
650 ],
651 ]
652 );
653
654 // Compliance Settings metas.
655 register_post_meta(
656 'sureforms_form',
657 '_srfm_compliance',
658 [
659 'single' => true,
660 'type' => 'array',
661 'auth_callback' => '__return_true',
662 'show_in_rest' => [
663 'schema' => [
664 'type' => 'array',
665 'items' => [
666 'type' => 'object',
667 'properties' => [
668 'id' => [
669 'type' => 'string',
670 ],
671 'gdpr' => [
672 'type' => 'boolean',
673 ],
674 'do_not_store_entries' => [
675 'type' => 'boolean',
676 ],
677 'auto_delete_entries' => [
678 'type' => 'boolean',
679 ],
680 'auto_delete_days' => [
681 'type' => 'string',
682 ],
683 ],
684 ],
685 ],
686 ],
687 'default' => [
688 [
689 'id' => 'gdpr',
690 'gdpr' => false,
691 'do_not_store_entries' => false,
692 'auto_delete_entries' => false,
693 'auto_delete_days' => '',
694 ],
695 ],
696 ]
697 );
698
699 // form confirmation.
700 register_post_meta(
701 'sureforms_form',
702 '_srfm_form_confirmation',
703 [
704 'single' => true,
705 'type' => 'array',
706 'auth_callback' => '__return_true',
707 'show_in_rest' => [
708 'schema' => [
709 'type' => 'array',
710 'items' => [
711 'type' => 'object',
712 'properties' => [
713 'id' => [
714 'type' => 'integer',
715 ],
716 'confirmation_type' => [
717 'type' => 'string',
718 ],
719 'page_url' => [
720 'type' => 'string',
721 ],
722 'custom_url' => [
723 'type' => 'string',
724 ],
725 'message' => [
726 'type' => 'string',
727 ],
728 'submission_action' => [
729 'type' => 'string',
730 ],
731 ],
732 ],
733 ],
734 ],
735 'default' => [
736 [
737 'id' => 1,
738 'confirmation_type' => 'same page',
739 'page_url' => '',
740 'custom_url' => '',
741 'message' => '<p style="text-align: center;"><img src="' . esc_attr( $check_icon ) . '"></img></p><h2 style="text-align: center;">Thank you</h2><p style="text-align: center;">We have received your email. You\'ll hear from us as soon as possible.</p><p style="text-align: center;">Please be sure to whitelist our {admin_email} email address to ensure our replies reach your inbox safely.</p>',
742 'submission_action' => 'hide form',
743 ],
744 ],
745 ]
746 );
747
748 // Sureforms entry metas.
749 register_post_meta(
750 'sureforms_entry',
751 '_srfm_submission_info',
752 [
753 'single' => true,
754 'type' => 'array',
755 'auth_callback' => '__return_true',
756 'show_in_rest' => [
757 'schema' => [
758 'type' => 'array',
759 'items' => [
760 'type' => 'object',
761 'properties' => [
762 'user_ip' => [
763 'type' => 'string',
764 ],
765 'browser_name' => [
766 'type' => 'string',
767 ],
768 'device_name' => [
769 'type' => 'string',
770 ],
771 ],
772 ],
773 ],
774 ],
775 ]
776 );
777
778 // store form id in entry.
779 register_post_meta(
780 'sureforms_entry',
781 '_srfm_entry_form_id',
782 [
783 'single' => true,
784 'type' => 'integer',
785 'auth_callback' => '__return_true',
786 'show_in_rest' => true,
787 ]
788 );
789
790 // conditional logic.
791 do_action( 'srfm_register_conditional_logic_post_meta' );
792 /**
793 * Hook for registering additional Post Meta
794 */
795 do_action( 'srfm_register_additional_post_meta' );
796
797 }
798
799 /**
800 * Sureforms entries meta box callback.
801 *
802 * @param \WP_Post $post Template.
803 * @return void
804 * @since 0.0.1
805 */
806 public function sureforms_meta_box_callback( \WP_Post $post ) {
807 $meta_data = get_post_meta( $post->ID, 'srfm_entry_meta', true );
808 if ( ! is_array( $meta_data ) ) {
809 return;
810 }
811 $excluded_fields = [ 'srfm-honeypot-field', 'g-recaptcha-response', 'srfm-sender-email-field' ];
812
813 ?>
814 <table class="widefat striped">
815 <tbody>
816 <tr><th><b><?php esc_html_e( 'Fields', 'sureforms' ); ?></b></th><th><b><?php esc_html_e( 'Values', 'sureforms' ); ?></b></th></tr>
817 <?php
818 foreach ( $meta_data as $field_name => $value ) :
819 if ( in_array( $field_name, $excluded_fields, true ) ) {
820 continue;
821 }
822
823 if ( false === str_contains( $field_name, '-lbl-' ) ) {
824 continue;
825 }
826
827 $label = explode( '-lbl-', $field_name )[1];
828 // Getting the encrypted label. we are removing the block slug here.
829 $label = explode( '-', $label )[0];
830
831 ?>
832 <tr>
833 <td><b><?php echo $label ? esc_html( Helper::decrypt( $label ) ) : ''; ?><b></td>
834 <?php if ( strpos( $field_name, 'srfm-upload' ) !== false ) : ?>
835 <style>
836 .file-cards-container {
837 display: flex;
838 flex-wrap: wrap;
839 gap: 10px;
840 }
841
842 .file-card {
843 border: 1px solid #ddd;
844 border-radius: 4px;
845 padding: 10px;
846 width: 100px; /* Reduced width */
847 text-align: center;
848 background: #f9f9f9;
849 font-size: 12px; /* Reduced font size for smaller cards */
850 }
851
852 .file-card-image img {
853 max-width: 80px; /* Reduced max width */
854 max-height: 80px; /* Reduced max height */
855 object-fit: cover;
856 }
857
858 .file-card-icon {
859 font-size: 24px; /* Reduced icon size */
860 margin-bottom: 5px;
861 }
862
863 .file-card-details {
864 margin-bottom: 5px;
865 font-weight: bold;
866 }
867
868 .file-card-url a {
869 color: #007bff;
870 text-decoration: none;
871 font-size: 12px; /* Reduced font size */
872 }
873
874 .file-card-url a:hover {
875 text-decoration: underline;
876 }
877 </style>
878 <td>
879 <div class="file-cards-container">
880 <?php
881 $upload_values = $value;
882 if ( ! empty( $upload_values ) && is_array( $upload_values ) ) {
883 foreach ( $upload_values as $value ) {
884 $value = Helper::get_string_value( $value );
885 if ( ! empty( $value ) ) {
886 $file_type = pathinfo( $value, PATHINFO_EXTENSION );
887 $is_image = in_array( $file_type, [ 'gif', 'png', 'bmp', 'jpg', 'jpeg', 'svg' ], true );
888 ?>
889 <div class="file-card">
890 <?php if ( $is_image ) : ?>
891 <div class="file-card-image">
892 <a target="_blank" href="<?php echo esc_attr( urldecode( $value ) ); ?>">
893 <img src="<?php echo esc_attr( urldecode( $value ) ); ?>" alt="img" />
894 </a>
895 </div>
896 <?php else : ?>
897 <div class="file-card-icon">
898 <?php echo '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M4 16.333V4.667a1.333 1.333 0 011.333-1.333h13.334a1.333 1.333 0 011.333 1.333v11.666a1.333 1.333 0 01-1.333 1.333H5.333A1.333 1.333 0 014 16.333zm8-8h2v6h-2v-6zm-2 8h6v2H10v-2zm-6-6h4v6H4v-6zm0-4h16v2H4V6z"/></svg>'; ?>
899 </div>
900 <div class="file-card-details">
901 <span><?php echo esc_html( strtoupper( $file_type ) ); ?></span>
902 </div>
903 <?php endif; ?>
904 <div class="file-card-url">
905 <a target="_blank" href="<?php echo esc_attr( urldecode( $value ) ); ?>"><?php echo esc_html__( 'Open', 'sureforms' ); ?></a>
906 </div>
907 </div>
908 <?php
909 }
910 }
911 }
912 ?>
913 </div>
914 </td>
915 <?php elseif ( strpos( $field_name, 'srfm-url' ) !== false ) : ?>
916 <?php if ( ! $value ) : ?>
917 <td><?php echo ''; ?></td>
918 <?php else : ?>
919 <?php
920 if (
921 substr( $value, 0, 7 ) !== 'http://' &&
922 substr( $value, 0, 8 ) !== 'https://'
923 ) {
924 $value = 'https://' . $value;
925 }
926 ?>
927 <td><a target="_blank" href="<?php echo esc_url( $value ); ?>"><?php echo esc_url( $value ); ?></a></td>
928 <?php endif; ?>
929 <?php else : ?>
930 <td><?php echo false !== strpos( $value, PHP_EOL ) ? wp_kses_post( wpautop( $value ) ) : wp_kses_post( $value ); ?></td>
931 <?php endif; ?>
932 </tr>
933 <?php endforeach; ?>
934 </tbody>
935 </table>
936 <?php
937 }
938
939
940 /**
941 * Add Sureforms entries meta box.
942 *
943 * @return void
944 * @since 0.0.1
945 */
946 public function entries_meta_box() {
947 add_meta_box(
948 'sureform_entry_meta',
949 'Form Data',
950 [ $this, 'sureforms_meta_box_callback' ],
951 'sureforms_entry',
952 'normal',
953 'high'
954 );
955 add_meta_box(
956 'sureform_form_name_meta',
957 'Submission Info',
958 [ $this, 'sureforms_form_name_meta_callback' ],
959 'sureforms_entry',
960 'side',
961 'low'
962 );
963 }
964
965 /**
966 * Sureforms box Form Name meta box callback.
967 *
968 * @param \WP_Post $post Template.
969 * @return void
970 * @since 0.0.1
971 */
972 public function sureforms_form_name_meta_callback( \WP_Post $post ) {
973 $post_id = $post->ID;
974 $taxonomy = 'sureforms_tax';
975 $terms = wp_get_post_terms( $post_id, $taxonomy );
976 if ( is_array( $terms ) && count( $terms ) > 0 ) {
977 $form_id = intval( $terms[0]->slug );
978 $form_name = ! empty( get_the_title( $form_id ) ) ? get_the_title( $form_id ) : 'SureForms Form';
979 $submission_info = get_post_meta( $post_id, '_srfm_submission_info', true );
980 if ( is_array( $submission_info ) && count( $submission_info ) > 0 ) {
981 $user_ip = $submission_info[0]['user_ip'] ? $submission_info[0]['user_ip'] : '';
982 $browser_name = $submission_info[0]['browser_name'] ? $submission_info[0]['browser_name'] : '';
983 $device_name = $submission_info[0]['device_name'] ? $submission_info[0]['device_name'] : '';
984 $entry_form_id = Helper::get_string_value( get_post_meta( $post_id, '_srfm_entry_form_id', true ) );
985 } else {
986 $user_ip = '';
987 $browser_name = '';
988 $device_name = '';
989 $entry_form_id = '';
990 }
991 ?>
992 <table style="border-collapse: separate; border-spacing: 5px 5px;">
993 <tr style="margin-bottom: 10px;">
994 <td><b><?php echo esc_html( __( 'Form Name:', 'sureforms' ) ); ?></b></td>
995 <td><?php echo esc_html( $form_name ); ?></td>
996 </tr>
997 <tr style="margin-bottom: 10px;">
998 <td><b><?php echo esc_html( __( 'Form ID:', 'sureforms' ) ); ?></b></td>
999 <td><?php echo esc_html( $entry_form_id ); ?></td>
1000 </tr>
1001 <tr style="margin-bottom: 10px;">
1002 <td><b><?php echo esc_html( __( 'User IP:', 'sureforms' ) ); ?></b></td>
1003 <td><a target="_blank" rel="noopener" href="https://ipinfo.io/<?php echo esc_html( $user_ip ); ?>"><?php echo esc_html( $user_ip ); ?></a></td>
1004 </tr>
1005 <tr style="margin-bottom: 10px;">
1006 <td><b><?php echo esc_html( __( 'Browser:', 'sureforms' ) ); ?></b></td>
1007 <td><?php echo esc_html( $browser_name ); ?></td>
1008 </tr>
1009 <tr style="margin-bottom: 10px;">
1010 <td><b><?php echo esc_html( __( 'Device:', 'sureforms' ) ); ?></b></td>
1011 <td><?php echo esc_html( $device_name ); ?></td>
1012 </tr>
1013 </table>
1014 <?php
1015 } else {
1016 ?>
1017 <p><?php echo esc_html__( 'SureForms Form', 'sureforms' ); ?></p>
1018 <?php
1019 }
1020 }
1021
1022 /**
1023 * Custom Shortcode.
1024 *
1025 * @param array<mixed> $atts Attributes.
1026 * @return string|false. $content Post Content.
1027 * @since 0.0.1
1028 */
1029 public function forms_shortcode( array $atts ) {
1030 $atts = shortcode_atts(
1031 [
1032 'id' => '',
1033 'show_title' => true,
1034 ],
1035 $atts
1036 );
1037
1038 $id = intval( $atts['id'] );
1039 $post = get_post( $id );
1040
1041 if ( ! empty( $id ) && $post ) {
1042 $content = Generate_Form_Markup::get_form_markup( $id, ! filter_var( $atts['show_title'], FILTER_VALIDATE_BOOLEAN ), '', 'post', true );
1043 return $content;
1044 }
1045
1046 return '';
1047 }
1048
1049 /**
1050 * Add custom column header.
1051 *
1052 * @param array<mixed> $columns Attributes.
1053 * @return array<mixed> $columns Post Content.
1054 * @since 0.0.1
1055 */
1056 public function custom_form_columns( $columns ) {
1057 $columns = [
1058 'cb' => $columns['cb'],
1059 'title' => $columns['title'],
1060 'sureforms' => __( 'Shortcode', 'sureforms' ),
1061 'entries' => __( 'Entries', 'sureforms' ),
1062 'author' => $columns['author'],
1063 'date' => $columns['date'],
1064 ];
1065 return $columns;
1066 }
1067
1068 /**
1069 * Populate custom column with data.
1070 *
1071 * @param string $column Attributes.
1072 * @param integer $post_id Attributes.
1073 * @return void
1074 * @since 0.0.1
1075 */
1076 public function custom_form_column_data( $column, $post_id ) {
1077 $post_id_formatted = strval( $post_id );
1078 if ( 'sureforms' === $column ) {
1079 ob_start();
1080 ?>
1081 <div class="srfm-shortcode-container">
1082 <input id="srfm-shortcode-input-<?php echo esc_attr( strval( $post_id ) ); ?>" class="srfm-shortcode-input" type="text" readonly value="[sureforms id='<?php echo esc_attr( $post_id_formatted ); ?>']" />
1083 <button type="button" class="components-button components-clipboard-button has-icon srfm-shortcode" onclick="handleFormShortcode(this)">
1084 <span id="srfm-copy-icon" class="dashicon dashicons dashicons-admin-page"></span>
1085 </button>
1086 </div>
1087 <?php
1088 ob_end_flush();
1089 }
1090 if ( 'entries' === $column ) {
1091 $entries_url = admin_url( 'edit.php?post_status=all&post_type=' . SRFM_ENTRIES_POST_TYPE . '&sureforms_tax=' . $post_id_formatted . '&filter_action=Filter&paged=1' );
1092
1093 $taxonomy = 'sureforms_tax';
1094
1095 $args = [
1096 'post_type' => SRFM_ENTRIES_POST_TYPE,
1097 'tax_query' // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query. -- We require tax_query for this function to work.
1098 => [
1099 [
1100 'taxonomy' => $taxonomy,
1101 'field' => 'slug',
1102 'terms' => $post_id_formatted,
1103 ],
1104 ],
1105 'posts_per_page' => 1, // Retrieve only 1 entry to minimize load.
1106 ];
1107
1108 $key = 'sureforms_entries_count_' . $post_id_formatted;
1109 $query = wp_cache_get( $key );
1110
1111 if ( ! $query ) {
1112 $query = new WP_Query( $args );
1113 wp_cache_set( $key, $query, '', 3600 );
1114 }
1115
1116 if ( $query instanceof WP_Query ) {
1117 $post_count = Helper::get_string_value( $query->found_posts );
1118
1119 ob_start();
1120 ?>
1121 <p class="srfm-entries-number"><a href="<?php echo esc_url( $entries_url ); ?>"><?php echo esc_html( $post_count ); ?></a></p>
1122 <?php
1123 ob_end_flush();
1124 }
1125 }
1126 }
1127
1128 /**
1129 * Add custom column header.
1130 *
1131 * @param array<mixed> $columns Attributes.
1132 * @return array<mixed> $columns Post Content.
1133 * @since 0.0.1
1134 */
1135 public function custom_entry_columns( $columns ) {
1136 $columns = [
1137 'cb' => $columns['cb'],
1138 'title' => __( 'First Field', 'sureforms' ),
1139 'form_name' => __( 'Form Name', 'sureforms' ),
1140 'entry_id' => __( 'ID', 'sureforms' ),
1141 'date' => __( 'Submitted On', 'sureforms' ),
1142 ];
1143 return $columns;
1144 }
1145
1146 /**
1147 * Populate custom column with data.
1148 *
1149 * @param string $column Attributes.
1150 * @param integer $post_id Attributes.
1151 * @return void
1152 * @since 0.0.1
1153 */
1154 public function custom_entry_column_data( $column, $post_id ) {
1155 if ( 'entry_id' === $column ) {
1156 $entry_id = strval( $post_id );
1157 echo '<p>#' . esc_html( $entry_id ) . '</p>';
1158 }
1159 if ( 'form_name' === $column ) {
1160 $taxonomy = 'sureforms_tax';
1161 $terms = wp_get_post_terms( $post_id, $taxonomy );
1162
1163 if ( is_array( $terms ) && count( $terms ) > 0 ) {
1164 $form_id = intval( $terms[0]->slug );
1165 $form_name = ! empty( get_the_title( $form_id ) ) ? get_the_title( $form_id ) : 'SureForms Form';
1166 echo '<p>' . esc_html( $form_name . ' #' . $form_id ) . '</p>';
1167 } else {
1168 ?>
1169 <p><?php echo esc_html__( 'SureForms Form', 'sureforms' ); ?></p>
1170 <?php
1171 }
1172 }
1173 }
1174
1175 /**
1176 * Add SureForms taxonomy filter.
1177 *
1178 * @return void
1179 * @since 0.0.1
1180 */
1181 public function add_tax_filter() {
1182 $screen = get_current_screen();
1183
1184 if ( ! is_null( $screen ) && 'edit-sureforms_entry' === $screen->id ) {
1185 $forms = get_posts(
1186 [
1187 'post_type' => SRFM_FORMS_POST_TYPE,
1188 'posts_per_page' => -1,
1189 'orderby' => 'title',
1190 'order' => 'ASC',
1191 ]
1192 );
1193
1194 if ( ! empty( $forms ) ) {
1195 $selected = isset( $_GET['sureforms_tax'] ) ? sanitize_key( wp_unslash( $_GET['sureforms_tax'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce Verification is not needed in this case. We are not getting the nonce value.
1196 echo '<select name="sureforms_tax" id="srfm-tax-filter">';
1197 echo '<option value="">' . esc_html__( ' All Form Entries', 'sureforms' ) . '</option>';
1198
1199 foreach ( $forms as $form ) {
1200 $selected_attr = selected( $selected, $form->ID, false );
1201 echo '<option value="' . esc_attr( strval( $form->ID ) ) . '" ' . esc_attr( $selected_attr ) . '>' . esc_html( $form->post_title ) . '</option>';
1202 }
1203
1204 echo '</select>';
1205
1206 }
1207 }
1208 }
1209
1210 /**
1211 * Show the import form popup
1212 *
1213 * @since 0.0.1
1214 * @return void
1215 */
1216 public function import_form_popup() {
1217 $screen = get_current_screen();
1218 $id = $screen ? $screen->id : '';
1219 if ( 'edit-sureforms_form' === $id ) {
1220 ?>
1221 <div class="srfm-import-plugin-wrap">
1222 <div class="srfm-import-wrap">
1223 <p class="srfm-import-help"><?php echo esc_html__( 'Please choose the SureForms export file (.json) that you wish to import.', 'sureforms' ); ?></p>
1224 <form method="post" enctype="multipart/form-data" class="srfm-import-form">
1225 <input type="file" id="srfm-import-file" onchange="handleFileChange(event)" name="import form" accept=".json">
1226 <input type="submit" name="import-form-submit" id="import-form-submit" class="srfm-import-button" value="Import Now" disabled>
1227 </form>
1228 <p id="srfm-import-error"><?php echo esc_html__( 'There is some error in json file, please export the SureForms Forms again.', 'sureforms' ); ?></p>
1229 </div>
1230 </div>
1231 <?php
1232 }
1233 }
1234
1235 /**
1236 * Redirect to home page if instant form is not enabled.
1237 *
1238 * @since 0.0.1
1239 * @return void
1240 */
1241 public function srfm_instant_form_redirect() {
1242
1243 $form_id = Helper::get_integer_value( get_the_ID() );
1244
1245 $instant_form_settings = Helper::get_array_value( Helper::get_post_meta( $form_id, '_srfm_instant_form_settings' ) );
1246 $enable_instant_form = ! empty( $instant_form_settings['enable_instant_form'] ) ? boolval( $instant_form_settings['enable_instant_form'] ) : false;
1247
1248 if ( $enable_instant_form ) {
1249 return;
1250 }
1251
1252 $form_preview = '';
1253
1254 $form_preview_attr = isset( $_GET['preview'] ) ? sanitize_text_field( wp_unslash( $_GET['preview'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verification is not needed here.
1255
1256 if ( $form_preview_attr ) {
1257 $form_preview = filter_var( $form_preview_attr, FILTER_VALIDATE_BOOLEAN );
1258 }
1259
1260 if ( is_singular( 'sureforms_form' ) && ! $form_preview && ! current_user_can( 'manage_options' ) ) {
1261 wp_safe_redirect( home_url() );
1262 return;
1263 }
1264 }
1265
1266 /**
1267 * Restrict interference of other plugins with SureForms.
1268 *
1269 * @since 0.0.5
1270 * @return void
1271 */
1272 private function restrict_unwanted_insertions() {
1273 // Restrict RankMath metaboxes in edit page.
1274 add_action( 'cmb2_admin_init', [ $this, 'restrict_data' ] );
1275
1276 // Restrict Yoast columns.
1277 add_filter( 'wpseo_accessible_post_types', [ $this, 'unset_sureforms_post_type' ] );
1278 add_filter( 'wpseo_metabox_prio', '__return_false' );
1279
1280 // Restrict AIOSEO columns.
1281 add_filter( 'aioseo_public_post_types', [ $this, 'unset_sureforms_post_type' ] );
1282 }
1283
1284 /**
1285 * Restrict RankMath meta boxes in edit page.
1286 *
1287 * @since 0.0.5
1288 * @return void
1289 */
1290 public function restrict_data() {
1291 add_filter( 'rank_math/excluded_post_types', [ $this, 'unset_sureforms_post_type' ] );
1292 }
1293
1294 /**
1295 * Remove SureForms post type from RankMath and Yoast.
1296 *
1297 * @param array<mixed> $post_types Post types.
1298 * @since 0.0.5
1299 * @return array<mixed> $post_types Modified post types.
1300 */
1301 public function unset_sureforms_post_type( $post_types ) {
1302 $filtered_post_types = array_filter(
1303 $post_types,
1304 function( $post_type ) {
1305 if ( is_array( $post_type ) && isset( $post_type['name'] ) ) {
1306 return SRFM_FORMS_POST_TYPE !== $post_type['name'];
1307 } else {
1308 return SRFM_FORMS_POST_TYPE !== $post_type;
1309 }
1310 }
1311 );
1312
1313 return $filtered_post_types;
1314 }
1315 }
1316