has_status( self::STATUS ) ) { return; } $product = $item->get_product(); $release = $product ? Preorvo_Product::release_time( $product ) : (int) $item->get_meta( Preorvo_Product::META_RELEASE ); if ( $release <= time() ) { return; } /* translators: %s: release date */ $text = sprintf( __( 'Pre-order: ships from %s', 'preorvo' ), Preorvo_Product::format_date( $release ) ); echo $plain_text ? "\n" . esc_html( $text ) : '
' . esc_html( $text ) . ''; } public static function status_style() { wp_register_style( 'preorvo-admin', false, array(), PREORVO_VERSION ); wp_enqueue_style( 'preorvo-admin' ); wp_add_inline_style( 'preorvo-admin', '.order-status.status-' . sanitize_html_class( self::STATUS ) . '{background:#e5d4f0;color:#5b2c86}' ); } public static function register_status() { register_post_status( 'wc-' . self::STATUS, array( 'label' => _x( 'Pre-ordered', 'Order status', 'preorvo' ), 'public' => false, 'exclude_from_search' => false, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, /* translators: %s: number of orders */ 'label_count' => _n_noop( 'Pre-ordered (%s)', 'Pre-ordered (%s)', 'preorvo' ), ) ); } public static function add_status_label( $statuses ) { $result = array(); foreach ( $statuses as $key => $label ) { $result[ $key ] = $label; if ( 'wc-processing' === $key ) { $result[ 'wc-' . self::STATUS ] = _x( 'Pre-ordered', 'Order status', 'preorvo' ); } } if ( ! isset( $result[ 'wc-' . self::STATUS ] ) ) { $result[ 'wc-' . self::STATUS ] = _x( 'Pre-ordered', 'Order status', 'preorvo' ); } return $result; } public static function add_paid_status( $statuses ) { $statuses[] = self::STATUS; return $statuses; } /** * When the order may ship: the latest release date among its pre-order items, or 0 if nothing is waiting. */ public static function release_time( $order ) { if ( 'yes' === $order->get_meta( self::META_RELEASED ) ) { return 0; } $latest = 0; foreach ( $order->get_items() as $item ) { $product = $item->get_product(); if ( $product ) { $release = Preorvo_Product::release_time( $product ); } else { // Product deleted: fall back to the date frozen at checkout. $stored = (int) $item->get_meta( Preorvo_Product::META_RELEASE ); $release = $stored > time() ? $stored : 0; } $latest = max( $latest, $release ); } return $latest; } public static function payment_complete_status( $status, $order_id, $order = null ) { $order = $order ? $order : wc_get_order( $order_id ); return ( $order && self::release_time( $order ) ) ? self::STATUS : $status; } public static function guard( $order ) { $changes = $order->get_changes(); if ( ! isset( $changes['status'] ) || ! in_array( $order->get_status(), array( 'processing', 'completed' ), true ) ) { return; } $release = self::release_time( $order ); if ( ! $release ) { return; } $order->set_status( self::STATUS ); self::drop_noop_transition( $order ); // A separate note: passed to set_status() it would also get WooCommerce's "changed from X to X" line. if ( $order->get_id() ) { $order->add_order_note( sprintf( /* translators: 1: blocked status, 2: release date */ __( 'Preorvo kept this order on hold: it was set to "%1$s" before the release date (%2$s). Use "Release pre-order now" to ship it early on purpose.', 'preorvo' ), wc_get_order_status_name( $changes['status'] ), Preorvo_Product::format_date( $release ) ) ); } } /** * When the guard puts an order back where it started, WooCommerce would still log * "Order status changed from Pre-ordered to Pre-ordered". Forget that empty transition. */ private static function drop_noop_transition( $order ) { if ( ! property_exists( 'WC_Order', 'status_transition' ) ) { return; } $drop = function () { if ( is_array( $this->status_transition ) && $this->status_transition['from'] === $this->status_transition['to'] ) { $this->status_transition = false; } }; \Closure::bind( $drop, $order, 'WC_Order' )(); } public static function on_preorder_status( $order_id, $order ) { // Some gateways (cash on delivery, manual edits) never call payment_complete(), so stock is reduced here too. wc_maybe_reduce_stock_levels( $order_id ); } public static function add_release_action( $actions, $order = null ) { if ( $order && $order->has_status( self::STATUS ) ) { $actions['preorvo_release_now'] = __( 'Release pre-order now', 'preorvo' ); } return $actions; } public static function release_now( $order ) { Preorvo_Release::release( $order, __( 'Pre-order released manually.', 'preorvo' ) ); } }