PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.56
Timetics – Appointment Booking Calendar & Scheduling v1.0.56
1.0.64 1.0.62 1.0.63 1.0.61 1.0.60 1.0.59 1.0.58 1.0.57 1.0.56 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.2 1.0.20 1.0.21 All 65 releases
timetics / core / bookings / hooks.php

hooks.php in Timetics – Appointment Booking Calendar & Scheduling 1.0.56, at core/bookings/hooks.php

426 lines 13.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Booking related hooks
4 *
5 * @package Timetics
6 */
7
8 namespace Timetics\Core\Bookings;
9
10 defined( 'ABSPATH' ) || exit;
11
12 use Timetics\Core\Appointments\Appointment;
13 use Timetics\Core\Emails\Customer_Booking_Reminder_Email;
14 use Timetics\Core\Emails\Staff_Booking_Reminder_Email;
15 use Timetics\Utils\Singleton;
16
17 /**
18 * Class Hooks
19 */
20 class Hooks {
21 use Singleton;
22
23 /**
24 * Initialization
25 *
26 * @return void
27 */
28 public function init() {
29 add_action( 'timetics_after_booking_create', [$this, 'register_schedule'] );
30 add_action( 'init', [$this, 'run_booking_schedule'] );
31 add_action( 'timetics_booking_clear_schedule', [$this, 'clear_booking_schedule'] );
32
33 add_action( 'timetics_after_booking_create', [$this, 'reschedule_booking'], 10, 4 );
34
35 add_action( 'init', [$this, 'register_booking_status'] );
36
37 add_action('woocommerce_before_calculate_totals', [ $this, 'timetics_variation_ticket_total_price' ] );
38
39 add_filter( 'woocommerce_add_cart_item_data', [ $this, 'timetics_add_cart_item_data' ], 10, 2 );
40
41 add_action( 'admin_init', [$this, 'delete_booking_before_paid'] );
42 }
43
44 /**
45 * Register cron job for schedule a reminder email
46 *
47 * @param integer $booking_id
48 *
49 * @return void
50 */
51 public function register_schedule( $booking_id ) {
52 $booking = new Booking( $booking_id );
53
54 $date = $booking->get_start_date();
55 $time = $booking->get_start_time();
56
57 $booking_timestamp = strtotime( $date . ' ' . $time );
58
59 $reminder_time = timetics_get_option( 'remainder_time' );
60
61 if ( ! $reminder_time ) {
62 return;
63 }
64
65 foreach ( $reminder_time as $time ) {
66 $timestamp = null;
67 $duration = $time['duration-time'];
68
69 switch ( $time['custom_duration_type'] ) {
70 case 'min':
71 $timestamp = $duration * 60;
72 break;
73 case 'hour':
74 $timestamp = $duration * 60 * 60;
75 break;
76 case 'day':
77 $timestamp = ( $duration * 24 ) * 60 * 60;
78 break;
79 }
80
81 $timestamp = intval($booking_timestamp)- intval($timestamp);
82
83 if ( ! wp_next_scheduled( 'timetics_booking_remainder_' . $booking_id ) ) {
84 wp_schedule_single_event( $timestamp, 'timetics_booking_remainder_' . $booking_id, [$booking_id] );
85 }
86 }
87 }
88
89 /**
90 * Booking schedule
91 *
92 * @return void
93 */
94 public function run_booking_schedule() {
95 $bookins = Booking::all();
96
97 if ( ! $bookins ) {
98 return;
99 }
100
101 // Run cron action.
102 foreach ( $bookins['items'] as $booking ) {
103 add_action( 'timetics_booking_remainder_' . $booking->ID, [$this, 'send_reminder_email'] );
104 }
105 }
106
107 /**
108 * Send booking reminder email
109 *
110 * @param integer $booking_id
111 *
112 * @return void
113 */
114 public function send_reminder_email( $booking_id ) {
115 $booking_reminder_customer = timetics_get_option( 'booking_reminder_customer' );
116 $booking_reminder_host = timetics_get_option( 'booking_reminder_host' );
117
118 $booking = new Booking( $booking_id );
119
120 if ( $booking_reminder_customer ) {
121 $customer_reminder = new Customer_Booking_Reminder_Email( $booking );
122 $customer_reminder->send();
123 }
124
125 if ( $booking_reminder_host ) {
126 $staff_reminder = new Staff_Booking_Reminder_Email( $booking );
127 $staff_reminder->send();
128 }
129
130 }
131
132 /**
133 * Clear cron job schedule
134 *
135 * @return
136 */
137 public function clear_booking_schedule() {
138 $bookins = Booking::all();
139
140 if ( ! $bookins ) {
141 return;
142 }
143
144 // Run cron action.
145 foreach ( $bookins['items'] as $booking ) {
146 $timestamp = wp_next_scheduled( 'timetics_booking_remainder_' . $booking->ID );
147
148 if ( $timestamp && $timestamp < time() ) {
149 wp_unschedule_event( $timestamp, 'timetics_booking_remainder_' . $booking->ID );
150 }
151 }
152 }
153
154 /**
155 * Update bookked entry if reschedule
156 *
157 * @param integer $booking_id
158 * @param integer $customer_id
159 * @param integer $meeting_id
160 * @param array $data
161 * @param integer $booking_entry
162 *
163 * @return void
164 */
165 public function reschedule_booking( $booking_id, $customer_id, $meeting_id, $data ) {
166 $reschedule = ! empty( $data['reschedule'] ) ? $data['reschedule'] : false;
167 $booking = new Booking( $booking_id );
168 $meeting = new Appointment( $meeting_id );
169 $booking_entry = new Booking_Entry();
170
171 if ( ! $reschedule ) {
172 return;
173 }
174
175 $entries = $booking_entry->find(
176 [
177 'staff_id' => $booking->get_staff_id(),
178 'meeting_id' => $meeting->get_id(),
179 'date' => $booking->get_start_date(),
180 'start' => $booking->get_start_time(),
181 ]
182 );
183
184 if ( ! $entries ) {
185 return;
186 }
187
188 $entry = $booking_entry->first();
189 $booked_seat = ! empty( $booking->get_seat() ) ? $booking->get_seat() : [];
190 $existing_seat = ! empty( $entry->get_seats() ) ? $entry->get_seats() : [];
191
192 if ( 'one-to-one' === strtolower( $meeting->get_type() ) ) {
193 $entry->delete();
194 } else {
195 $booked = intval( $entry->get_booked() ) - 1;
196
197 $entry->update( [
198 'booked' => $booked,
199 'seats' => array_values( array_diff( $existing_seat, $booked_seat ) ),
200 ] );
201 }
202 }
203
204 /**
205 * Register booking statuses
206 *
207 * @return void
208 */
209 public function register_booking_status() {
210 // Define label_count translations for each status
211 $label_counts = array(
212 /* translators: %s: Number of approved bookings */
213 'approved' => _n_noop(
214 'Approved <span class="count">(%s)</span>',
215 'Approved <span class="count">(%s)</span>',
216 'timetics'
217 ),
218
219 /* translators: %s: Number of pending bookings */
220 'pending' => _n_noop(
221 'Pending <span class="count">(%s)</span>',
222 'Pending <span class="count">(%s)</span>',
223 'timetics'
224 ),
225 /* translators: %s: Number of cancelled bookings */
226 'cancel' => _n_noop(
227 'Cancelled <span class="count">(%s)</span>',
228 'Cancelled <span class="count">(%s)</span>',
229 'timetics'
230 ),
231 /* translators: %s: Number of completed bookings */
232 'completed' => _n_noop(
233 'Completed <span class="count">(%s)</span>',
234 'Completed <span class="count">(%s)</span>',
235 'timetics'
236 ),
237 );
238
239 // Register each status
240 foreach ( $label_counts as $status => $label_count ) {
241 register_post_status( $status, array(
242 'public' => true,
243 'exclude_from_search' => false,
244 'show_in_admin_all_list' => false,
245 'show_in_admin_status_list' => false,
246 'label_count' => $label_count,
247 ) );
248 }
249 }
250
251 /**
252 * Delete bookings if unpaid before 30 mins
253 *
254 * @return void
255 */
256 public function delete_booking_before_paid() {
257 $args = [
258 'post_type' => 'timetics-booking',
259 'numberposts' => -1,
260 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Meta query is necessary for filtering bookings by payment method
261 'meta_query' => array(
262 'relation' => 'OR',
263 array(
264 'key' => '_tt_booking_payment_method',
265 'value' => 'stripe',
266 'compare' => '=',
267 ),
268 array(
269 'key' => '_tt_booking_payment_method',
270 'value' => 'paypal',
271 'compare' => '=',
272 ),
273 ),
274 ];
275
276 $bookings = get_posts( $args );
277
278 foreach ( $bookings as $booking ) {
279 $booking = new Booking( $booking->ID );
280
281 if ( 'completed' != $booking->get_status() && $this->is_booking_payment_expire( $booking ) ) {
282 $this->update_booking_entry( $booking->get_id() );
283 }
284 }
285 }
286
287 /**
288 * Check booking payment time expaire or not
289 *
290 * @param Object $booking
291 *
292 * @return bool
293 */
294 public function is_booking_payment_expire( $booking ) {
295 // Booking date and time
296 $post = get_post( $booking->get_id() );
297 $booking_datetime = $post->post_date;
298
299 // Convert the booking date and time to a DateTime object
300 $booking_datetime_object = new \DateTime( $booking_datetime );
301
302 // Calculate 30 minutes from the booking date and time
303 $target_datetime = clone $booking_datetime_object;
304 $target_datetime->modify( '+30 minutes' );
305
306 // Get the current date and time
307 $current_datetime = new \DateTime();
308
309 // Check if 30 minutes have passed
310 if ( $current_datetime > $target_datetime ) {
311 return true;
312 }
313
314 return false;
315 }
316
317 /**
318 * Update booking entry if payment time expire
319 *
320 * @param integer $booking_id
321 *
322 * @return void
323 */
324 public function update_booking_entry( $booking_id ) {
325 $booking = new Booking( $booking_id );
326 $meeting = new Appointment( $booking->get_appointment() );
327
328 if ( ! $booking->is_booking() ) {
329 return false;
330 }
331
332 $current_user_id = get_current_user_id();
333
334 if (
335 $meeting->is_appointment()
336 && ! user_can( $current_user_id, 'manage_options' )
337 && $meeting->get_author() != $current_user_id
338 ) {
339 $data = [
340 'success' => 0,
341 'message' => __( 'You are not allowed to delete this booking.', 'timetics' ),
342 ];
343
344 return new \WP_HTTP_Response( $data, 403 );
345 }
346
347 $booking_entry = new Booking_Entry();
348
349 $date_time = timetics_convert_timezone( $booking->get_start_date() . ' ' . $booking->get_start_time(), $booking->get_timezone(), $meeting->get_timezone() );
350
351 $entries = $booking_entry->find(
352 [
353 'staff_id' => $booking->get_staff_id(),
354 'meeting_id' => $booking->get_appointment(),
355 'date' => $date_time->format( 'Y-m-d' ),
356 'start' => $date_time->format( 'h:i a' ),
357 ]
358 );
359
360 if ( $entries ) {
361 $entry = $booking_entry->first();
362
363 if ( 'one-to-one' == strtolower( $meeting->get_type() ) ) {
364 $entry->delete();
365 } else {
366 $booked = intval( $entry->get_booked() ) - 1;
367 $booked_seat = ! empty( $booking->get_seat() ) ? $booking->get_seat() : [];
368 $existing_seat = ! empty( $entry->get_seats() ) ? $entry->get_seats() : [];
369
370 $entry->update( [
371 'booked' => $booked,
372 'seats' => array_values( array_diff( $existing_seat, $booked_seat ) ),
373 ] );
374 }
375 }
376 }
377
378 /**
379 * Change price for cart item
380 */
381 public function timetics_variation_ticket_total_price( $cart_object ) {
382 foreach ( $cart_object->cart_contents as $key => $value ) {
383 if ( ! empty( $value['booking_id'] ) && $value['booking_id'] !== 0 ) {
384 $order_total = !empty( $value['_timetics_variation_total_price'] ) ? $value['_timetics_variation_total_price'] : 0;
385
386 $value['data']->get_price();
387 $value['data']->set_price($order_total);
388 $value['data']->set_regular_price($order_total);
389 $value['data']->set_sale_price($order_total);
390
391 }
392 }
393
394 }
395
396 /**
397 * add booking_id as cart item data
398 *
399 * @param integer $booking_id
400 *
401 * @return void
402 */
403 public function timetics_add_cart_item_data( $cart_item_data ) {
404 $session_data = WC()->session->get( 'timetics_data' );
405 $booking_id = $session_data['booking_id'];
406 $booking = new Booking( $booking_id );
407 $total_price = floatval($booking->get_total()); // Ensure $total_price is a float
408
409 if ( is_array( $booking->get_seat() ) ) {
410 $total_quantity = count( $booking->get_seat() );
411 } else {
412 $total_quantity = 1;
413 }
414
415 if( ! empty( $booking_id ) && $total_price !== 0 ) {
416 $cart_item_data['_timetics_variation_total_quantity'] = $total_quantity;
417 $cart_item_data['booking_id'] = $booking_id;
418
419 // For balancing the cart item price
420 $cart_item_data['_timetics_variation_total_price'] = $total_price / $total_quantity;
421 }
422
423 return $cart_item_data;
424 }
425 }
426