class-order-status-manager.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <?php
  2. // Handles custom order status registration and integration.
  3. defined('ABSPATH') || exit;
  4. class Order_Status_Manager {
  5. private $custom_statuses;
  6. private $print_status_slugs = array('to-print', 'in-print');
  7. public function __construct() {
  8. add_action('init', array($this, 'register_custom_order_statuses'));
  9. add_filter('wc_order_statuses', array($this, 'add_custom_order_statuses_to_list'));
  10. add_action('woocommerce_order_status_changed', array($this, 'handle_status_transitions'), 10, 3);
  11. // Earlier versions of this plugin hooked `woocommerce_payment_complete`
  12. // to force orders to `processing`. That handler was effectively dead
  13. // code on modern WC — WC_Order::payment_complete() already sets the
  14. // status to `processing` (or `completed` for downloadable-only orders)
  15. // *before* firing the action, so our handler was either a no-op
  16. // (same-state update) or a deliberate skip. Removed in 1.4.3.
  17. }
  18. private function get_custom_status_definitions() {
  19. if ($this->custom_statuses === null) {
  20. $this->custom_statuses = array(
  21. 'wc-to-print' => array(
  22. 'label' => _x('Prepare to Printing', 'Order status', 'studiou-wc-ord-print-statuses'),
  23. 'label_count' => _n_noop(
  24. 'Prepare to Printing <span class="count">(%s)</span>',
  25. 'Prepare to Printing <span class="count">(%s)</span>',
  26. 'studiou-wc-ord-print-statuses'
  27. ),
  28. ),
  29. 'wc-in-print' => array(
  30. 'label' => _x('In Printing', 'Order status', 'studiou-wc-ord-print-statuses'),
  31. 'label_count' => _n_noop(
  32. 'In Printing <span class="count">(%s)</span>',
  33. 'In Printing <span class="count">(%s)</span>',
  34. 'studiou-wc-ord-print-statuses'
  35. ),
  36. ),
  37. );
  38. }
  39. return $this->custom_statuses;
  40. }
  41. public function register_custom_order_statuses() {
  42. foreach ($this->get_custom_status_definitions() as $status_slug => $status_args) {
  43. register_post_status($status_slug, array(
  44. 'label' => $status_args['label'],
  45. 'public' => true,
  46. 'exclude_from_search' => false,
  47. 'show_in_admin_all_list' => true,
  48. 'show_in_admin_status_list' => true,
  49. 'label_count' => $status_args['label_count'],
  50. ));
  51. }
  52. }
  53. public function add_custom_order_statuses_to_list($order_statuses) {
  54. $new_order_statuses = array();
  55. $inserted = false;
  56. foreach ($order_statuses as $key => $status) {
  57. $new_order_statuses[$key] = $status;
  58. if ($key === 'wc-processing') {
  59. foreach ($this->get_custom_status_definitions() as $status_slug => $status_args) {
  60. $new_order_statuses[$status_slug] = $status_args['label'];
  61. }
  62. $inserted = true;
  63. }
  64. }
  65. // Fallback: append at the end if `wc-processing` was removed by
  66. // another plugin. Better to surface the custom statuses somewhere
  67. // in the dropdown than to drop them silently.
  68. if (!$inserted) {
  69. foreach ($this->get_custom_status_definitions() as $status_slug => $status_args) {
  70. $new_order_statuses[$status_slug] = $status_args['label'];
  71. }
  72. }
  73. return $new_order_statuses;
  74. }
  75. /**
  76. * Stamp the relevant meta key when an order transitions into a print status.
  77. * Uses the order object (HPOS-safe) rather than update_post_meta.
  78. *
  79. * Note: bulk and import paths in Studiou_DB_Manager also stamp the same
  80. * meta key explicitly. That redundancy is intentional — the bulk path
  81. * always re-stamps (a re-run should refresh the timestamp), while this
  82. * listener handles manual single-order transitions originating from the
  83. * order edit screen. The "only if empty" guard below preserves the
  84. * original timestamp for manual flows; the bulk path overwrites it via
  85. * its own explicit call.
  86. */
  87. public function handle_status_transitions($order_id, $old_status, $new_status) {
  88. UtilsLog::log('Order #' . $order_id . ' status change ' . $old_status . ' -> ' . $new_status);
  89. if (!in_array($new_status, $this->print_status_slugs, true)) {
  90. return;
  91. }
  92. $order = wc_get_order($order_id);
  93. if (!$order) {
  94. return;
  95. }
  96. $meta_key = ($new_status === 'to-print') ? 'to_print_date' : 'in_print_date';
  97. if (!$order->get_meta($meta_key)) {
  98. $order->update_meta_data($meta_key, current_time('mysql'));
  99. $order->save();
  100. }
  101. }
  102. public function get_custom_statuses() {
  103. return $this->get_custom_status_definitions();
  104. }
  105. }