PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.19
Booktics – Appointment Booking Calendar for Service Businesses v1.0.19
1.0.25 1.0.24 1.0.23 1.0.22 1.0.21 1.0.20 1.0.19 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 All 27 releases
booktics / core / order / order-validator.php

order-validator.php in Booktics – Appointment Booking Calendar for Service Businesses 1.0.19, at core/order/order-validator.php

155 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Booktics\Order;
4
5 use Booktics\Models\Service_Model;
6 use Booktics\Models\Team_Member_Model;
7 use WP_Error;
8
9 class Order_Validator {
10 /**
11 * Validate order creation request
12 *
13 * @param array $data Order data
14 *
15 * @return true|WP_Error Returns true if valid, WP_Error otherwise
16 */
17 public function validate( array $data ) {
18 $error = new WP_Error();
19
20 // Validate basic required fields
21 $required_fields = array(
22 'items',
23 );
24
25 foreach ( $required_fields as $field ) {
26 if ( empty( $data[ $field ] ) ) {
27 /* translators: %s: Field name */
28 $error->add( 'missing_field', sprintf( __( '%s is required', 'booktics' ), $field ) );
29 }
30 }
31
32 if ( empty( $data['customer_id'] ) && empty( $data['customer']['email'] ) ) {
33 $error->add( 'missing_field', __( 'Customer email is required', 'booktics' ) );
34 }
35
36 if ( empty( $data['items'] ) || ! is_array( $data['items'] ) ) {
37 $error->add( 'invalid_items', __( 'Order must contain at least one item', 'booktics' ) );
38
39 return $error;
40 }
41
42 foreach ( $data['items'] as $item ) {
43 $item_validation = $this->validate_order_item( $item );
44 if ( is_wp_error( $item_validation ) ) {
45 return $item_validation;
46 }
47 }
48
49 return $error->has_errors() ? $error : true;
50 }
51
52 /**
53 * Validate individual order item
54 *
55 * @param array $item Order item data
56 *
57 * @return true|WP_Error Returns true if valid, WP_Error otherwise
58 */
59 private function validate_order_item( array $item ) {
60 $error = new WP_Error();
61
62 $service = ( new Service_Model() )->find( $item['service_id'] );
63 if ( ! $service ) {
64 $error->add( 'invalid_service', __( 'Invalid service selected', 'booktics' ) );
65 }
66
67 $team_member = ( new Team_Member_Model() )->find( $item['team_member_id'] );
68 if ( ! $team_member ) {
69 $error->add( 'invalid_team_member', __( 'Invalid team member selected', 'booktics' ) );
70 }
71 $error = apply_filters( 'booktics_extra_service_validate', $error, $item );
72
73 return $error->has_errors() ? $error : true;
74 }
75
76 /**
77 * Validate time slot availability
78 *
79 * @param array $item Order item data
80 *
81 * @return true|WP_Error Returns true if valid, WP_Error otherwise
82 */
83 private function validate_time_slot( array $item ) {
84 $error = new WP_Error();
85
86 $args = array(
87 'post_type' => 'booktics-appointment',
88 'post_status' => 'any',
89 'posts_per_page' => 1,
90 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Meta query is necessary for filtering appointments by meta fields
91 'meta_query' => array(
92 'relation' => 'AND',
93 array(
94 'key' => 'date',
95 'value' => $item['date'],
96 'compare' => '=',
97 ),
98 array(
99 'key' => 'team_member_id',
100 'value' => $item['team_member_id'],
101 'compare' => '=',
102 ),
103 array(
104 'relation' => 'OR',
105 // Appointment starts during requested time slot
106 array(
107 'relation' => 'AND',
108 array(
109 'key' => 'start_time',
110 'value' => $item['start_time'],
111 'compare' => '<=',
112 ),
113 array(
114 'key' => 'end_time',
115 'value' => $item['start_time'],
116 'compare' => '>',
117 ),
118 ),
119 // Appointment ends during requested time slot
120 array(
121 'relation' => 'AND',
122 array(
123 'key' => 'start_time',
124 'value' => $item['end_time'],
125 'compare' => '<',
126 ),
127 array(
128 'key' => 'end_time',
129 'value' => $item['end_time'],
130 'compare' => '>=',
131 ),
132 ),
133 ),
134 ),
135 );
136
137 $query = new \WP_Query( $args );
138
139 if ( $query->have_posts() ) {
140 $error->add(
141 'time_slot_unavailable',
142 sprintf(
143 /* translators: 1: Start time, 2: End time, 3: Date */
144 __( 'Time slot %1$s - %2$s on %3$s is not available', 'booktics' ),
145 $item['start_time'],
146 $item['end_time'],
147 $item['date']
148 )
149 );
150 }
151
152 return $error->has_errors() ? $error : true;
153 }
154 }
155