PluginProbe
Booking Calendar / 11.9
Booking Calendar v11.9
11.9 11.8.4 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 All 205 releases
← All changes | includes/_working_time/working_time.php +120 -3 11.3 → 11.9 View file →
@@ -1,4 +1,4 @@
1 1 <?php
2 2 /**
3 3 * Working Time settings and availability helpers.
4 4 *
@@ -94,9 +94,9 @@
94 94 * @param mixed $weekdays Weekday intervals.
95 95 *
96 96 * @return array
97 97 */
98 -function wpbc_working_time__normalize_weekday_intervals( $weekdays ) {
98 +function wpbc_working_time__normalize_weekday_intervals( $weekdays ) {
99 99
100 100 $normalized = array();
101 101
102 102 for ( $day = 0; $day <= 6; $day++ ) {
@@ -131,10 +131,127 @@
131 131 }
132 132 );
133 133 }
134 134
135 - return $normalized;
136 -}
135 + return $normalized;
136 +}
137 +
138 +/**
139 + * Validate a complete canonical weekly Working Time schedule.
140 + *
141 + * This strict validator complements the compatibility normalizer above. It is
142 + * intended for administration mutation boundaries, where silently dropping an
143 + * invalid or overlapping interval would make the saved schedule differ from
144 + * what the user submitted. Intervals that touch at one boundary are valid.
145 + *
146 + * @param mixed $weekdays Untrusted weekday interval records.
147 + * @param int $max_intervals_per_day Maximum intervals accepted for one weekday.
148 + *
149 + * @return array<int,array<int,array{start_second:int,end_second:int}>>|WP_Error Validated weekdays or an error.
150 + */
151 +function wpbc_working_time__validate_weekday_intervals( $weekdays, $max_intervals_per_day = 8 ) {
152 +
153 + if ( ! is_array( $weekdays ) ) {
154 + return new WP_Error( 'wpbc_working_time_weekdays_invalid', __( 'Enter a valid weekly Working Time schedule.', 'booking' ) );
155 + }
156 +
157 + foreach ( array_keys( $weekdays ) as $day_key ) {
158 + if ( ! preg_match( '/^[0-6]$/', (string) $day_key ) ) {
159 + return new WP_Error( 'wpbc_working_time_weekday_invalid', __( 'The Working Time schedule contains an invalid weekday.', 'booking' ) );
160 + }
161 + }
162 +
163 + $max_intervals_per_day = max( 1, min( 48, absint( $max_intervals_per_day ) ) );
164 + $normalized_weekdays = array();
165 +
166 + for ( $day_number = 0; $day_number <= 6; $day_number++ ) {
167 + $raw_intervals = isset( $weekdays[ $day_number ] ) && is_array( $weekdays[ $day_number ] )
168 + ? array_values( $weekdays[ $day_number ] )
169 + : array();
170 +
171 + if ( count( $raw_intervals ) > $max_intervals_per_day ) {
172 + return new WP_Error(
173 + 'wpbc_working_time_interval_limit',
174 + /* translators: %d: Maximum intervals per weekday. */
175 + sprintf( __( 'Add no more than %d Working Time intervals to one weekday.', 'booking' ), $max_intervals_per_day ),
176 + array( 'day_number' => $day_number )
177 + );
178 + }
179 +
180 + $normalized_intervals = array();
181 + foreach ( $raw_intervals as $raw_interval ) {
182 + if ( ! is_array( $raw_interval ) || array_diff( array_keys( $raw_interval ), array( 'start_second', 'end_second' ) ) ) {
183 + return new WP_Error(
184 + 'wpbc_working_time_interval_invalid',
185 + __( 'Enter a valid start and end time for every Working Time interval.', 'booking' ),
186 + array( 'day_number' => $day_number )
187 + );
188 + }
189 +
190 + $raw_start_second = isset( $raw_interval['start_second'] ) ? $raw_interval['start_second'] : null;
191 + $raw_end_second = isset( $raw_interval['end_second'] ) ? $raw_interval['end_second'] : null;
192 + if (
193 + ! is_scalar( $raw_start_second )
194 + || ! is_scalar( $raw_end_second )
195 + || ! preg_match( '/^\d+$/', (string) $raw_start_second )
196 + || ! preg_match( '/^\d+$/', (string) $raw_end_second )
197 + ) {
198 + return new WP_Error(
199 + 'wpbc_working_time_interval_invalid',
200 + __( 'Enter a valid start and end time for every Working Time interval.', 'booking' ),
201 + array( 'day_number' => $day_number )
202 + );
203 + }
204 +
205 + $start_second = absint( $raw_start_second );
206 + $end_second = absint( $raw_end_second );
207 + if (
208 + $start_second >= $end_second
209 + || DAY_IN_SECONDS < $end_second
210 + || 0 !== $start_second % MINUTE_IN_SECONDS
211 + || 0 !== $end_second % MINUTE_IN_SECONDS
212 + ) {
213 + return new WP_Error(
214 + 'wpbc_working_time_interval_invalid',
215 + __( 'Every Working Time interval must end after it starts and stay within one day.', 'booking' ),
216 + array( 'day_number' => $day_number )
217 + );
218 + }
219 +
220 + $normalized_intervals[] = array(
221 + 'start_second' => $start_second,
222 + 'end_second' => $end_second,
223 + );
224 + }
225 +
226 + usort(
227 + $normalized_intervals,
228 + function ( $first_interval, $second_interval ) {
229 + if ( $first_interval['start_second'] === $second_interval['start_second'] ) {
230 + return $first_interval['end_second'] - $second_interval['end_second'];
231 + }
232 +
233 + return $first_interval['start_second'] - $second_interval['start_second'];
234 + }
235 + );
236 +
237 + $previous_end = -1;
238 + foreach ( $normalized_intervals as $normalized_interval ) {
239 + if ( $normalized_interval['start_second'] < $previous_end ) {
240 + return new WP_Error(
241 + 'wpbc_working_time_interval_overlap',
242 + __( 'Working Time intervals on the same weekday cannot overlap or repeat.', 'booking' ),
243 + array( 'day_number' => $day_number )
244 + );
245 + }
246 + $previous_end = $normalized_interval['end_second'];
247 + }
248 +
249 + $normalized_weekdays[ $day_number ] = $normalized_intervals;
250 + }
251 +
252 + return $normalized_weekdays;
253 +}
137 254
138 255 /**
139 256 * Get stored Working Time settings.
140 257 *