custom_statuses === null) { $this->custom_statuses = array( 'wc-to-print' => array( 'label' => _x('Prepare to Printing', 'Order status', 'studiou-wc-ord-print-statuses'), 'label_count' => _n_noop( 'Prepare to Printing (%s)', 'Prepare to Printing (%s)', 'studiou-wc-ord-print-statuses' ), ), 'wc-in-print' => array( 'label' => _x('In Printing', 'Order status', 'studiou-wc-ord-print-statuses'), 'label_count' => _n_noop( 'In Printing (%s)', 'In Printing (%s)', 'studiou-wc-ord-print-statuses' ), ), ); } return $this->custom_statuses; } public function register_custom_order_statuses() { foreach ($this->get_custom_status_definitions() as $status_slug => $status_args) { register_post_status($status_slug, array( 'label' => $status_args['label'], 'public' => true, 'exclude_from_search' => false, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, 'label_count' => $status_args['label_count'], )); } } public function add_custom_order_statuses_to_list($order_statuses) { $new_order_statuses = array(); $inserted = false; foreach ($order_statuses as $key => $status) { $new_order_statuses[$key] = $status; if ($key === 'wc-processing') { foreach ($this->get_custom_status_definitions() as $status_slug => $status_args) { $new_order_statuses[$status_slug] = $status_args['label']; } $inserted = true; } } // Fallback: append at the end if `wc-processing` was removed by // another plugin. Better to surface the custom statuses somewhere // in the dropdown than to drop them silently. if (!$inserted) { foreach ($this->get_custom_status_definitions() as $status_slug => $status_args) { $new_order_statuses[$status_slug] = $status_args['label']; } } return $new_order_statuses; } /** * Stamp the relevant meta key when an order transitions into a print status. * Uses the order object (HPOS-safe) rather than update_post_meta. * * Note: bulk and import paths in Studiou_DB_Manager also stamp the same * meta key explicitly. That redundancy is intentional — the bulk path * always re-stamps (a re-run should refresh the timestamp), while this * listener handles manual single-order transitions originating from the * order edit screen. The "only if empty" guard below preserves the * original timestamp for manual flows; the bulk path overwrites it via * its own explicit call. */ public function handle_status_transitions($order_id, $old_status, $new_status) { UtilsLog::log('Order #' . $order_id . ' status change ' . $old_status . ' -> ' . $new_status); if (!in_array($new_status, $this->print_status_slugs, true)) { return; } $order = wc_get_order($order_id); if (!$order) { return; } $meta_key = ($new_status === 'to-print') ? 'to_print_date' : 'in_print_date'; if (!$order->get_meta($meta_key)) { $order->update_meta_data($meta_key, current_time('mysql')); $order->save(); } } public function get_custom_statuses() { return $this->get_custom_status_definitions(); } }