*/ private $settings; /** * Store settings for message generation. * * @param array $settings Sanitized plugin settings. */ public function __construct( $settings ) { $this->settings = $settings; } /** * Whether a usable international destination number is configured. * * @return bool */ public function is_ready() { return 1 === preg_match( '/^\d{7,15}$/', $this->settings['phone'] ); } /** * Return the destination URL prefix used by product-page JavaScript. * * @return string */ public function get_base_url() { if ( ! $this->is_ready() ) { return ''; } return 'https://wa.me/' . $this->settings['phone'] . '?text='; } /** * Build a complete click URL for a message. * * @param string $message Plain-text message. * @return string */ public function get_chat_url( $message ) { $base_url = $this->get_base_url(); if ( '' === $base_url || '' === $message ) { return ''; } return $base_url . rawurlencode( $message ); } /** * Return display-safe product values used by PHP and browser message builders. * * @param WC_Product $product WooCommerce product. * @return array */ public function get_product_context( $product ) { if ( ! $product instanceof WC_Product ) { return array(); } $product_url = get_permalink( $product->get_id() ); return array( 'name' => $this->plain_text( $product->get_name() ), 'sku' => $this->plain_text( $product->get_sku() ), 'price' => $this->product_price_text( $product ), 'url' => is_string( $product_url ) ? $product_url : '', ); } /** * Format the current catalog price without hidden screen-reader duplicates. * * @param WC_Product $product WooCommerce product. * @return string */ private function product_price_text( $product ) { if ( $product->is_type( 'variable' ) ) { $minimum = (float) $product->get_variation_price( 'min', true ); $maximum = (float) $product->get_variation_price( 'max', true ); if ( $minimum !== $maximum ) { return $this->plain_text( wc_price( $minimum ) ) . ' - ' . $this->plain_text( wc_price( $maximum ) ); } return $this->plain_text( wc_price( $minimum ) ); } if ( '' === $product->get_price() ) { return ''; } return $this->plain_text( wc_price( wc_get_price_to_display( $product ) ) ); } /** * Build the server-side product fallback message. * * @param WC_Product $product WooCommerce product. * @param float $quantity Selected quantity. * @return string */ public function get_product_message( $product, $quantity = 1 ) { $context = $this->get_product_context( $product ); if ( empty( $context ) ) { return ''; } return $this->get_product_message_from_context( $context, $quantity ); } /** * Build a product message from an already-sanitized context. * * @param array $context Product values. * @param float $quantity Selected quantity. * @param array $options Selected variation labels. * @return string */ public function get_product_message_from_context( $context, $quantity = 1, $options = array() ) { if ( empty( $context['name'] ) ) { return ''; } $lines = $this->get_message_opening(); $lines[] = sprintf( '%1$s: %2$s', __( 'Product', 'aetos-quick-order-chat' ), $context['name'] ); $lines[] = sprintf( '%1$s: %2$s', __( 'Quantity', 'aetos-quick-order-chat' ), $this->format_quantity( $quantity ) ); $options = array_values( array_filter( array_map( array( $this, 'plain_text' ), $options ) ) ); if ( ! empty( $options ) ) { $lines[] = sprintf( '%1$s: %2$s', __( 'Options', 'aetos-quick-order-chat' ), implode( ', ', $options ) ); } if ( $this->settings['include_sku'] && ! empty( $context['sku'] ) ) { $lines[] = sprintf( '%1$s: %2$s', __( 'SKU', 'aetos-quick-order-chat' ), $context['sku'] ); } if ( $this->settings['include_price'] && ! empty( $context['price'] ) ) { $lines[] = sprintf( '%1$s: %2$s', __( 'Price', 'aetos-quick-order-chat' ), $context['price'] ); } if ( $this->settings['include_link'] && ! empty( $context['url'] ) ) { $lines[] = sprintf( '%1$s: %2$s', __( 'Link', 'aetos-quick-order-chat' ), $context['url'] ); } return implode( "\n", $lines ); } /** * Build a message from the current WooCommerce cart session. * * @return string */ public function get_cart_message() { if ( ! function_exists( 'WC' ) || ! WC()->cart || WC()->cart->is_empty() ) { return ''; } $lines = $this->get_message_opening(); $item_index = 0; foreach ( WC()->cart->get_cart() as $cart_item ) { $product = isset( $cart_item['data'] ) ? $cart_item['data'] : null; if ( ! $product instanceof WC_Product || ! $product->exists() ) { continue; } ++$item_index; $quantity = isset( $cart_item['quantity'] ) ? (float) $cart_item['quantity'] : 1; $lines[] = sprintf( '%1$d. %2$s x %3$s', $item_index, $this->plain_text( $product->get_name() ), $this->format_quantity( $quantity ) ); if ( $this->settings['include_sku'] && $product->get_sku() ) { $lines[] = sprintf( '%1$s: %2$s', __( 'SKU', 'aetos-quick-order-chat' ), $this->plain_text( $product->get_sku() ) ); } if ( $this->settings['include_price'] ) { $lines[] = sprintf( '%1$s: %2$s', __( 'Line total', 'aetos-quick-order-chat' ), $this->plain_text( WC()->cart->get_product_subtotal( $product, $quantity ) ) ); } } if ( 0 === $item_index ) { return ''; } if ( $this->settings['include_price'] ) { $lines[] = ''; $lines[] = sprintf( '%1$s: %2$s', __( 'Cart total', 'aetos-quick-order-chat' ), $this->plain_text( wc_price( (float) WC()->cart->get_total( 'edit' ) ) ) ); } if ( $this->settings['include_link'] ) { $lines[] = sprintf( '%1$s: %2$s', __( 'Cart link', 'aetos-quick-order-chat' ), wc_get_cart_url() ); } return implode( "\n", $lines ); } /** * Return the custom introduction followed by one separating line. * * @return array */ private function get_message_opening() { return array( $this->settings['intro'], '' ); } /** * Convert an HTML-formatted WooCommerce value to readable plain text. * * @param mixed $value Value to normalize. * @return string */ public function plain_text( $value ) { $charset = get_bloginfo( 'charset' ); $charset = $charset ? $charset : 'UTF-8'; $text = wp_strip_all_tags( (string) $value ); return trim( html_entity_decode( $text, ENT_QUOTES, $charset ) ); } /** * Format integer or decimal quantities without unnecessary zeroes. * * @param float $quantity Quantity value. * @return string */ private function format_quantity( $quantity ) { $quantity = max( 0.001, (float) $quantity ); $formatted = number_format( $quantity, 3, '.', '' ); return rtrim( rtrim( $formatted, '0' ), '.' ); } }