WCML_Bookings

Class WCML_Bookings.

Defined (1)

The class is defined in the following location(s).

/compatibility/class-wcml-bookings.php  
  1. class WCML_Bookings { 
  2.  
  3. /** 
  4. * @var WPML_Element_Translation_Package 
  5. */ 
  6. public $tp; 
  7.  
  8. /** 
  9. * @var SitePress 
  10. */ 
  11. public $sitepress; 
  12.  
  13. /** 
  14. * @var woocommerce_wpml 
  15. */ 
  16. public $woocommerce_wpml; 
  17.  
  18. /** 
  19. * @var wpdb 
  20. */ 
  21. public $wpdb; 
  22.  
  23. /** 
  24. * WCML_Bookings constructor. 
  25. */ 
  26. function __construct( &$sitepress, &$woocommerce_wpml, &$wpdb ) { 
  27. $this->sitepress = $sitepress; 
  28. $this->woocommerce_wpml = $woocommerce_wpml; 
  29. $this->wpdb = $wpdb; 
  30. add_action( 'woocommerce_bookings_after_booking_base_cost', array( 
  31. $this,  
  32. 'wcml_price_field_after_booking_base_cost' 
  33. ) ); 
  34. add_action( 'woocommerce_bookings_after_booking_block_cost', array( 
  35. $this,  
  36. 'wcml_price_field_after_booking_block_cost' 
  37. ) ); 
  38. add_action( 'woocommerce_bookings_after_display_cost', array( $this, 'wcml_price_field_after_display_cost' ) ); 
  39. add_action( 'woocommerce_bookings_after_booking_pricing_base_cost', array( 
  40. $this,  
  41. 'wcml_price_field_after_booking_pricing_base_cost' 
  42. ), 10, 2 ); 
  43. add_action( 'woocommerce_bookings_after_booking_pricing_cost', array( 
  44. $this,  
  45. 'wcml_price_field_after_booking_pricing_cost' 
  46. ), 10, 2 ); 
  47. add_action( 'woocommerce_bookings_after_person_cost', array( $this, 'wcml_price_field_after_person_cost' ) ); 
  48. add_action( 'woocommerce_bookings_after_person_block_cost', array( 
  49. $this,  
  50. 'wcml_price_field_after_person_block_cost' 
  51. ) ); 
  52. add_action( 'woocommerce_bookings_after_resource_cost', array( 
  53. $this,  
  54. 'wcml_price_field_after_resource_cost' 
  55. ), 10, 2 ); 
  56. add_action( 'woocommerce_bookings_after_resource_block_cost', array( 
  57. $this,  
  58. 'wcml_price_field_after_resource_block_cost' 
  59. ), 10, 2 ); 
  60. add_action( 'woocommerce_bookings_after_bookings_pricing', array( $this, 'after_bookings_pricing' ) ); 
  61.  
  62. add_action( 'init', array( $this, 'load_assets' ) ); 
  63.  
  64. add_action( 'save_post', array( $this, 'save_custom_costs' ), 110, 1 ); 
  65. add_action( 'wcml_before_sync_product_data', array( $this, 'sync_bookings' ), 10, 3 ); 
  66. add_action( 'wcml_before_sync_product', array( $this, 'sync_booking_data' ), 10, 2 ); 
  67.  
  68. add_filter( 'woocommerce_bookings_process_cost_rules_cost', array( 
  69. $this,  
  70. 'wc_bookings_process_cost_rules_cost' 
  71. ), 10, 3 ); 
  72. add_filter( 'woocommerce_bookings_process_cost_rules_base_cost', array( 
  73. $this,  
  74. 'wc_bookings_process_cost_rules_base_cost' 
  75. ), 10, 3 ); 
  76. add_filter( 'woocommerce_bookings_process_cost_rules_override_block', array( 
  77. $this,  
  78. 'wc_bookings_process_cost_rules_override_block_cost' 
  79. ), 10, 3 ); 
  80.  
  81. add_filter( 'wcml_multi_currency_ajax_actions', array( $this, 'wcml_multi_currency_is_ajax' ) ); 
  82.  
  83. add_filter( 'wcml_cart_contents_not_changed', array( 
  84. $this,  
  85. 'filter_bundled_product_in_cart_contents' 
  86. ), 10, 3 ); 
  87.  
  88. add_action( 'woocommerce_bookings_after_create_booking_page', array( $this, 'booking_currency_dropdown' ) ); 
  89. add_action( 'init', array( $this, 'set_booking_currency' ) ); 
  90.  
  91. add_action( 'wp_ajax_wcml_booking_set_currency', array( $this, 'set_booking_currency_ajax' ) ); 
  92. add_action( 'woocommerce_bookings_create_booking_page_add_order_item', array( 
  93. $this,  
  94. 'set_order_currency_on_create_booking_page' 
  95. ) ); 
  96. add_filter( 'woocommerce_currency_symbol', array( $this, 'filter_booking_currency_symbol' ) ); 
  97. add_filter( 'get_booking_products_args', array( $this, 'filter_get_booking_products_args' ) ); 
  98. add_filter( 'wcml_filter_currency_position', array( $this, 'create_booking_page_client_currency' ) ); 
  99.  
  100. add_filter( 'wcml_client_currency', array( $this, 'create_booking_page_client_currency' ) ); 
  101.  
  102. add_action( 'wcml_gui_additional_box_html', array( $this, 'custom_box_html' ), 10, 3 ); 
  103. add_filter( 'wcml_gui_additional_box_data', array( $this, 'custom_box_html_data' ), 10, 4 ); 
  104. add_filter( 'wcml_check_is_single', array( $this, 'show_custom_blocks_for_resources_and_persons' ), 10, 3 ); 
  105. add_filter( 'wcml_product_content_exception', array( $this, 'remove_custom_fields_to_translate' ), 10, 3 ); 
  106. add_filter( 'wcml_not_display_single_fields_to_translate', array( 
  107. $this,  
  108. 'remove_single_custom_fields_to_translate' 
  109. ) ); 
  110. add_filter( 'wcml_product_content_label', array( $this, 'product_content_resource_label' ), 10, 2 ); 
  111. add_action( 'wcml_update_extra_fields', array( $this, 'wcml_products_tab_sync_resources_and_persons' ), 10, 4 ); 
  112.  
  113. add_action( 'woocommerce_new_booking', array( $this, 'duplicate_booking_for_translations' ) ); 
  114.  
  115. $bookings_statuses = array( 
  116. 'unpaid',  
  117. 'pending-confirmation',  
  118. 'confirmed',  
  119. 'paid',  
  120. 'cancelled',  
  121. 'complete',  
  122. 'in-cart',  
  123. 'was-in-cart' 
  124. ); 
  125. foreach ( $bookings_statuses as $status ) { 
  126. add_action( 'woocommerce_booking_' . $status, array( $this, 'update_status_for_translations' ) ); 
  127.  
  128. add_filter( 'parse_query', array( $this, 'booking_filters_query' ) ); 
  129. add_filter( 'woocommerce_bookings_in_date_range_query', array( $this, 'bookings_in_date_range_query' ) ); 
  130. add_action( 'before_delete_post', array( $this, 'delete_bookings' ) ); 
  131. add_action( 'wp_trash_post', array( $this, 'trash_bookings' ) ); 
  132.  
  133. if ( is_admin() ) { 
  134.  
  135. $this->tp = new WPML_Element_Translation_Package; 
  136.  
  137. add_filter( 'wpml_tm_translation_job_data', array( 
  138. $this,  
  139. 'append_persons_to_translation_package' 
  140. ), 10, 2 ); 
  141. add_action( 'wpml_translation_job_saved', array( $this, 'save_person_translation' ), 10, 3 ); 
  142.  
  143. add_filter( 'wpml_tm_translation_job_data', array( 
  144. $this,  
  145. 'append_resources_to_translation_package' 
  146. ), 10, 2 ); 
  147. add_action( 'wpml_translation_job_saved', array( $this, 'save_resource_translation' ), 10, 3 ); 
  148.  
  149. //lock fields on translations pages 
  150. add_filter( 'wcml_js_lock_fields_ids', array( $this, 'wcml_js_lock_fields_ids' ) ); 
  151. add_filter( 'wcml_after_load_lock_fields_js', array( $this, 'localize_lock_fields_js' ) ); 
  152.  
  153. //allow filtering resources by language 
  154. add_filter( 'get_booking_resources_args', array( $this, 'filter_get_booking_resources_args' ) ); 
  155. add_filter( 'get_translatable_documents', array( $this, 'filter_translatable_documents' ) ); 
  156. add_filter( 'pre_wpml_is_translated_post_type', array( $this, 'filter_is_translated_post_type' ) ); 
  157.  
  158. add_action( 'woocommerce_product_data_panels', array( $this, 'show_pointer_info' ) ); 
  159.  
  160. add_action( 'save_post', array( $this, 'sync_booking_status' ), 10, 3 ); 
  161.  
  162. if ( ! is_admin() || isset( $_POST['action'] ) && $_POST['action'] == 'wc_bookings_calculate_costs' ) { 
  163. add_filter( 'get_post_metadata', array( $this, 'filter_wc_booking_cost' ), 10, 4 ); 
  164.  
  165. //@TODO review after WPML 3.6 
  166. if ( version_compare( ICL_SITEPRESS_VERSION, '3.6', '<' ) ) { 
  167. add_action( 'added_post_meta', array( 
  168. $this,  
  169. 'maybe_fix_double_serialized_wc_booking_availability' 
  170. ), 10, 4 ); 
  171.  
  172. add_filter( 'wpml_language_filter_extra_conditions_snippet', array( $this, 'extra_conditions_to_filter_bookings' ) ); 
  173.  
  174. $this->clear_transient_fields(); 
  175.  
  176. add_filter( 'wpml_tm_dashboard_translatable_types', array( $this, 'hide_bookings_type_on_tm_dashboard' ) ); 
  177.  
  178. add_filter( 'wcml_add_to_cart_sold_individually', array( $this, 'add_to_cart_sold_individually' ), 10, 4 ); 
  179.  
  180.  
  181. function wcml_price_field_after_booking_base_cost( $post_id ) { 
  182.  
  183. $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_cost' ); 
  184.  
  185.  
  186. function wcml_price_field_after_booking_block_cost( $post_id ) { 
  187.  
  188. $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_base_cost' ); 
  189.  
  190.  
  191. function wcml_price_field_after_display_cost( $post_id ) { 
  192.  
  193. $this->echo_wcml_price_field( $post_id, 'wcml_wc_display_cost' ); 
  194.  
  195.  
  196. function wcml_price_field_after_booking_pricing_base_cost( $pricing, $post_id ) { 
  197.  
  198. $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_pricing_base_cost', $pricing ); 
  199.  
  200.  
  201. function wcml_price_field_after_booking_pricing_cost( $pricing, $post_id ) { 
  202.  
  203. $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_pricing_cost', $pricing ); 
  204.  
  205.  
  206. function wcml_price_field_after_person_cost( $person_type_id ) { 
  207.  
  208. $this->echo_wcml_price_field( $person_type_id, 'wcml_wc_booking_person_cost', false, false ); 
  209.  
  210.  
  211. function wcml_price_field_after_person_block_cost( $person_type_id ) { 
  212.  
  213. $this->echo_wcml_price_field( $person_type_id, 'wcml_wc_booking_person_block_cost', false, false ); 
  214.  
  215.  
  216. function wcml_price_field_after_resource_cost( $resource_id, $post_id ) { 
  217.  
  218. $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_resource_cost', false, true, $resource_id ); 
  219.  
  220.  
  221. function wcml_price_field_after_resource_block_cost( $resource_id, $post_id ) { 
  222.  
  223. $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_resource_block_cost', false, true, $resource_id ); 
  224.  
  225.  
  226. function echo_wcml_price_field( $post_id, $field, $pricing = false, $check = true, $resource_id = false ) { 
  227.  
  228.  
  229. if ( ( ! $check || $this->woocommerce_wpml->products->is_original_product( $post_id ) ) && $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) { 
  230.  
  231. $currencies = $this->woocommerce_wpml->multi_currency->get_currencies(); 
  232.  
  233. $wc_currencies = get_woocommerce_currencies(); 
  234.  
  235. echo '<div class="wcml_custom_cost_field" >'; 
  236.  
  237. foreach ( $currencies as $currency_code => $currency ) { 
  238.  
  239. switch ( $field ) { 
  240. case 'wcml_wc_booking_cost': 
  241. woocommerce_wp_text_input( array( 
  242. 'id' => 'wcml_wc_booking_cost',  
  243. 'class' => 'wcml_bookings_custom_price',  
  244. 'name' => 'wcml_wc_booking_cost[' . $currency_code . ']',  
  245. 'label' => get_woocommerce_currency_symbol( $currency_code ),  
  246. 'description' => __( 'One-off cost for the booking as a whole.', 'woocommerce-bookings' ),  
  247. 'value' => get_post_meta( $post_id, '_wc_booking_cost_' . $currency_code, true ),  
  248. 'type' => 'number',  
  249. 'desc_tip' => true,  
  250. 'custom_attributes' => array( 
  251. 'min' => '',  
  252. 'step' => '0.01' 
  253. ) ); 
  254. break; 
  255. case 'wcml_wc_booking_base_cost': 
  256. woocommerce_wp_text_input( array( 
  257. 'id' => 'wcml_wc_booking_base_cost',  
  258. 'class' => 'wcml_bookings_custom_price',  
  259. 'name' => 'wcml_wc_booking_base_cost[' . $currency_code . ']',  
  260. 'label' => get_woocommerce_currency_symbol( $currency_code ),  
  261. 'description' => __( 'This is the cost per block booked. All other costs (for resources and persons) are added to this.', 'woocommerce-bookings' ),  
  262. 'value' => get_post_meta( $post_id, '_wc_booking_base_cost_' . $currency_code, true ),  
  263. 'type' => 'number',  
  264. 'desc_tip' => true,  
  265. 'custom_attributes' => array( 
  266. 'min' => '',  
  267. 'step' => '0.01' 
  268. ) ); 
  269. break; 
  270. case 'wcml_wc_display_cost': 
  271. woocommerce_wp_text_input( array( 
  272. 'id' => 'wcml_wc_display_cost',  
  273. 'class' => 'wcml_bookings_custom_price',  
  274. 'name' => 'wcml_wc_display_cost[' . $currency_code . ']',  
  275. 'label' => get_woocommerce_currency_symbol( $currency_code ),  
  276. 'description' => __( 'The cost is displayed to the user on the frontend. Leave blank to have it calculated for you. If a booking has varying costs, this will be prefixed with the word "from:".', 'woocommerce-bookings' ),  
  277. 'value' => get_post_meta( $post_id, '_wc_display_cost_' . $currency_code, true ),  
  278. 'type' => 'number',  
  279. 'desc_tip' => true,  
  280. 'custom_attributes' => array( 
  281. 'min' => '',  
  282. 'step' => '0.01' 
  283. ) ); 
  284. break; 
  285.  
  286. case 'wcml_wc_booking_pricing_base_cost': 
  287.  
  288. if ( isset( $pricing[ 'base_cost_' . $currency_code ] ) ) { 
  289. $value = $pricing[ 'base_cost_' . $currency_code ]; 
  290. } else { 
  291. $value = ''; 
  292.  
  293. echo '<div class="wcml_bookings_range_block" >'; 
  294. echo '<label>' . get_woocommerce_currency_symbol( $currency_code ) . '</label>'; 
  295. echo '<input type="number" step="0.01" name="wcml_wc_booking_pricing_base_cost[' . $currency_code . '][]" class="wcml_bookings_custom_price" value="' . $value . '" placeholder="0" />'; 
  296. echo '</div>'; 
  297. break; 
  298.  
  299. case 'wcml_wc_booking_pricing_cost': 
  300.  
  301. if ( isset( $pricing[ 'cost_' . $currency_code ] ) ) { 
  302. $value = $pricing[ 'cost_' . $currency_code ]; 
  303. } else { 
  304. $value = ''; 
  305.  
  306. echo '<div class="wcml_bookings_range_block" >'; 
  307. echo '<label>' . get_woocommerce_currency_symbol( $currency_code ) . '</label>'; 
  308. echo '<input type="number" step="0.01" name="wcml_wc_booking_pricing_cost[' . $currency_code . '][]" class="wcml_bookings_custom_price" value="' . $value . '" placeholder="0" />'; 
  309. echo '</div>'; 
  310. break; 
  311.  
  312. case 'wcml_wc_booking_person_cost': 
  313.  
  314. $value = get_post_meta( $post_id, 'cost_' . $currency_code, true ); 
  315.  
  316. echo '<div class="wcml_bookings_person_block" >'; 
  317. echo '<label>' . get_woocommerce_currency_symbol( $currency_code ) . '</label>'; 
  318. echo '<input type="number" step="0.01" name="wcml_wc_booking_person_cost[' . $post_id . '][' . $currency_code . ']" class="wcml_bookings_custom_price" value="' . $value . '" placeholder="0" />'; 
  319. echo '</div>'; 
  320. break; 
  321.  
  322. case 'wcml_wc_booking_person_block_cost': 
  323.  
  324. $value = get_post_meta( $post_id, 'block_cost_' . $currency_code, true ); 
  325.  
  326. echo '<div class="wcml_bookings_person_block" >'; 
  327. echo '<label>' . get_woocommerce_currency_symbol( $currency_code ) . '</label>'; 
  328. echo '<input type="number" step="0.01" name="wcml_wc_booking_person_block_cost[' . $post_id . '][' . $currency_code . ']" class="wcml_bookings_custom_price" value="' . $value . '" placeholder="0" />'; 
  329. echo '</div>'; 
  330. break; 
  331.  
  332. case 'wcml_wc_booking_resource_cost': 
  333.  
  334. $resource_base_costs = maybe_unserialize( get_post_meta( $post_id, '_resource_base_costs', true ) ); 
  335.  
  336. if ( isset( $resource_base_costs['custom_costs'][ $currency_code ][ $resource_id ] ) ) { 
  337. $value = $resource_base_costs['custom_costs'][ $currency_code ][ $resource_id ]; 
  338. } else { 
  339. $value = ''; 
  340.  
  341. echo '<div class="wcml_bookings_resource_block" >'; 
  342. echo '<label>' . get_woocommerce_currency_symbol( $currency_code ) . '</label>'; 
  343. echo '<input type="number" step="0.01" name="wcml_wc_booking_resource_cost[' . $resource_id . '][' . $currency_code . ']" class="wcml_bookings_custom_price" value="' . $value . '" placeholder="0" />'; 
  344. echo '</div>'; 
  345. break; 
  346.  
  347. case 'wcml_wc_booking_resource_block_cost': 
  348.  
  349. $resource_block_costs = maybe_unserialize( get_post_meta( $post_id, '_resource_block_costs', true ) ); 
  350.  
  351. if ( isset( $resource_block_costs['custom_costs'][ $currency_code ][ $resource_id ] ) ) { 
  352. $value = $resource_block_costs['custom_costs'][ $currency_code ][ $resource_id ]; 
  353. } else { 
  354. $value = ''; 
  355.  
  356. echo '<div class="wcml_bookings_resource_block" >'; 
  357. echo '<label>' . get_woocommerce_currency_symbol( $currency_code ) . '</label>'; 
  358. echo '<input type="number" step="0.01" name="wcml_wc_booking_resource_block_cost[' . $resource_id . '][' . $currency_code . ']" class="wcml_bookings_custom_price" value="' . $value . '" placeholder="0" />'; 
  359. echo '</div>'; 
  360. break; 
  361.  
  362. default: 
  363. break; 
  364.  
  365.  
  366.  
  367. echo '</div>'; 
  368.  
  369.  
  370. function after_bookings_pricing( $post_id ) { 
  371.  
  372.  
  373. if ( in_array( 'booking', wp_get_post_terms( $post_id, 'product_type', array( "fields" => "names" ) ) ) && $this->woocommerce_wpml->products->is_original_product( $post_id ) && $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) { 
  374.  
  375. $custom_costs_status = get_post_meta( $post_id, '_wcml_custom_costs_status', true ); 
  376.  
  377. $checked = ! $custom_costs_status ? 'checked="checked"' : ' '; 
  378.  
  379. echo '<div class="wcml_custom_costs">'; 
  380.  
  381. echo '<input type="radio" name="_wcml_custom_costs" id="wcml_custom_costs_auto" value="0" class="wcml_custom_costs_input" ' . $checked . ' />'; 
  382. echo '<label for="wcml_custom_costs_auto">' . __( 'Calculate costs in other currencies automatically', 'woocommerce-multilingual' ) . '</label>'; 
  383.  
  384. $checked = $custom_costs_status == 1 ? 'checked="checked"' : ' '; 
  385.  
  386. echo '<input type="radio" name="_wcml_custom_costs" value="1" id="wcml_custom_costs_manually" class="wcml_custom_costs_input" ' . $checked . ' />'; 
  387. echo '<label for="wcml_custom_costs_manually">' . __( 'Set costs in other currencies manually', 'woocommerce-multilingual' ) . '</label>'; 
  388.  
  389. wp_nonce_field( 'wcml_save_custom_costs', '_wcml_custom_costs_nonce' ); 
  390.  
  391. echo '</div>'; 
  392.  
  393.  
  394. function save_custom_costs( $post_id ) { 
  395. $nonce = filter_var( isset( $_POST['_wcml_custom_costs_nonce'] ) ? $_POST['_wcml_custom_costs_nonce'] : '', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); 
  396.  
  397. if ( isset( $_POST['_wcml_custom_costs'] ) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_costs' ) ) { 
  398.  
  399. update_post_meta( $post_id, '_wcml_custom_costs_status', $_POST['_wcml_custom_costs'] ); 
  400.  
  401. if ( 1 === (int) $_POST['_wcml_custom_costs'] ) { 
  402.  
  403. $currencies = $this->woocommerce_wpml->multi_currency->get_currencies(); 
  404. if ( empty( $currencies ) || 0 === $post_id ) { 
  405. return false; 
  406.  
  407. $this->update_booking_costs( $currencies, $post_id ); 
  408. $this->update_booking_pricing( $currencies, $post_id ); 
  409.  
  410.  
  411. if ( isset( $_POST['wcml_wc_booking_person_cost'] ) && is_array( $_POST['wcml_wc_booking_person_cost'] ) ) { 
  412. $this->update_booking_person_cost( $currencies, $_POST['wcml_wc_booking_person_cost'] ); 
  413.  
  414. if ( isset( $_POST['wcml_wc_booking_person_block_cost'] ) && is_array( $_POST['wcml_wc_booking_person_block_cost'] ) ) { 
  415. $this->update_booking_person_block_cost( $currencies, $_POST['wcml_wc_booking_person_block_cost'] ); 
  416.  
  417. if ( isset( $_POST['wcml_wc_booking_resource_cost'] ) && is_array( $_POST['wcml_wc_booking_resource_cost'] ) ) { 
  418. $this->update_booking_resource_cost( $currencies, $post_id, $_POST['wcml_wc_booking_resource_cost'] ); 
  419.  
  420. if ( isset( $_POST['wcml_wc_booking_resource_block_cost'] ) && is_array( $_POST['wcml_wc_booking_resource_block_cost'] ) ) { 
  421. $this->update_booking_resource_block_cost( $currencies, $post_id, $_POST['wcml_wc_booking_resource_block_cost'] ); 
  422.  
  423. update_post_meta( $post_id, '_price', '' ); 
  424. } else { 
  425. return false; 
  426.  
  427.  
  428. // sync existing product bookings for translations 
  429. function sync_bookings( $original_product_id, $product_id, $lang ) { 
  430. $all_bookings_for_product = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT post_id as id FROM {$this->wpdb->postmeta} WHERE meta_key = '_booking_product_id' AND meta_value = %d", $original_product_id ) ); 
  431.  
  432. foreach ( $all_bookings_for_product as $booking ) { 
  433. $check_if_exists = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT pm3.* FROM {$this->wpdb->postmeta} AS pm1 
  434. LEFT JOIN {$this->wpdb->postmeta} AS pm2 ON pm1.post_id = pm2.post_id 
  435. LEFT JOIN {$this->wpdb->postmeta} AS pm3 ON pm1.post_id = pm3.post_id 
  436. WHERE pm1.meta_key = '_booking_duplicate_of' AND pm1.meta_value = %s AND pm2.meta_key = '_language_code' AND pm2.meta_value = %s AND pm3.meta_key = '_booking_product_id'" 
  437. , $booking->id, $lang ) ); 
  438.  
  439. if ( is_null( $check_if_exists ) ) { 
  440. $this->duplicate_booking_for_translations( $booking->id, $lang ); 
  441. } elseif ( '' === $check_if_exists->meta_value ) { 
  442. update_post_meta( $check_if_exists->post_id, '_booking_product_id', $this->get_translated_booking_product_id( $booking->id, $lang ) ); 
  443. update_post_meta( $check_if_exists->post_id, '_booking_resource_id', $this->get_translated_booking_resource_id( $booking->id, $lang ) ); 
  444. update_post_meta( $check_if_exists->post_id, '_booking_persons', $this->get_translated_booking_persons_ids( $booking->id, $lang ) ); 
  445.  
  446. function sync_booking_data( $original_product_id, $current_product_id ) { 
  447.  
  448. if ( has_term( 'booking', 'product_type', $original_product_id ) ) { 
  449. global $pagenow, $iclTranslationManagement; 
  450.  
  451. // get language code 
  452. $language_details = $this->sitepress->get_element_language_details( $original_product_id, 'post_product' ); 
  453. if ( $pagenow == 'admin.php' && empty( $language_details ) ) { 
  454. //translation editor support: sidestep icl_translations_cache 
  455. $language_details = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT element_id, trid, language_code, source_language_code FROM {$this->wpdb->prefix}icl_translations WHERE element_id = %d AND element_type = 'post_product'", $original_product_id ) ); 
  456. if ( empty( $language_details ) ) { 
  457. return; 
  458.  
  459. // pick posts to sync 
  460. $posts = array(); 
  461. $translations = $this->sitepress->get_element_translations( $language_details->trid, 'post_product' ); 
  462. foreach ( $translations as $translation ) { 
  463.  
  464. if ( ! $translation->original ) { 
  465. $posts[ $translation->element_id ] = $translation; 
  466.  
  467. foreach ( $posts as $post_id => $translation ) { 
  468.  
  469. $trn_lang = $this->sitepress->get_language_for_element( $post_id, 'post_product' ); 
  470.  
  471. //sync_resources 
  472. $this->sync_resources( $original_product_id, $post_id, $trn_lang ); 
  473.  
  474. //sync_persons 
  475. $this->sync_persons( $original_product_id, $post_id, $trn_lang ); 
  476.  
  477.  
  478.  
  479. function sync_resources( $original_product_id, $translated_product_id, $lang_code, $duplicate = true ) { 
  480.  
  481. $original_resources = $this->wpdb->get_results( $this->wpdb->prepare( 
  482. "SELECT resource_id, sort_order FROM {$this->wpdb->prefix}wc_booking_relationships WHERE product_id = %d",  
  483. $original_product_id ) ); 
  484.  
  485. $translated_resources = $this->wpdb->get_col( $this->wpdb->prepare( 
  486. "SELECT resource_id FROM {$this->wpdb->prefix}wc_booking_relationships WHERE product_id = %d",  
  487. $translated_product_id ) ); 
  488.  
  489. $used_translated_resources = array(); 
  490.  
  491. foreach ( $original_resources as $resource ) { 
  492.  
  493. $translated_resource_id = apply_filters( 'translate_object_id', $resource->resource_id, 'bookable_resource', false, $lang_code ); 
  494. if ( ! is_null( $translated_resource_id ) ) { 
  495.  
  496. if ( in_array( $translated_resource_id, $translated_resources ) ) { 
  497. $this->update_product_resource( $translated_product_id, $translated_resource_id, $resource ); 
  498. } else { 
  499. $this->add_product_resource( $translated_product_id, $translated_resource_id, $resource ); 
  500. $used_translated_resources[] = $translated_resource_id; 
  501. } else { 
  502. if ( $duplicate ) { 
  503. $this->duplicate_resource( $translated_product_id, $resource, $lang_code ); 
  504.  
  505.  
  506. $removed_translated_resources_id = array_diff( $translated_resources, $used_translated_resources ); 
  507. foreach ( $removed_translated_resources_id as $resource_id ) { 
  508. $this->remove_resource_from_product( $translated_product_id, $resource_id ); 
  509.  
  510. $this->sync_resource_costs( $original_product_id, $translated_product_id, '_resource_base_costs', $lang_code ); 
  511. $this->sync_resource_costs( $original_product_id, $translated_product_id, '_resource_block_costs', $lang_code ); 
  512.  
  513.  
  514. function duplicate_resource( $tr_product_id, $resource, $lang_code ) { 
  515. global $iclTranslationManagement; 
  516.  
  517. if ( method_exists( $this->sitepress, 'make_duplicate' ) ) { 
  518.  
  519. $trns_resource_id = $this->sitepress->make_duplicate( $resource->resource_id, $lang_code ); 
  520.  
  521. } else { 
  522.  
  523. if ( ! isset( $iclTranslationManagement ) ) { 
  524. $iclTranslationManagement = new TranslationManagement; 
  525.  
  526. $trns_resource_id = $iclTranslationManagement->make_duplicate( $resource->resource_id, $lang_code ); 
  527.  
  528.  
  529. $this->wpdb->insert( 
  530. $this->wpdb->prefix . 'wc_booking_relationships',  
  531. array( 
  532. 'product_id' => $tr_product_id,  
  533. 'resource_id' => $trns_resource_id,  
  534. 'sort_order' => $resource->sort_order 
  535. ); 
  536.  
  537. delete_post_meta( $trns_resource_id, '_icl_lang_duplicate_of' ); 
  538.  
  539. return $trns_resource_id; 
  540.  
  541. public function add_product_resource( $product_id, $resource_id, $resource_data ) { 
  542.  
  543. $this->wpdb->insert( 
  544. $this->wpdb->prefix . 'wc_booking_relationships',  
  545. array( 
  546. 'sort_order' => $resource_data->sort_order,  
  547. 'product_id' => $product_id,  
  548. 'resource_id' => $resource_id 
  549. ); 
  550.  
  551. update_post_meta( $resource_id, 'qty', get_post_meta( $resource_data->resource_id, 'qty', true ) ); 
  552. update_post_meta( $resource_id, '_wc_booking_availability', get_post_meta( $resource_data->resource_id, '_wc_booking_availability', true ) ); 
  553.  
  554.  
  555. public function remove_resource_from_product( $product_id, $resource_id ) { 
  556.  
  557. $this->wpdb->delete( 
  558. $this->wpdb->prefix . 'wc_booking_relationships',  
  559. array( 
  560. 'product_id' => $product_id,  
  561. 'resource_id' => $resource_id 
  562. ); 
  563.  
  564.  
  565. public function update_product_resource( $product_id, $resource_id, $resource_data ) { 
  566.  
  567. $this->wpdb->update( 
  568. $this->wpdb->prefix . 'wc_booking_relationships',  
  569. array( 
  570. 'sort_order' => $resource_data->sort_order 
  571. ),  
  572. array( 
  573. 'product_id' => $product_id,  
  574. 'resource_id' => $resource_id 
  575. ); 
  576.  
  577. update_post_meta( $resource_id, 'qty', get_post_meta( $resource_data->resource_id, 'qty', true ) ); 
  578. update_post_meta( $resource_id, '_wc_booking_availability', get_post_meta( $resource_data->resource_id, '_wc_booking_availability', true ) ); 
  579.  
  580.  
  581.  
  582. function sync_persons( $original_product_id, $tr_product_id, $lang_code, $duplicate = true ) { 
  583. $orig_persons = $this->wpdb->get_col( $this->wpdb->prepare( "SELECT ID FROM {$this->wpdb->posts} WHERE post_parent = %d AND post_type = 'bookable_person'", $original_product_id ) ); 
  584.  
  585. $trnsl_persons = $this->wpdb->get_col( $this->wpdb->prepare( "SELECT ID FROM {$this->wpdb->posts} WHERE post_parent = %d AND post_type = 'bookable_person'", $tr_product_id ) ); 
  586.  
  587.  
  588. foreach ( $orig_persons as $person ) { 
  589.  
  590. $trnsl_person_id = apply_filters( 'translate_object_id', $person, 'bookable_person', false, $lang_code ); 
  591.  
  592. if ( ! is_null( $trnsl_person_id ) && in_array( $trnsl_person_id, $trnsl_persons ) ) { 
  593.  
  594. if ( ( $key = array_search( $trnsl_person_id, $trnsl_persons ) ) !== false ) { 
  595.  
  596. unset( $trnsl_persons[ $key ] ); 
  597.  
  598. update_post_meta( $trnsl_person_id, 'block_cost', get_post_meta( $person, 'block_cost', true ) ); 
  599. update_post_meta( $trnsl_person_id, 'cost', get_post_meta( $person, 'cost', true ) ); 
  600. update_post_meta( $trnsl_person_id, 'max', get_post_meta( $person, 'max', true ) ); 
  601. update_post_meta( $trnsl_person_id, 'min', get_post_meta( $person, 'min', true ) ); 
  602.  
  603.  
  604. if ( get_post_meta( $person, '_wcml_custom_costs_status', true ) && $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) { 
  605. $currencies = $this->woocommerce_wpml->multi_currency->get_currencies(); 
  606.  
  607. foreach ( $currencies as $code => $currency ) { 
  608.  
  609. update_post_meta( $trnsl_person_id, 'block_cost_' . $code, get_post_meta( $person, 'block_cost_' . $code, true ) ); 
  610. update_post_meta( $trnsl_person_id, 'cost_' . $code, get_post_meta( $person, 'cost_' . $code, true ) ); 
  611.  
  612.  
  613.  
  614. } else { 
  615.  
  616. if ( $duplicate ) { 
  617.  
  618. $this->duplicate_person( $tr_product_id, $person, $lang_code ); 
  619.  
  620. } else { 
  621.  
  622. continue; 
  623.  
  624.  
  625.  
  626.  
  627. foreach ( $trnsl_persons as $trnsl_person ) { 
  628.  
  629. wp_delete_post( $trnsl_person ); 
  630.  
  631.  
  632.  
  633. function duplicate_person( $tr_product_id, $person_id, $lang_code ) { 
  634. global $iclTranslationManagement; 
  635.  
  636. if ( method_exists( $this->sitepress, 'make_duplicate' ) ) { 
  637.  
  638. $new_person_id = $this->sitepress->make_duplicate( $person_id, $lang_code ); 
  639.  
  640. } else { 
  641.  
  642. if ( ! isset( $iclTranslationManagement ) ) { 
  643. $iclTranslationManagement = new TranslationManagement; 
  644.  
  645. $new_person_id = $iclTranslationManagement->make_duplicate( $person_id, $lang_code ); 
  646.  
  647.  
  648. $this->wpdb->update( 
  649. $this->wpdb->posts,  
  650. array( 
  651. 'post_parent' => $tr_product_id 
  652. ),  
  653. array( 
  654. 'ID' => $new_person_id 
  655. ); 
  656.  
  657. delete_post_meta( $new_person_id, '_icl_lang_duplicate_of' ); 
  658.  
  659. return $new_person_id; 
  660.  
  661. function filter_wc_booking_cost( $check, $object_id, $meta_key, $single ) { 
  662.  
  663. if ( in_array( $meta_key, array( 
  664. '_wc_booking_cost',  
  665. '_wc_booking_base_cost',  
  666. '_wc_display_cost',  
  667. '_wc_booking_pricing',  
  668. 'cost',  
  669. 'block_cost',  
  670. '_resource_base_costs',  
  671. '_resource_block_costs' 
  672. ) ) ) { 
  673.  
  674. if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) { 
  675.  
  676. $original_id = $this->woocommerce_wpml->products->get_original_product_id( $object_id ); 
  677.  
  678. $cost_status = get_post_meta( $original_id, '_wcml_custom_costs_status', true ); 
  679.  
  680. $currency = $this->woocommerce_wpml->multi_currency->get_client_currency(); 
  681.  
  682. if ( $currency == get_option( 'woocommerce_currency' ) ) { 
  683. return $check; 
  684.  
  685. if ( in_array( $meta_key, array( 'cost', 'block_cost' ) ) ) { 
  686.  
  687. if ( get_post_type( $object_id ) == 'bookable_person' ) { 
  688.  
  689. $original_id = apply_filters( 'translate_object_id', wp_get_post_parent_id( $object_id ), 'product', true, $this->woocommerce_wpml->products->get_original_product_language( wp_get_post_parent_id( $object_id ) ) ); 
  690. $cost_status = get_post_meta( $original_id, '_wcml_custom_costs_status', true ); 
  691.  
  692. $value = get_post_meta( $object_id, $meta_key . '_' . $currency, true ); 
  693.  
  694. if ( $cost_status && $value ) { 
  695.  
  696. return $value; 
  697.  
  698. } else { 
  699.  
  700. remove_filter( 'get_post_metadata', array( $this, 'filter_wc_booking_cost' ), 10, 4 ); 
  701.  
  702. $cost = get_post_meta( $object_id, $meta_key, true ); 
  703.  
  704. add_filter( 'get_post_metadata', array( $this, 'filter_wc_booking_cost' ), 10, 4 ); 
  705.  
  706. return $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency ); 
  707.  
  708. } else { 
  709.  
  710. return $check; 
  711.  
  712.  
  713.  
  714. if ( in_array( $meta_key, array( 
  715. '_wc_booking_pricing',  
  716. '_resource_base_costs',  
  717. '_resource_block_costs' 
  718. ) ) ) { 
  719.  
  720. remove_filter( 'get_post_metadata', array( $this, 'filter_wc_booking_cost' ), 10, 4 ); 
  721.  
  722. if ( $meta_key == '_wc_booking_pricing' ) { 
  723.  
  724. if ( $original_id != $object_id ) { 
  725. $value = get_post_meta( $original_id, $meta_key ); 
  726. } else { 
  727. $value = $check; 
  728.  
  729. } else { 
  730.  
  731. $costs = maybe_unserialize( get_post_meta( $object_id, $meta_key, true ) ); 
  732.  
  733. if ( ! $costs ) { 
  734. $value = $check; 
  735. } elseif ( $cost_status && isset( $costs['custom_costs'][ $currency ] ) ) { 
  736.  
  737. $res_costs = array(); 
  738. foreach ( $costs['custom_costs'][ $currency ] as $resource_id => $cost ) { 
  739. $trns_resource_id = apply_filters( 'translate_object_id', $resource_id, 'bookable_resource', true, $this->sitepress->get_current_language() ); 
  740. $res_costs[ $trns_resource_id ] = $cost; 
  741. $value = array( 0 => $res_costs ); 
  742. } elseif ( $cost_status && isset( $costs[0]['custom_costs'][ $currency ] ) ) { 
  743. $value = array( 0 => $costs[0]['custom_costs'][ $currency ] ); 
  744. } else { 
  745.  
  746. $converted_values = array(); 
  747.  
  748. foreach ( $costs as $resource_id => $cost ) { 
  749. $converted_values[0][ $resource_id ] = $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency ); 
  750.  
  751. $value = $converted_values; 
  752.  
  753.  
  754. add_filter( 'get_post_metadata', array( $this, 'filter_wc_booking_cost' ), 10, 4 ); 
  755.  
  756. return $value; 
  757.  
  758.  
  759. $value = get_post_meta( $original_id, $meta_key . '_' . $currency, true ); 
  760.  
  761. if ( $cost_status && ( ! empty( $value ) || ( empty( $value ) && $meta_key == '_wc_display_cost' ) ) ) { 
  762.  
  763. return $value; 
  764.  
  765. } else { 
  766.  
  767. remove_filter( 'get_post_metadata', array( $this, 'filter_wc_booking_cost' ), 10, 4 ); 
  768.  
  769. $value = get_post_meta( $original_id, $meta_key, true ); 
  770.  
  771. $value = $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $value, $currency ); 
  772.  
  773. add_filter( 'get_post_metadata', array( $this, 'filter_wc_booking_cost' ), 10, 4 ); 
  774.  
  775. return $value; 
  776.  
  777.  
  778.  
  779.  
  780. return $check; 
  781.  
  782. function sync_resource_costs_with_translations( $object_id, $meta_key, $check = false ) { 
  783.  
  784.  
  785. $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $object_id ); 
  786.  
  787. if ( $object_id == $original_product_id ) { 
  788.  
  789. $trid = $this->sitepress->get_element_trid( $object_id, 'post_product' ); 
  790. $translations = $this->sitepress->get_element_translations( $trid, 'post_product' ); 
  791.  
  792. foreach ( $translations as $translation ) { 
  793.  
  794. if ( ! $translation->original ) { 
  795.  
  796. $this->sync_resource_costs( $original_product_id, $translation->element_id, $meta_key, $translation->language_code ); 
  797.  
  798.  
  799. return $check; 
  800.  
  801. } else { 
  802.  
  803. $language_code = $this->sitepress->get_language_for_element( $object_id, 'post_product' ); 
  804.  
  805. $this->sync_resource_costs( $original_product_id, $object_id, $meta_key, $language_code ); 
  806.  
  807. return true; 
  808.  
  809.  
  810.  
  811. function sync_resource_costs( $original_product_id, $object_id, $meta_key, $language_code ) { 
  812.  
  813. $original_costs = maybe_unserialize( get_post_meta( $original_product_id, $meta_key, true ) ); 
  814.  
  815. $wc_booking_resource_costs = array(); 
  816. if ( ! empty( $original_costs ) ) { 
  817. foreach ( $original_costs as $resource_id => $costs ) { 
  818.  
  819. if ( $resource_id == 'custom_costs' && isset( $costs['custom_costs'] ) ) { 
  820.  
  821. foreach ( $costs['custom_costs'] as $code => $currencies ) { 
  822.  
  823. foreach ( $currencies as $custom_costs_resource_id => $custom_cost ) { 
  824.  
  825. $trns_resource_id = apply_filters( 'translate_object_id', $custom_costs_resource_id, 'bookable_resource', true, $language_code ); 
  826.  
  827. $wc_booking_resource_costs['custom_costs'][ $code ][ $trns_resource_id ] = $custom_cost; 
  828.  
  829.  
  830.  
  831. } else { 
  832.  
  833. $trns_resource_id = apply_filters( 'translate_object_id', $resource_id, 'bookable_resource', true, $language_code ); 
  834.  
  835. $wc_booking_resource_costs[ $trns_resource_id ] = $costs; 
  836.  
  837.  
  838.  
  839. update_post_meta( $object_id, $meta_key, $wc_booking_resource_costs ); 
  840.  
  841.  
  842. function wc_bookings_process_cost_rules_cost( $cost, $fields, $key ) { 
  843. return $this->filter_pricing_cost( $cost, $fields, 'cost_', $key ); 
  844.  
  845. function wc_bookings_process_cost_rules_base_cost( $base_cost, $fields, $key ) { 
  846. return $this->filter_pricing_cost( $base_cost, $fields, 'base_cost_', $key ); 
  847.  
  848. function wc_bookings_process_cost_rules_override_block_cost( $override_cost, $fields, $key ) { 
  849. return $this->filter_pricing_cost( $override_cost, $fields, 'override_block_', $key ); 
  850.  
  851. function filter_pricing_cost( $cost, $fields, $name, $key ) { 
  852. global $product; 
  853.  
  854. if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) { 
  855.  
  856. $currency = $this->woocommerce_wpml->multi_currency->get_client_currency(); 
  857.  
  858. if ( $currency == get_option( 'woocommerce_currency' ) ) { 
  859. return $cost; 
  860.  
  861. if ( isset( $_POST['form'] ) ) { 
  862. parse_str( $_POST['form'], $posted ); 
  863.  
  864. $booking_id = $posted['add-to-cart']; 
  865.  
  866. } elseif ( isset( $_POST['add-to-cart'] ) ) { 
  867.  
  868. $booking_id = $_POST['add-to-cart']; 
  869.  
  870.  
  871. if ( isset( $booking_id ) ) { 
  872. $original_id = $this->woocommerce_wpml->products->get_original_product_id( $booking_id ); 
  873.  
  874. if ( $booking_id != $original_id ) { 
  875. $fields = maybe_unserialize( get_post_meta( $original_id, '_wc_booking_pricing', true ) ); 
  876. $fields = $fields[ $key ]; 
  877.  
  878. $needs_filter_pricing_cost = $this->needs_filter_pricing_cost( $name, $fields ); 
  879.  
  880. if( $needs_filter_pricing_cost ) { 
  881. if ( isset( $fields[ $name . $currency ] ) ) { 
  882. return $fields[ $name . $currency ]; 
  883. } else { 
  884. return $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency ); 
  885.  
  886.  
  887. return $cost; 
  888.  
  889.  
  890. function needs_filter_pricing_cost( $name, $fields ) { 
  891.  
  892. $modifier_skip_values = array( 'divide', 'times' ); 
  893.  
  894. if( 
  895. 'override_block_' === $name || 
  896. ( 'cost_' === $name && !in_array( $fields[ 'modifier' ], $modifier_skip_values ) ) || 
  897. ( 'base_cost_' === $name && !in_array( $fields[ 'base_modifier' ], $modifier_skip_values ) ) 
  898. ) { 
  899. return true; 
  900. }else{ 
  901. return false; 
  902.  
  903. function load_assets( $external_product_type = false ) { 
  904. global $pagenow; 
  905.  
  906. $product_id = $pagenow == 'post.php' && isset( $_GET['post'] ) ? (int)$_GET['post'] : false; 
  907.  
  908. if( $product_id && get_post_type( $product_id ) === 'product' ) { 
  909. $product_type = WooCommerce_Functions_Wrapper::get_product_type( $product_id ); 
  910.  
  911. if ( ( $product_type === 'booking' || $product_type === $external_product_type ) || $pagenow == 'post-new.php' ) { 
  912.  
  913. wp_register_style( 'wcml-bookings-css', WCML_PLUGIN_URL . '/compatibility/res/css/wcml-bookings.css', array(), WCML_VERSION ); 
  914. wp_enqueue_style( 'wcml-bookings-css' ); 
  915.  
  916. wp_register_script( 'wcml-bookings-js', WCML_PLUGIN_URL . '/compatibility/res/js/wcml-bookings.js', array( 'jquery' ), WCML_VERSION ); 
  917. wp_enqueue_script( 'wcml-bookings-js' ); 
  918.  
  919.  
  920.  
  921. function localize_lock_fields_js() { 
  922. wp_localize_script( 'wcml-bookings-js', 'lock_settings', array( 'lock_fields' => 1 ) ); 
  923.  
  924. function wcml_multi_currency_is_ajax( $actions ) { 
  925.  
  926. $actions[] = 'wc_bookings_calculate_costs'; 
  927.  
  928. return $actions; 
  929.  
  930. function filter_bundled_product_in_cart_contents( $cart_item, $key, $current_language ) { 
  931.  
  932. if ( $cart_item['data'] instanceof WC_Product_Booking && isset( $cart_item['booking'] ) ) { 
  933.  
  934.  
  935. $current_id = apply_filters( 'translate_object_id', $cart_item['product_id'], 'product', true, $current_language ); 
  936. $cart_product_id = $cart_item['product_id']; 
  937.  
  938. if ( $current_id != $cart_product_id ) { 
  939.  
  940. $cart_item['data'] = new WC_Product_Booking( $current_id ); 
  941.  
  942.  
  943. if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT || $current_id != $cart_product_id ) { 
  944.  
  945. $booking_info = array( 
  946. 'wc_bookings_field_start_date_year' => $cart_item['booking']['_year'],  
  947. 'wc_bookings_field_start_date_month' => $cart_item['booking']['_month'],  
  948. 'wc_bookings_field_start_date_day' => $cart_item['booking']['_day'],  
  949. 'add-to-cart' => $current_id 
  950. ); 
  951.  
  952. if ( isset( $cart_item['booking']['_persons'] ) ) { 
  953. foreach ( $cart_item['booking']['_persons'] as $person_id => $value ) { 
  954. $booking_info[ 'wc_bookings_field_persons_' . apply_filters( 'translate_object_id', $person_id, 'bookable_person', false, $current_language ) ] = $value; 
  955.  
  956. if ( isset( $cart_item['booking']['_resource_id'] ) ) { 
  957. $booking_info['wc_bookings_field_resource'] = apply_filters( 'translate_object_id', $cart_item['booking']['_resource_id'], 'bookable_resource', false, $current_language ); 
  958.  
  959. if ( isset( $cart_item['booking']['_duration'] ) ) { 
  960. $booking_info['wc_bookings_field_duration'] = $cart_item['booking']['_duration']; 
  961.  
  962. if ( isset( $cart_item['booking']['_time'] ) ) { 
  963. $booking_info['wc_bookings_field_start_date_time'] = $cart_item['booking']['_time']; 
  964.  
  965. $booking_form = new WC_Booking_Form( wc_get_product( $current_id ) ); 
  966.  
  967. $prod_qty = get_post_meta( $current_id, '_wc_booking_qty', true ); 
  968. update_post_meta( $current_id, '_wc_booking_qty', intval( $prod_qty + $cart_item['booking']['_qty'] ) ); 
  969. $cost = $booking_form->calculate_booking_cost( $booking_info ); 
  970. update_post_meta( $current_id, '_wc_booking_qty', $prod_qty ); 
  971.  
  972. if ( ! is_wp_error( $cost ) ) { 
  973. $cart_item['data']->set_price( $cost ); 
  974.  
  975.  
  976. return $cart_item; 
  977.  
  978.  
  979. function booking_currency_dropdown() { 
  980.  
  981.  
  982. if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) { 
  983. $current_booking_currency = $this->get_cookie_booking_currency(); 
  984.  
  985. $wc_currencies = get_woocommerce_currencies(); 
  986. $currencies = $this->woocommerce_wpml->multi_currency->get_currencies( $include_default = true ); 
  987. ?> 
  988. <tr valign="top"> 
  989. <th scope="row"><?php _e( 'Booking currency', 'woocommerce-multilingual' ); ?></th> 
  990. <td> 
  991. <select id="dropdown_booking_currency"> 
  992.  
  993. <?php foreach ( $currencies as $currency => $count ): ?> 
  994.  
  995. <option 
  996. value="<?php echo $currency ?>" <?php echo $current_booking_currency == $currency ? 'selected="selected"' : ''; ?>><?php echo $wc_currencies[ $currency ]; ?></option> 
  997.  
  998. <?php endforeach; ?> 
  999.  
  1000. </select> 
  1001. </td> 
  1002. </tr> 
  1003.  
  1004. <?php 
  1005.  
  1006. $wcml_booking_set_currency_nonce = wp_create_nonce( 'booking_set_currency' ); 
  1007.  
  1008. wc_enqueue_js( " 
  1009.  
  1010. jQuery(document).on('change', '#dropdown_booking_currency', function() { 
  1011. jQuery.ajax({ 
  1012. url: ajaxurl,  
  1013. type: 'post',  
  1014. data: { 
  1015. action: 'wcml_booking_set_currency',  
  1016. currency: jQuery('#dropdown_booking_currency').val(),  
  1017. wcml_nonce: '" . $wcml_booking_set_currency_nonce . "' 
  1018. },  
  1019. success: function( response ) { 
  1020. if(typeof response.error !== 'undefined') { 
  1021. alert(response.error); 
  1022. }else{ 
  1023. window.location = window.location.href; 
  1024. }) 
  1025. }); 
  1026. " ); 
  1027.  
  1028.  
  1029.  
  1030. function set_booking_currency_ajax() { 
  1031.  
  1032. $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); 
  1033. if ( ! $nonce || ! wp_verify_nonce( $nonce, 'booking_set_currency' ) ) { 
  1034. echo json_encode( array( 'error' => __( 'Invalid nonce', 'woocommerce-multilingual' ) ) ); 
  1035. die(); 
  1036.  
  1037. $this->set_booking_currency( filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ); 
  1038.  
  1039. die(); 
  1040.  
  1041. function set_booking_currency( $currency_code = false ) { 
  1042.  
  1043. if ( ! isset( $_COOKIE ['_wcml_booking_currency'] ) && ! headers_sent() ) { 
  1044.  
  1045.  
  1046. $currency_code = get_woocommerce_currency(); 
  1047.  
  1048. if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) { 
  1049. $order_currencies = $this->woocommerce_wpml->multi_currency->orders->get_orders_currencies(); 
  1050.  
  1051. if ( ! isset( $order_currencies[ $currency_code ] ) ) { 
  1052. foreach ( $order_currencies as $currency_code => $count ) { 
  1053. $currency_code = $currency_code; 
  1054. break; 
  1055.  
  1056. if ( $currency_code ) { 
  1057. setcookie( '_wcml_booking_currency', $currency_code, time() + 86400, COOKIEPATH, COOKIE_DOMAIN ); 
  1058.  
  1059.  
  1060. function get_cookie_booking_currency() { 
  1061.  
  1062. if ( isset( $_COOKIE ['_wcml_booking_currency'] ) ) { 
  1063. $currency = $_COOKIE['_wcml_booking_currency']; 
  1064. } else { 
  1065. $currency = get_woocommerce_currency(); 
  1066.  
  1067. return $currency; 
  1068.  
  1069. function filter_booking_currency_symbol( $currency ) { 
  1070. global $pagenow; 
  1071.  
  1072. remove_filter( 'woocommerce_currency_symbol', array( $this, 'filter_booking_currency_symbol' ) ); 
  1073. if ( isset( $_COOKIE ['_wcml_booking_currency'] ) && $pagenow == 'edit.php' && isset( $_GET['page'] ) && $_GET['page'] == 'create_booking' ) { 
  1074. $currency = get_woocommerce_currency_symbol( $_COOKIE ['_wcml_booking_currency'] ); 
  1075. add_filter( 'woocommerce_currency_symbol', array( $this, 'filter_booking_currency_symbol' ) ); 
  1076.  
  1077. return $currency; 
  1078.  
  1079. function create_booking_page_client_currency( $currency ) { 
  1080. global $pagenow; 
  1081.  
  1082. if ( wpml_is_ajax() && isset( $_POST['form'] ) ) { 
  1083. parse_str( $_POST['form'], $posted ); 
  1084.  
  1085. if ( ( $pagenow == 'edit.php' && isset( $_GET['page'] ) && $_GET['page'] == 'create_booking' ) || ( isset( $posted['_wp_http_referer'] ) && strpos( $posted['_wp_http_referer'], 'page=create_booking' ) !== false ) ) { 
  1086. $currency = $this->get_cookie_booking_currency(); 
  1087.  
  1088. return $currency; 
  1089.  
  1090. function set_order_currency_on_create_booking_page( $order_id ) { 
  1091. update_post_meta( $order_id, '_order_currency', $this->get_cookie_booking_currency() ); 
  1092.  
  1093. update_post_meta( $order_id, 'wpml_language', $this->sitepress->get_current_language() ); 
  1094.  
  1095.  
  1096. function filter_get_booking_products_args( $args ) { 
  1097. if ( isset( $args['suppress_filters'] ) ) { 
  1098. $args['suppress_filters'] = false; 
  1099.  
  1100. return $args; 
  1101.  
  1102. function custom_box_html( $obj, $product_id, $data ) { 
  1103. if ( WooCommerce_Functions_Wrapper::get_product_type( $product_id ) !== 'booking' ) { 
  1104. return; 
  1105.  
  1106. $bookings_section = new WPML_Editor_UI_Field_Section( __( 'Bookings', 'woocommerce-multilingual' ) ); 
  1107.  
  1108. if ( get_post_meta( $product_id, '_wc_booking_has_resources', true ) == 'yes' ) { 
  1109. $group = new WPML_Editor_UI_Field_Group( '', true ); 
  1110. $booking_field = new WPML_Editor_UI_Single_Line_Field( '_wc_booking_resouce_label', __( 'Resources Label', 'woocommerce-multilingual' ), $data, true ); 
  1111. $group->add_field( $booking_field ); 
  1112. $bookings_section->add_field( $group ); 
  1113.  
  1114. $orig_resources = maybe_unserialize( get_post_meta( $product_id, '_resource_base_costs', true ) ); 
  1115.  
  1116. if ( $orig_resources ) { 
  1117. $group = new WPML_Editor_UI_Field_Group( __( 'Resources', 'woocommerce-multilingual' ) ); 
  1118. $group_title = __( 'Resources', 'woocommerce-multilingual' ); 
  1119. foreach ( $orig_resources as $resource_id => $cost ) { 
  1120.  
  1121. if ( $resource_id == 'custom_costs' ) { 
  1122. continue; 
  1123.  
  1124. $group = new WPML_Editor_UI_Field_Group( $group_title ); 
  1125. $group_title = ''; 
  1126.  
  1127. $resource_field = new WPML_Editor_UI_Single_Line_Field( 'bookings-resource_' . $resource_id . '_title', __( 'Title', 'woocommerce-multilingual' ), $data, true ); 
  1128. $group->add_field( $resource_field ); 
  1129. $bookings_section->add_field( $group ); 
  1130.  
  1131.  
  1132. $original_persons = $this->get_original_persons( $product_id ); 
  1133. end( $original_persons ); 
  1134. $last_key = key( $original_persons ); 
  1135. $divider = true; 
  1136. $group_title = __( 'Person Types', 'woocommerce-multilingual' ); 
  1137. foreach ( $original_persons as $person_id ) { 
  1138. if ( $person_id == $last_key ) { 
  1139. $divider = false; 
  1140. $group = new WPML_Editor_UI_Field_Group( $group_title, $divider ); 
  1141. $group_title = ''; 
  1142.  
  1143. $person_field = new WPML_Editor_UI_Single_Line_Field( 'bookings-person_' . $person_id . '_title', __( 'Person Type Name', 'woocommerce-multilingual' ), $data, false ); 
  1144. $group->add_field( $person_field ); 
  1145. $person_field = new WPML_Editor_UI_Single_Line_Field( 'bookings-person_' . $person_id . '_description', __( 'Description', 'woocommerce-multilingual' ), $data, false ); 
  1146. $group->add_field( $person_field ); 
  1147. $bookings_section->add_field( $group ); 
  1148.  
  1149.  
  1150. if ( $orig_resources || $original_persons ) { 
  1151. $obj->add_field( $bookings_section ); 
  1152.  
  1153.  
  1154.  
  1155. function custom_box_html_data( $data, $product_id, $translation, $lang ) { 
  1156.  
  1157. if ( WooCommerce_Functions_Wrapper::get_product_type( $product_id ) !== 'booking' ) { 
  1158. return $data; 
  1159.  
  1160. if ( get_post_meta( $product_id, '_wc_booking_has_resources', true ) == 'yes' ) { 
  1161.  
  1162. $data['_wc_booking_resouce_label'] = array( 'original' => get_post_meta( $product_id, '_wc_booking_resouce_label', true ) ); 
  1163. $data['_wc_booking_resouce_label']['translation'] = $translation ? get_post_meta( $translation->ID, '_wc_booking_resouce_label', true ) : ''; 
  1164.  
  1165. $orig_resources = $this->get_original_resources( $product_id ); 
  1166.  
  1167. if ( $orig_resources && is_array( $orig_resources ) ) { 
  1168.  
  1169. foreach ( $orig_resources as $resource_id => $cost ) { 
  1170.  
  1171. if ( 'custom_costs' === $resource_id ) { 
  1172. continue; 
  1173. $data[ 'bookings-resource_' . $resource_id . '_title' ] = array( 'original' => get_the_title( $resource_id ) ); 
  1174. global $sitepress; 
  1175. $trns_resource_id = apply_filters( 'translate_object_id', $resource_id, 'bookable_resource', false, $lang ); 
  1176. $data[ 'bookings-resource_' . $resource_id . '_title' ]['translation'] = $trns_resource_id ? get_the_title( $trns_resource_id ) : ''; 
  1177.  
  1178. $original_persons = $this->get_original_persons( $product_id ); 
  1179.  
  1180. foreach ( $original_persons as $person_id ) { 
  1181.  
  1182. $data[ 'bookings-person_' . $person_id . '_title' ] = array( 'original' => get_the_title( $person_id ) ); 
  1183. $data[ 'bookings-person_' . $person_id . '_description' ] = array( 'original' => get_post( $person_id )->post_excerpt ); 
  1184.  
  1185. $trnsl_person_id = apply_filters( 'translate_object_id', $person_id, 'bookable_person', false, $lang ); 
  1186. $data[ 'bookings-person_' . $person_id . '_title' ]['translation'] = $trnsl_person_id ? get_the_title( $trnsl_person_id ) : ''; 
  1187. $data[ 'bookings-person_' . $person_id . '_description' ]['translation'] = $trnsl_person_id ? get_post( $trnsl_person_id )->post_excerpt : ''; 
  1188.  
  1189.  
  1190. return $data; 
  1191.  
  1192.  
  1193. function get_original_resources( $product_id ) { 
  1194. $orig_resources = maybe_unserialize( get_post_meta( $product_id, '_resource_base_costs', true ) ); 
  1195.  
  1196. return $orig_resources; 
  1197.  
  1198. function get_original_persons( $product_id ) { 
  1199. $original_persons = $this->wpdb->get_col( $this->wpdb->prepare( "SELECT ID FROM {$this->wpdb->posts} WHERE post_parent = %d AND post_type = 'bookable_person' AND post_status = 'publish'", $product_id ) ); 
  1200.  
  1201. return $original_persons; 
  1202.  
  1203. function show_custom_blocks_for_resources_and_persons( $check, $product_id, $product_content ) { 
  1204. if ( in_array( $product_content, array( 'wc_booking_resources', 'wc_booking_persons' ) ) ) { 
  1205. return false; 
  1206.  
  1207. return $check; 
  1208.  
  1209. function remove_custom_fields_to_translate( $exception, $product_id, $meta_key ) { 
  1210. if ( in_array( $meta_key, array( '_resource_base_costs', '_resource_block_costs' ) ) ) { 
  1211. $exception = true; 
  1212.  
  1213. return $exception; 
  1214.  
  1215. function remove_single_custom_fields_to_translate( $fields ) { 
  1216. $fields[] = '_wc_booking_resouce_label'; 
  1217.  
  1218. return $fields; 
  1219.  
  1220. function product_content_resource_label( $meta_key, $product_id ) { 
  1221. if ( $meta_key == '_wc_booking_resouce_label' ) { 
  1222. return __( 'Resources label', 'woocommerce-multilingual' ); 
  1223.  
  1224. return $meta_key; 
  1225.  
  1226. function wcml_products_tab_sync_resources_and_persons( $original_product_id, $tr_product_id, $data, $language ) { 
  1227. global $wpml_post_translations; 
  1228.  
  1229. remove_action( 'save_post', array( $wpml_post_translations, 'save_post_actions' ), 100, 2 ); 
  1230.  
  1231. $orig_resources = $orig_resources = $this->get_original_resources( $original_product_id );; 
  1232.  
  1233. if ( $orig_resources ) { 
  1234.  
  1235. foreach ( $orig_resources as $orig_resource_id => $cost ) { 
  1236.  
  1237. $resource_id = apply_filters( 'translate_object_id', $orig_resource_id, 'bookable_resource', false, $language ); 
  1238. $orig_resource = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT resource_id, sort_order FROM {$this->wpdb->prefix}wc_booking_relationships WHERE resource_id = %d AND product_id = %d", $orig_resource_id, $original_product_id ), OBJECT ); 
  1239.  
  1240. if ( is_null( $resource_id ) ) { 
  1241.  
  1242. if ( $orig_resource ) { 
  1243. $resource_id = $this->duplicate_resource( $tr_product_id, $orig_resource, $language ); 
  1244. } else { 
  1245. continue; 
  1246.  
  1247. } else { 
  1248. //update_relationship 
  1249.  
  1250. $exist = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT ID FROM {$this->wpdb->prefix}wc_booking_relationships WHERE resource_id = %d AND product_id = %d", $resource_id, $tr_product_id ) ); 
  1251.  
  1252. if ( ! $exist ) { 
  1253.  
  1254. $this->wpdb->insert( 
  1255. $this->wpdb->prefix . 'wc_booking_relationships',  
  1256. array( 
  1257. 'product_id' => $tr_product_id,  
  1258. 'resource_id' => $resource_id,  
  1259. 'sort_order' => $orig_resource->sort_order 
  1260. ); 
  1261.  
  1262.  
  1263.  
  1264.  
  1265. $this->wpdb->update( 
  1266. $this->wpdb->posts,  
  1267. array( 
  1268. 'post_title' => $data[ md5( 'bookings-resource_' . $orig_resource_id . '_title' ) ] 
  1269. ),  
  1270. array( 
  1271. 'ID' => $resource_id 
  1272. ); 
  1273.  
  1274. update_post_meta( $resource_id, 'wcml_is_translated', true ); 
  1275.  
  1276.  
  1277. //sync resources data 
  1278. $this->sync_resources( $original_product_id, $tr_product_id, $language, false ); 
  1279.  
  1280.  
  1281. $original_persons = $this->get_original_persons( $original_product_id ); 
  1282.  
  1283. //sync persons 
  1284. if ( $original_persons ) { 
  1285.  
  1286. foreach ( $original_persons as $original_person_id ) { 
  1287.  
  1288. $person_id = apply_filters( 'translate_object_id', $original_person_id, 'bookable_person', false, $language ); 
  1289.  
  1290. if ( is_null( $person_id ) ) { 
  1291.  
  1292. $person_id = $this->duplicate_person( $tr_product_id, $original_person_id, $language ); 
  1293.  
  1294. } else { 
  1295.  
  1296. $this->wpdb->update( 
  1297. $this->wpdb->posts,  
  1298. array( 
  1299. 'post_parent' => $tr_product_id 
  1300. ),  
  1301. array( 
  1302. 'ID' => $person_id 
  1303. ); 
  1304.  
  1305.  
  1306. $this->wpdb->update( 
  1307. $this->wpdb->posts,  
  1308. array( 
  1309. 'post_title' => $data[ md5( 'bookings-person_' . $original_person_id . '_title' ) ],  
  1310. 'post_excerpt' => $data[ md5( 'bookings-person_' . $original_person_id . '_description' ) ],  
  1311. ),  
  1312. array( 
  1313. 'ID' => $person_id 
  1314. ); 
  1315.  
  1316. update_post_meta( $person_id, 'wcml_is_translated', true ); 
  1317.  
  1318.  
  1319. //sync persons data 
  1320. $this->sync_persons( $original_product_id, $tr_product_id, $language, false ); 
  1321.  
  1322.  
  1323. add_action( 'save_post', array( $wpml_post_translations, 'save_post_actions' ), 100, 2 ); 
  1324.  
  1325.  
  1326. function duplicate_booking_for_translations( $booking_id, $lang = false ) { 
  1327. $booking_object = get_post( $booking_id ); 
  1328.  
  1329. $booking_data = array( 
  1330. 'post_type' => 'wc_booking',  
  1331. 'post_title' => $booking_object->post_title,  
  1332. 'post_status' => $booking_object->post_status,  
  1333. 'ping_status' => 'closed' 
  1334. ); 
  1335.  
  1336. if( $booking_object->post_parent && $lang ) { 
  1337. $translated_parent = apply_filters( 'translate_object_id', $booking_object->post_parent, get_post_type( $booking_object->post_parent ), false, $lang ); 
  1338. if( $translated_parent ) $booking_data[ 'post_parent' ] = $translated_parent; 
  1339.  
  1340. $active_languages = $this->sitepress->get_active_languages(); 
  1341.  
  1342. foreach ( $active_languages as $language ) { 
  1343.  
  1344. $booking_product_id = get_post_meta( $booking_id, '_booking_product_id', true ); 
  1345.  
  1346. if ( ! $lang ) { 
  1347. $booking_language = $this->sitepress->get_element_language_details( $booking_product_id, 'post_product' ); 
  1348. if ( $booking_language->language_code == $language['code'] ) { 
  1349. continue; 
  1350. } elseif ( $lang != $language['code'] ) { 
  1351. continue; 
  1352.  
  1353. $booking_persons = maybe_unserialize( get_post_meta( $booking_id, '_booking_persons', true ) ); 
  1354. $trnsl_booking_persons = array(); 
  1355.  
  1356. if ( is_array( $booking_persons ) && ! empty( $booking_persons ) ) { 
  1357. foreach ( $booking_persons as $person_id => $person_count ) { 
  1358.  
  1359. $trnsl_person_id = apply_filters( 'translate_object_id', $person_id, 'bookable_person', false, $language['code'] ); 
  1360.  
  1361. if ( is_null( $trnsl_person_id ) ) { 
  1362. $trnsl_booking_persons[] = $person_count; 
  1363. } else { 
  1364. $trnsl_booking_persons[ $trnsl_person_id ] = $person_count; 
  1365.  
  1366.  
  1367. $trnsl_booking_id = wp_insert_post( $booking_data ); 
  1368. $trid = $this->sitepress->get_element_trid( $booking_id ); 
  1369. $this->sitepress->set_element_language_details( $trnsl_booking_id, 'post_wc_booking', $trid, $language['code'] ); 
  1370.  
  1371. $meta_args = array( 
  1372. '_booking_order_item_id' => 0,  
  1373. '_booking_product_id' => $this->get_translated_booking_product_id( $booking_id, $language['code'] ),  
  1374. '_booking_resource_id' => $this->get_translated_booking_resource_id( $booking_id, $language['code'] ),  
  1375. '_booking_persons' => $this->get_translated_booking_persons_ids( $booking_id, $language['code'] ),  
  1376. '_booking_cost' => get_post_meta( $booking_id, '_booking_cost', true ),  
  1377. '_booking_start' => get_post_meta( $booking_id, '_booking_start', true ),  
  1378. '_booking_end' => get_post_meta( $booking_id, '_booking_end', true ),  
  1379. '_booking_all_day' => intval( get_post_meta( $booking_id, '_booking_all_day', true ) ),  
  1380. '_booking_parent_id' => get_post_meta( $booking_id, '_booking_parent_id', true ),  
  1381. '_booking_customer_id' => get_post_meta( $booking_id, '_booking_customer_id', true ),  
  1382. '_booking_duplicate_of' => $booking_id,  
  1383. '_language_code' => $language['code'],  
  1384. ); 
  1385.  
  1386. foreach ( $meta_args as $key => $value ) { 
  1387. update_post_meta( $trnsl_booking_id, $key, $value ); 
  1388.  
  1389. WC_Cache_Helper::get_transient_version( 'bookings', true ); 
  1390.  
  1391.  
  1392.  
  1393.  
  1394. function get_translated_booking_product_id( $booking_id, $language ) { 
  1395.  
  1396. $booking_product_id = get_post_meta( $booking_id, '_booking_product_id', true ); 
  1397. $trnsl_booking_product_id = ''; 
  1398.  
  1399. if ( $booking_product_id ) { 
  1400. $trnsl_booking_product_id = apply_filters( 'translate_object_id', $booking_product_id, 'product', false, $language ); 
  1401. if ( is_null( $trnsl_booking_product_id ) ) { 
  1402. $trnsl_booking_product_id = ''; 
  1403.  
  1404. return $trnsl_booking_product_id; 
  1405.  
  1406.  
  1407. function get_translated_booking_resource_id( $booking_id, $language ) { 
  1408.  
  1409. $booking_resource_id = get_post_meta( $booking_id, '_booking_resource_id', true ); 
  1410. $trnsl_booking_resource_id = ''; 
  1411.  
  1412. if ( $booking_resource_id ) { 
  1413. $trnsl_booking_resource_id = apply_filters( 'translate_object_id', $booking_resource_id, 'bookable_resource', false, $language ); 
  1414.  
  1415. if ( is_null( $trnsl_booking_resource_id ) ) { 
  1416. $trnsl_booking_resource_id = ''; 
  1417.  
  1418. return $trnsl_booking_resource_id; 
  1419.  
  1420. function get_translated_booking_persons_ids( $booking_id, $language ) { 
  1421.  
  1422. $booking_persons = maybe_unserialize( get_post_meta( $booking_id, '_booking_persons', true ) ); 
  1423. $trnsl_booking_persons = array(); 
  1424.  
  1425. if ( is_array( $booking_persons ) && ! empty( $booking_persons ) ) { 
  1426. foreach ( $booking_persons as $person_id => $person_count ) { 
  1427.  
  1428. $trnsl_person_id = apply_filters( 'translate_object_id', $person_id, 'bookable_person', false, $language ); 
  1429.  
  1430. if ( is_null( $trnsl_person_id ) ) { 
  1431. $trnsl_booking_persons[] = $person_count; 
  1432. } else { 
  1433. $trnsl_booking_persons[ $trnsl_person_id ] = $person_count; 
  1434.  
  1435.  
  1436. return $trnsl_booking_persons; 
  1437.  
  1438.  
  1439. function update_status_for_translations( $booking_id ) { 
  1440. $translated_bookings = $this->get_translated_bookings( $booking_id ); 
  1441.  
  1442. foreach ( $translated_bookings as $booking ) { 
  1443.  
  1444. $status = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT post_status FROM {$this->wpdb->posts} WHERE ID = %d", $booking_id ) ); //get_post_status( $booking_id ); 
  1445. $language = get_post_meta( $booking->post_id, '_language_code', true ); 
  1446.  
  1447. $this->wpdb->update( 
  1448. $this->wpdb->posts,  
  1449. array( 
  1450. 'post_status' => $status,  
  1451. 'post_parent' => wp_get_post_parent_id( $booking_id ),  
  1452. ),  
  1453. array( 
  1454. 'ID' => $booking->post_id 
  1455. ); 
  1456.  
  1457. update_post_meta( $booking->post_id, '_booking_product_id', $this->get_translated_booking_product_id( $booking_id, $language ) ); 
  1458. update_post_meta( $booking->post_id, '_booking_resource_id', $this->get_translated_booking_resource_id( $booking_id, $language ) ); 
  1459. update_post_meta( $booking->post_id, '_booking_persons', $this->get_translated_booking_persons_ids( $booking_id, $language ) ); 
  1460.  
  1461.  
  1462.  
  1463. function get_translated_bookings( $booking_id ) { 
  1464. $translated_bookings = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT post_id FROM {$this->wpdb->postmeta} WHERE meta_key = '_booking_duplicate_of' AND meta_value = %d", $booking_id ) ); 
  1465.  
  1466. return $translated_bookings; 
  1467.  
  1468. public function booking_filters_query( $query ) { 
  1469. global $typenow; 
  1470.  
  1471. if ( ( isset( $query->query_vars['post_type'] ) && $query->query_vars['post_type'] == 'wc_booking' ) ) { 
  1472.  
  1473. $current_lang = $this->sitepress->get_current_language(); 
  1474.  
  1475. $product_ids = $this->wpdb->get_col( $this->wpdb->prepare( 
  1476. "SELECT element_id 
  1477. FROM {$this->wpdb->prefix}icl_translations 
  1478. WHERE language_code = %s AND element_type = 'post_product'", $current_lang ) ); 
  1479.  
  1480. $product_ids = array_diff( $product_ids, array( null ) ); 
  1481.  
  1482. if ( ( ! isset( $_GET['lang'] ) || ( isset( $_GET['lang'] ) && $_GET['lang'] != 'all' ) ) ) { 
  1483. $query->query_vars['meta_query'][] = array( 
  1484. 'relation' => 'OR',  
  1485. array( 
  1486. 'key' => '_language_code',  
  1487. 'value' => $current_lang,  
  1488. 'compare ' => '=' 
  1489. ),  
  1490. array( 
  1491. 'key' => '_booking_product_id',  
  1492. 'value' => $product_ids,  
  1493. 'compare ' => 'IN' 
  1494. ); 
  1495.  
  1496. return $query; 
  1497.  
  1498. function bookings_in_date_range_query( $booking_ids ) { 
  1499. foreach ( $booking_ids as $key => $booking_id ) { 
  1500.  
  1501. $language_code = $this->sitepress->get_language_for_element( get_post_meta( $booking_id, '_booking_product_id', true ), 'post_product' ); 
  1502. $current_language = $this->sitepress->get_current_language(); 
  1503.  
  1504. if ( $language_code != $current_language ) { 
  1505. unset( $booking_ids[ $key ] ); 
  1506.  
  1507.  
  1508. return $booking_ids; 
  1509.  
  1510.  
  1511. function clear_transient_fields() { 
  1512.  
  1513. if ( isset( $_GET['post_type'] ) && $_GET['post_type'] == 'wc_booking' && isset( $_GET['page'] ) && $_GET['page'] == 'booking_calendar' ) { 
  1514.  
  1515. //delete transient fields 
  1516. $this->wpdb->query( " 
  1517. DELETE FROM {$this->wpdb->options} 
  1518. WHERE option_name LIKE '%book_dr_%' 
  1519. " ); 
  1520.  
  1521.  
  1522.  
  1523. function delete_bookings( $booking_id ) { 
  1524.  
  1525. if ( $booking_id > 0 && get_post_type( $booking_id ) == 'wc_booking' ) { 
  1526.  
  1527. $translated_bookings = $this->get_translated_bookings( $booking_id ); 
  1528.  
  1529. remove_action( 'before_delete_post', array( $this, 'delete_bookings' ) ); 
  1530.  
  1531. foreach ( $translated_bookings as $booking ) { 
  1532. $this->wpdb->update( 
  1533. $this->wpdb->posts,  
  1534. array( 
  1535. 'post_parent' => 0 
  1536. ),  
  1537. array( 
  1538. 'ID' => $booking->post_id 
  1539. ); 
  1540.  
  1541. wp_delete_post( $booking->post_id ); 
  1542.  
  1543.  
  1544. add_action( 'before_delete_post', array( $this, 'delete_bookings' ) ); 
  1545.  
  1546.  
  1547. function trash_bookings( $booking_id ) { 
  1548.  
  1549. if ( $booking_id > 0 && get_post_type( $booking_id ) == 'wc_booking' ) { 
  1550.  
  1551. $translated_bookings = $this->get_translated_bookings( $booking_id ); 
  1552.  
  1553. foreach ( $translated_bookings as $booking ) { 
  1554.  
  1555. $this->wpdb->update( 
  1556. $this->wpdb->posts,  
  1557. array( 
  1558. 'post_status' => 'trash' 
  1559. ),  
  1560. array( 
  1561. 'ID' => $booking->post_id 
  1562. ); 
  1563.  
  1564.  
  1565.  
  1566.  
  1567. function append_persons_to_translation_package( $package, $post ) { 
  1568.  
  1569. if ( $post->post_type == 'product' ) { 
  1570. $product_type = WooCommerce_Functions_Wrapper::get_product_type( $post->ID ); 
  1571.  
  1572. if ( $product_type === 'booking' ) { 
  1573.  
  1574. $bookable_product = new WC_Product_Booking( $post->ID ); 
  1575.  
  1576. $person_types = $bookable_product->get_person_types(); 
  1577.  
  1578. foreach ( $person_types as $person_type ) { 
  1579.  
  1580. $bookable_person = get_post( $person_type->ID ); 
  1581.  
  1582. $package['contents'][ 'wc_bookings:person:' . $bookable_person->ID . ':name' ] = array( 
  1583. 'translate' => 1,  
  1584. 'data' => $this->tp->encode_field_data( $bookable_person->post_title, 'base64' ),  
  1585. 'format' => 'base64' 
  1586. ); 
  1587.  
  1588. $package['contents'][ 'wc_bookings:person:' . $bookable_person->ID . ':description' ] = array( 
  1589. 'translate' => 1,  
  1590. 'data' => $this->tp->encode_field_data( $bookable_person->post_excerpt, 'base64' ),  
  1591. 'format' => 'base64' 
  1592. ); 
  1593.  
  1594.  
  1595.  
  1596.  
  1597. return $package; 
  1598.  
  1599.  
  1600. function save_person_translation( $post_id, $data, $job ) { 
  1601. $person_translations = array(); 
  1602.  
  1603. if ( WooCommerce_Functions_Wrapper::get_product_type( $post_id ) === 'booking' ) { 
  1604.  
  1605. foreach ( $data as $value ) { 
  1606.  
  1607. if ( $value['finished'] && strpos( $value['field_type'], 'wc_bookings:person:' ) === 0 ) { 
  1608.  
  1609. $exp = explode( ':', $value['field_type'] ); 
  1610.  
  1611. $person_id = $exp[2]; 
  1612. $field = $exp[3]; 
  1613.  
  1614. $person_translations[ $person_id ][ $field ] = $value['data']; 
  1615.  
  1616.  
  1617.  
  1618. if ( $person_translations ) { 
  1619.  
  1620. foreach ( $person_translations as $person_id => $pt ) { 
  1621.  
  1622. $person_trid = $this->sitepress->get_element_trid( $person_id, 'post_bookable_person' ); 
  1623.  
  1624.  
  1625. $person_id_translated = apply_filters( 'translate_object_id', $person_id, 'bookable_person', false, $job->language_code ); 
  1626.  
  1627. if ( empty( $person_id_translated ) ) { 
  1628.  
  1629. $person_post = array( 
  1630.  
  1631. 'post_type' => 'bookable_person',  
  1632. 'post_status' => 'publish',  
  1633. 'post_title' => $pt['name'],  
  1634. 'post_parent' => $post_id,  
  1635. 'post_excerpt' => isset( $pt['description'] ) ? $pt['description'] : '' 
  1636.  
  1637. ); 
  1638.  
  1639. $person_id_translated = wp_insert_post( $person_post ); 
  1640.  
  1641. $this->sitepress->set_element_language_details( $person_id_translated, 'post_bookable_person', $person_trid, $job->language_code ); 
  1642.  
  1643. } else { 
  1644.  
  1645. $person_post = array( 
  1646. 'ID' => $person_id_translated,  
  1647. 'post_title' => $pt['name'],  
  1648. 'post_excerpt' => isset( $pt['description'] ) ? $pt['description'] : '' 
  1649. ); 
  1650.  
  1651. wp_update_post( $person_post ); 
  1652.  
  1653.  
  1654.  
  1655.  
  1656.  
  1657.  
  1658. function append_resources_to_translation_package( $package, $post ) { 
  1659.  
  1660. if ( $post->post_type == 'product' ) { 
  1661. $product = wc_get_product( $post->ID ); 
  1662.  
  1663. $product_type = WooCommerce_Functions_Wrapper::get_product_type( $post->ID ); 
  1664.  
  1665. if ( $product_type === 'booking' && $product->has_resources() ) { 
  1666.  
  1667. $resources = $product->get_resources(); 
  1668.  
  1669. foreach ( $resources as $resource ) { 
  1670.  
  1671. $package['contents'][ 'wc_bookings:resource:' . $resource->ID . ':name' ] = array( 
  1672. 'translate' => 1,  
  1673. 'data' => $this->tp->encode_field_data( $resource->post_title, 'base64' ),  
  1674. 'format' => 'base64' 
  1675. ); 
  1676.  
  1677.  
  1678.  
  1679.  
  1680. return $package; 
  1681.  
  1682.  
  1683. function save_resource_translation( $post_id, $data, $job ) { 
  1684. $resource_translations = array(); 
  1685.  
  1686. if ( WooCommerce_Functions_Wrapper::get_product_type( $post_id ) === 'booking' ) { 
  1687.  
  1688. foreach ( $data as $value ) { 
  1689.  
  1690. if ( $value['finished'] && strpos( $value['field_type'], 'wc_bookings:resource:' ) === 0 ) { 
  1691.  
  1692. $exp = explode( ':', $value['field_type'] ); 
  1693.  
  1694. $resource_id = $exp[2]; 
  1695. $field = $exp[3]; 
  1696.  
  1697. $resource_translations[ $resource_id ][ $field ] = $value['data']; 
  1698.  
  1699.  
  1700.  
  1701. if ( $resource_translations ) { 
  1702.  
  1703. foreach ( $resource_translations as $resource_id => $rt ) { 
  1704.  
  1705. $resource_trid = $this->sitepress->get_element_trid( $resource_id, 'post_bookable_resource' ); 
  1706.  
  1707. $resource_id_translated = apply_filters( 'translate_object_id', $resource_id, 'bookable_resource', false, $job->language_code ); 
  1708.  
  1709. if ( empty( $resource_id_translated ) ) { 
  1710.  
  1711. $resource_post = array( 
  1712.  
  1713. 'post_type' => 'bookable_resource',  
  1714. 'post_status' => 'publish',  
  1715. 'post_title' => $rt['name'],  
  1716. 'post_parent' => $post_id 
  1717. ); 
  1718.  
  1719. $resource_id_translated = wp_insert_post( $resource_post ); 
  1720.  
  1721. $this->sitepress->set_element_language_details( $resource_id_translated, 'post_bookable_resource', $resource_trid, $job->language_code ); 
  1722.  
  1723. $sort_order = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT sort_order FROM {$this->wpdb->prefix}wc_booking_relationships WHERE resource_id=%d", $resource_id ) ); 
  1724. $relationship = array( 
  1725. 'product_id' => $post_id,  
  1726. 'resource_id' => $resource_id_translated,  
  1727. 'sort_order' => $sort_order 
  1728. ); 
  1729. $this->wpdb->insert( $this->wpdb->prefix . 'wc_booking_relationships', $relationship ); 
  1730.  
  1731. } else { 
  1732.  
  1733. $resource_post = array( 
  1734. 'ID' => $resource_id_translated,  
  1735. 'post_title' => $rt['name'] 
  1736. ); 
  1737.  
  1738. wp_update_post( $resource_post ); 
  1739.  
  1740. $sort_order = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT sort_order FROM {$this->wpdb->prefix}wc_booking_relationships WHERE resource_id=%d", $resource_id ) ); 
  1741. $this->wpdb->update( $this->wpdb->prefix . 'wc_booking_relationships', array( 'sort_order' => $sort_order ),  
  1742. array( 'product_id' => $post_id, 'resource_id' => $resource_id_translated ) ); 
  1743.  
  1744.  
  1745.  
  1746.  
  1747.  
  1748.  
  1749.  
  1750.  
  1751. function wcml_js_lock_fields_ids( $ids ) { 
  1752.  
  1753. $ids = array_merge( $ids, array( 
  1754. '_wc_booking_has_resources',  
  1755. '_wc_booking_has_persons',  
  1756. '_wc_booking_duration_type',  
  1757. '_wc_booking_duration',  
  1758. '_wc_booking_duration_unit',  
  1759. '_wc_booking_calendar_display_mode',  
  1760. '_wc_booking_requires_confirmation',  
  1761. '_wc_booking_user_can_cancel',  
  1762. '_wc_accommodation_booking_min_duration',  
  1763. '_wc_accommodation_booking_max_duration',  
  1764. '_wc_accommodation_booking_max_duration',  
  1765. '_wc_accommodation_booking_calendar_display_mode',  
  1766. '_wc_accommodation_booking_requires_confirmation',  
  1767. '_wc_accommodation_booking_user_can_cancel',  
  1768. '_wc_accommodation_booking_cancel_limit',  
  1769. '_wc_accommodation_booking_cancel_limit_unit',  
  1770. '_wc_accommodation_booking_qty',  
  1771. '_wc_accommodation_booking_min_date',  
  1772. '_wc_accommodation_booking_min_date_unit',  
  1773. '_wc_accommodation_booking_max_date',  
  1774. '_wc_accommodation_booking_max_date_unit',  
  1775. 'bookings_pricing select',  
  1776. 'bookings_resources select',  
  1777. 'bookings_availability select',  
  1778. 'bookings_persons input[type="checkbox"]' 
  1779. ) ); 
  1780.  
  1781. return $ids; 
  1782.  
  1783. /** 
  1784. * @param array $args 
  1785. * @return array 
  1786. */ 
  1787. public function filter_get_booking_resources_args( $args ) { 
  1788.  
  1789. $screen = get_current_screen(); 
  1790. if ( $screen->id == 'product' ) { 
  1791. $args['suppress_filters'] = false; 
  1792.  
  1793. return $args; 
  1794.  
  1795.  
  1796. /** 
  1797. * @param array $currencies 
  1798. * @param int $post_id 
  1799. * @return bool 
  1800. */ 
  1801. private function update_booking_costs( $currencies = array(), $post_id = 0 ) { 
  1802. $booking_options = array( 
  1803. 'wcml_wc_booking_cost' => '_wc_booking_cost_',  
  1804. 'wcml_wc_booking_base_cost' => '_wc_booking_base_cost_',  
  1805. 'wcml_wc_display_cost' => '_wc_display_cost_',  
  1806. ); 
  1807.  
  1808. foreach ( $currencies as $code => $currency ) { 
  1809. foreach ( $booking_options as $booking_options_post_key => $booking_options_meta_key_prefix ) { 
  1810. if ( isset( $_POST[ $booking_options_post_key ][ $code ] ) ) { 
  1811. update_post_meta( $post_id, $booking_options_meta_key_prefix . $code, sanitize_text_field( $_POST[ $booking_options_post_key ][ $code ] ) ); 
  1812.  
  1813. return true; 
  1814.  
  1815. /** 
  1816. * @param array $currencies 
  1817. * @param int $post_id 
  1818. * @return bool 
  1819. */ 
  1820. private function update_booking_pricing( $currencies = array(), $post_id = 0 ) { 
  1821. $updated_meta = array(); 
  1822. $booking_pricing = get_post_meta( $post_id, '_wc_booking_pricing', true ); 
  1823. if ( empty( $booking_pricing ) ) { 
  1824. return false; 
  1825.  
  1826. foreach ( $booking_pricing as $key => $prices ) { 
  1827. $updated_meta[ $key ] = $prices; 
  1828. foreach ( $currencies as $code => $currency ) { 
  1829. if ( isset( $_POST['wcml_wc_booking_pricing_base_cost'][ $code ][ $key ] ) ) { 
  1830. $updated_meta[ $key ][ 'base_cost_' . $code ] = sanitize_text_field( $_POST['wcml_wc_booking_pricing_base_cost'][ $code ][ $key ] ); 
  1831. if ( isset( $_POST['wcml_wc_booking_pricing_cost'][ $code ][ $key ] ) ) { 
  1832. $updated_meta[ $key ][ 'cost_' . $code ] = sanitize_text_field( $_POST['wcml_wc_booking_pricing_cost'][ $code ][ $key ] ); 
  1833.  
  1834.  
  1835. update_post_meta( $post_id, '_wc_booking_pricing', $updated_meta ); 
  1836.  
  1837. return true; 
  1838.  
  1839. /** 
  1840. * @param array $currencies 
  1841. * @param array $person_costs 
  1842. * @return bool 
  1843. */ 
  1844. private function update_booking_person_cost( $currencies = array(), $person_costs = array() ) { 
  1845. if ( empty( $person_costs ) ) { 
  1846. return false; 
  1847.  
  1848. foreach ( $person_costs as $person_id => $costs ) { 
  1849. foreach ( $currencies as $code => $currency ) { 
  1850. if ( isset( $costs[ $code ] ) ) { 
  1851. update_post_meta( $person_id, 'cost_' . $code, sanitize_text_field( $costs[ $code ] ) ); 
  1852.  
  1853. return true; 
  1854.  
  1855. /** 
  1856. * @param array $currencies 
  1857. * @param array $block_costs 
  1858. * @return bool 
  1859. */ 
  1860. private function update_booking_person_block_cost( $currencies = array(), $block_costs = array() ) { 
  1861. if ( empty( $block_costs ) ) { 
  1862. return false; 
  1863.  
  1864. foreach ( $block_costs as $person_id => $costs ) { 
  1865. foreach ( $currencies as $code => $currency ) { 
  1866. if ( isset( $costs[ $code ] ) ) { 
  1867. update_post_meta( $person_id, 'block_cost_' . $code, sanitize_text_field( $costs[ $code ] ) ); 
  1868.  
  1869. return true; 
  1870.  
  1871. /** 
  1872. * @param array $currencies 
  1873. * @param int $post_id 
  1874. * @param array $resource_cost 
  1875. * @return bool 
  1876. */ 
  1877. private function update_booking_resource_cost( $currencies = array(), $post_id = 0, $resource_cost = array() ) { 
  1878. if ( empty( $resource_cost ) ) { 
  1879. return false; 
  1880.  
  1881. $updated_meta = get_post_meta( $post_id, '_resource_base_costs', true ); 
  1882. if ( ! is_array( $updated_meta ) ) { 
  1883. $updated_meta = array(); 
  1884.  
  1885. $wc_booking_resource_costs = array(); 
  1886.  
  1887. foreach ( $resource_cost as $resource_id => $costs ) { 
  1888.  
  1889. foreach ( $currencies as $code => $currency ) { 
  1890.  
  1891. if ( isset( $costs[ $code ] ) ) { 
  1892. $wc_booking_resource_costs[ $code ][ $resource_id ] = sanitize_text_field( $costs[ $code ] ); 
  1893.  
  1894.  
  1895.  
  1896. $updated_meta['custom_costs'] = $wc_booking_resource_costs; 
  1897.  
  1898. update_post_meta( $post_id, '_resource_base_costs', $updated_meta ); 
  1899.  
  1900. $this->sync_resource_costs_with_translations( $post_id, '_resource_base_costs' ); 
  1901.  
  1902. return true; 
  1903.  
  1904. /** 
  1905. * @param array $currencies 
  1906. * @param int $post_id 
  1907. * @return bool 
  1908. */ 
  1909. private function update_booking_resource_block_cost( $currencies = array(), $post_id = 0, $resource_block_cost = array() ) { 
  1910. if ( empty( $resource_block_cost ) ) { 
  1911. return false; 
  1912.  
  1913. $updated_meta = get_post_meta( $post_id, '_resource_block_costs', true ); 
  1914.  
  1915. $wc_booking_resource_block_costs = array(); 
  1916.  
  1917. foreach ( $resource_block_cost as $resource_id => $costs ) { 
  1918.  
  1919. foreach ( $currencies as $code => $currency ) { 
  1920.  
  1921. if ( isset( $costs[ $code ] ) ) { 
  1922. $wc_booking_resource_block_costs[ $code ][ $resource_id ] = sanitize_text_field( $costs[ $code ] ); 
  1923.  
  1924.  
  1925.  
  1926. $updated_meta['custom_costs'] = $wc_booking_resource_block_costs; 
  1927.  
  1928. update_post_meta( $post_id, '_resource_block_costs', $updated_meta ); 
  1929.  
  1930. $this->sync_resource_costs_with_translations( $post_id, '_resource_block_costs' ); 
  1931.  
  1932. return true; 
  1933.  
  1934. public function maybe_fix_double_serialized_wc_booking_availability( $mid, $object_id, $meta_key, $_meta_value ) { 
  1935. global $wpdb; 
  1936.  
  1937. if ( version_compare( ICL_SITEPRESS_VERSION, '3.6', '<' ) ) { 
  1938.  
  1939. $meta_keys_to_fix = array( 
  1940. '_wc_booking_availability',  
  1941. '_wc_booking_pricing' 
  1942. ); 
  1943.  
  1944. if ( in_array( $meta_key, $meta_keys_to_fix ) ) { 
  1945.  
  1946. if ( is_string( $_meta_value ) ) { 
  1947. $wpdb->update( $wpdb->postmeta, array( 'meta_value' => $_meta_value ), array( 'meta_id' => $mid ) ); 
  1948.  
  1949.  
  1950.  
  1951.  
  1952. public function extra_conditions_to_filter_bookings( $extra_conditions ) { 
  1953.  
  1954. if( isset( $_GET[ 'post_type' ] ) && $_GET[ 'post_type' ] == 'wc_booking' && !isset( $_GET[ 'post_status' ] ) ) { 
  1955. $extra_conditions = str_replace( "GROUP BY", " AND post_status = 'confirmed' GROUP BY", $extra_conditions ); 
  1956.  
  1957. return $extra_conditions; 
  1958.  
  1959. public function hide_bookings_type_on_tm_dashboard( $types ) { 
  1960. unset( $types[ 'wc_booking' ] ); 
  1961. return $types; 
  1962.  
  1963. public function show_pointer_info() { 
  1964.  
  1965. $pointer_ui = new WCML_Pointer_UI( 
  1966. sprintf( __( 'You can translate the titles of your custom Resources on the %sWooCommerce product translation page%s', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page=wpml-wcml').'">', '</a>' ),  
  1967. 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-bookings-woocommerce-multilingual/',  
  1968. 'bookings_resources .woocommerce_bookable_resources #message' 
  1969. ); 
  1970.  
  1971. $pointer_ui->show(); 
  1972.  
  1973. $pointer_ui = new WCML_Pointer_UI( 
  1974. sprintf( __( 'You can translate the Person Type Name and Description on the %sWooCommerce product translation page%s', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page=wpml-wcml').'">', '</a>' ),  
  1975. 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-bookings-woocommerce-multilingual/',  
  1976. 'bookings_persons #persons-types>div.toolbar' 
  1977. ); 
  1978.  
  1979. $pointer_ui->show(); 
  1980.  
  1981.  
  1982. public function add_to_cart_sold_individually( $sold_indiv, $cart_item_data, $product_id, $quantity ) { 
  1983.  
  1984. if( isset( $cart_item_data[ 'booking' ] ) ) { 
  1985. $sold_indiv = false; 
  1986. foreach( WC()->cart->cart_contents as $cart_item ) { 
  1987. if( 
  1988. isset( $cart_item[ 'booking' ] ) && isset( $cart_item[ 'booking' ][ '_booking_id' ] ) && 
  1989. $cart_item[ 'booking' ][ '_start_date' ] == $cart_item_data[ 'booking' ][ '_start_date' ] && 
  1990. $cart_item[ 'booking' ][ '_end_date' ] == $cart_item_data[ 'booking' ][ '_end_date' ] && 
  1991. $cart_item[ 'booking' ][ '_booking_id' ] == $cart_item_data[ 'booking' ][ '_booking_id' ] 
  1992. ) { 
  1993. $sold_indiv = true; 
  1994.  
  1995. return $sold_indiv; 
  1996.  
  1997. // unset "bookings" from translatable documents to hide WPML languages section from booking edit page 
  1998. public function filter_translatable_documents( $icl_post_types ) { 
  1999.  
  2000. if( 
  2001. ( isset( $_GET[ 'post' ] ) && get_post_type( $_GET[ 'post' ] ) == 'wc_booking' ) || 
  2002. ( isset( $_GET[ 'post_type' ] ) && $_GET[ 'post_type' ] == 'wc_booking' ) 
  2003. ) { 
  2004. unset( $icl_post_types[ 'wc_booking' ] ); 
  2005.  
  2006. return $icl_post_types; 
  2007.  
  2008. // hide WPML languages links section from bookings list page 
  2009. public function filter_is_translated_post_type( $type ) { 
  2010.  
  2011. if( isset( $_GET[ 'post_type' ] ) && $_GET[ 'post_type' ] == 'wc_booking' ) { 
  2012. return false; 
  2013.  
  2014. return $type; 
  2015.  
  2016. /** 
  2017. * @param int $post_id 
  2018. * @param WP_Post $post 
  2019. * @param bool $update 
  2020. */ 
  2021. public function sync_booking_status( $post_id, $post, $update ) { 
  2022.  
  2023. if( $post->post_type === 'wc_booking' && $update ) { 
  2024.  
  2025. $trid = $this->sitepress->get_element_trid( $post_id, 'post_wc_booking' ); 
  2026. $translations = $this->sitepress->get_element_translations( $trid, 'post_wc_booking' ); 
  2027.  
  2028. foreach( $translations as $translation ) { 
  2029. if( $translation->element_id != $post_id ) { 
  2030. $this->wpdb->update( 
  2031. $this->wpdb->posts,  
  2032. array( 'post_status' => $post->post_status ),  
  2033. array( 'ID' => $translation->element_id ) 
  2034. ); 
  2035.  
  2036.  
  2037.  
  2038.  
  2039.