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-resources-bulk.php

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

170 lines 8.4 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 bulk operations.
4 *
5 * @package Booking Calendar
6 * @since 11.6.0
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Decode one JSON request property after inspector authorization.
15 *
16 * @param string $property_name POST property name.
17 * @param string $error_message Safe translated message.
18 * @return array<mixed>|WP_Error Decoded array or safe error.
19 */
20 function wpbc_catalog_booking_resources_bulk_decode_json( $property_name, $error_message ) {
21 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Each endpoint verifies the catalog nonce before calling this helper.
22 if ( ! isset( $_POST[ $property_name ] ) || ! is_scalar( $_POST[ $property_name ] ) ) {
23 return new WP_Error( 'wpbc_catalog_bulk_json_missing', $error_message );
24 }
25 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Authorized by the caller.
26 $decoded = json_decode( wp_unslash( (string) $_POST[ $property_name ] ), true );
27
28 return JSON_ERROR_NONE === json_last_error() && is_array( $decoded ) ? $decoded : new WP_Error( 'wpbc_catalog_bulk_json_invalid', $error_message );
29 }
30
31 /**
32 * Return the common bulk-edit schema for an explicit selection.
33 *
34 * @return void
35 */
36 function wpbc_catalog_booking_resources_ajax_bulk_schema() {
37 $authorized = wpbc_catalog_booking_resource_inspector_authorize();
38 if ( is_wp_error( $authorized ) ) {
39 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
40 }
41 $ids = wpbc_catalog_booking_resources_bulk_decode_json( 'resource_ids', __( 'The selected Booking Resources are invalid.', 'booking' ) );
42 if ( is_wp_error( $ids ) ) {
43 wpbc_catalog_booking_resource_inspector_send_error( $ids );
44 }
45 $schema = ( new WPBC_Catalog_Booking_Resources_Bulk_Editor() )->get_schema( $ids );
46 if ( is_wp_error( $schema ) ) {
47 wpbc_catalog_booking_resource_inspector_send_error( $schema, 'wpbc_catalog_bulk_edition' === $schema->get_error_code() ? 403 : 400 );
48 }
49 wp_send_json_success( array( 'schema' => $schema ) );
50 }
51 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCES_BULK_SCHEMA', 'wpbc_catalog_booking_resources_ajax_bulk_schema' );
52
53 /**
54 * Return a signed old-to-new bulk-edit preview.
55 *
56 * @return void
57 */
58 function wpbc_catalog_booking_resources_ajax_bulk_preview() {
59 $authorized = wpbc_catalog_booking_resource_inspector_authorize();
60 if ( is_wp_error( $authorized ) ) {
61 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
62 }
63 $ids = wpbc_catalog_booking_resources_bulk_decode_json( 'resource_ids', __( 'The selected Booking Resources are invalid.', 'booking' ) );
64 $operations = wpbc_catalog_booking_resources_bulk_decode_json( 'operations', __( 'The bulk operations are invalid.', 'booking' ) );
65 if ( is_wp_error( $ids ) || is_wp_error( $operations ) ) {
66 wpbc_catalog_booking_resource_inspector_send_error( is_wp_error( $ids ) ? $ids : $operations );
67 }
68 $preview = ( new WPBC_Catalog_Booking_Resources_Bulk_Editor() )->preview( $ids, $operations );
69 if ( is_wp_error( $preview ) ) {
70 wpbc_catalog_booking_resource_inspector_send_error( $preview, 'wpbc_catalog_bulk_edition' === $preview->get_error_code() ? 403 : 400 );
71 }
72 wp_send_json_success( array( 'preview' => $preview ) );
73 }
74 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCES_BULK_PREVIEW', 'wpbc_catalog_booking_resources_ajax_bulk_preview' );
75
76 /**
77 * Apply a reviewed bulk update after mutation authorization and revalidation.
78 *
79 * @return void
80 */
81 function wpbc_catalog_booking_resources_ajax_bulk_apply() {
82 $authorized = wpbc_catalog_booking_resource_inspector_authorize( 'bulk_update' );
83 if ( is_wp_error( $authorized ) ) {
84 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
85 }
86 $ids = wpbc_catalog_booking_resources_bulk_decode_json( 'resource_ids', __( 'The selected Booking Resources are invalid.', 'booking' ) );
87 $operations = wpbc_catalog_booking_resources_bulk_decode_json( 'operations', __( 'The bulk operations are invalid.', 'booking' ) );
88 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above.
89 $review_token = isset( $_POST['review_token'] ) && is_scalar( $_POST['review_token'] ) ? sanitize_text_field( wp_unslash( (string) $_POST['review_token'] ) ) : '';
90 if ( is_wp_error( $ids ) || is_wp_error( $operations ) ) {
91 wpbc_catalog_booking_resource_inspector_send_error( is_wp_error( $ids ) ? $ids : $operations );
92 }
93 $result = ( new WPBC_Catalog_Booking_Resources_Bulk_Editor() )->apply( $ids, $operations, $review_token );
94 if ( is_wp_error( $result ) ) {
95 $status = 'wpbc_catalog_bulk_review_stale' === $result->get_error_code() ? 409 : 400;
96 if ( 'wpbc_catalog_bulk_edition' === $result->get_error_code() ) {
97 $status = 403;
98 }
99 wpbc_catalog_booking_resource_inspector_send_error( $result, $status );
100 }
101 wp_send_json_success(
102 array(
103 'updated_ids' => array_map( 'absint', $result['updated_ids'] ),
104 'message' => sprintf( _n( '%s Booking Resource updated.', '%s Booking Resources updated.', $result['updated_count'], 'booking' ), number_format_i18n( $result['updated_count'] ) ),
105 )
106 );
107 }
108 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCES_BULK_APPLY', 'wpbc_catalog_booking_resources_ajax_bulk_apply' );
109
110 /**
111 * Return a signed permanent-deletion review.
112 *
113 * @return void
114 */
115 function wpbc_catalog_booking_resources_ajax_delete_preview() {
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 $ids = wpbc_catalog_booking_resources_bulk_decode_json( 'resource_ids', __( 'The selected Booking Resources are invalid.', 'booking' ) );
121 if ( is_wp_error( $ids ) ) {
122 wpbc_catalog_booking_resource_inspector_send_error( $ids );
123 }
124 $preview = ( new WPBC_Catalog_Booking_Resources_Deleter() )->preview( $ids );
125 if ( is_wp_error( $preview ) ) {
126 $status = in_array( $preview->get_error_code(), array( 'wpbc_catalog_delete_demo', 'wpbc_catalog_delete_demo_seed', 'wpbc_catalog_delete_edition' ), true ) ? 403 : 400;
127 wpbc_catalog_booking_resource_inspector_send_error( $preview, $status );
128 }
129 wp_send_json_success( array( 'preview' => $preview ) );
130 }
131 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCES_DELETE_PREVIEW', 'wpbc_catalog_booking_resources_ajax_delete_preview' );
132
133 /**
134 * Permanently delete a reviewed Resource selection.
135 *
136 * @return void
137 */
138 function wpbc_catalog_booking_resources_ajax_delete_apply() {
139 $authorized = wpbc_catalog_booking_resource_inspector_authorize( 'delete' );
140 if ( is_wp_error( $authorized ) ) {
141 wpbc_catalog_booking_resource_inspector_send_error( $authorized, 403 );
142 }
143 $ids = wpbc_catalog_booking_resources_bulk_decode_json( 'resource_ids', __( 'The selected Booking Resources are invalid.', 'booking' ) );
144 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above.
145 $review_token = isset( $_POST['review_token'] ) && is_scalar( $_POST['review_token'] ) ? sanitize_text_field( wp_unslash( (string) $_POST['review_token'] ) ) : '';
146 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified above; this is an explicit destructive-action confirmation.
147 $acknowledged = isset( $_POST['acknowledged'] ) && is_scalar( $_POST['acknowledged'] ) && '1' === (string) wp_unslash( $_POST['acknowledged'] );
148 if ( is_wp_error( $ids ) ) {
149 wpbc_catalog_booking_resource_inspector_send_error( $ids );
150 }
151 if ( ! $acknowledged ) {
152 wpbc_catalog_booking_resource_inspector_send_error( new WP_Error( 'wpbc_catalog_delete_acknowledgement_required', __( 'Confirm that the selected Booking Resources will be permanently deleted.', 'booking' ) ) );
153 }
154 $result = ( new WPBC_Catalog_Booking_Resources_Deleter() )->delete( $ids, $review_token );
155 if ( is_wp_error( $result ) ) {
156 $status = 'wpbc_catalog_delete_review_stale' === $result->get_error_code() ? 409 : 400;
157 if ( in_array( $result->get_error_code(), array( 'wpbc_catalog_delete_demo', 'wpbc_catalog_delete_demo_seed', 'wpbc_catalog_delete_edition' ), true ) ) {
158 $status = 403;
159 }
160 wpbc_catalog_booking_resource_inspector_send_error( $result, $status );
161 }
162 wp_send_json_success(
163 array(
164 'deleted_ids' => array_map( 'absint', $result['deleted_ids'] ),
165 'message' => sprintf( _n( '%s Booking Resource deleted.', '%s Booking Resources deleted.', $result['deleted_count'], 'booking' ), number_format_i18n( $result['deleted_count'] ) ),
166 )
167 );
168 }
169 add_action( 'wp_ajax_WPBC_AJX_CATALOG_BOOKING_RESOURCES_DELETE_APPLY', 'wpbc_catalog_booking_resources_ajax_delete_apply' );
170