is_block_editor() ) { return false; } // Skip on the SureForms form editor itself. if ( SRFM_FORMS_POST_TYPE === $screen->post_type ) { return false; } // Skip if the current post has an active dismissal recorded against it. // Best-effort — when no post is in scope (e.g. the Site Editor) we // still enqueue and let the JS layer surface or hide based on live // editor state. $post_id = $this->get_current_post_id(); if ( $post_id > 0 && $this->is_dismissal_active( $post_id ) ) { return false; } return true; } /** * Whether the given post has an active dismissal within the expiry window. * * Treats any non-numeric / zero / future-timestamp value as inactive, * and rolls over once the recorded timestamp is older than * `DISMISS_EXPIRY_SECONDS`. * * @since 2.8.2 * @param int $post_id Post ID to check. * @return bool */ public function is_dismissal_active( $post_id ) { $dismissed_at = Helper::get_integer_value( get_post_meta( $post_id, self::DISMISS_META_KEY, true ) ); if ( $dismissed_at <= 0 ) { return false; } return time() - $dismissed_at < self::DISMISS_EXPIRY_SECONDS; } /** * Enqueue the nudge script when allowed. * * @since 2.8.2 * @return void */ public function enqueue_scripts() { if ( ! $this->allow_load() ) { return; } $handle = SRFM_SLUG . '-editor-nudge'; $asset_path = SRFM_DIR . 'assets/build/editorNudge.asset.php'; $asset = file_exists( $asset_path ) ? include $asset_path : [ 'dependencies' => [ 'wp-data', 'wp-i18n', 'wp-dom-ready' ], 'version' => SRFM_VER, ]; wp_enqueue_script( $handle, SRFM_URL . 'assets/build/editorNudge.js', $asset['dependencies'], $asset['version'], true ); $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min'; $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified'; wp_enqueue_style( $handle, SRFM_URL . 'assets/css/' . $dir_name . '/editor-nudge' . $file_prefix . '.css', [], SRFM_VER ); // Editor nudge UTM attribution — start. // Tag the "Create Form" CTA with the same UTM scheme used by other // SureForms nudge links so the destination flow can attribute the // click. Only fills keys not already present in the URL. $create_form_url = admin_url( 'admin.php?page=add-new-form' ); $nudge_utm = [ 'utm_source' => 'sureforms_plugin', 'utm_medium' => 'editor_nudge', 'utm_campaign' => 'core_plugin', ]; $existing_args = []; $query_string = wp_parse_url( $create_form_url, PHP_URL_QUERY ); if ( is_string( $query_string ) && '' !== $query_string ) { parse_str( $query_string, $existing_args ); } $missing_utm = array_diff_key( $nudge_utm, $existing_args ); if ( ! empty( $missing_utm ) ) { $create_form_url = add_query_arg( $missing_utm, $create_form_url ); } // Editor nudge UTM attribution — end. wp_localize_script( $handle, 'srfm_editor_nudge', [ 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( self::NONCE_ACTION ), 'create_form_url' => $create_form_url, 'message' => __( 'Hey! It looks like you\'re creating a form. Build a ready-to-use form in under 30 seconds with SureForms AI, with no extra setup required.', 'sureforms' ), 'button_label' => __( 'Create Form', 'sureforms' ), 'logo_url' => SRFM_URL . 'admin/assets/sureforms-logo.png', ] ); Helper::register_script_translations( $handle ); } /** * AJAX handler to persist the dismissed state for the post being edited. * * @since 2.8.2 * @return void */ public function handle_dismiss() { if ( ! Helper::current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => __( 'You are not allowed to perform this action.', 'sureforms' ) ], 403 ); } if ( ! check_ajax_referer( self::NONCE_ACTION, 'nonce', false ) ) { wp_send_json_error( [ 'message' => __( 'Invalid security token.', 'sureforms' ) ], 400 ); } $post_id = isset( $_POST['post_id'] ) ? Helper::get_integer_value( sanitize_text_field( wp_unslash( $_POST['post_id'] ) ) ) : 0; $post = $post_id > 0 ? get_post( $post_id ) : null; if ( ! $post ) { wp_send_json_error( [ 'message' => __( 'Invalid post.', 'sureforms' ) ], 400 ); } // The nudge never surfaces on the SureForms form CPT, so dismissals // for it are never legitimate — reject before touching post meta. if ( SRFM_FORMS_POST_TYPE === $post->post_type ) { wp_send_json_error( [ 'message' => __( 'Invalid post.', 'sureforms' ) ], 400 ); } // Granular per-post authorization — `manage_options` alone is not // enough; the requesting user must also be able to edit THIS post. if ( ! current_user_can( 'edit_post', $post_id ) ) { wp_send_json_error( [ 'message' => __( 'You cannot edit this post.', 'sureforms' ) ], 403 ); } update_post_meta( $post_id, self::DISMISS_META_KEY, time() ); wp_send_json_success(); } /** * Resolve the post ID being edited on the current admin request. * * @since 2.8.2 * @return int Post ID, or 0 when no post is in scope. */ protected function get_current_post_id() { global $post; if ( $post instanceof \WP_Post && $post->ID > 0 ) { return (int) $post->ID; } return 0; } }