includes(); $this->init_hooks(); } /** * Include required files. */ private function includes() { // Core. require_once ORDERCOURIER_PATH . 'includes/class-install.php'; require_once ORDERCOURIER_PATH . 'includes/class-settings.php'; require_once ORDERCOURIER_PATH . 'includes/class-restrictions.php'; require_once ORDERCOURIER_PATH . 'includes/class-message-builder.php'; require_once ORDERCOURIER_PATH . 'includes/class-phone-validator.php'; require_once ORDERCOURIER_PATH . 'includes/class-agent-manager.php'; require_once ORDERCOURIER_PATH . 'includes/class-order-manager.php'; require_once ORDERCOURIER_PATH . 'includes/class-rate-limiter.php'; require_once ORDERCOURIER_PATH . 'includes/class-privacy.php'; require_once ORDERCOURIER_PATH . 'includes/class-events.php'; // Admin. if ( is_admin() ) { require_once ORDERCOURIER_PATH . 'includes/admin/class-admin.php'; } // Frontend. if ( ! is_admin() || wp_doing_ajax() ) { require_once ORDERCOURIER_PATH . 'includes/frontend/class-frontend.php'; require_once ORDERCOURIER_PATH . 'includes/frontend/class-widget.php'; } // Blocks. require_once ORDERCOURIER_PATH . 'includes/blocks/class-blocks-integration.php'; // Gateway. require_once ORDERCOURIER_PATH . 'includes/class-gateway.php'; // REST API. require_once ORDERCOURIER_PATH . 'includes/api/class-rest-api.php'; require_once ORDERCOURIER_PATH . 'includes/api/class-store-api.php'; } /** * Initialize hooks. */ private function init_hooks() { add_action( 'init', array( $this, 'init' ) ); add_action( 'woocommerce_init', array( $this, 'woocommerce_init' ) ); add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateway' ) ); add_action( 'template_redirect', array( 'Prologic365\OrderCourier\Gateway', 'handle_redirect_bridge' ) ); // Disable shipping for quote-only carts. add_filter( 'woocommerce_cart_needs_shipping', array( $this, 'cart_needs_shipping' ) ); add_filter( 'woocommerce_product_needs_shipping', array( $this, 'product_needs_shipping' ), 10, 2 ); // Send admin email when chat order is created. add_action( 'ordercourier_after_create_order', array( $this, 'maybe_send_admin_email' ), 10, 3 ); } /** * Initialize on init action. */ public function init() { // Register custom order status. Order_Manager::register_order_status(); // Initialize privacy hooks. new Privacy(); // Initialize events tracking. Events::init(); /** * Action fired when OrderCourier initializes. * PRO and other add-ons can use this to register their features. * * @since 1.0.0 */ do_action( 'ordercourier_init' ); } /** * Initialize when WooCommerce is ready. */ public function woocommerce_init() { // Initialize admin. if ( is_admin() ) { new Admin\Admin(); } // Initialize frontend. if ( ! is_admin() || wp_doing_ajax() ) { new Frontend\Frontend(); new Frontend\Widget(); } // Initialize blocks integration. new Blocks\Blocks_Integration(); // Initialize REST API. new API\REST_API(); new API\Store_API(); } /** * Add payment gateway. * * @param array $gateways Payment gateways. * @return array */ public function add_gateway( $gateways ) { $gateways[] = 'Prologic365\OrderCourier\Gateway'; return $gateways; } /** * Check if cart needs shipping. * Returns false if the entire cart contains only quote items. * * @param bool $needs_shipping Whether cart needs shipping. * @return bool */ public function cart_needs_shipping( $needs_shipping ) { if ( ! $needs_shipping ) { return false; } // Check if this is a quote-only cart. if ( WC()->cart && ! WC()->cart->is_empty() ) { $all_quote = true; foreach ( WC()->cart->get_cart() as $cart_item ) { $product = $cart_item['data']; if ( ! $product ) { continue; } // Check if product has a price. if ( '' !== $product->get_price() ) { // Also check if product is marked as quote-only (check parent for variations). $product_id = $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id(); $quote_only = get_post_meta( $product_id, '_oc_quote_only', true ); if ( 'yes' !== $quote_only ) { $all_quote = false; break; } } } // If all items are quote items, cart doesn't need shipping. if ( $all_quote ) { return false; } } return $needs_shipping; } /** * Check if product needs shipping. * Returns false for quote-only products. * * @param bool $needs_shipping Whether product needs shipping. * @param \WC_Product $product Product object. * @return bool */ public function product_needs_shipping( $needs_shipping, $product ) { if ( ! $needs_shipping || ! $product ) { return $needs_shipping; } // Check if product has no price or is marked as quote-only (check parent for variations). if ( '' === $product->get_price() ) { return false; } $product_id = $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id(); $quote_only = get_post_meta( $product_id, '_oc_quote_only', true ); if ( 'yes' === $quote_only ) { return false; } return $needs_shipping; } /** * Maybe send admin email notification when a chat order is created. * * @param int $order_id Order ID. * @param \WC_Cart $cart Cart object (optional). * @param array $data Additional data (optional). */ public function maybe_send_admin_email( $order_id, $cart = null, $data = array() ) { // Check if admin email is enabled. if ( 'yes' !== Settings::get( 'send_admin_email', 'no' ) ) { return; } $order = wc_get_order( $order_id ); if ( ! $order ) { return; } // Avoid duplicate if WC New Order email is enabled and will trigger for this status. if ( $order->has_status( array( 'processing', 'on-hold', 'completed' ) ) ) { $mailer = WC()->mailer(); $new_order_email = isset( $mailer->emails['WC_Email_New_Order'] ) ? $mailer->emails['WC_Email_New_Order'] : null; if ( $new_order_email && $new_order_email->is_enabled() ) { return; } } // Get admin email. $admin_email = get_option( 'admin_email' ); if ( empty( $admin_email ) ) { return; } // Suppress unused parameter warnings as they are required by the hook signature. unset( $cart, $data ); // Build email subject and message. $site_name = get_bloginfo( 'name' ); $order_number = $order->get_order_number(); /* translators: 1: Site name 2: Order number */ $subject = sprintf( __( '[%1$s] New Chat Order (%2$s)', 'ordercourier' ), $site_name, $order_number ); $customer_name = trim( $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() ); if ( empty( $customer_name ) ) { $customer_name = $order->get_billing_email() ? $order->get_billing_email() : $order->get_billing_phone(); } if ( empty( $customer_name ) ) { $customer_name = __( 'Guest', 'ordercourier' ); } $order_total = html_entity_decode( wp_strip_all_tags( wc_price( $order->get_total() ) ), ENT_QUOTES | ENT_HTML5 ); $order_edit_url = esc_url_raw( $order->get_edit_order_url() ); $message = sprintf( /* translators: 1: Order number, 2: Customer name, 3: Order total, 4: Order edit link */ __( 'A new order has been placed via chat: Order #%1$s Customer: %2$s Total: %3$s View order: %4$s', 'ordercourier' ), $order_number, $customer_name, $order_total, $order_edit_url ); // Send email. wp_mail( $admin_email, $subject, $message ); /** * Action fired after admin email is sent. * * @since 1.0.0 * @param int $order_id Order ID. * @param \WC_Order $order Order object. * @param string $admin_email Admin email address. */ do_action( 'ordercourier_admin_email_sent', $order_id, $order, $admin_email ); } }