PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 1.7.4
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v1.7.4
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 1.7.4, at inc/post-types.php

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