PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 1.0.3
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v1.0.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 +174 -1506 2.7.11.0.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,208 +35,33 @@
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' ] );
80 - add_action( 'admin_menu', [ $this, 'add_upgrade_to_pro' ] );
81 - add_action( 'admin_footer', [ $this, 'add_upgrade_to_pro_target_attr' ] );
82 - }
83 -
84 40 add_filter( 'plugin_action_links', [ $this, 'add_settings_link' ], 10, 2 );
85 41 add_action( 'enqueue_block_assets', [ $this, 'enqueue_styles' ] );
86 42 add_action( 'admin_head', [ $this, 'enqueue_header_styles' ] );
87 - add_filter( 'admin_body_class', [ $this, 'admin_template_picker_body_class' ] );
43 + add_action( 'admin_body_class', [ $this, 'admin_template_picker_body_class' ] );
88 44
89 45 // this action is used to restrict Spectra's quick action bar on SureForms CPTS.
90 46 add_action( 'uag_enable_quick_action_sidebar', [ $this, 'restrict_spectra_quick_action_bar' ] );
91 47
92 48 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 - add_action( 'admin_notices', [ $this, 'srfm_pro_version_compatibility' ] );
97 49
98 - // Enfold theme compatibility to enable block editor for SureForms post type.
99 - add_filter( 'avf_use_block_editor_for_post', [ $this, 'enable_block_editor_in_enfold_theme' ] );
100 -
101 - // Add action links to the plugin page.
102 - 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 - 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' ] );
50 + // Handle entry actions.
51 + add_action( 'admin_init', [ $this, 'handle_entry_actions' ] );
52 + add_action( 'admin_notices', [ Entries_List_Table::class, 'display_bulk_action_notice' ] );
127 53 }
128 54
129 55 /**
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 - * Show action on plugin page.
224 - *
225 - * @param array $links links.
226 - * @return array
227 - * @since 1.4.2
228 - */
229 - public function add_action_links( $links ) {
230 - if ( ! Helper::has_pro() ) {
231 - // Display upsell link if SureForms Pro is not installed.
232 - $upsell_link = add_query_arg(
233 - [
234 - 'utm_medium' => 'plugin-list',
235 - ],
236 - Helper::get_sureforms_website_url( 'pricing' )
237 - );
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() );
246 - }
247 -
248 - return $links;
249 - }
250 -
251 - /**
252 - * Enable block editor in Enfold theme for SureForms post type.
253 - *
254 - * @param bool $use_block_editor Whether to use block editor.
255 - * @since 1.3.1
256 - */
257 - public function enable_block_editor_in_enfold_theme( $use_block_editor ) {
258 - // if SureForms form post type then return true.
259 - if ( SRFM_FORMS_POST_TYPE === get_current_screen()->post_type ) {
260 - return true;
261 - }
262 - return $use_block_editor;
263 - }
264 -
265 - /**
266 56 * Enable Gutenberg for SureForms associated post types.
267 57 *
268 58 * @since 0.0.10
269 59 */
270 60 public function enable_gutenberg_for_sureforms() {
271 - /**
272 - * Check if the classic editor is enabled from Classic Editor plugin settings or Divi settings.
273 - */
274 - if ( 'block' === get_option( 'classic-editor-replace' ) || 'on' === get_option( 'et_enable_classic_editor' ) ) {
61 +
62 + // Check if the Classic Editor plugin is active and if it is set to replace the block editor.
63 + if ( ! class_exists( 'Classic_Editor' ) || 'block' === get_option( 'classic-editor-replace' ) ) {
275 64 return;
276 65 }
277 66
278 67 $srfm_post_types = apply_filters( 'srfm_enable_gutenberg_post_types', [ SRFM_FORMS_POST_TYPE ] );
@@ -311,15 +100,20 @@
311 100 * @return void
312 101 * @since 0.0.1
313 102 */
314 103 public function add_menu_page() {
315 - $menu_slug = 'sureforms_menu';
104 + if ( ! current_user_can( 'manage_options' ) ) {
105 + return;
106 + }
316 107
108 + $capability = 'manage_options';
109 + $menu_slug = 'sureforms_menu';
110 +
317 111 $logo = file_get_contents( plugin_dir_path( SRFM_FILE ) . 'images/icon.svg' );
318 112 add_menu_page(
319 113 __( 'SureForms', 'sureforms' ),
320 114 __( 'SureForms', 'sureforms' ),
321 - self::$sureforms_page_default_capability,
115 + 'edit_others_posts',
322 116 $menu_slug,
323 117 static function () {
324 118 },
325 119 'data:image/svg+xml;base64,' . base64_encode( $logo ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
@@ -330,9 +124,9 @@
330 124 add_submenu_page(
331 125 $menu_slug,
332 126 __( 'Dashboard', 'sureforms' ),
333 127 __( 'Dashboard', 'sureforms' ),
334 - self::$sureforms_page_default_capability,
128 + $capability,
335 129 $menu_slug,
336 130 [ $this, 'render_dashboard' ]
337 131 );
338 132 }
@@ -348,9 +142,9 @@
348 142 add_submenu_page(
349 143 'sureforms_menu',
350 144 __( 'Settings', 'sureforms' ),
351 145 __( 'Settings', 'sureforms' ),
352 - self::$sureforms_page_default_capability,
146 + 'edit_others_posts',
353 147 'sureforms_form_settings',
354 148 $callback
355 149 );
356 150
@@ -363,129 +157,8 @@
363 157 }
364 158 }
365 159
366 160 /**
367 - * Open to Upgrade to Pro submenu link in new tab.
368 - *
369 - * @return void
370 - * @since 1.6.1
371 - */
372 - public function add_upgrade_to_pro_target_attr() {
373 - ?>
374 - <script type="text/javascript">
375 - document.addEventListener('DOMContentLoaded', function () {
376 - // Upgrade link handler.
377 - // IMPORTANT: If this URL changes, also update it in the `add_upgrade_to_pro` function.
378 - const upgradeLink = document.querySelector('a[href*="https://sureforms.com/upgrade"]');
379 - if (upgradeLink) {
380 - upgradeLink.addEventListener('click', e => {
381 - e.preventDefault();
382 - window.open(upgradeLink.href, '_blank');
383 - });
384 - }
385 - });
386 - </script>
387 - <?php
388 - }
389 -
390 - /**
391 - * Add Upgrade to pro menu item.
392 - *
393 - * @return void
394 - * @since 1.6.1
395 - */
396 - public function add_upgrade_to_pro() {
397 - // The url used here is used as a selector for css to style the upgrade to pro submenu.
398 - // If you are changing this url, please make sure to update the css as well.
399 - $upgrade_url = add_query_arg(
400 - [
401 - 'utm_medium' => 'submenu_link_upgrade',
402 - ],
403 - Helper::get_sureforms_website_url( 'upgrade' )
404 - );
405 -
406 - add_submenu_page(
407 - 'sureforms_menu',
408 - __( 'Upgrade', 'sureforms' ),
409 - __( 'Upgrade', 'sureforms' ),
410 - self::$sureforms_page_default_capability,
411 - $upgrade_url
412 - );
413 - }
414 -
415 - /**
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 161 * Render Admin Dashboard.
489 162 *
490 163 * @return void
491 164 * @since 0.0.1
@@ -490,11 +163,9 @@
490 163 * @return void
491 164 * @since 0.0.1
492 165 */
493 166 public function render_dashboard() {
494 - ?>
495 - <div id="srfm-dashboard-container" class="srfm-admin-wrapper"></div>
496 - <?php
167 + echo '<div id="srfm-dashboard-container"></div>';
497 168 }
498 169
499 170 /**
500 171 * Settings page callback.
@@ -502,43 +173,12 @@
502 173 * @return void
503 174 * @since 0.0.1
504 175 */
505 176 public function settings_page_callback() {
506 - ?>
507 - <div id="srfm-settings-container" class="srfm-admin-wrapper"></div>
508 - <?php
177 + echo '<div id="srfm-settings-container"></div>';
509 178 }
510 179
511 180 /**
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 181 * Add new form menu item.
542 182 *
543 183 * @return void
544 184 * @since 0.0.1
@@ -545,62 +185,27 @@
545 185 */
546 186 public function add_new_form() {
547 187 add_submenu_page(
548 188 '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 189 __( 'New Form', 'sureforms' ),
559 190 __( 'New Form', 'sureforms' ),
560 - self::$sureforms_page_default_capability,
191 + 'edit_others_posts',
561 192 'add-new-form',
562 193 [ $this, 'add_new_form_callback' ],
563 194 2
564 195 );
565 - $entries_hook = add_submenu_page(
196 + add_submenu_page(
566 197 'sureforms_menu',
567 198 __( 'Entries', 'sureforms' ),
568 199 __( 'Entries', 'sureforms' ),
569 - self::$sureforms_page_default_capability,
200 + 'edit_others_posts',
570 201 SRFM_ENTRIES,
571 202 [ $this, 'render_entries' ],
572 203 3
573 204 );
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 205 }
589 206
590 207 /**
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 208 * Add new form mentu item callback.
604 209 *
605 210 * @return void
606 211 * @since 0.0.1
@@ -605,109 +210,44 @@
605 210 * @return void
606 211 * @since 0.0.1
607 212 */
608 213 public function add_new_form_callback() {
609 - ?>
610 - <div id="srfm-add-new-form-container" class="srfm-admin-wrapper"></div>
611 - <?php
214 + echo '<div id="srfm-add-new-form-container"></div>';
612 215 }
613 216
614 217 /**
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 218 * Entries page callback.
628 219 *
629 220 * @since 0.0.13
630 - * @since 2.0.0 - Updated the entries UI and the function definition.
631 221 * @return void
632 222 */
633 223 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() ) {
224 + // Render single entry view.
225 + // Adding the phpcs ignore nonce verification as no database operations are performed in this function, it is used to display the single entry view.
226 + if ( isset( $_GET['entry_id'] ) && is_numeric( $_GET['entry_id'] ) && isset( $_GET['view'] ) && 'details' === $_GET['view'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
227 + $single_entry_view = new Single_Entry();
228 + $single_entry_view->render();
645 229 return;
646 230 }
647 231
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();
232 + // Render all entries view.
233 + $entries_table = new Entries_List_Table();
234 + $entries_table->prepare_items();
235 + echo '<div class="wrap"><h1 class="wp-heading-inline">Entries</h1>';
236 + if ( empty( $entries_table->all_entries_count ) && empty( $entries_table->trash_entries_count ) ) {
237 + $instance = Post_Types::get_instance();
238 + $instance->sureforms_render_blank_state( SRFM_ENTRIES );
239 + $instance->get_blank_state_styles();
651 240 return;
652 241 }
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 - }
242 + echo '<form method="get">';
243 + echo '<input type="hidden" name="page" value="sureforms_entries">';
244 + $entries_table->display();
245 + echo '</form>';
246 + echo '</div>';
693 247 }
694 248
695 249 /**
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 250 * Adds a settings link to the plugin action links on the plugins page.
711 251 *
712 252 * @param array $links An array of plugin action links.
713 253 * @param string $file The plugin file path.
@@ -715,22 +255,15 @@
715 255 * @since 0.0.1
716 256 */
717 257 public function add_settings_link( $links, $file ) {
718 258 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(
259 + $plugin_links = apply_filters(
727 260 'sureforms_plugin_action_links',
728 261 [
729 - 'sureforms_settings' => $settings_link_html,
262 + 'sureforms_settings' => '<a href="' . esc_url( admin_url( 'admin.php?page=sureforms_form_settings&tab=general-settings' ) ) . '">' . esc_html__( 'Settings', 'sureforms' ) . '</a>',
730 263 ]
731 264 );
732 - $links = array_merge( $plugin_links, $links );
265 + $links = array_merge( $plugin_links, $links );
733 266 }
734 267 return $links;
735 268 }
736 269
@@ -740,9 +273,8 @@
740 273 * @since 0.0.1
741 274 */
742 275 public function enqueue_styles() {
743 276 $current_screen = get_current_screen();
744 - global $wp_version;
745 277
746 278 $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
747 279 $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
748 280
@@ -761,16 +293,8 @@
761 293 wp_enqueue_style( SRFM_SLUG . '-intl', $vendor_css_uri . 'intl/intlTelInput-backend.min.css', [], SRFM_VER );
762 294 wp_enqueue_style( SRFM_SLUG . '-common', $css_uri . 'common' . $file_prefix . '.css', [], SRFM_VER );
763 295 wp_enqueue_style( SRFM_SLUG . '-reactQuill', $vendor_css_uri . 'quill/quill.snow.css', [], SRFM_VER );
764 296 wp_enqueue_style( SRFM_SLUG . '-single-form-modal', $css_uri . 'single-form-setting' . $file_prefix . '.css', [], SRFM_VER );
765 -
766 - // if version is equal to or lower than 6.6.2 then add compatibility css.
767 - if ( version_compare( $wp_version, '6.6.2', '<=' ) ) {
768 - $srfm_inline_css = '.srfm-settings-modal .srfm-setting-modal-container .components-toggle-control .components-base-control__help{
769 - margin-left: 4em;
770 - }';
771 - wp_add_inline_style( SRFM_SLUG . '-single-form-modal', $srfm_inline_css );
772 - }
773 297 }
774 298
775 299 wp_enqueue_style( SRFM_SLUG . '-form-selector', $css_uri . 'srfm-form-selector' . $file_prefix . '.css', [], SRFM_VER );
776 300 wp_enqueue_style( SRFM_SLUG . '-common-editor', SRFM_URL . 'assets/build/common-editor.css', [], SRFM_VER, 'all' );
@@ -785,9 +309,9 @@
785 309 public function get_breadcrumbs_for_current_page() {
786 310 global $post, $pagenow;
787 311 $breadcrumbs = [];
788 312
789 - if ( 'admin.php' === $pagenow && isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We don't need nonce verification here.
313 + if ( 'admin.php' === $pagenow && isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
790 314 $page_title = get_admin_page_title();
791 315 $breadcrumbs[] = [
792 316 'title' => $page_title,
793 317 'link' => '',
@@ -800,9 +324,9 @@
800 324 'title' => $post_type_plural,
801 325 'link' => admin_url( 'edit.php?post_type=' . $post_type_obj->name ),
802 326 ];
803 327
804 - if ( 'edit.php' === $pagenow && ! isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We don't need nonce verification here.
328 + if ( 'edit.php' === $pagenow && ! isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
805 329 $breadcrumbs[ count( $breadcrumbs ) - 1 ]['link'] = '';
806 330 } else {
807 331 $breadcrumbs[] = [
808 332 /* Translators: Post Title. */
@@ -836,124 +360,38 @@
836 360 * @since 0.0.1
837 361 */
838 362 public function enqueue_scripts() {
839 363 $current_screen = get_current_screen();
840 - global $wp_version;
841 364
842 - $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
843 - $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
844 - $css_uri = SRFM_URL . 'assets/css/' . $dir_name . '/';
845 - $is_rtl = is_rtl();
846 - $rtl = $is_rtl ? '-rtl' : '';
365 + $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
366 + $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
367 + $js_uri = SRFM_URL . 'assets/js/' . $dir_name . '/';
368 + $css_uri = SRFM_URL . 'assets/css/' . $dir_name . '/';
847 369
848 - /**
849 - * List of the handles in which we need to add translation compatibility.
850 - */
851 - $script_translations_handlers = [];
852 - $onboarding_instance = Onboarding::get_instance();
853 - $current_user = wp_get_current_user();
370 + /* RTL */
371 + if ( is_rtl() ) {
372 + $file_prefix .= '-rtl';
373 + }
854 374
855 375 $localization_data = [
856 - 'site_url' => get_site_url(),
857 - 'current_user_login' => $current_user->user_login ?? '',
858 - 'website_lead_details' => [
859 - 'first_name' => $current_user->first_name ?? '',
860 - 'last_name' => $current_user->last_name ?? '',
861 - 'email' => $current_user->user_email ?? '',
862 - ],
863 - 'breadcrumbs' => $this->get_breadcrumbs_for_current_page(),
864 - 'sureforms_dashboard_url' => admin_url( '/admin.php?page=sureforms_menu' ),
865 - 'plugin_version' => SRFM_VER,
866 - 'global_settings_nonce' => Helper::current_user_can() ? wp_create_nonce( 'wp_rest' ) : '',
867 - 'is_pro_active' => Helper::has_pro(),
868 - 'is_first_form_created' => self::is_first_form_created(),
869 - 'check_three_days_threshold' => self::check_first_form_creation_threshold(),
870 - 'check_eight_days_threshold' => self::check_first_form_creation_threshold( 8 ),
871 - 'pro_plugin_version' => Helper::has_pro() ? SRFM_PRO_VER : '',
872 - 'pro_plugin_name' => Helper::has_pro() && defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro',
873 - 'sureforms_pricing_page' => Helper::get_sureforms_website_url( 'pricing' ),
874 - 'field_spacing_vars' => Helper::get_css_vars(),
875 - 'is_ver_lower_than_6_7' => version_compare( $wp_version, '6.6.2', '<=' ),
876 - 'integrations' => Helper::sureforms_get_integration(),
877 - 'rotating_plugin_banner' => Helper::get_rotating_plugin_banner(),
878 - 'ajax_url' => admin_url( 'admin-ajax.php' ),
879 - 'sf_plugin_manager_nonce' => wp_create_nonce( 'sf_plugin_manager_nonce' ),
880 - 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
881 - 'plugin_activating_text' => __( 'Activating...', 'sureforms' ),
882 - 'plugin_activated_text' => __( 'Activated', 'sureforms' ),
883 - 'plugin_activate_text' => __( 'Activate', 'sureforms' ),
884 - 'plugin_installing_text' => __( 'Installing...', 'sureforms' ),
885 - 'plugin_installed_text' => __( 'Installed', 'sureforms' ),
886 - 'privacy_policy_url' => Helper::get_sureforms_website_url( 'privacy-policy/' ),
887 - 'is_rtl' => $is_rtl,
888 - 'onboarding_completed' => method_exists( $onboarding_instance, 'get_onboarding_status' ) ? $onboarding_instance->get_onboarding_status() : false,
889 - 'onboarding_redirect' => isset( $_GET['srfm-activation-redirect'] ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce is not required for the activation redirection.
890 - 'pointer_nonce' => wp_create_nonce( 'sureforms_pointer_action' ),
891 - 'general_settings_url' => admin_url( '/options-general.php' ),
892 - 'additional_header_nav_items' => [],
893 - 'payments' => apply_filters(
894 - 'srfm_admin_localize_payments_data',
895 - [
896 - 'stripe_connected' => Stripe_Helper::is_stripe_connected(),
897 - 'stripe_mode' => Stripe_Helper::get_stripe_mode(),
898 - 'stripe_connect_url' => Stripe_Helper::get_stripe_settings_url(),
899 - 'currencies_data' => Payment_Helper::get_all_currencies_data(),
900 - 'zero_decimal_currencies' => Payment_Helper::get_zero_decimal_currencies(),
901 - 'webhook_url' => Stripe_Helper::get_webhook_url(),
902 - 'webhook_test_connected' => Stripe_Helper::is_webhook_configured( 'test', true ),
903 - 'webhook_live_connected' => Stripe_Helper::is_webhook_configured( 'live', true ),
904 - 'is_transaction_present' => Stripe_Helper::is_transaction_present(),
905 - 'payment_currency' => Payment_Helper::get_currency(),
906 - 'currency_sign_position' => Payment_Helper::get_currency_sign_position(),
907 - ]
908 - ),
909 - 'mcp_adapter_status' => file_exists( WP_PLUGIN_DIR . '/mcp-adapter/mcp-adapter.php' )
910 - ? ( is_plugin_active( 'mcp-adapter/mcp-adapter.php' ) ? 'active' : 'installed' )
911 - : 'not_installed',
376 + 'site_url' => get_site_url(),
377 + 'breadcrumbs' => $this->get_breadcrumbs_for_current_page(),
378 + 'sureforms_dashboard_url' => admin_url( '/admin.php?page=sureforms_menu' ),
379 + 'plugin_version' => SRFM_VER,
380 + 'global_settings_nonce' => current_user_can( 'manage_options' ) ? wp_create_nonce( 'wp_rest' ) : '',
381 + 'is_pro_active' => defined( 'SRFM_PRO_VER' ),
382 + 'pro_plugin_version' => defined( 'SRFM_PRO_VER' ) ? SRFM_PRO_VER : '',
383 + 'pro_plugin_name' => defined( 'SRFM_PRO_VER' ) && defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro',
384 + 'sureforms_pricing_page' => $this->get_sureforms_website_url( 'pricing' ),
385 + 'field_spacing_vars' => Helper::get_css_vars(),
912 386 ];
913 387
914 - $is_screen_sureforms_menu = Helper::validate_request_context( 'sureforms_menu', 'page' );
915 - $is_screen_add_new_form = Helper::validate_request_context( 'add-new-form', 'page' );
916 - $is_screen_sureforms_forms = Helper::validate_request_context( 'sureforms_forms', 'page' );
917 - $is_screen_sureforms_form_settings = Helper::validate_request_context( 'sureforms_form_settings', 'page' );
918 - $is_screen_sureforms_payments = Helper::validate_request_context( 'sureforms_payments', 'page' );
919 - $is_screen_sureforms_entries = Helper::validate_request_context( SRFM_ENTRIES, 'page' );
920 - $is_screen_sureforms_learn = Helper::validate_request_context( 'sureforms_learn', 'page' );
921 - $is_screen_quiz_empty_state = Helper::validate_request_context( 'sureforms_quiz_entries', 'page' );
922 - $is_post_type_sureforms_form = SRFM_FORMS_POST_TYPE === $current_screen->post_type;
923 -
924 - /**
925 - * Check if the current screen is the SureForms Menu and AI Auth Email is present then we will add user type as registered.
926 - * Compatibility with existing UI code that checks for this condition.
927 - */
928 - if ( $is_screen_sureforms_menu ) {
929 - // If email is stored send the user type as registered else non-registered.
930 - $localization_data['srfm_ai_details'] = [
931 - 'type' => ! empty( get_option( 'srfm_ai_auth_user_email' ) ) ? 'registered' : 'non-registered',
932 - ];
388 + if ( class_exists( 'SRFM_PRO\Admin\Licensing' ) ) {
389 + $license_active = \SRFM_PRO\Admin\Licensing::is_license_active();
390 + $localization_data['is_license_active'] = $license_active;
933 391 }
934 392
935 - // Add the Quizzes nav item to the header when pro is not active.
936 - if ( ! Helper::has_pro() ) {
937 - $localization_data['additional_header_nav_items'][] = [
938 - 'slug' => 'sureforms_quiz_entries',
939 - 'text' => __( 'Quizzes', 'sureforms' ),
940 - 'link' => admin_url( 'admin.php?page=sureforms_quiz_entries' ),
941 - ];
942 - }
943 -
944 - $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;
945 -
946 - /**
947 - * Filter to allow extending the SureForms dashboard screen check.
948 - *
949 - * @since 2.6.0
950 - *
951 - * @param bool $is_sureforms_screen Whether the current screen is a SureForms dashboard screen.
952 - */
953 - $is_sureforms_screen = apply_filters( 'srfm_is_dashboard_screen', $is_sureforms_screen );
954 -
955 - if ( $is_sureforms_screen ) {
393 + if ( SRFM_FORMS_POST_TYPE === $current_screen->post_type || 'toplevel_page_sureforms_menu' === $current_screen->base || 'sureforms_page_sureforms_form_settings' === $current_screen->id || 'sureforms_page_' . SRFM_ENTRIES === $current_screen->id ) {
956 394 $asset_handle = '-dashboard';
957 395
958 396 wp_enqueue_style( SRFM_SLUG . $asset_handle . '-font', 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap', [], SRFM_VER );
959 397
@@ -967,24 +405,9 @@
967 405 wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/dashboard.js', $script_info['dependencies'], SRFM_VER, true );
968 406
969 407 wp_localize_script( SRFM_SLUG . $asset_handle, 'scIcons', [ 'path' => SRFM_URL . 'assets/build/icon-assets' ] );
970 408
971 - $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
972 -
973 - if ( class_exists( 'SRFM_PRO\Admin\Licensing' ) ) {
974 - $license_active = \SRFM_PRO\Admin\Licensing::is_license_active();
975 - $localization_data['is_license_active'] = $license_active;
976 -
977 - // Updating current licensing status.
978 - $srfm_pro_license_status = get_option( 'srfm_pro_license_status', '' );
979 - $current_license_status = $license_active ? 'licensed' : 'unlicensed';
980 - if ( $current_license_status !== $srfm_pro_license_status ) {
981 - update_option( 'srfm_pro_license_status', $current_license_status );
982 - }
983 - }
984 -
985 - $localization_data['security_settings_url'] = admin_url( '/admin.php?page=sureforms_form_settings&tab=security-settings&subpage=recaptcha' );
986 - $localization_data['integration_settings_url'] = admin_url( '/admin.php?page=sureforms_form_settings&tab=integration-settings' );
409 + $localization_data['security_settings_url'] = admin_url( '/admin.php?page=sureforms_form_settings&tab=security-settings' );
987 410 wp_localize_script(
988 411 SRFM_SLUG . $asset_handle,
989 412 SRFM_SLUG . '_admin',
990 413 apply_filters(
@@ -992,134 +415,39 @@
992 415 $localization_data
993 416 )
994 417 );
995 418 wp_enqueue_style( SRFM_SLUG . '-dashboard', SRFM_URL . 'assets/build/dashboard.css', [], SRFM_VER, 'all' );
419 +
996 420 }
997 421
998 - if ( $is_screen_sureforms_form_settings || $is_screen_sureforms_forms ) {
999 - wp_enqueue_style( SRFM_SLUG . '-settings', $css_uri . 'backend/settings' . $file_prefix . $rtl . '.css', [], SRFM_VER );
422 + if ( 'sureforms_page_sureforms_form_settings' === $current_screen->id ) {
423 + wp_enqueue_style( SRFM_SLUG . '-settings', $css_uri . 'backend/settings' . $file_prefix . '.css', [], SRFM_VER );
1000 424 }
1001 425
1002 426 // Enqueue styles for the entries page.
1003 - if ( $is_screen_sureforms_entries ) {
427 + if ( 'sureforms_page_' . SRFM_ENTRIES === $current_screen->id ) {
1004 428 $asset_handle = '-entries';
429 + wp_enqueue_style( SRFM_SLUG . $asset_handle, $css_uri . 'backend/entries' . $file_prefix . '.css', [], SRFM_VER );
1005 430 wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/entries.js', $script_info['dependencies'], SRFM_VER, true );
1006 -
1007 - wp_localize_script(
1008 - SRFM_SLUG . $asset_handle,
1009 - SRFM_SLUG . '_admin',
1010 - apply_filters(
1011 - SRFM_SLUG . '_admin_filter',
1012 - $localization_data
1013 - )
1014 - );
1015 - $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
1016 431 }
1017 432
1018 - // Enqueue scripts for the learn page.
1019 - if ( $is_screen_sureforms_learn ) {
1020 - $asset_handle = '-learn';
1021 - wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/learn.js', $script_info['dependencies'], SRFM_VER, true );
433 + // Admin Submenu Styles.
434 + wp_enqueue_style( SRFM_SLUG . '-admin', $css_uri . 'backend/admin' . $file_prefix . '.css', [], SRFM_VER );
1022 435
1023 - wp_localize_script(
1024 - SRFM_SLUG . $asset_handle,
1025 - SRFM_SLUG . '_admin',
1026 - apply_filters(
1027 - SRFM_SLUG . '_admin_filter',
1028 - $localization_data
1029 - )
1030 - );
1031 - $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
1032 - }
436 + if ( 'edit-' . SRFM_FORMS_POST_TYPE === $current_screen->id ) {
437 + $asset_handle = 'page_header';
1033 438
1034 - // Enqueue scripts for the forms page.
1035 - if ( $is_screen_sureforms_forms ) {
1036 - $asset_handle = '-forms';
1037 -
1038 - $script_asset_path = SRFM_DIR . 'assets/build/forms.asset.php';
1039 - $script_info = file_exists( $script_asset_path )
1040 - ? include $script_asset_path
1041 - : [
1042 - 'dependencies' => [],
1043 - 'version' => SRFM_VER,
1044 - ];
1045 -
1046 - wp_enqueue_script( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/forms.js', $script_info['dependencies'], SRFM_VER, true );
1047 - wp_localize_script(
1048 - SRFM_SLUG . $asset_handle,
1049 - SRFM_SLUG . '_admin',
1050 - apply_filters(
1051 - SRFM_SLUG . '_admin_filter',
1052 - $localization_data
1053 - )
1054 - );
1055 - wp_enqueue_style( SRFM_SLUG . $asset_handle, SRFM_URL . 'assets/build/forms.css', [], SRFM_VER, 'all' );
1056 -
1057 - $script_translations_handlers[] = SRFM_SLUG . $asset_handle;
1058 - }
1059 -
1060 - // Enqueue scripts for the SureMail promotional page.
1061 - $is_screen_sureforms_smtp = Helper::validate_request_context( 'sureforms_smtp', 'page' );
1062 - if ( $is_screen_sureforms_smtp ) {
1063 - $asset_handle = 'suremail';
1064 -
1065 439 $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1066 440 $script_info = file_exists( $script_asset_path )
1067 - ? include $script_asset_path
1068 - : [
1069 - 'dependencies' => [],
1070 - 'version' => SRFM_VER,
1071 - ];
1072 -
1073 - wp_enqueue_script( SRFM_SLUG . '-suremail', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1074 - wp_enqueue_style( SRFM_SLUG . '-suremail', SRFM_URL . 'assets/build/suremail.css', [], SRFM_VER, 'all' );
1075 -
1076 - // Localize script for SureMail page.
1077 - $suremail_localization_data = [
1078 - 'ajax_url' => admin_url( 'admin-ajax.php' ),
1079 - 'admin_url' => admin_url(),
1080 - 'suremail_url' => 'https://sureforms.com/suremail/',
1081 - 'plugin_installer_nonce' => wp_create_nonce( 'updates' ),
1082 - 'sfPluginManagerNonce' => wp_create_nonce( 'sf_plugin_manager_nonce' ),
1083 - 'suremail_status' => file_exists( WP_PLUGIN_DIR . '/suremails/suremails.php' )
1084 - ? ( is_plugin_active( 'suremails/suremails.php' ) ? 'active' : 'installed' )
1085 - : 'not_installed',
441 + ? include $script_asset_path
442 + : [
443 + 'dependencies' => [],
444 + 'version' => SRFM_VER,
1086 445 ];
1087 -
1088 - wp_localize_script(
1089 - SRFM_SLUG . '-suremail',
1090 - SRFM_SLUG . '_admin',
1091 - apply_filters(
1092 - SRFM_SLUG . '_suremail_admin_filter',
1093 - $suremail_localization_data
1094 - )
1095 - );
1096 -
1097 - $script_translations_handlers[] = SRFM_SLUG . '-suremail';
446 + wp_enqueue_script( SRFM_SLUG . '-form-page-header', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
447 + wp_enqueue_style( SRFM_SLUG . '-form-archive-styles', $css_uri . 'form-archive-styles' . $file_prefix . '.css', [], SRFM_VER );
1098 448 }
1099 -
1100 - // Enqueue scripts for the Quiz empty state page (free users only).
1101 - if ( $is_screen_quiz_empty_state && ! Helper::has_pro() ) {
1102 - $asset_handle = 'quizEmptyState';
1103 -
1104 - $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1105 - $script_info = file_exists( $script_asset_path )
1106 - ? include $script_asset_path
1107 - : [
1108 - 'dependencies' => [],
1109 - 'version' => SRFM_VER,
1110 - ];
1111 -
1112 - wp_enqueue_script( SRFM_SLUG . '-quiz-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
1113 - wp_enqueue_style( SRFM_SLUG . '-quiz-empty-state', SRFM_URL . 'assets/build/' . $asset_handle . '.css', [], SRFM_VER, 'all' );
1114 -
1115 - $script_translations_handlers[] = SRFM_SLUG . '-quiz-empty-state';
1116 - }
1117 -
1118 - // Admin Submenu Styles.
1119 - wp_enqueue_style( SRFM_SLUG . '-admin', $css_uri . 'backend/admin' . $file_prefix . $rtl . '.css', [], SRFM_VER );
1120 -
1121 - if ( $is_screen_sureforms_form_settings ) {
449 + if ( 'sureforms_page_' . SRFM_FORMS_POST_TYPE . '_settings' === $current_screen->base ) {
1122 450 $asset_handle = 'settings';
1123 451
1124 452 $script_asset_path = SRFM_DIR . 'assets/build/' . $asset_handle . '.asset.php';
1125 453 $script_info = file_exists( $script_asset_path )
@@ -1129,23 +457,55 @@
1129 457 'version' => SRFM_VER,
1130 458 ];
1131 459
1132 460 wp_enqueue_script( SRFM_SLUG . '-settings', SRFM_URL . 'assets/build/' . $asset_handle . '.js', $script_info['dependencies'], SRFM_VER, true );
461 + wp_enqueue_style( SRFM_SLUG . '-setting-styles', SRFM_URL . 'assets/build/' . $asset_handle . '.css', [ 'wp-components' ], SRFM_VER, 'all' );
1133 462 wp_localize_script(
1134 463 SRFM_SLUG . '-settings',
1135 464 SRFM_SLUG . '_admin',
1136 - apply_filters(
1137 - SRFM_SLUG . '_admin_filter',
1138 - $localization_data
1139 - )
465 + $localization_data
1140 466 );
467 + }
468 + if ( 'edit-' . SRFM_FORMS_POST_TYPE === $current_screen->id ) {
469 + wp_enqueue_script( SRFM_SLUG . '-form-archive', $js_uri . 'form-archive' . $file_prefix . '.js', [], SRFM_VER, true );
470 + wp_enqueue_script( SRFM_SLUG . '-export', $js_uri . 'export' . $file_prefix . '.js', [ 'wp-i18n' ], SRFM_VER, true );
471 + wp_localize_script(
472 + SRFM_SLUG . '-export',
473 + SRFM_SLUG . '_export',
474 + [
475 + 'ajaxurl' => admin_url( 'admin-ajax.php' ),
476 + 'srfm_export_nonce' => wp_create_nonce( 'export_form_nonce' ),
477 + 'site_url' => get_site_url(),
478 + 'srfm_import_endpoint' => '/wp-json/sureforms/v1/sureforms_import',
479 + 'import_form_nonce' => current_user_can( 'edit_posts' ) ? wp_create_nonce( 'wp_rest' ) : '',
480 + ]
481 + );
1141 482
1142 - $script_translations_handlers[] = SRFM_SLUG . '-settings';
483 + wp_enqueue_script( SRFM_SLUG . '-backend', $js_uri . 'backend' . $file_prefix . '.js', [], SRFM_VER, true );
484 + wp_localize_script(
485 + SRFM_SLUG . '-backend',
486 + SRFM_SLUG . '_backend',
487 + [
488 + 'site_url' => get_site_url(),
489 + ]
490 + );
491 +
1143 492 }
1144 493
1145 - if ( $is_screen_add_new_form ) {
1146 - wp_enqueue_style( SRFM_SLUG . '-template-picker', $css_uri . 'template-picker' . $file_prefix . $rtl . '.css', [], SRFM_VER );
494 + if ( 'sureforms_page_add-new-form' === $current_screen->id ) {
1147 495
496 + $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
497 + $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
498 +
499 + $css_uri = SRFM_URL . 'assets/css/' . $dir_name . '/';
500 +
501 + /* RTL */
502 + if ( is_rtl() ) {
503 + $file_prefix .= '-rtl';
504 + }
505 +
506 + wp_enqueue_style( SRFM_SLUG . '-template-picker', $css_uri . 'template-picker' . $file_prefix . '.css', [], SRFM_VER );
507 +
1148 508 $sureforms_admin = 'templatePicker';
1149 509
1150 510 $script_asset_path = SRFM_DIR . 'assets/build/' . $sureforms_admin . '.asset.php';
1151 511 $script_info = file_exists( $script_asset_path )
@@ -1161,22 +521,20 @@
1161 521 SRFM_SLUG . '_admin',
1162 522 [
1163 523 'site_url' => get_site_url(),
1164 524 'plugin_url' => SRFM_URL,
525 + 'preview_images_url' => SRFM_URL . 'images/template-previews/',
1165 526 'admin_url' => admin_url( 'admin.php' ),
1166 527 'new_template_picker_base_url' => admin_url( 'post-new.php?post_type=sureforms_form' ),
1167 - 'capability' => Helper::current_user_can(),
1168 - 'template_picker_nonce' => Helper::current_user_can() ? wp_create_nonce( 'wp_rest' ) : '',
1169 - 'is_pro_active' => Helper::has_pro(),
528 + 'capability' => current_user_can( 'edit_posts' ),
529 + 'template_picker_nonce' => current_user_can( 'edit_posts' ) ? wp_create_nonce( 'wp_rest' ) : '',
530 + 'is_pro_active' => defined( 'SRFM_PRO_VER' ),
1170 531 'srfm_ai_usage_details' => AI_Helper::get_current_usage_details(),
1171 532 'is_pro_license_active' => AI_Helper::is_pro_license_active(),
1172 533 'srfm_ai_auth_user_email' => get_option( 'srfm_ai_auth_user_email' ),
1173 - 'pricing_page_url' => Helper::get_sureforms_website_url( 'pricing' ),
1174 - 'licensing_nonce' => wp_create_nonce( 'srfm_pro_licensing_nonce' ),
534 + 'pricing_page_url' => $this->get_sureforms_website_url( 'pricing' ),
1175 535 ]
1176 536 );
1177 -
1178 - $script_translations_handlers[] = SRFM_SLUG . '-template-picker';
1179 537 }
1180 538 // Quick action sidebar.
1181 539 $default_allowed_quick_sidebar_blocks = apply_filters(
1182 540 'srfm_quick_sidebar_allowed_blocks',
@@ -1187,9 +545,8 @@
1187 545 'srfm/checkbox',
1188 546 'srfm/number',
1189 547 'srfm/inline-button',
1190 548 'srfm/advanced-heading',
1191 - 'srfm/payment',
1192 549 ]
1193 550 );
1194 551 if ( ! is_array( $default_allowed_quick_sidebar_blocks ) ) {
1195 552 $default_allowed_quick_sidebar_blocks = [];
@@ -1201,79 +558,39 @@
1201 558 }
1202 559 $quick_sidebar_allowed_blocks = get_option( 'srfm_quick_sidebar_allowed_blocks' );
1203 560 $quick_sidebar_allowed_blocks = ! empty( $quick_sidebar_allowed_blocks ) && is_array( $quick_sidebar_allowed_blocks ) ? $quick_sidebar_allowed_blocks : $default_allowed_quick_sidebar_blocks;
1204 561 $srfm_ajax_nonce = wp_create_nonce( 'srfm_ajax_nonce' );
562 + wp_enqueue_script( SRFM_SLUG . '-quick-action-siderbar', SRFM_URL . 'assets/build/quickActionSidebar.js', [], SRFM_VER, true );
563 + wp_localize_script(
564 + SRFM_SLUG . '-quick-action-siderbar',
565 + SRFM_SLUG . '_quick_sidebar_blocks',
566 + [
567 + 'allowed_blocks' => $quick_sidebar_allowed_blocks,
568 + 'srfm_enable_quick_action_sidebar' => $srfm_enable_quick_action_sidebar,
569 + 'srfm_ajax_nonce' => $srfm_ajax_nonce,
570 + 'srfm_ajax_url' => admin_url( 'admin-ajax.php' ),
571 + ]
572 + );
1205 573
1206 - if ( Helper::is_sureforms_admin_page() ) {
1207 - wp_enqueue_script( SRFM_SLUG . '-quick-action-siderbar', SRFM_URL . 'assets/build/quickActionSidebar.js', [], SRFM_VER, true );
1208 - wp_localize_script(
1209 - SRFM_SLUG . '-quick-action-siderbar',
1210 - SRFM_SLUG . '_quick_sidebar_blocks',
1211 - [
1212 - 'allowed_blocks' => $quick_sidebar_allowed_blocks,
1213 - 'srfm_enable_quick_action_sidebar' => $srfm_enable_quick_action_sidebar,
1214 - 'srfm_ajax_nonce' => $srfm_ajax_nonce,
1215 - 'srfm_ajax_url' => admin_url( 'admin-ajax.php' ),
1216 - ]
1217 - );
1218 -
1219 - $script_translations_handlers[] = SRFM_SLUG . '-quick-action-siderbar';
1220 - }
1221 -
1222 574 /**
1223 575 * Enqueuing SureTriggers Integration script.
1224 576 * This script loads suretriggers iframe in Intergations tab.
1225 577 */
1226 - if ( $is_post_type_sureforms_form ) {
578 + if ( SRFM_FORMS_POST_TYPE === $current_screen->post_type ) {
1227 579 wp_enqueue_script( SRFM_SLUG . '-suretriggers-integration', SRFM_SURETRIGGERS_INTEGRATION_BASE_URL . 'js/v2/embed.js', [], SRFM_VER, true );
1228 580 }
1229 -
1230 - // Check $script_translations_handlers is not empty before calling the function.
1231 - if ( ! empty( $script_translations_handlers ) ) {
1232 - // Remove duplicates values from the array.
1233 - $script_translations_handlers = array_unique( $script_translations_handlers );
1234 -
1235 - foreach ( $script_translations_handlers as $script_handle ) {
1236 - Helper::register_script_translations( $script_handle );
1237 - }
1238 - }
1239 581 }
1240 582
1241 583 /**
1242 584 * Form Template Picker Admin Body Classes
1243 - * WordPress sometimes translates class names in the admin body tag, which can result in
1244 - * incorrect or missing class names when rendering the admin pages. This function ensures
1245 - * that essential class names are manually added to the body tag to maintain proper functionality.
1246 585 *
1247 586 * @since 0.0.1
1248 587 * @param string $classes Space separated class string.
1249 588 */
1250 589 public function admin_template_picker_body_class( $classes = '' ) {
1251 - // Define an associative array of class names and their corresponding conditions.
1252 - // Each condition checks whether a specific request context matches.
1253 - $srfm_classes = [
1254 - 'sureforms_page_sureforms_entries' => Helper::validate_request_context( SRFM_ENTRIES, 'page' ),
1255 - 'sureforms_page_sureforms_form_settings' => Helper::validate_request_context( 'sureforms_form_settings', 'page' ),
1256 - 'srfm-template-picker' => Helper::validate_request_context( 'add-new-form', 'page' ),
1257 - ];
590 + $theme_builder_class = isset( $_GET['page'] ) && 'add-new-form' === $_GET['page'] ? 'srfm-template-picker' : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Fetching a $_GET value, no nonce available to validate.
591 + $classes .= ' ' . $theme_builder_class . ' ';
1258 592
1259 - $add_srfm_classes = '';
1260 -
1261 - // Loop through the defined classes and conditions.
1262 - foreach ( $srfm_classes as $class => $condition ) {
1263 - // Check if the condition evaluates to true.
1264 - if ( $condition ) {
1265 - // Append the class to the existing classes string, followed by a space.
1266 - $add_srfm_classes .= empty( $add_srfm_classes ) ? $class : ' ' . $class;
1267 - }
1268 - }
1269 -
1270 - // Append the new classes to the existing classes string.
1271 - if ( ! empty( $add_srfm_classes ) ) {
1272 - $classes .= ' ' . $add_srfm_classes;
1273 - }
1274 -
1275 - // Return the updated list of classes.
1276 593 return $classes;
1277 594 }
1278 595
1279 596 /**
@@ -1292,705 +609,56 @@
1292 609 return $status;
1293 610 }
1294 611
1295 612 /**
1296 - * Register Pro compatibility notices early for React pages.
613 + * Get SureForms Website URL.
1297 614 *
1298 - * This method runs on admin_init (priority 5) to ensure notices are
1299 - * registered BEFORE admin_enqueue_scripts, so they're available when
1300 - * wp_localize_script runs.
1301 - *
1302 - * Hooked - admin_init (priority 5)
1303 - *
1304 - * @return void
1305 - * @since 2.5.0
615 + * @param string $trail The URL trail to append to SureForms website URL. The parameter should not include a leading slash as the base URL already ends with a trailing slash.
616 + * @since 0.0.7
617 + * @return string
1306 618 */
1307 - public function register_pro_compatibility_notices() {
1308 - // Early exit if Pro is not active, user lacks permissions, or Notice_Manager is unavailable.
1309 - if ( ! Helper::has_pro() || ! Helper::current_user_can() || ! class_exists( 'SRFM\Admin\Notice_Manager' ) ) {
1310 - return;
619 + public static function get_sureforms_website_url( $trail ) {
620 + $url = SRFM_WEBSITE;
621 + if ( ! empty( $trail ) && is_string( $trail ) ) {
622 + $url = SRFM_WEBSITE . $trail;
1311 623 }
1312 624
1313 - // Register version outdated notice for React pages.
1314 - if ( ! version_compare( SRFM_PRO_VER, SRFM_PRO_RECOMMENDED_VER, '>=' ) ) {
1315 - $pro_plugin_name = defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro';
1316 - $react_outdated_message = sprintf(
1317 - // translators: %1$s: SureForms version, %2$s: SureForms Pro Plugin Name, %3$s: SureForms Pro Version.
1318 - esc_html__( 'SureForms %1$s requires minimum %2$s %3$s to work properly. Please update to the latest version.', 'sureforms' ),
1319 - esc_html( SRFM_VER ),
1320 - esc_html( $pro_plugin_name ),
1321 - esc_html( SRFM_PRO_RECOMMENDED_VER )
1322 - );
1323 -
1324 - \SRFM\Admin\Notice_Manager::register_notice(
1325 - [
1326 - 'id' => 'sureforms-pro-version-outdated',
1327 - 'variant' => 'warning',
1328 - 'message' => $react_outdated_message,
1329 - 'actions' => [
1330 - [
1331 - 'label' => esc_html__( 'Update Now', 'sureforms' ),
1332 - 'url' => admin_url( 'update-core.php' ),
1333 - 'variant' => 'primary',
1334 - ],
1335 - ],
1336 - 'pages' => [ 'all' ],
1337 - ]
1338 - );
1339 - }
625 + return esc_url( $url );
1340 626 }
1341 627
1342 - /**
1343 - * Admin Notice Callback if sureforms pro is out of date.
1344 - *
1345 - * Hooked - admin_notices
1346 - *
1347 - * @return void
1348 - * @since 1.0.4
1349 - */
1350 - public function srfm_pro_version_compatibility() {
1351 - if ( ! Helper::has_pro() ) {
1352 - return;
1353 - }
628 + // Entries methods.
1354 629
1355 - if ( empty( get_current_screen() ) ) {
1356 - return;
1357 - }
1358 -
1359 - if ( ! Helper::current_user_can() ) {
1360 - return;
1361 - }
1362 -
1363 - $srfm_pro_license_status = get_option( 'srfm_pro_license_status', '' );
1364 - /**
1365 - * If the license status is not set then get the license status and update the option accordingly.
1366 - * This will be executed only once. Subsequently, the option status is updated by the licensing class on license activation or deactivation.
1367 - */
1368 - if ( empty( $srfm_pro_license_status ) && class_exists( 'SRFM_PRO\Admin\Licensing' ) ) {
1369 - $srfm_pro_license_status = \SRFM_PRO\Admin\Licensing::is_license_active() ? 'licensed' : 'unlicensed';
1370 - update_option( 'srfm_pro_license_status', $srfm_pro_license_status );
1371 - }
1372 -
1373 - $pro_plugin_name = defined( 'SRFM_PRO_PRODUCT' ) ? SRFM_PRO_PRODUCT : 'SureForms Pro';
1374 - $message = '';
1375 - $url = admin_url( 'admin.php?page=sureforms_form_settings&tab=account-settings' );
1376 - if ( 'unlicensed' === $srfm_pro_license_status ) {
1377 - ob_start();
1378 - ?>
1379 - <p>
1380 - <?php
1381 - printf(
1382 - // translators: %1$s: Opening anchor tag with URL, %2$s: Closing anchor tag, %3$s: SureForms Pro Plugin Name.
1383 - esc_html__( 'Please %1$sactivate%2$s your copy of %3$s to get new features, access support, receive update notifications, and more.', 'sureforms' ),
1384 - '<a href="' . esc_url( $url ) . '">',
1385 - '</a>',
1386 - '<i>' . esc_html( $pro_plugin_name ) . '</i>'
1387 - );
1388 - ?>
1389 - </p>
1390 - <?php
1391 - $message = ob_get_clean();
1392 - }
1393 -
1394 - if ( ! version_compare( SRFM_PRO_VER, SRFM_PRO_RECOMMENDED_VER, '>=' ) ) {
1395 - ob_start();
1396 - ?>
1397 - <p>
1398 - <?php
1399 - printf(
1400 - // 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.
1401 - 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' ),
1402 - esc_html( SRFM_VER ),
1403 - esc_html( $pro_plugin_name ),
1404 - esc_html( SRFM_PRO_RECOMMENDED_VER ),
1405 - '<a href="' . esc_url( admin_url( 'update-core.php' ) ) . '">',
1406 - '</a>'
1407 - );
1408 - ?>
1409 - </p>
1410 - <?php
1411 - $message .= ob_get_clean();
1412 - }
1413 -
1414 - if ( ! empty( $message ) ) {
1415 - // Phpcs ignore comment is required as $message variable is already escaped.
1416 - ?>
1417 - <div class="notice notice-warning"><?php echo wp_kses_post( $message ); ?></div>
1418 - <?php
1419 - }
1420 - }
1421 -
1422 630 /**
1423 - * Display a notice to the user about providing a review.
631 + * Handle entry actions.
1424 632 *
1425 - * @since 2.5.2
633 + * @since 0.0.13
1426 634 * @return void
1427 635 */
1428 - public function display_srfm_rating_notice() {
1429 - // Only show to admins.
1430 - if ( ! Helper::current_user_can() ) {
636 + public function handle_entry_actions() {
637 + if ( isset( $_GET['entry'] ) && isset( $_GET['action'] ) ) {
638 + Entries_List_Table::process_bulk_actions();
1431 639 return;
1432 640 }
1433 -
1434 - // Allow the notice to be disabled.
1435 - if ( ! apply_filters( 'srfm_show_rating_notice', true ) ) {
641 + if ( ! isset( $_GET['page'] ) || SRFM_ENTRIES !== $_GET['page'] ) {
1436 642 return;
1437 643 }
1438 -
1439 - Astra_Notices::add_notice(
1440 - [
1441 - 'id' => 'srfm-plugin-review-notice',
1442 - 'type' => '',
1443 - 'message' => $this->build_notice_markup(
1444 - esc_html__( 'Amazing! SureForms is powering your forms and submissions - let\'s keep growing together!', 'sureforms' ),
1445 - esc_html__( 'If SureForms has been helpful, would you mind taking a moment to leave a 5-star review on WordPress.org?', 'sureforms' ),
1446 - esc_url( 'https://wordpress.org/support/plugin/sureforms/reviews/?filter=5#new-post' ),
1447 - esc_html__( 'Rate SureForms', 'sureforms' ),
1448 - esc_html__( 'Maybe later', 'sureforms' ),
1449 - esc_html__( 'I already did', 'sureforms' ),
1450 - WEEK_IN_SECONDS,
1451 - true
1452 - ),
1453 - 'repeat-notice-after' => WEEK_IN_SECONDS,
1454 - 'show_if' => $this->maybe_display_rating_notice(),
1455 - 'display-with-other-notices' => true,
1456 - ]
1457 - );
1458 -
1459 - add_action( 'astra_notice_after_markup_srfm-plugin-review-notice', [ $this, 'enqueue_notice_response_script' ] );
1460 - }
1461 -
1462 - /**
1463 - * Display a "Getting Started" admin notice for new users who haven't yet
1464 - * reached the rating-notice milestone (3+ forms or 3+ entries).
1465 - *
1466 - * The Astra Notices library handles the 7-day delay via the
1467 - * `display-notice-after` parameter.
1468 - *
1469 - * @since 2.5.2
1470 - * @return void
1471 - */
1472 - public function display_srfm_getting_started_notice() {
1473 - // Only show to admins.
1474 - if ( ! Helper::current_user_can() ) {
644 + if ( ! isset( $_GET['entry_id'] ) || ! isset( $_GET['action'] ) ) {
1475 645 return;
1476 646 }
1477 -
1478 - // Allow the notice to be disabled programmatically.
1479 - if ( ! apply_filters( 'srfm_show_getting_started_notice', true ) ) {
1480 - return;
647 + if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'srfm_entries_action' ) ) {
648 + wp_die( esc_html__( 'Nonce verification failed.', 'sureforms' ) );
1481 649 }
1482 -
1483 - Astra_Notices::add_notice(
1484 - [
1485 - 'id' => 'srfm-getting-started-notice',
1486 - 'type' => '',
1487 - 'message' => $this->build_notice_markup(
1488 - esc_html__( 'SureForms is ready to power your forms — explore what\'s possible!', 'sureforms' ),
1489 - esc_html__( 'Manage your forms, track submissions, and discover features like AI Form Builder, payment integrations, and more from the SureForms dashboard.', 'sureforms' ),
1490 - esc_url( admin_url( 'admin.php?page=sureforms_menu' ) ),
1491 - esc_html__( 'Go to Dashboard', 'sureforms' ),
1492 - esc_html__( 'Maybe later', 'sureforms' ),
1493 - esc_html__( 'I already know', 'sureforms' ),
1494 - WEEK_IN_SECONDS
1495 - ),
1496 - 'repeat-notice-after' => WEEK_IN_SECONDS,
1497 - 'show_if' => ! $this->maybe_display_rating_notice(),
1498 - 'display-notice-after' => WEEK_IN_SECONDS,
1499 - 'display-with-other-notices' => true,
1500 - ]
1501 - );
1502 -
1503 - add_action( 'astra_notice_after_markup_srfm-getting-started-notice', [ $this, 'enqueue_notice_response_script' ] );
1504 - }
1505 -
1506 - /**
1507 - * Enqueue the notice response analytics script.
1508 - *
1509 - * Called via the astra_notice_after_markup_{id} hook so the script
1510 - * only loads when a SureForms notice is actually rendered.
1511 - *
1512 - * @since 2.5.2
1513 - * @return void
1514 - */
1515 - public function enqueue_notice_response_script() {
1516 - if ( wp_script_is( 'srfm-notice-response', 'enqueued' ) ) {
1517 - return;
1518 - }
1519 -
1520 - wp_enqueue_script(
1521 - 'srfm-notice-response',
1522 - SRFM_URL . 'admin/assets/js/notice-response.js',
1523 - [],
1524 - SRFM_VER,
1525 - true
1526 - );
1527 -
1528 - wp_localize_script(
1529 - 'srfm-notice-response',
1530 - 'srfmNoticeResponse',
1531 - [
1532 - 'ajaxurl' => admin_url( 'admin-ajax.php' ),
1533 - 'nonce' => wp_create_nonce( 'srfm_notice_response' ),
1534 - ]
1535 - );
1536 - }
1537 -
1538 - /**
1539 - * Handle the notice response AJAX request.
1540 - *
1541 - * Validates the request and records the analytics event
1542 - * for the notice button that was clicked.
1543 - *
1544 - * @since 2.5.2
1545 - * @return void
1546 - */
1547 - public function handle_notice_response() {
1548 - if ( ! check_ajax_referer( 'srfm_notice_response', 'nonce', false ) ) {
1549 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1550 - }
1551 -
1552 - if ( ! Helper::current_user_can() ) {
1553 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1554 - }
1555 -
1556 - $notice_id = isset( $_POST['notice_id'] ) ? sanitize_text_field( wp_unslash( $_POST['notice_id'] ) ) : '';
1557 - $button = isset( $_POST['button'] ) ? sanitize_text_field( wp_unslash( $_POST['button'] ) ) : '';
1558 -
1559 - $valid = [
1560 - 'srfm-getting-started-notice' => [
1561 - 'go_to_dashboard' => 'getting_started_notice_cta',
1562 - 'maybe_later' => 'getting_started_notice_snooze',
1563 - 'dismissed' => 'getting_started_notice_dismiss',
1564 - ],
1565 - 'srfm-plugin-review-notice' => [
1566 - 'rate_sureforms' => 'rating_notice_cta',
1567 - 'maybe_later' => 'rating_notice_snooze',
1568 - 'dismissed' => 'rating_notice_dismiss',
1569 - ],
1570 - ];
1571 -
1572 - if ( ! isset( $valid[ $notice_id ][ $button ] ) ) {
1573 - wp_send_json_error( [ 'message' => __( 'Invalid parameters.', 'sureforms' ) ], 400 );
1574 - }
1575 -
1576 - $event_name = $valid[ $notice_id ][ $button ];
1577 - Analytics::events()->track( $event_name, $button );
1578 -
1579 - wp_send_json_success();
1580 - }
1581 -
1582 - /**
1583 - * Disables the capabilities for WPForms to avoid conflicts when enqueueing
1584 - * scripts and styles for WPForms.
1585 - *
1586 - * This function is intended to prevent any potential conflicts that may arise
1587 - * when WPForms scripts and styles are enqueued. By disabling certain capabilities,
1588 - * it ensures that WPForms does not interfere with other functionalities.
1589 - *
1590 - * @param bool $user_can A boolean indicating whether the user has the capability.
1591 - * @return bool Returns true if the capabilities are successfully disabled, false otherwise.
1592 - * @since 1.4.2
1593 - */
1594 - public function disable_wpforms_capabilities( $user_can ) {
1595 - // Note: Nonce verification is intentionally omitted here as no database operations are performed.
1596 - // The values of the $_REQUEST variables are strictly validated, ensuring security without the need for nonce verification.
1597 -
1598 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1599 - $post_id = ! empty( $_REQUEST['post'] ) && ! empty( $_REQUEST['action'] ) ? absint( $_REQUEST['post'] ) : 0;
1600 -
1601 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended
1602 - $post_type = $post_id ? get_post_type( $post_id ) : sanitize_text_field( wp_unslash( $_REQUEST['post_type'] ?? '' ) );
1603 - return SRFM_FORMS_POST_TYPE === $post_type ? false : $user_can;
1604 - }
1605 -
1606 - /**
1607 - * Enqueueus the admin pointer script and styles.
1608 - *
1609 - * @return void
1610 - * @since 1.8.0
1611 - */
1612 - public function enqueue_admin_pointer() {
1613 - if ( ! $this->is_admin_pointer_visible() ) {
1614 - return;
1615 - }
1616 - wp_enqueue_style( 'wp-pointer' );
1617 - wp_enqueue_script( 'wp-pointer' );
1618 - wp_enqueue_script(
1619 - 'sureforms-admin-pointer',
1620 - plugins_url( 'admin/assets/js/sureforms-pointer.js', SRFM_FILE ),
1621 - [ 'wp-pointer', 'jquery' ],
1622 - SRFM_VER,
1623 - true
1624 - );
1625 - wp_localize_script(
1626 - 'sureforms-admin-pointer',
1627 - 'sureformsPointerData',
1628 - [
1629 - 'ajaxurl' => admin_url( 'admin-ajax.php' ),
1630 - 'pointer_nonce' => wp_create_nonce( 'sureforms_pointer_action' ),
1631 - ]
1632 - );
1633 - }
1634 -
1635 - /**
1636 - * Ajax handler for pointer popup visibility.
1637 - *
1638 - * @return void
1639 - * @since 1.8.0
1640 - */
1641 - public function pointer_should_show() {
1642 - // Security: Check user capability.
1643 - if ( ! Helper::current_user_can() ) {
1644 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1645 - }
1646 - // Security: Nonce check.
1647 - if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1648 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1649 - }
1650 -
1651 - $content_markup = sprintf(
1652 - /* translators: 1: opening span, 2: opening strong (inline), 3: closing strong, 4: closing span, 5: opening strong (block), 6: closing strong */
1653 - __( '%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' ),
1654 - '<span>',
1655 - '<strong>',
1656 - '</strong>',
1657 - '</span><br/>',
1658 - '<strong style="font-size:1.1em;">',
1659 - '</strong>'
1660 - );
1661 - wp_send_json(
1662 - [
1663 - 'show' => true,
1664 - 'title' => esc_html( __( 'SureForms is waiting for you!', 'sureforms' ) ),
1665 - 'content' => wp_kses_post( $content_markup ),
1666 - 'button_text' => esc_html( __( 'Build My First Form', 'sureforms' ) ),
1667 - 'dismiss' => esc_html( __( 'Dismiss', 'sureforms' ) ),
1668 - 'button_url' => admin_url( 'admin.php?page=add-new-form' ),
1669 - ]
1670 - );
1671 - }
1672 -
1673 - /**
1674 - * Ajax callback for pointer popup dismissed action.
1675 - *
1676 - * @return void
1677 - * @since 1.8.0
1678 - */
1679 - public function pointer_dismissed() {
1680 - // Security: Check user capability.
1681 - if ( ! Helper::current_user_can() ) {
1682 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1683 - }
1684 - // Security: Nonce check.
1685 - if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1686 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1687 - }
1688 - // Use Helper to update srfm_options key.
1689 - Helper::update_srfm_option( 'pointer_popup_dismissed', time() );
1690 -
1691 - wp_send_json_success();
1692 - }
1693 -
1694 - /**
1695 - * Ajax pointer accepted CTA callback.
1696 - *
1697 - * @return void
1698 - * @since 1.8.0
1699 - */
1700 - public function pointer_accepted_cta() {
1701 - // Security: Check user capability.
1702 - if ( ! Helper::current_user_can() ) {
1703 - wp_send_json_error( [ 'message' => __( 'Unauthorized user.', 'sureforms' ) ], 403 );
1704 - }
1705 - // Security: Nonce check.
1706 - if ( empty( $_POST['pointer_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pointer_nonce'] ) ), 'sureforms_pointer_action' ) ) {
1707 - wp_send_json_error( [ 'message' => __( 'Invalid nonce.', 'sureforms' ) ], 403 );
1708 - }
1709 - // Use Helper to update srfm_options key.
1710 - Helper::update_srfm_option( 'pointer_popup_accepted', time() );
1711 -
1712 - wp_send_json_success();
1713 - }
1714 -
1715 - /**
1716 - * Maybe register the dashboard widget based on entries.
1717 - *
1718 - * @return void
1719 - * @since 1.9.1
1720 - */
1721 - public function maybe_register_dashboard_widget() {
1722 -
1723 - // Only for users with manage_options capability.
1724 - if ( ! Helper::current_user_can() ) {
1725 - return;
1726 - }
1727 -
1728 - // Quick check if there are any entries in the last 7 days.
1729 - $seven_days_ago = strtotime( '-7 days' );
1730 - $total_entries = Entries::get_entries_count_after( $seven_days_ago );
1731 -
1732 - // Only add the dashboard setup hook if there are entries.
1733 - if ( $total_entries > 0 ) {
1734 - // Get forms with entries (limit 4 for dashboard widget).
1735 - $this->dashboard_widget_data = Helper::get_forms_with_entry_counts( $seven_days_ago, 4 );
1736 -
1737 - // Only show dashboard widget if there are forms with entries.
1738 - if ( ! empty( $this->dashboard_widget_data ) ) {
1739 - add_action( 'wp_dashboard_setup', [ $this, 'register_dashboard_widget' ] );
650 + $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : '';
651 + $entry_id = Helper::get_integer_value( sanitize_text_field( wp_unslash( $_GET['entry_id'] ) ) );
652 + $view = isset( $_GET['view'] ) ? sanitize_text_field( wp_unslash( $_GET['view'] ) ) : '';
653 + if ( $entry_id > 0 ) {
654 + if ( 'read' === $action && 'details' === $view ) {
655 + $entry_status = Entries::get( $entry_id )['status'];
656 + if ( 'trash' === $entry_status ) {
657 + wp_die( esc_html__( 'You cannot view this entry because it is in trash.', 'sureforms' ) );
658 + }
1740 659 }
660 + Entries_List_Table::handle_entry_status( $entry_id, $action, $view );
1741 661 }
1742 - }
1743 -
1744 - /**
1745 - * Register the dashboard widget.
1746 - *
1747 - * @return void
1748 - * @since 1.9.1
1749 - */
1750 - public function register_dashboard_widget() {
1751 - // Add the widget with high priority to position it at the top.
1752 - wp_add_dashboard_widget(
1753 - 'sureforms_recent_entries',
1754 - __( 'SureForms', 'sureforms' ),
1755 - [ $this, 'render_dashboard_widget' ],
1756 - null,
1757 - null,
1758 - 'normal',
1759 - 'high'
1760 - );
1761 - }
1762 -
1763 - /**
1764 - * Render the dashboard widget content.
1765 - *
1766 - * @return void
1767 - * @since 1.9.1
1768 - */
1769 - public function render_dashboard_widget() {
1770 - // Use the pre-fetched data to avoid duplicate queries.
1771 - $entries_data = $this->dashboard_widget_data;
1772 -
1773 - // Display the widget content.
1774 - ?>
1775 - <div class="srfm-dashboard-widget">
1776 - <div class="srfm-widget-header">
1777 - <h3 class="srfm-widget-title">
1778 - <?php esc_html_e( 'Recent Entries', 'sureforms' ); ?>
1779 - <span class="srfm-widget-subtitle"><?php esc_html_e( '( Last 7 days )', 'sureforms' ); ?></span>
1780 - </h3>
1781 - <a href="<?php echo esc_url( admin_url( 'admin.php?page=sureforms_entries' ) ); ?>" class="srfm-widget-view-link">
1782 - <?php esc_html_e( 'View', 'sureforms' ); ?>
1783 - </a>
1784 - </div>
1785 -
1786 - <div class="srfm-table-wrapper">
1787 - <table class="srfm-entries-table">
1788 - <thead>
1789 - <tr>
1790 - <th><?php esc_html_e( 'Form Name', 'sureforms' ); ?></th>
1791 - <th><?php esc_html_e( 'Entries', 'sureforms' ); ?></th>
1792 - </tr>
1793 - </thead>
1794 - <tbody>
1795 - <?php foreach ( $entries_data as $form_data ) { ?>
1796 - <tr>
1797 - <td class="form-name"><?php echo esc_html( $form_data['title'] ); ?></td>
1798 - <td class="entry-count"><?php echo esc_html( $form_data['count'] ); ?></td>
1799 - </tr>
1800 - <?php } ?>
1801 - </tbody>
1802 - </table>
1803 - </div>
1804 -
1805 - <?php
1806 - // Render footer if applicable.
1807 - $this->render_dashboard_widget_footer( $entries_data );
1808 - ?>
1809 - </div>
1810 - <?php
1811 - }
1812 -
1813 - /**
1814 - * Build the shared HTML markup for admin notices.
1815 - *
1816 - * @since 2.5.2
1817 - *
1818 - * All text parameters must be pre-escaped by the caller (e.g. via esc_html__()).
1819 - * URL parameters must be pre-escaped via esc_url().
1820 - *
1821 - * @param string $heading The notice heading text (pre-escaped).
1822 - * @param string $message The notice body text (pre-escaped).
1823 - * @param string $cta_url The primary CTA URL (pre-escaped).
1824 - * @param string $cta_text The primary CTA button text (pre-escaped).
1825 - * @param string $snooze_text The snooze button text (pre-escaped).
1826 - * @param string $dismiss_text The dismiss button text (pre-escaped).
1827 - * @param int $snooze_duration Snooze duration in seconds for the data-repeat-notice-after attribute.
1828 - * @param bool $external_cta Whether the CTA opens in a new tab and also dismisses the notice
1829 - * via the astra-notice-close class. Default false.
1830 - * @return string The notice HTML markup.
1831 - */
1832 - private function build_notice_markup( $heading, $message, $cta_url, $cta_text, $snooze_text, $dismiss_text, $snooze_duration, $external_cta = false ) {
1833 - $image_path = esc_url( SRFM_URL . 'admin/assets/sureforms-logo.png' );
1834 - $cta_class = $external_cta ? 'astra-notice-close button-primary' : 'button-primary';
1835 - $cta_attrs = $external_cta ? ' target="_blank" rel="noopener noreferrer"' : '';
1836 -
1837 - return sprintf(
1838 - '<div class="notice-image">
1839 - <img src="%1$s" class="custom-logo" alt="SureForms" itemprop="logo">
1840 - </div>
1841 - <div class="notice-content">
1842 - <div class="notice-heading">
1843 - %2$s
1844 - </div>
1845 - %3$s<br />
1846 - <div class="astra-review-notice-container">
1847 - <a href="%4$s" class="%5$s"%6$s>
1848 - %7$s
1849 - </a>
1850 - <span class="dashicons dashicons-clock" aria-hidden="true"></span>
1851 - <a href="#" data-repeat-notice-after="%8$s" class="astra-notice-close">
1852 - %9$s
1853 - </a>
1854 - <span class="dashicons dashicons-smiley" aria-hidden="true"></span>
1855 - <a href="#" class="astra-notice-close">
1856 - %10$s
1857 - </a>
1858 - </div>
1859 - </div>',
1860 - $image_path,
1861 - $heading,
1862 - $message,
1863 - $cta_url,
1864 - esc_attr( $cta_class ),
1865 - $cta_attrs,
1866 - $cta_text,
1867 - $snooze_duration,
1868 - $snooze_text,
1869 - $dismiss_text
1870 - );
1871 - }
1872 -
1873 - /**
1874 - * Callback for displaying the rating notice conditionally.
1875 - *
1876 - * Returns true if the user has 3 or more published forms or 3 or more form entries.
1877 - *
1878 - * @since 2.5.2
1879 - * @return bool
1880 - */
1881 - private function maybe_display_rating_notice() {
1882 - if ( null === $this->should_show_rating ) {
1883 - $entries_count = Entries::get_total_entries_by_status( 'all' );
1884 - $form_count = wp_count_posts( SRFM_FORMS_POST_TYPE );
1885 - $this->should_show_rating = $entries_count >= self::RATING_NOTICE_THRESHOLD || Helper::get_integer_value( $form_count->publish ?? 0 ) >= self::RATING_NOTICE_THRESHOLD;
1886 - }
1887 -
1888 - return $this->should_show_rating;
1889 - }
1890 -
1891 - /**
1892 - * Get random premium feature text.
1893 - *
1894 - * @return string Random feature text.
1895 - * @since 1.9.1
1896 - */
1897 - private function get_random_premium_feature_text() {
1898 - $features = [
1899 - __( 'Use Conditional Logic to show only what matters', 'sureforms' ),
1900 - __( 'Split your form into steps to keep it easy', 'sureforms' ),
1901 - __( 'Let people upload files directly to your form', 'sureforms' ),
1902 - __( 'Turn responses into downloadable PDFs automatically', 'sureforms' ),
1903 - __( 'Let users sign with a simple signature field', 'sureforms' ),
1904 - __( 'Connect your form to other tools using webhooks', 'sureforms' ),
1905 - __( 'Use Conversational Forms for a chat-like experience', 'sureforms' ),
1906 - __( 'Let users register or log in through your form', 'sureforms' ),
1907 - __( 'Build forms that create WordPress user accounts', 'sureforms' ),
1908 - __( 'Add calculations to auto-total scores or prices', 'sureforms' ),
1909 - ];
1910 -
1911 - // Get a random feature.
1912 - $random_key = array_rand( $features );
1913 - return $features[ $random_key ];
1914 - }
1915 -
1916 - /**
1917 - * Render the dashboard widget footer for upsell.
1918 - *
1919 - * @param array $entries_data The entries data array.
1920 - * @return void
1921 - * @since 1.9.1
1922 - */
1923 - private function render_dashboard_widget_footer( $entries_data ) {
1924 - // Only show footer if Pro is not active.
1925 - if ( Helper::has_pro() ) {
1926 - return;
1927 - }
1928 -
1929 - // Count total entries in last 7 days.
1930 - $total_entries = 0;
1931 - foreach ( $entries_data as $form_data ) {
1932 - $total_entries += $form_data['count'];
1933 - }
1934 -
1935 - // Count total published forms.
1936 - $published_forms_count = wp_count_posts( SRFM_FORMS_POST_TYPE )->publish;
1937 -
1938 - // Show footer only if 3+ entries received OR 3+ forms published.
1939 - if ( $total_entries >= 3 || $published_forms_count >= 3 ) {
1940 - ?>
1941 - <div class="srfm-widget-footer">
1942 - <div class="srfm-upgrade-content">
1943 - <svg class="srfm-logo-icon" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
1944 - <rect width="20" height="20" fill="#D54407"/>
1945 - <path d="M5.7139 4.2854H14.2853V7.1425H7.1424L5.7139 8.5711V7.1425V4.2854Z" fill="white"/>
1946 - <path d="M5.7139 4.2854H14.2853V7.1425H7.1424L5.7139 8.5711V7.1425V4.2854Z" fill="white"/>
1947 - <path d="M5.7148 8.5713H12.8577V11.4284H7.1434L5.7148 12.857V11.4284V8.5713Z" fill="white"/>
1948 - <path d="M5.7148 8.5713H12.8577V11.4284H7.1434L5.7148 12.857V11.4284V8.5713Z" fill="white"/>
1949 - <path d="M5.7148 12.8569H10.0006V15.7141H5.7148V12.8569Z" fill="white"/>
1950 - <path d="M5.7148 12.8569H10.0006V15.7141H5.7148V12.8569Z" fill="white"/>
1951 - </svg>
1952 - <span><?php echo esc_html( $this->get_random_premium_feature_text() ); ?></span>
1953 - </div>
1954 - <?php
1955 - $upgrade_url = add_query_arg(
1956 - [
1957 - 'utm_medium' => 'dashboard-widget',
1958 - ],
1959 - Helper::get_sureforms_website_url( 'pricing' )
1960 - );
1961 - ?>
1962 - <a href="<?php echo esc_url( $upgrade_url ); ?>" class="srfm-upgrade-link" target="_blank">
1963 - <?php esc_html_e( 'Upgrade', 'sureforms' ); ?>
1964 - </a>
1965 - </div>
1966 - <?php
1967 - }
1968 - }
1969 -
1970 - /**
1971 - * Determine if the admin pointer should be visible on this page.
1972 - *
1973 - * @since 1.8.0
1974 - * @return bool
1975 - */
1976 - private function is_admin_pointer_visible() {
1977 - global $pagenow;
1978 - $allowed_pages = [ 'index.php', 'options-general.php' ];
1979 -
1980 - // Do not show if pointer dismissed, accepted, or more than 1 form exists.
1981 - if (
1982 - ! empty( Helper::get_srfm_option( 'pointer_popup_dismissed' ) )
1983 - || ! empty( Helper::get_srfm_option( 'pointer_popup_accepted' ) )
1984 - || (int) ( wp_count_posts( SRFM_FORMS_POST_TYPE )->publish ?? 0 ) > 1
1985 - ) {
1986 - return false;
1987 - }
1988 -
1989 - if ( in_array( $pagenow, $allowed_pages, true ) ) {
1990 - return true;
1991 - }
1992 -
1993 - return false;
1994 662 }
1995 663
1996 664 }