PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 2.5.0
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v2.5.0
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 / admin / admin.php

admin.php in SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz 2.5.0, at admin/admin.php

1,639 lines 54.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin Class.
4 *
5 * @package sureforms.
6 */
7
8 namespace SRFM\Admin;
9
10 use SRFM\Inc\AI_Form_Builder\AI_Helper;
11 use SRFM\Inc\Database\Tables\Entries;
12 use SRFM\Inc\Helper;
13 use SRFM\Inc\Onboarding;
14 use SRFM\Inc\Payments\Payment_Helper;
15 use SRFM\Inc\Payments\Stripe\Stripe_Helper;
16 use SRFM\Inc\Traits\Get_Instance;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit; // Exit if accessed directly.
20 }
21 /**
22 * Admin handler class.
23 *
24 * @since 0.0.1
25 */
26 class Admin {
27 use Get_Instance;
28
29 /**
30 * Dashboard widget entries data.
31 *
32 * @var array
33 * @since 1.9.1
34 */
35 private $dashboard_widget_data = [];
36
37 /**
38 * SureForms Page Default permission.
39 *
40 * @var string
41 * @since 1.12.2
42 */
43 private static $sureforms_page_default_capability = 'manage_options';
44
45 /**
46 * Class constructor.
47 *
48 * @return void
49 * @since 0.0.1
50 */
51 public function __construct() {
52 add_action( 'admin_menu', [ $this, 'add_menu_page' ], 9 );
53 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
54 add_action( 'admin_menu', [ $this, 'settings_page' ] );
55 add_action( 'admin_menu', [ $this, 'add_new_form' ] );
56 add_action( 'admin_menu', [ $this, 'add_suremail_page' ] );
57 if ( ! Helper::has_pro() ) {
58 add_action( 'admin_menu', [ $this, 'add_upgrade_to_pro' ] );
59 add_action( 'admin_footer', [ $this, 'add_upgrade_to_pro_target_attr' ] );
60 }
61
62 add_filter( 'plugin_action_links', [ $this, 'add_settings_link' ], 10, 2 );
63 add_action( 'enqueue_block_assets', [ $this, 'enqueue_styles' ] );
64 add_action( 'admin_head', [ $this, 'enqueue_header_styles' ] );
65 add_filter( 'admin_body_class', [ $this, 'admin_template_picker_body_class' ] );
66
67 // this action is used to restrict Spectra's quick action bar on SureForms CPTS.
68 add_action( 'uag_enable_quick_action_sidebar', [ $this, 'restrict_spectra_quick_action_bar' ] );
69
70 add_action( 'current_screen', [ $this, 'enable_gutenberg_for_sureforms' ], 100 );
71 // Register notices early for React pages (before admin_enqueue_scripts).
72 add_action( 'admin_init', [ $this, 'register_pro_compatibility_notices' ], 5 );
73 // Display notices on traditional WordPress admin pages.
74 add_action( 'admin_notices', [ $this, 'srfm_pro_version_compatibility' ] );
75
76 // This action enqueues translations for NPS Survey library.
77 // A better solution will be required from library to resolve plugin conflict.
78 add_action(
79 'admin_footer',
80 static function() {
81 Helper::register_script_translations( 'nps-survey-script' );
82 },
83 1000
84 );
85 // Enfold theme compatibility to enable block editor for SureForms post type.
86 add_filter( 'avf_use_block_editor_for_post', [ $this, 'enable_block_editor_in_enfold_theme' ] );
87
88 // Add action links to the plugin page.
89 add_filter( 'plugin_action_links_' . SRFM_BASENAME, [ $this, 'add_action_links' ] );
90 // Check if admin notification is enabled and add entries badge.
91 $general_options = get_option( 'srfm_general_settings_options', [] );
92 $admin_notification_on = isset( $general_options['srfm_admin_notification'] ) ? (bool) $general_options['srfm_admin_notification'] : true;
93
94 if ( $admin_notification_on ) {
95 add_action( 'admin_menu', [ $this, 'maybe_add_entries_badge' ], 99 );
96 }
97
98 add_action( 'admin_menu', [ $this, 'add_payments_badge' ], 99 );
99
100 add_filter( 'wpforms_current_user_can', [ $this, 'disable_wpforms_capabilities' ], 10, 3 );
101
102 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_pointer' ] );
103 // Ajax callbacks for wp-pointer functionality.
104 add_action( 'wp_ajax_should_show_pointer', [ $this, 'pointer_should_show' ] );
105 add_action( 'wp_ajax_sureforms_dismiss_pointer', [ $this, 'pointer_dismissed' ] );
106 add_action( 'wp_ajax_sureforms_accept_cta', [ $this, 'pointer_accepted_cta' ] );
107
108 // Register dashboard widget only if there are recent entries.
109 add_action( 'admin_init', [ $this, 'maybe_register_dashboard_widget' ] );
110
111 // Save first form creation time stamp.
112 add_action( 'admin_init', [ $this, 'save_first_form_creation_time_stamp' ] );
113 }
114
115 /**
116 * Get the first form creation time stamp.
117 *
118 * @since 1.10.1
119 * @return int|false
120 */
121 public static function get_first_form_creation_time_stamp() {
122 return Helper::get_srfm_option( 'first_form_created_at', false );
123 }
124
125 /**
126 * Check if the first form has been created.
127 *
128 * @since 1.10.1
129 * @return bool
130 */
131 public static function is_first_form_created() {
132 // Convert the first form creation time stamp to a boolean. If it exists, it will return true, otherwise false.
133 $first_form_creation_time_stamp = self::get_first_form_creation_time_stamp();
134
135 // If the first form creation time stamp is not set, return false.
136 if ( ! $first_form_creation_time_stamp ) {
137 return false; // No forms created yet.
138 }
139
140 // Check if the first form creation time stamp is a valid integer and greater than zero.
141 return is_int( $first_form_creation_time_stamp ) && $first_form_creation_time_stamp > 0;
142 }
143
144 /**
145 * Check and save the first form creation time stamp.
146 * If not already saved.
147 *
148 * @since 1.10.1
149 * @return void
150 */
151 public static function save_first_form_creation_time_stamp() {
152 if ( ! Helper::current_user_can() || self::is_first_form_created() || ! defined( 'SRFM_FORMS_POST_TYPE' ) || ! post_type_exists( SRFM_FORMS_POST_TYPE ) ) {
153 return;
154 }
155
156 // Get the first form creation time from the database that is published.
157 $query = new \WP_Query(
158 [
159 'post_type' => SRFM_FORMS_POST_TYPE,
160 'posts_per_page' => 1,
161 'orderby' => 'date',
162 'order' => 'ASC',
163 'fields' => 'ids',
164 'post_status' => 'publish',
165 ]
166 );
167
168 if ( ! empty( $query->posts ) && isset( $query->posts[0] ) ) {
169 // Get the first post from the query result.
170 $post_id = $query->posts[0];
171 // Get the post creation time in GMT.
172 $creation_time = get_post_field( 'post_date_gmt', $post_id );
173 // Convert the creation time to a timestamp.
174 $timestamp = strtotime( $creation_time );
175
176 if ( ! $timestamp ) {
177 return;
178 }
179
180 Helper::update_srfm_option( 'first_form_created_at', $timestamp );
181 }
182 }
183
184 /**
185 * Check if n days have passed since the first form creation.
186 * This is used to determine if the dynamic nudges should be shown.
187 *
188 * @param int $days Number of days to check.
189 * @since 1.10.1
190 * @return bool
191 */
192 public static function check_first_form_creation_threshold( $days = 3 ) {
193 $first_form_creation_time_stamp = self::get_first_form_creation_time_stamp();
194
195 if ( ! $first_form_creation_time_stamp ) {
196 return false; // No forms created yet.
197 }
198
199 /**
200 * Calculate the number of days since the first form was created.
201 */
202 $days_from_creation = ( strtotime( current_time( 'mysql' ) ) - $first_form_creation_time_stamp ) / DAY_IN_SECONDS;
203
204 // Return a boolean indicating if the number of days since creation is greater than the specified days.
205 return $days_from_creation > $days;
206 }
207
208 /**
209 * Show action on plugin page.
210 *
211 * @param array $links links.
212 * @return array
213 * @since 1.4.2
214 */
215 public function add_action_links( $links ) {
216 if ( ! Helper::has_pro() ) {
217 // Display upsell link if SureForms Pro is not installed.
218 $upsell_link = add_query_arg(
219 [
220 'utm_medium' => 'plugin-list',
221 ],
222 Helper::get_sureforms_website_url( 'pricing' )
223 );
224
225 ob_start();
226 ?>
227 <a href="<?php echo esc_url( $upsell_link ); ?>" target="_blank" rel="noreferrer" class="sureforms-plugins-go-pro">
228 <?php echo esc_html__( 'Get SureForms Pro', 'sureforms' ); ?>
229 </a>
230 <?php
231 $links[] = trim( ob_get_clean() );
232 }
233
234 return $links;
235 }
236
237 /**
238 * Enable block editor in Enfold theme for SureForms post type.
239 *
240 * @param bool $use_block_editor Whether to use block editor.
241 * @since 1.3.1
242 */
243 public function enable_block_editor_in_enfold_theme( $use_block_editor ) {
244 // if SureForms form post type then return true.
245 if ( SRFM_FORMS_POST_TYPE === get_current_screen()->post_type ) {
246 return true;
247 }
248 return $use_block_editor;
249 }
250
251 /**
252 * Enable Gutenberg for SureForms associated post types.
253 *
254 * @since 0.0.10
255 */
256 public function enable_gutenberg_for_sureforms() {
257 /**
258 * Check if the classic editor is enabled from Classic Editor plugin settings or Divi settings.
259 */
260 if ( 'block' === get_option( 'classic-editor-replace' ) || 'on' === get_option( 'et_enable_classic_editor' ) ) {
261 return;
262 }
263
264 $srfm_post_types = apply_filters( 'srfm_enable_gutenberg_post_types', [ SRFM_FORMS_POST_TYPE ] );
265
266 if ( in_array( get_current_screen()->post_type, $srfm_post_types, true ) ) {
267 add_filter( 'use_block_editor_for_post_type', '__return_true', 110 );
268 add_filter( 'gutenberg_can_edit_post_type', '__return_true', 110 );
269 }
270 }
271
272 /**
273 * Sureforms editor header styles.
274 *
275 * @since 0.0.1
276 */
277 public function enqueue_header_styles() {
278 $current_screen = get_current_screen();
279 $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
280 $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
281
282 $css_uri = SRFM_URL . 'assets/css/' . $dir_name . '/';
283
284 /* RTL */
285 if ( is_rtl() ) {
286 $file_prefix .= '-rtl';
287 }
288
289 if ( 'sureforms_form' === $current_screen->id ) {
290 wp_enqueue_style( SRFM_SLUG . '-editor-header-styles', $css_uri . 'header-styles' . $file_prefix . '.css', [], SRFM_VER );
291 }
292 }
293
294 /**
295 * Add menu page.
296 *
297 * @return void
298 * @since 0.0.1
299 */
300 public function add_menu_page() {
301 $menu_slug = 'sureforms_menu';
302
303 $logo = file_get_contents( plugin_dir_path( SRFM_FILE ) . 'images/icon.svg' );
304 add_menu_page(
305 __( 'SureForms', 'sureforms' ),
306 __( 'SureForms', 'sureforms' ),
307 self::$sureforms_page_default_capability,
308 $menu_slug,
309 static function () {
310 },
311 'data:image/svg+xml;base64,' . base64_encode( $logo ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
312 30
313 );
314
315 // Add the Dashboard Submenu.
316 add_submenu_page(
317 $menu_slug,
318 __( 'Dashboard', 'sureforms' ),
319 __( 'Dashboard', 'sureforms' ),
320 self::$sureforms_page_default_capability,
321 $menu_slug,
322 [ $this, 'render_dashboard' ]
323 );
324 }
325
326 /**
327 * Add Settings page.
328 *
329 * @return void
330 * @since 0.0.1
331 */
332 public function settings_page() {
333 $callback = [ $this, 'settings_page_callback' ];
334 add_submenu_page(
335 'sureforms_menu',
336 __( 'Settings', 'sureforms' ),
337 __( 'Settings', 'sureforms' ),
338 self::$sureforms_page_default_capability,
339 'sureforms_form_settings',
340 $callback
341 );
342
343 // Get the current submenu page.
344 $submenu_page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- $_GET['page'] does not provide nonce.
345
346 if ( ! isset( $_GET['tab'] ) && 'sureforms_form_settings' === $submenu_page ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- $_GET['page'] does not provide nonce.
347 wp_safe_redirect( admin_url( 'admin.php?page=sureforms_form_settings&tab=general-settings' ) );
348 exit;
349 }
350 }
351
352 /**
353 * Open to Upgrade to Pro submenu link in new tab.
354 *
355 * @return void
356 * @since 1.6.1
357 */
358 public function add_upgrade_to_pro_target_attr() {
359 ?>
360 <script type="text/javascript">
361 document.addEventListener('DOMContentLoaded', function () {
362 // Upgrade link handler.
363 // IMPORTANT: If this URL changes, also update it in the `add_upgrade_to_pro` function.
364 const upgradeLink = document.querySelector('a[href*="https://sureforms.com/upgrade"]');
365 if (upgradeLink) {
366 upgradeLink.addEventListener('click', e => {
367 e.preventDefault();
368 window.open(upgradeLink.href, '_blank');
369 });
370 }
371 });
372 </script>
373 <?php
374 }
375
376 /**
377 * Add Upgrade to pro menu item.
378 *
379 * @return void
380 * @since 1.6.1
381 */
382 public function add_upgrade_to_pro() {
383 // The url used here is used as a selector for css to style the upgrade to pro submenu.
384 // If you are changing this url, please make sure to update the css as well.
385 $upgrade_url = add_query_arg(
386 [
387 'utm_medium' => 'submenu_link_upgrade',
388 ],
389 Helper::get_sureforms_website_url( 'upgrade' )
390 );
391
392 add_submenu_page(
393 'sureforms_menu',
394 __( 'Upgrade', 'sureforms' ),
395 __( 'Upgrade', 'sureforms' ),
396 self::$sureforms_page_default_capability,
397 $upgrade_url
398 );
399 }
400
401 /**
402 * Add SMTP promotional submenu page.
403 *
404 * @return void
405 * @since 1.7.1
406 */
407 public function add_suremail_page() {
408 add_submenu_page(
409 'sureforms_menu',
410 __( 'SMTP', 'sureforms' ),
411 __( 'SMTP', 'sureforms' ),
412 self::$sureforms_page_default_capability,
413 'sureforms_smtp',
414 [ $this, 'suremail_page_callback' ]
415 );
416
417 // Get the current submenu page.
418 $submenu_page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- $_GET['page'] does not provide nonce.
419
420 // Check if SureMail is installed and active.
421 if ( 'sureforms_smtp' === $submenu_page && file_exists( WP_PLUGIN_DIR . '/suremails/suremails.php' ) && is_plugin_active( 'suremails/suremails.php' ) ) {
422 // Plugin is installed and active - redirect to SureMail dashboard.
423 wp_safe_redirect( admin_url( 'options-general.php?page=suremail#/dashboard' ) );
424 exit;
425 }
426 }
427
428 /**
429 * SMTP promotional page callback.
430 *
431 * @return void
432 * @since 1.7.1
433 */
434 public function suremail_page_callback() {
435 ?>
436 <div id="srfm-suremail-container" class="srfm-admin-wrapper"></div>
437 <?php
438 }
439
440 /**
441 * Render Admin Dashboard.
442 *
443 * @return void
444 * @since 0.0.1
445 */
446 public function render_dashboard() {
447 ?>
448 <div id="srfm-dashboard-container" class="srfm-admin-wrapper"></div>
449 <?php
450 }
451
452 /**
453 * Settings page callback.
454 *
455 * @return void
456 * @since 0.0.1
457 */
458 public function settings_page_callback() {
459 ?>
460 <div id="srfm-settings-container" class="srfm-admin-wrapper"></div>
461 <?php
462 }
463
464 /**
465 * Add new form menu item.
466 *
467 * @return void
468 * @since 0.0.1
469 */
470 public function add_new_form() {
471 add_submenu_page(
472 'sureforms_menu',
473 __( 'Forms', 'sureforms' ),
474 __( 'Forms', 'sureforms' ),
475 self::$sureforms_page_default_capability,
476 'sureforms_forms',
477 [ $this, 'render_forms' ],
478 1
479 );
480 add_submenu_page(
481 'sureforms_menu',
482 __( 'New Form', 'sureforms' ),
483 __( 'New Form', 'sureforms' ),
484 self::$sureforms_page_default_capability,
485 'add-new-form',
486 [ $this, 'add_new_form_callback' ],
487 2
488 );
489 $entries_hook = add_submenu_page(
490 'sureforms_menu',
491 __( 'Entries', 'sureforms' ),
492 __( 'Entries', 'sureforms' ),
493 self::$sureforms_page_default_capability,
494 SRFM_ENTRIES,
495 [ $this, 'render_entries' ],
496 3
497 );
498
499 add_submenu_page(
500 'sureforms_menu',
501 __( 'Payments', 'sureforms' ),
502 __( 'Payments', 'sureforms' ),
503 self::$sureforms_page_default_capability,
504 SRFM_PAYMENTS,
505 [ $this, 'render_payments' ],
506 4
507 );
508
509 if ( $entries_hook ) {
510 add_action( 'load-' . $entries_hook, [ $this, 'mark_entries_page_visit' ] );
511 }
512 }
513
514 /**
515 * Payments page callback.
516 *
517 * @return void
518 * @since 2.0.0
519 */
520 public function render_payments() {
521 ?>
522 <div id="srfm-payments-react-container" class="srfm-admin-wrapper"></div>
523 <?php
524 }
525
526 /**
527 * Add new form mentu item callback.
528 *
529 * @return void
530 * @since 0.0.1
531 */
532 public function add_new_form_callback() {
533 ?>
534 <div id="srfm-add-new-form-container" class="srfm-admin-wrapper"></div>
535 <?php
536 }
537
538 /**
539 * Forms page callback.
540 *
541 * @return void
542 * @since 2.0.0
543 */
544 public function render_forms() {
545 ?>
546 <div id="srfm-forms-root" class="srfm-admin-wrapper"></div>
547 <?php
548 }
549
550 /**
551 * Entries page callback.
552 *
553 * @since 0.0.13
554 * @since 2.0.0 - Updated the entries UI and the function definition.
555 * @return void
556 */
557 public function render_entries() {
558 echo '<div id="srfm-entries-root"></div>';
559 }
560
561 /**
562 * Add notification badge to SureForms menu when there are new entries.
563 *
564 * @since 1.7.3
565 * @return void
566 */
567 public function maybe_add_entries_badge() {
568 if ( ! Helper::current_user_can() ) {
569 return;
570 }
571
572 // If currently viewing the entries listing page, mark it as visited and skip the badge.
573 if ( isset( $_GET['page'] ) && SRFM_ENTRIES === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only checking the page slug.
574 $this->mark_entries_page_visit();
575 return;
576 }
577
578 $srfm_options = get_option( 'srfm_options', [] );
579 $last_visit = isset( $srfm_options['entries_last_visited'] ) ? absint( $srfm_options['entries_last_visited'] ) : 0;
580 $new_entries = Entries::get_entries_count_after( $last_visit );
581
582 if ( $new_entries <= 0 ) {
583 return;
584 }
585
586 global $menu;
587 foreach ( $menu as $index => $item ) {
588 if ( isset( $item[2] ) && 'sureforms_menu' === $item[2] ) {
589 ob_start();
590 ?>
591 <span class="srfm-update-dot"></span>
592 <?php
593 $dot_html = ob_get_clean();
594 // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Adding notifications for menu item.
595 $menu[ $index ][0] .= $dot_html;
596 break;
597 }
598 }
599
600 global $submenu;
601 if ( isset( $submenu['sureforms_menu'] ) ) {
602 foreach ( $submenu['sureforms_menu'] as $index => $sub_item ) {
603 if ( isset( $sub_item[2] ) && SRFM_ENTRIES === $sub_item[2] ) {
604 ob_start();
605 ?>
606 <span class="update-plugins count-<?php echo absint( $new_entries ); ?>">
607 <span class="plugin-count"><?php echo absint( $new_entries ); ?></span>
608 </span>
609 <?php
610 $badge_html = ob_get_clean();
611 // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Adding notifications for submenu item.
612 $submenu['sureforms_menu'][ $index ][0] .= $badge_html;
613 break;
614 }
615 }
616 }
617 }
618
619 /**
620 * Summary of add_payments_badge
621 *
622 * @since 2.0.0
623 * @return void
624 */
625 public function add_payments_badge() {
626 if ( ! Helper::current_user_can() ) {
627 return;
628 }
629
630 global $submenu;
631 if ( isset( $submenu['sureforms_menu'] ) ) {
632 foreach ( $submenu['sureforms_menu'] as $index => $sub_item ) {
633 if ( isset( $sub_item[2] ) && SRFM_PAYMENTS === $sub_item[2] ) {
634 ob_start();
635 ?>
636 <span style="color: #4ADE80;font-size: 9px;font-weight: 600;"><?php echo esc_html__( 'New', 'sureforms' ); ?></span>
637 <?php
638 $new_badge_html = ob_get_clean();
639 // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Adding notifications for submenu item.
640 $submenu['sureforms_menu'][ $index ][0] .= $new_badge_html;
641 break;
642 }
643 }
644 }
645 }
646
647 /**
648 * Mark the user's visit to the entries page.
649 *
650 * @since 1.7.3
651 * @return void
652 */
653 public function mark_entries_page_visit() {
654 if ( Helper::current_user_can() ) {
655 $srfm_options = get_option( 'srfm_options', [] );
656 $srfm_options['entries_last_visited'] = time();
657 \SRFM\Inc\Helper::update_admin_settings_option( 'srfm_options', $srfm_options );
658 }
659 }
660
661 /**
662 * Adds a settings link to the plugin action links on the plugins page.
663 *
664 * @param array $links An array of plugin action links.
665 * @param string $file The plugin file path.
666 * @return array The updated array of plugin action links.
667 * @since 0.0.1
668 */
669 public function add_settings_link( $links, $file ) {
670 if ( 'sureforms/sureforms.php' === $file ) {
671 ob_start();
672 ?>
673 <a href="<?php echo esc_url( admin_url( 'admin.php?page=sureforms_form_settings&tab=general-settings' ) ); ?>">
674 <?php echo esc_html__( 'Settings', 'sureforms' ); ?>
675 </a>
676 <?php
677 $settings_link_html = ob_get_clean();
678 $plugin_links = apply_filters(
679 'sureforms_plugin_action_links',
680 [
681 'sureforms_settings' => $settings_link_html,
682 ]
683 );
684 $links = array_merge( $plugin_links, $links );
685 }
686 return $links;
687 }
688
689 /**
690 * Sureforms block editor styles.
691 *
692 * @since 0.0.1
693 */
694 public function enqueue_styles() {
695 $current_screen = get_current_screen();
696 global $wp_version;
697
698 $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
699 $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
700
701 $css_uri = SRFM_URL . 'assets/css/' . $dir_name . '/';
702 $vendor_css_uri = SRFM_URL . 'assets/css/minified/deps/';
703
704 /* RTL */
705 if ( is_rtl() ) {
706 $file_prefix .= '-rtl';
707 }
708
709 // Enqueue editor styles for post and page.
710 if ( SRFM_FORMS_POST_TYPE === $current_screen->post_type ) {
711 wp_enqueue_style( SRFM_SLUG . '-editor', $css_uri . 'backend/editor' . $file_prefix . '.css', [], SRFM_VER );
712 wp_enqueue_style( SRFM_SLUG . '-backend-blocks', $css_uri . 'blocks/default/backend' . $file_prefix . '.css', [], SRFM_VER );
713 wp_enqueue_style( SRFM_SLUG . '-intl', $vendor_css_uri . 'intl/intlTelInput-backend.min.css', [], SRFM_VER );
714 wp_enqueue_style( SRFM_SLUG . '-common', $css_uri . 'common' . $file_prefix . '.css', [], SRFM_VER );
715 wp_enqueue_style( SRFM_SLUG . '-reactQuill', $vendor_css_uri . 'quill/quill.snow.css', [], SRFM_VER );
716 wp_enqueue_style( SRFM_SLUG . '-single-form-modal', $css_uri . 'single-form-setting' . $file_prefix . '.css', [], SRFM_VER );
717
718 // if version is equal to or lower than 6.6.2 then add compatibility css.
719 if ( version_compare( $wp_version, '6.6.2', '<=' ) ) {
720 $srfm_inline_css = '.srfm-settings-modal .srfm-setting-modal-container .components-toggle-control .components-base-control__help{
721 margin-left: 4em;
722 }';
723 wp_add_inline_style( SRFM_SLUG . '-single-form-modal', $srfm_inline_css );
724 }
725 }
726
727 wp_enqueue_style( SRFM_SLUG . '-form-selector', $css_uri . 'srfm-form-selector' . $file_prefix . '.css', [], SRFM_VER );
728 wp_enqueue_style( SRFM_SLUG . '-common-editor', SRFM_URL . 'assets/build/common-editor.css', [], SRFM_VER, 'all' );
729 }
730
731 /**
732 * Get Breadcrumbs for current page.
733 *
734 * @since 0.0.1
735 * @return array Breadcrumbs Array.
736 */
737 public function get_breadcrumbs_for_current_page() {
738 global $post, $pagenow;
739 $breadcrumbs = [];
740
741 if ( 'admin.php' === $pagenow && isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We don't need nonce verification here.
742 $page_title = get_admin_page_title();
743 $breadcrumbs[] = [
744 'title' => $page_title,
745 'link' => '',
746 ];
747 } elseif ( $post && in_array( $pagenow, [ 'post.php', 'post-new.php', 'edit.php' ], true ) ) {
748 $post_type_obj = get_post_type_object( get_post_type() );
749 if ( $post_type_obj ) {
750 $post_type_plural = $post_type_obj->labels->name;
751 $breadcrumbs[] = [
752 'title' => $post_type_plural,
753 'link' => admin_url( 'edit.php?post_type=' . $post_type_obj->name ),
754 ];
755
756 if ( 'edit.php' === $pagenow && ! isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We don't need nonce verification here.
757 $breadcrumbs[ count( $breadcrumbs ) - 1 ]['link'] = '';
758 } else {
759 $breadcrumbs[] = [
760 /* Translators: Post Title. */
761 'title' => sprintf( __( 'Edit %1$s', 'sureforms' ), get_the_title() ),
762 'link' => get_edit_post_link( $post->ID ),
763 ];
764 }
765 }
766 } else {
767 $current_screen = get_current_screen();
768 if ( $current_screen && 'sureforms_form' === $current_screen->post_type ) {
769 $breadcrumbs[] = [
770 'title' => 'Forms',
771 'link' => '',
772 ];
773 } else {
774 $breadcrumbs[] = [
775 'title' => '',
776 'link' => '',
777 ];
778 }
779 }
780
781 return $breadcrumbs;
782 }
783
784 /**
785 * Enqueue Admin Scripts.
786 *
787 * @return void
788 * @since 0.0.1
789 */
790 public function enqueue_scripts() {
791 $current_screen = get_current_screen();
792 global $wp_version;
793
794 $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
795 $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
796 $css_uri = SRFM_URL . 'assets/css/' . $dir_name . '/';
797 $is_rtl = is_rtl();
798 $rtl = $is_rtl ? '-rtl' : '';
799
800 /**
801 * List of the handles in which we need to add translation compatibility.
802 */
803 $script_translations_handlers = [];
804 $onboarding_instance = Onboarding::get_instance();
805
806 $localization_data = [
807 'site_url' => get_site_url(),
808 'breadcrumbs' => $this->get_breadcrumbs_for_current_page(),
809 'sureforms_dashboard_url' => admin_url( '/admin.php?page=sureforms_menu' ),
810 'plugin_version' => SRFM_VER,
811 'global_settings_nonce' => Helper::current_user_can() ? wp_create_nonce( 'wp_rest' ) : '',
812 'is_pro_active' => Helper::has_pro(),
813 'is_first_form_created' => self::is_first_form_created(),
814 'check_three_days_threshold' => self::check_first_form_creation_threshold(),
815 'check_eight_days_threshold' => self::check_first_form_creation_threshold( 8 ),
816 'pro_plugin_version' => Helper::has_pro() ? SRFM_PRO_VER : '',
817 'pro_plugin_name' => Helper::has_pro() && defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro',
818 'sureforms_pricing_page' => Helper::get_sureforms_website_url( 'pricing' ),
819 'field_spacing_vars' => Helper::get_css_vars(),
820 'is_ver_lower_than_6_7' => version_compare( $wp_version, '6.6.2', '<=' ),
821 'integrations' => Helper::sureforms_get_integration(),
822 'rotating_plugin_banner' => Helper::get_rotating_plugin_banner(),
823 'ajax_url' => admin_url( 'admin-ajax.php' ),
824 'sf_plugin_manager_nonce' => wp_create_nonce( 'sf_plugin_manager_nonce' ),
825 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
826 'plugin_activating_text' => __( 'Activating...', 'sureforms' ),
827 'plugin_activated_text' => __( 'Activated', 'sureforms' ),
828 'plugin_activate_text' => __( 'Activate', 'sureforms' ),
829 'plugin_installing_text' => __( 'Installing...', 'sureforms' ),
830 'plugin_installed_text' => __( 'Installed', 'sureforms' ),
831 'is_rtl' => $is_rtl,
832 'onboarding_completed' => method_exists( $onboarding_instance, 'get_onboarding_status' ) ? $onboarding_instance->get_onboarding_status() : false,
833 'onboarding_redirect' => isset( $_GET['srfm-activation-redirect'] ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce is not required for the activation redirection.
834 'pointer_nonce' => wp_create_nonce( 'sureforms_pointer_action' ),
835 'general_settings_url' => admin_url( '/options-general.php' ),
836 'payments' => apply_filters(
837 'srfm_admin_localize_payments_data',
838 [
839 'stripe_connected' => Stripe_Helper::is_stripe_connected(),
840 'stripe_mode' => Stripe_Helper::get_stripe_mode(),
841 'stripe_connect_url' => Stripe_Helper::get_stripe_settings_url(),
842 'currencies_data' => Payment_Helper::get_all_currencies_data(),
843 'zero_decimal_currencies' => Payment_Helper::get_zero_decimal_currencies(),
844 'webhook_url' => Stripe_Helper::get_webhook_url(),
845 'webhook_test_connected' => Stripe_Helper::is_webhook_configured( 'test', true ),
846 'webhook_live_connected' => Stripe_Helper::is_webhook_configured( 'live', true ),
847 'is_transaction_present' => Stripe_Helper::is_transaction_present(),
848 'payment_currency' => Payment_Helper::get_currency(),
849 ]
850 ),
851 ];
852
853 $is_screen_sureforms_menu = Helper::validate_request_context( 'sureforms_menu', 'page' );
854 $is_screen_add_new_form = Helper::validate_request_context( 'add-new-form', 'page' );
855 $is_screen_sureforms_forms = Helper::validate_request_context( 'sureforms_forms', 'page' );
856 $is_screen_sureforms_form_settings = Helper::validate_request_context( 'sureforms_form_settings', 'page' );
857 $is_screen_sureforms_payments = Helper::validate_request_context( 'sureforms_payments', 'page' );
858 $is_screen_sureforms_entries = Helper::validate_request_context( SRFM_ENTRIES, 'page' );
859 $is_post_type_sureforms_form = SRFM_FORMS_POST_TYPE === $current_screen->post_type;
860
861 /**
862 * Check if the current screen is the SureForms Menu and AI Auth Email is present then we will add user type as registered.
863 * Compatibility with existing UI code that checks for this condition.
864 */
865 if ( $is_screen_sureforms_menu ) {
866 // If email is stored send the user type as registered else non-registered.
867 $localization_data['srfm_ai_details'] = [
868 'type' => ! empty( get_option( 'srfm_ai_auth_user_email' ) ) ? 'registered' : 'non-registered',
869 ];
870 }
871
872 if ( $is_screen_sureforms_menu || $is_post_type_sureforms_form || $is_screen_add_new_form || $is_screen_sureforms_forms || $is_screen_sureforms_form_settings || $is_screen_sureforms_entries || $is_screen_sureforms_payments ) {
873 $asset_handle = '-dashboard';
874
875 wp_enqueue_style( SRFM_SLUG . $asset_handle . '-font', 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap', [], SRFM_VER );
876
877 $script_asset_path = SRFM_DIR . 'assets/build/dashboard.asset.php';
878 $script_info = file_exists( $script_asset_path )
879 ? include $script_asset_path
880 : [
881 'dependencies' => [],
882 'version' => SRFM_VER,
883 ];
884 wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/dashboard.js', $script_info['dependencies'], SRFM_VER, true );
885
886 wp_localize_script( SRFM_SLUG . $asset_handle, 'scIcons', [ 'path' => SRFM_URL . 'assets/build/icon-assets' ] );
887
888 $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
889
890 if ( class_exists( 'SRFM_PRO\Admin\Licensing' ) ) {
891 $license_active = \SRFM_PRO\Admin\Licensing::is_license_active();
892 $localization_data['is_license_active'] = $license_active;
893
894 // Updating current licensing status.
895 $srfm_pro_license_status = get_option( 'srfm_pro_license_status', '' );
896 $current_license_status = $license_active ? 'licensed' : 'unlicensed';
897 if ( $current_license_status !== $srfm_pro_license_status ) {
898 update_option( 'srfm_pro_license_status', $current_license_status );
899 }
900 }
901
902 $localization_data['security_settings_url'] = admin_url( '/admin.php?page=sureforms_form_settings&tab=security-settings&subpage=recaptcha' );
903 $localization_data['integration_settings_url'] = admin_url( '/admin.php?page=sureforms_form_settings&tab=integration-settings' );
904 wp_localize_script(
905 SRFM_SLUG . $asset_handle,
906 SRFM_SLUG . '_admin',
907 apply_filters(
908 SRFM_SLUG . '_admin_filter',
909 $localization_data
910 )
911 );
912 wp_enqueue_style( SRFM_SLUG . '-dashboard', SRFM_URL . 'assets/build/dashboard.css', [], SRFM_VER, 'all' );
913 }
914
915 if ( $is_screen_sureforms_form_settings || $is_screen_sureforms_forms ) {
916 wp_enqueue_style( SRFM_SLUG . '-settings', $css_uri . 'backend/settings' . $file_prefix . $rtl . '.css', [], SRFM_VER );
917 }
918
919 // Enqueue styles for the entries page.
920 if ( $is_screen_sureforms_entries ) {
921 $asset_handle = '-entries';
922 wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/entries.js', $script_info['dependencies'], SRFM_VER, true );
923
924 wp_localize_script(
925 SRFM_SLUG . $asset_handle,
926 SRFM_SLUG . '_admin',
927 apply_filters(
928 SRFM_SLUG . '_admin_filter',
929 $localization_data
930 )
931 );
932 $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
933 }
934
935 // Enqueue scripts for the forms page.
936 if ( $is_screen_sureforms_forms ) {
937 $asset_handle = '-forms';
938
939 $script_asset_path = SRFM_DIR . 'assets/build/forms.asset.php';
940 $script_info = file_exists( $script_asset_path )
941 ? include $script_asset_path
942 : [
943 'dependencies' => [],
944 'version' => SRFM_VER,
945 ];
946
947 wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/forms.js', $script_info['dependencies'], SRFM_VER, true );
948 wp_localize_script(
949 SRFM_SLUG . $asset_handle,
950 SRFM_SLUG . '_admin',
951 apply_filters(
952 SRFM_SLUG . '_admin_filter',
953 $localization_data
954 )
955 );
956 wp_enqueue_style( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/forms.css', [], SRFM_VER, 'all' );
957
958 $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
959 }
960
961 // Enqueue scripts for the SureMail promotional page.
962 $is_screen_sureforms_smtp = Helper::validate_request_context( 'sureforms_smtp', 'page' );
963 if ( $is_screen_sureforms_smtp ) {
964 $asset_handle = 'suremail';
965
966 $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
967 $script_info = file_exists( $script_asset_path )
968 ? include $script_asset_path
969 : [
970 'dependencies' => [],
971 'version' => SRFM_VER,
972 ];
973
974 wp_enqueue_script( SRFM_SLUG . '-suremail', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
975 wp_enqueue_style( SRFM_SLUG . '-suremail', SRFM_URL . 'assets/build/suremail.css', [], SRFM_VER, 'all' );
976
977 // Localize script for SureMail page.
978 $suremail_localization_data = [
979 'ajax_url' => admin_url( 'admin-ajax.php' ),
980 'admin_url' => admin_url(),
981 'suremail_url' => 'https://sureforms.com/suremail/',
982 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
983 'sfPluginManagerNonce' => wp_create_nonce( 'sf_plugin_manager_nonce' ),
984 'suremail_status' => file_exists( WP_PLUGIN_DIR . '/suremails/suremails.php' )
985 ? ( is_plugin_active( 'suremails/suremails.php' ) ? 'active' : 'installed' )
986 : 'not_installed',
987 ];
988
989 wp_localize_script(
990 SRFM_SLUG . '-suremail',
991 SRFM_SLUG . '_admin',
992 apply_filters(
993 SRFM_SLUG . '_suremail_admin_filter',
994 $suremail_localization_data
995 )
996 );
997
998 $script_translations_handlers[] = SRFM_SLUG . '-suremail';
999 }
1000
1001 // Admin Submenu Styles.
1002 wp_enqueue_style( SRFM_SLUG . '-admin', $css_uri . 'backend/admin' . $file_prefix . $rtl . '.css', [], SRFM_VER );
1003
1004 if ( $is_screen_sureforms_form_settings ) {
1005 $asset_handle = 'settings';
1006
1007 $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1008 $script_info = file_exists( $script_asset_path )
1009 ? include $script_asset_path
1010 : [
1011 'dependencies' => [],
1012 'version' => SRFM_VER,
1013 ];
1014
1015 wp_enqueue_script( SRFM_SLUG . '-settings', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1016 wp_localize_script(
1017 SRFM_SLUG . '-settings',
1018 SRFM_SLUG . '_admin',
1019 $localization_data
1020 );
1021
1022 $script_translations_handlers[] = SRFM_SLUG . '-settings';
1023 }
1024
1025 if ( $is_screen_add_new_form ) {
1026 wp_enqueue_style( SRFM_SLUG . '-template-picker', $css_uri . 'template-picker' . $file_prefix . $rtl . '.css', [], SRFM_VER );
1027
1028 $sureforms_admin = 'templatePicker';
1029
1030 $script_asset_path = SRFM_DIR . 'assets/build/' . $sureforms_admin . '.asset.php';
1031 $script_info = file_exists( $script_asset_path )
1032 ? include $script_asset_path
1033 : [
1034 'dependencies' => [],
1035 'version' => SRFM_VER,
1036 ];
1037 wp_enqueue_script( SRFM_SLUG . '-template-picker', SRFM_URL . 'assets/build/' . $sureforms_admin . '.js', $script_info['dependencies'], SRFM_VER, true );
1038
1039 wp_localize_script(
1040 SRFM_SLUG . '-template-picker',
1041 SRFM_SLUG . '_admin',
1042 [
1043 'site_url' => get_site_url(),
1044 'plugin_url' => SRFM_URL,
1045 'admin_url' => admin_url( 'admin.php' ),
1046 'new_template_picker_base_url' => admin_url( 'post-new.php?post_type=sureforms_form' ),
1047 'capability' => Helper::current_user_can(),
1048 'template_picker_nonce' => Helper::current_user_can() ? wp_create_nonce( 'wp_rest' ) : '',
1049 'is_pro_active' => Helper::has_pro(),
1050 'srfm_ai_usage_details' => AI_Helper::get_current_usage_details(),
1051 'is_pro_license_active' => AI_Helper::is_pro_license_active(),
1052 'srfm_ai_auth_user_email' => get_option( 'srfm_ai_auth_user_email' ),
1053 'pricing_page_url' => Helper::get_sureforms_website_url( 'pricing' ),
1054 'licensing_nonce' => wp_create_nonce( 'srfm_pro_licensing_nonce' ),
1055 ]
1056 );
1057
1058 $script_translations_handlers[] = SRFM_SLUG . '-template-picker';
1059 }
1060 // Quick action sidebar.
1061 $default_allowed_quick_sidebar_blocks = apply_filters(
1062 'srfm_quick_sidebar_allowed_blocks',
1063 [
1064 'srfm/input',
1065 'srfm/email',
1066 'srfm/textarea',
1067 'srfm/checkbox',
1068 'srfm/number',
1069 'srfm/inline-button',
1070 'srfm/advanced-heading',
1071 'srfm/payment',
1072 ]
1073 );
1074 if ( ! is_array( $default_allowed_quick_sidebar_blocks ) ) {
1075 $default_allowed_quick_sidebar_blocks = [];
1076 }
1077
1078 $srfm_enable_quick_action_sidebar = get_option( 'srfm_enable_quick_action_sidebar' );
1079 if ( ! $srfm_enable_quick_action_sidebar ) {
1080 $srfm_enable_quick_action_sidebar = 'disabled';
1081 }
1082 $quick_sidebar_allowed_blocks = get_option( 'srfm_quick_sidebar_allowed_blocks' );
1083 $quick_sidebar_allowed_blocks = ! empty( $quick_sidebar_allowed_blocks ) && is_array( $quick_sidebar_allowed_blocks ) ? $quick_sidebar_allowed_blocks : $default_allowed_quick_sidebar_blocks;
1084 $srfm_ajax_nonce = wp_create_nonce( 'srfm_ajax_nonce' );
1085
1086 if ( Helper::is_sureforms_admin_page() ) {
1087 wp_enqueue_script( SRFM_SLUG . '-quick-action-siderbar', SRFM_URL . 'assets/build/quickActionSidebar.js', [], SRFM_VER, true );
1088 wp_localize_script(
1089 SRFM_SLUG . '-quick-action-siderbar',
1090 SRFM_SLUG . '_quick_sidebar_blocks',
1091 [
1092 'allowed_blocks' => $quick_sidebar_allowed_blocks,
1093 'srfm_enable_quick_action_sidebar' => $srfm_enable_quick_action_sidebar,
1094 'srfm_ajax_nonce' => $srfm_ajax_nonce,
1095 'srfm_ajax_url' => admin_url( 'admin-ajax.php' ),
1096 ]
1097 );
1098
1099 $script_translations_handlers[] = SRFM_SLUG . '-quick-action-siderbar';
1100 }
1101
1102 /**
1103 * Enqueuing SureTriggers Integration script.
1104 * This script loads suretriggers iframe in Intergations tab.
1105 */
1106 if ( $is_post_type_sureforms_form ) {
1107 wp_enqueue_script( SRFM_SLUG . '-suretriggers-integration', SRFM_SURETRIGGERS_INTEGRATION_BASE_URL . 'js/v2/embed.js', [], SRFM_VER, true );
1108 }
1109
1110 // Check $script_translations_handlers is not empty before calling the function.
1111 if ( ! empty( $script_translations_handlers ) ) {
1112 // Remove duplicates values from the array.
1113 $script_translations_handlers = array_unique( $script_translations_handlers );
1114
1115 foreach ( $script_translations_handlers as $script_handle ) {
1116 Helper::register_script_translations( $script_handle );
1117 }
1118 }
1119 }
1120
1121 /**
1122 * Form Template Picker Admin Body Classes
1123 * WordPress sometimes translates class names in the admin body tag, which can result in
1124 * incorrect or missing class names when rendering the admin pages. This function ensures
1125 * that essential class names are manually added to the body tag to maintain proper functionality.
1126 *
1127 * @since 0.0.1
1128 * @param string $classes Space separated class string.
1129 */
1130 public function admin_template_picker_body_class( $classes = '' ) {
1131 // Define an associative array of class names and their corresponding conditions.
1132 // Each condition checks whether a specific request context matches.
1133 $srfm_classes = [
1134 'sureforms_page_sureforms_entries' => Helper::validate_request_context( SRFM_ENTRIES, 'page' ),
1135 'sureforms_page_sureforms_form_settings' => Helper::validate_request_context( 'sureforms_form_settings', 'page' ),
1136 'srfm-template-picker' => Helper::validate_request_context( 'add-new-form', 'page' ),
1137 ];
1138
1139 $add_srfm_classes = '';
1140
1141 // Loop through the defined classes and conditions.
1142 foreach ( $srfm_classes as $class => $condition ) {
1143 // Check if the condition evaluates to true.
1144 if ( $condition ) {
1145 // Append the class to the existing classes string, followed by a space.
1146 $add_srfm_classes .= empty( $add_srfm_classes ) ? $class : ' ' . $class;
1147 }
1148 }
1149
1150 // Append the new classes to the existing classes string.
1151 if ( ! empty( $add_srfm_classes ) ) {
1152 $classes .= ' ' . $add_srfm_classes;
1153 }
1154
1155 // Return the updated list of classes.
1156 return $classes;
1157 }
1158
1159 /**
1160 * Disable spectra's quick action bar in sureforms CPT.
1161 *
1162 * @param string $status current status of the quick action bar.
1163 * @since 0.0.2
1164 * @return string
1165 */
1166 public function restrict_spectra_quick_action_bar( $status ) {
1167 $screen = get_current_screen();
1168 if ( 'disabled' !== $status && isset( $screen->id ) && 'sureforms_form' === $screen->id ) {
1169 $status = 'disabled';
1170 }
1171
1172 return $status;
1173 }
1174
1175 /**
1176 * Register Pro compatibility notices early for React pages.
1177 *
1178 * This method runs on admin_init (priority 5) to ensure notices are
1179 * registered BEFORE admin_enqueue_scripts, so they're available when
1180 * wp_localize_script runs.
1181 *
1182 * Hooked - admin_init (priority 5)
1183 *
1184 * @return void
1185 * @since 2.5.0
1186 */
1187 public function register_pro_compatibility_notices() {
1188 // Early exit if Pro is not active, user lacks permissions, or Notice_Manager is unavailable.
1189 if ( ! Helper::has_pro() || ! Helper::current_user_can() || ! class_exists( 'SRFM\Admin\Notice_Manager' ) ) {
1190 return;
1191 }
1192
1193 // Register version outdated notice for React pages.
1194 if ( ! version_compare( SRFM_PRO_VER, SRFM_PRO_RECOMMENDED_VER, '>=' ) ) {
1195 $pro_plugin_name = defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro';
1196 $react_outdated_message = sprintf(
1197 // translators: %1$s: SureForms version, %2$s: SureForms Pro Plugin Name, %3$s: SureForms Pro Version.
1198 esc_html__( 'SureForms %1$s requires minimum %2$s %3$s to work properly. Please update to the latest version.', 'sureforms' ),
1199 esc_html( SRFM_VER ),
1200 esc_html( $pro_plugin_name ),
1201 esc_html( SRFM_PRO_RECOMMENDED_VER )
1202 );
1203
1204 \SRFM\Admin\Notice_Manager::register_notice(
1205 [
1206 'id' => 'sureforms-pro-version-outdated',
1207 'variant' => 'warning',
1208 'message' => $react_outdated_message,
1209 'actions' => [
1210 [
1211 'label' => esc_html__( 'Update Now', 'sureforms' ),
1212 'url' => admin_url( 'update-core.php' ),
1213 'variant' => 'primary',
1214 ],
1215 ],
1216 'pages' => [ 'all' ],
1217 ]
1218 );
1219 }
1220 }
1221
1222 /**
1223 * Admin Notice Callback if sureforms pro is out of date.
1224 *
1225 * Hooked - admin_notices
1226 *
1227 * @return void
1228 * @since 1.0.4
1229 */
1230 public function srfm_pro_version_compatibility() {
1231 if ( ! Helper::has_pro() ) {
1232 return;
1233 }
1234
1235 if ( empty( get_current_screen() ) ) {
1236 return;
1237 }
1238
1239 if ( ! Helper::current_user_can() ) {
1240 return;
1241 }
1242
1243 $srfm_pro_license_status = get_option( 'srfm_pro_license_status', '' );
1244 /**
1245 * If the license status is not set then get the license status and update the option accordingly.
1246 * This will be executed only once. Subsequently, the option status is updated by the licensing class on license activation or deactivation.
1247 */
1248 if ( empty( $srfm_pro_license_status ) && class_exists( 'SRFM_PRO\Admin\Licensing' ) ) {
1249 $srfm_pro_license_status = \SRFM_PRO\Admin\Licensing::is_license_active() ? 'licensed' : 'unlicensed';
1250 update_option( 'srfm_pro_license_status', $srfm_pro_license_status );
1251 }
1252
1253 $pro_plugin_name = defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro';
1254 $message = '';
1255 $url = admin_url( 'admin.php?page=sureforms_form_settings&tab=account-settings' );
1256 if ( 'unlicensed' === $srfm_pro_license_status ) {
1257 ob_start();
1258 ?>
1259 <p>
1260 <?php
1261 printf(
1262 // translators: %1$s: Opening anchor tag with URL, %2$s: Closing anchor tag, %3$s: SureForms Pro Plugin Name.
1263 esc_html__( 'Please %1$sactivate%2$s your copy of %3$s to get new features, access support, receive update notifications, and more.', 'sureforms' ),
1264 '<a href="' . esc_url( $url ) . '">',
1265 '</a>',
1266 '<i>' . esc_html( $pro_plugin_name ) . '</i>'
1267 );
1268 ?>
1269 </p>
1270 <?php
1271 $message = ob_get_clean();
1272 }
1273
1274 if ( ! version_compare( SRFM_PRO_VER, SRFM_PRO_RECOMMENDED_VER, '>=' ) ) {
1275 ob_start();
1276 ?>
1277 <p>
1278 <?php
1279 printf(
1280 // translators: %1$s: SureForms version, %2$s: SureForms Pro Plugin Name, %3$s: SureForms Pro Version, %4$s: Anchor tag open, %5$s: Closing anchor tag.
1281 esc_html__( 'SureForms %1$s requires minimum %2$s %3$s to work properly. Please update to the latest version from %4$shere%5$s.', 'sureforms' ),
1282 esc_html( SRFM_VER ),
1283 esc_html( $pro_plugin_name ),
1284 esc_html( SRFM_PRO_RECOMMENDED_VER ),
1285 '<a href="' . esc_url( admin_url( 'update-core.php' ) ) . '">',
1286 '</a>'
1287 );
1288 ?>
1289 </p>
1290 <?php
1291 $message .= ob_get_clean();
1292 }
1293
1294 if ( ! empty( $message ) ) {
1295 // Phpcs ignore comment is required as $message variable is already escaped.
1296 ?>
1297 <div class="notice notice-warning"><?php echo wp_kses_post( $message ); ?></div>
1298 <?php
1299 }
1300 }
1301
1302 /**
1303 * Disables the capabilities for WPForms to avoid conflicts when enqueueing
1304 * scripts and styles for WPForms.
1305 *
1306 * This function is intended to prevent any potential conflicts that may arise
1307 * when WPForms scripts and styles are enqueued. By disabling certain capabilities,
1308 * it ensures that WPForms does not interfere with other functionalities.
1309 *
1310 * @param bool $user_can A boolean indicating whether the user has the capability.
1311 * @return bool Returns true if the capabilities are successfully disabled, false otherwise.
1312 * @since 1.4.2
1313 */
1314 public function disable_wpforms_capabilities( $user_can ) {
1315 // Note: Nonce verification is intentionally omitted here as no database operations are performed.
1316 // The values of the $_REQUEST variables are strictly validated, ensuring security without the need for nonce verification.
1317
1318 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1319 $post_id = ! empty( $_REQUEST['post'] ) && ! empty( $_REQUEST['action'] ) ? absint( $_REQUEST['post'] ) : 0;
1320
1321 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1322 $post_type = $post_id ? get_post_type( $post_id ) : sanitize_text_field( wp_unslash( $_REQUEST['post_type'] ?? '' ) );
1323 return SRFM_FORMS_POST_TYPE === $post_type ? false : $user_can;
1324 }
1325
1326 /**
1327 * Enqueueus the admin pointer script and styles.
1328 *
1329 * @return void
1330 * @since 1.8.0
1331 */
1332 public function enqueue_admin_pointer() {
1333 if ( ! $this->is_admin_pointer_visible() ) {
1334 return;
1335 }
1336 wp_enqueue_style( 'wp-pointer' );
1337 wp_enqueue_script( 'wp-pointer' );
1338 wp_enqueue_script(
1339 'sureforms-admin-pointer',
1340 plugins_url( 'admin/assets/js/sureforms-pointer.js', SRFM_FILE ),
1341 [ 'wp-pointer', 'jquery' ],
1342 SRFM_VER,
1343 true
1344 );
1345 wp_localize_script(
1346 'sureforms-admin-pointer',
1347 'sureformsPointerData',
1348 [
1349 'ajaxurl' => admin_url( 'admin-ajax.php' ),
1350 'pointer_nonce' => wp_create_nonce( 'sureforms_pointer_action' ),
1351 ]
1352 );
1353 }
1354
1355 /**
1356 * Ajax handler for pointer popup visibility.
1357 *
1358 * @return void
1359 * @since 1.8.0
1360 */
1361 public function pointer_should_show() {
1362 // Security: Check user capability.
1363 if ( ! Helper::current_user_can() ) {
1364 wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1365 }
1366 // Security: Nonce check.
1367 if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1368 wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1369 }
1370
1371 $content_markup = sprintf(
1372 /* translators: 1: opening span, 2: opening strong (inline), 3: closing strong, 4: closing span, 5: opening strong (block), 6: closing strong */
1373 __( '%1$sGet started by %2$sbuilding your first form%3$s.%4$s%5$sExperience the power of our intuitive AI Form Builder%6$s', 'sureforms' ),
1374 '<span>',
1375 '<strong>',
1376 '</strong>',
1377 '</span><br/>',
1378 '<strong style="font-size:1.1em;">',
1379 '</strong>'
1380 );
1381 wp_send_json(
1382 [
1383 'show' => true,
1384 'title' => esc_html( __( 'SureForms is waiting for you!', 'sureforms' ) ),
1385 'content' => wp_kses_post( $content_markup ),
1386 'button_text' => esc_html( __( 'Build My First Form', 'sureforms' ) ),
1387 'dismiss' => esc_html( __( 'Dismiss', 'sureforms' ) ),
1388 'button_url' => admin_url( 'admin.php?page=add-new-form' ),
1389 ]
1390 );
1391 }
1392
1393 /**
1394 * Ajax callback for pointer popup dismissed action.
1395 *
1396 * @return void
1397 * @since 1.8.0
1398 */
1399 public function pointer_dismissed() {
1400 // Security: Check user capability.
1401 if ( ! Helper::current_user_can() ) {
1402 wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1403 }
1404 // Security: Nonce check.
1405 if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1406 wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1407 }
1408 // Use Helper to update srfm_options key.
1409 Helper::update_srfm_option( 'pointer_popup_dismissed', time() );
1410
1411 wp_send_json_success();
1412 }
1413
1414 /**
1415 * Ajax pointer accepted CTA callback.
1416 *
1417 * @return void
1418 * @since 1.8.0
1419 */
1420 public function pointer_accepted_cta() {
1421 // Security: Check user capability.
1422 if ( ! Helper::current_user_can() ) {
1423 wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1424 }
1425 // Security: Nonce check.
1426 if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1427 wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1428 }
1429 // Use Helper to update srfm_options key.
1430 Helper::update_srfm_option( 'pointer_popup_accepted', time() );
1431
1432 wp_send_json_success();
1433 }
1434
1435 /**
1436 * Maybe register the dashboard widget based on entries.
1437 *
1438 * @return void
1439 * @since 1.9.1
1440 */
1441 public function maybe_register_dashboard_widget() {
1442
1443 // Only for users with manage_options capability.
1444 if ( ! Helper::current_user_can() ) {
1445 return;
1446 }
1447
1448 // Quick check if there are any entries in the last 7 days.
1449 $seven_days_ago = strtotime( '-7 days' );
1450 $total_entries = Entries::get_entries_count_after( $seven_days_ago );
1451
1452 // Only add the dashboard setup hook if there are entries.
1453 if ( $total_entries > 0 ) {
1454 // Get forms with entries (limit 4 for dashboard widget).
1455 $this->dashboard_widget_data = Helper::get_forms_with_entry_counts( $seven_days_ago, 4 );
1456
1457 // Only show dashboard widget if there are forms with entries.
1458 if ( ! empty( $this->dashboard_widget_data ) ) {
1459 add_action( 'wp_dashboard_setup', [ $this, 'register_dashboard_widget' ] );
1460 }
1461 }
1462 }
1463
1464 /**
1465 * Register the dashboard widget.
1466 *
1467 * @return void
1468 * @since 1.9.1
1469 */
1470 public function register_dashboard_widget() {
1471 // Add the widget with high priority to position it at the top.
1472 wp_add_dashboard_widget(
1473 'sureforms_recent_entries',
1474 __( 'SureForms', 'sureforms' ),
1475 [ $this, 'render_dashboard_widget' ],
1476 null,
1477 null,
1478 'normal',
1479 'high'
1480 );
1481 }
1482
1483 /**
1484 * Render the dashboard widget content.
1485 *
1486 * @return void
1487 * @since 1.9.1
1488 */
1489 public function render_dashboard_widget() {
1490 // Use the pre-fetched data to avoid duplicate queries.
1491 $entries_data = $this->dashboard_widget_data;
1492
1493 // Display the widget content.
1494 ?>
1495 <div class="srfm-dashboard-widget">
1496 <div class="srfm-widget-header">
1497 <h3 class="srfm-widget-title">
1498 <?php esc_html_e( 'Recent Entries', 'sureforms' ); ?>
1499 <span class="srfm-widget-subtitle"><?php esc_html_e( '( Last 7 days )', 'sureforms' ); ?></span>
1500 </h3>
1501 <a href="<?php echo esc_url( admin_url( 'admin.php?page=sureforms_entries' ) ); ?>" class="srfm-widget-view-link">
1502 <?php esc_html_e( 'View', 'sureforms' ); ?>
1503 </a>
1504 </div>
1505
1506 <div class="srfm-table-wrapper">
1507 <table class="srfm-entries-table">
1508 <thead>
1509 <tr>
1510 <th><?php esc_html_e( 'Form Name', 'sureforms' ); ?></th>
1511 <th><?php esc_html_e( 'Entries', 'sureforms' ); ?></th>
1512 </tr>
1513 </thead>
1514 <tbody>
1515 <?php foreach ( $entries_data as $form_data ) { ?>
1516 <tr>
1517 <td class="form-name"><?php echo esc_html( $form_data['title'] ); ?></td>
1518 <td class="entry-count"><?php echo esc_html( $form_data['count'] ); ?></td>
1519 </tr>
1520 <?php } ?>
1521 </tbody>
1522 </table>
1523 </div>
1524
1525 <?php
1526 // Render footer if applicable.
1527 $this->render_dashboard_widget_footer( $entries_data );
1528 ?>
1529 </div>
1530 <?php
1531 }
1532
1533 /**
1534 * Get random premium feature text.
1535 *
1536 * @return string Random feature text.
1537 * @since 1.9.1
1538 */
1539 private function get_random_premium_feature_text() {
1540 $features = [
1541 __( 'Use Conditional Logic to show only what matters', 'sureforms' ),
1542 __( 'Split your form into steps to keep it easy', 'sureforms' ),
1543 __( 'Let people upload files directly to your form', 'sureforms' ),
1544 __( 'Turn responses into downloadable PDFs automatically', 'sureforms' ),
1545 __( 'Let users sign with a simple signature field', 'sureforms' ),
1546 __( 'Connect your form to other tools using webhooks', 'sureforms' ),
1547 __( 'Use Conversational Forms for a chat-like experience', 'sureforms' ),
1548 __( 'Let users register or log in through your form', 'sureforms' ),
1549 __( 'Build forms that create WordPress user accounts', 'sureforms' ),
1550 __( 'Add calculations to auto-total scores or prices', 'sureforms' ),
1551 ];
1552
1553 // Get a random feature.
1554 $random_key = array_rand( $features );
1555 return $features[ $random_key ];
1556 }
1557
1558 /**
1559 * Render the dashboard widget footer for upsell.
1560 *
1561 * @param array $entries_data The entries data array.
1562 * @return void
1563 * @since 1.9.1
1564 */
1565 private function render_dashboard_widget_footer( $entries_data ) {
1566 // Only show footer if Pro is not active.
1567 if ( Helper::has_pro() ) {
1568 return;
1569 }
1570
1571 // Count total entries in last 7 days.
1572 $total_entries = 0;
1573 foreach ( $entries_data as $form_data ) {
1574 $total_entries += $form_data['count'];
1575 }
1576
1577 // Count total published forms.
1578 $published_forms_count = wp_count_posts( SRFM_FORMS_POST_TYPE )->publish;
1579
1580 // Show footer only if 3+ entries received OR 3+ forms published.
1581 if ( $total_entries >= 3 || $published_forms_count >= 3 ) {
1582 ?>
1583 <div class="srfm-widget-footer">
1584 <div class="srfm-upgrade-content">
1585 <svg class="srfm-logo-icon" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
1586 <rect width="20" height="20" fill="#D54407"/>
1587 <path d="M5.7139 4.2854H14.2853V7.1425H7.1424L5.7139 8.5711V7.1425V4.2854Z" fill="white"/>
1588 <path d="M5.7139 4.2854H14.2853V7.1425H7.1424L5.7139 8.5711V7.1425V4.2854Z" fill="white"/>
1589 <path d="M5.7148 8.5713H12.8577V11.4284H7.1434L5.7148 12.857V11.4284V8.5713Z" fill="white"/>
1590 <path d="M5.7148 8.5713H12.8577V11.4284H7.1434L5.7148 12.857V11.4284V8.5713Z" fill="white"/>
1591 <path d="M5.7148 12.8569H10.0006V15.7141H5.7148V12.8569Z" fill="white"/>
1592 <path d="M5.7148 12.8569H10.0006V15.7141H5.7148V12.8569Z" fill="white"/>
1593 </svg>
1594 <span><?php echo esc_html( $this->get_random_premium_feature_text() ); ?></span>
1595 </div>
1596 <?php
1597 $upgrade_url = add_query_arg(
1598 [
1599 'utm_medium' => 'dashboard-widget',
1600 ],
1601 Helper::get_sureforms_website_url( 'pricing' )
1602 );
1603 ?>
1604 <a href="<?php echo esc_url( $upgrade_url ); ?>" class="srfm-upgrade-link" target="_blank">
1605 <?php esc_html_e( 'Upgrade', 'sureforms' ); ?>
1606 </a>
1607 </div>
1608 <?php
1609 }
1610 }
1611
1612 /**
1613 * Determine if the admin pointer should be visible on this page.
1614 *
1615 * @since 1.8.0
1616 * @return bool
1617 */
1618 private function is_admin_pointer_visible() {
1619 global $pagenow;
1620 $allowed_pages = [ 'index.php', 'options-general.php' ];
1621
1622 // Do not show if pointer dismissed, accepted, or more than 1 form exists.
1623 if (
1624 ! empty( Helper::get_srfm_option( 'pointer_popup_dismissed' ) )
1625 || ! empty( Helper::get_srfm_option( 'pointer_popup_accepted' ) )
1626 || (int) ( wp_count_posts( SRFM_FORMS_POST_TYPE )->publish ?? 0 ) > 1
1627 ) {
1628 return false;
1629 }
1630
1631 if ( in_array( $pagenow, $allowed_pages, true ) ) {
1632 return true;
1633 }
1634
1635 return false;
1636 }
1637
1638 }
1639