PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 1.5.0
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v1.5.0
2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 0.0.2 0.0.3 All 96 releases
← All changes | admin/admin.php +197 -1575 2.11.01.5.0 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,211 +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 -
132 - /**
133 - * Suppress foreign (third-party) admin notices on SureForms admin screens.
134 - *
135 - * Some plugins (e.g. Ninja Forms) print large promotional banners on every
136 - * admin page via the admin_notices / all_admin_notices / network_admin_notices
137 - * hooks. These bleed onto SureForms' own React admin screens and break the UI.
138 - * We run at the EARLIEST priority on each notice hook (all third-party
139 - * callbacks are registered before these hooks fire, during admin_init /
140 - * plugin load) and strip the foreign ones before they are echoed, while
141 - * preserving SureForms' own notices. Scoped strictly to SureForms screens.
142 - */
143 - add_action( 'admin_notices', [ $this, 'suppress_foreign_admin_notices' ], PHP_INT_MIN );
144 - add_action( 'all_admin_notices', [ $this, 'suppress_foreign_admin_notices' ], PHP_INT_MIN );
145 - add_action( 'network_admin_notices', [ $this, 'suppress_foreign_admin_notices' ], PHP_INT_MIN );
146 70 }
147 71
148 72 /**
149 - * Remove third-party admin notices on SureForms admin screens.
150 - *
151 - * Iterates over the callbacks registered on the admin notice hooks and
152 - * removes any that are not owned by SureForms. A callback is considered
153 - * owned by SureForms when it belongs to a class in the `SRFM` / `SRFM_PRO`
154 - * namespaces or to the bundled `BSF_Admin_Notices` / `Astra_Notices`
155 - * notices library. SureForms' own notices are therefore preserved while
156 - * foreign promotional banners are suppressed.
157 - *
158 - * This callback is hooked at `PHP_INT_MIN` so that it runs first on each
159 - * notice hook and removes the foreign callbacks before WordPress echoes
160 - * them (WP_Hook honours removals made during iteration). It is strictly
161 - * scoped to SureForms admin screens via {@see Helper::is_sureforms_admin_page()}
162 - * so no other admin page is affected.
163 - *
164 - * @since 2.10.0
165 - * @return void
166 - */
167 - public function suppress_foreign_admin_notices() {
168 - // Bail early if we are not on a SureForms admin screen. This keeps the
169 - // suppression strictly scoped and avoids touching any other admin page.
170 - // is_sureforms_admin_page() covers the core screens (dashboard, add-new,
171 - // settings, entries, the form CPT); we additionally match any admin page
172 - // whose `page` slug is SureForms-owned (sureforms_* / srfm_*) so the
173 - // suppression also applies to the payments/quiz/survey/learn/SMTP screens.
174 - if ( ! Helper::is_sureforms_admin_page() && ! $this->is_sureforms_owned_admin_page() ) {
175 - return;
176 - }
177 -
178 - global $wp_filter;
179 -
180 - // The hook currently being fired (admin_notices, all_admin_notices or network_admin_notices).
181 - $current_hook = current_action();
182 -
183 - if ( empty( $current_hook ) || empty( $wp_filter[ $current_hook ] ) || ! ( $wp_filter[ $current_hook ] instanceof \WP_Hook ) ) {
184 - return;
185 - }
186 -
187 - foreach ( $wp_filter[ $current_hook ]->callbacks as $priority => $callbacks ) {
188 - foreach ( $callbacks as $callback ) {
189 - $function = $callback['function'] ?? null;
190 -
191 - // Never remove our own suppression callback.
192 - if ( is_array( $function ) && isset( $function[0] ) && $function[0] === $this && 'suppress_foreign_admin_notices' === $function[1] ) {
193 - continue;
194 - }
195 -
196 - // Preserve SureForms-owned notices, remove everything else.
197 - if ( $this->is_sureforms_owned_notice_callback( $function ) ) {
198 - continue;
199 - }
200 -
201 - remove_action( $current_hook, $function, $priority );
202 - }
203 - }
204 - }
205 -
206 - /**
207 - * Get the first form creation time stamp.
208 - *
209 - * @since 1.10.1
210 - * @return int|false
211 - */
212 - public static function get_first_form_creation_time_stamp() {
213 - return Helper::get_srfm_option( 'first_form_created_at', false );
214 - }
215 -
216 - /**
217 - * Check if the first form has been created.
218 - *
219 - * @since 1.10.1
220 - * @return bool
221 - */
222 - public static function is_first_form_created() {
223 - // Convert the first form creation time stamp to a boolean. If it exists, it will return true, otherwise false.
224 - $first_form_creation_time_stamp = self::get_first_form_creation_time_stamp();
225 -
226 - // If the first form creation time stamp is not set, return false.
227 - if ( ! $first_form_creation_time_stamp ) {
228 - return false; // No forms created yet.
229 - }
230 -
231 - // Check if the first form creation time stamp is a valid integer and greater than zero.
232 - return is_int( $first_form_creation_time_stamp ) && $first_form_creation_time_stamp > 0;
233 - }
234 -
235 - /**
236 - * Check and save the first form creation time stamp.
237 - * If not already saved.
238 - *
239 - * @since 1.10.1
240 - * @return void
241 - */
242 - public static function save_first_form_creation_time_stamp() {
243 - if ( ! Helper::current_user_can() || self::is_first_form_created() || ! defined( 'SRFM_FORMS_POST_TYPE' ) || ! post_type_exists( SRFM_FORMS_POST_TYPE ) ) {
244 - return;
245 - }
246 -
247 - // Get the first form creation time from the database that is published.
248 - $query = new \WP_Query(
249 - [
250 - 'post_type' => SRFM_FORMS_POST_TYPE,
251 - 'posts_per_page' => 1,
252 - 'orderby' => 'date',
253 - 'order' => 'ASC',
254 - 'fields' => 'ids',
255 - 'post_status' => 'publish',
256 - ]
257 - );
258 -
259 - if ( ! empty( $query->posts ) && isset( $query->posts[0] ) ) {
260 - // Get the first post from the query result.
261 - $post_id = $query->posts[0];
262 - // Get the post creation time in GMT.
263 - $creation_time = get_post_field( 'post_date_gmt', $post_id );
264 - // Convert the creation time to a timestamp.
265 - $timestamp = strtotime( $creation_time );
266 -
267 - if ( ! $timestamp ) {
268 - return;
269 - }
270 -
271 - Helper::update_srfm_option( 'first_form_created_at', $timestamp );
272 - }
273 - }
274 -
275 - /**
276 - * Check if n days have passed since the first form creation.
277 - * This is used to determine if the dynamic nudges should be shown.
278 - *
279 - * @param int $days Number of days to check.
280 - * @since 1.10.1
281 - * @return bool
282 - */
283 - public static function check_first_form_creation_threshold( $days = 3 ) {
284 - $first_form_creation_time_stamp = self::get_first_form_creation_time_stamp();
285 -
286 - if ( ! $first_form_creation_time_stamp ) {
287 - return false; // No forms created yet.
288 - }
289 -
290 - /**
291 - * Calculate the number of days since the first form was created.
292 - */
293 - $days_from_creation = ( strtotime( current_time( 'mysql' ) ) - $first_form_creation_time_stamp ) / DAY_IN_SECONDS;
294 -
295 - // Return a boolean indicating if the number of days since creation is greater than the specified days.
296 - return $days_from_creation > $days;
297 - }
298 -
299 - /**
300 73 * Show action on plugin page.
301 74 *
302 75 * @param array $links links.
303 76 * @return array
@@ -303,19 +76,17 @@
303 76 * @return array
304 77 * @since 1.4.2
305 78 */
306 79 public function add_action_links( $links ) {
307 - if ( ! Helper::has_pro() ) {
80 + if ( ! defined( 'SRFM_PRO_FILE' ) && ! file_exists( WP_PLUGIN_DIR . '/sureforms-pro/sureforms-pro.php' ) ) {
308 81 // Display upsell link if SureForms Pro is not installed.
309 - $upsell_link = Helper::get_sureforms_website_url( 'pricing', [ 'utm_medium' => 'plugin-list' ] );
310 -
311 - ob_start();
312 - ?>
313 - <a href="<?php echo esc_url( $upsell_link ); ?>" target="_blank" rel="noreferrer" class="sureforms-plugins-go-pro">
314 - <?php echo esc_html__( 'Get SureForms Pro', 'sureforms' ); ?>
315 - </a>
316 - <?php
317 - $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>';
318 89 }
319 90
320 91 return $links;
321 92 }
@@ -383,15 +154,20 @@
383 154 * @return void
384 155 * @since 0.0.1
385 156 */
386 157 public function add_menu_page() {
387 - $menu_slug = 'sureforms_menu';
158 + if ( ! current_user_can( 'manage_options' ) ) {
159 + return;
160 + }
388 161
162 + $capability = 'manage_options';
163 + $menu_slug = 'sureforms_menu';
164 +
389 165 $logo = file_get_contents( plugin_dir_path( SRFM_FILE ) . 'images/icon.svg' );
390 166 add_menu_page(
391 167 __( 'SureForms', 'sureforms' ),
392 168 __( 'SureForms', 'sureforms' ),
393 - self::$sureforms_page_default_capability,
169 + 'edit_others_posts',
394 170 $menu_slug,
395 171 static function () {
396 172 },
397 173 'data:image/svg+xml;base64,' . base64_encode( $logo ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
@@ -402,9 +178,9 @@
402 178 add_submenu_page(
403 179 $menu_slug,
404 180 __( 'Dashboard', 'sureforms' ),
405 181 __( 'Dashboard', 'sureforms' ),
406 - self::$sureforms_page_default_capability,
182 + $capability,
407 183 $menu_slug,
408 184 [ $this, 'render_dashboard' ]
409 185 );
410 186 }
@@ -420,9 +196,9 @@
420 196 add_submenu_page(
421 197 'sureforms_menu',
422 198 __( 'Settings', 'sureforms' ),
423 199 __( 'Settings', 'sureforms' ),
424 - self::$sureforms_page_default_capability,
200 + 'edit_others_posts',
425 201 'sureforms_form_settings',
426 202 $callback
427 203 );
428 204
@@ -435,190 +211,8 @@
435 211 }
436 212 }
437 213
438 214 /**
439 - * Open to Upgrade to Pro submenu link in new tab.
440 - *
441 - * @return void
442 - * @since 1.6.1
443 - */
444 - public function add_upgrade_to_pro_target_attr() {
445 - ?>
446 - <script type="text/javascript">
447 - document.addEventListener('DOMContentLoaded', function () {
448 - // Upgrade link handler.
449 - // IMPORTANT: If this URL changes, also update it in the `add_upgrade_to_pro` function.
450 - const upgradeLink = document.querySelector('a[href*="https://sureforms.com/upgrade"]');
451 - if (upgradeLink) {
452 - upgradeLink.addEventListener('click', e => {
453 - e.preventDefault();
454 - window.open(upgradeLink.href, '_blank');
455 - });
456 - }
457 - });
458 - </script>
459 - <?php
460 - }
461 -
462 - /**
463 - * Add Upgrade to pro menu item.
464 - *
465 - * @return void
466 - * @since 1.6.1
467 - */
468 - public function add_upgrade_to_pro() {
469 - // The url used here is used as a selector for css to style the upgrade to pro submenu.
470 - // If you are changing this url, please make sure to update the css as well.
471 - $upgrade_url = Helper::get_sureforms_website_url( 'upgrade', [ 'utm_medium' => 'submenu_link_upgrade' ] );
472 -
473 - add_submenu_page(
474 - 'sureforms_menu',
475 - __( 'Upgrade', 'sureforms' ),
476 - __( 'Upgrade', 'sureforms' ),
477 - self::$sureforms_page_default_capability,
478 - $upgrade_url
479 - );
480 - }
481 -
482 - /**
483 - * Add Quiz empty state submenu page for free users.
484 - *
485 - * @return void
486 - * @since 2.7.0
487 - */
488 - public function add_quiz_page() {
489 - add_submenu_page(
490 - 'sureforms_menu',
491 - __( 'Quiz Entries', 'sureforms' ),
492 - __( 'Quizzes', 'sureforms' ) .
493 - ' <span style="color:#4ADE80;font-size:9px;font-weight:600;">' .
494 - esc_html__( 'New', 'sureforms' ) .
495 - '</span>',
496 - self::$sureforms_page_default_capability,
497 - 'sureforms_quiz_entries',
498 - [ $this, 'render_quiz_empty_state' ],
499 - 5
500 - );
501 - }
502 -
503 - /**
504 - * Quiz empty state page callback.
505 - *
506 - * @return void
507 - * @since 2.7.0
508 - */
509 - public function render_quiz_empty_state() {
510 - ?>
511 - <div id="srfm-quiz-entries-root" class="srfm-admin-wrapper"></div>
512 - <?php
513 - }
514 -
515 - /**
516 - * Add Survey Reports promotional submenu page for free users.
517 - *
518 - * @return void
519 - * @since 2.8.0
520 - */
521 - public function add_survey_reports_page() {
522 - add_submenu_page(
523 - 'sureforms_menu',
524 - __( 'Survey Reports', 'sureforms' ),
525 - __( 'Survey Reports', 'sureforms' ) .
526 - ' <span style="color:#4ADE80;font-size:9px;font-weight:600;">' .
527 - esc_html__( 'New', 'sureforms' ) .
528 - '</span>',
529 - self::$sureforms_page_default_capability,
530 - 'sureforms_survey_reports',
531 - [ $this, 'render_survey_empty_state' ],
532 - 6
533 - );
534 - }
535 -
536 - /**
537 - * Survey empty state page callback.
538 - *
539 - * @return void
540 - * @since 2.8.0
541 - */
542 - public function render_survey_empty_state() {
543 - ?>
544 - <div id="srfm-survey-empty-state-root" class="srfm-admin-wrapper"></div>
545 - <?php
546 - }
547 -
548 - /**
549 - * Add Partial Entries promotional submenu page for free users.
550 - *
551 - * @return void
552 - * @since 2.9.0
553 - */
554 - public function add_partial_entries_page() {
555 - add_submenu_page(
556 - 'sureforms_menu',
557 - __( 'Partial Entries', 'sureforms' ),
558 - __( 'Partial Entries', 'sureforms' ) .
559 - ' <span style="color:#4ADE80;font-size:9px;font-weight:600;">' .
560 - esc_html__( 'New', 'sureforms' ) .
561 - '</span>',
562 - self::$sureforms_page_default_capability,
563 - 'sureforms_partial_entries',
564 - [ $this, 'render_partial_entries_empty_state' ],
565 - 7
566 - );
567 - }
568 -
569 - /**
570 - * Partial Entries empty state page callback.
571 - *
572 - * @return void
573 - * @since 2.9.0
574 - */
575 - public function render_partial_entries_empty_state() {
576 - ?>
577 - <div id="srfm-partial-entries-empty-state-root" class="srfm-admin-wrapper"></div>
578 - <?php
579 - }
580 -
581 - /**
582 - * Add SMTP promotional submenu page.
583 - *
584 - * @return void
585 - * @since 1.7.1
586 - */
587 - public function add_suremail_page() {
588 - add_submenu_page(
589 - 'sureforms_menu',
590 - __( 'SMTP', 'sureforms' ),
591 - __( 'SMTP', 'sureforms' ),
592 - self::$sureforms_page_default_capability,
593 - 'sureforms_smtp',
594 - [ $this, 'suremail_page_callback' ]
595 - );
596 -
597 - // Get the current submenu page.
598 - $submenu_page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- $_GET['page'] does not provide nonce.
599 -
600 - // Check if SureMail is installed and active.
601 - if ( 'sureforms_smtp' === $submenu_page && file_exists( WP_PLUGIN_DIR . '/suremails/suremails.php' ) && is_plugin_active( 'suremails/suremails.php' ) ) {
602 - // Plugin is installed and active - redirect to SureMail dashboard.
603 - wp_safe_redirect( admin_url( 'options-general.php?page=suremail#/dashboard' ) );
604 - exit;
605 - }
606 - }
607 -
608 - /**
609 - * SMTP promotional page callback.
610 - *
611 - * @return void
612 - * @since 1.7.1
613 - */
614 - public function suremail_page_callback() {
615 - ?>
616 - <div id="srfm-suremail-container" class="srfm-admin-wrapper"></div>
617 - <?php
618 - }
619 -
620 - /**
621 215 * Render Admin Dashboard.
622 216 *
623 217 * @return void
624 218 * @since 0.0.1
@@ -623,11 +217,9 @@
623 217 * @return void
624 218 * @since 0.0.1
625 219 */
626 220 public function render_dashboard() {
627 - ?>
628 - <div id="srfm-dashboard-container" class="srfm-admin-wrapper"></div>
629 - <?php
221 + echo '<div id="srfm-dashboard-container"></div>';
630 222 }
631 223
632 224 /**
633 225 * Settings page callback.
@@ -635,43 +227,12 @@
635 227 * @return void
636 228 * @since 0.0.1
637 229 */
638 230 public function settings_page_callback() {
639 - ?>
640 - <div id="srfm-settings-container" class="srfm-admin-wrapper"></div>
641 - <?php
231 + echo '<div id="srfm-settings-container"></div>';
642 232 }
643 233
644 234 /**
645 - * Add Learn submenu page.
646 - *
647 - * @return void
648 - * @since 2.5.2
649 - */
650 - public function add_learn_page() {
651 - add_submenu_page(
652 - 'sureforms_menu',
653 - __( 'Learn', 'sureforms' ),
654 - __( 'Learn', 'sureforms' ),
655 - self::$sureforms_page_default_capability,
656 - 'sureforms_learn',
657 - [ $this, 'render_learn' ]
658 - );
659 - }
660 -
661 - /**
662 - * Learn page callback.
663 - *
664 - * @return void
665 - * @since 2.5.2
666 - */
667 - public function render_learn() {
668 - ?>
669 - <div id="srfm-learn-root" class="srfm-admin-wrapper"></div>
670 - <?php
671 - }
672 -
673 - /**
674 235 * Add new form menu item.
675 236 *
676 237 * @return void
677 238 * @since 0.0.1
@@ -678,62 +239,27 @@
678 239 */
679 240 public function add_new_form() {
680 241 add_submenu_page(
681 242 'sureforms_menu',
682 - __( 'Forms', 'sureforms' ),
683 - __( 'Forms', 'sureforms' ),
684 - self::$sureforms_page_default_capability,
685 - 'sureforms_forms',
686 - [ $this, 'render_forms' ],
687 - 1
688 - );
689 - add_submenu_page(
690 - 'sureforms_menu',
691 243 __( 'New Form', 'sureforms' ),
692 244 __( 'New Form', 'sureforms' ),
693 - self::$sureforms_page_default_capability,
245 + 'edit_others_posts',
694 246 'add-new-form',
695 247 [ $this, 'add_new_form_callback' ],
696 248 2
697 249 );
698 - $entries_hook = add_submenu_page(
250 + add_submenu_page(
699 251 'sureforms_menu',
700 252 __( 'Entries', 'sureforms' ),
701 253 __( 'Entries', 'sureforms' ),
702 - self::$sureforms_page_default_capability,
254 + 'edit_others_posts',
703 255 SRFM_ENTRIES,
704 256 [ $this, 'render_entries' ],
705 257 3
706 258 );
707 -
708 - add_submenu_page(
709 - 'sureforms_menu',
710 - __( 'Payments', 'sureforms' ),
711 - __( 'Payments', 'sureforms' ),
712 - self::$sureforms_page_default_capability,
713 - SRFM_PAYMENTS,
714 - [ $this, 'render_payments' ],
715 - 4
716 - );
717 -
718 - if ( $entries_hook ) {
719 - add_action( 'load-' . $entries_hook, [ $this, 'mark_entries_page_visit' ] );
720 - }
721 259 }
722 260
723 261 /**
724 - * Payments page callback.
725 - *
726 - * @return void
727 - * @since 2.0.0
728 - */
729 - public function render_payments() {
730 - ?>
731 - <div id="srfm-payments-react-container" class="srfm-admin-wrapper"></div>
732 - <?php
733 - }
734 -
735 - /**
736 262 * Add new form mentu item callback.
737 263 *
738 264 * @return void
739 265 * @since 0.0.1
@@ -738,109 +264,44 @@
738 264 * @return void
739 265 * @since 0.0.1
740 266 */
741 267 public function add_new_form_callback() {
742 - ?>
743 - <div id="srfm-add-new-form-container" class="srfm-admin-wrapper"></div>
744 - <?php
268 + echo '<div id="srfm-add-new-form-container"></div>';
745 269 }
746 270
747 271 /**
748 - * Forms page callback.
749 - *
750 - * @return void
751 - * @since 2.0.0
752 - */
753 - public function render_forms() {
754 - ?>
755 - <div id="srfm-forms-root" class="srfm-admin-wrapper"></div>
756 - <?php
757 - }
758 -
759 - /**
760 272 * Entries page callback.
761 273 *
762 274 * @since 0.0.13
763 - * @since 2.0.0 - Updated the entries UI and the function definition.
764 275 * @return void
765 276 */
766 277 public function render_entries() {
767 - echo '<div id="srfm-entries-root"></div>';
768 - }
769 -
770 - /**
771 - * Add notification badge to SureForms menu when there are new entries.
772 - *
773 - * @since 1.7.3
774 - * @return void
775 - */
776 - public function maybe_add_entries_badge() {
777 - 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();
778 283 return;
779 284 }
780 285
781 - // If currently viewing the entries listing page, mark it as visited and skip the badge.
782 - if ( isset( $_GET['page'] ) && SRFM_ENTRIES === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only checking the page slug.
783 - $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();
784 294 return;
785 295 }
786 -
787 - $srfm_options = get_option( 'srfm_options', [] );
788 - $last_visit = isset( $srfm_options['entries_last_visited'] ) ? absint( $srfm_options['entries_last_visited'] ) : 0;
789 - $new_entries = Entries::get_entries_count_after( $last_visit );
790 -
791 - if ( $new_entries <= 0 ) {
792 - return;
793 - }
794 -
795 - global $menu;
796 - foreach ( $menu as $index => $item ) {
797 - if ( isset( $item[2] ) && 'sureforms_menu' === $item[2] ) {
798 - ob_start();
799 - ?>
800 - <span class="srfm-update-dot"></span>
801 - <?php
802 - $dot_html = ob_get_clean();
803 - // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Adding notifications for menu item.
804 - $menu[ $index ][0] .= $dot_html;
805 - break;
806 - }
807 - }
808 -
809 - global $submenu;
810 - if ( isset( $submenu['sureforms_menu'] ) ) {
811 - foreach ( $submenu['sureforms_menu'] as $index => $sub_item ) {
812 - if ( isset( $sub_item[2] ) && SRFM_ENTRIES === $sub_item[2] ) {
813 - ob_start();
814 - ?>
815 - <span class="update-plugins count-<?php echo absint( $new_entries ); ?>">
816 - <span class="plugin-count"><?php echo absint( $new_entries ); ?></span>
817 - </span>
818 - <?php
819 - $badge_html = ob_get_clean();
820 - // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Adding notifications for submenu item.
821 - $submenu['sureforms_menu'][ $index ][0] .= $badge_html;
822 - break;
823 - }
824 - }
825 - }
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>';
826 301 }
827 302
828 303 /**
829 - * Mark the user's visit to the entries page.
830 - *
831 - * @since 1.7.3
832 - * @return void
833 - */
834 - public function mark_entries_page_visit() {
835 - if ( Helper::current_user_can() ) {
836 - $srfm_options = get_option( 'srfm_options', [] );
837 - $srfm_options['entries_last_visited'] = time();
838 - \SRFM\Inc\Helper::update_admin_settings_option( 'srfm_options', $srfm_options );
839 - }
840 - }
841 -
842 - /**
843 304 * Adds a settings link to the plugin action links on the plugins page.
844 305 *
845 306 * @param array $links An array of plugin action links.
846 307 * @param string $file The plugin file path.
@@ -848,22 +309,15 @@
848 309 * @since 0.0.1
849 310 */
850 311 public function add_settings_link( $links, $file ) {
851 312 if ( 'sureforms/sureforms.php' === $file ) {
852 - ob_start();
853 - ?>
854 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=sureforms_form_settings&tab=general-settings' ) ); ?>">
855 - <?php echo esc_html__( 'Settings', 'sureforms' ); ?>
856 - </a>
857 - <?php
858 - $settings_link_html = ob_get_clean();
859 - $plugin_links = apply_filters(
313 + $plugin_links = apply_filters(
860 314 'sureforms_plugin_action_links',
861 315 [
862 - '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>',
863 317 ]
864 318 );
865 - $links = array_merge( $plugin_links, $links );
319 + $links = array_merge( $plugin_links, $links );
866 320 }
867 321 return $links;
868 322 }
869 323
@@ -973,8 +427,9 @@
973 427 global $wp_version;
974 428
975 429 $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
976 430 $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
431 + $js_uri = SRFM_URL . 'assets/js/' . $dir_name . '/';
977 432 $css_uri = SRFM_URL . 'assets/css/' . $dir_name . '/';
978 433 $is_rtl = is_rtl();
979 434 $rtl = $is_rtl ? '-rtl' : '';
980 435
@@ -981,135 +436,30 @@
981 436 /**
982 437 * List of the handles in which we need to add translation compatibility.
983 438 */
984 439 $script_translations_handlers = [];
985 - $onboarding_instance = Onboarding::get_instance();
986 - $current_user = wp_get_current_user();
987 440
988 441 $localization_data = [
989 - 'site_url' => get_site_url(),
990 - 'current_user_login' => $current_user->user_login ?? '',
991 - 'website_lead_details' => [
992 - 'first_name' => $current_user->first_name ?? '',
993 - 'last_name' => $current_user->last_name ?? '',
994 - 'email' => $current_user->user_email ?? '',
995 - ],
996 - 'breadcrumbs' => $this->get_breadcrumbs_for_current_page(),
997 - 'sureforms_dashboard_url' => admin_url( '/admin.php?page=sureforms_menu' ),
998 - 'plugin_version' => SRFM_VER,
999 - 'global_settings_nonce' => Helper::current_user_can() ? wp_create_nonce( 'wp_rest' ) : '',
1000 - 'is_pro_active' => Helper::has_pro(),
1001 - 'is_first_form_created' => self::is_first_form_created(),
1002 - 'check_three_days_threshold' => self::check_first_form_creation_threshold(),
1003 - 'check_eight_days_threshold' => self::check_first_form_creation_threshold( 8 ),
1004 - 'pro_plugin_version' => Helper::has_pro() ? SRFM_PRO_VER : '',
1005 - 'pro_plugin_name' => Helper::has_pro() && defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro',
1006 - 'sureforms_pricing_page' => Helper::get_sureforms_website_url( 'pricing' ),
1007 - 'field_spacing_vars' => Helper::get_css_vars(),
1008 - 'is_ver_lower_than_6_7' => version_compare( $wp_version, '6.6.2', '<=' ),
1009 - 'integrations' => Helper::sureforms_get_integration(),
1010 - 'rotating_plugin_banner' => Helper::get_rotating_plugin_banner(),
1011 - 'ajax_url' => admin_url( 'admin-ajax.php' ),
1012 - 'sf_plugin_manager_nonce' => wp_create_nonce( 'sf_plugin_manager_nonce' ),
1013 - 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
1014 - 'plugin_activating_text' => __( 'Activating...', 'sureforms' ),
1015 - 'plugin_activated_text' => __( 'Activated', 'sureforms' ),
1016 - 'plugin_activate_text' => __( 'Activate', 'sureforms' ),
1017 - 'plugin_installing_text' => __( 'Installing...', 'sureforms' ),
1018 - 'plugin_installed_text' => __( 'Installed', 'sureforms' ),
1019 - 'privacy_policy_url' => Helper::get_sureforms_website_url( 'privacy-policy/' ),
1020 - 'is_rtl' => $is_rtl,
1021 - 'onboarding_completed' => method_exists( $onboarding_instance, 'get_onboarding_status' ) ? $onboarding_instance->get_onboarding_status() : false,
1022 - 'migration_banner_dismissed' => method_exists( $onboarding_instance, 'is_migration_banner_dismissed' ) ? $onboarding_instance->is_migration_banner_dismissed() : false,
1023 - 'migration_settings_url' => admin_url( 'admin.php?page=sureforms_form_settings&tab=migration-settings' ),
1024 - 'onboarding_redirect' => isset( $_GET['srfm-activation-redirect'] ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce is not required for the activation redirection.
1025 - 'pointer_nonce' => wp_create_nonce( 'sureforms_pointer_action' ),
1026 - 'general_settings_url' => admin_url( '/options-general.php' ),
1027 - 'additional_header_nav_items' => [],
1028 - // Smart tags for the Global Defaults email notification fields.
1029 - // srfm_block_data is only available in the block editor; these keys
1030 - // make the same data accessible on the settings page via srfm_admin.
1031 - 'smart_tags_array' => Smart_Tags::smart_tag_list(),
1032 - 'smart_tags_array_email' => Smart_Tags::email_smart_tag_list(),
1033 - // Default confirmation message HTML (icon + heading + text) used as
1034 - // the initial React state before the settings API response arrives.
1035 - 'default_confirmation_message' => Global_Settings::get_default_confirmation_message(),
1036 - 'payments' => apply_filters(
1037 - 'srfm_admin_localize_payments_data',
1038 - [
1039 - 'stripe_connected' => Stripe_Helper::is_stripe_connected(),
1040 - 'stripe_mode' => Stripe_Helper::get_stripe_mode(),
1041 - 'stripe_connect_url' => Stripe_Helper::get_stripe_settings_url(),
1042 - 'currencies_data' => Payment_Helper::get_all_currencies_data(),
1043 - 'zero_decimal_currencies' => Payment_Helper::get_zero_decimal_currencies(),
1044 - 'webhook_url' => Stripe_Helper::get_webhook_url(),
1045 - 'webhook_test_connected' => Stripe_Helper::is_webhook_configured( 'test', true ),
1046 - 'webhook_live_connected' => Stripe_Helper::is_webhook_configured( 'live', true ),
1047 - 'is_transaction_present' => Stripe_Helper::is_transaction_present(),
1048 - 'payment_currency' => Payment_Helper::get_currency(),
1049 - 'currency_sign_position' => Payment_Helper::get_currency_sign_position(),
1050 - ]
1051 - ),
1052 - 'mcp_adapter_status' => file_exists( WP_PLUGIN_DIR . '/mcp-adapter/mcp-adapter.php' )
1053 - ? ( is_plugin_active( 'mcp-adapter/mcp-adapter.php' ) ? 'active' : 'installed' )
1054 - : 'not_installed',
1055 - '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', '<=' ),
1056 453 ];
1057 454
1058 - $is_screen_sureforms_menu = Helper::validate_request_context( 'sureforms_menu', 'page' );
1059 - $is_screen_add_new_form = Helper::validate_request_context( 'add-new-form', 'page' );
1060 - $is_screen_sureforms_forms = Helper::validate_request_context( 'sureforms_forms', 'page' );
1061 - $is_screen_sureforms_form_settings = Helper::validate_request_context( 'sureforms_form_settings', 'page' );
1062 - $is_screen_sureforms_payments = Helper::validate_request_context( 'sureforms_payments', 'page' );
1063 - $is_screen_sureforms_entries = Helper::validate_request_context( SRFM_ENTRIES, 'page' );
1064 - $is_screen_sureforms_learn = Helper::validate_request_context( 'sureforms_learn', 'page' );
1065 - $is_screen_quiz_empty_state = Helper::validate_request_context( 'sureforms_quiz_entries', 'page' );
1066 - $is_screen_survey_empty_state = Helper::validate_request_context( 'sureforms_survey_reports', 'page' );
1067 - $is_screen_partial_entries_empty_state = Helper::validate_request_context( 'sureforms_partial_entries', 'page' );
1068 - $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;
1069 460
1070 - /**
1071 - * Check if the current screen is the SureForms Menu and AI Auth Email is present then we will add user type as registered.
1072 - * Compatibility with existing UI code that checks for this condition.
1073 - */
1074 - if ( $is_screen_sureforms_menu ) {
1075 - // If email is stored send the user type as registered else non-registered.
1076 - $localization_data['srfm_ai_details'] = [
1077 - 'type' => ! empty( get_option( 'srfm_ai_auth_user_email' ) ) ? 'registered' : 'non-registered',
1078 - ];
1079 - }
1080 -
1081 - // Add the Quizzes and Survey Reports nav items when pro is not active.
1082 - if ( ! Helper::has_pro() ) {
1083 - $localization_data['additional_header_nav_items'][] = [
1084 - 'slug' => 'sureforms_quiz_entries',
1085 - 'text' => __( 'Quizzes', 'sureforms' ),
1086 - 'link' => admin_url( 'admin.php?page=sureforms_quiz_entries' ),
1087 - ];
1088 - $localization_data['additional_header_nav_items'][] = [
1089 - 'slug' => 'sureforms_survey_reports',
1090 - 'text' => __( 'Survey Reports', 'sureforms' ),
1091 - 'link' => admin_url( 'admin.php?page=sureforms_survey_reports' ),
1092 - ];
1093 - $localization_data['additional_header_nav_items'][] = [
1094 - 'slug' => 'sureforms_partial_entries',
1095 - 'text' => __( 'Partial Entries', 'sureforms' ),
1096 - 'link' => admin_url( 'admin.php?page=sureforms_partial_entries' ),
1097 - ];
1098 - }
1099 -
1100 - $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;
1101 -
1102 - /**
1103 - * Filter to allow extending the SureForms dashboard screen check.
1104 - *
1105 - * @since 2.6.0
1106 - *
1107 - * @param bool $is_sureforms_screen Whether the current screen is a SureForms dashboard screen.
1108 - */
1109 - $is_sureforms_screen = apply_filters( 'srfm_is_dashboard_screen', $is_sureforms_screen );
1110 -
1111 - 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 ) {
1112 462 $asset_handle = '-dashboard';
1113 463
1114 464 wp_enqueue_style( SRFM_SLUG . $asset_handle . '-font', 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap', [], SRFM_VER );
1115 465
@@ -1137,9 +487,9 @@
1137 487 update_option( 'srfm_pro_license_status', $current_license_status );
1138 488 }
1139 489 }
1140 490
1141 - $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' );
1142 492 $localization_data['integration_settings_url'] = admin_url( '/admin.php?page=sureforms_form_settings&tab=integration-settings' );
1143 493 wp_localize_script(
1144 494 SRFM_SLUG . $asset_handle,
1145 495 SRFM_SLUG . '_admin',
@@ -1148,12 +498,27 @@
1148 498 $localization_data
1149 499 )
1150 500 );
1151 501 wp_enqueue_style( SRFM_SLUG . '-dashboard', SRFM_URL . 'assets/build/dashboard.css', [], SRFM_VER, 'all' );
502 +
1152 503 }
1153 504
1154 - if ( $is_screen_sureforms_form_settings || $is_screen_sureforms_forms ) {
505 + if ( $is_screen_sureforms_form_settings ) {
1155 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 + }
1156 521 }
1157 522
1158 523 // Enqueue styles for the entries page.
1159 524 if ( $is_screen_sureforms_entries ) {
@@ -1159,158 +524,30 @@
1159 524 if ( $is_screen_sureforms_entries ) {
1160 525 $asset_handle = '-entries';
1161 526 wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/entries.js', $script_info['dependencies'], SRFM_VER, true );
1162 527
1163 - wp_localize_script(
1164 - SRFM_SLUG . $asset_handle,
1165 - SRFM_SLUG . '_admin',
1166 - apply_filters(
1167 - SRFM_SLUG . '_admin_filter',
1168 - $localization_data
1169 - )
1170 - );
1171 528 $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
1172 529 }
1173 530
1174 - // Enqueue scripts for the learn page.
1175 - if ( $is_screen_sureforms_learn ) {
1176 - $asset_handle = '-learn';
1177 - 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 );
1178 533
1179 - wp_localize_script(
1180 - SRFM_SLUG . $asset_handle,
1181 - SRFM_SLUG . '_admin',
1182 - apply_filters(
1183 - SRFM_SLUG . '_admin_filter',
1184 - $localization_data
1185 - )
1186 - );
1187 - $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
1188 - }
534 + if ( 'edit-' . SRFM_FORMS_POST_TYPE === $current_screen->id ) {
535 + $asset_handle = 'page_header';
1189 536
1190 - // Enqueue scripts for the forms page.
1191 - if ( $is_screen_sureforms_forms ) {
1192 - $asset_handle = '-forms';
1193 -
1194 - $script_asset_path = SRFM_DIR . 'assets/build/forms.asset.php';
1195 - $script_info = file_exists( $script_asset_path )
1196 - ? include $script_asset_path
1197 - : [
1198 - 'dependencies' => [],
1199 - 'version' => SRFM_VER,
1200 - ];
1201 -
1202 - wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/forms.js', $script_info['dependencies'], SRFM_VER, true );
1203 - wp_localize_script(
1204 - SRFM_SLUG . $asset_handle,
1205 - SRFM_SLUG . '_admin',
1206 - apply_filters(
1207 - SRFM_SLUG . '_admin_filter',
1208 - $localization_data
1209 - )
1210 - );
1211 - wp_enqueue_style( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/forms.css', [], SRFM_VER, 'all' );
1212 -
1213 - $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
1214 - }
1215 -
1216 - // Enqueue scripts for the SureMail promotional page.
1217 - $is_screen_sureforms_smtp = Helper::validate_request_context( 'sureforms_smtp', 'page' );
1218 - if ( $is_screen_sureforms_smtp ) {
1219 - $asset_handle = 'suremail';
1220 -
1221 537 $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1222 538 $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 . '-suremail', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1230 - wp_enqueue_style( SRFM_SLUG . '-suremail', SRFM_URL . 'assets/build/suremail.css', [], SRFM_VER, 'all' );
1231 -
1232 - // Localize script for SureMail page.
1233 - $suremail_localization_data = [
1234 - 'ajax_url' => admin_url( 'admin-ajax.php' ),
1235 - 'admin_url' => admin_url(),
1236 - 'suremail_url' => 'https://sureforms.com/suremail/',
1237 - 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
1238 - 'sfPluginManagerNonce' => wp_create_nonce( 'sf_plugin_manager_nonce' ),
1239 - 'suremail_status' => file_exists( WP_PLUGIN_DIR . '/suremails/suremails.php' )
1240 - ? ( is_plugin_active( 'suremails/suremails.php' ) ? 'active' : 'installed' )
1241 - : 'not_installed',
539 + ? include $script_asset_path
540 + : [
541 + 'dependencies' => [],
542 + 'version' => SRFM_VER,
1242 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 );
1243 546
1244 - wp_localize_script(
1245 - SRFM_SLUG . '-suremail',
1246 - SRFM_SLUG . '_admin',
1247 - apply_filters(
1248 - SRFM_SLUG . '_suremail_admin_filter',
1249 - $suremail_localization_data
1250 - )
1251 - );
1252 -
1253 - $script_translations_handlers[] = SRFM_SLUG . '-suremail';
547 + $script_translations_handlers[] = SRFM_SLUG . '-form-page-header';
1254 548 }
1255 549
1256 - // Enqueue scripts for the Quiz empty state page (free users only).
1257 - if ( $is_screen_quiz_empty_state && ! Helper::has_pro() ) {
1258 - $asset_handle = 'quizEmptyState';
1259 -
1260 - $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1261 - $script_info = file_exists( $script_asset_path )
1262 - ? include $script_asset_path
1263 - : [
1264 - 'dependencies' => [],
1265 - 'version' => SRFM_VER,
1266 - ];
1267 -
1268 - wp_enqueue_script( SRFM_SLUG . '-quiz-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1269 - wp_enqueue_style( SRFM_SLUG . '-quiz-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.css', [], SRFM_VER, 'all' );
1270 -
1271 - $script_translations_handlers[] = SRFM_SLUG . '-quiz-empty-state';
1272 - }
1273 -
1274 - // Enqueue scripts for the Survey Reports empty state page (free users only).
1275 - if ( $is_screen_survey_empty_state && ! Helper::has_pro() ) {
1276 - $asset_handle = 'surveyEmptyState';
1277 -
1278 - $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1279 - $script_info = file_exists( $script_asset_path )
1280 - ? include $script_asset_path
1281 - : [
1282 - 'dependencies' => [],
1283 - 'version' => SRFM_VER,
1284 - ];
1285 -
1286 - wp_enqueue_script( SRFM_SLUG . '-survey-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1287 - wp_enqueue_style( SRFM_SLUG . '-survey-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.css', [], SRFM_VER, 'all' );
1288 -
1289 - $script_translations_handlers[] = SRFM_SLUG . '-survey-empty-state';
1290 - }
1291 -
1292 - // Enqueue scripts for the Partial Entries empty state page (free users only).
1293 - if ( $is_screen_partial_entries_empty_state && ! Helper::has_pro() ) {
1294 - $asset_handle = 'partialEntriesEmptyState';
1295 -
1296 - $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1297 - $script_info = file_exists( $script_asset_path )
1298 - ? include $script_asset_path
1299 - : [
1300 - 'dependencies' => [],
1301 - 'version' => SRFM_VER,
1302 - ];
1303 -
1304 - wp_enqueue_script( SRFM_SLUG . '-partial-entries-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1305 - wp_enqueue_style( SRFM_SLUG . '-partial-entries-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.css', [], SRFM_VER, 'all' );
1306 -
1307 - $script_translations_handlers[] = SRFM_SLUG . '-partial-entries-empty-state';
1308 - }
1309 -
1310 - // Admin Submenu Styles.
1311 - wp_enqueue_style( SRFM_SLUG . '-admin', $css_uri . 'backend/admin' . $file_prefix . $rtl . '.css', [], SRFM_VER );
1312 -
1313 550 if ( $is_screen_sureforms_form_settings ) {
1314 551 $asset_handle = 'settings';
1315 552
1316 553 $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
@@ -1321,22 +558,44 @@
1321 558 'version' => SRFM_VER,
1322 559 ];
1323 560
1324 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' );
1325 563 wp_localize_script(
1326 564 SRFM_SLUG . '-settings',
1327 565 SRFM_SLUG . '_admin',
1328 - apply_filters(
1329 - SRFM_SLUG . '_admin_filter',
1330 - $localization_data
1331 - )
566 + $localization_data
1332 567 );
1333 568
1334 - // Enqueue Tailwind and Quill editor styles for the settings page.
1335 - wp_enqueue_style( SRFM_SLUG . '-settings-build', SRFM_URL . 'assets/build/settings.css', [], SRFM_VER, 'all' );
1336 - 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 + 'import_form_nonce' => current_user_can( 'edit_posts' ) ? wp_create_nonce( 'wp_rest' ) : '',
582 + 'import_btn_string' => __( 'Import Form', 'sureforms' ),
583 + ]
584 + );
1337 585
1338 - $script_translations_handlers[] = SRFM_SLUG . '-settings';
586 + wp_enqueue_script( SRFM_SLUG . '-backend', $js_uri . 'backend' . $file_prefix . '.js', [], SRFM_VER, true );
587 + wp_localize_script(
588 + SRFM_SLUG . '-backend',
589 + SRFM_SLUG . '_backend',
590 + [
591 + 'site_url' => get_site_url(),
592 + ]
593 + );
594 +
595 + $script_translations_handlers[] = SRFM_SLUG . '-form-archive';
596 + $script_translations_handlers[] = SRFM_SLUG . '-export';
597 + $script_translations_handlers[] = SRFM_SLUG . '-backend';
1339 598 }
1340 599
1341 600 if ( $is_screen_add_new_form ) {
1342 601 wp_enqueue_style( SRFM_SLUG . '-template-picker', $css_uri . 'template-picker' . $file_prefix . $rtl . '.css', [], SRFM_VER );
@@ -1357,18 +616,18 @@
1357 616 SRFM_SLUG . '_admin',
1358 617 [
1359 618 'site_url' => get_site_url(),
1360 619 'plugin_url' => SRFM_URL,
620 + 'preview_images_url' => SRFM_URL . 'images/template-previews/',
1361 621 'admin_url' => admin_url( 'admin.php' ),
1362 622 'new_template_picker_base_url' => admin_url( 'post-new.php?post_type=sureforms_form' ),
1363 - 'capability' => Helper::current_user_can(),
1364 - 'template_picker_nonce' => Helper::current_user_can() ? wp_create_nonce( 'wp_rest' ) : '',
1365 - 'is_pro_active' => Helper::has_pro(),
623 + 'capability' => current_user_can( 'edit_posts' ),
624 + 'template_picker_nonce' => current_user_can( 'edit_posts' ) ? wp_create_nonce( 'wp_rest' ) : '',
625 + 'is_pro_active' => defined( 'SRFM_PRO_VER' ),
1366 626 'srfm_ai_usage_details' => AI_Helper::get_current_usage_details(),
1367 627 'is_pro_license_active' => AI_Helper::is_pro_license_active(),
1368 628 'srfm_ai_auth_user_email' => get_option( 'srfm_ai_auth_user_email' ),
1369 629 'pricing_page_url' => Helper::get_sureforms_website_url( 'pricing' ),
1370 - 'licensing_nonce' => wp_create_nonce( 'srfm_pro_licensing_nonce' ),
1371 630 ]
1372 631 );
1373 632
1374 633 $script_translations_handlers[] = SRFM_SLUG . '-template-picker';
@@ -1383,9 +642,8 @@
1383 642 'srfm/checkbox',
1384 643 'srfm/number',
1385 644 'srfm/inline-button',
1386 645 'srfm/advanced-heading',
1387 - 'srfm/payment',
1388 646 ]
1389 647 );
1390 648 if ( ! is_array( $default_allowed_quick_sidebar_blocks ) ) {
1391 649 $default_allowed_quick_sidebar_blocks = [];
@@ -1397,25 +655,22 @@
1397 655 }
1398 656 $quick_sidebar_allowed_blocks = get_option( 'srfm_quick_sidebar_allowed_blocks' );
1399 657 $quick_sidebar_allowed_blocks = ! empty( $quick_sidebar_allowed_blocks ) && is_array( $quick_sidebar_allowed_blocks ) ? $quick_sidebar_allowed_blocks : $default_allowed_quick_sidebar_blocks;
1400 658 $srfm_ajax_nonce = wp_create_nonce( 'srfm_ajax_nonce' );
659 + wp_enqueue_script( SRFM_SLUG . '-quick-action-siderbar', SRFM_URL . 'assets/build/quickActionSidebar.js', [], SRFM_VER, true );
660 + wp_localize_script(
661 + SRFM_SLUG . '-quick-action-siderbar',
662 + SRFM_SLUG . '_quick_sidebar_blocks',
663 + [
664 + 'allowed_blocks' => $quick_sidebar_allowed_blocks,
665 + 'srfm_enable_quick_action_sidebar' => $srfm_enable_quick_action_sidebar,
666 + 'srfm_ajax_nonce' => $srfm_ajax_nonce,
667 + 'srfm_ajax_url' => admin_url( 'admin-ajax.php' ),
668 + ]
669 + );
1401 670
1402 - if ( Helper::is_sureforms_admin_page() ) {
1403 - wp_enqueue_script( SRFM_SLUG . '-quick-action-siderbar', SRFM_URL . 'assets/build/quickActionSidebar.js', [], SRFM_VER, true );
1404 - wp_localize_script(
1405 - SRFM_SLUG . '-quick-action-siderbar',
1406 - SRFM_SLUG . '_quick_sidebar_blocks',
1407 - [
1408 - 'allowed_blocks' => $quick_sidebar_allowed_blocks,
1409 - 'srfm_enable_quick_action_sidebar' => $srfm_enable_quick_action_sidebar,
1410 - 'srfm_ajax_nonce' => $srfm_ajax_nonce,
1411 - 'srfm_ajax_url' => admin_url( 'admin-ajax.php' ),
1412 - ]
1413 - );
671 + $script_translations_handlers[] = SRFM_SLUG . '-quick-action-siderbar';
1414 672
1415 - $script_translations_handlers[] = SRFM_SLUG . '-quick-action-siderbar';
1416 - }
1417 -
1418 673 /**
1419 674 * Enqueuing SureTriggers Integration script.
1420 675 * This script loads suretriggers iframe in Intergations tab.
1421 676 */
@@ -1487,53 +742,40 @@
1487 742
1488 743 return $status;
1489 744 }
1490 745
746 + // Entries methods.
747 +
1491 748 /**
1492 - * Register Pro compatibility notices early for React pages.
749 + * Handle entry actions.
1493 750 *
1494 - * This method runs on admin_init (priority 5) to ensure notices are
1495 - * registered BEFORE admin_enqueue_scripts, so they're available when
1496 - * wp_localize_script runs.
1497 - *
1498 - * Hooked - admin_init (priority 5)
1499 - *
751 + * @since 0.0.13
1500 752 * @return void
1501 - * @since 2.5.0
1502 753 */
1503 - public function register_pro_compatibility_notices() {
1504 - // Early exit if Pro is not active, user lacks permissions, or Notice_Manager is unavailable.
1505 - if ( ! Helper::has_pro() || ! Helper::current_user_can() || ! class_exists( 'SRFM\Admin\Notice_Manager' ) ) {
754 + public function handle_entry_actions() {
755 + Entries_List_Table::process_bulk_actions();
756 +
757 + if ( ! isset( $_GET['page'] ) || SRFM_ENTRIES !== $_GET['page'] ) {
1506 758 return;
1507 759 }
1508 -
1509 - // Register version outdated notice for React pages.
1510 - if ( ! version_compare( SRFM_PRO_VER, SRFM_PRO_RECOMMENDED_VER, '>=' ) ) {
1511 - $pro_plugin_name = defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro';
1512 - $react_outdated_message = sprintf(
1513 - // translators: %1$s: SureForms version, %2$s: SureForms Pro Plugin Name, %3$s: SureForms Pro Version.
1514 - esc_html__( 'SureForms %1$s requires minimum %2$s %3$s to work properly. Please update to the latest version.', 'sureforms' ),
1515 - esc_html( SRFM_VER ),
1516 - esc_html( $pro_plugin_name ),
1517 - esc_html( SRFM_PRO_RECOMMENDED_VER )
1518 - );
1519 -
1520 - \SRFM\Admin\Notice_Manager::register_notice(
1521 - [
1522 - 'id' => 'sureforms-pro-version-outdated',
1523 - 'variant' => 'warning',
1524 - 'message' => $react_outdated_message,
1525 - 'actions' => [
1526 - [
1527 - 'label' => esc_html__( 'Update Now', 'sureforms' ),
1528 - 'url' => admin_url( 'update-core.php' ),
1529 - 'variant' => 'primary',
1530 - ],
1531 - ],
1532 - 'pages' => [ 'all' ],
1533 - ]
1534 - );
760 + if ( ! isset( $_GET['entry_id'] ) || ! isset( $_GET['action'] ) ) {
761 + return;
1535 762 }
763 + if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'srfm_entries_action' ) ) {
764 + wp_die( esc_html__( 'Nonce verification failed.', 'sureforms' ) );
765 + }
766 + $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : '';
767 + $entry_id = Helper::get_integer_value( sanitize_text_field( wp_unslash( $_GET['entry_id'] ) ) );
768 + $view = isset( $_GET['view'] ) ? sanitize_text_field( wp_unslash( $_GET['view'] ) ) : '';
769 + if ( $entry_id > 0 ) {
770 + if ( 'read' === $action && 'details' === $view ) {
771 + $entry_status = Entries::get( $entry_id )['status'];
772 + if ( 'trash' === $entry_status ) {
773 + wp_die( esc_html__( 'You cannot view this entry because it is in trash.', 'sureforms' ) );
774 + }
775 + }
776 + Entries_List_Table::handle_entry_status( $entry_id, $action, $view );
777 + }
1536 778 }
1537 779
1538 780 /**
1539 781 * Admin Notice Callback if sureforms pro is out of date.
@@ -1543,9 +785,10 @@
1543 785 * @return void
1544 786 * @since 1.0.4
1545 787 */
1546 788 public function srfm_pro_version_compatibility() {
1547 - if ( ! Helper::has_pro() ) {
789 + $plugin_file = 'sureforms-pro/sureforms-pro.php';
790 + if ( ! is_plugin_active( $plugin_file ) || ! defined( 'SRFM_PRO_VER' ) ) {
1548 791 return;
1549 792 }
1550 793
1551 794 if ( empty( get_current_screen() ) ) {
@@ -1551,9 +794,9 @@
1551 794 if ( empty( get_current_screen() ) ) {
1552 795 return;
1553 796 }
1554 797
1555 - if ( ! Helper::current_user_can() ) {
798 + if ( ! current_user_can( 'update_plugins' ) ) {
1556 799 return;
1557 800 }
1558 801
1559 802 $srfm_pro_license_status = get_option( 'srfm_pro_license_status', '' );
@@ -1569,214 +812,36 @@
1569 812 $pro_plugin_name = defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro';
1570 813 $message = '';
1571 814 $url = admin_url( 'admin.php?page=sureforms_form_settings&tab=account-settings' );
1572 815 if ( 'unlicensed' === $srfm_pro_license_status ) {
1573 - ob_start();
1574 - ?>
1575 - <p>
1576 - <?php
1577 - printf(
1578 - // translators: %1$s: Opening anchor tag with URL, %2$s: Closing anchor tag, %3$s: SureForms Pro Plugin Name.
1579 - esc_html__( 'Please %1$sactivate%2$s your copy of %3$s to get new features, access support, receive update notifications, and more.', 'sureforms' ),
1580 - '<a href="' . esc_url( $url ) . '">',
1581 - '</a>',
1582 - '<i>' . esc_html( $pro_plugin_name ) . '</i>'
1583 - );
1584 - ?>
1585 - </p>
1586 - <?php
1587 - $message = ob_get_clean();
816 + $message = '<p>' . sprintf(
817 + // translators: %1$s: Opening anchor tag with URL, %2$s: Closing anchor tag, %3$s: SureForms Pro Plugin Name.
818 + esc_html__( 'Please %1$sactivate%2$s your copy of %3$s to get new features, access support, receive update notifications, and more.', 'sureforms' ),
819 + '<a href="' . esc_url( $url ) . '">',
820 + '</a>',
821 + '<i>' . esc_html( $pro_plugin_name ) . '</i>'
822 + ) . '</p>';
1588 823 }
1589 824
1590 825 if ( ! version_compare( SRFM_PRO_VER, SRFM_PRO_RECOMMENDED_VER, '>=' ) ) {
1591 - ob_start();
1592 - ?>
1593 - <p>
1594 - <?php
1595 - printf(
1596 - // 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.
1597 - 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' ),
1598 - esc_html( SRFM_VER ),
1599 - esc_html( $pro_plugin_name ),
1600 - esc_html( SRFM_PRO_RECOMMENDED_VER ),
1601 - '<a href="' . esc_url( admin_url( 'update-core.php' ) ) . '">',
1602 - '</a>'
1603 - );
1604 - ?>
1605 - </p>
1606 - <?php
1607 - $message .= ob_get_clean();
826 + $message .= '<p>' . sprintf(
827 + // 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.
828 + 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' ),
829 + esc_html( SRFM_VER ),
830 + esc_html( $pro_plugin_name ),
831 + esc_html( SRFM_PRO_RECOMMENDED_VER ),
832 + '<a href=' . esc_url( admin_url( 'update-core.php' ) ) . '>',
833 + '</a>'
834 + ) . '</p>';
1608 835 }
1609 836
1610 837 if ( ! empty( $message ) ) {
1611 838 // Phpcs ignore comment is required as $message variable is already escaped.
1612 - ?>
1613 - <div class="notice notice-warning"><?php echo wp_kses_post( $message ); ?></div>
1614 - <?php
839 + echo '<div class="notice notice-warning">' . wp_kses_post( $message ) . '</div>';
1615 840 }
1616 841 }
1617 842
1618 843 /**
1619 - * Display a notice to the user about providing a review.
1620 - *
1621 - * @since 2.5.2
1622 - * @return void
1623 - */
1624 - public function display_srfm_rating_notice() {
1625 - // Only show to admins.
1626 - if ( ! Helper::current_user_can() ) {
1627 - return;
1628 - }
1629 -
1630 - // Allow the notice to be disabled.
1631 - if ( ! apply_filters( 'srfm_show_rating_notice', true ) ) {
1632 - return;
1633 - }
1634 -
1635 - Astra_Notices::add_notice(
1636 - [
1637 - 'id' => 'srfm-plugin-review-notice',
1638 - 'type' => '',
1639 - 'message' => $this->build_notice_markup(
1640 - esc_html__( 'Amazing! SureForms is powering your forms and submissions - let\'s keep growing together!', 'sureforms' ),
1641 - esc_html__( 'If SureForms has been helpful, would you mind taking a moment to leave a 5-star review on WordPress.org?', 'sureforms' ),
1642 - esc_url( 'https://wordpress.org/support/plugin/sureforms/reviews/?filter=5#new-post' ),
1643 - esc_html__( 'Rate SureForms', 'sureforms' ),
1644 - esc_html__( 'Maybe later', 'sureforms' ),
1645 - esc_html__( 'I already did', 'sureforms' ),
1646 - WEEK_IN_SECONDS,
1647 - true
1648 - ),
1649 - 'repeat-notice-after' => WEEK_IN_SECONDS,
1650 - 'show_if' => $this->maybe_display_rating_notice(),
1651 - 'display-with-other-notices' => true,
1652 - ]
1653 - );
1654 -
1655 - add_action( 'astra_notice_after_markup_srfm-plugin-review-notice', [ $this, 'enqueue_notice_response_script' ] );
1656 - }
1657 -
1658 - /**
1659 - * Display a "Getting Started" admin notice for new users who haven't yet
1660 - * reached the rating-notice milestone (3+ forms or 3+ entries).
1661 - *
1662 - * The Astra Notices library handles the 7-day delay via the
1663 - * `display-notice-after` parameter.
1664 - *
1665 - * @since 2.5.2
1666 - * @return void
1667 - */
1668 - public function display_srfm_getting_started_notice() {
1669 - // Only show to admins.
1670 - if ( ! Helper::current_user_can() ) {
1671 - return;
1672 - }
1673 -
1674 - // Allow the notice to be disabled programmatically.
1675 - if ( ! apply_filters( 'srfm_show_getting_started_notice', true ) ) {
1676 - return;
1677 - }
1678 -
1679 - Astra_Notices::add_notice(
1680 - [
1681 - 'id' => 'srfm-getting-started-notice',
1682 - 'type' => '',
1683 - 'message' => $this->build_notice_markup(
1684 - esc_html__( 'SureForms is ready to power your forms — explore what\'s possible!', 'sureforms' ),
1685 - esc_html__( 'Manage your forms, track submissions, and discover features like AI Form Builder, payment integrations, and more from the SureForms dashboard.', 'sureforms' ),
1686 - esc_url( admin_url( 'admin.php?page=sureforms_menu' ) ),
1687 - esc_html__( 'Go to Dashboard', 'sureforms' ),
1688 - esc_html__( 'Maybe later', 'sureforms' ),
1689 - esc_html__( 'I already know', 'sureforms' ),
1690 - WEEK_IN_SECONDS
1691 - ),
1692 - 'repeat-notice-after' => WEEK_IN_SECONDS,
1693 - 'show_if' => ! $this->maybe_display_rating_notice(),
1694 - 'display-notice-after' => WEEK_IN_SECONDS,
1695 - 'display-with-other-notices' => true,
1696 - ]
1697 - );
1698 -
1699 - add_action( 'astra_notice_after_markup_srfm-getting-started-notice', [ $this, 'enqueue_notice_response_script' ] );
1700 - }
1701 -
1702 - /**
1703 - * Enqueue the notice response analytics script.
1704 - *
1705 - * Called via the astra_notice_after_markup_{id} hook so the script
1706 - * only loads when a SureForms notice is actually rendered.
1707 - *
1708 - * @since 2.5.2
1709 - * @return void
1710 - */
1711 - public function enqueue_notice_response_script() {
1712 - if ( wp_script_is( 'srfm-notice-response', 'enqueued' ) ) {
1713 - return;
1714 - }
1715 -
1716 - wp_enqueue_script(
1717 - 'srfm-notice-response',
1718 - SRFM_URL . 'admin/assets/js/notice-response.js',
1719 - [],
1720 - SRFM_VER,
1721 - true
1722 - );
1723 -
1724 - wp_localize_script(
1725 - 'srfm-notice-response',
1726 - 'srfmNoticeResponse',
1727 - [
1728 - 'ajaxurl' => admin_url( 'admin-ajax.php' ),
1729 - 'nonce' => wp_create_nonce( 'srfm_notice_response' ),
1730 - ]
1731 - );
1732 - }
1733 -
1734 - /**
1735 - * Handle the notice response AJAX request.
1736 - *
1737 - * Validates the request and records the analytics event
1738 - * for the notice button that was clicked.
1739 - *
1740 - * @since 2.5.2
1741 - * @return void
1742 - */
1743 - public function handle_notice_response() {
1744 - if ( ! check_ajax_referer( 'srfm_notice_response', 'nonce', false ) ) {
1745 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1746 - }
1747 -
1748 - if ( ! Helper::current_user_can() ) {
1749 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1750 - }
1751 -
1752 - $notice_id = isset( $_POST['notice_id'] ) ? sanitize_text_field( wp_unslash( $_POST['notice_id'] ) ) : '';
1753 - $button = isset( $_POST['button'] ) ? sanitize_text_field( wp_unslash( $_POST['button'] ) ) : '';
1754 -
1755 - $valid = [
1756 - 'srfm-getting-started-notice' => [
1757 - 'go_to_dashboard' => 'getting_started_notice_cta',
1758 - 'maybe_later' => 'getting_started_notice_snooze',
1759 - 'dismissed' => 'getting_started_notice_dismiss',
1760 - ],
1761 - 'srfm-plugin-review-notice' => [
1762 - 'rate_sureforms' => 'rating_notice_cta',
1763 - 'maybe_later' => 'rating_notice_snooze',
1764 - 'dismissed' => 'rating_notice_dismiss',
1765 - ],
1766 - ];
1767 -
1768 - if ( ! isset( $valid[ $notice_id ][ $button ] ) ) {
1769 - wp_send_json_error( [ 'message' => __( 'Invalid parameters.', 'sureforms' ) ], 400 );
1770 - }
1771 -
1772 - $event_name = $valid[ $notice_id ][ $button ];
1773 - Analytics::events()->track( $event_name, $button );
1774 -
1775 - wp_send_json_success();
1776 - }
1777 -
1778 - /**
1779 844 * Disables the capabilities for WPForms to avoid conflicts when enqueueing
1780 845 * scripts and styles for WPForms.
1781 846 *
1782 847 * This function is intended to prevent any potential conflicts that may arise
@@ -1797,448 +862,5 @@
1797 862 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1798 863 $post_type = $post_id ? get_post_type( $post_id ) : sanitize_text_field( wp_unslash( $_REQUEST['post_type'] ?? '' ) );
1799 864 return SRFM_FORMS_POST_TYPE === $post_type ? false : $user_can;
1800 865 }
1801 -
1802 - /**
1803 - * Enqueueus the admin pointer script and styles.
1804 - *
1805 - * @return void
1806 - * @since 1.8.0
1807 - */
1808 - public function enqueue_admin_pointer() {
1809 - if ( ! $this->is_admin_pointer_visible() ) {
1810 - return;
1811 - }
1812 - wp_enqueue_style( 'wp-pointer' );
1813 - wp_enqueue_script( 'wp-pointer' );
1814 - wp_enqueue_script(
1815 - 'sureforms-admin-pointer',
1816 - plugins_url( 'admin/assets/js/sureforms-pointer.js', SRFM_FILE ),
1817 - [ 'wp-pointer', 'jquery' ],
1818 - SRFM_VER,
1819 - true
1820 - );
1821 - wp_localize_script(
1822 - 'sureforms-admin-pointer',
1823 - 'sureformsPointerData',
1824 - [
1825 - 'ajaxurl' => admin_url( 'admin-ajax.php' ),
1826 - 'pointer_nonce' => wp_create_nonce( 'sureforms_pointer_action' ),
1827 - ]
1828 - );
1829 - }
1830 -
1831 - /**
1832 - * Ajax handler for pointer popup visibility.
1833 - *
1834 - * @return void
1835 - * @since 1.8.0
1836 - */
1837 - public function pointer_should_show() {
1838 - // Security: Check user capability.
1839 - if ( ! Helper::current_user_can() ) {
1840 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1841 - }
1842 - // Security: Nonce check.
1843 - if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1844 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1845 - }
1846 -
1847 - $content_markup = sprintf(
1848 - /* translators: 1: opening span, 2: opening strong (inline), 3: closing strong, 4: closing span, 5: opening strong (block), 6: closing strong */
1849 - __( '%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' ),
1850 - '<span>',
1851 - '<strong>',
1852 - '</strong>',
1853 - '</span><br/>',
1854 - '<strong style="font-size:1.1em;">',
1855 - '</strong>'
1856 - );
1857 - wp_send_json(
1858 - [
1859 - 'show' => true,
1860 - 'title' => esc_html( __( 'SureForms is waiting for you!', 'sureforms' ) ),
1861 - 'content' => wp_kses_post( $content_markup ),
1862 - 'button_text' => esc_html( __( 'Build My First Form', 'sureforms' ) ),
1863 - 'dismiss' => esc_html( __( 'Dismiss', 'sureforms' ) ),
1864 - 'button_url' => admin_url( 'admin.php?page=add-new-form' ),
1865 - ]
1866 - );
1867 - }
1868 -
1869 - /**
1870 - * Ajax callback for pointer popup dismissed action.
1871 - *
1872 - * @return void
1873 - * @since 1.8.0
1874 - */
1875 - public function pointer_dismissed() {
1876 - // Security: Check user capability.
1877 - if ( ! Helper::current_user_can() ) {
1878 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1879 - }
1880 - // Security: Nonce check.
1881 - if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1882 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1883 - }
1884 - // Use Helper to update srfm_options key.
1885 - Helper::update_srfm_option( 'pointer_popup_dismissed', time() );
1886 -
1887 - wp_send_json_success();
1888 - }
1889 -
1890 - /**
1891 - * Ajax pointer accepted CTA callback.
1892 - *
1893 - * @return void
1894 - * @since 1.8.0
1895 - */
1896 - public function pointer_accepted_cta() {
1897 - // Security: Check user capability.
1898 - if ( ! Helper::current_user_can() ) {
1899 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1900 - }
1901 - // Security: Nonce check.
1902 - if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1903 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1904 - }
1905 - // Use Helper to update srfm_options key.
1906 - Helper::update_srfm_option( 'pointer_popup_accepted', time() );
1907 -
1908 - wp_send_json_success();
1909 - }
1910 -
1911 - /**
1912 - * Maybe register the dashboard widget based on entries.
1913 - *
1914 - * @return void
1915 - * @since 1.9.1
1916 - */
1917 - public function maybe_register_dashboard_widget() {
1918 -
1919 - // Only for users with manage_options capability.
1920 - if ( ! Helper::current_user_can() ) {
1921 - return;
1922 - }
1923 -
1924 - // Quick check if there are any entries in the last 7 days.
1925 - $seven_days_ago = strtotime( '-7 days' );
1926 - $total_entries = Entries::get_entries_count_after( $seven_days_ago );
1927 -
1928 - // Only add the dashboard setup hook if there are entries.
1929 - if ( $total_entries > 0 ) {
1930 - // Get forms with entries (limit 4 for dashboard widget).
1931 - $this->dashboard_widget_data = Helper::get_forms_with_entry_counts( $seven_days_ago, 4 );
1932 -
1933 - // Only show dashboard widget if there are forms with entries.
1934 - if ( ! empty( $this->dashboard_widget_data ) ) {
1935 - add_action( 'wp_dashboard_setup', [ $this, 'register_dashboard_widget' ] );
1936 - }
1937 - }
1938 - }
1939 -
1940 - /**
1941 - * Register the dashboard widget.
1942 - *
1943 - * @return void
1944 - * @since 1.9.1
1945 - */
1946 - public function register_dashboard_widget() {
1947 - // Add the widget with high priority to position it at the top.
1948 - wp_add_dashboard_widget(
1949 - 'sureforms_recent_entries',
1950 - __( 'SureForms', 'sureforms' ),
1951 - [ $this, 'render_dashboard_widget' ],
1952 - null,
1953 - null,
1954 - 'normal',
1955 - 'high'
1956 - );
1957 - }
1958 -
1959 - /**
1960 - * Render the dashboard widget content.
1961 - *
1962 - * @return void
1963 - * @since 1.9.1
1964 - */
1965 - public function render_dashboard_widget() {
1966 - // Use the pre-fetched data to avoid duplicate queries.
1967 - $entries_data = $this->dashboard_widget_data;
1968 -
1969 - // Display the widget content.
1970 - ?>
1971 - <div class="srfm-dashboard-widget">
1972 - <div class="srfm-widget-header">
1973 - <h3 class="srfm-widget-title">
1974 - <?php esc_html_e( 'Recent Entries', 'sureforms' ); ?>
1975 - <span class="srfm-widget-subtitle"><?php esc_html_e( '( Last 7 days )', 'sureforms' ); ?></span>
1976 - </h3>
1977 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=sureforms_entries' ) ); ?>" class="srfm-widget-view-link">
1978 - <?php esc_html_e( 'View', 'sureforms' ); ?>
1979 - </a>
1980 - </div>
1981 -
1982 - <div class="srfm-table-wrapper">
1983 - <table class="srfm-entries-table">
1984 - <thead>
1985 - <tr>
1986 - <th><?php esc_html_e( 'Form Name', 'sureforms' ); ?></th>
1987 - <th><?php esc_html_e( 'Entries', 'sureforms' ); ?></th>
1988 - </tr>
1989 - </thead>
1990 - <tbody>
1991 - <?php foreach ( $entries_data as $form_data ) { ?>
1992 - <tr>
1993 - <td class="form-name"><?php echo esc_html( $form_data['title'] ); ?></td>
1994 - <td class="entry-count"><?php echo esc_html( $form_data['count'] ); ?></td>
1995 - </tr>
1996 - <?php } ?>
1997 - </tbody>
1998 - </table>
1999 - </div>
2000 -
2001 - <?php
2002 - // Render footer if applicable.
2003 - $this->render_dashboard_widget_footer( $entries_data );
2004 - ?>
2005 - </div>
2006 - <?php
2007 - }
2008 -
2009 - /**
2010 - * Determine whether a notice callback is owned by SureForms.
2011 - *
2012 - * Recognises object methods on classes in the `SRFM` / `SRFM_PRO` namespaces
2013 - * as well as the bundled notices libraries (`BSF_Admin_Notices` and the
2014 - * legacy `Astra_Notices` alias). Everything else is treated as foreign.
2015 - *
2016 - * @param callable|array|string|null $function The registered callback function.
2017 - * @since 2.10.0
2018 - * @return bool True when the callback belongs to SureForms, false otherwise.
2019 - */
2020 - private function is_sureforms_owned_notice_callback( $function ) {
2021 - $class_name = '';
2022 -
2023 - if ( is_array( $function ) && isset( $function[0] ) ) {
2024 - // Object or static method callback represented as an array. The first
2025 - // element is either the object instance or the fully qualified class name.
2026 - $class_name = is_object( $function[0] ) ? get_class( $function[0] ) : (string) $function[0];
2027 - } elseif ( is_string( $function ) && false !== strpos( $function, '::' ) ) {
2028 - // Static method passed as "Class::method".
2029 - $class_name = strstr( $function, '::', true );
2030 - }
2031 -
2032 - if ( '' === $class_name ) {
2033 - // Plain function callbacks are never owned by SureForms.
2034 - return false;
2035 - }
2036 -
2037 - // SureForms (free and pro) namespaced classes. Pro's real namespace is
2038 - // `SRFM_Pro\` (case-sensitive) — not the all-caps `SRFM_PRO_` constant
2039 - // prefix — so match it case-insensitively to be safe.
2040 - if ( 0 === strpos( $class_name, 'SRFM\\' ) || 0 === stripos( $class_name, 'SRFM_Pro\\' ) ) {
2041 - return true;
2042 - }
2043 -
2044 - // Bundled notices library shipped with SureForms.
2045 - return in_array( $class_name, [ 'BSF_Admin_Notices', 'Astra_Notices' ], true );
2046 - }
2047 -
2048 - /**
2049 - * Whether the current admin page is a SureForms-owned screen identified by a
2050 - * `sureforms_*` / `srfm_*` `page` query slug. Complements
2051 - * {@see Helper::is_sureforms_admin_page()} so foreign-notice suppression also
2052 - * covers the payments / quiz / survey / learn / SMTP / partial-entries screens
2053 - * that the core helper does not enumerate. Read-only screen check.
2054 - *
2055 - * @since 2.10.0
2056 - * @return bool
2057 - */
2058 - private function is_sureforms_owned_admin_page() {
2059 - if ( ! is_admin() || empty( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only screen detection, no state change.
2060 - return false;
2061 - }
2062 - $page = sanitize_key( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only screen detection, no state change.
2063 - return 0 === strpos( $page, 'sureforms' ) || 0 === strpos( $page, 'srfm' );
2064 - }
2065 -
2066 - /**
2067 - * Build the shared HTML markup for admin notices.
2068 - *
2069 - * @since 2.5.2
2070 - *
2071 - * All text parameters must be pre-escaped by the caller (e.g. via esc_html__()).
2072 - * URL parameters must be pre-escaped via esc_url().
2073 - *
2074 - * @param string $heading The notice heading text (pre-escaped).
2075 - * @param string $message The notice body text (pre-escaped).
2076 - * @param string $cta_url The primary CTA URL (pre-escaped).
2077 - * @param string $cta_text The primary CTA button text (pre-escaped).
2078 - * @param string $snooze_text The snooze button text (pre-escaped).
2079 - * @param string $dismiss_text The dismiss button text (pre-escaped).
2080 - * @param int $snooze_duration Snooze duration in seconds for the data-repeat-notice-after attribute.
2081 - * @param bool $external_cta Whether the CTA opens in a new tab and also dismisses the notice
2082 - * via the astra-notice-close class. Default false.
2083 - * @return string The notice HTML markup.
2084 - */
2085 - private function build_notice_markup( $heading, $message, $cta_url, $cta_text, $snooze_text, $dismiss_text, $snooze_duration, $external_cta = false ) {
2086 - $image_path = esc_url( SRFM_URL . 'admin/assets/sureforms-logo.png' );
2087 - $cta_class = $external_cta ? 'astra-notice-close button-primary' : 'button-primary';
2088 - $cta_attrs = $external_cta ? ' target="_blank" rel="noopener noreferrer"' : '';
2089 -
2090 - return sprintf(
2091 - '<div class="notice-image">
2092 - <img src="%1$s" class="custom-logo" alt="SureForms" itemprop="logo">
2093 - </div>
2094 - <div class="notice-content">
2095 - <div class="notice-heading">
2096 - %2$s
2097 - </div>
2098 - %3$s<br />
2099 - <div class="astra-review-notice-container">
2100 - <a href="%4$s" class="%5$s"%6$s>
2101 - %7$s
2102 - </a>
2103 - <span class="dashicons dashicons-clock" aria-hidden="true"></span>
2104 - <a href="#" data-repeat-notice-after="%8$s" class="astra-notice-close">
2105 - %9$s
2106 - </a>
2107 - <span class="dashicons dashicons-smiley" aria-hidden="true"></span>
2108 - <a href="#" class="astra-notice-close">
2109 - %10$s
2110 - </a>
2111 - </div>
2112 - </div>',
2113 - $image_path,
2114 - $heading,
2115 - $message,
2116 - $cta_url,
2117 - esc_attr( $cta_class ),
2118 - $cta_attrs,
2119 - $cta_text,
2120 - $snooze_duration,
2121 - $snooze_text,
2122 - $dismiss_text
2123 - );
2124 - }
2125 -
2126 - /**
2127 - * Callback for displaying the rating notice conditionally.
2128 - *
2129 - * Returns true if the user has 3 or more published forms or 3 or more form entries.
2130 - *
2131 - * @since 2.5.2
2132 - * @return bool
2133 - */
2134 - private function maybe_display_rating_notice() {
2135 - if ( null === $this->should_show_rating ) {
2136 - $entries_count = Entries::get_total_entries_by_status( 'all' );
2137 - $form_count = wp_count_posts( SRFM_FORMS_POST_TYPE );
2138 - $this->should_show_rating = $entries_count >= self::RATING_NOTICE_THRESHOLD || Helper::get_integer_value( $form_count->publish ?? 0 ) >= self::RATING_NOTICE_THRESHOLD;
2139 - }
2140 -
2141 - return $this->should_show_rating;
2142 - }
2143 -
2144 - /**
2145 - * Get random premium feature text.
2146 - *
2147 - * @return string Random feature text.
2148 - * @since 1.9.1
2149 - */
2150 - private function get_random_premium_feature_text() {
2151 - $features = [
2152 - __( 'Use Conditional Logic to show only what matters', 'sureforms' ),
2153 - __( 'Split your form into steps to keep it easy', 'sureforms' ),
2154 - __( 'Let people upload files directly to your form', 'sureforms' ),
2155 - __( 'Turn responses into downloadable PDFs automatically', 'sureforms' ),
2156 - __( 'Let users sign with a simple signature field', 'sureforms' ),
2157 - __( 'Connect your form to other tools using webhooks', 'sureforms' ),
2158 - __( 'Use Conversational Forms for a chat-like experience', 'sureforms' ),
2159 - __( 'Let users register or log in through your form', 'sureforms' ),
2160 - __( 'Build forms that create WordPress user accounts', 'sureforms' ),
2161 - __( 'Add calculations to auto-total scores or prices', 'sureforms' ),
2162 - ];
2163 -
2164 - // Get a random feature.
2165 - $random_key = array_rand( $features );
2166 - return $features[ $random_key ];
2167 - }
2168 -
2169 - /**
2170 - * Render the dashboard widget footer for upsell.
2171 - *
2172 - * @param array $entries_data The entries data array.
2173 - * @return void
2174 - * @since 1.9.1
2175 - */
2176 - private function render_dashboard_widget_footer( $entries_data ) {
2177 - // Only show footer if Pro is not active.
2178 - if ( Helper::has_pro() ) {
2179 - return;
2180 - }
2181 -
2182 - // Count total entries in last 7 days.
2183 - $total_entries = 0;
2184 - foreach ( $entries_data as $form_data ) {
2185 - $total_entries += $form_data['count'];
2186 - }
2187 -
2188 - // Count total published forms.
2189 - $published_forms_count = wp_count_posts( SRFM_FORMS_POST_TYPE )->publish;
2190 -
2191 - // Show footer only if 3+ entries received OR 3+ forms published.
2192 - if ( $total_entries >= 3 || $published_forms_count >= 3 ) {
2193 - ?>
2194 - <div class="srfm-widget-footer">
2195 - <div class="srfm-upgrade-content">
2196 - <svg class="srfm-logo-icon" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2197 - <rect width="20" height="20" fill="#D54407"/>
2198 - <path d="M5.7139 4.2854H14.2853V7.1425H7.1424L5.7139 8.5711V7.1425V4.2854Z" fill="white"/>
2199 - <path d="M5.7139 4.2854H14.2853V7.1425H7.1424L5.7139 8.5711V7.1425V4.2854Z" fill="white"/>
2200 - <path d="M5.7148 8.5713H12.8577V11.4284H7.1434L5.7148 12.857V11.4284V8.5713Z" fill="white"/>
2201 - <path d="M5.7148 8.5713H12.8577V11.4284H7.1434L5.7148 12.857V11.4284V8.5713Z" fill="white"/>
2202 - <path d="M5.7148 12.8569H10.0006V15.7141H5.7148V12.8569Z" fill="white"/>
2203 - <path d="M5.7148 12.8569H10.0006V15.7141H5.7148V12.8569Z" fill="white"/>
2204 - </svg>
2205 - <span><?php echo esc_html( $this->get_random_premium_feature_text() ); ?></span>
2206 - </div>
2207 - <?php
2208 - $upgrade_url = Helper::get_sureforms_website_url( 'pricing', [ 'utm_medium' => 'dashboard-widget' ] );
2209 - ?>
2210 - <a href="<?php echo esc_url( $upgrade_url ); ?>" class="srfm-upgrade-link" target="_blank">
2211 - <?php esc_html_e( 'Upgrade', 'sureforms' ); ?>
2212 - </a>
2213 - </div>
2214 - <?php
2215 - }
2216 - }
2217 -
2218 - /**
2219 - * Determine if the admin pointer should be visible on this page.
2220 - *
2221 - * @since 1.8.0
2222 - * @return bool
2223 - */
2224 - private function is_admin_pointer_visible() {
2225 - global $pagenow;
2226 - $allowed_pages = [ 'index.php', 'options-general.php' ];
2227 -
2228 - // Do not show if pointer dismissed, accepted, or more than 1 form exists.
2229 - if (
2230 - ! empty( Helper::get_srfm_option( 'pointer_popup_dismissed' ) )
2231 - || ! empty( Helper::get_srfm_option( 'pointer_popup_accepted' ) )
2232 - || (int) ( wp_count_posts( SRFM_FORMS_POST_TYPE )->publish ?? 0 ) > 1
2233 - ) {
2234 - return false;
2235 - }
2236 -
2237 - if ( in_array( $pagenow, $allowed_pages, true ) ) {
2238 - return true;
2239 - }
2240 -
2241 - return false;
2242 - }
2243 -
2244 866 }