PluginProbe
Booking Calendar / 11.8.3
Booking Calendar v11.8.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
← All changes | core/admin/wpbc-sql.php +255 -76 10.10.211.8.3 View file →
@@ -1,4 +1,4 @@
1 1 <?php /**
2 2 * @version 1.0
3 3 * @package Booking Calendar
4 4 * @category Data Engine for Booking Listing / Calendar Overview pages
@@ -24,16 +24,22 @@
24 24
25 25 if ( wpbc_is_bookings_page() ) { // We are inside of this page. Menu item selected.
26 26
27 27 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
28 - if ( ( isset( $_REQUEST['view_mode'] ) ) && ( 'vm_booking_listing' === $_REQUEST['view_mode'] ) ) { //FixIn: 9.2.0
28 + $requested_tab = isset( $_REQUEST['tab'] ) ? sanitize_key( wp_unslash( $_REQUEST['tab'] ) ) : '';
29 + if ( ( '' !== $requested_tab ) && ( ! in_array( $requested_tab, array( 'vm_booking_listing', 'vm_calendar' ), true ) ) ) { // FixIn: Add Booking lives as its own Bookings tab.
29 30 return;
30 31 }
31 32
33 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
34 + if ( 'vm_booking_listing' === $requested_tab ) { //FixIn: 9.2.0
35 + return;
36 + }
37 +
32 38 $booking_default_view_mode = wpbc_get_default_saved_view_mode_for_wpbc_page();
33 39 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
34 - if ( ! isset( $_REQUEST['view_mode'] ) ) {
35 - $_REQUEST['view_mode'] = $booking_default_view_mode; // Set to REQUEST
40 + if ( ! isset( $_REQUEST['tab'] ) ) {
41 + $_REQUEST['tab'] = $booking_default_view_mode; // Set to REQUEST
36 42 }
37 43
38 44 // Get saved filters set, (if its not set in request yet), like "tab" & "view_mode" and overload $_REQUEST
39 45 wpbc_set_default_saved_params_to_request_for_booking_listing( 'default' );
@@ -53,21 +59,22 @@
53 59 */
54 60 function wpbc_get_default_saved_view_mode_for_wpbc_page() {
55 61
56 62 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
57 - if ( ! isset( $_REQUEST['view_mode'] ) ) {
63 + if ( ! isset( $_REQUEST['tab'] ) ) {
58 64 $booking_default_view_mode = get_bk_option( 'booking_listing_default_view_mode' );
59 65 } else {
60 - $booking_default_view_mode = sanitize_text_field( wp_unslash( $_REQUEST['view_mode'] ) ); /* phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing */ /* FixIn: sanitize_unslash */
66 + $booking_default_view_mode = sanitize_text_field( wp_unslash( $_REQUEST['tab'] ) ); /* phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing */ /* FixIn: sanitize_unslash */
61 67 }
62 -//$booking_default_view_mode='vm_listing'; //TODO:2023-05-20 remove it!!!!!!
63 - if ( ! in_array( $booking_default_view_mode, array( 'vm_calendar', 'vm_booking_listing' ) ) ) { //FixIn: 9.2.1 // FixIn: 9.6.3.5.
64 - $booking_default_view_mode = 'vm_booking_listing';
68 +
69 + // TODO:2023-05-20 remove it!!. 'vm_booking_listing';.
70 + if ( ! in_array( $booking_default_view_mode, array( 'vm_calendar', 'vm_booking_listing' ), true ) ) {
71 + $booking_default_view_mode = 'vm_booking_listing'; // FixIn: 9.2.1 // FixIn: 9.6.3.5.
65 72 }
66 73
67 - $booking_default_view_mode = ( 'vm_listing' == $booking_default_view_mode ) ? 'vm_booking_listing' : $booking_default_view_mode; // FixIn: 9.6.3.5.
74 + $booking_default_view_mode = ( 'vm_listing' === $booking_default_view_mode ) ? 'vm_booking_listing' : $booking_default_view_mode; // FixIn: 9.6.3.5.
68 75
69 - return $booking_default_view_mode; // 'vm_calendar' / 'vm_booking_listing' ;
76 + return $booking_default_view_mode; // 'vm_calendar' / 'vm_booking_listing'.
70 77 }
71 78
72 79
73 80 /**
@@ -77,49 +84,41 @@
77 84 *
78 85 * @param string $filter_name - name of saved filter set. Currntly is using only one "Default"
79 86 */
80 87 function wpbc_set_default_saved_params_to_request_for_booking_listing( $filter_name ) {
81 -//debuge($_REQUEST);
82 - // Exclude some parameters from the saved Default parameters - the values of these parameters are loading from General Booking Settings page or from the request.
83 - $exclude_options_from_saved_params = array(
84 - 'tab' // Default
85 - , 'page' // From plugin
86 - , 'view_mode' // Default
87 - , 'wh_booking_type' // Default
88 - , 'view_days_num' // Default
89 - , 'blank_field__this_field_only_for_formatting_buttons' // Skip this, this parameter for formating purpose in toolbar
90 - );
91 - $wpdevbk_filter_params = array();
92 88
89 + // Exclude some parameters from the saved Default parameters - the values of these parameters are loading from General Booking Settings page or from the request.
90 + $exclude_options_from_saved_params = array(
91 + 'tab', // Default.
92 + 'page', // From plugin.
93 + 'wh_booking_type', // Default.
94 + 'view_days_num', // Default.
95 + 'blank_field__this_field_only_for_formatting_buttons', // Skip this, this parameter for formating purpose in toolbar.
96 + );
93 97
94 - // Get here default View mode saved in a General Booking Settings page
95 - $booking_default_view_mode = wpbc_get_default_saved_view_mode_for_wpbc_page();
96 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
97 - if ( !isset( $_REQUEST['view_mode'] ) )
98 - $wpdevbk_filter_params['view_mode'] = $booking_default_view_mode; // 'vm_calendar' / 'vm_booking_listing' ;
99 - $_REQUEST['view_mode'] = $booking_default_view_mode; // Set to REQUEST
100 -
101 -// if ( !isset( $_REQUEST['view_mode'] ) ) {
102 -// $booking_default_view_mode = get_bk_option( 'booking_listing_default_view_mode' );
103 -// if ( $booking_default_view_mode !== false ) {
104 -// $wpdevbk_filter_params['view_mode'] = $booking_default_view_mode; // 'vm_calendar' / 'vm_booking_listing' ;
105 -// $_REQUEST['view_mode'] = $booking_default_view_mode; // Set to REQUEST
106 -// } else
107 -// $_REQUEST['view_mode'] = 'vm_booking_listing';
108 -// }
98 + $wpdevbk_filter_params = array();
109 99
110 - // Get here default view_days_num
111 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
112 - if ( !isset( $_REQUEST['view_days_num'] ) ) {
113 - $booking_view_days_num = get_bk_option( 'booking_view_days_num' );
114 - if ( $booking_view_days_num !== false ) {
115 - $wpdevbk_filter_params['view_days_num'] = $booking_view_days_num; // '30'
116 - $_REQUEST['view_days_num'] = $booking_view_days_num;
117 - } else
118 - $_REQUEST['view_days_num'] = '365';
119 - }
100 + // Get here default View mode saved in a General Booking Settings page.
101 + $booking_default_view_mode = wpbc_get_default_saved_view_mode_for_wpbc_page();
102 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
103 + if ( ! isset( $_REQUEST['tab'] ) ) {
104 + $wpdevbk_filter_params['tab'] = $booking_default_view_mode;
105 + }
106 + // 'vm_calendar' / 'vm_booking_listing' ;.
107 + $_REQUEST['tab'] = $booking_default_view_mode;
120 108
121 109
110 + // Get here default view_days_num.
111 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
112 + if ( ! isset( $_REQUEST['view_days_num'] ) ) {
113 + $booking_view_days_num = get_bk_option( 'booking_view_days_num' );
114 + if ( false !== $booking_view_days_num ) {
115 + $wpdevbk_filter_params['view_days_num'] = $booking_view_days_num; // '30'.
116 + $_REQUEST['view_days_num'] = $booking_view_days_num;
117 + } else {
118 + $_REQUEST['view_days_num'] = '365';
119 + }
120 + }
122 121 }
123 122
124 123
125 124
@@ -771,12 +770,12 @@
771 770
772 771 //debuge( $sql_start_select . $sql . $sql_where . $sql_order . $sql_limit );
773 772
774 773 // -----------------------------------------------------------------------------------------------------------------
775 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
774 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
776 775 $bookings_res = $wpdb->get_results( $sql_start_select . $sql . $sql_where . $sql_order . $sql_limit ); // Get Bookings.
777 776
778 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
777 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
779 778 $bookings_count = $wpdb->get_results( $sql_start_count . $sql . $sql_where ); // Get Number of bookings.
780 779
781 780 $bookings_count = ( ( count( $bookings_count ) > 0 ) ? $bookings_count[0]->count : 0 );
782 781
@@ -836,9 +835,9 @@
836 835 } else {
837 836 $sql .= ' ORDER BY booking_id, booking_date ';
838 837 }
839 838
840 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
839 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
841 840 $booking_dates = $wpdb->get_results( $sql );
842 841
843 842 } else {
844 843 $booking_dates = array();
@@ -1117,15 +1116,20 @@
1117 1116 $sql_where = " WHERE bk.booking_id > " . $wh_booking_id . " ";
1118 1117
1119 1118 }
1120 1119
1121 - else if ( strpos( $wh_booking_id, ',' ) !== false ) {
1122 - $sql_where = " WHERE bk.booking_id IN (" . $wh_booking_id . ") ";
1120 + else if ( strpos( $wh_booking_id, ',' ) !== false ) {
1121 + $booking_ids = array_filter( array_map( 'absint', explode( ',', $wh_booking_id ) ) );
1122 + $booking_ids = array_values( array_unique( $booking_ids ) );
1123 + $sql_where = empty( $booking_ids )
1124 + ? ' WHERE bk.booking_id = -1 '
1125 + : ' WHERE bk.booking_id IN (' . implode( ',', $booking_ids ) . ') ';
1126 +
1127 + } else {
1128 + $booking_id = ( '-1' === (string) $wh_booking_id ) ? -1 : absint( $wh_booking_id );
1129 + $sql_where = ' WHERE bk.booking_id = ' . $booking_id . ' ';
1130 + }
1123 1131
1124 - } else {
1125 - $sql_where = " WHERE bk.booking_id = " . $wh_booking_id . " ";
1126 - }
1127 -
1128 1132 // Check if searching booking is belonging to specific user in Booking Calendar MultiUser version
1129 1133 $sql_where = apply_bk_filter('update_where_sql_for_getting_bookings_in_multiuser', $sql_where );
1130 1134
1131 1135 }
@@ -1172,44 +1176,42 @@
1172 1176 else { $and_pre = ''; $and_suf = ' AND '; }
1173 1177
1174 1178 // Actual
1175 1179 if ( ( ( $wh_booking_date === '' ) && ( $wh_booking_date2 === '' ) ) || ($wh_booking_date === '0') ) {
1176 - $sql_where = $and_pre."( ".$pref."booking_date >= ( CURDATE() - INTERVAL '00:00:01' HOUR_SECOND ) ) ".$and_suf ; // FixIn: 8.5.2.14.
1180 + $sql_where = $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL '00:00:01' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ; // FixIn: 8.5.2.14.
1177 1181
1178 1182 } else if ($wh_booking_date === '1') { // Today // FixIn: 7.1.2.8.
1179 - $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL '23:59:59' HOUR_SECOND ) ) ".$and_suf ;
1180 - $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() - INTERVAL '00:00:01' HOUR_SECOND ) ) ".$and_suf ; // FixIn: 8.4.7.21.
1183 + $sql_where = $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL '23:59:59' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ;
1184 + $sql_where .= $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL '00:00:01' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ; // FixIn: 8.4.7.21.
1181 1185
1182 1186
1183 1187 } else if ($wh_booking_date === '2') { // Previous
1184 - $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() - INTERVAL '00:00:01' HOUR_SECOND ) ) ".$and_suf ; // FixIn: 8.5.2.16.
1188 + $sql_where = $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL '00:00:01' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ; // FixIn: 8.5.2.16.
1185 1189
1186 1190 } else if ($wh_booking_date === '3') { // All
1187 1191 $sql_where = '';
1188 1192
1189 1193 } else if ($wh_booking_date === '4') { // Next
1190 - $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL ". $wh_booking_date2 . " DAY ) ) ".$and_suf ;
1191 - // $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() - INTERVAL 1 DAY ) ) ".$and_suf ;
1192 - $sql_where .= $and_pre."( ".$pref."booking_date > ( CURDATE() ) ) ".$and_suf ; // FixIn: 8.0.1.1.
1194 + $sql_where = $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL ". $wh_booking_date2 . " DAY", 'curdate' ) . ") ) ".$and_suf ;
1195 + // $sql_where .= $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1196 + $sql_where .= $and_pre."( ".$pref."booking_date > ( " . wpbc_sql_date_math_expr_explicit('', 'curdate') . " ) ) ".$and_suf ; // FixIn: 8.0.1.1.
1193 1197
1194 1198 } else if ($wh_booking_date === '5') { // Prior
1195 1199 $wh_booking_date2 = str_replace('-', '', $wh_booking_date2);
1196 - $sql_where = $and_pre."( ".$pref."booking_date >= ( CURDATE() - INTERVAL ". $wh_booking_date2 . " DAY ) ) ".$and_suf ;
1197 - $sql_where .= $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL 1 DAY ) ) ".$and_suf ;
1200 + $sql_where = $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL ". $wh_booking_date2 . " DAY", 'curdate' ) . ") ) ".$and_suf ;
1201 + $sql_where .= $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1198 1202
1199 1203 } else if ($wh_booking_date === '7') { // Check In date - Today/Tomorrow
1200 - // $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL '23:59:59' HOUR_SECOND ) ) ".$and_suf ;
1201 - // $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() ) ) ".$and_suf ;
1202 - $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL '1 23:59:59' DAY_SECOND ) ) ".$and_suf ;
1203 - $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() + INTERVAL 1 DAY ) ) ".$and_suf ;
1204 + $sql_where = $and_pre."( ".$pref."booking_date <= ( " . wpbc_sql_date_math_expr_explicit( "+ INTERVAL '47:59:59' HOUR_SECOND", 'curdate' ) . " ) ) ".$and_suf ;
1205 + $sql_where .= $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1204 1206
1205 1207 } else if ($wh_booking_date === '8') { // Check Out date - Tomorrow
1206 - $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL '1 23:59:59' DAY_SECOND ) ) ".$and_suf ;
1207 - $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() + INTERVAL 1 DAY ) ) ".$and_suf ;
1208 + $sql_where = $and_pre."( ".$pref."booking_date <= ( " . wpbc_sql_date_math_expr_explicit( "+ INTERVAL '47:59:59' HOUR_SECOND", 'curdate' ) . " ) ) ".$and_suf ;
1209 + $sql_where .= $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1208 1210
1209 1211 } else if ($wh_booking_date === '9') { // Today check in/out
1210 - $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL 1 DAY ) ) ".$and_suf ;
1211 - $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() - INTERVAL 1 DAY ) ) ".$and_suf ;
1212 + $sql_where = $and_pre."( ".$pref."booking_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1213 + $sql_where .= $and_pre."( ".$pref."booking_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1212 1214
1213 1215 } else { // Fixed
1214 1216
1215 1217 if ( $wh_booking_date !== '' )
@@ -1242,10 +1244,10 @@
1242 1244 if ($pref == 'bk.') { $and_pre = ' AND '; $and_suf = ''; }
1243 1245 else { $and_pre = ''; $and_suf = ' AND '; }
1244 1246
1245 1247 if ($wh_modification_date === '1') { // Today
1246 - $sql_where = $and_pre."( ".$pref."modification_date <= ( CURDATE() + INTERVAL '23:59:59' HOUR_SECOND ) ) ".$and_suf ; // FixIn: 8.4.7.22.
1247 - $sql_where .= $and_pre."( ".$pref."modification_date >= ( CURDATE() - INTERVAL '00:00:01' HOUR_SECOND ) ) ".$and_suf ; // FixIn: 8.4.7.22.
1248 + $sql_where = $and_pre."( ".$pref."modification_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL '23:59:59' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ; // FixIn: 8.4.7.22.
1249 + $sql_where .= $and_pre."( ".$pref."modification_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL '00:00:01' HOUR_SECOND", 'curdate' ) . ") ) ".$and_suf ; // FixIn: 8.4.7.22.
1248 1250
1249 1251 } else if ($wh_modification_date === '3') { // All
1250 1252 $sql_where = '';
1251 1253
@@ -1250,10 +1252,10 @@
1250 1252 $sql_where = '';
1251 1253
1252 1254 } else if ($wh_modification_date === '5') { // Prior
1253 1255 $wh_modification_date2 = str_replace('-', '', $wh_modification_date2);
1254 - $sql_where = $and_pre."( ".$pref."modification_date >= ( CURDATE() - INTERVAL ". $wh_modification_date2 . " DAY ) ) ".$and_suf ;
1255 - $sql_where .= $and_pre."( ".$pref."modification_date <= ( CURDATE() + INTERVAL 1 DAY ) ) ".$and_suf ;
1256 + $sql_where = $and_pre."( ".$pref."modification_date >= (" . wpbc_sql_date_math_expr_explicit( "- INTERVAL ". $wh_modification_date2 . " DAY", 'curdate' ) . ") ) ".$and_suf ;
1257 + $sql_where .= $and_pre."( ".$pref."modification_date <= (" . wpbc_sql_date_math_expr_explicit( "+ INTERVAL 1 DAY", 'curdate' ) . ") ) ".$and_suf ;
1256 1258
1257 1259 } else { // Fixed
1258 1260
1259 1261 if ( $wh_modification_date !== '' )
@@ -1263,5 +1265,182 @@
1263 1265 $sql_where.= $and_pre."( ".$pref."modification_date <= '" . $wh_modification_date2 . "' ) ".$and_suf;
1264 1266 }
1265 1267
1266 1268 return $sql_where;
1269 +}
1270 +
1271 +
1272 +/**
1273 + * Generate SQL-compatible datetime/date expression based on explicit base function and optional interval.
1274 + *
1275 + * @param string $mysql_expr - MySQL-style interval expression. Examples: "- INTERVAL '00:00:01' HOUR_SECOND", "+ INTERVAL 5 DAY", etc.
1276 + * @param string $base_func - 'curdate'|'now' Either 'curdate' (default) for CURDATE() / date('now'), or 'now' for NOW() / datetime('now').
1277 + *
1278 + * @return string SQL expression (unquoted), adapted for MySQL or SQLite.
1279 + *
1280 + * Exmaples:
1281 + * wpbc_sql_date_math_expr_explicit("- INTERVAL '00:00:01' HOUR_SECOND", 'curdate') | MySQL: CURDATE() - INTERVAL '00:00:01' HOUR_SECOND # SQLite: datetime('now', '-1 seconds') (auto-upgraded)
1282 + * wpbc_sql_date_math_expr_explicit("+ INTERVAL 2 DAY", 'curdate') | MySQL: CURDATE() + INTERVAL 2 DAY # SQLite: date('now', '+2 days')
1283 + * wpbc_sql_date_math_expr_explicit('', 'now'); | MySQL: NOW() # SQLite: datetime('now') |.
1284 + * wpbc_sql_date_math_expr_explicit(); | MySQL: CURDATE() # SQLite: date('now')
1285 + * wpbc_sql_date_math_expr_explicit("+ INTERVAL 30 MINUTE", 'curdate') | MySQL: CURDATE() + INTERVAL 30 MINUTE # SQLite: datetime('now', '+1800 seconds') (auto-upgraded)
1286 + */
1287 +function wpbc_sql_date_math_expr_explicit( $mysql_expr = '', $base_func = 'curdate' ) {
1288 + global $wpdb;
1289 +
1290 + $is_sqlite = ( get_class( $wpdb ) === 'WP_SQLite_DB' );
1291 + $original_base_func = strtolower( $base_func );
1292 + $base_func = $original_base_func;
1293 +
1294 + // Fallback if invalid.
1295 + if ( ! in_array( $base_func, array( 'curdate', 'now' ), true ) ) {
1296 + $base_func = 'curdate';
1297 + }
1298 +
1299 + // Promote to datetime() if base is 'curdate' and delta is time-based.
1300 + $has_time_delta = ( false !== stripos( $mysql_expr, 'HOUR' ) ||
1301 + false !== stripos( $mysql_expr, 'MINUTE' ) ||
1302 + false !== stripos( $mysql_expr, 'SECOND' ) ||
1303 + false !== strpos( $mysql_expr, ':' ) );
1304 +
1305 + if ( $is_sqlite && 'curdate' === $base_func && $has_time_delta ) {
1306 + $base_func = 'now'; // auto-promote for SQLite.
1307 + }
1308 +
1309 + $mysql_base_func = ( 'curdate' === $base_func ) ? 'CURDATE()' : 'NOW()';
1310 + $sqlite_base_func = ( 'curdate' === $base_func ) ? 'date' : 'datetime';
1311 +
1312 + if ( empty( $mysql_expr ) ) {
1313 + return $is_sqlite ? "{$sqlite_base_func}('now')" : $mysql_base_func;
1314 + }
1315 +
1316 + if ( ! $is_sqlite ) {
1317 + return "{$mysql_base_func} {$mysql_expr}";
1318 + }
1319 +
1320 + $modifiers = wpbc__convert_mysql_interval_to_sqlite_modifiers( $mysql_expr );
1321 +
1322 + // Fix: anchor to midnight if original func was 'curdate' with time math.
1323 + if ( 'curdate' === $original_base_func && $has_time_delta ) {
1324 + return "datetime('now','start of day'{$modifiers})";
1325 + }
1326 +
1327 + return "{$sqlite_base_func}('now'{$modifiers})";
1328 +}
1329 +
1330 +
1331 +
1332 +/**
1333 + * Convert MySQL-style interval expression to SQLite-compatible modifier(s)
1334 + *
1335 + * @param string $expr - expression.
1336 + *
1337 + * @return string
1338 + *
1339 + * Supports:
1340 + * - INTERVAL 5 DAY
1341 + * - INTERVAL '00:00:01' HOUR_SECOND
1342 + * - Multiple modifiers if needed (returns ', '+X unit', '+Y unit'...')
1343 + */
1344 +function wpbc__convert_mysql_interval_to_sqlite_modifiers( $expr ) {
1345 +
1346 + $expr = trim( $expr );
1347 +
1348 + if ( preg_match( '/([+-])?\s*INTERVAL\s+(\'?)([^\'\s]+)\2\s+([A-Z_]+)/i', $expr, $m ) ) {
1349 + $sign = ( '-' === $m[1] ) ? '-' : '+';
1350 + $value = $m[3];
1351 + $type = strtoupper( $m[4] );
1352 +
1353 + switch ( $type ) {
1354 + case 'DAY':
1355 + return ", '{$sign}{$value} days'";
1356 +
1357 + case 'HOUR_SECOND':
1358 + case 'SECOND':
1359 + $seconds = 0;
1360 + if ( strpos( $value, ':' ) !== false ) {
1361 + $parts = array_map( 'intval', explode( ':', $value ) );
1362 + if ( count( $parts ) === 3 ) {
1363 + $seconds = $parts[0] * 3600 + $parts[1] * 60 + $parts[2];
1364 + } elseif ( count( $parts ) === 2 ) {
1365 + $seconds = $parts[0] * 60 + $parts[1];
1366 + }
1367 + } else {
1368 + $seconds = intval( $value );
1369 + }
1370 +
1371 + return ", '{$sign}{$seconds} seconds'";
1372 +
1373 + default:
1374 + return ", '{$sign}{$value} " . strtolower( $type ) . "'";
1375 + }
1376 + }
1377 +
1378 + return '';
1379 +}
1380 +
1381 +// FixIn: 10.14.9.1.
1382 +/**
1383 + * Sanitize and validate "dates_to_check" parameter.
1384 + *
1385 + * Accepts scalar or array, normalizes to array of 'Y-m-d' strings
1386 + * that match /^\d{4}-\d{2}-\d{2}$/.
1387 + *
1388 + * @param mixed $dates_to_check Raw dates_to_check parameter.
1389 + *
1390 + * @return array Sanitized, validated dates.
1391 + */
1392 +function wpbc_sanitize_dates_to_check( $dates_to_check ) {
1393 +
1394 + if ( ! is_array( $dates_to_check ) ) {
1395 + $dates_to_check = array( $dates_to_check );
1396 + }
1397 +
1398 + $sanitized_dates = array();
1399 +
1400 + foreach ( $dates_to_check as $maybe_date ) {
1401 +
1402 + // Basic text cleanup.
1403 + $maybe_date = sanitize_text_field( $maybe_date );
1404 +
1405 + // Strict format: YYYY-MM-DD only.
1406 + if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $maybe_date ) ) {
1407 + $sanitized_dates[] = $maybe_date;
1408 + }
1409 + }
1410 +
1411 + return $sanitized_dates;
1412 +}
1413 +
1414 +
1415 +// FixIn: 10.14.17.1.
1416 +/**
1417 + * Sanitize and validate dates and times parameter.
1418 + *
1419 + * Accepts scalar or array, normalizes to array of 'Y-m-d H:i:s' strings
1420 + * that match /^\d{4}-\d{2}-\d{2}$/.
1421 + *
1422 + * @param mixed $dates_to_check Raw dates_to_check parameter.
1423 + *
1424 + * @return array Sanitized, validated dates.
1425 + */
1426 +function wpbc_sanitize_date_ymdhis_to_check( $dates_to_check ) {
1427 +
1428 + if ( ! is_array( $dates_to_check ) ) {
1429 + $dates_to_check = array( $dates_to_check );
1430 + }
1431 +
1432 + $sanitized_dates = array();
1433 +
1434 + foreach ( $dates_to_check as $maybe_date ) {
1435 +
1436 + // Basic text cleanup.
1437 + $maybe_date = sanitize_text_field( $maybe_date );
1438 +
1439 + // Strict format: YYYY-MM-DD only.
1440 + if ( preg_match( '/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $maybe_date ) ) {
1441 + $sanitized_dates[] = $maybe_date;
1442 + }
1443 + }
1444 +
1445 + return $sanitized_dates;
1267 1446 }