settings_helper = $settings_helper; add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) ); add_action( 'wp_body_open', array( $this, 'render' ), 5 ); add_action( 'wp_footer', array( $this, 'render_fallback' ), 5 ); add_shortcode( 'aaweb_announcement_bar_preview', array( $this, 'shortcode_preview' ) ); } /** * Enqueue frontend CSS/JS when needed. * * @return void */ public function enqueue_assets() { $settings = $this->settings_helper->get(); if ( ! $this->should_display( $settings ) && ! is_admin() ) { return; } wp_enqueue_style( 'aaweb-ab-public', AAWEB_AB_URL . 'assets/css/public.css', array(), AAWEB_AB_VERSION ); wp_enqueue_script( 'aaweb-ab-public', AAWEB_AB_URL . 'assets/js/public.js', array(), AAWEB_AB_VERSION, true ); } /** * Fallback render for themes without wp_body_open. * * @return void */ public function render_fallback() { if ( did_action( 'wp_body_open' ) ) { return; } $this->render(); } /** * Render live bar. * * @return void */ public function render() { if ( $this->rendered ) { return; } $settings = $this->settings_helper->get(); if ( ! $this->should_display( $settings ) ) { return; } $this->rendered = true; echo $this->get_markup( $settings, false ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Shortcode preview. * * @return string */ public function shortcode_preview() { $settings = $this->settings_helper->get(); wp_enqueue_style( 'aaweb-ab-public', AAWEB_AB_URL . 'assets/css/public.css', array(), AAWEB_AB_VERSION ); wp_enqueue_script( 'aaweb-ab-public', AAWEB_AB_URL . 'assets/js/public.js', array(), AAWEB_AB_VERSION, true ); return $this->get_markup( $settings, true ); } /** * Check display rules. * * @param array $settings Settings. * @return bool */ private function should_display( $settings ) { if ( empty( $settings['enabled'] ) || is_admin() || wp_doing_ajax() || wp_doing_cron() ) { return false; } if ( ! empty( $_GET['elementor-preview'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended return false; } if ( ! $this->is_within_schedule( $settings ) || ! $this->device_matches( $settings ) || $this->excluded_by_page_id( $settings ) ) { return false; } if ( 'homepage' === $settings['display_rule'] && ! is_front_page() ) { return false; } if ( 'exclude_wc_pages' === $settings['display_rule'] && $this->is_woocommerce_excluded_page() ) { return false; } if ( 'woo_products' === $settings['display_rule'] && ! $this->matches_target_products( $settings ) ) { return false; } if ( 'woo_categories' === $settings['display_rule'] && ! $this->matches_target_categories( $settings ) ) { return false; } return true; } /** * Check WooCommerce excluded pages. * * @return bool */ private function is_woocommerce_excluded_page() { return ( function_exists( 'is_cart' ) && is_cart() ) || ( function_exists( 'is_checkout' ) && is_checkout() ) || ( function_exists( 'is_account_page' ) && is_account_page() ); } /** * Match selected WooCommerce product IDs. * * @param array $settings Settings. * @return bool */ private function matches_target_products( $settings ) { if ( ! function_exists( 'is_product' ) || ! is_product() ) { return false; } $ids = $this->parse_id_list( $settings['target_product_ids'] ); return ! empty( $ids ) && in_array( get_queried_object_id(), $ids, true ); } /** * Match selected WooCommerce product categories. * * Matches both category archive pages and single products assigned to a selected category. * * @param array $settings Settings. * @return bool */ private function matches_target_categories( $settings ) { $ids = $this->parse_id_list( $settings['target_category_ids'] ); if ( empty( $ids ) ) { return false; } if ( function_exists( 'is_product_category' ) && is_product_category() ) { return in_array( get_queried_object_id(), $ids, true ); } if ( function_exists( 'is_product' ) && is_product() ) { $product_id = get_queried_object_id(); $terms = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'ids' ) ); if ( is_wp_error( $terms ) ) { return false; } return (bool) array_intersect( $ids, array_map( 'absint', $terms ) ); } return false; } /** * Parse a comma separated list of IDs. * * @param mixed $value Raw value. * @return array */ private function parse_id_list( $value ) { return array_values( array_unique( array_filter( array_map( 'absint', array_map( 'trim', explode( ',', (string) $value ) ) ) ) ) ); } /** * Schedule check. * * @param array $settings Settings. * @return bool */ private function is_within_schedule( $settings ) { $today = current_time( 'Y-m-d' ); if ( ! empty( $settings['start_date'] ) && $today < $settings['start_date'] ) { return false; } if ( ! empty( $settings['end_date'] ) && $today > $settings['end_date'] ) { return false; } return true; } /** * Device check. * * @param array $settings Settings. * @return bool */ private function device_matches( $settings ) { $is_mobile = function_exists( 'wp_is_mobile' ) && wp_is_mobile(); if ( 'desktop' === $settings['device_visibility'] && $is_mobile ) { return false; } if ( 'mobile' === $settings['device_visibility'] && ! $is_mobile ) { return false; } return true; } /** * Page ID exclusions. * * @param array $settings Settings. * @return bool */ private function excluded_by_page_id( $settings ) { if ( empty( $settings['exclude_page_ids'] ) ) { return false; } $ids = array_filter( array_map( 'absint', explode( ',', (string) $settings['exclude_page_ids'] ) ) ); return is_singular() && in_array( get_queried_object_id(), $ids, true ); } /** * Render markup. * * @param array $settings Settings. * @param bool $preview Preview mode. * @return string */ private function get_markup( $settings, $preview = false ) { $content_html = $this->get_content_html( $settings ); $button_html = $this->get_button_html( $settings ); $coupon_html = $this->get_coupon_html( $settings ); $countdown_html = $this->get_countdown_html( $settings ); if ( '' === trim( wp_strip_all_tags( $content_html . $button_html . $coupon_html . $countdown_html ) ) && '' === trim( $content_html . $button_html . $coupon_html . $countdown_html ) ) { return ''; } $bar_id = $preview ? 'aaweb-announcement-bar-preview' : 'aaweb-announcement-bar'; $hash = $this->get_version_hash( $settings ); $dismissible = ! empty( $settings['dismissible'] ) && ! $preview; $wrapper_attr = $this->get_wrapper_attributes( $settings, $bar_id, $hash, $dismissible ); ob_start(); ?>
>
$settings Settings. * @param string $bar_id ID. * @param string $hash Version hash. * @param bool $dismissible Dismissible. * @return string */ private function get_wrapper_attributes( $settings, $bar_id, $hash, $dismissible ) { $classes = array( 'aaweb-ab-wrap', 'aaweb-ab-align-' . sanitize_html_class( $settings['horizontal_align'] ), 'aaweb-ab-valign-' . sanitize_html_class( $settings['vertical_align'] ), ); if ( ! empty( $settings['sticky'] ) ) { $classes[] = 'is-sticky'; } if ( ! empty( $settings['border_bottom'] ) ) { $classes[] = 'has-border-bottom'; } if ( $dismissible ) { $classes[] = 'is-dismissible'; } if ( ! empty( $settings['custom_class'] ) ) { $classes[] = sanitize_html_class( $settings['custom_class'] ); } $style_parts = array( '--aaweb-ab-bg:' . esc_attr( $settings['background_color'] ), '--aaweb-ab-text:' . esc_attr( $settings['text_color'] ), '--aaweb-ab-link:' . esc_attr( $settings['link_color'] ), '--aaweb-ab-border:' . esc_attr( $settings['border_color'] ), '--aaweb-ab-font-size:' . (int) $settings['font_size'] . 'px', '--aaweb-ab-font-weight:' . esc_attr( $settings['font_weight'] ), '--aaweb-ab-btn-bg:' . esc_attr( $settings['button_bg_color'] ), '--aaweb-ab-btn-text:' . esc_attr( $settings['button_text_color'] ), '--aaweb-ab-btn-hover-bg:' . esc_attr( $settings['button_hover_bg_color'] ), '--aaweb-ab-btn-hover-text:' . esc_attr( $settings['button_hover_text_color'] ), '--aaweb-ab-btn-border:' . esc_attr( $settings['button_border_color'] ), '--aaweb-ab-btn-border-width:' . (int) $settings['button_border_width'] . 'px', '--aaweb-ab-btn-radius:' . (int) $settings['button_radius'] . 'px', '--aaweb-ab-btn-py:' . (int) $settings['button_padding_y'] . 'px', '--aaweb-ab-btn-px:' . (int) $settings['button_padding_x'] . 'px', '--aaweb-ab-btn-font-size:' . (int) $settings['button_font_size'] . 'px', '--aaweb-ab-btn-font-weight:' . esc_attr( $settings['button_font_weight'] ), '--aaweb-ab-btn-ml:' . (int) $settings['button_margin_left'] . 'px', '--aaweb-ab-btn-mr:' . (int) $settings['button_margin_right'] . 'px', '--aaweb-ab-close-bg:' . esc_attr( $settings['close_bg_color'] ), '--aaweb-ab-close-text:' . esc_attr( $settings['close_text_color'] ), '--aaweb-ab-close-hover-bg:' . esc_attr( $settings['close_hover_bg_color'] ), '--aaweb-ab-close-hover-text:' . esc_attr( $settings['close_hover_text_color'] ), '--aaweb-ab-close-border:' . esc_attr( $settings['close_border_color'] ), '--aaweb-ab-close-border-width:' . (int) $settings['close_border_width'] . 'px', '--aaweb-ab-close-size:' . (int) $settings['close_size'] . 'px', '--aaweb-ab-close-icon-size:' . (int) $settings['close_icon_size'] . 'px', '--aaweb-ab-close-radius:' . (int) $settings['close_radius'] . 'px', '--aaweb-ab-close-right:' . (int) $settings['close_right'] . 'px', ); if ( ! empty( $settings['container_width'] ) ) { $style_parts[] = '--aaweb-ab-width:' . (int) $settings['container_width'] . 'px'; } $style = implode( ';', $style_parts ) . ';'; return sprintf( 'id="%1$s" class="%2$s" role="status" aria-label="%3$s" style="%4$s" data-dismiss-days="%5$d" data-version-hash="%6$s"', esc_attr( $bar_id ), esc_attr( implode( ' ', $classes ) ), esc_attr__( 'Site announcement', 'aaweb-announcement-bar' ), esc_attr( $style ), (int) $settings['dismiss_days'], esc_attr( $hash ) ); } /** * Get safe content HTML without CTA link. * * @param array $settings Settings. * @return string */ private function get_content_html( $settings ) { if ( 'html' === $settings['content_mode'] && ! empty( $settings['html_content'] ) ) { $primary = wp_kses_post( $settings['html_content'] ); } else { $primary = esc_html( $settings['text'] ); } if ( empty( $settings['mobile_text_enabled'] ) || '' === trim( (string) $settings['mobile_text'] ) ) { return $primary; } return sprintf( '
%1$s
%2$s
', $primary, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped esc_html( $settings['mobile_text'] ) ); } /** * Get CTA button markup. * * @param array $settings Settings. * @return string */ private function get_button_html( $settings ) { if ( empty( $settings['button_enabled'] ) || empty( $settings['link_url'] ) || empty( $settings['link_text'] ) ) { return ''; } $classes = array( 'aaweb-ab-button' ); if ( 'desktop' === $settings['button_visibility'] ) { $classes[] = 'aaweb-ab-button-desktop-only'; } if ( 'mobile' === $settings['button_visibility'] ) { $classes[] = 'aaweb-ab-button-mobile-only'; } if ( 'none' !== $settings['button_animation'] ) { $classes[] = 'has-animation-' . sanitize_html_class( $settings['button_animation'] ); } $rel = '_blank' === $settings['link_target'] ? ' rel="noopener noreferrer"' : ''; return sprintf( '%5$s', esc_url( $settings['link_url'] ), esc_attr( implode( ' ', $classes ) ), esc_attr( $settings['link_target'] ), $rel, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped esc_html( $settings['link_text'] ) ); } /** * Get click-to-copy coupon markup. * * @param array $settings Settings. * @return string */ private function get_coupon_html( $settings ) { if ( empty( $settings['coupon_enabled'] ) || '' === trim( (string) $settings['coupon_code'] ) ) { return ''; } return sprintf( '', esc_attr( $settings['coupon_code'] ), esc_attr__( 'Copied!', 'aaweb-announcement-bar' ), esc_attr__( 'Copy failed', 'aaweb-announcement-bar' ), esc_attr( sprintf( /* translators: %s: coupon code. */ __( 'Copy coupon code %s', 'aaweb-announcement-bar' ), $settings['coupon_code'] ) ), esc_html( $settings['coupon_label'] ), esc_html( $settings['coupon_code'] ) ); } /** * Get countdown markup. * * @param array $settings Settings. * @return string */ private function get_countdown_html( $settings ) { if ( empty( $settings['countdown_enabled'] ) || empty( $settings['end_date'] ) ) { return ''; } $end = date_create_from_format( 'Y-m-d H:i:s', $settings['end_date'] . ' 23:59:59', wp_timezone() ); if ( ! $end ) { return ''; } return sprintf( '%2$s --:--:--', esc_attr( $end->format( DATE_ATOM ) ), esc_html( $settings['countdown_label'] ) ); } /** * Get content version hash for dismiss cookies. * * @param array $settings Settings. * @return string */ private function get_version_hash( $settings ) { $source = wp_json_encode( array( 'content_mode' => $settings['content_mode'], 'text' => $settings['text'], 'html_content' => $settings['html_content'], 'mobile_text_enabled'=> $settings['mobile_text_enabled'], 'mobile_text' => $settings['mobile_text'], 'button_enabled' => $settings['button_enabled'], 'link_url' => $settings['link_url'], 'link_text' => $settings['link_text'], 'button_position' => $settings['button_position'], 'horizontal_align' => $settings['horizontal_align'], 'vertical_align' => $settings['vertical_align'], 'button_visibility' => $settings['button_visibility'], 'coupon_enabled' => $settings['coupon_enabled'], 'coupon_label' => $settings['coupon_label'], 'coupon_code' => $settings['coupon_code'], 'start_date' => $settings['start_date'], 'end_date' => $settings['end_date'], 'countdown_enabled' => $settings['countdown_enabled'], 'countdown_label' => $settings['countdown_label'], 'display_rule' => $settings['display_rule'], 'target_product_ids' => $settings['target_product_ids'], 'target_category_ids'=> $settings['target_category_ids'], 'device_visibility' => $settings['device_visibility'], ) ); return substr( md5( (string) $source ), 0, 12 ); } }