Skip to content

Commit 1ea2f3f

Browse files
authored
gpb-daily-service-booking-limit.php: Added a new snippet.
1 parent 4a28114 commit 1ea2f3f

File tree

1 file changed

+141
-141
lines changed

1 file changed

+141
-141
lines changed

gp-bookings/gpb-daily-service-booking-limit.php

Lines changed: 141 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -33,181 +33,181 @@ public function __construct( array $args ) {
3333
'capacity_message' => __( 'We are fully booked for that day. Please choose another date.', 'gp-bookings' ),
3434
));
3535

36-
$this->form_id = $args['form_id'];
37-
$this->service_ids = array_map( 'intval', (array) $args['service_ids'] );
38-
$this->daily_limit = (int) $args['daily_limit'];
39-
$this->capacity_message = $args['capacity_message'];
36+
$this->form_id = $args['form_id'];
37+
$this->service_ids = array_map( 'intval', (array) $args['service_ids'] );
38+
$this->daily_limit = (int) $args['daily_limit'];
39+
$this->capacity_message = $args['capacity_message'];
4040

41-
if ( empty( $this->service_ids ) ) {
42-
return;
43-
}
41+
if ( empty( $this->service_ids ) ) {
42+
return;
43+
}
4444

45-
add_action( 'gpb_before_booking_created', array( $this, 'guard_booking_creation' ), 10, 2 );
46-
add_filter( 'gform_validation', array( $this, 'validate_submission' ) );
47-
}
45+
add_action( 'gpb_before_booking_created', array( $this, 'guard_booking_creation' ), 10, 2 );
46+
add_filter( 'gform_validation', array( $this, 'validate_submission' ) );
47+
}
4848

49-
public function guard_booking_creation( array $booking_data, $bookable ) {
50-
if ( ! $bookable instanceof \GP_Bookings\Service || ! in_array( $bookable->get_id(), $this->service_ids, true ) ) {
51-
return;
52-
}
49+
public function guard_booking_creation( array $booking_data, $bookable ) {
50+
if ( ! $bookable instanceof \GP_Bookings\Service || ! in_array( $bookable->get_id(), $this->service_ids, true ) ) {
51+
return;
52+
}
5353

5454
// Normalize to the start date in the site timezone so nightly/range bookings count correctly.
55-
$date = $this->normalize_booking_date(
56-
$booking_data['start_datetime'] ?? '',
57-
$booking_data['end_datetime'] ?? ( $booking_data['start_datetime'] ?? '' ),
58-
$bookable
59-
);
60-
if ( ! $date ) {
61-
return;
62-
}
63-
$quantity = isset( $booking_data['quantity'] ) ? max( 1, (int) $booking_data['quantity'] ) : 1;
55+
$date = $this->normalize_booking_date(
56+
$booking_data['start_datetime'] ?? '',
57+
$booking_data['end_datetime'] ?? ( $booking_data['start_datetime'] ?? '' ),
58+
$bookable
59+
);
60+
if ( ! $date ) {
61+
return;
62+
}
63+
$quantity = isset( $booking_data['quantity'] ) ? max( 1, (int) $booking_data['quantity'] ) : 1;
6464

6565
// Guard again at save time so last-second bookings can't slip past the form validation.
66-
if ( $this->get_total_for_date( $date ) + $quantity > $this->daily_limit ) {
67-
throw new \GP_Bookings\Exceptions\CapacityException( $this->capacity_message );
68-
}
69-
}
66+
if ( $this->get_total_for_date( $date ) + $quantity > $this->daily_limit ) {
67+
throw new \GP_Bookings\Exceptions\CapacityException( $this->capacity_message );
68+
}
69+
}
7070

71-
public function validate_submission( $result ) {
72-
$is_object = is_object( $result );
73-
$form = $is_object ? $result->form : $result['form'];
71+
public function validate_submission( $result ) {
72+
$is_object = is_object( $result );
73+
$form = $is_object ? $result->form : $result['form'];
7474

75-
if ( $this->form_id && (int) $form['id'] !== (int) $this->form_id ) {
76-
return $result;
77-
}
75+
if ( $this->form_id && (int) $form['id'] !== (int) $this->form_id ) {
76+
return $result;
77+
}
7878

79-
$is_valid = $is_object ? $result->is_valid : $result['is_valid'];
79+
$is_valid = $is_object ? $result->is_valid : $result['is_valid'];
8080

8181
// Track per-day totals so multiple booking fields in one submission don't exceed the cap.
82-
$daily_totals = [];
82+
$daily_totals = [];
8383

84-
foreach ( $form['fields'] as &$field ) {
85-
if ( ! isset( $field->inputType ) || $field->inputType !== 'gpb_booking' ) {
86-
continue;
87-
}
84+
foreach ( $form['fields'] as &$field ) {
85+
if ( ! isset( $field->inputType ) || $field->inputType !== 'gpb_booking' ) {
86+
continue;
87+
}
8888

89-
$children = $field->get_child_fields( $form );
90-
$service = $children['service'] ?? null;
91-
$time = $children['booking_time'] ?? null;
89+
$children = $field->get_child_fields( $form );
90+
$service = $children['service'] ?? null;
91+
$time = $children['booking_time'] ?? null;
9292

93-
if ( ! $service || ! $time ) {
94-
continue;
95-
}
93+
if ( ! $service || ! $time ) {
94+
continue;
95+
}
9696

97-
$service_id = isset( $service->gpbService ) ? (int) $service->gpbService : 0;
98-
if ( ! $service_id || ! in_array( $service_id, $this->service_ids, true ) ) {
99-
continue;
100-
}
97+
$service_id = isset( $service->gpbService ) ? (int) $service->gpbService : 0;
98+
if ( ! $service_id || ! in_array( $service_id, $this->service_ids, true ) ) {
99+
continue;
100+
}
101101

102-
$service_model = \GP_Bookings\Service::get( $service_id );
103-
if ( ! $service_model ) {
104-
continue;
105-
}
102+
$service_model = \GP_Bookings\Service::get( $service_id );
103+
if ( ! $service_model ) {
104+
continue;
105+
}
106106

107-
$datetime = $this->get_posted_value( (int) $time->id );
108-
if ( ! $datetime ) {
109-
continue;
110-
}
107+
$datetime = $this->get_posted_value( (int) $time->id );
108+
if ( ! $datetime ) {
109+
continue;
110+
}
111111

112-
$date = $this->normalize_booking_date( $datetime, $datetime, $service_model );
113-
if ( ! $date ) {
114-
continue;
115-
}
112+
$date = $this->normalize_booking_date( $datetime, $datetime, $service_model );
113+
if ( ! $date ) {
114+
continue;
115+
}
116116

117-
$quantity = rgpost( 'input_' . (int) $field->id . '_3' );
118-
$quantity = $quantity === null || $quantity === '' ? 1 : max( 1, (int) $quantity );
117+
$quantity = rgpost( 'input_' . (int) $field->id . '_3' );
118+
$quantity = $quantity === null || $quantity === '' ? 1 : max( 1, (int) $quantity );
119119

120120
// Reuse the current total for this date so we only hit the database once per day per submission.
121-
$current_total = $daily_totals[ $date ] ?? $this->get_total_for_date( $date );
121+
$current_total = $daily_totals[ $date ] ?? $this->get_total_for_date( $date );
122122

123-
if ( $current_total + $quantity > $this->daily_limit ) {
124-
$this->flag_field_error( $form, (int) $time->id );
125-
$is_valid = false;
126-
continue;
127-
}
123+
if ( $current_total + $quantity > $this->daily_limit ) {
124+
$this->flag_field_error( $form, (int) $time->id );
125+
$is_valid = false;
126+
continue;
127+
}
128128

129-
$daily_totals[ $date ] = $current_total + $quantity;
130-
}
129+
$daily_totals[ $date ] = $current_total + $quantity;
130+
}
131131

132-
unset( $field );
132+
unset( $field );
133133

134-
if ( ! $is_valid ) {
135-
$form['validation_message'] = $this->capacity_message;
136-
}
134+
if ( ! $is_valid ) {
135+
$form['validation_message'] = $this->capacity_message;
136+
}
137137

138-
if ( $is_object ) {
139-
$result->form = $form;
140-
$result->is_valid = $is_valid;
141-
return $result;
142-
}
138+
if ( $is_object ) {
139+
$result->form = $form;
140+
$result->is_valid = $is_valid;
141+
return $result;
142+
}
143143

144-
$result['form'] = $form;
145-
$result['is_valid'] = $is_valid;
146-
return $result;
147-
}
144+
$result['form'] = $form;
145+
$result['is_valid'] = $is_valid;
146+
return $result;
147+
}
148148

149-
private function get_total_for_date( string $date ): int {
150-
$start = $date . ' 00:00:00';
151-
$end = $date . ' 23:59:59';
149+
private function get_total_for_date( string $date ): int {
150+
$start = $date . ' 00:00:00';
151+
$end = $date . ' 23:59:59';
152152
// Count both pending and confirmed bookings to reflect in-progress reservations.
153-
$bookings = \GP_Bookings\Queries\Booking_Query::get_bookings_in_range(
154-
$start,
155-
$end,
156-
array(
157-
'object_id' => $this->service_ids,
158-
'object_type' => 'service',
159-
'status' => array( 'pending', 'confirmed' ),
160-
'exclude_service_with_resource' => false,
161-
)
162-
);
163-
164-
$total = 0;
165-
166-
foreach ( $bookings as $booking ) {
167-
$total += (int) $booking->get_quantity();
168-
}
169-
170-
return $total;
171-
}
172-
173-
private function normalize_booking_date( $start, $end, $bookable ): ?string {
174-
try {
175-
$normalized = \GP_Bookings\Booking::normalize_datetime_values( $start, $end, $bookable );
176-
} catch ( \Throwable $e ) {
177-
return null;
178-
}
179-
180-
return $normalized['start']->format( 'Y-m-d' );
181-
}
182-
183-
private function get_posted_value( int $field_id ) {
184-
$value = rgpost( 'input_' . $field_id );
185-
186-
if ( is_array( $value ) ) {
187-
$value = reset( $value );
188-
}
189-
190-
return $value === null || $value === '' ? null : $value;
191-
}
192-
193-
private function flag_field_error( array &$form, int $field_id ): void {
194-
foreach ( $form['fields'] as &$field ) {
195-
if ( (int) $field->id === $field_id ) {
196-
$field->failed_validation = true;
197-
$field->validation_message = $this->capacity_message;
198-
break;
199-
}
200-
}
201-
202-
unset( $field );
203-
}
153+
$bookings = \GP_Bookings\Queries\Booking_Query::get_bookings_in_range(
154+
$start,
155+
$end,
156+
array(
157+
'object_id' => $this->service_ids,
158+
'object_type' => 'service',
159+
'status' => array( 'pending', 'confirmed' ),
160+
'exclude_service_with_resource' => false,
161+
)
162+
);
163+
164+
$total = 0;
165+
166+
foreach ( $bookings as $booking ) {
167+
$total += (int) $booking->get_quantity();
168+
}
169+
170+
return $total;
171+
}
172+
173+
private function normalize_booking_date( $start, $end, $bookable ): ?string {
174+
try {
175+
$normalized = \GP_Bookings\Booking::normalize_datetime_values( $start, $end, $bookable );
176+
} catch ( \Throwable $e ) {
177+
return null;
178+
}
179+
180+
return $normalized['start']->format( 'Y-m-d' );
181+
}
182+
183+
private function get_posted_value( int $field_id ) {
184+
$value = rgpost( 'input_' . $field_id );
185+
186+
if ( is_array( $value ) ) {
187+
$value = reset( $value );
188+
}
189+
190+
return $value === null || $value === '' ? null : $value;
191+
}
192+
193+
private function flag_field_error( array &$form, int $field_id ): void {
194+
foreach ( $form['fields'] as &$field ) {
195+
if ( (int) $field->id === $field_id ) {
196+
$field->failed_validation = true;
197+
$field->validation_message = $this->capacity_message;
198+
break;
199+
}
200+
}
201+
202+
unset( $field );
203+
}
204204

205205
}
206206

207207
# Configuration
208208
new GPB_Daily_Service_Limit( array(
209209
'form_id' => 123,
210-
'service_ids' => array( 45, 67 ),
211-
'daily_limit' => 10,
212-
// 'capacity_message' => '',
210+
'service_ids' => array( 45, 67 ),
211+
'daily_limit' => 10,
212+
// 'capacity_message' => '',
213213
) );

0 commit comments

Comments
 (0)