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
booking / includes / page-catalog-booking-resources / ajax / booking-resource-capacity.php

booking-resource-capacity.php in Booking Calendar 11.9, at includes/page-catalog-booking-resources/ajax/booking-resource-capacity.php

144 lines 7.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Independent AJAX transport for reviewed Resource capacity operations.
4 *
5 * @package Booking Calendar
6 * @since 11.6.0
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Decode explicitly selected child IDs after catalog authorization.
15 *
16 * @return array<int,mixed>|WP_Error Decoded IDs or safe request error.
17 */
18 function wpbc_catalog_booking_resource_capacity_get_detach_ids() {
19 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- The calling endpoint verifies the catalog nonce.
20 if ( ! isset( $_POST['detach_resource_ids'] ) || ! is_scalar( $_POST['detach_resource_ids'] ) ) {
21 return array();
22 }
23 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Authorized by the caller and domain-validated by the service.
24 $decoded_ids = json_decode( wp_unslash( (string) $_POST['detach_resource_ids'] ), true );
25 if ( JSON_ERROR_NONE !== json_last_error() || ! is_array( $decoded_ids ) ) {
26 return new WP_Error( 'wpbc_catalog_capacity_json_invalid', __( 'The selected resource units are invalid.', 'booking' ) );
27 }
28
29 return $decoded_ids;
30 }
31
32 /**
33 * Return the requested capacity-decrease outcome.
34 *
35 * @return string Sanitized action; the domain service performs allow-list validation.
36 */
37 function wpbc_catalog_booking_resource_capacity_get_decrease_action() {
38 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- The calling endpoint verifies the catalog nonce.
39 return isset( $_POST['decrease_action'] ) && is_scalar( $_POST['decrease_action'] )
40 ? sanitize_key( wp_unslash( (string) $_POST['decrease_action'] ) )
41 : 'detach';
42 }
43
44 /**
45 * Return current capacity context for an authorized Resource row.
46 *
47 * @return void Terminates with normalized JSON.
48 */
49 function wpbc_catalog_booking_resource_ajax_capacity_context() {
50 $authorized = wpbc_catalog_booking_resource_inspector_authorize();
51 if ( is_wp_error( $authorized ) ) {
52 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
53 }
54 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above.
55 $resource_id = isset( $_POST['resource_id'] ) ? absint( wp_unslash( $_POST['resource_id'] ) ) : 0;
56 $context = ( new WPBC_Catalog_Booking_Resource_Capacity_Service() )->get_context( $resource_id );
57 if ( is_wp_error( $context ) ) {
58 $status = in_array( $context->get_error_code(), array( 'wpbc_catalog_capacity_edition', 'wpbc_catalog_capacity_demo' ), true ) ? 403 : 400;
59 wpbc_catalog_booking_resource_inspector_send_error( $context, $status );
60 }
61
62 wp_send_json_success( array( 'context' => $context ) );
63 }
64 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCE_CAPACITY_CONTEXT', 'wpbc_catalog_booking_resource_ajax_capacity_context' );
65
66 /**
67 * Return a signed, non-mutating structural capacity review.
68 *
69 * @return void Terminates with normalized JSON.
70 */
71 function wpbc_catalog_booking_resource_ajax_capacity_preview() {
72 $authorized = wpbc_catalog_booking_resource_inspector_authorize();
73 if ( is_wp_error( $authorized ) ) {
74 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
75 }
76 $detach_resource_ids = wpbc_catalog_booking_resource_capacity_get_detach_ids();
77 if ( is_wp_error( $detach_resource_ids ) ) {
78 wpbc_catalog_booking_resource_inspector_send_error( $detach_resource_ids );
79 }
80 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above.
81 $resource_id = isset( $_POST['resource_id'] ) ? absint( wp_unslash( $_POST['resource_id'] ) ) : 0;
82 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Strictly validated by the capacity service.
83 $target_capacity = isset( $_POST['target_capacity'] ) && is_scalar( $_POST['target_capacity'] ) ? wp_unslash( (string) $_POST['target_capacity'] ) : '';
84 $decrease_action = wpbc_catalog_booking_resource_capacity_get_decrease_action();
85 $preview = ( new WPBC_Catalog_Booking_Resource_Capacity_Service() )->preview( $resource_id, $target_capacity, $detach_resource_ids, $decrease_action );
86 if ( is_wp_error( $preview ) ) {
87 $status = 'wpbc_catalog_capacity_edition' === $preview->get_error_code() ? 403 : 400;
88 wpbc_catalog_booking_resource_inspector_send_error( $preview, $status );
89 }
90
91 wp_send_json_success( array( 'preview' => $preview ) );
92 }
93 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCE_CAPACITY_PREVIEW', 'wpbc_catalog_booking_resource_ajax_capacity_preview' );
94
95 /**
96 * Apply one signed capacity change after apply-time revalidation.
97 *
98 * @return void Terminates with normalized JSON.
99 */
100 function wpbc_catalog_booking_resource_ajax_capacity_apply() {
101 $authorized = wpbc_catalog_booking_resource_inspector_authorize( 'capacity' );
102 if ( is_wp_error( $authorized ) ) {
103 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
104 }
105 $detach_resource_ids = wpbc_catalog_booking_resource_capacity_get_detach_ids();
106 if ( is_wp_error( $detach_resource_ids ) ) {
107 wpbc_catalog_booking_resource_inspector_send_error( $detach_resource_ids );
108 }
109 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above.
110 $resource_id = isset( $_POST['resource_id'] ) ? absint( wp_unslash( $_POST['resource_id'] ) ) : 0;
111 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Strictly validated by the capacity service.
112 $target_capacity = isset( $_POST['target_capacity'] ) && is_scalar( $_POST['target_capacity'] ) ? wp_unslash( (string) $_POST['target_capacity'] ) : '';
113 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above and compared with a request-bound signature.
114 $review_token = isset( $_POST['review_token'] ) && is_scalar( $_POST['review_token'] ) ? sanitize_text_field( wp_unslash( (string) $_POST['review_token'] ) ) : '';
115 $decrease_action = wpbc_catalog_booking_resource_capacity_get_decrease_action();
116 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above and required again by the domain service for deletion.
117 $acknowledged = isset( $_POST['acknowledged'] ) && '1' === (string) wp_unslash( $_POST['acknowledged'] );
118 $result = ( new WPBC_Catalog_Booking_Resource_Capacity_Service() )->apply( $resource_id, $target_capacity, $detach_resource_ids, $review_token, $decrease_action, $acknowledged );
119 if ( is_wp_error( $result ) ) {
120 $status = in_array( $result->get_error_code(), array( 'wpbc_catalog_capacity_review_stale', 'wpbc_catalog_delete_review_stale', 'wpbc_catalog_capacity_delete_structure_changed' ), true ) ? 409 : 400;
121 if ( in_array( $result->get_error_code(), array( 'wpbc_catalog_capacity_edition', 'wpbc_catalog_capacity_demo' ), true ) ) {
122 $status = 403;
123 }
124 wpbc_catalog_booking_resource_inspector_send_error( $result, $status );
125 }
126
127 wp_send_json_success(
128 array(
129 'message' => sprintf(
130 /* translators: %s: New Booking Resource capacity. */
131 __( 'Resource capacity changed to %s.', 'booking' ),
132 number_format_i18n( absint( $result['new_capacity'] ) )
133 ),
134 'resource_id' => absint( $result['resource_id'] ),
135 'new_capacity' => absint( $result['new_capacity'] ),
136 'created_ids' => $result['created_ids'],
137 'detached_ids' => $result['detached_ids'],
138 'deleted_ids' => $result['deleted_ids'],
139 'affected_ids' => $result['affected_ids'],
140 )
141 );
142 }
143 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCE_CAPACITY_APPLY', 'wpbc_catalog_booking_resource_ajax_capacity_apply' );
144