self::PRODUCT, 'slot' => self::slot(), 'locale' => get_user_locale(), ) ); } /** * Local, no-network WELCOME banner shown while the content opt-in is OFF, in the * slot the (empty) server banner would occupy. Same thin-bar format as the * "Upgrade to Pro" bar, stacked just above it. It greets the merchant and offers * a one-click activation: * - « Yes » → posts the opt-in handler with content_optin=1 (one click, * nonce + capability) → the server content shows, this banner is gone. * - « Hide » → per-user 4h dismissal (AJAX), top banner only. * No email is ever collected. All copy is gettext (overridable via filters, * English fallback). Never contacts any server. * * @param bool $dismissible Render the « Hide » control and honour the per-user 4h * dismissal (top banner). False on the showcase body, * where the welcome banner IS the page content. * @return void */ public static function welcome_banner( $dismissible = true ) { if ( ! current_user_can( self::CAP ) ) { return; } if ( self::content_optin() ) { return; // ON → the server banner (admin_banner) takes this slot. } if ( $dismissible ) { $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; if ( $screen && false !== strpos( (string) $screen->id, 'equasign-suite' ) ) { return; // showcase page: its body carries the welcome banner (non-dismissible). } $at = (int) get_user_meta( get_current_user_id(), self::META_DISMISSED, true ); if ( $at > 0 && ( time() - $at ) < 4 * HOUR_IN_SECONDS ) { return; // hidden less than 4 hours ago. } } $text = (string) apply_filters( 'equasign_welcome_text', __( 'Thank you for installing EquaSign. Would you like to display EquaSuite offers and news here?', 'equasign' ) ); $yes = (string) apply_filters( 'equasign_welcome_yes_label', __( 'Yes', 'equasign' ) ); $hide = (string) apply_filters( 'equasign_welcome_hide_label', __( 'Hide', 'equasign' ) ); echo '
'; echo '' . esc_html( $text ) . ''; echo '
'; echo ''; echo ''; wp_nonce_field( 'equasign_content_optin_enable' ); echo ''; echo '
'; if ( $dismissible ) { printf( '', esc_url( admin_url( 'admin-ajax.php' ) ), esc_attr( wp_create_nonce( 'equasign_dismiss_incite' ) ), esc_html( $hide ) ); } echo '
'; // .equasign-welcomebar if ( $dismissible ) { // Self-contained per-user dismissal (server-stored, 4h). No dependency on // bundled scripts; one delegated listener per page. wp_print_inline_script_tag( '(function(){if(window.equasignWelcome){return;}window.equasignWelcome=1;document.addEventListener("click",function(e){var b=e.target.closest(".equasign-welcomebar__hide[data-equasign-dismiss]");if(!b){return;}e.preventDefault();var box=b.closest(".equasign-welcomebar");var f=new FormData();f.append("action","equasign_dismiss_incite");f.append("_ajax_nonce",b.getAttribute("data-nonce"));fetch(b.getAttribute("data-equasign-dismiss"),{method:"POST",credentials:"same-origin",body:f});if(box){box.style.display="none";}});})();' ); // Native emitter (not a raw tag). } } /** * Registers the "EquaSuite" showcase submenu in LAST position (priority 99), * but ONLY while the content opt-in is ON. When OFF the page would only show the * local fallback, so we hide the entry entirely (no dead/empty menu item); the * welcome banner + its "Yes" button are the entry point to enable it. * * @return void */ public static function register_showcase_menu() { if ( ! self::content_optin() ) { return; } add_submenu_page( 'equasign', __( 'EquaSuite', 'equasign' ), __( 'EquaSuite', 'equasign' ), self::CAP, 'equasign-suite', array( __CLASS__, 'page_showcase' ) ); } /** * Renders the "EquaSuite" showcase page. * * @return void */ public static function page_showcase() { if ( ! current_user_can( self::CAP ) ) { wp_die( esc_html__( 'You are not allowed to access this page.', 'equasign' ) ); } echo '
'; echo '

' . esc_html__( 'EquaSuite', 'equasign' ) . '

'; if ( self::content_optin() ) { if ( class_exists( 'EquaSuite_Content_Client' ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- built/escaped inside the socle. echo EquaSuite_Content_Client::render_showcase( array( 'product_id' => self::PRODUCT, 'slot' => self::slot(), 'locale' => get_user_locale(), ) ); } } else { // Opt-in OFF: local welcome banner in place of the server showcase (no // network, no error). Non-dismissible here — it IS the page content. self::welcome_banner( false ); } echo '
'; } /* ---------------------------------------------------------------------- */ /* Opt-in handler (self-contained). */ /* ---------------------------------------------------------------------- */ /** * Persists the content-server opt-in, driven by the `content_optin` checkbox. * Serves both the one-click "Yes" of the welcome banner and the isolated opt-in * section of the settings page, then returns the merchant to the page they came * from. RGPD: the box is unchecked by default — nothing is enabled unless it is * actively ticked. * * @return void */ public static function h_content_enable() { if ( ! current_user_can( self::CAP ) ) { wp_die( esc_html__( 'You are not allowed to access this page.', 'equasign' ) ); } check_admin_referer( 'equasign_content_optin_enable' ); update_option( self::OPT_OPTIN, ! empty( $_POST['content_optin'] ) ? 1 : 0, false ); $back = wp_get_referer(); wp_safe_redirect( $back ? $back : admin_url( 'admin.php?page=equasign-settings' ) ); exit; } /** * AJAX: remember (per user, server-side) that the welcome banner was dismissed, * so it stays hidden for 4 hours. No page output. * * @return void */ public static function ajax_dismiss_incite() { check_ajax_referer( 'equasign_dismiss_incite' ); if ( ! current_user_can( self::CAP ) ) { wp_send_json_error( array( 'error' => 'forbidden' ), 403 ); } update_user_meta( get_current_user_id(), self::META_DISMISSED, time() ); wp_send_json_success(); } }