PluginProbe
Booking Calendar / 10.1.3
Booking Calendar v10.1.3
11.8.3 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 All 203 releases
booking / includes / page-availability / availability__resource.php

availability__resource.php in Booking Calendar 10.1.3, at includes/page-availability/availability__resource.php

484 lines 20.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @version 1.0
4 * @package Booking Calendar
5 * @category Resource Availability - define "unavailable" "date_status" in "wp_booking_dates_props" table.
6 * @author wpdevelop
7 *
8 * @web-site https://wpbookingcalendar.com/
9 * @email info@wpbookingcalendar.com
10 * @modified 2022-11-23
11 *
12 */
13
14 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
15
16
17 /**
18 * Get unavailable dates for the booking resource. Based on 'resource availability' - new Availability UI.
19 *
20 * @param int $resource_id
21 *
22 * @return array|object|stdClass[]|null
23 */
24 function wpbc_resource__get_unavailable_dates( $resource_id = 1 ){
25
26 $resource_id = intval( $resource_id );
27 if ( empty( $resource_id ) ) {
28 $resource_id = 1;
29 }
30
31 $resource_availability = wpbc_availability__get_dates_status__sql( array(
32 'calendar_date' => 'CURDATE', // 'CURDATE' | 'ALL'
33 'prop_name' => 'date_status', // 'rate', 'allow_start_day_selection', 'allow_days_number_to_select', 'availability_count', ...
34 'prop_value' => 'unavailable', // 'unavailable', 'available', 'pending', 'approved'
35 'resource_id' => intval( $resource_id ) // int or dcv
36 ) );
37
38 $unavailable__dates_y_m_d__arr = array();
39
40 foreach ( $resource_availability as $unavailable_db_obj ) {
41 list( $date_y_m_d, $time_his ) = explode( ' ', $unavailable_db_obj->calendar_date );
42 $unavailable__dates_y_m_d__arr[] = $date_y_m_d;
43 }
44
45 return $unavailable__dates_y_m_d__arr;
46 }
47
48
49 /**
50 * Get unavailable dates for array of booking resources
51 *
52 * @param array $resource_id_arr // [1, 13, 8, 6, 7]
53 * @param mixed $search_dates // 'CURDATE' | 'ALL' | [ "2023-08-03" , "2023-08-04" , "2023-08-05" ]
54 *
55 * @return array - array of unavailable dates: array( resource_A_ID => array( DATES_Y_M_D, .... ),
56 resource_B_ID => array( DATES_Y_M_D, .... ), ...
57 Example:
58 array( 1 => array( "2023-08-03" , "2023-08-04" ),
59 8 => array( "2023-08-03" ), ...
60 */
61 function wpbc_for_resources_arr__get_unavailable_dates( $resource_id_arr, $search_dates = 'CURDATE' ) { //FixIn: 9.7.3.11
62
63 // Booking resources -----------------------------------------------------------------------------------------------
64 $resource_id_csd = implode( ',', $resource_id_arr ); // '9,13,5,6,7,1,2,10,11,12,3,4,8'
65
66 // Dates -----------------------------------------------------------------------------------------------------------
67 if ( is_array( $search_dates ) ) { // Array of dates: ["2023-08-03"]
68
69 foreach ( $search_dates as $date_ymd ) {
70 $search_dates_arr[] = $date_ymd . ' 00:00:00';
71 }
72 $search_dates_formated = implode( ',', $search_dates_arr );
73
74 } else { // Probably 'CURDATE' | 'ALL'
75
76 $search_dates_formated = ( in_array( $search_dates, array( 'ALL', 'CURDATE' ) ) )
77 ? $search_dates
78 : 'CURDATE' ;
79 }
80
81 // Unavailable objects ---------------------------------------------------------------------------------------------
82 $resource_availability = wpbc_availability__get_dates_status__sql( array(
83 'calendar_date' => $search_dates_formated, // 'CURDATE' | 'ALL'
84 'prop_name' => 'date_status', // 'rate', 'allow_start_day_selection', 'allow_days_number_to_select', 'availability_count', ...
85 'prop_value' => 'unavailable', // 'unavailable', 'available', 'pending', 'approved'
86 'resource_id' => $resource_id_csd // int or dcv
87 ) );
88
89 // Formatted array of unavailable booking resource dates ----------------------------------------------------------
90 $resource_unavailable_dates_arr = array();
91 foreach ( $resource_availability as $resource_unavailable_obj ) {
92
93 if ( ! isset( $resource_unavailable_dates_arr[ $resource_unavailable_obj->resource_id ] ) ) {
94 $resource_unavailable_dates_arr[ $resource_unavailable_obj->resource_id ] = array();
95 }
96 $calendar_date = explode( ' ', $resource_unavailable_obj->calendar_date );
97 $resource_unavailable_dates_arr[ $resource_unavailable_obj->resource_id ][] = $calendar_date[0];
98 }
99
100 return $resource_unavailable_dates_arr;
101 }
102
103
104 /**
105 * Get dates status of specific booking resource
106 *
107 * @param array $params = array(
108 'prop_name' => 'date_status', // 'rate', 'allow_start_day_selection', 'allow_days_number_to_select', 'availability_count', ...
109 'prop_value' => 'unavailable', // 'unavailable', 'available', 'pending', 'approved'
110 'resource_id' => 1 // int or dcv
111 )
112 *
113 * booking date property can be relative to: prop_name = 'date_status', 'rate', 'allow_start_day_selection', 'allow_days_number_to_select', 'availability_count', ...
114 *
115 * prop_name = 'date_status' -> prop_value = 'unavailable', 'available', 'pending', 'approved'
116 *
117 * @return array of DB objects array(
118 0 = {stdClass} {
119 ->booking_dates_prop_id = "1"
120 ->resource_id = "4"
121 ->calendar_date = "2023-04-04 00:00:00"
122 ->prop_name = "date_status"
123 ->prop_value = "unavailable"
124 }
125 , ... )
126 *
127 * Example:
128 wpbc_availability__get_dates_status__sql( array(
129 'calendar_date' => 'CURDATE', // 'CURDATE' | 'ALL' | '2023-07-15 00:00:00,2023-07-21 00:00:00'
130 'prop_name' => 'date_status', // 'rate', 'allow_start_day_selection', 'allow_days_number_to_select', 'availability_count', ...
131 'prop_value' => 'unavailable', // 'unavailable', 'available', 'pending', 'approved'
132 'resource_id' => 1 // int or dcv
133 ) );
134 */
135 function wpbc_availability__get_dates_status__sql( $params ){
136
137 // CACHE - GET :: check if such request was cached and get it ----------------------------------------------- //FixIn: 9.7.3.14
138 $params_for_cache_key = $params;
139 if ( isset( $params_for_cache_key['resource_id'] ) ) {
140 $params_for_cache_key['resource_id'] = (string) $params_for_cache_key['resource_id'];
141 }
142 $params_for_cache = maybe_serialize( $params_for_cache_key );
143 $cache_result = wpbc_cache__get( 'wpbc_availability__get_dates_status__sql', $params_for_cache );
144 if ( ! is_null( $cache_result ) ) {
145 return $cache_result;
146 }
147 // -----------------------------------------------------------------------------------------------------------------
148
149
150 $defaults = array(
151 'calendar_date' => 'CURDATE', // 'CURDATE' | 'ALL' | '2023-07-15 00:00:00,2023-07-21 00:00:00' //FixIn: 9.7.3.11
152 'prop_name' => 'date_status', // 'rate', 'allow_start_day_selection', 'allow_days_number_to_select', 'availability_count', ...
153 'prop_value' => 'unavailable', // 'unavailable', 'available', 'pending', 'approved'
154 'resource_id' => 1 // int or dcv
155 );
156 $params = wp_parse_args( $params, $defaults );
157
158 // S a n i t i z e
159 $params_rules = array(
160 'calendar_date' => array( 'validate' => 's', 'default' => 'CURDATE' ) , // array( 'validate' => array( 'CURDATE', 'ALL' ), 'default' => 'CURDATE' ) ,
161 'prop_name' => array( 'validate' => 's', 'default' => 'date_status' ) ,
162 'prop_value' => array( 'validate' => 's', 'default' => 'unavailable' ) ,
163 'resource_id' => array( 'validate' => 'digit_or_csd', 'default' => 1 )
164 );
165 $params = wpbc_sanitize_params_in_arr( $params, $params_rules );
166 /**
167
168 $params['resource_id'] = ( '' != $params['resource_id'] ) ? wpbc_sanitize_digit_or_csd( $params['resource_id'] ) : 1;
169 $params['prop_name'] = wpbc_sanitize_text( $params['prop_name'] );
170 $params['prop_value'] = wpbc_sanitize_text( $params['prop_value'] );
171 */
172
173
174 // S Q L
175 global $wpdb;
176 $sql = array();
177 $sql_args = array();
178
179
180 $sql['start_select'] = "SELECT * "; // "SELECT DISTINCT calendar_date ";
181 $sql['from'] = "FROM {$wpdb->prefix}booking_dates_props ";
182
183 // W H E R E
184 $sql['where'] = 'WHERE ( 1 = 1 ) ';
185 $sql['where'] .= " AND resource_id IN ( {$params['resource_id']} ) ";
186
187 if ( '' != $params['calendar_date'] ) {
188
189 //FixIn: 9.7.3.11
190 if ( 'ALL' == $params['calendar_date'] ) {
191 // All dates
192 } else if ( 'CURDATE' == $params['calendar_date'] ) {
193
194 $sql['where'] .= " AND calendar_date >= CURDATE() "; // Current dates
195
196 } else { // Specific Date(s)
197
198 if ( false === strpos( $params['calendar_date'], ',' ) ) { // One date: - '2023-07-15 00:00:00'
199
200 $sql['where'] .= " AND ( calendar_date = %s ) ";
201 $sql_args[] = $params['calendar_date'];
202 } else { // Comma seperated dates: - '2023-07-15 00:00:00, 2023-07-16 00:00:00'
203
204 $dates_arr = explode( ',', $params['calendar_date'] );
205 $in_search_arr = array();
206 foreach ( $dates_arr as $date_ymd ) {
207 $in_search_arr[] = '%s';
208 $sql_args[] = $date_ymd;
209 }
210 $in_search_dates_csv = implode( ',', $in_search_arr );
211 $sql['where'] .= " AND calendar_date IN ( {$in_search_dates_csv} ) ";
212 }
213 }
214 }
215
216 if ( '' != $params['prop_name'] ) {
217 $sql['where'] .= " AND ( prop_name = %s ) ";
218 $sql_args[] = $params['prop_name'];
219 }
220
221 if ( '' != $params['prop_value'] ) {
222 $sql['where'] .= " AND ( prop_value = %s ) ";
223 $sql_args[] = $params['prop_value'];
224 }
225
226 // O R D E R
227 $sql['order'] = " ORDER BY calendar_date";
228
229 // L I M I T
230 $sql['limit'] = '';
231 /**
232 * $sql['limit'] = " LIMIT %d, %d ";
233 $sql_args[] = ( $params['page_num'] - 1 ) * $params['page_items_count'];
234 $sql_args[] = $params['page_items_count'];
235 */
236
237
238
239 /**
240 * Good Practice: https://blog.ircmaxell.com/2017/10/disclosure-wordpress-wpdb-sql-injection-technical.html
241 *
242 $sql['where'] .= "( bk.form LIKE %s ) ";
243 $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%';
244
245 if ( is_numeric( $params['keyword'] ) ) {
246 $sql['where'] .= " OR ( bk.booking_id = %d ) ";
247 $sql_args[] = intval( $params['keyword'] );
248 }
249 *
250 */
251 $sql_prepared = $wpdb->prepare(
252 $sql['start_select']
253 . $sql['from']
254 . $sql['where']
255 . $sql['order']
256 . $sql['limit']
257 , $sql_args
258 );
259
260 $bookings_sql_obj = $wpdb->get_results($sql_prepared);
261
262 // CACHE - SAVE :: ------------------------------------------------------------------------------------------------
263 $cache_result = wpbc_cache__save( 'wpbc_availability__get_dates_status__sql', $params_for_cache, $bookings_sql_obj );
264
265 return $bookings_sql_obj;
266 /*
267 "CREATE TABLE {$wpdb->prefix}booking_dates_props (
268 booking_dates_prop_id bigint(20) unsigned NOT NULL auto_increment,
269 resource_id bigint(10) NOT NULL default 1,
270 calendar_date datetime NOT NULL default '0000-00-00 00:00:00',
271 prop_name varchar(200) NOT NULL default '',
272 prop_value text,
273 PRIMARY KEY (booking_dates_prop_id)
274 )";
275 */
276 }
277
278
279 /**
280 * Update dates status
281 *
282 * @param $params array(
283 'resource_id' => 1, // int
284 'prop_name' => 'date_status', // 'rate', 'allow_start_day_selection', 'allow_days_number_to_select', 'availability_count', ...
285 'prop_value' => 'unavailable', // 'available', 'unavailable' , 'pending', 'approved'
286 'dates_selection' => '' // '2023-04-04 | 2023-04-07'
287
288 )
289 *
290 * @return bool|int - return how many DB rows affected -how many dates processed
291 */
292 function wpbc_availability__update_dates_status__sql( $params ){
293
294 $defaults = array(
295 'resource_id' => 1, // int
296 'prop_name' => 'date_status', // 'rate', 'allow_start_day_selection', 'allow_days_number_to_select', 'availability_count', ...
297 'prop_value' => 'unavailable', // 'available', 'unavailable' , 'pending', 'approved'
298 'dates_selection' => '' // '2023-04-04 | 2023-04-07'
299
300 );
301 $params = wp_parse_args( $params, $defaults );
302
303 // S a n i t i z e
304 $params_rules = array(
305 'dates_selection' => array( 'validate' => 's', 'default' => '' ) ,
306 'prop_name' => array( 'validate' => 's', 'default' => 'date_status' ) ,
307 'prop_value' => array( 'validate' => 's', 'default' => 'unavailable' ) ,
308 'resource_id' => array( 'validate' => 'digit_or_csd', 'default' => 1 )
309 );
310 $params = wpbc_sanitize_params_in_arr( $params, $params_rules );
311
312
313 if ( false !== strpos( $params['dates_selection'], '~' ) ) { // Range Days
314
315 $dates_arr = wpbc_get_dates_arr__from_dates_range( array(
316 'dates_separator' => ' ~ ', // ' ~ '
317 'dates' => $params['dates_selection'], // '2023-04-04 ~ 2023-04-07'
318 ) );
319
320 } else { // Multiple Days
321 $dates_arr = wpbc_get_dates_arr__from_dates_comma_separated( array(
322 'dates_separator' => ', ', // ', '
323 'dates' => $params['dates_selection'], // '2023-04-04 ~ 2023-04-07'
324 ) );
325 }
326
327 $row_number = false;
328
329 if ( ! empty( $dates_arr ) ) {
330
331 global $wpdb;
332
333 // Remove dates ------------------------------------------------------------------------------------------------
334
335 // "DELETE FROM {$wpdb->prefix}booking_dates_props WHERE resource_id = %d AND prop_name = %s AND ( calendar_date = %s OR calendar_date = %s )"
336 $sql = "DELETE FROM {$wpdb->prefix}booking_dates_props WHERE resource_id = %d AND prop_name = %s ";
337
338 $sql_args = array();
339 $sql_args[] = $params['resource_id'];
340 $sql_args[] = $params['prop_name'];
341
342 $sub_sql = array();
343 foreach ( $dates_arr as $calendar_date ) {
344
345 $sub_sql[] = 'calendar_date = %s';
346 $sql_args[] = $calendar_date . ' 00:00:00';
347 }
348 if ( count( $sub_sql ) > 0 ) {
349 $sql .= ' AND ( ';
350 $sub_sql = implode( ' OR ', $sub_sql );
351 $sql .= $sub_sql;
352 $sql .= " )";
353 }
354
355 $sql_prepared = $wpdb->prepare( $sql, $sql_args );
356 $row_number = $wpdb->query( $sql_prepared );
357
358
359 // If we set the dates as 'available', then we skip INSERT into DB, because previously we have already deleted all 'unavailable' dates status for such dates
360 if ( ( 'date_status' == $params['prop_name'] ) && ( 'available' == $params['prop_value'] ) ) {
361 return $row_number;
362 }
363
364 // Insert new dates ------------------------------------------------------------------------------------------------
365 $sql_args = array();
366
367 $sql = "INSERT INTO {$wpdb->prefix}booking_dates_props ( resource_id, calendar_date, prop_name, prop_value) VALUES ";
368
369 $sub_sql = array();
370 foreach ( $dates_arr as $calendar_date ) {
371
372 $sub_sql[] = "( %d, %s, %s, %s )";
373 $sql_args[] = $params['resource_id'];
374 $sql_args[] = $calendar_date . ' 00:00:00';
375 $sql_args[] = $params['prop_name'];
376 $sql_args[] = $params['prop_value'];
377 }
378
379 $sub_sql = implode( ',', $sub_sql );
380 $sql .= $sub_sql;
381
382 $sql_prepared = $wpdb->prepare( $sql, $sql_args );
383 $row_number = $wpdb->query( $sql_prepared );
384 }
385
386 return $row_number;
387 }
388
389
390 /**
391 * Delete the dates status from DB - erase availability
392 *
393 * @param array $params array(
394 'resource_id' => 1, // int
395 'prop_name' => 'date_status', // 'rate', 'allow_start_day_selection', 'allow_days_number_to_select', 'availability_count', ...
396 'prop_value' => 'unavailable', // 'available', 'unavailable' , 'pending', 'approved'
397 'dates_selection' => 'all' // '2023-04-04 ~ 2023-04-07'
398
399 )
400 *
401 * @return bool|int - count of deleted rows or false if operation was not applied
402 *
403 * Examples:
404 * wpbc_availability__delete_dates_status__sql(array( 'resource_id' => 1 ));
405 * wpbc_availability__delete_dates_status__sql(array( 'resource_id' => 1, 'prop_name' => 'date_status' ))
406 * wpbc_availability__delete_dates_status__sql(array( 'resource_id' => 1, 'prop_name' => 'date_status', 'dates_selection' => 'all' ))
407 * wpbc_availability__delete_dates_status__sql(array( 'resource_id' => 1, 'prop_name' => 'date_status', 'dates_selection' => '2023-04-04 ~ 2023-04-07' ))
408 * wpbc_availability__delete_dates_status__sql(array( 'resource_id' => 1, 'prop_name' => 'date_status', 'dates_selection' => '2023-04-04, 2023-04-07, 2023-04-05' ))
409 */
410 function wpbc_availability__delete_dates_status__sql( $params ){
411
412 $defaults = array(
413 'resource_id' => 1, // int
414 'prop_name' => 'date_status', // 'rate', 'allow_start_day_selection', 'allow_days_number_to_select', 'availability_count', ...
415 'prop_value' => 'unavailable', // 'available', 'unavailable' , 'pending', 'approved'
416 'dates_selection' => 'all' // '2023-04-04 ~ 2023-04-07'
417
418 );
419 $params = wp_parse_args( $params, $defaults );
420
421 // S a n i t i z e
422 $params_rules = array(
423 'dates_selection' => array( 'validate' => 's', 'default' => '' ) ,
424 'prop_name' => array( 'validate' => 's', 'default' => 'date_status' ) ,
425 'prop_value' => array( 'validate' => 's', 'default' => 'unavailable' ) ,
426 'resource_id' => array( 'validate' => 'digit_or_csd', 'default' => 1 )
427 );
428 $params = wpbc_sanitize_params_in_arr( $params, $params_rules );
429
430
431
432 if ( 'all' === $params['dates_selection'] ) { // All Dates
433
434 $dates_arr = array();
435
436 } elseif ( false !== strpos( $params['dates_selection'], '~' ) ) { // Range Days
437
438 $dates_arr = wpbc_get_dates_arr__from_dates_range( array(
439 'dates_separator' => ' ~ ', // ' ~ '
440 'dates' => $params['dates_selection'], // '2023-04-04 ~ 2023-04-07'
441 ) );
442
443 } else { // Multiple Days
444 $dates_arr = wpbc_get_dates_arr__from_dates_comma_separated( array(
445 'dates_separator' => ', ', // ', '
446 'dates' => $params['dates_selection'], // '2023-04-04, 2023-04-07, 2023-04-05'
447 ) );
448 }
449
450 $row_number = false;
451
452 global $wpdb;
453
454 // Remove dates ------------------------------------------------------------------------------------------------
455
456 // "DELETE FROM {$wpdb->prefix}booking_dates_props WHERE resource_id = %d AND prop_name = %s AND ( calendar_date = %s OR calendar_date = %s )"
457 $sql = "DELETE FROM {$wpdb->prefix}booking_dates_props WHERE resource_id = %d AND prop_name = %s ";
458
459 $sql_args = array();
460 $sql_args[] = $params['resource_id'];
461 $sql_args[] = $params['prop_name'];
462
463 // If we transfer here dates, instead of 'all', then we delete only such specific dates status from DB
464 if ( ! empty( $dates_arr ) ) {
465 $sub_sql = array();
466 foreach ( $dates_arr as $calendar_date ) {
467
468 $sub_sql[] = 'calendar_date = %s';
469 $sql_args[] = $calendar_date . ' 00:00:00';
470 }
471 if ( count( $sub_sql ) > 0 ) {
472 $sql .= ' AND ( ';
473 $sub_sql = implode( ' OR ', $sub_sql );
474 $sql .= $sub_sql;
475 $sql .= " )";
476 }
477 }
478
479 $sql_prepared = $wpdb->prepare( $sql, $sql_args );
480 $row_number = $wpdb->query( $sql_prepared );
481
482 return $row_number;
483 }
484