<?php if ( ! defined( 'ABSPATH' ) ) exit; class GT_BOGO_Bundle_Configurator { private $id = 'bundle_configurator'; public function __construct() { if ( is_admin() && ! defined('DOING_AJAX') ) return; if ( ! $this->enabled() ) return; add_action( 'wp_enqueue_scripts', [ $this, 'enqueue' ] ); } private function enabled() { return (bool) get_option( 'gtbogo_sp_' . $this->id . '_enabled', 0 ) && get_option( 'gtbogo_sp_' . $this->id . '_intensity', 'subtle' ) !== 'off'; } private function intensity() { return get_option( 'gtbogo_sp_' . $this->id . '_intensity', 'subtle' ); } private function styles() { $map = [ 'subtle' => [ 'font_size' => '0.85em', 'opacity' => '0.8' ], 'moderate' => [ 'font_size' => '0.9em', 'opacity' => '0.9' ], 'bold' => [ 'font_size' => '0.95em', 'opacity' => '1.0' ], ]; return $map[ $this->intensity() ] ?? $map['subtle']; } private function get_active_rule() { global $wpdb; return $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}gtbogo_rules WHERE status='active' ORDER BY priority ASC LIMIT 1", ARRAY_A ); } private function get_suggested_products( $current_id, $limit = 3 ) { global $product; $cats = []; if ( $product ) { $terms = get_the_terms( $product->get_id(), 'product_cat' ); if ( $terms ) $cats = wp_list_pluck( $terms, 'term_id' ); } $args = [ 'post_type' => 'product', 'posts_per_page' => $limit, 'post__not_in' => [ $current_id ], 'post_status' => 'publish', 'orderby' => 'rand', ]; if ( $cats ) { $args['tax_query'] = [ [ 'taxonomy' => 'product_cat', 'field' => 'term_id', 'terms' => $cats ] ]; } return get_posts( $args ); } public function enqueue() { wp_add_inline_style( 'woocommerce-general', ' .gtbogo-bundle-configurator{font-family:inherit;color:inherit;border:1px solid currentColor;border-radius:6px;padding:20px;margin:24px 0} .gtbogo-bundle-title{font-weight:700;margin:0 0 14px;font-size:1em} .gtbogo-bundle-items{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px} .gtbogo-bundle-item{display:flex;align-items:center;gap:8px;font-size:0.85em;opacity:0.8;cursor:pointer;border:1px solid currentColor;border-radius:4px;padding:6px 10px} .gtbogo-bundle-item img{width:40px;height:40px;object-fit:cover;border-radius:3px;flex-shrink:0} .gtbogo-bundle-item-name{font-weight:600} .gtbogo-bundle-item-price{opacity:0.6;font-size:0.9em} .gtbogo-bundle-savings{font-size:0.88em;font-weight:600;padding:8px 12px;border-left:3px solid currentColor;margin-top:10px} .gtbogo-bundle-add{display:inline-block;margin-top:12px;padding:10px 20px;border:1px solid currentColor;border-radius:4px;font-family:inherit;font-weight:600;font-size:0.85em;cursor:pointer;background:none;color:inherit} ' ); } public function render() { global $product; if ( ! $product ) return; $rule = $this->get_active_rule(); if ( ! $rule ) return; $buy = (int) ( $rule['buy_quantity'] ?? 1 ); $get = (int) ( $rule['get_quantity'] ?? 1 ); $disc = (int) ( $rule['discount_value'] ?? 50 ); $need = $buy - 1; if ( $need < 1 ) $need = 1; $posts = $this->get_suggested_products( $product->get_id(), $need + 1 ); if ( ! $posts ) return; $s = $this->styles(); ?> <div class="gtbogo-bundle-configurator" style="font-size:<?php echo esc_attr($s['font_size']); ?>;opacity:<?php echo esc_attr($s['opacity']); ?>"> <p class="gtbogo-bundle-title"> <?php printf( esc_html( GT_BOGO_Copy::format( 'bundle_headline_format', $this->intensity(), (int) $disc ) ), esc_html( $buy ), esc_html( $get ), esc_html( $disc ) ); ?> </p> <div class="gtbogo-bundle-items"> <?php echo '<div class="gtbogo-bundle-item">'; echo '<img src="' . esc_url( get_the_post_thumbnail_url( $product->get_id(), 'thumbnail' ) ) . '" alt="">'; echo '<div><div class="gtbogo-bundle-item-name">' . esc_html( $product->get_name() ) . '</div>'; echo '<div class="gtbogo-bundle-item-price">' . wp_kses_post( $product->get_price_html() ) . '</div></div>'; echo '</div>'; foreach ( array_slice( $posts, 0, $need ) as $post ) { $p = wc_get_product( $post->ID ); if ( ! $p ) continue; echo '<div class="gtbogo-bundle-item">'; echo '<img src="' . esc_url( get_the_post_thumbnail_url( $post->ID, 'thumbnail' ) ) . '" alt="">'; echo '<div><div class="gtbogo-bundle-item-name">' . esc_html( $p->get_name() ) . '</div>'; echo '<div class="gtbogo-bundle-item-price">' . wp_kses_post( $p->get_price_html() ) . '</div></div>'; echo '</div>'; } ?> </div> <div class="gtbogo-bundle-savings"> <?php printf( esc_html( GT_BOGO_Copy::format( 'bundle_qualifier_format', $this->intensity(), (int) $disc ) ), esc_html( $disc ) ); ?> </div> </div> <?php } }