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