template_engine = new GC_Template_Engine(); $this->init_hooks(); } /** * Initialize hooks based on configured position. * * @return void */ private function init_hooks(): void { // Only load on frontend. if ( is_admin() ) { return; } // Check if delivery display is enabled. if ( 'no' === get_option( 'genius_commerce_enable_delivery_display', 'yes' ) ) { return; } $position = get_option( 'genius_commerce_delivery_position', 'after_price' ); switch ( $position ) { case 'after_price': // Priority 25 = after price (priority 10) and before excerpt (priority 20). add_action( 'woocommerce_single_product_summary', array( $this, 'display_delivery' ), 15 ); break; case 'after_excerpt': // Priority 25 = after excerpt (priority 20). add_action( 'woocommerce_single_product_summary', array( $this, 'display_delivery' ), 25 ); break; case 'manual': // Only via shortcode - no automatic display. break; } // Register shortcode for manual placement. add_shortcode( 'genius_delivery', array( $this, 'delivery_shortcode' ) ); } /** * Display delivery information on product page. * * Hooked to woocommerce_single_product_summary. * * @return void */ public function display_delivery(): void { global $product; if ( ! $product instanceof \WC_Product ) { return; } $delivery = $this->get_delivery_info( $product ); if ( ! $delivery ) { return; } // Build template arguments. $template_args = array( 'delivery_date' => $delivery['formatted'], 'delivery_type' => $delivery['type'], 'delivery_raw' => $delivery['value'], 'product' => $product, ); /** * Filter the delivery product template arguments. * * Allows themes to modify or add template variables. * * @since 1.0.0 * * @param array $template_args Template arguments. * @param \WC_Product $product The product object. * @param array $delivery Raw delivery data. */ $template_args = apply_filters( 'genius_commerce_delivery_product_template_args', $template_args, $product, $delivery ); echo wp_kses_post( $this->template_engine->render( 'delivery-product.php', $template_args ) ); } /** * Get delivery information for a product. * * Checks product meta fields in order of priority: * 1. genius_deliverydate (specific date) * 2. genius_deliverytime (text like "2-3 werkdagen") * 3. Default from settings * * @param \WC_Product $product Product object. * @return array{type: string, value: string, formatted: string}|null Delivery info or null. */ private function get_delivery_info( \WC_Product $product ): ?array { // First try specific delivery date. $delivery_date = $product->get_meta( 'genius_deliverydate' ); if ( ! empty( $delivery_date ) ) { return array( 'type' => 'date', 'value' => $delivery_date, 'formatted' => $this->format_date( $delivery_date ), ); } // Then try textual delivery time. $delivery_time = $product->get_meta( 'genius_deliverytime' ); if ( ! empty( $delivery_time ) ) { return array( 'type' => 'text', 'value' => $delivery_time, 'formatted' => $delivery_time, ); } // Fallback to default from settings. $default = get_option( 'genius_commerce_default_delivery_time', '' ); if ( ! empty( $default ) ) { return array( 'type' => 'default', 'value' => $default, 'formatted' => $default, ); } // No delivery info available. return null; } /** * Format a date string for display. * * @param string $date ISO date string (Y-m-d). * @return string Formatted date string. */ private function format_date( string $date ): string { $timestamp = strtotime( $date ); if ( false === $timestamp ) { return $date; } // Use WordPress date format. return wp_date( get_option( 'date_format', 'j F Y' ), $timestamp ); } /** * Shortcode handler for delivery display. * * Usage: [genius_delivery] * Usage: [genius_delivery format="d-m-Y"] * Usage: [genius_delivery prefix="Verwachte levering: "] * Usage: [genius_delivery prefix=""] (geen prefix) * * @param array $atts Shortcode attributes. * @return string Rendered delivery HTML. */ public function delivery_shortcode( $atts ): string { $atts = shortcode_atts( array( 'format' => '', 'prefix' => __( 'Levertijd: ', 'genius-commerce' ), 'fallback' => '', 'context' => 'auto', ), $atts, 'genius_delivery' ); // Determine context. $delivery_date = null; if ( 'cart' === $atts['context'] || ( 'auto' === $atts['context'] && ( is_cart() || is_checkout() ) ) ) { // Cart context - get furthest delivery date. $delivery_date = $this->get_furthest_cart_delivery_date(); } else { // Product context. global $product; if ( $product instanceof \WC_Product ) { $delivery = $this->get_delivery_info( $product ); if ( $delivery ) { $delivery_date = $delivery['formatted']; // Apply custom format if provided and it's a date type. if ( ! empty( $atts['format'] ) && 'date' === $delivery['type'] ) { $timestamp = strtotime( $delivery['value'] ); if ( $timestamp ) { $delivery_date = wp_date( $atts['format'], $timestamp ); } } } } } // No delivery date found. if ( ! $delivery_date ) { return esc_html( $atts['fallback'] ); } // Build template arguments — escape shortcode attributes to prevent XSS. $template_args = array( 'prefix' => esc_html( $atts['prefix'] ), 'delivery_date' => esc_html( $delivery_date ), 'context' => esc_attr( $atts['context'] ), ); /** * Filter the delivery cart/shortcode template arguments. * * Allows themes to modify or add template variables. * * @since 1.0.0 * * @param array $template_args Template arguments. * @param array $atts Shortcode attributes. */ $template_args = apply_filters( 'genius_commerce_delivery_cart_template_args', $template_args, $atts ); // Render using template. return $this->template_engine->render( 'delivery-cart.php', $template_args ); } /** * Get the furthest delivery date from all cart items. * * @return string|null Formatted delivery date or null. */ private function get_furthest_cart_delivery_date(): ?string { if ( ! WC()->cart || WC()->cart->is_empty() ) { return null; } $furthest_timestamp = null; $fallback_text = null; foreach ( WC()->cart->get_cart() as $cart_item ) { /** @var \WC_Product $product */ $product = $cart_item['data']; // Check for specific date. $delivery_date = $product->get_meta( 'genius_deliverydate' ); if ( ! empty( $delivery_date ) ) { $timestamp = strtotime( $delivery_date ); if ( $timestamp && ( null === $furthest_timestamp || $timestamp > $furthest_timestamp ) ) { $furthest_timestamp = $timestamp; } } elseif ( null === $fallback_text ) { // Capture first text-based delivery time as fallback. $delivery_time = $product->get_meta( 'genius_deliverytime' ); if ( ! empty( $delivery_time ) ) { $fallback_text = $delivery_time; } } } // Return furthest date if available. if ( null !== $furthest_timestamp ) { return wp_date( get_option( 'date_format', 'j F Y' ), $furthest_timestamp ); } // Return text fallback. if ( null !== $fallback_text ) { return $fallback_text; } // Return default from settings. $default = get_option( 'genius_commerce_default_delivery_time', '' ); if ( ! empty( $default ) ) { return $default; } return null; } }