get_active_popups(); $preview_id = $this->get_preview_id(); if ( empty( $popups ) && ! $preview_id ) { return; } // Ensure Gutenberg block styles (alignments, colours, etc.) are loaded. wp_enqueue_style( 'wp-block-library' ); wp_enqueue_style( 'foxcp-frontend', FOXCP_PLUGIN_URL . 'assets/css/popup-frontend.css', [ 'wp-block-library' ], FOXCP_VERSION ); wp_enqueue_script( 'foxcp-frontend', FOXCP_PLUGIN_URL . 'assets/js/popup-frontend.js', [], FOXCP_VERSION, true ); // Build popup config for JS. $popup_data = []; foreach ( $popups as $popup ) { $popup_data[] = [ 'id' => $popup->ID, 'delay' => (int) get_post_meta( $popup->ID, '_foxcp_trigger_delay', true ), 'scroll' => (int) get_post_meta( $popup->ID, '_foxcp_trigger_scroll', true ), 'preview' => false, 'cookieAlways' => (bool) get_post_meta( $popup->ID, '_foxcp_cookie_always', true ), 'cookieDuration' => (int) ( get_post_meta( $popup->ID, '_foxcp_cookie_duration', true ) ?: self::COOKIE_DAYS_FALLBACK ), 'cookieUnit' => get_post_meta( $popup->ID, '_foxcp_cookie_unit', true ) ?: 'days', 'animation' => get_post_meta( $popup->ID, '_foxcp_animation', true ) ?: 'none', 'exitIntent' => (bool) get_post_meta( $popup->ID, '_foxcp_trigger_exit_intent', true ), 'imageMode' => (bool) get_post_meta( $popup->ID, '_foxcp_image_mode', true ), 'linkUrl' => get_post_meta( $popup->ID, '_foxcp_link_url', true ) ?: '', ]; } // Preview popup: show immediately, skip cookie check. if ( $preview_id ) { // Only add once – avoid duplicate if it's already in the regular list. $already_listed = array_filter( $popup_data, static function ( $p ) use ( $preview_id ) { return (int) $p['id'] === $preview_id; } ); if ( empty( $already_listed ) ) { $popup_data[] = [ 'id' => $preview_id, 'delay' => 0, 'scroll' => 0, 'preview' => true, ]; } else { // Force immediate display for the preview entry. foreach ( $popup_data as &$p ) { if ( (int) $p['id'] === $preview_id ) { $p['preview'] = true; $p['delay'] = 0; $p['scroll'] = 0; } } unset( $p ); } } wp_localize_script( 'foxcp-frontend', 'foxcpData', [ 'popups' => $popup_data, ] ); } // ------------------------------------------------------------------------- // HTML output // ------------------------------------------------------------------------- public function render_popups() { $popups = $this->get_active_popups(); $preview_id = $this->get_preview_id(); if ( empty( $popups ) && ! $preview_id ) { return; } // Merge preview popup into render list if not already present. $ids_to_render = array_map( static function ( $p ) { return $p->ID; }, $popups ); if ( $preview_id && ! in_array( $preview_id, $ids_to_render, true ) ) { $preview_post = get_post( $preview_id ); if ( $preview_post ) { $popups[] = $preview_post; } } // Save the current global post so we can restore it afterwards. global $post; $original_post = $post; foreach ( $popups as $popup ) { $popup_id = (int) $popup->ID; $image_mode = (bool) get_post_meta( $popup_id, '_foxcp_image_mode', true ); $link_url = get_post_meta( $popup_id, '_foxcp_link_url', true ); $popup_classes = 'foxcp-popup'; if ( $image_mode ) { $popup_classes .= ' foxcp-image-mode'; } // Switch the global post context to this popup so that // the_content() and all its filters operate on the popup's // own post_content – not the content of the page being viewed. $post = $popup; // phpcs:ignore WordPress.WP.GlobalVariablesOverride setup_postdata( $popup ); ?> 'foxcp_popup', 'post_status' => 'publish', 'posts_per_page' => -1, ] ); if ( empty( $all_popups ) ) { return []; } return array_filter( $all_popups, function ( $popup ) { // Cart-abandonment popups are handled by FOXCP_WooCommerce. if ( get_post_meta( $popup->ID, '_foxcp_woo_cart_abandonment', true ) ) { return false; } if ( is_front_page() && get_post_meta( $popup->ID, '_foxcp_display_home', true ) ) { return true; } if ( is_single() && get_post_meta( $popup->ID, '_foxcp_display_posts', true ) ) { return true; } if ( is_page() && ! is_front_page() && get_post_meta( $popup->ID, '_foxcp_display_pages', true ) ) { return true; } return false; } ); } /** * Returns the popup ID from the ?foxcp_preview=ID query parameter. * Only available to logged-in users who can edit posts. * * @return int|false */ private function get_preview_id() { if ( empty( $_GET['foxcp_preview'] ) ) { return false; } // Only allow editors/admins to use preview mode. if ( ! current_user_can( 'edit_posts' ) ) { return false; } $id = absint( $_GET['foxcp_preview'] ); // Verify nonce to prevent unauthorized preview access. if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'foxcp_preview_' . $id ) ) { return false; } $post = get_post( $id ); if ( ! $post || 'foxcp_popup' !== $post->post_type ) { return false; } return $id; } }