class-wc-order.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. <?php
  2. class Booked_WC_Order {
  3. private static $orders = array();
  4. public $order;
  5. public $order_id;
  6. public $appointments = array();
  7. public $products;
  8. public $items = array();
  9. private function __construct( $order_id ) {
  10. $this->order_id = $order_id;
  11. $this->get_data();
  12. $this->get_items();
  13. $this->get_appointments();
  14. $this->get_status_text();
  15. }
  16. public static function get( $order_id=null ) {
  17. if ( !is_integer($order_id) ) {
  18. $message = sprintf( __('%s integer expected when %s given.', 'booked-woocommerce-payments'), 'Booked_WC_Order::get($order_id)', gettype($order_id) );
  19. throw new Exception($message);
  20. } else if ( $order_id===0 ) {
  21. self::$orders[$order_id] = false;
  22. } else if ( !isset(self::$orders[$order_id]) ) {
  23. self::$orders[$order_id] = new self($order_id);
  24. }
  25. return self::$orders[$order_id];
  26. }
  27. protected function get_data() {
  28. $order_id = absint($this->order_id);
  29. $this->order = new WC_Order($order_id);
  30. return $this;
  31. }
  32. protected function get_status_text() {
  33. $status = $this->order->get_status();
  34. $statuses = wc_get_order_statuses();
  35. $this->order->post_status_text = isset($statuses[$status]) ? $statuses[$status] : $status;
  36. return $this;
  37. }
  38. protected function get_items() {
  39. $this->items = $this->order->get_items();
  40. return $this;
  41. }
  42. protected function get_appointments() {
  43. $this->appointments = get_post_meta($this->order_id, '_' . BOOKED_WC_PLUGIN_PREFIX . 'order_appointments', true);
  44. return $this;
  45. }
  46. }
  47. class Booked_WC_Order_Hooks {
  48. // woocommerce_order_status_refunded
  49. // woocommerce_order_status_cancelled
  50. // delete appointments on refunded or cancelled
  51. public static function woocommerce_order_remove_appointment( $order_id ) {
  52. $order_id = (int) $order_id;
  53. $this_post = get_post($order_id);
  54. if (!$this_post || $this_post->post_type!=='shop_order') {
  55. return;
  56. }
  57. $order = Booked_WC_Order::get($order_id);
  58. $appointments = $order->appointments;
  59. if ( !$appointments ) {
  60. return;
  61. }
  62. $deleted = array();
  63. foreach ($appointments as $app_id) {
  64. if (!in_array($app_id, $deleted) && !get_post($app_id)) {
  65. return;
  66. }
  67. $deleted[] = $app_id;
  68. try {
  69. do_action('booked_appointment_cancelled',$app_id);
  70. wp_delete_post($app_id, true);
  71. } catch (Exception $e) {
  72. //
  73. }
  74. }
  75. }
  76. public static function woocommerce_order_complete( $order_id ) {
  77. $order_id = (int) $order_id;
  78. $this_post = get_post($order_id);
  79. if (!$this_post || $this_post->post_type!=='shop_order') {
  80. return;
  81. }
  82. $order = Booked_WC_Order::get($order_id);
  83. $appointments = $order->appointments;
  84. if ( !$appointments ) {
  85. return;
  86. }
  87. $completed = array();
  88. foreach ($appointments as $appt_id) {
  89. if (!in_array($appt_id, $completed) && !get_post($appt_id)) {
  90. return;
  91. }
  92. $completed[] = $appt_id;
  93. $send_upon_completion = Booked_WC_Functions::booked_disable_confirmation_emails();
  94. if ( $send_upon_completion ):
  95. // Add Booked WC confirmation email actions
  96. add_action( 'booked_wc_confirmation_email', 'booked_mailer', 10, 3 );
  97. add_action( 'booked_wc_admin_confirmation_email', 'booked_mailer', 10, 3 );
  98. // Send a confirmation email to the User?
  99. $email_content = get_option('booked_appt_confirmation_email_content');
  100. $email_subject = get_option('booked_appt_confirmation_email_subject');
  101. $token_replacements = booked_get_appointment_tokens( $appt_id );
  102. if ($email_content && $email_subject):
  103. $email_content = booked_token_replacement( $email_content,$token_replacements );
  104. $email_subject = booked_token_replacement( $email_subject,$token_replacements );
  105. do_action( 'booked_wc_confirmation_email', $token_replacements['email'], $email_subject, $email_content );
  106. endif;
  107. // Send an email to the Admin?
  108. $email_content = get_option('booked_admin_appointment_email_content');
  109. $email_subject = get_option('booked_admin_appointment_email_subject');
  110. if ($email_content && $email_subject):
  111. $cals = wp_get_object_terms( $appt_id, 'booked_custom_calendars' );
  112. $calendar_id = $cals[0]->term_id;
  113. $admin_email = booked_which_admin_to_send_email($calendar_id);
  114. $email_content = booked_token_replacement( $email_content,$token_replacements );
  115. $email_subject = booked_token_replacement( $email_subject,$token_replacements );
  116. do_action( 'booked_wc_admin_confirmation_email', $admin_email, $email_subject, $email_content );
  117. endif;
  118. // Remove Booked WC confirmation email actions
  119. remove_action( 'booked_wc_confirmation_email', 'booked_mailer', 10 );
  120. remove_action( 'booked_wc_admin_confirmation_email', 'booked_mailer', 10 );
  121. endif;
  122. }
  123. }
  124. // validate cart and appointment products
  125. // this is needed in case a specific appointment has two or more products and the user removes any of them in order to reduce the price
  126. public static function woocommerce_validate_order_items( $order_id ) {
  127. $cart_appointments = Booked_WC_Cart::get_cart_appointments();
  128. $appointment_ids = array();
  129. foreach ($cart_appointments['ids'] as $app_id) {
  130. $app_id = intval($app_id);
  131. if ( $app_id<=0 ) {
  132. continue;
  133. }
  134. $appointment = Booked_WC_Appointment::get($app_id);
  135. if ( !$appointment->products ) {
  136. continue;
  137. }
  138. foreach ($appointment->products as $product) {
  139. $product_id = apply_filters( 'wpml_object_id', $product->product_id, 'product', false);
  140. $variation_id = isset($product->variation_id) ? $product->variation_id : 0;
  141. $check_key = "{$app_id}::{$product_id}::{$variation_id}";
  142. if ( !in_array($check_key, $cart_appointments['extended']) ) {
  143. $message = sprintf( __('Appointment "%s" and cart products do not match. Please make sure that all appointment products are available in the cart.', 'booked-woocommerce-payments'), $appointment->timeslot_text );
  144. throw new Exception( $message );
  145. }
  146. }
  147. }
  148. // if the script above passes, link the appointments and their order
  149. foreach ($cart_appointments['ids'] as $app_id) {
  150. // link the appointment with the order
  151. update_post_meta($app_id, '_' . BOOKED_WC_PLUGIN_PREFIX . 'appointment_order_id', $order_id);
  152. }
  153. if ( $cart_appointments['ids'] ) {
  154. // link the order with all appointments appointment
  155. update_post_meta($order_id, '_' . BOOKED_WC_PLUGIN_PREFIX . 'order_appointments', $cart_appointments['ids']);
  156. }
  157. }
  158. // assign order items to their appointments in case the plugin must extend even more
  159. public static function woocommerce_add_order_item_meta($item_id, $values, $cart_item_key, $unique=false) {
  160. $prefix = BOOKED_WC_PLUGIN_PREFIX;
  161. $item_metas = array(
  162. 'appointment_id',
  163. 'appointment_cal_name',
  164. 'appointment_assignee_name',
  165. // 'appointment_timerange',
  166. );
  167. // populating main metas
  168. foreach ($item_metas as $key) {
  169. $meta_key = $prefix . $key;
  170. if ( !isset($values[$meta_key]) ) {
  171. continue;
  172. }
  173. $value = $values[$meta_key];
  174. if ( !$value ) {
  175. return;
  176. }
  177. wc_add_order_item_meta($item_id, $meta_key, $value, $unique);
  178. }
  179. if ( isset( $values[ $prefix . 'appointment_id' ] ) ){
  180. $appt_id = $values[ $prefix . 'appointment_id' ];
  181. $appointment = Booked_WC_Appointment::get( $appt_id );
  182. $custom_fields = (array) $appointment->custom_fields;
  183. $i = 0;
  184. foreach ($custom_fields as $field_label => $field_value){
  185. $meta_key = '_' . $prefix . 'cfield_' . $i;
  186. $value = str_replace( ':', '', $field_label ) . '--SEP--' . $field_value;
  187. wc_add_order_item_meta( $item_id, $meta_key, $value, $unique);
  188. $i++;
  189. }
  190. }
  191. }
  192. public static function woocommerce_hidden_order_itemmeta( $hidden_meta ) {
  193. $hidden_meta[] = BOOKED_WC_PLUGIN_PREFIX . 'appointment_timerange';
  194. return $hidden_meta;
  195. }
  196. public static function woocommerce_order_items_meta_display($output, $order_item_meta_obj) {
  197. // preg_match_all('~<dt.+class="([^"]+)".*Form Field:</dt>~im', $output, $matches);
  198. // wrap labels in strong
  199. $output = preg_replace('~(cfield_\d+.+<p>)([^:]+:)(.+)(</p>)~im', '$1<small><strong>$2</strong>$3</small>$4', $output);
  200. // replace the form field text
  201. return preg_replace('~(<dt.+class="[^"]+".*)Form Field:(</dt>)~im', '$1$2', $output);
  202. }
  203. }