PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
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 10.11 All 204 releases
booking / includes / page-appointment-services / ajax / appointment_services__list.php

appointment_services__list.php in Booking Calendar 11.8.4, at includes/page-appointment-services/ajax/appointment_services__list.php

142 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * AJAX list endpoint for the template-driven Appointment Services catalog.
4 *
5 * @package Booking Calendar
6 * @since 11.6.0
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Return a safe request sequence from an untrusted payload.
15 *
16 * @param mixed $request_values Untrusted request values.
17 *
18 * @return int Non-negative request sequence or zero.
19 */
20 function wpbc_appointment_services_get_catalog_request_id( $request_values ) {
21 if ( ! is_array( $request_values ) || ! isset( $request_values['request_id'] ) || ! is_scalar( $request_values['request_id'] ) ) {
22 return 0;
23 }
24
25 return preg_match( '/^\d+$/', (string) $request_values['request_id'] ) ? (int) $request_values['request_id'] : 0;
26 }
27
28 /**
29 * Send a normalized Services catalog error.
30 *
31 * @param int $request_id Client request sequence.
32 * @param WP_Error $error Safe error.
33 * @param int $status HTTP status.
34 * @param bool $retryable Whether the browser may retry.
35 *
36 * @return void Terminates the AJAX request.
37 */
38 function wpbc_appointment_services_send_catalog_error( $request_id, $error, $status, $retryable = false ) {
39 wp_send_json(
40 WPBC_UI_Catalog_Response::from_wp_error( 'appointment_services_catalog', $request_id, $error, $retryable ),
41 absint( $status )
42 );
43 }
44
45 /**
46 * Serve the authorized Service list through the shared catalog contract.
47 *
48 * Transport authorization and request normalization stay here. The Service
49 * repository owns SQL and ownership, while the DTO owns the item contract.
50 *
51 * @return void Terminates the AJAX request.
52 */
53 function wpbc_appointment_services_ajax_list() {
54 $configuration = WPBC_UI_Catalog_Registry::get_instance()->get_configuration( 'appointment_services_catalog' );
55 if ( empty( $configuration ) ) {
56 wpbc_appointment_services_send_catalog_error( 0, new WP_Error( 'wpbc_appointment_services_unavailable', __( 'The Services catalog is unavailable.', 'booking' ) ), 503, true );
57 }
58
59 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified immediately below.
60 $raw_request = is_array( $_POST ) ? wp_unslash( $_POST ) : array();
61 $request_id = wpbc_appointment_services_get_catalog_request_id( $raw_request );
62 if ( false === check_ajax_referer( $configuration['nonce_name'], 'nonce', false ) ) {
63 wpbc_appointment_services_send_catalog_error( $request_id, new WP_Error( 'wpbc_appointment_services_invalid_nonce', __( 'Security check failed.', 'booking' ) ), 403 );
64 }
65 if ( ! current_user_can( wpbc_appointment_services_get_manage_capability() ) ) {
66 wpbc_appointment_services_send_catalog_error( $request_id, new WP_Error( 'wpbc_appointment_services_forbidden', __( 'You do not have permission to view Services.', 'booking' ) ), 403 );
67 }
68
69 $preference_action = isset( $raw_request['preference_action'] ) && is_scalar( $raw_request['preference_action'] ) ? sanitize_key( (string) $raw_request['preference_action'] ) : '';
70 if ( ! in_array( $preference_action, array( '', 'save', 'reset' ), true ) ) {
71 wpbc_appointment_services_send_catalog_error( $request_id, new WP_Error( 'wpbc_appointment_services_invalid_preferences', __( 'The catalog preference request is invalid.', 'booking' ) ), 400 );
72 }
73 $preference_revision = isset( $raw_request['preference_revision'] ) && is_scalar( $raw_request['preference_revision'] ) && preg_match( '/^\d+$/', (string) $raw_request['preference_revision'] )
74 ? (string) $raw_request['preference_revision']
75 : '0';
76 if ( isset( $raw_request['preferences_only'] ) && ( ! is_scalar( $raw_request['preferences_only'] ) || ! in_array( (string) $raw_request['preferences_only'], array( '0', '1' ), true ) ) ) {
77 wpbc_appointment_services_send_catalog_error( $request_id, new WP_Error( 'wpbc_appointment_services_invalid_preferences', __( 'The catalog preference request is invalid.', 'booking' ) ), 400 );
78 }
79 $preferences_only = isset( $raw_request['preferences_only'] ) && '1' === (string) $raw_request['preferences_only'];
80 if ( '' !== $preference_action && '0' === $preference_revision ) {
81 wpbc_appointment_services_send_catalog_error( $request_id, new WP_Error( 'wpbc_appointment_services_invalid_preferences', __( 'The catalog preference revision is invalid.', 'booking' ) ), 400 );
82 }
83 if ( $preferences_only && 'save' !== $preference_action ) {
84 wpbc_appointment_services_send_catalog_error( $request_id, new WP_Error( 'wpbc_appointment_services_invalid_preferences', __( 'The catalog preference request is invalid.', 'booking' ) ), 400 );
85 }
86 if ( 'reset' === $preference_action && ! WPBC_UI_Catalog_Preferences::reset( 'appointment_services_catalog', 0, $preference_revision ) ) {
87 wpbc_appointment_services_send_catalog_error( $request_id, new WP_Error( 'wpbc_appointment_services_preference_reset_failed', __( 'The catalog preferences could not be reset.', 'booking' ) ), 500, true );
88 }
89
90 $stored_preferences = WPBC_UI_Catalog_Preferences::load( 'appointment_services_catalog' );
91 $shared_keys = array( 'request_id', 'page_number', 'items_per_page', 'sort_by', 'sort_order', 'search', 'visible_columns', 'column_order', 'template_pack' );
92 $shared_request = WPBC_UI_Catalog_Request::create(
93 $configuration,
94 array_intersect_key( $raw_request, array_fill_keys( $shared_keys, true ) ),
95 $stored_preferences
96 );
97 if ( is_wp_error( $shared_request ) ) {
98 wpbc_appointment_services_send_catalog_error( $request_id, $shared_request, 400 );
99 }
100
101 $service_values = array(
102 'status' => isset( $stored_preferences['status'] ) ? $stored_preferences['status'] : 'all',
103 'resource_id' => isset( $stored_preferences['resource_id'] ) ? $stored_preferences['resource_id'] : 0,
104 );
105 foreach ( array( 'status', 'resource_id' ) as $service_key ) {
106 if ( array_key_exists( $service_key, $raw_request ) ) {
107 $service_values[ $service_key ] = $raw_request[ $service_key ];
108 }
109 }
110 $service_request = WPBC_Appointment_Services_Catalog_Request::create( $service_values );
111 if ( is_wp_error( $service_request ) ) {
112 wpbc_appointment_services_send_catalog_error( $request_id, $service_request, 400 );
113 }
114
115 if ( 'save' === $preference_action ) {
116 $preference_result = WPBC_UI_Catalog_Preferences::save(
117 'appointment_services_catalog',
118 $shared_request,
119 array(
120 'status' => $service_request->get( 'status', 'all' ),
121 'resource_id' => $service_request->get( 'resource_id', 0 ),
122 ),
123 0,
124 $preference_revision
125 );
126 if ( is_wp_error( $preference_result ) ) {
127 wpbc_appointment_services_send_catalog_error( $request_id, $preference_result, 400 );
128 }
129 }
130 if ( $preferences_only ) {
131 wp_send_json( array( 'success' => true, 'request_id' => $request_id ), 200 );
132 }
133
134 $response = ( new WPBC_Appointment_Services_Catalog_Provider( wpbc_appointment_services_get_data_provider(), null, $service_request ) )->get_response( $shared_request );
135 if ( is_wp_error( $response ) ) {
136 wpbc_appointment_services_send_catalog_error( $request_id, $response, 500, true );
137 }
138
139 wp_send_json( $response->to_array(), 200 );
140 }
141 add_action( 'wp_ajax_WPBC_AJX_APPOINTMENT_SERVICES_LIST', 'wpbc_appointment_services_ajax_list' );
142