PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 1.4.2
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v1.4.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
← All changes | admin/admin.php +198 -1443 2.9.01.4.2 View file →
@@ -6,26 +6,19 @@
6 6 */
7 7
8 8 namespace SRFM\Admin;
9 9
10 -use Astra_Notices;
10 +use SRFM\Admin\Views\Entries_List_Table;
11 +use SRFM\Admin\Views\Single_Entry;
11 12 use SRFM\Inc\AI_Form_Builder\AI_Helper;
12 13 use SRFM\Inc\Database\Tables\Entries;
13 -use SRFM\Inc\Global_Settings\Global_Settings;
14 14 use SRFM\Inc\Helper;
15 -use SRFM\Inc\Onboarding;
16 -use SRFM\Inc\Payments\Payment_Helper;
17 -use SRFM\Inc\Payments\Stripe\Stripe_Helper;
18 -use SRFM\Inc\Smart_Tags;
15 +use SRFM\Inc\Post_Types;
19 16 use SRFM\Inc\Traits\Get_Instance;
20 17
21 18 if ( ! defined( 'ABSPATH' ) ) {
22 19 exit; // Exit if accessed directly.
23 20 }
24 -
25 -if ( ! class_exists( 'BSF_Admin_Notices' ) ) {
26 - require_once SRFM_DIR . 'inc/lib/astra-notices/class-bsf-admin-notices.php';
27 -}
28 21 /**
29 22 * Admin handler class.
30 23 *
31 24 * @since 0.0.1
@@ -33,39 +26,8 @@
33 26 class Admin {
34 27 use Get_Instance;
35 28
36 29 /**
37 - * Minimum number of forms or entries required to show the rating notice.
38 - *
39 - * @since 2.5.2
40 - */
41 - public const RATING_NOTICE_THRESHOLD = 3;
42 -
43 - /**
44 - * Dashboard widget entries data.
45 - *
46 - * @var array
47 - * @since 1.9.1
48 - */
49 - private $dashboard_widget_data = [];
50 -
51 - /**
52 - * Cached result for whether the rating notice should display.
53 - *
54 - * @var bool|null
55 - * @since 2.5.2
56 - */
57 - private $should_show_rating = null;
58 -
59 - /**
60 - * SureForms Page Default permission.
61 - *
62 - * @var string
63 - * @since 1.12.2
64 - */
65 - private static $sureforms_page_default_capability = 'manage_options';
66 -
67 - /**
68 30 * Class constructor.
69 31 *
70 32 * @return void
71 33 * @since 0.0.1
@@ -73,19 +35,9 @@
73 35 public function __construct() {
74 36 add_action( 'admin_menu', [ $this, 'add_menu_page' ], 9 );
75 37 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
76 38 add_action( 'admin_menu', [ $this, 'settings_page' ] );
77 - add_action( 'admin_menu', [ $this, 'add_learn_page' ] );
78 39 add_action( 'admin_menu', [ $this, 'add_new_form' ] );
79 - add_action( 'admin_menu', [ $this, 'add_suremail_page' ] );
80 - if ( ! Helper::has_pro() ) {
81 - add_action( 'admin_menu', [ $this, 'add_quiz_page' ] );
82 - add_action( 'admin_menu', [ $this, 'add_survey_reports_page' ] );
83 - add_action( 'admin_menu', [ $this, 'add_partial_entries_page' ] );
84 - add_action( 'admin_menu', [ $this, 'add_upgrade_to_pro' ] );
85 - add_action( 'admin_footer', [ $this, 'add_upgrade_to_pro_target_attr' ] );
86 - }
87 -
88 40 add_filter( 'plugin_action_links', [ $this, 'add_settings_link' ], 10, 2 );
89 41 add_action( 'enqueue_block_assets', [ $this, 'enqueue_styles' ] );
90 42 add_action( 'admin_head', [ $this, 'enqueue_header_styles' ] );
91 43 add_filter( 'admin_body_class', [ $this, 'admin_template_picker_body_class' ] );
@@ -93,138 +45,32 @@
93 45 // this action is used to restrict Spectra's quick action bar on SureForms CPTS.
94 46 add_action( 'uag_enable_quick_action_sidebar', [ $this, 'restrict_spectra_quick_action_bar' ] );
95 47
96 48 add_action( 'current_screen', [ $this, 'enable_gutenberg_for_sureforms' ], 100 );
97 - // Register notices early for React pages (before admin_enqueue_scripts).
98 - add_action( 'admin_init', [ $this, 'register_pro_compatibility_notices' ], 5 );
99 - // Display notices on traditional WordPress admin pages.
100 49 add_action( 'admin_notices', [ $this, 'srfm_pro_version_compatibility' ] );
101 50
51 + // Handle entry actions.
52 + add_action( 'admin_init', [ $this, 'handle_entry_actions' ] );
53 + add_action( 'admin_notices', [ Entries_List_Table::class, 'display_bulk_action_notice' ] );
54 +
55 + // This action enqueues translations for NPS Survey library.
56 + // A better solution will be required from library to resolve plugin conflict.
57 + add_action(
58 + 'admin_footer',
59 + static function() {
60 + Helper::register_script_translations( 'nps-survey-script' );
61 + },
62 + 1000
63 + );
102 64 // Enfold theme compatibility to enable block editor for SureForms post type.
103 65 add_filter( 'avf_use_block_editor_for_post', [ $this, 'enable_block_editor_in_enfold_theme' ] );
104 66
105 67 // Add action links to the plugin page.
106 68 add_filter( 'plugin_action_links_' . SRFM_BASENAME, [ $this, 'add_action_links' ] );
107 - // Check if admin notification is enabled and add entries badge.
108 - $general_options = get_option( 'srfm_general_settings_options', [] );
109 - $admin_notification_on = isset( $general_options['srfm_admin_notification'] ) ? (bool) $general_options['srfm_admin_notification'] : true;
110 -
111 - if ( $admin_notification_on ) {
112 - add_action( 'admin_menu', [ $this, 'maybe_add_entries_badge' ], 99 );
113 - }
114 -
115 69 add_filter( 'wpforms_current_user_can', [ $this, 'disable_wpforms_capabilities' ], 10, 3 );
116 -
117 - add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_pointer' ] );
118 - // Ajax callbacks for wp-pointer functionality.
119 - add_action( 'wp_ajax_should_show_pointer', [ $this, 'pointer_should_show' ] );
120 - add_action( 'wp_ajax_sureforms_dismiss_pointer', [ $this, 'pointer_dismissed' ] );
121 - add_action( 'wp_ajax_sureforms_accept_cta', [ $this, 'pointer_accepted_cta' ] );
122 - add_action( 'wp_ajax_srfm_notice_response', [ $this, 'handle_notice_response' ] );
123 -
124 - // Register dashboard widget only if there are recent entries.
125 - add_action( 'admin_init', [ $this, 'maybe_register_dashboard_widget' ] );
126 -
127 - // Save first form creation time stamp.
128 - add_action( 'admin_init', [ $this, 'save_first_form_creation_time_stamp' ] );
129 - add_action( 'admin_notices', [ $this, 'display_srfm_rating_notice' ] );
130 - add_action( 'admin_notices', [ $this, 'display_srfm_getting_started_notice' ] );
131 70 }
132 71
133 72 /**
134 - * Get the first form creation time stamp.
135 - *
136 - * @since 1.10.1
137 - * @return int|false
138 - */
139 - public static function get_first_form_creation_time_stamp() {
140 - return Helper::get_srfm_option( 'first_form_created_at', false );
141 - }
142 -
143 - /**
144 - * Check if the first form has been created.
145 - *
146 - * @since 1.10.1
147 - * @return bool
148 - */
149 - public static function is_first_form_created() {
150 - // Convert the first form creation time stamp to a boolean. If it exists, it will return true, otherwise false.
151 - $first_form_creation_time_stamp = self::get_first_form_creation_time_stamp();
152 -
153 - // If the first form creation time stamp is not set, return false.
154 - if ( ! $first_form_creation_time_stamp ) {
155 - return false; // No forms created yet.
156 - }
157 -
158 - // Check if the first form creation time stamp is a valid integer and greater than zero.
159 - return is_int( $first_form_creation_time_stamp ) && $first_form_creation_time_stamp > 0;
160 - }
161 -
162 - /**
163 - * Check and save the first form creation time stamp.
164 - * If not already saved.
165 - *
166 - * @since 1.10.1
167 - * @return void
168 - */
169 - public static function save_first_form_creation_time_stamp() {
170 - if ( ! Helper::current_user_can() || self::is_first_form_created() || ! defined( 'SRFM_FORMS_POST_TYPE' ) || ! post_type_exists( SRFM_FORMS_POST_TYPE ) ) {
171 - return;
172 - }
173 -
174 - // Get the first form creation time from the database that is published.
175 - $query = new \WP_Query(
176 - [
177 - 'post_type' => SRFM_FORMS_POST_TYPE,
178 - 'posts_per_page' => 1,
179 - 'orderby' => 'date',
180 - 'order' => 'ASC',
181 - 'fields' => 'ids',
182 - 'post_status' => 'publish',
183 - ]
184 - );
185 -
186 - if ( ! empty( $query->posts ) && isset( $query->posts[0] ) ) {
187 - // Get the first post from the query result.
188 - $post_id = $query->posts[0];
189 - // Get the post creation time in GMT.
190 - $creation_time = get_post_field( 'post_date_gmt', $post_id );
191 - // Convert the creation time to a timestamp.
192 - $timestamp = strtotime( $creation_time );
193 -
194 - if ( ! $timestamp ) {
195 - return;
196 - }
197 -
198 - Helper::update_srfm_option( 'first_form_created_at', $timestamp );
199 - }
200 - }
201 -
202 - /**
203 - * Check if n days have passed since the first form creation.
204 - * This is used to determine if the dynamic nudges should be shown.
205 - *
206 - * @param int $days Number of days to check.
207 - * @since 1.10.1
208 - * @return bool
209 - */
210 - public static function check_first_form_creation_threshold( $days = 3 ) {
211 - $first_form_creation_time_stamp = self::get_first_form_creation_time_stamp();
212 -
213 - if ( ! $first_form_creation_time_stamp ) {
214 - return false; // No forms created yet.
215 - }
216 -
217 - /**
218 - * Calculate the number of days since the first form was created.
219 - */
220 - $days_from_creation = ( strtotime( current_time( 'mysql' ) ) - $first_form_creation_time_stamp ) / DAY_IN_SECONDS;
221 -
222 - // Return a boolean indicating if the number of days since creation is greater than the specified days.
223 - return $days_from_creation > $days;
224 - }
225 -
226 - /**
227 73 * Show action on plugin page.
228 74 *
229 75 * @param array $links links.
230 76 * @return array
@@ -230,19 +76,17 @@
230 76 * @return array
231 77 * @since 1.4.2
232 78 */
233 79 public function add_action_links( $links ) {
234 - if ( ! Helper::has_pro() ) {
80 + if ( ! defined( 'SRFM_PRO_FILE' ) && ! file_exists( WP_PLUGIN_DIR . '/sureforms-pro/sureforms-pro.php' ) ) {
235 81 // Display upsell link if SureForms Pro is not installed.
236 - $upsell_link = Helper::get_sureforms_website_url( 'pricing', [ 'utm_medium' => 'plugin-list' ] );
237 -
238 - ob_start();
239 - ?>
240 - <a href="<?php echo esc_url( $upsell_link ); ?>" target="_blank" rel="noreferrer" class="sureforms-plugins-go-pro">
241 - <?php echo esc_html__( 'Get SureForms Pro', 'sureforms' ); ?>
242 - </a>
243 - <?php
244 - $links[] = trim( ob_get_clean() );
82 + $upsell_link = add_query_arg(
83 + [
84 + 'utm_medium' => 'plugin-list',
85 + ],
86 + Helper::get_sureforms_website_url( 'pricing' )
87 + );
88 + $links[] = '<a href="' . esc_url( $upsell_link ) . '" target="_blank" rel="noreferrer" class="sureforms-plugins-go-pro">' . esc_html__( 'Get SureForms Pro', 'sureforms' ) . '</a>';
245 89 }
246 90
247 91 return $links;
248 92 }
@@ -310,15 +154,20 @@
310 154 * @return void
311 155 * @since 0.0.1
312 156 */
313 157 public function add_menu_page() {
314 - $menu_slug = 'sureforms_menu';
158 + if ( ! current_user_can( 'manage_options' ) ) {
159 + return;
160 + }
315 161
162 + $capability = 'manage_options';
163 + $menu_slug = 'sureforms_menu';
164 +
316 165 $logo = file_get_contents( plugin_dir_path( SRFM_FILE ) . 'images/icon.svg' );
317 166 add_menu_page(
318 167 __( 'SureForms', 'sureforms' ),
319 168 __( 'SureForms', 'sureforms' ),
320 - self::$sureforms_page_default_capability,
169 + 'edit_others_posts',
321 170 $menu_slug,
322 171 static function () {
323 172 },
324 173 'data:image/svg+xml;base64,' . base64_encode( $logo ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
@@ -329,9 +178,9 @@
329 178 add_submenu_page(
330 179 $menu_slug,
331 180 __( 'Dashboard', 'sureforms' ),
332 181 __( 'Dashboard', 'sureforms' ),
333 - self::$sureforms_page_default_capability,
182 + $capability,
334 183 $menu_slug,
335 184 [ $this, 'render_dashboard' ]
336 185 );
337 186 }
@@ -347,9 +196,9 @@
347 196 add_submenu_page(
348 197 'sureforms_menu',
349 198 __( 'Settings', 'sureforms' ),
350 199 __( 'Settings', 'sureforms' ),
351 - self::$sureforms_page_default_capability,
200 + 'edit_others_posts',
352 201 'sureforms_form_settings',
353 202 $callback
354 203 );
355 204
@@ -362,190 +211,8 @@
362 211 }
363 212 }
364 213
365 214 /**
366 - * Open to Upgrade to Pro submenu link in new tab.
367 - *
368 - * @return void
369 - * @since 1.6.1
370 - */
371 - public function add_upgrade_to_pro_target_attr() {
372 - ?>
373 - <script type="text/javascript">
374 - document.addEventListener('DOMContentLoaded', function () {
375 - // Upgrade link handler.
376 - // IMPORTANT: If this URL changes, also update it in the `add_upgrade_to_pro` function.
377 - const upgradeLink = document.querySelector('a[href*="https://sureforms.com/upgrade"]');
378 - if (upgradeLink) {
379 - upgradeLink.addEventListener('click', e => {
380 - e.preventDefault();
381 - window.open(upgradeLink.href, '_blank');
382 - });
383 - }
384 - });
385 - </script>
386 - <?php
387 - }
388 -
389 - /**
390 - * Add Upgrade to pro menu item.
391 - *
392 - * @return void
393 - * @since 1.6.1
394 - */
395 - public function add_upgrade_to_pro() {
396 - // The url used here is used as a selector for css to style the upgrade to pro submenu.
397 - // If you are changing this url, please make sure to update the css as well.
398 - $upgrade_url = Helper::get_sureforms_website_url( 'upgrade', [ 'utm_medium' => 'submenu_link_upgrade' ] );
399 -
400 - add_submenu_page(
401 - 'sureforms_menu',
402 - __( 'Upgrade', 'sureforms' ),
403 - __( 'Upgrade', 'sureforms' ),
404 - self::$sureforms_page_default_capability,
405 - $upgrade_url
406 - );
407 - }
408 -
409 - /**
410 - * Add Quiz empty state submenu page for free users.
411 - *
412 - * @return void
413 - * @since 2.7.0
414 - */
415 - public function add_quiz_page() {
416 - add_submenu_page(
417 - 'sureforms_menu',
418 - __( 'Quiz Entries', 'sureforms' ),
419 - __( 'Quizzes', 'sureforms' ) .
420 - ' <span style="color:#4ADE80;font-size:9px;font-weight:600;">' .
421 - esc_html__( 'New', 'sureforms' ) .
422 - '</span>',
423 - self::$sureforms_page_default_capability,
424 - 'sureforms_quiz_entries',
425 - [ $this, 'render_quiz_empty_state' ],
426 - 5
427 - );
428 - }
429 -
430 - /**
431 - * Quiz empty state page callback.
432 - *
433 - * @return void
434 - * @since 2.7.0
435 - */
436 - public function render_quiz_empty_state() {
437 - ?>
438 - <div id="srfm-quiz-entries-root" class="srfm-admin-wrapper"></div>
439 - <?php
440 - }
441 -
442 - /**
443 - * Add Survey Reports promotional submenu page for free users.
444 - *
445 - * @return void
446 - * @since 2.8.0
447 - */
448 - public function add_survey_reports_page() {
449 - add_submenu_page(
450 - 'sureforms_menu',
451 - __( 'Survey Reports', 'sureforms' ),
452 - __( 'Survey Reports', 'sureforms' ) .
453 - ' <span style="color:#4ADE80;font-size:9px;font-weight:600;">' .
454 - esc_html__( 'New', 'sureforms' ) .
455 - '</span>',
456 - self::$sureforms_page_default_capability,
457 - 'sureforms_survey_reports',
458 - [ $this, 'render_survey_empty_state' ],
459 - 6
460 - );
461 - }
462 -
463 - /**
464 - * Survey empty state page callback.
465 - *
466 - * @return void
467 - * @since 2.8.0
468 - */
469 - public function render_survey_empty_state() {
470 - ?>
471 - <div id="srfm-survey-empty-state-root" class="srfm-admin-wrapper"></div>
472 - <?php
473 - }
474 -
475 - /**
476 - * Add Partial Entries promotional submenu page for free users.
477 - *
478 - * @return void
479 - * @since 2.9.0
480 - */
481 - public function add_partial_entries_page() {
482 - add_submenu_page(
483 - 'sureforms_menu',
484 - __( 'Partial Entries', 'sureforms' ),
485 - __( 'Partial Entries', 'sureforms' ) .
486 - ' <span style="color:#4ADE80;font-size:9px;font-weight:600;">' .
487 - esc_html__( 'New', 'sureforms' ) .
488 - '</span>',
489 - self::$sureforms_page_default_capability,
490 - 'sureforms_partial_entries',
491 - [ $this, 'render_partial_entries_empty_state' ],
492 - 7
493 - );
494 - }
495 -
496 - /**
497 - * Partial Entries empty state page callback.
498 - *
499 - * @return void
500 - * @since 2.9.0
501 - */
502 - public function render_partial_entries_empty_state() {
503 - ?>
504 - <div id="srfm-partial-entries-empty-state-root" class="srfm-admin-wrapper"></div>
505 - <?php
506 - }
507 -
508 - /**
509 - * Add SMTP promotional submenu page.
510 - *
511 - * @return void
512 - * @since 1.7.1
513 - */
514 - public function add_suremail_page() {
515 - add_submenu_page(
516 - 'sureforms_menu',
517 - __( 'SMTP', 'sureforms' ),
518 - __( 'SMTP', 'sureforms' ),
519 - self::$sureforms_page_default_capability,
520 - 'sureforms_smtp',
521 - [ $this, 'suremail_page_callback' ]
522 - );
523 -
524 - // Get the current submenu page.
525 - $submenu_page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- $_GET['page'] does not provide nonce.
526 -
527 - // Check if SureMail is installed and active.
528 - if ( 'sureforms_smtp' === $submenu_page && file_exists( WP_PLUGIN_DIR . '/suremails/suremails.php' ) && is_plugin_active( 'suremails/suremails.php' ) ) {
529 - // Plugin is installed and active - redirect to SureMail dashboard.
530 - wp_safe_redirect( admin_url( 'options-general.php?page=suremail#/dashboard' ) );
531 - exit;
532 - }
533 - }
534 -
535 - /**
536 - * SMTP promotional page callback.
537 - *
538 - * @return void
539 - * @since 1.7.1
540 - */
541 - public function suremail_page_callback() {
542 - ?>
543 - <div id="srfm-suremail-container" class="srfm-admin-wrapper"></div>
544 - <?php
545 - }
546 -
547 - /**
548 215 * Render Admin Dashboard.
549 216 *
550 217 * @return void
551 218 * @since 0.0.1
@@ -550,11 +217,9 @@
550 217 * @return void
551 218 * @since 0.0.1
552 219 */
553 220 public function render_dashboard() {
554 - ?>
555 - <div id="srfm-dashboard-container" class="srfm-admin-wrapper"></div>
556 - <?php
221 + echo '<div id="srfm-dashboard-container"></div>';
557 222 }
558 223
559 224 /**
560 225 * Settings page callback.
@@ -562,43 +227,12 @@
562 227 * @return void
563 228 * @since 0.0.1
564 229 */
565 230 public function settings_page_callback() {
566 - ?>
567 - <div id="srfm-settings-container" class="srfm-admin-wrapper"></div>
568 - <?php
231 + echo '<div id="srfm-settings-container"></div>';
569 232 }
570 233
571 234 /**
572 - * Add Learn submenu page.
573 - *
574 - * @return void
575 - * @since 2.5.2
576 - */
577 - public function add_learn_page() {
578 - add_submenu_page(
579 - 'sureforms_menu',
580 - __( 'Learn', 'sureforms' ),
581 - __( 'Learn', 'sureforms' ),
582 - self::$sureforms_page_default_capability,
583 - 'sureforms_learn',
584 - [ $this, 'render_learn' ]
585 - );
586 - }
587 -
588 - /**
589 - * Learn page callback.
590 - *
591 - * @return void
592 - * @since 2.5.2
593 - */
594 - public function render_learn() {
595 - ?>
596 - <div id="srfm-learn-root" class="srfm-admin-wrapper"></div>
597 - <?php
598 - }
599 -
600 - /**
601 235 * Add new form menu item.
602 236 *
603 237 * @return void
604 238 * @since 0.0.1
@@ -605,62 +239,27 @@
605 239 */
606 240 public function add_new_form() {
607 241 add_submenu_page(
608 242 'sureforms_menu',
609 - __( 'Forms', 'sureforms' ),
610 - __( 'Forms', 'sureforms' ),
611 - self::$sureforms_page_default_capability,
612 - 'sureforms_forms',
613 - [ $this, 'render_forms' ],
614 - 1
615 - );
616 - add_submenu_page(
617 - 'sureforms_menu',
618 243 __( 'New Form', 'sureforms' ),
619 244 __( 'New Form', 'sureforms' ),
620 - self::$sureforms_page_default_capability,
245 + 'edit_others_posts',
621 246 'add-new-form',
622 247 [ $this, 'add_new_form_callback' ],
623 248 2
624 249 );
625 - $entries_hook = add_submenu_page(
250 + add_submenu_page(
626 251 'sureforms_menu',
627 252 __( 'Entries', 'sureforms' ),
628 253 __( 'Entries', 'sureforms' ),
629 - self::$sureforms_page_default_capability,
254 + 'edit_others_posts',
630 255 SRFM_ENTRIES,
631 256 [ $this, 'render_entries' ],
632 257 3
633 258 );
634 -
635 - add_submenu_page(
636 - 'sureforms_menu',
637 - __( 'Payments', 'sureforms' ),
638 - __( 'Payments', 'sureforms' ),
639 - self::$sureforms_page_default_capability,
640 - SRFM_PAYMENTS,
641 - [ $this, 'render_payments' ],
642 - 4
643 - );
644 -
645 - if ( $entries_hook ) {
646 - add_action( 'load-' . $entries_hook, [ $this, 'mark_entries_page_visit' ] );
647 - }
648 259 }
649 260
650 261 /**
651 - * Payments page callback.
652 - *
653 - * @return void
654 - * @since 2.0.0
655 - */
656 - public function render_payments() {
657 - ?>
658 - <div id="srfm-payments-react-container" class="srfm-admin-wrapper"></div>
659 - <?php
660 - }
661 -
662 - /**
663 262 * Add new form mentu item callback.
664 263 *
665 264 * @return void
666 265 * @since 0.0.1
@@ -665,109 +264,44 @@
665 264 * @return void
666 265 * @since 0.0.1
667 266 */
668 267 public function add_new_form_callback() {
669 - ?>
670 - <div id="srfm-add-new-form-container" class="srfm-admin-wrapper"></div>
671 - <?php
268 + echo '<div id="srfm-add-new-form-container"></div>';
672 269 }
673 270
674 271 /**
675 - * Forms page callback.
676 - *
677 - * @return void
678 - * @since 2.0.0
679 - */
680 - public function render_forms() {
681 - ?>
682 - <div id="srfm-forms-root" class="srfm-admin-wrapper"></div>
683 - <?php
684 - }
685 -
686 - /**
687 272 * Entries page callback.
688 273 *
689 274 * @since 0.0.13
690 - * @since 2.0.0 - Updated the entries UI and the function definition.
691 275 * @return void
692 276 */
693 277 public function render_entries() {
694 - echo '<div id="srfm-entries-root"></div>';
695 - }
696 -
697 - /**
698 - * Add notification badge to SureForms menu when there are new entries.
699 - *
700 - * @since 1.7.3
701 - * @return void
702 - */
703 - public function maybe_add_entries_badge() {
704 - if ( ! Helper::current_user_can() ) {
278 + // Render single entry view.
279 + // Adding the phpcs ignore nonce verification as no database operations are performed in this function, it is used to display the single entry view.
280 + if ( isset( $_GET['entry_id'] ) && is_numeric( $_GET['entry_id'] ) && isset( $_GET['view'] ) && 'details' === $_GET['view'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verification is not needed here and explained in the comments above as well.
281 + $single_entry_view = new Single_Entry();
282 + $single_entry_view->render();
705 283 return;
706 284 }
707 285
708 - // If currently viewing the entries listing page, mark it as visited and skip the badge.
709 - if ( isset( $_GET['page'] ) && SRFM_ENTRIES === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only checking the page slug.
710 - $this->mark_entries_page_visit();
286 + // Render all entries view.
287 + $entries_table = new Entries_List_Table();
288 + $entries_table->prepare_items();
289 + echo '<div class="wrap"><h1 class="wp-heading-inline">' . esc_html__( 'Entries', 'sureforms' ) . '</h1>';
290 + if ( empty( $entries_table->all_entries_count ) && empty( $entries_table->trash_entries_count ) ) {
291 + $instance = Post_Types::get_instance();
292 + $instance->sureforms_render_blank_state( SRFM_ENTRIES );
293 + $instance->get_blank_state_styles();
711 294 return;
712 295 }
713 -
714 - $srfm_options = get_option( 'srfm_options', [] );
715 - $last_visit = isset( $srfm_options['entries_last_visited'] ) ? absint( $srfm_options['entries_last_visited'] ) : 0;
716 - $new_entries = Entries::get_entries_count_after( $last_visit );
717 -
718 - if ( $new_entries <= 0 ) {
719 - return;
720 - }
721 -
722 - global $menu;
723 - foreach ( $menu as $index => $item ) {
724 - if ( isset( $item[2] ) && 'sureforms_menu' === $item[2] ) {
725 - ob_start();
726 - ?>
727 - <span class="srfm-update-dot"></span>
728 - <?php
729 - $dot_html = ob_get_clean();
730 - // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Adding notifications for menu item.
731 - $menu[ $index ][0] .= $dot_html;
732 - break;
733 - }
734 - }
735 -
736 - global $submenu;
737 - if ( isset( $submenu['sureforms_menu'] ) ) {
738 - foreach ( $submenu['sureforms_menu'] as $index => $sub_item ) {
739 - if ( isset( $sub_item[2] ) && SRFM_ENTRIES === $sub_item[2] ) {
740 - ob_start();
741 - ?>
742 - <span class="update-plugins count-<?php echo absint( $new_entries ); ?>">
743 - <span class="plugin-count"><?php echo absint( $new_entries ); ?></span>
744 - </span>
745 - <?php
746 - $badge_html = ob_get_clean();
747 - // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Adding notifications for submenu item.
748 - $submenu['sureforms_menu'][ $index ][0] .= $badge_html;
749 - break;
750 - }
751 - }
752 - }
296 + echo '<form method="get">';
297 + echo '<input type="hidden" name="page" value="sureforms_entries">';
298 + $entries_table->display();
299 + echo '</form>';
300 + echo '</div>';
753 301 }
754 302
755 303 /**
756 - * Mark the user's visit to the entries page.
757 - *
758 - * @since 1.7.3
759 - * @return void
760 - */
761 - public function mark_entries_page_visit() {
762 - if ( Helper::current_user_can() ) {
763 - $srfm_options = get_option( 'srfm_options', [] );
764 - $srfm_options['entries_last_visited'] = time();
765 - \SRFM\Inc\Helper::update_admin_settings_option( 'srfm_options', $srfm_options );
766 - }
767 - }
768 -
769 - /**
770 304 * Adds a settings link to the plugin action links on the plugins page.
771 305 *
772 306 * @param array $links An array of plugin action links.
773 307 * @param string $file The plugin file path.
@@ -775,22 +309,15 @@
775 309 * @since 0.0.1
776 310 */
777 311 public function add_settings_link( $links, $file ) {
778 312 if ( 'sureforms/sureforms.php' === $file ) {
779 - ob_start();
780 - ?>
781 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=sureforms_form_settings&tab=general-settings' ) ); ?>">
782 - <?php echo esc_html__( 'Settings', 'sureforms' ); ?>
783 - </a>
784 - <?php
785 - $settings_link_html = ob_get_clean();
786 - $plugin_links = apply_filters(
313 + $plugin_links = apply_filters(
787 314 'sureforms_plugin_action_links',
788 315 [
789 - 'sureforms_settings' => $settings_link_html,
316 + 'sureforms_settings' => '<a href="' . esc_url( admin_url( 'admin.php?page=sureforms_form_settings&tab=general-settings' ) ) . '">' . esc_html__( 'Settings', 'sureforms' ) . '</a>',
790 317 ]
791 318 );
792 - $links = array_merge( $plugin_links, $links );
319 + $links = array_merge( $plugin_links, $links );
793 320 }
794 321 return $links;
795 322 }
796 323
@@ -900,8 +427,9 @@
900 427 global $wp_version;
901 428
902 429 $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
903 430 $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
431 + $js_uri = SRFM_URL . 'assets/js/' . $dir_name . '/';
904 432 $css_uri = SRFM_URL . 'assets/css/' . $dir_name . '/';
905 433 $is_rtl = is_rtl();
906 434 $rtl = $is_rtl ? '-rtl' : '';
907 435
@@ -908,133 +436,30 @@
908 436 /**
909 437 * List of the handles in which we need to add translation compatibility.
910 438 */
911 439 $script_translations_handlers = [];
912 - $onboarding_instance = Onboarding::get_instance();
913 - $current_user = wp_get_current_user();
914 440
915 441 $localization_data = [
916 - 'site_url' => get_site_url(),
917 - 'current_user_login' => $current_user->user_login ?? '',
918 - 'website_lead_details' => [
919 - 'first_name' => $current_user->first_name ?? '',
920 - 'last_name' => $current_user->last_name ?? '',
921 - 'email' => $current_user->user_email ?? '',
922 - ],
923 - 'breadcrumbs' => $this->get_breadcrumbs_for_current_page(),
924 - 'sureforms_dashboard_url' => admin_url( '/admin.php?page=sureforms_menu' ),
925 - 'plugin_version' => SRFM_VER,
926 - 'global_settings_nonce' => Helper::current_user_can() ? wp_create_nonce( 'wp_rest' ) : '',
927 - 'is_pro_active' => Helper::has_pro(),
928 - 'is_first_form_created' => self::is_first_form_created(),
929 - 'check_three_days_threshold' => self::check_first_form_creation_threshold(),
930 - 'check_eight_days_threshold' => self::check_first_form_creation_threshold( 8 ),
931 - 'pro_plugin_version' => Helper::has_pro() ? SRFM_PRO_VER : '',
932 - 'pro_plugin_name' => Helper::has_pro() && defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro',
933 - 'sureforms_pricing_page' => Helper::get_sureforms_website_url( 'pricing' ),
934 - 'field_spacing_vars' => Helper::get_css_vars(),
935 - 'is_ver_lower_than_6_7' => version_compare( $wp_version, '6.6.2', '<=' ),
936 - 'integrations' => Helper::sureforms_get_integration(),
937 - 'rotating_plugin_banner' => Helper::get_rotating_plugin_banner(),
938 - 'ajax_url' => admin_url( 'admin-ajax.php' ),
939 - 'sf_plugin_manager_nonce' => wp_create_nonce( 'sf_plugin_manager_nonce' ),
940 - 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
941 - 'plugin_activating_text' => __( 'Activating...', 'sureforms' ),
942 - 'plugin_activated_text' => __( 'Activated', 'sureforms' ),
943 - 'plugin_activate_text' => __( 'Activate', 'sureforms' ),
944 - 'plugin_installing_text' => __( 'Installing...', 'sureforms' ),
945 - 'plugin_installed_text' => __( 'Installed', 'sureforms' ),
946 - 'privacy_policy_url' => Helper::get_sureforms_website_url( 'privacy-policy/' ),
947 - 'is_rtl' => $is_rtl,
948 - 'onboarding_completed' => method_exists( $onboarding_instance, 'get_onboarding_status' ) ? $onboarding_instance->get_onboarding_status() : false,
949 - 'onboarding_redirect' => isset( $_GET['srfm-activation-redirect'] ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce is not required for the activation redirection.
950 - 'pointer_nonce' => wp_create_nonce( 'sureforms_pointer_action' ),
951 - 'general_settings_url' => admin_url( '/options-general.php' ),
952 - 'additional_header_nav_items' => [],
953 - // Smart tags for the Global Defaults email notification fields.
954 - // srfm_block_data is only available in the block editor; these keys
955 - // make the same data accessible on the settings page via srfm_admin.
956 - 'smart_tags_array' => Smart_Tags::smart_tag_list(),
957 - 'smart_tags_array_email' => Smart_Tags::email_smart_tag_list(),
958 - // Default confirmation message HTML (icon + heading + text) used as
959 - // the initial React state before the settings API response arrives.
960 - 'default_confirmation_message' => Global_Settings::get_default_confirmation_message(),
961 - 'payments' => apply_filters(
962 - 'srfm_admin_localize_payments_data',
963 - [
964 - 'stripe_connected' => Stripe_Helper::is_stripe_connected(),
965 - 'stripe_mode' => Stripe_Helper::get_stripe_mode(),
966 - 'stripe_connect_url' => Stripe_Helper::get_stripe_settings_url(),
967 - 'currencies_data' => Payment_Helper::get_all_currencies_data(),
968 - 'zero_decimal_currencies' => Payment_Helper::get_zero_decimal_currencies(),
969 - 'webhook_url' => Stripe_Helper::get_webhook_url(),
970 - 'webhook_test_connected' => Stripe_Helper::is_webhook_configured( 'test', true ),
971 - 'webhook_live_connected' => Stripe_Helper::is_webhook_configured( 'live', true ),
972 - 'is_transaction_present' => Stripe_Helper::is_transaction_present(),
973 - 'payment_currency' => Payment_Helper::get_currency(),
974 - 'currency_sign_position' => Payment_Helper::get_currency_sign_position(),
975 - ]
976 - ),
977 - 'mcp_adapter_status' => file_exists( WP_PLUGIN_DIR . '/mcp-adapter/mcp-adapter.php' )
978 - ? ( is_plugin_active( 'mcp-adapter/mcp-adapter.php' ) ? 'active' : 'installed' )
979 - : 'not_installed',
980 - 'mcp_endpoint_url' => esc_url_raw( rest_url( 'sureforms/v1/mcp' ) ),
442 + 'site_url' => get_site_url(),
443 + 'breadcrumbs' => $this->get_breadcrumbs_for_current_page(),
444 + 'sureforms_dashboard_url' => admin_url( '/admin.php?page=sureforms_menu' ),
445 + 'plugin_version' => SRFM_VER,
446 + 'global_settings_nonce' => current_user_can( 'manage_options' ) ? wp_create_nonce( 'wp_rest' ) : '',
447 + 'is_pro_active' => defined( 'SRFM_PRO_VER' ),
448 + 'pro_plugin_version' => defined( 'SRFM_PRO_VER' ) ? SRFM_PRO_VER : '',
449 + 'pro_plugin_name' => defined( 'SRFM_PRO_VER' ) && defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro',
450 + 'sureforms_pricing_page' => Helper::get_sureforms_website_url( 'pricing' ),
451 + 'field_spacing_vars' => Helper::get_css_vars(),
452 + 'is_ver_lower_than_6_7' => version_compare( $wp_version, '6.6.2', '<=' ),
981 453 ];
982 454
983 - $is_screen_sureforms_menu = Helper::validate_request_context( 'sureforms_menu', 'page' );
984 - $is_screen_add_new_form = Helper::validate_request_context( 'add-new-form', 'page' );
985 - $is_screen_sureforms_forms = Helper::validate_request_context( 'sureforms_forms', 'page' );
986 - $is_screen_sureforms_form_settings = Helper::validate_request_context( 'sureforms_form_settings', 'page' );
987 - $is_screen_sureforms_payments = Helper::validate_request_context( 'sureforms_payments', 'page' );
988 - $is_screen_sureforms_entries = Helper::validate_request_context( SRFM_ENTRIES, 'page' );
989 - $is_screen_sureforms_learn = Helper::validate_request_context( 'sureforms_learn', 'page' );
990 - $is_screen_quiz_empty_state = Helper::validate_request_context( 'sureforms_quiz_entries', 'page' );
991 - $is_screen_survey_empty_state = Helper::validate_request_context( 'sureforms_survey_reports', 'page' );
992 - $is_screen_partial_entries_empty_state = Helper::validate_request_context( 'sureforms_partial_entries', 'page' );
993 - $is_post_type_sureforms_form = SRFM_FORMS_POST_TYPE === $current_screen->post_type;
455 + $is_screen_sureforms_menu = Helper::validate_request_context( 'sureforms_menu', 'page' );
456 + $is_screen_add_new_form = Helper::validate_request_context( 'add-new-form', 'page' );
457 + $is_screen_sureforms_form_settings = Helper::validate_request_context( 'sureforms_form_settings', 'page' );
458 + $is_screen_sureforms_entries = Helper::validate_request_context( SRFM_ENTRIES, 'page' );
459 + $is_post_type_sureforms_form = SRFM_FORMS_POST_TYPE === $current_screen->post_type;
994 460
995 - /**
996 - * Check if the current screen is the SureForms Menu and AI Auth Email is present then we will add user type as registered.
997 - * Compatibility with existing UI code that checks for this condition.
998 - */
999 - if ( $is_screen_sureforms_menu ) {
1000 - // If email is stored send the user type as registered else non-registered.
1001 - $localization_data['srfm_ai_details'] = [
1002 - 'type' => ! empty( get_option( 'srfm_ai_auth_user_email' ) ) ? 'registered' : 'non-registered',
1003 - ];
1004 - }
1005 -
1006 - // Add the Quizzes and Survey Reports nav items when pro is not active.
1007 - if ( ! Helper::has_pro() ) {
1008 - $localization_data['additional_header_nav_items'][] = [
1009 - 'slug' => 'sureforms_quiz_entries',
1010 - 'text' => __( 'Quizzes', 'sureforms' ),
1011 - 'link' => admin_url( 'admin.php?page=sureforms_quiz_entries' ),
1012 - ];
1013 - $localization_data['additional_header_nav_items'][] = [
1014 - 'slug' => 'sureforms_survey_reports',
1015 - 'text' => __( 'Survey Reports', 'sureforms' ),
1016 - 'link' => admin_url( 'admin.php?page=sureforms_survey_reports' ),
1017 - ];
1018 - $localization_data['additional_header_nav_items'][] = [
1019 - 'slug' => 'sureforms_partial_entries',
1020 - 'text' => __( 'Partial Entries', 'sureforms' ),
1021 - 'link' => admin_url( 'admin.php?page=sureforms_partial_entries' ),
1022 - ];
1023 - }
1024 -
1025 - $is_sureforms_screen = $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 || $is_screen_sureforms_learn || $is_screen_quiz_empty_state || $is_screen_survey_empty_state || $is_screen_partial_entries_empty_state;
1026 -
1027 - /**
1028 - * Filter to allow extending the SureForms dashboard screen check.
1029 - *
1030 - * @since 2.6.0
1031 - *
1032 - * @param bool $is_sureforms_screen Whether the current screen is a SureForms dashboard screen.
1033 - */
1034 - $is_sureforms_screen = apply_filters( 'srfm_is_dashboard_screen', $is_sureforms_screen );
1035 -
1036 - if ( $is_sureforms_screen ) {
461 + if ( $is_screen_sureforms_menu || $is_post_type_sureforms_form || $is_screen_add_new_form || $is_screen_sureforms_form_settings || $is_screen_sureforms_entries ) {
1037 462 $asset_handle = '-dashboard';
1038 463
1039 464 wp_enqueue_style( SRFM_SLUG . $asset_handle . '-font', 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap', [], SRFM_VER );
1040 465
@@ -1062,9 +487,9 @@
1062 487 update_option( 'srfm_pro_license_status', $current_license_status );
1063 488 }
1064 489 }
1065 490
1066 - $localization_data['security_settings_url'] = admin_url( '/admin.php?page=sureforms_form_settings&tab=security-settings&subpage=recaptcha' );
491 + $localization_data['security_settings_url'] = admin_url( '/admin.php?page=sureforms_form_settings&tab=security-settings' );
1067 492 $localization_data['integration_settings_url'] = admin_url( '/admin.php?page=sureforms_form_settings&tab=integration-settings' );
1068 493 wp_localize_script(
1069 494 SRFM_SLUG . $asset_handle,
1070 495 SRFM_SLUG . '_admin',
@@ -1073,12 +498,27 @@
1073 498 $localization_data
1074 499 )
1075 500 );
1076 501 wp_enqueue_style( SRFM_SLUG . '-dashboard', SRFM_URL . 'assets/build/dashboard.css', [], SRFM_VER, 'all' );
502 +
1077 503 }
1078 504
1079 - if ( $is_screen_sureforms_form_settings || $is_screen_sureforms_forms ) {
505 + if ( $is_screen_sureforms_form_settings ) {
1080 506 wp_enqueue_style( SRFM_SLUG . '-settings', $css_uri . 'backend/settings' . $file_prefix . $rtl . '.css', [], SRFM_VER );
507 +
508 + // if version is equal to or lower than 6.6.2 then add compatibility css.
509 + if ( version_compare( $wp_version, '6.6.2', '<=' ) ) {
510 + $srfm_inline_css = '
511 + .srfm-settings-page-container
512 + .components-toggle-control {
513 + .components-base-control__help{
514 + margin-left: 4em;
515 + }
516 + }
517 + }
518 + ';
519 + wp_add_inline_style( SRFM_SLUG . '-settings', $srfm_inline_css );
520 + }
1081 521 }
1082 522
1083 523 // Enqueue styles for the entries page.
1084 524 if ( $is_screen_sureforms_entries ) {
@@ -1084,158 +524,30 @@
1084 524 if ( $is_screen_sureforms_entries ) {
1085 525 $asset_handle = '-entries';
1086 526 wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/entries.js', $script_info['dependencies'], SRFM_VER, true );
1087 527
1088 - wp_localize_script(
1089 - SRFM_SLUG . $asset_handle,
1090 - SRFM_SLUG . '_admin',
1091 - apply_filters(
1092 - SRFM_SLUG . '_admin_filter',
1093 - $localization_data
1094 - )
1095 - );
1096 528 $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
1097 529 }
1098 530
1099 - // Enqueue scripts for the learn page.
1100 - if ( $is_screen_sureforms_learn ) {
1101 - $asset_handle = '-learn';
1102 - wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/learn.js', $script_info['dependencies'], SRFM_VER, true );
531 + // Admin Submenu Styles.
532 + wp_enqueue_style( SRFM_SLUG . '-admin', $css_uri . 'backend/admin' . $file_prefix . $rtl . '.css', [], SRFM_VER );
1103 533
1104 - wp_localize_script(
1105 - SRFM_SLUG . $asset_handle,
1106 - SRFM_SLUG . '_admin',
1107 - apply_filters(
1108 - SRFM_SLUG . '_admin_filter',
1109 - $localization_data
1110 - )
1111 - );
1112 - $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
1113 - }
534 + if ( 'edit-' . SRFM_FORMS_POST_TYPE === $current_screen->id ) {
535 + $asset_handle = 'page_header';
1114 536
1115 - // Enqueue scripts for the forms page.
1116 - if ( $is_screen_sureforms_forms ) {
1117 - $asset_handle = '-forms';
1118 -
1119 - $script_asset_path = SRFM_DIR . 'assets/build/forms.asset.php';
1120 - $script_info = file_exists( $script_asset_path )
1121 - ? include $script_asset_path
1122 - : [
1123 - 'dependencies' => [],
1124 - 'version' => SRFM_VER,
1125 - ];
1126 -
1127 - wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/forms.js', $script_info['dependencies'], SRFM_VER, true );
1128 - wp_localize_script(
1129 - SRFM_SLUG . $asset_handle,
1130 - SRFM_SLUG . '_admin',
1131 - apply_filters(
1132 - SRFM_SLUG . '_admin_filter',
1133 - $localization_data
1134 - )
1135 - );
1136 - wp_enqueue_style( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/forms.css', [], SRFM_VER, 'all' );
1137 -
1138 - $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
1139 - }
1140 -
1141 - // Enqueue scripts for the SureMail promotional page.
1142 - $is_screen_sureforms_smtp = Helper::validate_request_context( 'sureforms_smtp', 'page' );
1143 - if ( $is_screen_sureforms_smtp ) {
1144 - $asset_handle = 'suremail';
1145 -
1146 537 $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1147 538 $script_info = file_exists( $script_asset_path )
1148 - ? include $script_asset_path
1149 - : [
1150 - 'dependencies' => [],
1151 - 'version' => SRFM_VER,
1152 - ];
1153 -
1154 - wp_enqueue_script( SRFM_SLUG . '-suremail', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1155 - wp_enqueue_style( SRFM_SLUG . '-suremail', SRFM_URL . 'assets/build/suremail.css', [], SRFM_VER, 'all' );
1156 -
1157 - // Localize script for SureMail page.
1158 - $suremail_localization_data = [
1159 - 'ajax_url' => admin_url( 'admin-ajax.php' ),
1160 - 'admin_url' => admin_url(),
1161 - 'suremail_url' => 'https://sureforms.com/suremail/',
1162 - 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
1163 - 'sfPluginManagerNonce' => wp_create_nonce( 'sf_plugin_manager_nonce' ),
1164 - 'suremail_status' => file_exists( WP_PLUGIN_DIR . '/suremails/suremails.php' )
1165 - ? ( is_plugin_active( 'suremails/suremails.php' ) ? 'active' : 'installed' )
1166 - : 'not_installed',
539 + ? include $script_asset_path
540 + : [
541 + 'dependencies' => [],
542 + 'version' => SRFM_VER,
1167 543 ];
544 + wp_enqueue_script( SRFM_SLUG . '-form-page-header', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
545 + wp_enqueue_style( SRFM_SLUG . '-form-archive-styles', $css_uri . 'form-archive-styles' . $file_prefix . $rtl . '.css', [], SRFM_VER );
1168 546
1169 - wp_localize_script(
1170 - SRFM_SLUG . '-suremail',
1171 - SRFM_SLUG . '_admin',
1172 - apply_filters(
1173 - SRFM_SLUG . '_suremail_admin_filter',
1174 - $suremail_localization_data
1175 - )
1176 - );
1177 -
1178 - $script_translations_handlers[] = SRFM_SLUG . '-suremail';
547 + $script_translations_handlers[] = SRFM_SLUG . '-form-page-header';
1179 548 }
1180 549
1181 - // Enqueue scripts for the Quiz empty state page (free users only).
1182 - if ( $is_screen_quiz_empty_state && ! Helper::has_pro() ) {
1183 - $asset_handle = 'quizEmptyState';
1184 -
1185 - $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1186 - $script_info = file_exists( $script_asset_path )
1187 - ? include $script_asset_path
1188 - : [
1189 - 'dependencies' => [],
1190 - 'version' => SRFM_VER,
1191 - ];
1192 -
1193 - wp_enqueue_script( SRFM_SLUG . '-quiz-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1194 - wp_enqueue_style( SRFM_SLUG . '-quiz-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.css', [], SRFM_VER, 'all' );
1195 -
1196 - $script_translations_handlers[] = SRFM_SLUG . '-quiz-empty-state';
1197 - }
1198 -
1199 - // Enqueue scripts for the Survey Reports empty state page (free users only).
1200 - if ( $is_screen_survey_empty_state && ! Helper::has_pro() ) {
1201 - $asset_handle = 'surveyEmptyState';
1202 -
1203 - $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1204 - $script_info = file_exists( $script_asset_path )
1205 - ? include $script_asset_path
1206 - : [
1207 - 'dependencies' => [],
1208 - 'version' => SRFM_VER,
1209 - ];
1210 -
1211 - wp_enqueue_script( SRFM_SLUG . '-survey-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1212 - wp_enqueue_style( SRFM_SLUG . '-survey-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.css', [], SRFM_VER, 'all' );
1213 -
1214 - $script_translations_handlers[] = SRFM_SLUG . '-survey-empty-state';
1215 - }
1216 -
1217 - // Enqueue scripts for the Partial Entries empty state page (free users only).
1218 - if ( $is_screen_partial_entries_empty_state && ! Helper::has_pro() ) {
1219 - $asset_handle = 'partialEntriesEmptyState';
1220 -
1221 - $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1222 - $script_info = file_exists( $script_asset_path )
1223 - ? include $script_asset_path
1224 - : [
1225 - 'dependencies' => [],
1226 - 'version' => SRFM_VER,
1227 - ];
1228 -
1229 - wp_enqueue_script( SRFM_SLUG . '-partial-entries-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1230 - wp_enqueue_style( SRFM_SLUG . '-partial-entries-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.css', [], SRFM_VER, 'all' );
1231 -
1232 - $script_translations_handlers[] = SRFM_SLUG . '-partial-entries-empty-state';
1233 - }
1234 -
1235 - // Admin Submenu Styles.
1236 - wp_enqueue_style( SRFM_SLUG . '-admin', $css_uri . 'backend/admin' . $file_prefix . $rtl . '.css', [], SRFM_VER );
1237 -
1238 550 if ( $is_screen_sureforms_form_settings ) {
1239 551 $asset_handle = 'settings';
1240 552
1241 553 $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
@@ -1246,22 +558,45 @@
1246 558 'version' => SRFM_VER,
1247 559 ];
1248 560
1249 561 wp_enqueue_script( SRFM_SLUG . '-settings', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
562 + wp_enqueue_style( SRFM_SLUG . '-setting-styles', SRFM_URL . 'assets/build/' . $asset_handle . '.css', [ 'wp-components' ], SRFM_VER, 'all' );
1250 563 wp_localize_script(
1251 564 SRFM_SLUG . '-settings',
1252 565 SRFM_SLUG . '_admin',
1253 - apply_filters(
1254 - SRFM_SLUG . '_admin_filter',
1255 - $localization_data
1256 - )
566 + $localization_data
1257 567 );
1258 568
1259 - // Enqueue Tailwind and Quill editor styles for the settings page.
1260 - wp_enqueue_style( SRFM_SLUG . '-settings-build', SRFM_URL . 'assets/build/settings.css', [], SRFM_VER, 'all' );
1261 - wp_enqueue_style( SRFM_SLUG . '-reactQuill', SRFM_URL . 'assets/css/minified/deps/quill/quill.snow.css', [], SRFM_VER );
569 + $script_translations_handlers[] = SRFM_SLUG . '-settings';
570 + }
571 + if ( 'edit-' . SRFM_FORMS_POST_TYPE === $current_screen->id ) {
572 + wp_enqueue_script( SRFM_SLUG . '-form-archive', $js_uri . 'form-archive' . $file_prefix . '.js', [], SRFM_VER, true );
573 + wp_enqueue_script( SRFM_SLUG . '-export', $js_uri . 'export' . $file_prefix . '.js', [ 'wp-i18n' ], SRFM_VER, true );
574 + wp_localize_script(
575 + SRFM_SLUG . '-export',
576 + SRFM_SLUG . '_export',
577 + [
578 + 'ajaxurl' => admin_url( 'admin-ajax.php' ),
579 + 'srfm_export_nonce' => wp_create_nonce( 'export_form_nonce' ),
580 + 'site_url' => get_site_url(),
581 + 'srfm_import_endpoint' => '/wp-json/sureforms/v1/sureforms_import',
582 + 'import_form_nonce' => current_user_can( 'edit_posts' ) ? wp_create_nonce( 'wp_rest' ) : '',
583 + 'import_btn_string' => __( 'Import Form', 'sureforms' ),
584 + ]
585 + );
1262 586
1263 - $script_translations_handlers[] = SRFM_SLUG . '-settings';
587 + wp_enqueue_script( SRFM_SLUG . '-backend', $js_uri . 'backend' . $file_prefix . '.js', [], SRFM_VER, true );
588 + wp_localize_script(
589 + SRFM_SLUG . '-backend',
590 + SRFM_SLUG . '_backend',
591 + [
592 + 'site_url' => get_site_url(),
593 + ]
594 + );
595 +
596 + $script_translations_handlers[] = SRFM_SLUG . '-form-archive';
597 + $script_translations_handlers[] = SRFM_SLUG . '-export';
598 + $script_translations_handlers[] = SRFM_SLUG . '-backend';
1264 599 }
1265 600
1266 601 if ( $is_screen_add_new_form ) {
1267 602 wp_enqueue_style( SRFM_SLUG . '-template-picker', $css_uri . 'template-picker' . $file_prefix . $rtl . '.css', [], SRFM_VER );
@@ -1282,18 +617,18 @@
1282 617 SRFM_SLUG . '_admin',
1283 618 [
1284 619 'site_url' => get_site_url(),
1285 620 'plugin_url' => SRFM_URL,
621 + 'preview_images_url' => SRFM_URL . 'images/template-previews/',
1286 622 'admin_url' => admin_url( 'admin.php' ),
1287 623 'new_template_picker_base_url' => admin_url( 'post-new.php?post_type=sureforms_form' ),
1288 - 'capability' => Helper::current_user_can(),
1289 - 'template_picker_nonce' => Helper::current_user_can() ? wp_create_nonce( 'wp_rest' ) : '',
1290 - 'is_pro_active' => Helper::has_pro(),
624 + 'capability' => current_user_can( 'edit_posts' ),
625 + 'template_picker_nonce' => current_user_can( 'edit_posts' ) ? wp_create_nonce( 'wp_rest' ) : '',
626 + 'is_pro_active' => defined( 'SRFM_PRO_VER' ),
1291 627 'srfm_ai_usage_details' => AI_Helper::get_current_usage_details(),
1292 628 'is_pro_license_active' => AI_Helper::is_pro_license_active(),
1293 629 'srfm_ai_auth_user_email' => get_option( 'srfm_ai_auth_user_email' ),
1294 630 'pricing_page_url' => Helper::get_sureforms_website_url( 'pricing' ),
1295 - 'licensing_nonce' => wp_create_nonce( 'srfm_pro_licensing_nonce' ),
1296 631 ]
1297 632 );
1298 633
1299 634 $script_translations_handlers[] = SRFM_SLUG . '-template-picker';
@@ -1308,9 +643,8 @@
1308 643 'srfm/checkbox',
1309 644 'srfm/number',
1310 645 'srfm/inline-button',
1311 646 'srfm/advanced-heading',
1312 - 'srfm/payment',
1313 647 ]
1314 648 );
1315 649 if ( ! is_array( $default_allowed_quick_sidebar_blocks ) ) {
1316 650 $default_allowed_quick_sidebar_blocks = [];
@@ -1322,25 +656,22 @@
1322 656 }
1323 657 $quick_sidebar_allowed_blocks = get_option( 'srfm_quick_sidebar_allowed_blocks' );
1324 658 $quick_sidebar_allowed_blocks = ! empty( $quick_sidebar_allowed_blocks ) && is_array( $quick_sidebar_allowed_blocks ) ? $quick_sidebar_allowed_blocks : $default_allowed_quick_sidebar_blocks;
1325 659 $srfm_ajax_nonce = wp_create_nonce( 'srfm_ajax_nonce' );
660 + wp_enqueue_script( SRFM_SLUG . '-quick-action-siderbar', SRFM_URL . 'assets/build/quickActionSidebar.js', [], SRFM_VER, true );
661 + wp_localize_script(
662 + SRFM_SLUG . '-quick-action-siderbar',
663 + SRFM_SLUG . '_quick_sidebar_blocks',
664 + [
665 + 'allowed_blocks' => $quick_sidebar_allowed_blocks,
666 + 'srfm_enable_quick_action_sidebar' => $srfm_enable_quick_action_sidebar,
667 + 'srfm_ajax_nonce' => $srfm_ajax_nonce,
668 + 'srfm_ajax_url' => admin_url( 'admin-ajax.php' ),
669 + ]
670 + );
1326 671
1327 - if ( Helper::is_sureforms_admin_page() ) {
1328 - wp_enqueue_script( SRFM_SLUG . '-quick-action-siderbar', SRFM_URL . 'assets/build/quickActionSidebar.js', [], SRFM_VER, true );
1329 - wp_localize_script(
1330 - SRFM_SLUG . '-quick-action-siderbar',
1331 - SRFM_SLUG . '_quick_sidebar_blocks',
1332 - [
1333 - 'allowed_blocks' => $quick_sidebar_allowed_blocks,
1334 - 'srfm_enable_quick_action_sidebar' => $srfm_enable_quick_action_sidebar,
1335 - 'srfm_ajax_nonce' => $srfm_ajax_nonce,
1336 - 'srfm_ajax_url' => admin_url( 'admin-ajax.php' ),
1337 - ]
1338 - );
672 + $script_translations_handlers[] = SRFM_SLUG . '-quick-action-siderbar';
1339 673
1340 - $script_translations_handlers[] = SRFM_SLUG . '-quick-action-siderbar';
1341 - }
1342 -
1343 674 /**
1344 675 * Enqueuing SureTriggers Integration script.
1345 676 * This script loads suretriggers iframe in Intergations tab.
1346 677 */
@@ -1412,53 +743,40 @@
1412 743
1413 744 return $status;
1414 745 }
1415 746
747 + // Entries methods.
748 +
1416 749 /**
1417 - * Register Pro compatibility notices early for React pages.
750 + * Handle entry actions.
1418 751 *
1419 - * This method runs on admin_init (priority 5) to ensure notices are
1420 - * registered BEFORE admin_enqueue_scripts, so they're available when
1421 - * wp_localize_script runs.
1422 - *
1423 - * Hooked - admin_init (priority 5)
1424 - *
752 + * @since 0.0.13
1425 753 * @return void
1426 - * @since 2.5.0
1427 754 */
1428 - public function register_pro_compatibility_notices() {
1429 - // Early exit if Pro is not active, user lacks permissions, or Notice_Manager is unavailable.
1430 - if ( ! Helper::has_pro() || ! Helper::current_user_can() || ! class_exists( 'SRFM\Admin\Notice_Manager' ) ) {
755 + public function handle_entry_actions() {
756 + Entries_List_Table::process_bulk_actions();
757 +
758 + if ( ! isset( $_GET['page'] ) || SRFM_ENTRIES !== $_GET['page'] ) {
1431 759 return;
1432 760 }
1433 -
1434 - // Register version outdated notice for React pages.
1435 - if ( ! version_compare( SRFM_PRO_VER, SRFM_PRO_RECOMMENDED_VER, '>=' ) ) {
1436 - $pro_plugin_name = defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro';
1437 - $react_outdated_message = sprintf(
1438 - // translators: %1$s: SureForms version, %2$s: SureForms Pro Plugin Name, %3$s: SureForms Pro Version.
1439 - esc_html__( 'SureForms %1$s requires minimum %2$s %3$s to work properly. Please update to the latest version.', 'sureforms' ),
1440 - esc_html( SRFM_VER ),
1441 - esc_html( $pro_plugin_name ),
1442 - esc_html( SRFM_PRO_RECOMMENDED_VER )
1443 - );
1444 -
1445 - \SRFM\Admin\Notice_Manager::register_notice(
1446 - [
1447 - 'id' => 'sureforms-pro-version-outdated',
1448 - 'variant' => 'warning',
1449 - 'message' => $react_outdated_message,
1450 - 'actions' => [
1451 - [
1452 - 'label' => esc_html__( 'Update Now', 'sureforms' ),
1453 - 'url' => admin_url( 'update-core.php' ),
1454 - 'variant' => 'primary',
1455 - ],
1456 - ],
1457 - 'pages' => [ 'all' ],
1458 - ]
1459 - );
761 + if ( ! isset( $_GET['entry_id'] ) || ! isset( $_GET['action'] ) ) {
762 + return;
1460 763 }
764 + if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'srfm_entries_action' ) ) {
765 + wp_die( esc_html__( 'Nonce verification failed.', 'sureforms' ) );
766 + }
767 + $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : '';
768 + $entry_id = Helper::get_integer_value( sanitize_text_field( wp_unslash( $_GET['entry_id'] ) ) );
769 + $view = isset( $_GET['view'] ) ? sanitize_text_field( wp_unslash( $_GET['view'] ) ) : '';
770 + if ( $entry_id > 0 ) {
771 + if ( 'read' === $action && 'details' === $view ) {
772 + $entry_status = Entries::get( $entry_id )['status'];
773 + if ( 'trash' === $entry_status ) {
774 + wp_die( esc_html__( 'You cannot view this entry because it is in trash.', 'sureforms' ) );
775 + }
776 + }
777 + Entries_List_Table::handle_entry_status( $entry_id, $action, $view );
778 + }
1461 779 }
1462 780
1463 781 /**
1464 782 * Admin Notice Callback if sureforms pro is out of date.
@@ -1468,9 +786,10 @@
1468 786 * @return void
1469 787 * @since 1.0.4
1470 788 */
1471 789 public function srfm_pro_version_compatibility() {
1472 - if ( ! Helper::has_pro() ) {
790 + $plugin_file = 'sureforms-pro/sureforms-pro.php';
791 + if ( ! is_plugin_active( $plugin_file ) || ! defined( 'SRFM_PRO_VER' ) ) {
1473 792 return;
1474 793 }
1475 794
1476 795 if ( empty( get_current_screen() ) ) {
@@ -1476,9 +795,9 @@
1476 795 if ( empty( get_current_screen() ) ) {
1477 796 return;
1478 797 }
1479 798
1480 - if ( ! Helper::current_user_can() ) {
799 + if ( ! current_user_can( 'update_plugins' ) ) {
1481 800 return;
1482 801 }
1483 802
1484 803 $srfm_pro_license_status = get_option( 'srfm_pro_license_status', '' );
@@ -1494,214 +813,36 @@
1494 813 $pro_plugin_name = defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro';
1495 814 $message = '';
1496 815 $url = admin_url( 'admin.php?page=sureforms_form_settings&tab=account-settings' );
1497 816 if ( 'unlicensed' === $srfm_pro_license_status ) {
1498 - ob_start();
1499 - ?>
1500 - <p>
1501 - <?php
1502 - printf(
1503 - // translators: %1$s: Opening anchor tag with URL, %2$s: Closing anchor tag, %3$s: SureForms Pro Plugin Name.
1504 - esc_html__( 'Please %1$sactivate%2$s your copy of %3$s to get new features, access support, receive update notifications, and more.', 'sureforms' ),
1505 - '<a href="' . esc_url( $url ) . '">',
1506 - '</a>',
1507 - '<i>' . esc_html( $pro_plugin_name ) . '</i>'
1508 - );
1509 - ?>
1510 - </p>
1511 - <?php
1512 - $message = ob_get_clean();
817 + $message = '<p>' . sprintf(
818 + // translators: %1$s: Opening anchor tag with URL, %2$s: Closing anchor tag, %3$s: SureForms Pro Plugin Name.
819 + esc_html__( 'Please %1$sactivate%2$s your copy of %3$s to get new features, access support, receive update notifications, and more.', 'sureforms' ),
820 + '<a href="' . esc_url( $url ) . '">',
821 + '</a>',
822 + '<i>' . esc_html( $pro_plugin_name ) . '</i>'
823 + ) . '</p>';
1513 824 }
1514 825
1515 826 if ( ! version_compare( SRFM_PRO_VER, SRFM_PRO_RECOMMENDED_VER, '>=' ) ) {
1516 - ob_start();
1517 - ?>
1518 - <p>
1519 - <?php
1520 - printf(
1521 - // 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.
1522 - 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' ),
1523 - esc_html( SRFM_VER ),
1524 - esc_html( $pro_plugin_name ),
1525 - esc_html( SRFM_PRO_RECOMMENDED_VER ),
1526 - '<a href="' . esc_url( admin_url( 'update-core.php' ) ) . '">',
1527 - '</a>'
1528 - );
1529 - ?>
1530 - </p>
1531 - <?php
1532 - $message .= ob_get_clean();
827 + $message .= '<p>' . sprintf(
828 + // 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.
829 + 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' ),
830 + esc_html( SRFM_VER ),
831 + esc_html( $pro_plugin_name ),
832 + esc_html( SRFM_PRO_RECOMMENDED_VER ),
833 + '<a href=' . esc_url( admin_url( 'update-core.php' ) ) . '>',
834 + '</a>'
835 + ) . '</p>';
1533 836 }
1534 837
1535 838 if ( ! empty( $message ) ) {
1536 839 // Phpcs ignore comment is required as $message variable is already escaped.
1537 - ?>
1538 - <div class="notice notice-warning"><?php echo wp_kses_post( $message ); ?></div>
1539 - <?php
840 + echo '<div class="notice notice-warning">' . wp_kses_post( $message ) . '</div>';
1540 841 }
1541 842 }
1542 843
1543 844 /**
1544 - * Display a notice to the user about providing a review.
1545 - *
1546 - * @since 2.5.2
1547 - * @return void
1548 - */
1549 - public function display_srfm_rating_notice() {
1550 - // Only show to admins.
1551 - if ( ! Helper::current_user_can() ) {
1552 - return;
1553 - }
1554 -
1555 - // Allow the notice to be disabled.
1556 - if ( ! apply_filters( 'srfm_show_rating_notice', true ) ) {
1557 - return;
1558 - }
1559 -
1560 - Astra_Notices::add_notice(
1561 - [
1562 - 'id' => 'srfm-plugin-review-notice',
1563 - 'type' => '',
1564 - 'message' => $this->build_notice_markup(
1565 - esc_html__( 'Amazing! SureForms is powering your forms and submissions - let\'s keep growing together!', 'sureforms' ),
1566 - esc_html__( 'If SureForms has been helpful, would you mind taking a moment to leave a 5-star review on WordPress.org?', 'sureforms' ),
1567 - esc_url( 'https://wordpress.org/support/plugin/sureforms/reviews/?filter=5#new-post' ),
1568 - esc_html__( 'Rate SureForms', 'sureforms' ),
1569 - esc_html__( 'Maybe later', 'sureforms' ),
1570 - esc_html__( 'I already did', 'sureforms' ),
1571 - WEEK_IN_SECONDS,
1572 - true
1573 - ),
1574 - 'repeat-notice-after' => WEEK_IN_SECONDS,
1575 - 'show_if' => $this->maybe_display_rating_notice(),
1576 - 'display-with-other-notices' => true,
1577 - ]
1578 - );
1579 -
1580 - add_action( 'astra_notice_after_markup_srfm-plugin-review-notice', [ $this, 'enqueue_notice_response_script' ] );
1581 - }
1582 -
1583 - /**
1584 - * Display a "Getting Started" admin notice for new users who haven't yet
1585 - * reached the rating-notice milestone (3+ forms or 3+ entries).
1586 - *
1587 - * The Astra Notices library handles the 7-day delay via the
1588 - * `display-notice-after` parameter.
1589 - *
1590 - * @since 2.5.2
1591 - * @return void
1592 - */
1593 - public function display_srfm_getting_started_notice() {
1594 - // Only show to admins.
1595 - if ( ! Helper::current_user_can() ) {
1596 - return;
1597 - }
1598 -
1599 - // Allow the notice to be disabled programmatically.
1600 - if ( ! apply_filters( 'srfm_show_getting_started_notice', true ) ) {
1601 - return;
1602 - }
1603 -
1604 - Astra_Notices::add_notice(
1605 - [
1606 - 'id' => 'srfm-getting-started-notice',
1607 - 'type' => '',
1608 - 'message' => $this->build_notice_markup(
1609 - esc_html__( 'SureForms is ready to power your forms — explore what\'s possible!', 'sureforms' ),
1610 - esc_html__( 'Manage your forms, track submissions, and discover features like AI Form Builder, payment integrations, and more from the SureForms dashboard.', 'sureforms' ),
1611 - esc_url( admin_url( 'admin.php?page=sureforms_menu' ) ),
1612 - esc_html__( 'Go to Dashboard', 'sureforms' ),
1613 - esc_html__( 'Maybe later', 'sureforms' ),
1614 - esc_html__( 'I already know', 'sureforms' ),
1615 - WEEK_IN_SECONDS
1616 - ),
1617 - 'repeat-notice-after' => WEEK_IN_SECONDS,
1618 - 'show_if' => ! $this->maybe_display_rating_notice(),
1619 - 'display-notice-after' => WEEK_IN_SECONDS,
1620 - 'display-with-other-notices' => true,
1621 - ]
1622 - );
1623 -
1624 - add_action( 'astra_notice_after_markup_srfm-getting-started-notice', [ $this, 'enqueue_notice_response_script' ] );
1625 - }
1626 -
1627 - /**
1628 - * Enqueue the notice response analytics script.
1629 - *
1630 - * Called via the astra_notice_after_markup_{id} hook so the script
1631 - * only loads when a SureForms notice is actually rendered.
1632 - *
1633 - * @since 2.5.2
1634 - * @return void
1635 - */
1636 - public function enqueue_notice_response_script() {
1637 - if ( wp_script_is( 'srfm-notice-response', 'enqueued' ) ) {
1638 - return;
1639 - }
1640 -
1641 - wp_enqueue_script(
1642 - 'srfm-notice-response',
1643 - SRFM_URL . 'admin/assets/js/notice-response.js',
1644 - [],
1645 - SRFM_VER,
1646 - true
1647 - );
1648 -
1649 - wp_localize_script(
1650 - 'srfm-notice-response',
1651 - 'srfmNoticeResponse',
1652 - [
1653 - 'ajaxurl' => admin_url( 'admin-ajax.php' ),
1654 - 'nonce' => wp_create_nonce( 'srfm_notice_response' ),
1655 - ]
1656 - );
1657 - }
1658 -
1659 - /**
1660 - * Handle the notice response AJAX request.
1661 - *
1662 - * Validates the request and records the analytics event
1663 - * for the notice button that was clicked.
1664 - *
1665 - * @since 2.5.2
1666 - * @return void
1667 - */
1668 - public function handle_notice_response() {
1669 - if ( ! check_ajax_referer( 'srfm_notice_response', 'nonce', false ) ) {
1670 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1671 - }
1672 -
1673 - if ( ! Helper::current_user_can() ) {
1674 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1675 - }
1676 -
1677 - $notice_id = isset( $_POST['notice_id'] ) ? sanitize_text_field( wp_unslash( $_POST['notice_id'] ) ) : '';
1678 - $button = isset( $_POST['button'] ) ? sanitize_text_field( wp_unslash( $_POST['button'] ) ) : '';
1679 -
1680 - $valid = [
1681 - 'srfm-getting-started-notice' => [
1682 - 'go_to_dashboard' => 'getting_started_notice_cta',
1683 - 'maybe_later' => 'getting_started_notice_snooze',
1684 - 'dismissed' => 'getting_started_notice_dismiss',
1685 - ],
1686 - 'srfm-plugin-review-notice' => [
1687 - 'rate_sureforms' => 'rating_notice_cta',
1688 - 'maybe_later' => 'rating_notice_snooze',
1689 - 'dismissed' => 'rating_notice_dismiss',
1690 - ],
1691 - ];
1692 -
1693 - if ( ! isset( $valid[ $notice_id ][ $button ] ) ) {
1694 - wp_send_json_error( [ 'message' => __( 'Invalid parameters.', 'sureforms' ) ], 400 );
1695 - }
1696 -
1697 - $event_name = $valid[ $notice_id ][ $button ];
1698 - Analytics::events()->track( $event_name, $button );
1699 -
1700 - wp_send_json_success();
1701 - }
1702 -
1703 - /**
1704 845 * Disables the capabilities for WPForms to avoid conflicts when enqueueing
1705 846 * scripts and styles for WPForms.
1706 847 *
1707 848 * This function is intended to prevent any potential conflicts that may arise
@@ -1722,391 +863,5 @@
1722 863 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1723 864 $post_type = $post_id ? get_post_type( $post_id ) : sanitize_text_field( wp_unslash( $_REQUEST['post_type'] ?? '' ) );
1724 865 return SRFM_FORMS_POST_TYPE === $post_type ? false : $user_can;
1725 866 }
1726 -
1727 - /**
1728 - * Enqueueus the admin pointer script and styles.
1729 - *
1730 - * @return void
1731 - * @since 1.8.0
1732 - */
1733 - public function enqueue_admin_pointer() {
1734 - if ( ! $this->is_admin_pointer_visible() ) {
1735 - return;
1736 - }
1737 - wp_enqueue_style( 'wp-pointer' );
1738 - wp_enqueue_script( 'wp-pointer' );
1739 - wp_enqueue_script(
1740 - 'sureforms-admin-pointer',
1741 - plugins_url( 'admin/assets/js/sureforms-pointer.js', SRFM_FILE ),
1742 - [ 'wp-pointer', 'jquery' ],
1743 - SRFM_VER,
1744 - true
1745 - );
1746 - wp_localize_script(
1747 - 'sureforms-admin-pointer',
1748 - 'sureformsPointerData',
1749 - [
1750 - 'ajaxurl' => admin_url( 'admin-ajax.php' ),
1751 - 'pointer_nonce' => wp_create_nonce( 'sureforms_pointer_action' ),
1752 - ]
1753 - );
1754 - }
1755 -
1756 - /**
1757 - * Ajax handler for pointer popup visibility.
1758 - *
1759 - * @return void
1760 - * @since 1.8.0
1761 - */
1762 - public function pointer_should_show() {
1763 - // Security: Check user capability.
1764 - if ( ! Helper::current_user_can() ) {
1765 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1766 - }
1767 - // Security: Nonce check.
1768 - if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1769 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1770 - }
1771 -
1772 - $content_markup = sprintf(
1773 - /* translators: 1: opening span, 2: opening strong (inline), 3: closing strong, 4: closing span, 5: opening strong (block), 6: closing strong */
1774 - __( '%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' ),
1775 - '<span>',
1776 - '<strong>',
1777 - '</strong>',
1778 - '</span><br/>',
1779 - '<strong style="font-size:1.1em;">',
1780 - '</strong>'
1781 - );
1782 - wp_send_json(
1783 - [
1784 - 'show' => true,
1785 - 'title' => esc_html( __( 'SureForms is waiting for you!', 'sureforms' ) ),
1786 - 'content' => wp_kses_post( $content_markup ),
1787 - 'button_text' => esc_html( __( 'Build My First Form', 'sureforms' ) ),
1788 - 'dismiss' => esc_html( __( 'Dismiss', 'sureforms' ) ),
1789 - 'button_url' => admin_url( 'admin.php?page=add-new-form' ),
1790 - ]
1791 - );
1792 - }
1793 -
1794 - /**
1795 - * Ajax callback for pointer popup dismissed action.
1796 - *
1797 - * @return void
1798 - * @since 1.8.0
1799 - */
1800 - public function pointer_dismissed() {
1801 - // Security: Check user capability.
1802 - if ( ! Helper::current_user_can() ) {
1803 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1804 - }
1805 - // Security: Nonce check.
1806 - if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1807 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1808 - }
1809 - // Use Helper to update srfm_options key.
1810 - Helper::update_srfm_option( 'pointer_popup_dismissed', time() );
1811 -
1812 - wp_send_json_success();
1813 - }
1814 -
1815 - /**
1816 - * Ajax pointer accepted CTA callback.
1817 - *
1818 - * @return void
1819 - * @since 1.8.0
1820 - */
1821 - public function pointer_accepted_cta() {
1822 - // Security: Check user capability.
1823 - if ( ! Helper::current_user_can() ) {
1824 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1825 - }
1826 - // Security: Nonce check.
1827 - if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1828 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1829 - }
1830 - // Use Helper to update srfm_options key.
1831 - Helper::update_srfm_option( 'pointer_popup_accepted', time() );
1832 -
1833 - wp_send_json_success();
1834 - }
1835 -
1836 - /**
1837 - * Maybe register the dashboard widget based on entries.
1838 - *
1839 - * @return void
1840 - * @since 1.9.1
1841 - */
1842 - public function maybe_register_dashboard_widget() {
1843 -
1844 - // Only for users with manage_options capability.
1845 - if ( ! Helper::current_user_can() ) {
1846 - return;
1847 - }
1848 -
1849 - // Quick check if there are any entries in the last 7 days.
1850 - $seven_days_ago = strtotime( '-7 days' );
1851 - $total_entries = Entries::get_entries_count_after( $seven_days_ago );
1852 -
1853 - // Only add the dashboard setup hook if there are entries.
1854 - if ( $total_entries > 0 ) {
1855 - // Get forms with entries (limit 4 for dashboard widget).
1856 - $this->dashboard_widget_data = Helper::get_forms_with_entry_counts( $seven_days_ago, 4 );
1857 -
1858 - // Only show dashboard widget if there are forms with entries.
1859 - if ( ! empty( $this->dashboard_widget_data ) ) {
1860 - add_action( 'wp_dashboard_setup', [ $this, 'register_dashboard_widget' ] );
1861 - }
1862 - }
1863 - }
1864 -
1865 - /**
1866 - * Register the dashboard widget.
1867 - *
1868 - * @return void
1869 - * @since 1.9.1
1870 - */
1871 - public function register_dashboard_widget() {
1872 - // Add the widget with high priority to position it at the top.
1873 - wp_add_dashboard_widget(
1874 - 'sureforms_recent_entries',
1875 - __( 'SureForms', 'sureforms' ),
1876 - [ $this, 'render_dashboard_widget' ],
1877 - null,
1878 - null,
1879 - 'normal',
1880 - 'high'
1881 - );
1882 - }
1883 -
1884 - /**
1885 - * Render the dashboard widget content.
1886 - *
1887 - * @return void
1888 - * @since 1.9.1
1889 - */
1890 - public function render_dashboard_widget() {
1891 - // Use the pre-fetched data to avoid duplicate queries.
1892 - $entries_data = $this->dashboard_widget_data;
1893 -
1894 - // Display the widget content.
1895 - ?>
1896 - <div class="srfm-dashboard-widget">
1897 - <div class="srfm-widget-header">
1898 - <h3 class="srfm-widget-title">
1899 - <?php esc_html_e( 'Recent Entries', 'sureforms' ); ?>
1900 - <span class="srfm-widget-subtitle"><?php esc_html_e( '( Last 7 days )', 'sureforms' ); ?></span>
1901 - </h3>
1902 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=sureforms_entries' ) ); ?>" class="srfm-widget-view-link">
1903 - <?php esc_html_e( 'View', 'sureforms' ); ?>
1904 - </a>
1905 - </div>
1906 -
1907 - <div class="srfm-table-wrapper">
1908 - <table class="srfm-entries-table">
1909 - <thead>
1910 - <tr>
1911 - <th><?php esc_html_e( 'Form Name', 'sureforms' ); ?></th>
1912 - <th><?php esc_html_e( 'Entries', 'sureforms' ); ?></th>
1913 - </tr>
1914 - </thead>
1915 - <tbody>
1916 - <?php foreach ( $entries_data as $form_data ) { ?>
1917 - <tr>
1918 - <td class="form-name"><?php echo esc_html( $form_data['title'] ); ?></td>
1919 - <td class="entry-count"><?php echo esc_html( $form_data['count'] ); ?></td>
1920 - </tr>
1921 - <?php } ?>
1922 - </tbody>
1923 - </table>
1924 - </div>
1925 -
1926 - <?php
1927 - // Render footer if applicable.
1928 - $this->render_dashboard_widget_footer( $entries_data );
1929 - ?>
1930 - </div>
1931 - <?php
1932 - }
1933 -
1934 - /**
1935 - * Build the shared HTML markup for admin notices.
1936 - *
1937 - * @since 2.5.2
1938 - *
1939 - * All text parameters must be pre-escaped by the caller (e.g. via esc_html__()).
1940 - * URL parameters must be pre-escaped via esc_url().
1941 - *
1942 - * @param string $heading The notice heading text (pre-escaped).
1943 - * @param string $message The notice body text (pre-escaped).
1944 - * @param string $cta_url The primary CTA URL (pre-escaped).
1945 - * @param string $cta_text The primary CTA button text (pre-escaped).
1946 - * @param string $snooze_text The snooze button text (pre-escaped).
1947 - * @param string $dismiss_text The dismiss button text (pre-escaped).
1948 - * @param int $snooze_duration Snooze duration in seconds for the data-repeat-notice-after attribute.
1949 - * @param bool $external_cta Whether the CTA opens in a new tab and also dismisses the notice
1950 - * via the astra-notice-close class. Default false.
1951 - * @return string The notice HTML markup.
1952 - */
1953 - private function build_notice_markup( $heading, $message, $cta_url, $cta_text, $snooze_text, $dismiss_text, $snooze_duration, $external_cta = false ) {
1954 - $image_path = esc_url( SRFM_URL . 'admin/assets/sureforms-logo.png' );
1955 - $cta_class = $external_cta ? 'astra-notice-close button-primary' : 'button-primary';
1956 - $cta_attrs = $external_cta ? ' target="_blank" rel="noopener noreferrer"' : '';
1957 -
1958 - return sprintf(
1959 - '<div class="notice-image">
1960 - <img src="%1$s" class="custom-logo" alt="SureForms" itemprop="logo">
1961 - </div>
1962 - <div class="notice-content">
1963 - <div class="notice-heading">
1964 - %2$s
1965 - </div>
1966 - %3$s<br />
1967 - <div class="astra-review-notice-container">
1968 - <a href="%4$s" class="%5$s"%6$s>
1969 - %7$s
1970 - </a>
1971 - <span class="dashicons dashicons-clock" aria-hidden="true"></span>
1972 - <a href="#" data-repeat-notice-after="%8$s" class="astra-notice-close">
1973 - %9$s
1974 - </a>
1975 - <span class="dashicons dashicons-smiley" aria-hidden="true"></span>
1976 - <a href="#" class="astra-notice-close">
1977 - %10$s
1978 - </a>
1979 - </div>
1980 - </div>',
1981 - $image_path,
1982 - $heading,
1983 - $message,
1984 - $cta_url,
1985 - esc_attr( $cta_class ),
1986 - $cta_attrs,
1987 - $cta_text,
1988 - $snooze_duration,
1989 - $snooze_text,
1990 - $dismiss_text
1991 - );
1992 - }
1993 -
1994 - /**
1995 - * Callback for displaying the rating notice conditionally.
1996 - *
1997 - * Returns true if the user has 3 or more published forms or 3 or more form entries.
1998 - *
1999 - * @since 2.5.2
2000 - * @return bool
2001 - */
2002 - private function maybe_display_rating_notice() {
2003 - if ( null === $this->should_show_rating ) {
2004 - $entries_count = Entries::get_total_entries_by_status( 'all' );
2005 - $form_count = wp_count_posts( SRFM_FORMS_POST_TYPE );
2006 - $this->should_show_rating = $entries_count >= self::RATING_NOTICE_THRESHOLD || Helper::get_integer_value( $form_count->publish ?? 0 ) >= self::RATING_NOTICE_THRESHOLD;
2007 - }
2008 -
2009 - return $this->should_show_rating;
2010 - }
2011 -
2012 - /**
2013 - * Get random premium feature text.
2014 - *
2015 - * @return string Random feature text.
2016 - * @since 1.9.1
2017 - */
2018 - private function get_random_premium_feature_text() {
2019 - $features = [
2020 - __( 'Use Conditional Logic to show only what matters', 'sureforms' ),
2021 - __( 'Split your form into steps to keep it easy', 'sureforms' ),
2022 - __( 'Let people upload files directly to your form', 'sureforms' ),
2023 - __( 'Turn responses into downloadable PDFs automatically', 'sureforms' ),
2024 - __( 'Let users sign with a simple signature field', 'sureforms' ),
2025 - __( 'Connect your form to other tools using webhooks', 'sureforms' ),
2026 - __( 'Use Conversational Forms for a chat-like experience', 'sureforms' ),
2027 - __( 'Let users register or log in through your form', 'sureforms' ),
2028 - __( 'Build forms that create WordPress user accounts', 'sureforms' ),
2029 - __( 'Add calculations to auto-total scores or prices', 'sureforms' ),
2030 - ];
2031 -
2032 - // Get a random feature.
2033 - $random_key = array_rand( $features );
2034 - return $features[ $random_key ];
2035 - }
2036 -
2037 - /**
2038 - * Render the dashboard widget footer for upsell.
2039 - *
2040 - * @param array $entries_data The entries data array.
2041 - * @return void
2042 - * @since 1.9.1
2043 - */
2044 - private function render_dashboard_widget_footer( $entries_data ) {
2045 - // Only show footer if Pro is not active.
2046 - if ( Helper::has_pro() ) {
2047 - return;
2048 - }
2049 -
2050 - // Count total entries in last 7 days.
2051 - $total_entries = 0;
2052 - foreach ( $entries_data as $form_data ) {
2053 - $total_entries += $form_data['count'];
2054 - }
2055 -
2056 - // Count total published forms.
2057 - $published_forms_count = wp_count_posts( SRFM_FORMS_POST_TYPE )->publish;
2058 -
2059 - // Show footer only if 3+ entries received OR 3+ forms published.
2060 - if ( $total_entries >= 3 || $published_forms_count >= 3 ) {
2061 - ?>
2062 - <div class="srfm-widget-footer">
2063 - <div class="srfm-upgrade-content">
2064 - <svg class="srfm-logo-icon" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2065 - <rect width="20" height="20" fill="#D54407"/>
2066 - <path d="M5.7139 4.2854H14.2853V7.1425H7.1424L5.7139 8.5711V7.1425V4.2854Z" fill="white"/>
2067 - <path d="M5.7139 4.2854H14.2853V7.1425H7.1424L5.7139 8.5711V7.1425V4.2854Z" fill="white"/>
2068 - <path d="M5.7148 8.5713H12.8577V11.4284H7.1434L5.7148 12.857V11.4284V8.5713Z" fill="white"/>
2069 - <path d="M5.7148 8.5713H12.8577V11.4284H7.1434L5.7148 12.857V11.4284V8.5713Z" fill="white"/>
2070 - <path d="M5.7148 12.8569H10.0006V15.7141H5.7148V12.8569Z" fill="white"/>
2071 - <path d="M5.7148 12.8569H10.0006V15.7141H5.7148V12.8569Z" fill="white"/>
2072 - </svg>
2073 - <span><?php echo esc_html( $this->get_random_premium_feature_text() ); ?></span>
2074 - </div>
2075 - <?php
2076 - $upgrade_url = Helper::get_sureforms_website_url( 'pricing', [ 'utm_medium' => 'dashboard-widget' ] );
2077 - ?>
2078 - <a href="<?php echo esc_url( $upgrade_url ); ?>" class="srfm-upgrade-link" target="_blank">
2079 - <?php esc_html_e( 'Upgrade', 'sureforms' ); ?>
2080 - </a>
2081 - </div>
2082 - <?php
2083 - }
2084 - }
2085 -
2086 - /**
2087 - * Determine if the admin pointer should be visible on this page.
2088 - *
2089 - * @since 1.8.0
2090 - * @return bool
2091 - */
2092 - private function is_admin_pointer_visible() {
2093 - global $pagenow;
2094 - $allowed_pages = [ 'index.php', 'options-general.php' ];
2095 -
2096 - // Do not show if pointer dismissed, accepted, or more than 1 form exists.
2097 - if (
2098 - ! empty( Helper::get_srfm_option( 'pointer_popup_dismissed' ) )
2099 - || ! empty( Helper::get_srfm_option( 'pointer_popup_accepted' ) )
2100 - || (int) ( wp_count_posts( SRFM_FORMS_POST_TYPE )->publish ?? 0 ) > 1
2101 - ) {
2102 - return false;
2103 - }
2104 -
2105 - if ( in_array( $pagenow, $allowed_pages, true ) ) {
2106 - return true;
2107 - }
2108 -
2109 - return false;
2110 - }
2111 -
2112 867 }