PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 1.7.2
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v1.7.2
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
1,221 lines 37.2 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 SRFM\Inc\Traits\Get_Instance;
13 use WP_Admin_Bar;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // Exit if accessed directly.
17 }
18
19 /**
20 * Post Types Main Class.
21 *
22 * @since 0.0.1
23 */
24 class Post_Types {
25 use Get_Instance;
26
27 /**
28 * Constructor
29 *
30 * @since 0.0.1
31 */
32 public function __construct() {
33 $this->restrict_unwanted_insertions();
34 add_action( 'init', [ $this, 'register_post_types' ] );
35 add_action( 'init', [ $this, 'register_post_metas' ] );
36 add_filter( 'manage_sureforms_form_posts_columns', [ $this, 'custom_form_columns' ] );
37 add_action( 'manage_sureforms_form_posts_custom_column', [ $this, 'custom_form_column_data' ], 10, 2 );
38 add_shortcode( 'sureforms', [ $this, 'forms_shortcode' ] );
39 add_action( 'manage_posts_extra_tablenav', [ $this, 'maybe_render_blank_form_state' ] );
40 add_action( 'in_admin_header', [ $this, 'embed_page_header' ] );
41 add_filter( 'post_row_actions', [ $this, 'modify_entries_list_row_actions' ], 10, 2 );
42 add_filter( 'bulk_actions-edit-sureforms_form', [ $this, 'register_modify_bulk_actions' ], 99 );
43 add_action( 'admin_notices', [ $this, 'import_form_popup' ] );
44 add_action( 'admin_bar_menu', [ $this, 'remove_admin_bar_menu_item' ], 80, 1 );
45 add_action( 'template_redirect', [ $this, 'srfm_instant_form_redirect' ] );
46 add_action( 'template_redirect', [ $this, 'disable_sureforms_archive_page' ], 9 );
47 }
48
49 /**
50 * Add SureForms menu.
51 *
52 * @param string $title Parent slug.
53 * @param string $subtitle Parent slug.
54 * @param string $image Parent slug.
55 * @param string $button_text Parent slug.
56 * @param string $button_url Parent slug.
57 * @param string $after_button After button content.
58 * @return void
59 * @since 0.0.1
60 */
61 public function get_blank_page_markup( $title, $subtitle, $image, $button_text = '', $button_url = '', $after_button = '' ) {
62 echo '<div class="sureform-add-new-form">';
63
64 echo '<p class="sureform-blank-page-title">' . esc_html( $title ) . '</p>';
65
66 echo '<p class="sureform-blank-page-subtitle">' . esc_html( $subtitle ) . '</p>';
67
68 echo '<img src="' . esc_url( SRFM_URL . '/images/' . $image . '.svg' ) . '">';
69
70 if ( ! empty( $button_text ) && ! empty( $button_url ) ) {
71 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>';
72 }
73 echo '</div>';
74 }
75
76 /**
77 * Render blank state for add new form screen.
78 *
79 * @param string $post_type Post type.
80 * @return void
81 * @since 0.0.1
82 */
83 public function sureforms_render_blank_state( $post_type ) {
84
85 if ( SRFM_FORMS_POST_TYPE === $post_type ) {
86 $page_name = 'add-new-form';
87 $new_form_url = admin_url( 'admin.php?page=' . $page_name );
88 $import_button = '<button class="button button-secondary srfm-import-btn">' . __( 'Import Form', 'sureforms' ) . '</button>';
89
90 $this->get_blank_page_markup(
91 esc_html__( 'Let’s build your first form', 'sureforms' ),
92 esc_html__(
93 'Craft beautiful and functional forms in minutes',
94 'sureforms'
95 ),
96 'add-new-form',
97 esc_html__( 'Add New Form', 'sureforms' ),
98 $new_form_url,
99 $import_button
100 );
101 }
102
103 if ( SRFM_ENTRIES === $post_type ) {
104
105 $this->get_blank_page_markup(
106 esc_html__( 'No records found', 'sureforms' ),
107 esc_html__(
108 'This is where your form entries will appear',
109 'sureforms'
110 ),
111 'blank-entries'
112 );
113 }
114 }
115
116 /**
117 * Registers the forms and submissions post types.
118 *
119 * @return void
120 * @since 0.0.1
121 */
122 public function register_post_types() {
123 $form_labels = [
124 'name' => _x( 'Forms', 'post type general name', 'sureforms' ),
125 'singular_name' => _x( 'Form', 'post type singular name', 'sureforms' ),
126 'menu_name' => _x( 'Forms', 'admin menu', 'sureforms' ),
127 'add_new' => _x( 'Add New', 'form', 'sureforms' ),
128 'add_new_item' => __( 'Add New Form', 'sureforms' ),
129 'new_item' => __( 'New Form', 'sureforms' ),
130 'edit_item' => __( 'Edit Form', 'sureforms' ),
131 'view_item' => __( 'View Form', 'sureforms' ),
132 'view_items' => __( 'View Forms', 'sureforms' ),
133 'all_items' => __( 'Forms', 'sureforms' ),
134 'search_items' => __( 'Search Forms', 'sureforms' ),
135 'parent_item_colon' => __( 'Parent Forms:', 'sureforms' ),
136 'not_found' => __( 'No forms found.', 'sureforms' ),
137 'not_found_in_trash' => __( 'No forms found in Trash.', 'sureforms' ),
138 'item_published' => __( 'Form published.', 'sureforms' ),
139 'item_updated' => __( 'Form updated.', 'sureforms' ),
140 ];
141 register_post_type(
142 SRFM_FORMS_POST_TYPE,
143 [
144 'labels' => $form_labels,
145 'rewrite' => [ 'slug' => 'form' ],
146 'public' => true,
147 'show_in_rest' => true,
148 'has_archive' => true,
149 'show_ui' => true,
150 'supports' => [ 'title', 'author', 'editor', 'custom-fields' ],
151 'show_in_menu' => 'sureforms_menu',
152 'show_in_nav_menus' => true,
153 ]
154 );
155 // will be used later.
156 // register_post_status(
157 // 'unread',
158 // array(
159 // 'label' => _x( 'Unread', 'sureforms', 'sureforms' ),
160 // 'public' => true,
161 // 'exclude_from_search' => false,
162 // 'show_in_admin_all_list' => true,
163 // 'show_in_admin_status_list' => true,
164 // Translators: %s is the number of unread items.
165 // 'label_count' => _n_noop( 'Unread (%s)', 'Unread (%s)', 'sureforms' ),
166 // )
167 // );.
168 }
169
170 /**
171 * Redirects requests for SureForms archieve page to homeurl
172 *
173 * @since 1.4.0
174 * @return void
175 */
176 public function disable_sureforms_archive_page() {
177 if ( is_post_type_archive( SRFM_FORMS_POST_TYPE ) ) {
178 wp_safe_redirect( home_url(), 301 );
179 exit;
180 }
181 }
182
183 /**
184 * Remove add new form menu item.
185 *
186 * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance.
187 *
188 * @return void
189 * @since 0.0.1
190 */
191 public function remove_admin_bar_menu_item( $wp_admin_bar ) {
192 $wp_admin_bar->remove_node( 'new-sureforms_form' );
193 }
194
195 /**
196 * Modify list row actions.
197 *
198 * @param array<mixed> $actions An array of row action links.
199 * @param \WP_Post $post The current WP_Post object.
200 *
201 * @return array<mixed> $actions Modified row action links.
202 * @since 0.0.1
203 */
204 public function modify_entries_list_row_actions( $actions, $post ) {
205 if ( 'sureforms_form' === $post->post_type ) {
206 $actions['export'] = '<a href="#" onclick="exportForm(' . $post->ID . ')">' . __( 'Export', 'sureforms' ) . '</a>';
207 }
208
209 return $actions;
210 }
211
212 /**
213 * Modify list bulk actions.
214 *
215 * @param array<mixed> $bulk_actions An array of bulk action links.
216 * @since 0.0.1
217 * @return array<mixed> $bulk_actions Modified action links.
218 */
219 public function register_modify_bulk_actions( $bulk_actions ) {
220
221 $white_listed_actions = [
222 'edit',
223 'trash',
224 'delete',
225 'untrash',
226 ];
227
228 // remove all actions except white listed actions.
229 $bulk_actions = array_intersect_key( $bulk_actions, array_flip( $white_listed_actions ) );
230
231 // Add export action only if edit and trash actions are present in bulk actions.
232 if ( isset( $bulk_actions['edit'] ) && isset( $bulk_actions['trash'] ) ) {
233 $bulk_actions['export'] = __( 'Export', 'sureforms' );
234 }
235
236 return $bulk_actions;
237 }
238
239 /**
240 * Show blank slate styles.
241 *
242 * @return void
243 * @since 0.0.1
244 */
245 public function get_blank_state_styles() {
246 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>';
247 }
248
249 /**
250 * Show blank slate.
251 *
252 * @param string $which String which tablenav is being shown.
253 * @return void
254 * @since 0.0.1
255 */
256 public function maybe_render_blank_form_state( $which ) {
257 $screen = get_current_screen();
258 $post_type = $screen ? $screen->post_type : '';
259
260 if ( SRFM_FORMS_POST_TYPE === $post_type && 'bottom' === $which ) {
261
262 $counts = (array) wp_count_posts( SRFM_FORMS_POST_TYPE );
263 unset( $counts['auto-draft'] );
264 $count = array_sum( $counts );
265
266 if ( 0 < $count ) {
267 return;
268 }
269
270 $this->sureforms_render_blank_state( $post_type );
271
272 $this->get_blank_state_styles();
273
274 }
275 }
276
277 /**
278 * Set up a div for the header to render into it.
279 *
280 * @return void
281 * @since 0.0.1
282 */
283 public static function embed_page_header() {
284 $screen = get_current_screen();
285 $screen_id = $screen ? $screen->id : '';
286
287 $is_screen_sureforms_entries = Helper::validate_request_context( SRFM_ENTRIES, 'page' );
288
289 if ( 'edit-' . SRFM_FORMS_POST_TYPE === $screen_id || $is_screen_sureforms_entries ) {
290 ?>
291 <style>
292 .srfm-page-header {
293 min-height: 56px;
294 @media screen and ( max-width: 600px ) {
295 padding-top: 46px;
296 }
297 }
298 </style>
299 <div id="srfm-page-header" class="srfm-page-header srfm-admin-wrapper">
300 <div class="srfm-page-pre-nav-content"></div>
301 </div>
302 <?php
303 }
304 }
305
306 /**
307 * Registers the sureforms metas.
308 *
309 * @return void
310 * @since 0.0.1
311 */
312 public function register_post_metas() {
313 $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
314
315 $metas = apply_filters(
316 'srfm_register_post_meta',
317 [
318 // General tab metas.
319 '_srfm_use_label_as_placeholder' => 'boolean',
320 '_srfm_submit_button_text' => 'string',
321 '_srfm_is_inline_button' => 'boolean',
322 // Submit Button.
323 '_srfm_submit_width_backend' => 'string',
324 '_srfm_button_border_radius' => 'integer',
325 '_srfm_submit_alignment' => 'string',
326 '_srfm_submit_alignment_backend' => 'string',
327 '_srfm_submit_width' => 'string',
328 '_srfm_inherit_theme_button' => 'boolean',
329 // Additional Classes.
330 '_srfm_additional_classes' => 'string',
331
332 // Advanced tab metas.
333 // Success Message.
334 '_srfm_submit_type' => 'string',
335 // Security.
336 '_srfm_captcha_security_type' => 'string',
337 '_srfm_form_recaptcha' => 'string',
338 // post meta to store if the form is AI generated.
339 '_srfm_is_ai_generated' => 'boolean',
340 ]
341 );
342
343 // Form Custom CSS meta.
344 register_post_meta(
345 'sureforms_form',
346 '_srfm_form_custom_css',
347 [
348 'show_in_rest' => true,
349 'type' => 'string',
350 'single' => true,
351 'auth_callback' => static function() {
352 return current_user_can( 'edit_posts' );
353 },
354 'sanitize_callback' => static function( $meta_value ) {
355 return wp_kses_post( $meta_value );
356 },
357 ]
358 );
359
360 foreach ( $metas as $meta => $type ) {
361 register_meta(
362 'post',
363 $meta,
364 [
365 'object_subtype' => SRFM_FORMS_POST_TYPE,
366 'show_in_rest' => true,
367 'single' => true,
368 'type' => $type,
369 'sanitize_callback' => 'sanitize_text_field',
370 'auth_callback' => static function() {
371 return current_user_can( 'edit_posts' );
372 },
373 ]
374 );
375 }
376
377 // Registers meta to handle values associated with form styling.
378 register_post_meta(
379 SRFM_FORMS_POST_TYPE,
380 '_srfm_instant_form_settings',
381 [
382 'single' => true,
383 'type' => 'object',
384 'auth_callback' => '__return_true',
385 'show_in_rest' => [
386 'schema' => [
387 'type' => 'object',
388 'properties' => [
389 'site_logo' => [
390 'type' => 'string',
391 ],
392 'site_logo_id' => [
393 'type' => 'integer',
394 ],
395 // Form page banner settings.
396 'cover_type' => [
397 'type' => 'string',
398 ],
399 'cover_color' => [
400 'type' => 'string',
401 ],
402 'cover_image' => [
403 'type' => 'string',
404 ],
405 'cover_image_id' => [
406 'type' => 'integer',
407 ],
408 // Form page background settings.
409 'bg_type' => [
410 'type' => 'string',
411 ],
412 'bg_color' => [
413 'type' => 'string',
414 ],
415 'bg_image' => [
416 'type' => 'string',
417 ],
418 'bg_image_id' => [
419 'type' => 'integer',
420 ],
421 'enable_instant_form' => [
422 'type' => 'boolean',
423 ],
424 'form_container_width' => [
425 'type' => 'integer',
426 ],
427 'single_page_form_title' => [
428 'type' => 'boolean',
429 ],
430 'use_banner_as_page_background' => [
431 'type' => 'boolean',
432 ],
433 ],
434 ],
435 ],
436 'default' => [
437 'bg_type' => 'color',
438 'bg_color' => '#ffffff',
439 'bg_image' => '',
440 'site_logo' => '',
441 'cover_type' => 'color',
442 'cover_color' => '#111C44',
443 'cover_image' => '',
444 'enable_instant_form' => false,
445 'form_container_width' => 620,
446 'single_page_form_title' => true,
447 'use_banner_as_page_background' => false,
448 ],
449 ]
450 );
451
452 register_post_meta(
453 SRFM_FORMS_POST_TYPE,
454 '_srfm_forms_styling',
455 [
456 'single' => true,
457 'type' => 'object',
458 'auth_callback' => '__return_true',
459 'show_in_rest' => [
460 'schema' => [
461 'type' => 'object',
462 'properties' => [
463 'primary_color' => [
464 'type' => 'string',
465 ],
466 'text_color' => [
467 'type' => 'string',
468 ],
469 'text_color_on_primary' => [
470 'type' => 'string',
471 ],
472 'field_spacing' => [
473 'type' => 'string',
474 ],
475 'submit_button_alignment' => [
476 'type' => 'string',
477 ],
478 'bg_type' => [
479 'type' => 'string',
480 ],
481 'bg_color' => [
482 'type' => 'string',
483 ],
484 'bg_image' => [
485 'type' => 'string',
486 ],
487 'bg_image_id' => [
488 'type' => 'integer',
489 ],
490 // Image Properties.
491 'bg_image_position' => [
492 'type' => 'object',
493 'properties' => [
494 'x' => [
495 'type' => 'number',
496 'format' => 'float',
497 ],
498 'y' => [
499 'type' => 'number',
500 'format' => 'float',
501 ],
502 ],
503 ],
504 'bg_image_attachment' => [
505 'type' => 'string',
506 ],
507 'bg_image_repeat' => [
508 'type' => 'string',
509 ],
510 'bg_image_size' => [
511 'type' => 'string',
512 ],
513 'bg_image_size_custom' => [
514 'type' => 'integer',
515 ],
516 'bg_image_size_custom_unit' => [
517 'type' => 'string',
518 ],
519 // Gradient Properties.
520 'bg_gradient' => [
521 'type' => 'string',
522 ],
523 'gradient_type' => [
524 'type' => 'string',
525 ],
526 'bg_gradient_type' => [
527 'type' => 'string',
528 ],
529 'bg_gradient_color_1' => [
530 'type' => 'string',
531 ],
532 'bg_gradient_color_2' => [
533 'type' => 'string',
534 ],
535 'bg_gradient_angle' => [
536 'type' => 'integer',
537 ],
538 'bg_gradient_location_1' => [
539 'type' => 'integer',
540 ],
541 'bg_gradient_location_2' => [
542 'type' => 'integer',
543 ],
544 // Overlay Properties.
545 'bg_overlay_size' => [
546 'type' => 'string',
547 ],
548 'bg_gradient_overlay_type' => [
549 'type' => 'string',
550 ],
551 'bg_overlay_opacity' => [
552 'type' => 'number',
553 ],
554 'bg_overlay_image' => [
555 'type' => 'string',
556 ],
557 'bg_overlay_image_id' => [
558 'type' => 'integer',
559 ],
560 'bg_image_overlay_color' => [
561 'type' => 'string',
562 ],
563 'bg_overlay_custom_size_unit' => [
564 'type' => 'string',
565 ],
566 'bg_overlay_custom_size' => [
567 'type' => 'integer',
568 ],
569 'bg_overlay_blend_mode' => [
570 'type' => 'string',
571 ],
572 'bg_overlay_position' => [
573 'type' => 'object',
574 'properties' => [
575 'x' => [
576 'type' => 'number',
577 'format' => 'float',
578 ],
579 'y' => [
580 'type' => 'number',
581 'format' => 'float',
582 ],
583 ],
584 ],
585 'bg_overlay_attachment' => [
586 'type' => 'string',
587 ],
588 'bg_overlay_repeat' => [
589 'type' => 'string',
590 ],
591 // Gradient Overlay Properties.
592 'bg_overlay_gradient' => [
593 'type' => 'string',
594 ],
595 'overlay_gradient_type' => [
596 'type' => 'string',
597 ],
598 'bg_overlay_gradient_type' => [
599 'type' => 'string',
600 ],
601 'bg_overlay_gradient_color_1' => [
602 'type' => 'string',
603 ],
604 'bg_overlay_gradient_color_2' => [
605 'type' => 'string',
606 ],
607 'bg_overlay_gradient_angle' => [
608 'type' => 'integer',
609 ],
610 'bg_overlay_gradient_location_1' => [
611 'type' => 'integer',
612 ],
613 'bg_overlay_gradient_location_2' => [
614 'type' => 'integer',
615 ],
616 // Form Padding.
617 'form_padding_top' => [
618 'type' => 'number',
619 ],
620 'form_padding_right' => [
621 'type' => 'number',
622 ],
623 'form_padding_bottom' => [
624 'type' => 'number',
625 ],
626 'form_padding_left' => [
627 'type' => 'number',
628 ],
629 'form_padding_unit' => [
630 'type' => 'string',
631 ],
632 'form_padding_link' => [
633 'type' => 'boolean',
634 ],
635 // Border Radius.
636 'form_border_radius_top' => [
637 'type' => 'number',
638 ],
639 'form_border_radius_right' => [
640 'type' => 'number',
641 ],
642 'form_border_radius_bottom' => [
643 'type' => 'number',
644 ],
645 'form_border_radius_left' => [
646 'type' => 'number',
647 ],
648 'form_border_radius_unit' => [
649 'type' => 'string',
650 ],
651 'form_border_radius_link' => [
652 'type' => 'boolean',
653 ],
654 // Form Padding and Border Radius.
655 // Form Padding.
656 'instant_form_padding_top' => [
657 'type' => 'number',
658 ],
659 'instant_form_padding_right' => [
660 'type' => 'number',
661 ],
662 'instant_form_padding_bottom' => [
663 'type' => 'number',
664 ],
665 'instant_form_padding_left' => [
666 'type' => 'number',
667 ],
668 'instant_form_padding_unit' => [
669 'type' => 'string',
670 ],
671 'instant_form_padding_link' => [
672 'type' => 'boolean',
673 ],
674 // Border Radius.
675 'instant_form_border_radius_top' => [
676 'type' => 'number',
677 ],
678 'instant_form_border_radius_right' => [
679 'type' => 'number',
680 ],
681 'instant_form_border_radius_bottom' => [
682 'type' => 'number',
683 ],
684 'instant_form_border_radius_left' => [
685 'type' => 'number',
686 ],
687 'instant_form_border_radius_unit' => [
688 'type' => 'string',
689 ],
690 'instant_form_border_radius_link' => [
691 'type' => 'boolean',
692 ],
693 ],
694 ],
695 ],
696 'default' => [
697 'primary_color' => '#111C44',
698 'text_color' => '#1E1E1E',
699 'text_color_on_primary' => '#FFFFFF',
700 'field_spacing' => 'medium',
701 'submit_button_alignment' => 'left',
702 'bg_type' => 'color',
703 'bg_color' => '#ffffff',
704 'bg_image' => '',
705 'bg_image_position' => [
706 'x' => 0.5,
707 'y' => 0.5,
708 ],
709 'bg_image_attachment' => 'scroll',
710 'bg_image_repeat' => 'no-repeat',
711 'bg_image_size' => 'cover',
712 'bg_image_size_custom' => 100, // Image width when set to custom.
713 'bg_image_size_custom_unit' => '%',
714 'gradient_type' => 'basic',
715 'bg_gradient_type' => 'linear',
716 'bg_gradient_color_1' => '#FFC9B2',
717 'bg_gradient_color_2' => '#C7CBFF',
718 'bg_gradient_angle' => 90,
719 'bg_gradient_location_1' => 0,
720 'bg_gradient_location_2' => 100,
721 'bg_overlay_size' => 'cover',
722 'bg_gradient_overlay_type' => '',
723 'bg_overlay_opacity' => 1,
724 'bg_overlay_image' => '',
725 'bg_image_overlay_color' => '#FFFFFF75',
726 'bg_overlay_custom_size_unit' => '%',
727 'bg_overlay_custom_size' => 100,
728 'bg_overlay_position' => [
729 'x' => 0.5,
730 'y' => 0.5,
731 ],
732 'bg_overlay_attachment' => 'scroll',
733 'bg_overlay_repeat' => 'no-repeat',
734 'bg_overlay_blend_mode' => 'normal',
735 // Gradient Overlay Properties.
736 'overlay_gradient_type' => 'basic',
737 'bg_overlay_gradient_type' => 'linear',
738 'bg_overlay_gradient_color_1' => '#FFC9B2',
739 'bg_overlay_gradient_color_2' => '#C7CBFF',
740 'bg_overlay_gradient_angle' => 90,
741 'bg_overlay_gradient_location_1' => 0,
742 'bg_overlay_gradient_location_2' => 100,
743 // Form Properties.
744 // Padding.
745 'form_padding_top' => 0,
746 'form_padding_right' => 0,
747 'form_padding_bottom' => 0,
748 'form_padding_left' => 0,
749 'form_padding_unit' => 'px',
750 'form_padding_link' => true,
751 // Border Radius.
752 'form_border_radius_top' => 0,
753 'form_border_radius_right' => 0,
754 'form_border_radius_bottom' => 0,
755 'form_border_radius_left' => 0,
756 'form_border_radius_unit' => 'px',
757 'form_border_radius_link' => true,
758 // Form Properties.
759 // Padding.
760 'instant_form_padding_top' => 32,
761 'instant_form_padding_right' => 32,
762 'instant_form_padding_bottom' => 32,
763 'instant_form_padding_left' => 32,
764 'instant_form_padding_unit' => 'px',
765 'instant_form_padding_link' => true,
766 // Border Radius.
767 'instant_form_border_radius_top' => 12,
768 'instant_form_border_radius_right' => 12,
769 'instant_form_border_radius_bottom' => 12,
770 'instant_form_border_radius_left' => 12,
771 'instant_form_border_radius_unit' => 'px',
772 'instant_form_border_radius_link' => true,
773 ],
774 ]
775 );
776
777 // Email notification Metas.
778 register_post_meta(
779 'sureforms_form',
780 '_srfm_email_notification',
781 [
782 'single' => true,
783 'type' => 'array',
784 'auth_callback' => '__return_true',
785 'show_in_rest' => [
786 'schema' => [
787 'type' => 'array',
788 'items' => [
789 'type' => 'object',
790 'properties' => [
791 'id' => [
792 'type' => 'integer',
793 ],
794 'status' => [
795 'type' => 'boolean',
796 ],
797 'is_raw_format' => [
798 'type' => 'boolean',
799 ],
800 'name' => [
801 'type' => 'string',
802 ],
803 'email_to' => [
804 'type' => 'string',
805 ],
806 'email_reply_to' => [
807 'type' => 'string',
808 ],
809 'from_name' => [
810 'type' => 'string',
811 ],
812 'from_email' => [
813 'type' => 'string',
814 ],
815 'email_cc' => [
816 'type' => 'string',
817 ],
818 'email_bcc' => [
819 'type' => 'string',
820 ],
821 'subject' => [
822 'type' => 'string',
823 ],
824 'email_body' => [
825 'type' => 'string',
826 ],
827 ],
828 ],
829 ],
830 ],
831 'default' => [
832 [
833 'id' => 1,
834 'status' => true,
835 'is_raw_format' => false,
836 'name' => __( 'Admin Notification Email', 'sureforms' ),
837 'email_to' => '{admin_email}',
838 'email_reply_to' => '{admin_email}',
839 'from_name' => '{site_title}',
840 'from_email' => '{admin_email}',
841 'email_cc' => '{admin_email}',
842 'email_bcc' => '{admin_email}',
843 'subject' => sprintf( /* translators: %s: Form title smart tag */ __( 'New Form Submission - %s', 'sureforms' ), '{form_title}' ),
844 'email_body' => '{all_data}',
845 ],
846 ],
847 ]
848 );
849
850 // Compliance Settings metas.
851 register_post_meta(
852 'sureforms_form',
853 '_srfm_compliance',
854 [
855 'single' => true,
856 'type' => 'array',
857 'auth_callback' => '__return_true',
858 'show_in_rest' => [
859 'schema' => [
860 'type' => 'array',
861 'items' => [
862 'type' => 'object',
863 'properties' => [
864 'id' => [
865 'type' => 'string',
866 ],
867 'gdpr' => [
868 'type' => 'boolean',
869 ],
870 'do_not_store_entries' => [
871 'type' => 'boolean',
872 ],
873 'auto_delete_entries' => [
874 'type' => 'boolean',
875 ],
876 'auto_delete_days' => [
877 'type' => 'string',
878 ],
879 ],
880 ],
881 ],
882 ],
883 'default' => [
884 [
885 'id' => 'gdpr',
886 'gdpr' => false,
887 'do_not_store_entries' => false,
888 'auto_delete_entries' => false,
889 'auto_delete_days' => '',
890 ],
891 ],
892 ]
893 );
894
895 // form confirmation.
896 register_post_meta(
897 'sureforms_form',
898 '_srfm_form_confirmation',
899 [
900 'single' => true,
901 'type' => 'array',
902 'auth_callback' => static function() {
903 return current_user_can( 'manage_options' );
904 },
905 'sanitize_callback' => static function( $meta_value ) {
906 if ( ! is_array( $meta_value ) ) {
907 return [];
908 }
909 $sanitized = [];
910 foreach ( $meta_value as $item ) {
911 if ( ! is_array( $item ) ) {
912 continue;
913 }
914 $sanitized_item = [
915 'id' => isset( $item['id'] ) ? intval( $item['id'] ) : 0,
916 'confirmation_type' => isset( $item['confirmation_type'] ) ? sanitize_text_field( $item['confirmation_type'] ) : '',
917 'page_url' => isset( $item['page_url'] ) ? esc_url_raw( $item['page_url'] ) : '',
918 'custom_url' => isset( $item['custom_url'] ) ? esc_url_raw( $item['custom_url'] ) : '',
919 'message' => isset( $item['message'] ) ? Helper::strip_js_attributes( $item['message'] ) : '',
920 'submission_action' => isset( $item['submission_action'] ) ? sanitize_text_field( $item['submission_action'] ) : '',
921 'enable_query_params' => isset( $item['enable_query_params'] ) ? filter_var( $item['enable_query_params'], FILTER_VALIDATE_BOOLEAN ) : false,
922 'query_params' => isset( $item['query_params'] ) ? array_map( 'sanitize_text_field', (array) $item['query_params'] ) : [],
923 ];
924
925 $sanitized_item = apply_filters( 'srfm_form_confirmation_params', $sanitized_item, $item );
926
927 $sanitized[] = $sanitized_item;
928 }
929 return $sanitized;
930 },
931 'show_in_rest' => [
932 'schema' => [
933 'type' => 'array',
934 'items' => [
935 'type' => 'object',
936 'properties' => [
937 'id' => [
938 'type' => 'integer',
939 ],
940 'confirmation_type' => [
941 'type' => 'string',
942 ],
943 'page_url' => [
944 'type' => 'string',
945 ],
946 'custom_url' => [
947 'type' => 'string',
948 ],
949 'message' => [
950 'type' => 'string',
951 ],
952 'submission_action' => [
953 'type' => 'string',
954 ],
955 'enable_query_params' => [
956 'type' => 'boolean',
957 ],
958 'query_params' => [
959 'type' => 'array',
960 ],
961 ],
962 ],
963 ],
964 ],
965 'default' => [
966 [
967 'id' => 1,
968 'confirmation_type' => 'same page',
969 'page_url' => '',
970 'custom_url' => '',
971 'message' => '<p style="text-align: center;"><img src="' . esc_attr( $check_icon ) . '" alt="" aria-hidden="true"></img></p><h2 style="text-align: center;">' . esc_html__( 'Thank you', 'sureforms' ) . '</h2>',
972 'submission_action' => 'hide form',
973 ],
974 ],
975 ]
976 );
977
978 // conditional logic.
979 do_action( 'srfm_register_conditional_logic_post_meta' );
980 /**
981 * Hook for registering additional Post Meta
982 */
983 do_action( 'srfm_register_additional_post_meta' );
984 }
985
986 /**
987 * Custom Shortcode.
988 *
989 * @param array<mixed> $atts Attributes.
990 * @return string|false. $content Post Content.
991 * @since 0.0.1
992 */
993 public function forms_shortcode( array $atts ) {
994 $atts = shortcode_atts(
995 [
996 'id' => '',
997 'show_title' => true,
998 ],
999 $atts
1000 );
1001
1002 $id = intval( $atts['id'] );
1003 $post = get_post( $id );
1004
1005 if ( ! empty( $id ) && $post ) {
1006 return Generate_Form_Markup::get_form_markup( $id, ! filter_var( $atts['show_title'], FILTER_VALIDATE_BOOLEAN ), '', 'post', true );
1007 }
1008
1009 return '';
1010 }
1011
1012 /**
1013 * Add custom column header.
1014 *
1015 * @param array<mixed> $columns Attributes.
1016 * @return array<mixed> $columns Post Content.
1017 * @since 0.0.1
1018 */
1019 public function custom_form_columns( $columns ) {
1020 return [
1021 'cb' => $columns['cb'],
1022 'title' => $columns['title'],
1023 'sureforms' => __( 'Shortcode', 'sureforms' ),
1024 'entries' => __( 'Entries', 'sureforms' ),
1025 'author' => $columns['author'],
1026 'date' => $columns['date'],
1027 ];
1028 }
1029
1030 /**
1031 * Populate custom column with data.
1032 *
1033 * @param string $column Attributes.
1034 * @param int $post_id Attributes.
1035 * @return void
1036 * @since 0.0.1
1037 */
1038 public function custom_form_column_data( $column, $post_id ) {
1039 if ( 'sureforms' === $column ) {
1040 ob_start();
1041 ?>
1042 <div class="srfm-shortcode-container">
1043 <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 ) ); ?>']" />
1044 <button type="button" class="components-button components-clipboard-button has-icon srfm-shortcode" onclick="handleFormShortcode(this)">
1045 <span id="srfm-copy-icon" class="dashicon dashicons dashicons-admin-page"></span>
1046 </button>
1047 </div>
1048 <?php
1049 ob_end_flush();
1050 }
1051 if ( 'entries' === $column ) {
1052 // Entries URL to redirect user based on the form ID.
1053 $entries_url = wp_nonce_url(
1054 add_query_arg(
1055 [
1056 'form_filter' => $post_id,
1057 ],
1058 admin_url( 'admin.php?page=sureforms_entries' )
1059 ),
1060 'srfm_entries_action'
1061 );
1062
1063 // Get the entry count for the form.
1064 $entries_count = Entries::get_total_entries_by_status( 'all', $post_id );
1065
1066 ob_start();
1067 ?>
1068 <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>
1069 <?php
1070 ob_end_flush();
1071 }
1072 }
1073
1074 /**
1075 * Show the import form popup
1076 *
1077 * @since 0.0.1
1078 * @return void
1079 */
1080 public function import_form_popup() {
1081 $screen = get_current_screen();
1082 $id = $screen ? $screen->id : '';
1083 if ( 'edit-sureforms_form' === $id ) {
1084 ?>
1085 <div class="srfm-import-plugin-wrap">
1086 <div class="srfm-import-wrap">
1087 <p class="srfm-import-help"><?php echo esc_html__( 'Please choose the SureForms export file (.json) that you wish to import.', 'sureforms' ); ?></p>
1088 <form method="post" enctype="multipart/form-data" class="srfm-import-form">
1089 <input type="file" id="srfm-import-file" onchange="handleFileChange(event)" name="import form" accept=".json">
1090 <input type="submit" name="import-form-submit" id="import-form-submit" class="srfm-import-button" value="<?php esc_attr_e( 'Import Now', 'sureforms' ); ?>" disabled>
1091 </form>
1092 <p id="srfm-import-error"><?php echo esc_html__( 'There is some error in json file, please export the SureForms Forms again.', 'sureforms' ); ?></p>
1093 </div>
1094 </div>
1095 <?php
1096 }
1097 }
1098
1099 /**
1100 * Redirect to home page if instant form is not enabled.
1101 *
1102 * @since 0.0.1
1103 * @return void
1104 */
1105 public function srfm_instant_form_redirect() {
1106
1107 $form_id = Helper::get_integer_value( get_the_ID() );
1108
1109 $instant_form_settings = Helper::get_array_value( Helper::get_post_meta( $form_id, '_srfm_instant_form_settings' ) );
1110 $enable_instant_form = ! empty( $instant_form_settings['enable_instant_form'] ) ? boolval( $instant_form_settings['enable_instant_form'] ) : false;
1111
1112 if ( $enable_instant_form ) {
1113 return;
1114 }
1115
1116 $form_preview = '';
1117
1118 $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.
1119
1120 if ( $form_preview_attr ) {
1121 $form_preview = filter_var( $form_preview_attr, FILTER_VALIDATE_BOOLEAN );
1122 }
1123
1124 if ( is_singular( 'sureforms_form' ) && ! $form_preview && ! current_user_can( 'manage_options' ) ) {
1125 wp_safe_redirect( home_url() );
1126 return;
1127 }
1128 }
1129
1130 /**
1131 * Restrict RankMath meta boxes in edit page.
1132 *
1133 * @since 0.0.5
1134 * @return void
1135 */
1136 public function restrict_data() {
1137 add_filter( 'rank_math/excluded_post_types', [ $this, 'unset_sureforms_post_type' ] );
1138 }
1139
1140 /**
1141 * Remove SureForms post type from RankMath and Yoast.
1142 *
1143 * @param array<mixed> $post_types Post types.
1144 * @since 0.0.5
1145 * @return array<mixed> $post_types Modified post types.
1146 */
1147 public function unset_sureforms_post_type( $post_types ) {
1148 return array_filter(
1149 $post_types,
1150 static function( $post_type ) {
1151 if ( is_array( $post_type ) && isset( $post_type['name'] ) ) {
1152 return SRFM_FORMS_POST_TYPE !== $post_type['name'];
1153 }
1154 return SRFM_FORMS_POST_TYPE !== $post_type;
1155 }
1156 );
1157 }
1158
1159 /**
1160 * Restrict unwanted insertions from the AIOSEO plugin.
1161 *
1162 * This method ensures that the SureForms post type is excluded from AIOSEO's
1163 * public post types unless the current page is related to AIOSEO settings.
1164 *
1165 * @return void
1166 * @since 1.6.0
1167 */
1168 public function restrict_in_aioseo_plugin() {
1169 /**
1170 * Checks if the AIOSEO plugin is installed and excludes the SureForms post type from AIOSEO's public post types.
1171 *
1172 * - Verifies the presence of the AIOSEO_DIR constant to ensure AIOSEO is installed.
1173 * - Allows AIOSEO functionality on its own settings pages by checking the `REQUEST_URI` and `page` query parameter.
1174 * - Excludes the SureForms post type from AIOSEO's public post types using the `aioseo_public_post_types` filter.
1175 *
1176 * Security Note:
1177 * - Nonce verification is intentionally skipped (`phpcs:ignore WordPress.Security.NonceVerification.Recommended`)
1178 * because this code is only performing a read operation to check the current request URI and query parameters.
1179 * It does not modify or process sensitive data, making nonce verification unnecessary in this context.
1180 */
1181 // Check if AIOSEO is installed by verifying the AIOSEO_DIR constant.
1182 if ( ! defined( 'AIOSEO_DIR' ) ) {
1183 return;
1184 }
1185
1186 // Allow AIOSEO functionality on its own settings pages.
1187 if ( isset( $_SERVER['REQUEST_URI'] ) ) {
1188 $request_uri = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
1189 if ( strpos( $request_uri, 'admin.php' ) !== false ) {
1190 if ( isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verification is not required here because Safe here as we're only reading the `page` parameter.
1191 $page = sanitize_text_field( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verification is not required here because only we are reading the `page` parameter.
1192 if ( strpos( $page, 'aioseo' ) !== false ) {
1193 return;
1194 }
1195 }
1196 }
1197 }
1198
1199 // Exclude the SureForms post type from AIOSEO's public post types.
1200 add_filter( 'aioseo_public_post_types', [ $this, 'unset_sureforms_post_type' ] );
1201 }
1202
1203 /**
1204 * Restrict interference of other plugins with SureForms.
1205 *
1206 * @since 0.0.5
1207 * @return void
1208 */
1209 private function restrict_unwanted_insertions() {
1210 // Restrict RankMath metaboxes in edit page.
1211 add_action( 'cmb2_admin_init', [ $this, 'restrict_data' ] );
1212
1213 // Restrict Yoast columns.
1214 add_filter( 'wpseo_accessible_post_types', [ $this, 'unset_sureforms_post_type' ] );
1215 add_filter( 'wpseo_metabox_prio', '__return_false' );
1216
1217 // Restrict AIOSEO columns.
1218 $this->restrict_in_aioseo_plugin();
1219 }
1220 }
1221