PluginProbe
Booking Calendar / 11.8.2
Booking Calendar v11.8.2
11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 10.11.2 10.11.3 All 202 releases
← All changes | core/wpbc-dates.php +99 -27 11.211.8.2 View file →
@@ -1,4 +1,4 @@
1 1 <?php
2 2 /**
3 3 * @version 1.0
4 4 * @package Booking Calendar
@@ -135,10 +135,40 @@
135 135 return $time_m_h . ':' . $time_m_m;
136 136 }
137 137
138 138
139 -/**
140 - * Get Times from booking Form, if these times fields exist
139 +/**
140 + * Parse a duration field value into numeric hours and minutes.
141 + *
142 + * Duration values come from serialized front-end form data. Placeholder or
143 + * otherwise malformed values must not reach arithmetic because PHP 8 throws
144 + * a TypeError when a non-numeric string is multiplied by an integer.
145 + *
146 + * @param string $duration_time_value Duration in `HH:MM` format.
147 + *
148 + * @return array|false Numeric hours and minutes, or false for an invalid duration.
149 + */
150 +function wpbc_parse_duration_time_value( $duration_time_value ) {
151 +
152 + $duration_time_value = trim( (string) $duration_time_value );
153 +
154 + if ( ! preg_match( '/^([0-9]+):([0-9]{1,2})$/', $duration_time_value, $duration_time_matches ) ) {
155 + return false;
156 + }
157 +
158 + $duration_hours = intval( $duration_time_matches[1] );
159 + $duration_minutes = intval( $duration_time_matches[2] );
160 +
161 + if ( 59 < $duration_minutes ) {
162 + return false;
163 + }
164 +
165 + return array( $duration_hours, $duration_minutes );
166 +}
167 +
168 +
169 +/**
170 + * Get Times from booking Form, if these times fields exist
141 171 *
142 172 * @param type $booking_form_data
143 173 * @param type $booking_type
144 174 * @return mixed
@@ -233,34 +263,36 @@
233 263 } else {
234 264 $end_time = explode( ':', $end_time );
235 265 }
236 266
237 - if ( strpos( $booking_form_data, 'durationtime' . $booking_type ) !== false ) { // Get END TIME From form request
238 - $pos1 = strpos( $booking_form_data, 'durationtime' . $booking_type ); // Find start time pos
239 - $pos1 = strpos( $booking_form_data, '^', $pos1 ) + 1; // Find TIME pos
240 - $pos2 = strpos( $booking_form_data, '~', $pos1 ); // Find TIME length
267 + if ( strpos( $booking_form_data, 'durationtime' . $booking_type ) !== false ) { // Get END TIME From form request
268 + $pos1 = strpos( $booking_form_data, 'durationtime' . $booking_type ); // Find start time pos
269 + $pos1 = strpos( $booking_form_data, '^', $pos1 ) + 1; // Find TIME pos
270 + $pos2 = strpos( $booking_form_data, '~', $pos1 ); // Find TIME length
241 271 if ( $pos2 === false ) {
242 272 $pos2 = strlen( $booking_form_data );
243 273 }
244 - $pos2 = $pos2 - $pos1;
245 - $end_time = substr( $booking_form_data, $pos1, $pos2 );
274 + $pos2 = $pos2 - $pos1;
275 + $duration_time_value = substr( $booking_form_data, $pos1, $pos2 );
276 + $duration_time_parts = wpbc_parse_duration_time_value( $duration_time_value );
277 +
278 + if ( false !== $duration_time_parts ) {
279 + $is_time_exist = true;
280 +
281 + // Get the selected start time and add the validated duration to calculate the end time.
282 + $new_end_time = mktime( intval( $start_time[0] ), intval( $start_time[1] ) );
283 + $new_end_time += $duration_time_parts[0] * 60 * 60;
284 + $new_end_time += $duration_time_parts[1] * 60;
285 + $end_time = gmdate( 'H:i', $new_end_time );
286 +
287 + if ( '00:00' === $end_time ) {
288 + $end_time = '23:59';
289 + }
290 + $end_time = explode( ':', $end_time );
291 + $end_time[2] = '02';
292 + }
293 + }
246 294
247 - $is_time_exist = true;
248 -
249 - $end_time = explode( ':', $end_time );
250 -
251 - // Here we are get start time and add duration for end time
252 - $new_end_time = mktime( intval( $start_time[0] ), intval( $start_time[1] ) );
253 - $new_end_time = $new_end_time + $end_time[0] * 60 * 60 + $end_time[1] * 60;
254 - $end_time = gmdate( 'H:i', $new_end_time );
255 -
256 - if ( $end_time == '00:00' ) {
257 - $end_time = '23:59';
258 - }
259 - $end_time = explode( ':', $end_time );
260 - $end_time[2] = '02';
261 - }
262 -
263 295 }
264 296
265 297 if ( $is_time_exist ) {
266 298 return array( $start_time, $end_time );
@@ -651,9 +683,9 @@
651 683 *
652 684 * @param string $some_day : '2015-05-29'
653 685 * @return boolean : true | false
654 686 */
655 -function wpbc_is_date_in_past( $some_day ) {
687 +function wpbc_is_date_in_past( $some_day ) {
656 688
657 689 $some_day_d = gmdate( 'm.d.Y', mysql2date( 'U', $some_day ) );
658 690 $some_array = explode( '.', $some_day_d );
659 691 $some_day = mktime( 0, 0, 0, intval($some_array[0]), ( intval($some_array[1]) + 1 ), intval($some_array[2]) );
@@ -664,9 +696,49 @@
664 696 return true;
665 697 } else {
666 698 return false;
667 699 }
668 -}
700 +}
701 +
702 +
703 +/**
704 + * Check whether a booking can still be changed by a visitor.
705 + *
706 + * Visitor edit and cancellation actions must fail closed when the booking does
707 + * not exist, is in the trash, has no dates, or its final booked date has
708 + * already passed. The comparison deliberately uses wpbc_is_date_in_past() so
709 + * the rule remains compatible with the established date-based front-end edit
710 + * restriction and does not unexpectedly expire time-slot bookings mid-day.
711 + *
712 + * @param int $booking_id Booking ID resolved from a verified visitor hash.
713 + *
714 + * @return bool True when at least one booked date is current or future.
715 + */
716 +function wpbc_is_visitor_booking_action_allowed( $booking_id ) {
717 + global $wpdb;
718 +
719 + $booking_id = absint( $booking_id );
720 + if ( empty( $booking_id ) ) {
721 + return false;
722 + }
723 +
724 + $last_booking_date = $wpdb->get_var(
725 + $wpdb->prepare(
726 + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
727 + "SELECT MAX(dt.booking_date)
728 + FROM {$wpdb->prefix}bookingdates AS dt
729 + INNER JOIN {$wpdb->prefix}booking AS bk ON bk.booking_id = dt.booking_id
730 + WHERE bk.booking_id = %d AND bk.trash = 0",
731 + $booking_id
732 + )
733 + ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
734 +
735 + if ( empty( $last_booking_date ) || ! is_string( $last_booking_date ) ) {
736 + return false;
737 + }
738 +
739 + return ! wpbc_is_date_in_past( $last_booking_date );
740 +}
669 741
670 742
671 743 /**
672 744 * Check if the booking was made without calendar ( no booking date submited.)
@@ -1009,5 +1081,5 @@
1009 1081
1010 1082 }
1011 1083
1012 1084 return $days_availability;
1013 - }
1085 + }