PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 0.0.13
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v0.0.13
2.12.7 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 All 97 releases
sureforms / inc / post-types.php

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

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