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