PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.64
Timetics – Appointment Booking Calendar & Scheduling v1.0.64
1.0.64 1.0.62 1.0.63 1.0.61 1.0.60 1.0.59 1.0.58 1.0.57 1.0.56 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.19 1.0.2 1.0.20 1.0.21 All 65 releases
← All changes | core/customers/api-customer.php +84 -24 1.0.14 → 1.0.64 View file →
@@ -5,8 +5,10 @@
5 5 * @package Timetics
6 6 */
7 7 namespace Timetics\Core\Customers;
8 8
9 +defined( 'ABSPATH' ) || exit;
10 +
9 11 use Timetics\Base\Api;
10 12 use Timetics\Core\Bookings\Api_Booking;
11 13 use Timetics\Utils\Singleton;
12 14 use WP_HTTP_Response;
@@ -57,9 +59,9 @@
57 59 [
58 60 'methods' => \WP_REST_Server::DELETABLE,
59 61 'callback' => [$this, 'bulk_delete'],
60 62 'permission_callback' => function () {
61 - return current_user_can( 'manage_timetics' );
63 + return current_user_can( 'manage_options' );
62 64 },
63 65 ],
64 66 ]
65 67 );
@@ -73,24 +75,31 @@
73 75 $this->namespace, '/' . $this->rest_base . '/(?P<customer_id>[\d]+)', [
74 76 [
75 77 'methods' => \WP_REST_Server::READABLE,
76 78 'callback' => [$this, 'get_item'],
77 - 'permission_callback' => function () {
78 - return current_user_can( 'timetics-customer' );
79 + 'permission_callback' => function ( $request ) {
80 + $customer_id = (int) $request['customer_id'];
81 +
82 + if ( timetics_can_view_all_data() || get_current_user_id() === $customer_id ) {
83 + return true;
84 + }
85 +
86 + // manage_timetics is not admin-only — staff may only view a
87 + // customer they actually have a visible booking with.
88 + return current_user_can( 'manage_timetics' )
89 + && in_array( $customer_id, timetics_get_visible_customer_ids(), true );
79 90 },
80 91 ],
81 92 [
82 93 'methods' => \WP_REST_Server::EDITABLE,
83 - 'callback' => [$this, 'update_item'],
84 - 'permission_callback' => function () {
85 - return current_user_can( 'timetics-customer' );
86 - },
94 + 'callback' => [$this, 'update_item'],
95 + 'permission_callback' => [$this, 'update_item_permission_callback'],
87 96 ],
88 97 [
89 98 'methods' => \WP_REST_Server::DELETABLE,
90 99 'callback' => [$this, 'delete_item'],
91 100 'permission_callback' => function () {
92 - return current_user_can( 'timetics-customer' );
101 + return current_user_can( 'manage_options' );
93 102 },
94 103 ],
95 104 ]
96 105 );
@@ -100,9 +109,9 @@
100 109 [
101 110 'methods' => \WP_REST_Server::READABLE,
102 111 'callback' => [$this, 'search_items'],
103 112 'permission_callback' => function () {
104 - return current_user_can( 'edit_posts' );
113 + return current_user_can( 'manage_timetics' );
105 114 },
106 115 ],
107 116 ]
108 117 );
@@ -116,10 +125,17 @@
116 125 $this->namespace, '/' . $this->rest_base . '/(?P<customer_id>[\d]+)/bookings', [
117 126 [
118 127 'methods' => \WP_REST_Server::READABLE,
119 128 'callback' => [$this, 'get_bookings'],
120 - 'permission_callback' => function () {
121 - return current_user_can( 'timetics-customer' );
129 + 'permission_callback' => function ( $request ) {
130 + $customer_id = (int) $request['customer_id'];
131 +
132 + if ( timetics_can_view_all_data() || get_current_user_id() === $customer_id ) {
133 + return true;
134 + }
135 +
136 + return current_user_can( 'manage_timetics' )
137 + && in_array( $customer_id, timetics_get_visible_customer_ids(), true );
122 138 },
123 139 ],
124 140 ]
125 141 );
@@ -135,15 +151,20 @@
135 151 public function get_items( $request ) {
136 152 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
137 153 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
138 154
139 - $customer = Customer::all(
140 - [
141 - 'number' => $per_page,
142 - 'paged' => $paged,
143 - ]
144 - );
155 + $args = [
156 + 'number' => $per_page,
157 + 'paged' => $paged,
158 + ];
145 159
160 + // Staff only see customers from their own bookings, administrators see everyone.
161 + if ( ! timetics_can_view_all_data() ) {
162 + $args['include'] = timetics_get_visible_customer_ids( get_current_user_id() );
163 + }
164 +
165 + $customer = Customer::all( $args );
166 +
146 167 $items = [];
147 168
148 169 foreach ( $customer['items'] as $item ) {
149 170 $items[] = $this->prepare_item( $item->ID );
@@ -208,15 +229,24 @@
208 229 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
209 230 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
210 231 $search = ! empty( $request['search'] ) ? sanitize_text_field( $request['search'] ) : '';
211 232
233 + $query_args = array(
234 + 'role' => 'timetics-customer',
235 + 'number' => $per_page,
236 + 'paged' => $paged,
237 + );
238 +
239 + // Staff only see customers from their own bookings, administrators see everyone.
240 + if ( ! timetics_can_view_all_data() ) {
241 + $query_args['include'] = timetics_get_visible_customer_ids( get_current_user_id() );
242 + }
243 +
212 244 // Get search.
213 245 $users = new WP_User_Query(
214 - array(
215 - 'role' => 'timetics-customer',
216 - 'number' => $per_page,
217 - 'paged' => $paged,
218 -
246 + array_merge(
247 + $query_args,
248 + array(
219 249 // @codingStandardsIgnoreStart
220 250 'meta_query' => array(
221 251 'relation' => 'OR',
222 252 array(
@@ -240,8 +270,9 @@
240 270 'compare' => 'LIKE',
241 271 ),
242 272 ),
243 273 // @codingStandardsIgnoreEnd
274 + )
244 275 )
245 276 );
246 277
247 278 // Prepare items for response.
@@ -274,8 +305,37 @@
274 305 return $this->save_customer( $request );
275 306 }
276 307
277 308 /**
309 + * Update customer Permission check
310 + *
311 + * @param WP_Rest_Request $request
312 + *
313 + * @return JSON | WP_Error
314 + */
315 + public function update_item_permission_callback( $request ) {
316 + $customer_id = (int) $request['customer_id'];
317 +
318 + // Admins can always update any customer. manage_timetics is not
319 + // admin-only — every timetics-staff account has it — so it must not
320 + // grant edit access to someone else's customer record.
321 + if ( current_user_can( 'manage_options' ) ) {
322 + return true;
323 + }
324 +
325 + // Customers can update themselves with a valid nonce
326 + $nonce = $request->get_header( 'X-WP-Nonce' );
327 + if ( ! empty( $nonce ) && wp_verify_nonce( $nonce, 'wp_rest' ) ) {
328 + $current_user_id = get_current_user_id();
329 + if ( $customer_id === $current_user_id && $current_user_id > 0 ) {
330 + return true;
331 + }
332 + }
333 +
334 + return false;
335 + }
336 +
337 + /**
278 338 * Update customer
279 339 *
280 340 * @param WP_Rest_Request $request
281 341 *
@@ -494,9 +554,8 @@
494 554 'last_name' => $customer->get_last_name(),
495 555 'email' => $customer->get_email(),
496 556 'phone' => $customer->get_phone(),
497 557 'image' => $customer->get_image(),
498 - 'password' => $customer->get_password(),
499 558 'total_booking' => $customer->get_total_booking(),
500 559 ];
501 560 }
502 561
@@ -541,8 +600,9 @@
541 600 'post_type' => 'timetics-booking',
542 601 'posts_per_page' => $per_page,
543 602 'paged' => $paged,
544 603 'post_status' => 'any',
604 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Meta query is necessary for filtering bookings by customer
545 605 'meta_query' => array(
546 606 'relation' => 'OR',
547 607 array(
548 608 'key' => '_tt_booking_customer',
@@ -559,9 +619,9 @@
559 619 $items = [];
560 620 $booking = new Api_Booking();
561 621
562 622 foreach ( $bookings->posts as $item ) {
563 - $items[] = $booking->prepare_item( $item->ID );
623 + $items[] = $booking->prepare_item( $item->ID, false );
564 624 }
565 625
566 626 $data = [
567 627 'success' => 1,