@@ -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
208208new 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