status_manager = $status_manager; } /** * Register hooks. * * @return void */ public function register() { add_filter( 'woocommerce_is_purchasable', array( $this, 'filter_is_purchasable' ), 10, 2 ); add_filter( 'woocommerce_variation_is_purchasable', array( $this, 'filter_variation_is_purchasable' ), 10, 2 ); add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'filter_add_to_cart_validation' ), 10, 5 ); add_action( 'woocommerce_checkout_process', array( $this, 'validate_checkout_process' ) ); add_action( 'woocommerce_after_checkout_validation', array( $this, 'validate_checkout_after_validation' ), 10, 2 ); add_filter( 'woocommerce_product_single_add_to_cart_text', array( $this, 'filter_add_to_cart_text' ) ); add_filter( 'woocommerce_product_add_to_cart_text', array( $this, 'filter_add_to_cart_text' ) ); add_filter( 'woocommerce_add_to_cart_url', array( $this, 'filter_add_to_cart_url' ), 10, 2 ); add_action( 'woocommerce_single_product_summary', array( $this, 'render_single_product_closed_message' ), 4 ); add_action( 'template_redirect', array( $this, 'maybe_redirect_checkout_when_offline' ), 20 ); add_action( 'wp_footer', array( $this, 'render_live_status_script' ), 99 ); } /** * Filter purchasability when store is offline. * * @param bool $is_purchasable Purchasable flag. * @param WC_Product $product Product object. * @return bool */ public function filter_is_purchasable( $is_purchasable, $product ) { unset( $product ); if ( ! $is_purchasable ) { return false; } return $this->status_manager->is_online(); } /** * Variation purchasability mirror filter. * * @param bool $is_purchasable Purchasable flag. * @param WC_Product $variation Variation object. * @return bool */ public function filter_variation_is_purchasable( $is_purchasable, $variation ) { return $this->filter_is_purchasable( $is_purchasable, $variation ); } /** * Validate add-to-cart requests while offline. * * @param bool $passed Validation state. * @param int $product_id Product ID. * @param int $quantity Quantity. * @param int $variation_id Variation ID. * @param array $variations Variation data. * @return bool */ public function filter_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = 0, $variations = array() ) { unset( $product_id, $quantity, $variation_id, $variations ); if ( ! $passed ) { return false; } if ( $this->status_manager->is_online() ) { return true; } $message = $this->status_manager->get_closed_message(); if ( '' !== $message && function_exists( 'wc_add_notice' ) ) { wc_add_notice( $message, 'error' ); } return false; } /** * Checkout validation. * * @return void */ public function validate_checkout_process() { if ( $this->status_manager->is_online() ) { return; } $message = $this->status_manager->get_closed_message(); if ( '' !== $message && function_exists( 'wc_add_notice' ) ) { wc_add_notice( $message, 'error' ); } } /** * Checkout validation errors. * * @param array $data Posted data. * @param WP_Error $errors Error object. * @return void */ public function validate_checkout_after_validation( $data, $errors ) { unset( $data ); if ( $this->status_manager->is_online() ) { return; } $message = $this->status_manager->get_closed_message(); if ( '' !== $message && $errors instanceof WP_Error ) { $errors->add( 'abct_store_closed', $message ); } } /** * Replace add-to-cart label when offline. * * @param string $text Current text. * @return string */ public function filter_add_to_cart_text( $text ) { if ( $this->status_manager->is_online() ) { return $text; } return __( 'Store closed', 'abct-smart-orders' ); } /** * Redirect loop add-to-cart links to product page when offline. * * @param string $url URL. * @param WC_Product $product Product. * @return string */ public function filter_add_to_cart_url( $url, $product ) { if ( $this->status_manager->is_online() ) { return $url; } if ( is_object( $product ) && method_exists( $product, 'get_id' ) ) { return get_permalink( $product->get_id() ); } return $url; } /** * Render closed message on product pages. * * @return void */ public function render_single_product_closed_message() { if ( $this->status_manager->is_online() ) { return; } if ( method_exists( $this->status_manager, 'should_show_closed_message' ) && ! $this->status_manager->should_show_closed_message() ) { return; } $message = $this->status_manager->get_closed_message(); if ( '' === $message ) { return; } echo '
' . esc_html( $message ) . '
'; } /** * Prevent checkout completion flow while offline. * * @return void */ public function maybe_redirect_checkout_when_offline() { $is_order_received = function_exists( 'is_wc_endpoint_url' ) && is_wc_endpoint_url( 'order-received' ); if ( ! function_exists( 'is_checkout' ) || ! is_checkout() || $is_order_received ) { return; } if ( $this->status_manager->is_online() ) { return; } $message = $this->status_manager->get_closed_message(); if ( '' !== $message && function_exists( 'wc_add_notice' ) ) { wc_add_notice( $message, 'error' ); } if ( function_exists( 'wc_get_cart_url' ) ) { wp_safe_redirect( wc_get_cart_url() ); exit; } } /** * Render lightweight status polling script. * * @return void */ public function render_live_status_script() { if ( ! function_exists( 'is_woocommerce' ) ) { return; } if ( ! ( is_woocommerce() || ( function_exists( 'is_cart' ) && is_cart() ) || ( function_exists( 'is_checkout' ) && is_checkout() ) || ( function_exists( 'is_product' ) && is_product() ) ) ) { return; } $interval_ms = max( 5000, absint( apply_filters( 'abct_store_status_poll_interval_ms', 10000 ) ) ); ?>