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

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

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