PluginProbe
Booking Calendar / 11.7
Booking Calendar v11.7
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-inspector.php

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

216 lines 8.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Independent create and edit inspector endpoints.
4 *
5 * @package Booking Calendar
6 * @since 11.6.0
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Return whether one mutation is intentionally available in public demos.
15 *
16 * Public demos permit catalog creation, editing, and reviewed deletion so
17 * visitors can evaluate those workflows. The deletion service independently
18 * protects activation fixtures and every mutation retains its normal edition,
19 * capability, ownership, validation, and stale-state checks.
20 *
21 * @param string $mutation_action Mutation identifier.
22 *
23 * @return bool True for an allow-listed demo mutation.
24 */
25 function wpbc_catalog_booking_resource_inspector_is_demo_mutation_allowed( $mutation_action ) {
26 return in_array(
27 sanitize_key( (string) $mutation_action ),
28 array( 'create', 'update', 'bulk_update', 'inline_update', 'delete' ),
29 true
30 );
31 }
32
33 /**
34 * Authorize one inspector request at the transport boundary.
35 *
36 * @param string $mutation_action Mutation identifier, or an empty string for a read-only request.
37 *
38 * @return true|WP_Error True when authorized or a safe error.
39 */
40 function wpbc_catalog_booking_resource_inspector_authorize( $mutation_action = '' ) {
41 $mutation_action = sanitize_key( (string) $mutation_action );
42
43 if ( ! check_ajax_referer( 'wpbc_catalog_booking_resources_nonce', 'nonce', false ) ) {
44 return new WP_Error( 'wpbc_catalog_resource_inspector_nonce', __( 'The Booking Resource request could not be verified.', 'booking' ) );
45 }
46 if ( ! current_user_can( wpbc_catalog_booking_resources_get_manage_capability() ) ) {
47 return new WP_Error( 'wpbc_catalog_resource_inspector_forbidden', __( 'You are not allowed to manage Booking Resources.', 'booking' ) );
48 }
49 if (
50 '' !== $mutation_action
51 && wpbc_is_this_demo()
52 && ! wpbc_catalog_booking_resource_inspector_is_demo_mutation_allowed( $mutation_action )
53 ) {
54 return new WP_Error( 'wpbc_catalog_resource_inspector_demo', __( 'Resource changes are disabled in the public demo.', 'booking' ) );
55 }
56
57 return true;
58 }
59
60 /**
61 * Decode a submitted inspector field map.
62 *
63 * @return array<string,mixed>|WP_Error Decoded fields or a safe error.
64 */
65 function wpbc_catalog_booking_resource_inspector_get_fields() {
66 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce and capability are verified by each endpoint before this helper is called.
67 if ( ! isset( $_POST['fields'] ) || ! is_scalar( $_POST['fields'] ) ) {
68 return new WP_Error( 'wpbc_catalog_resource_inspector_fields_missing', __( 'The Booking Resource request is invalid.', 'booking' ) );
69 }
70 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Authorized by the caller.
71 $decoded_fields = json_decode( wp_unslash( (string) $_POST['fields'] ), true );
72
73 return is_array( $decoded_fields ) ? $decoded_fields : new WP_Error( 'wpbc_catalog_resource_inspector_fields_invalid', __( 'The Booking Resource request is invalid.', 'booking' ) );
74 }
75
76 /**
77 * Send one safe inspector error response.
78 *
79 * @param WP_Error $error Safe error.
80 * @param int $status HTTP status.
81 *
82 * @return void
83 */
84 function wpbc_catalog_booking_resource_inspector_send_error( $error, $status = 400 ) {
85 wp_send_json_error(
86 array(
87 'code' => sanitize_key( $error->get_error_code() ),
88 'message' => sanitize_text_field( $error->get_error_message() ),
89 ),
90 absint( $status )
91 );
92 }
93
94 /**
95 * Return the current create-inspector schema.
96 *
97 * @return void
98 */
99 function wpbc_catalog_booking_resource_ajax_create_schema() {
100 $authorized = wpbc_catalog_booking_resource_inspector_authorize();
101 if ( is_wp_error( $authorized ) ) {
102 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
103 }
104
105 $schema = ( new WPBC_Catalog_Booking_Resource_Inspector_Schema() )->get_create_schema();
106 wp_send_json_success( array( 'schema' => $schema ) );
107 }
108 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCE_CREATE_SCHEMA', 'wpbc_catalog_booking_resource_ajax_create_schema' );
109
110 /**
111 * Return one authorized Resource edit schema.
112 *
113 * @return void
114 */
115 function wpbc_catalog_booking_resource_ajax_edit_schema() {
116 $authorized = wpbc_catalog_booking_resource_inspector_authorize();
117 if ( is_wp_error( $authorized ) ) {
118 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
119 }
120 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above.
121 $resource_id = isset( $_POST['resource_id'] ) && is_scalar( $_POST['resource_id'] ) ? absint( $_POST['resource_id'] ) : 0;
122 if ( ! $resource_id ) {
123 wpbc_catalog_booking_resource_inspector_send_error( new WP_Error( 'wpbc_catalog_resource_inspector_id', __( 'The Booking Resource is invalid.', 'booking' ) ) );
124 }
125
126 $resource = ( new WPBC_Catalog_Booking_Resources_Repository() )->get_resource_details( $resource_id );
127 if ( is_wp_error( $resource ) ) {
128 wpbc_catalog_booking_resource_inspector_send_error( $resource, 500 );
129 }
130 if ( null === $resource ) {
131 wpbc_catalog_booking_resource_inspector_send_error( new WP_Error( 'wpbc_catalog_resource_inspector_not_found', __( 'The Booking Resource was not found or is not available to this account.', 'booking' ) ), 404 );
132 }
133
134 $schema = ( new WPBC_Catalog_Booking_Resource_Inspector_Schema() )->get_edit_schema( $resource );
135 if ( is_wp_error( $schema ) ) {
136 wpbc_catalog_booking_resource_inspector_send_error( $schema );
137 }
138 wp_send_json_success( array( 'schema' => $schema ) );
139 }
140 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCE_EDIT_SCHEMA', 'wpbc_catalog_booking_resource_ajax_edit_schema' );
141
142 /**
143 * Create one validated Resource batch.
144 *
145 * @return void
146 */
147 function wpbc_catalog_booking_resource_ajax_create() {
148 $authorized = wpbc_catalog_booking_resource_inspector_authorize( 'create' );
149 if ( is_wp_error( $authorized ) ) {
150 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
151 }
152 $fields = wpbc_catalog_booking_resource_inspector_get_fields();
153 if ( is_wp_error( $fields ) ) {
154 wpbc_catalog_booking_resource_inspector_send_error( $fields );
155 }
156 $created = ( new WPBC_Catalog_Booking_Resource_Creator() )->create( $fields );
157 if ( is_wp_error( $created ) ) {
158 wpbc_catalog_booking_resource_inspector_send_error( $created );
159 }
160
161 $resource_count = count( $created['resource_ids'] );
162 wp_send_json_success(
163 array(
164 'resource_ids' => array_map( 'absint', $created['resource_ids'] ),
165 'message' => sprintf(
166 /* translators: %d: Number of created Booking Resources. */
167 _n( '%d Booking Resource created.', '%d Booking Resources created.', $resource_count, 'booking' ),
168 $resource_count
169 ),
170 )
171 );
172 }
173 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCE_CREATE', 'wpbc_catalog_booking_resource_ajax_create' );
174
175 /**
176 * Update one authorized Resource.
177 *
178 * @return void
179 */
180 function wpbc_catalog_booking_resource_ajax_update() {
181 $authorized = wpbc_catalog_booking_resource_inspector_authorize( 'update' );
182 if ( is_wp_error( $authorized ) ) {
183 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
184 }
185 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above.
186 $resource_id = isset( $_POST['resource_id'] ) && is_scalar( $_POST['resource_id'] ) ? absint( $_POST['resource_id'] ) : 0;
187 $fields = wpbc_catalog_booking_resource_inspector_get_fields();
188 if ( ! $resource_id ) {
189 wpbc_catalog_booking_resource_inspector_send_error( new WP_Error( 'wpbc_catalog_resource_update_id', __( 'The Booking Resource is invalid.', 'booking' ) ) );
190 }
191 if ( is_wp_error( $fields ) ) {
192 wpbc_catalog_booking_resource_inspector_send_error( $fields );
193 }
194
195 $updated = ( new WPBC_Catalog_Booking_Resource_Updater() )->update( $resource_id, $fields );
196 if ( is_wp_error( $updated ) ) {
197 wpbc_catalog_booking_resource_inspector_send_error( $updated );
198 }
199 $refreshed_resource = ( new WPBC_Catalog_Booking_Resources_Repository() )->get_resource_details( $resource_id );
200 $refreshed_schema = array();
201 if ( is_array( $refreshed_resource ) ) {
202 $refreshed_schema = ( new WPBC_Catalog_Booking_Resource_Inspector_Schema() )->get_edit_schema( $refreshed_resource );
203 if ( is_wp_error( $refreshed_schema ) ) {
204 $refreshed_schema = array();
205 }
206 }
207 wp_send_json_success(
208 array(
209 'resource_ids' => array( $resource_id ),
210 'message' => __( 'Booking Resource saved.', 'booking' ),
211 'schema' => $refreshed_schema,
212 )
213 );
214 }
215 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCE_UPDATE', 'wpbc_catalog_booking_resource_ajax_update' );
216