PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.14
Booktics – Appointment Booking Calendar for Service Businesses v1.0.14
1.0.29 1.0.28 1.0.27 1.0.26 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 All 31 releases
booktics / core / team-member / controllers / team-member-controller.php

team-member-controller.php in Booktics – Appointment Booking Calendar for Service Businesses 1.0.14, at core/team-member/controllers/team-member-controller.php

638 lines 22.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\Team_Member\Controllers;
4
5 use Booktics\Abstracts\Base_Rest_Controller;
6 use Booktics\Abstracts\User_Model;
7 use Booktics\Models\Service_Model;
8 use Booktics\Models\Team_Member_Model;
9 use Booktics\Services\Schedule_Manager;
10 use Booktics\Services\Schedule_Record;
11 use Booktics\Team_Member\Handlers\Team_Member_Event_Handler;
12 use Exception;
13 use WP_Error;
14 use WP_HTTP_Response;
15 use WP_REST_Response;
16 use WP_REST_Server;
17
18 /**
19 * Team member controller
20 *
21 * @package Booktics/Team_Member
22 */
23 class Team_Member_Controller extends Base_Rest_Controller {
24
25 /**
26 * Endpoint namespace
27 *
28 * @var string
29 */
30 protected $namespace = 'booktics/v1';
31
32 /**
33 * Route name
34 *
35 * @var string
36 */
37 protected $base = 'team-members';
38
39 /**
40 * Register routes
41 *
42 * @return void
43 */
44 public function register_routes(): void {
45 register_rest_route(
46 $this->namespace, $this->base, array(
47 array(
48 'methods' => WP_REST_Server::CREATABLE,
49 'callback' => array( $this, 'create_item' ),
50 'permission_callback' => array(
51 $this,
52 'create_team_member_permission',
53 ),
54 ),
55 array(
56 'methods' => WP_REST_Server::READABLE,
57 'callback' => array( $this, 'get_items' ),
58 'permission_callback' => array(
59 $this,
60 'get_team_member_permission',
61 ),
62 ),
63 array(
64 'methods' => WP_REST_Server::DELETABLE,
65 'callback' => array( $this, 'delete_items' ),
66 'permission_callback' => array(
67 $this,
68 'delete_team_member_permission',
69 ),
70 ),
71 )
72 );
73
74 register_rest_route(
75 $this->namespace, $this->base.'/profile', array(
76 array(
77 'methods' => WP_REST_Server::READABLE,
78 'callback' => array( $this, 'get_profile' ),
79 'permission_callback' => array(
80 $this,
81 'get_team_member_profile_permission',
82 ),
83 ),
84 )
85 );
86
87 register_rest_route(
88 $this->namespace, '/' . $this->base . '/(?P<id>[\d]+)', array(
89 array(
90 'methods' => WP_REST_Server::EDITABLE,
91 'callback' => array( $this, 'update_item' ),
92 'permission_callback' => array(
93 $this,
94 'update_team_member_permission',
95 ),
96 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
97 ),
98 array(
99 'methods' => WP_REST_Server::DELETABLE,
100 'callback' => array( $this, 'delete_item' ),
101 'permission_callback' => array(
102 $this,
103 'delete_team_member_permission',
104 ),
105 ),
106 array(
107 'method' => WP_REST_Server::READABLE,
108 'callback' => array( $this, 'get_item' ),
109 'permission_callback' => array(
110 $this,
111 'get_team_member_permission',
112 ),
113 ),
114 )
115 );
116
117 register_rest_route(
118 $this->namespace, '/' . $this->base . '/(?P<id>[\d]+)/reinvites', array(
119 array(
120 'methods' => WP_REST_Server::READABLE,
121 'callback' => array( $this, 'reinvite' ),
122 'permission_callback' => array(
123 $this,
124 'create_team_member_permission',
125 ),
126 ),
127 )
128 );
129 }
130
131 /**
132 * Check if a given request has access to create items.
133 *
134 * @param $request
135 *
136 * @return mixed
137 */
138 public function create_team_member_permission( $request ) {
139 return current_user_can( 'manage_options' );
140 }
141
142 /**
143 * Prepare and validate team member data
144 *
145 * @param $request
146 *
147 * @return array|bool|WP_Error
148 */
149 protected function prepare_team_member_data( $request ) {
150 $input_data = json_decode( $request->get_body(), true );
151
152 $validate = booktics_validate(
153 $input_data, array(
154 'first_name' => array(
155 'required',
156 ),
157 'email' => array(
158 'required',
159 'unique:wp_users,email',
160 ),
161 )
162 );
163
164 if ( is_wp_error( $validate ) ) {
165 return $validate;
166 }
167
168 return array(
169 'first_name' => $input_data['first_name'],
170 'last_name' => $input_data['last_name'],
171 'user_email' => $input_data['email'],
172 'user_login' => User_Model::generate_username( $input_data['email'] ),
173 'phone' => $input_data['phone'],
174 'email' => $input_data['email'],
175 'status' => 'pending',
176 'enable_custom_holiday' => $input_data['enable_custom_holiday'] ?? false,
177 'enable_custom_schedule' => $input_data['enable_custom_schedule'] ?? false,
178 'enable_custom_availability' => $input_data['enable_custom_availability'] ?? false,
179 );
180 }
181
182 /**
183 * Store new team member data
184 *
185 * @param $request
186 *
187 * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
188 */
189 public function create_item( $request ) {
190 $prepared_data = $this->prepare_team_member_data( $request );
191 if ( is_wp_error( $prepared_data ) ) {
192 return $this->error(
193 $prepared_data->get_error_message(),
194 422,
195 'Validation',
196 $prepared_data->errors
197 );
198 }
199
200 $all_team_members = ( new Team_Member_Model() )->all( array() );
201 if ( ! is_booktics_pro() && isset( $all_team_members['total'] ) && $all_team_members['total'] >= 3 ) {
202 return $this->error(
203 'Team member limit reached for free plan.',
204 422,
205 'Validation'
206 );
207 }
208
209 $team_member = new Team_Member_Model();
210 $created = $team_member->save( $prepared_data );
211
212 $image_url = $request->get_param( 'image' );
213 if ( $image_url ) {
214 $team_member->update( array( 'image' => esc_url_raw( $image_url ) ) );
215 }
216
217 if ( ! $created ) {
218 return $this->error( __( 'Team member create error', 'booktics' ), 500 );
219 }
220
221 do_action( 'booktics_team_member_created', $team_member, $request );
222
223 ( new Team_Member_Event_Handler() )->on_team_member_create( $created );
224
225 return $this->response( $team_member->find( $created )->to_array(), __( 'Successfully created team member', 'booktics' ), 201 );
226 }
227
228 /**
229 * Check if a given request has access to get all team member
230 *
231 * @param $request
232 *
233 * @return bool
234 */
235 public function get_team_member_permission( $request ) {
236 return true;
237 }
238
239 /**
240 * Get paginated list items for team member
241 *
242 * @param $request
243 *
244 * @return WP_Error|WP_HTTP_Response|WP_REST_Response
245 */
246 public function get_items( $request ) {
247 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
248 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
249 $first_name = ! empty( $request['first_name'] ) ? trim( $request['first_name'] ) : '';
250 $last_name = ! empty( $request['last_name'] ) ? trim( $request['last_name'] ) : '';
251 $email = ! empty( $request['email'] ) ? trim( $request['email'] ) : '';
252 $phone = ! empty( $request['phone'] ) ? trim( $request['phone'] ) : '';
253 $user_name = ! empty( $request['user_name'] ) ? trim( $request['user_name'] ) : '';
254 $status = ! empty( $request['status'] ) ? trim( $request['status'] ) : '';
255 $service_id = ! empty( $request['service_id'] ) ? trim( $request['service_id'] ) : '';
256 $search = ! empty( $request['search'] ) ? trim( $request['search'] ) : '';
257
258 $team_members = ( new Team_Member_Model() )
259 ->when(
260 $first_name, function ( $q, $v ) {
261 $q->where( 'first_name', $v, 'LIKE' );
262 }
263 )
264 ->when(
265 $last_name, function ( $q, $v ) {
266 $q->where( 'last_name', $v, 'LIKE' );
267 }
268 )
269 ->when(
270 $email, function ( $q, $v ) {
271 $q->where( 'user_email', $v, 'LIKE' );
272 }
273 )
274 ->when(
275 $phone, function ( $q, $v ) {
276 $q->where( 'phone', $v, 'LIKE' );
277 }
278 )
279 ->when(
280 $user_name, function ( $q, $v ) {
281 $q->where( 'user_login', $v, 'LIKE' );
282 }
283 )
284 ->when(
285 $service_id, function ( $q, $v ) {
286 $q->where( 'services', $v, 'LIKE' );
287 }
288 )
289 ->when(
290 $status, function ( $q, $v ) {
291 $q->where( 'status', $v, 'LIKE' );
292 }
293 )
294 ->when(
295 $search, function ( $q, $v ) {
296 $q->where( 'first_name', $v, 'LIKE' )
297 ->or_where( 'last_name', $v, 'LIKE' )
298 ->or_where( 'phone', $v, 'LIKE' );
299 }
300 )->all(
301 array(
302 'paged' => $paged,
303 'number' => $per_page,
304 )
305 );
306
307 return $this->response( $team_members );
308 }
309
310 /**
311 * Checks if a given request has access to update a team member.
312 *
313 * @param $request
314 *
315 * @return bool
316 */
317 public function update_team_member_permission( $request ) {
318 return current_user_can( 'manage_options' );
319 }
320
321 /**
322 * Updates a single team member.
323 *
324 * @param $request
325 *
326 * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
327 * @throws Exception
328 */
329 public function update_item( $request ) {
330 if ( ! isset( $request['id'] ) ) {
331 return $this->error( __( 'Invalid team member id', 'booktics' ), 400 );
332 }
333 $team_member = ( new Team_Member_Model( $request['id'] ) );
334
335 if ( isset( $request['password'] ) ) {
336 $current_password = sanitize_text_field( $request['current_password'] ?? '' );
337 $new_password = sanitize_text_field( $request['password'] ?? '' );
338 $confirm_password = sanitize_text_field( $request['confirm_password'] ?? '' );
339
340 $validate = booktics_validate(
341 array(
342 'current_password' => $current_password,
343 'password' => $new_password,
344 'confirm_password' => $confirm_password,
345 ), array(
346 'current_password' => array( 'required' ),
347 'password' => array( 'required' ),
348 'confirm_password' => array( 'required' ),
349 )
350 );
351
352 if ( is_wp_error( $validate ) ) {
353 return $validate;
354 }
355
356 $user = wp_get_current_user();
357
358 if ( ! wp_check_password( $current_password, $user->user_pass, $user->ID ) ) {
359 return $this->error( __( 'Current password is incorrect.', 'booktics' ), 401 );
360 }
361
362 wp_set_password( $new_password, $user->ID );
363
364 return $this->response(
365 $team_member->find( $request['id'] )->to_array(),
366 __( 'Successfully updated team member', 'booktics' )
367 );
368 }
369
370 $prepared_data = $this->prepare_team_member_update( $request );
371 if ( is_wp_error( $prepared_data ) ) {
372 return $this->error( $prepared_data->get_error_message(), 422, 'Validation', $prepared_data->errors );
373 }
374
375 $updated = $team_member->update( $prepared_data );
376 // First handle adding team member to new services
377 foreach ( $prepared_data['services'] as $service ) {
378 $service_model = Service_Model::find( $service );
379 $service_team_member = $service_model->team_member == '' ? array() : $service_model->team_member;
380 if ( ! in_array( (int) $team_member->id, $service_team_member ) ) {
381 $service_team_member[] = (int) $request['id'];
382 if ( $service_model ) {
383 $service_model->update( array( 'team_member' => $service_team_member ) );
384 }
385 }
386 }
387
388 // Then remove team member from services they're no longer assigned to
389 $services = Service_Model::query()
390 ->where( 'team_member', $request['id'], 'LIKE' )
391 ->where_not_ids( $prepared_data['services'] )
392 ->get();
393
394 foreach ( $services as $service ) {
395 if ( $service->team_member ) {
396 $service_team_members = array_diff( $service->team_member, array( (int) $request['id'] ) );
397 Service_Model::find( $service->id )->update( array( 'team_member' => $service_team_members ) );
398 }
399 }
400 $image_url = $request->get_param( 'image' );
401 if ( $image_url ) {
402 $team_member->update( array( 'image' => esc_url_raw( $image_url ) ) );
403 }
404
405 if ( ! $updated ) {
406 return $this->error( __( 'Team member update error', 'booktics' ), 500 );
407 }
408 if ( isset( $request['schedule'] ) || isset( $request['custom'] ) || isset( $request['holiday'] ) ) {
409 $input_data = json_decode( $request->get_body(), true );
410 $team_member_schedule = Schedule_Manager::make( $input_data );
411 $team_member_schedule->with_team_member_id( $request['id'] );
412 $team_member_schedule->save();
413 }
414
415 do_action( 'booktics_team_member_updated', $team_member, $request );
416
417 $team_member = $team_member->find( $request['id'] )->to_array();
418 $schedule_record = ( new Schedule_Record() )->get_schedules( $request['id'] );
419 $team_member['schedule'] = empty( $schedule_record['schedule'] )
420 ? (object) array() : $schedule_record['schedule'];
421 $team_member['custom'] = $schedule_record['custom'];
422 $team_member['holiday'] = $schedule_record['holiday'];
423
424 return $this->response(
425 $team_member,
426 __( 'Successfully updated team member', 'booktics' )
427 );
428 }
429
430 /**
431 * Prepare data for team member update
432 *
433 * @param $request
434 *
435 * @return array|bool|WP_Error
436 */
437 public function prepare_team_member_update( $request ) {
438 $input_data = json_decode( $request->get_body(), true );
439 $validation_rules = array(
440 'first_name' => array(
441 'required',
442 ),
443 'email' => array(
444 'required',
445 'unique:wp_users,email,' . $request['id'],
446 ),
447 );
448 $update_validation_rules = array();
449 $validated_data = array();
450 foreach ( $input_data as $key => $value ) {
451 $validated_data[ $key ] = $value;
452 if ( ! isset( $validation_rules[ $key ] ) ) {
453 continue;
454 }
455 $update_validation_rules[ $key ] = $validation_rules[ $key ];
456 if ( $key == 'email' ) {
457 $update_validation_rules[ $key ] = $validation_rules[ $key ];
458 $validated_data['user_email'] = sanitize_email( $value );
459 }
460 }
461 $validate = booktics_validate( $input_data, $update_validation_rules );
462
463 if ( is_wp_error( $validate ) ) {
464 return $validate;
465 }
466
467 $validated_data['services'] = ! empty( $input_data['services'] ) ? $input_data['services'] : array();
468 //$validated_data['status'] = 'active';
469
470 return $validated_data;
471 }
472
473 /**
474 * Checks if a given request has access to delete a team member.
475 *
476 * @param $request
477 *
478 * @return bool
479 */
480 public function delete_team_member_permission( $request ) {
481 return current_user_can( 'manage_options' );
482 }
483
484 /**
485 * Delete a team member
486 *
487 * @param $request
488 *
489 * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
490 */
491 public function delete_item( $request ) {
492 $id = intval( $request['id'] );
493
494 $team_member = new Team_Member_Model( $id );
495 $previous = $team_member->find( $id );
496
497 // Remove team member from assigned services
498 $services = Service_Model::query()->where( 'team_member', $id, 'LIKE' )->get();
499 foreach ( $services as $service ) {
500 if ( $service->team_member ) {
501 $service_team_members = array_diff( $service->team_member, array( $id ) );
502 Service_Model::find( $service->id )->update( array( 'team_member' => $service_team_members ) );
503 }
504 }
505
506 $deleted = $team_member->delete();
507
508 if ( ! $deleted ) {
509 return $this->error( __( 'Team member delete error', 'booktics' ), 500 );
510 }
511
512 do_action( 'booktics_team_members_deleted', $request );
513
514 return $this->response( $previous, __( 'Successfully deleted team member', 'booktics' ) );
515 }
516
517 /**
518 * Delete multiple team member
519 *
520 * @param $request
521 *
522 * @return array|WP_Error|WP_HTTP_Response
523 */
524 public function delete_items( $request ) {
525 $ids = ! empty( $request['ids'] ) ? $request['ids'] : array();
526
527 if ( ! $ids ) {
528 return $this->error( __( 'Team member ids cannot be empty', 'booktics' ), 500 );
529 }
530 $count = 0;
531 foreach ( $ids as $id ) {
532 $team_member = new Team_Member_Model( $id );
533 if ( $team_member->delete() ) {
534 ++$count;
535 }
536 }
537 if ( $count == 0 ) {
538 return $this->error( __( 'Team member delete error', 'booktics' ), 500 );
539 }
540
541 do_action( 'booktics_team_members_deleted', $request );
542
543 return $this->response( array(), __( 'Successfully deleted team member', 'booktics' ) );
544 }
545
546 /**
547 * Get single team member
548 *
549 * @param $request
550 *
551 * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
552 */
553 public function get_item( $request ) {
554 $id = intval( $request['id'] );
555 $team_member = new Team_Member_Model( $id );
556 $team_member = $team_member->find( $id );
557 if ( ! $team_member ) {
558 return $this->error( __( 'Team member not found', 'booktics' ), 404 );
559 }
560 $team_member = $team_member->to_array();
561 $schedule_record = ( new Schedule_Record() )->get_schedules( $request['id'] );
562 $team_member['schedule'] = ! empty( $schedule_record['schedule'] ) ? $schedule_record['schedule'] : $team_member['schedule'];
563 $team_member['custom'] = ! empty( $schedule_record['custom'] ) ? $schedule_record['custom'] : $team_member['custom'];
564 $team_member['holiday'] = ! empty( $schedule_record['holiday'] ) ? $schedule_record['holiday'] : $team_member['holiday'];
565
566 // Add filter to allow modifying team member data
567 $team_member = apply_filters( 'booktics_team_member_data', $team_member, $id );
568
569 return $this->response( $team_member, __( 'Team member successfully fetched', 'booktics' ) );
570 }
571
572 /**
573 * Check if a given request has access to create items.
574 *
575 * @param $request
576 *
577 * @return mixed
578 */
579 public function create_team_member_schedule_permission( $request ) {
580 return current_user_can( 'manage_options' );
581 }
582
583 /**
584 * Team member reinvite
585 *
586 * @param $request
587 *
588 * @return array|WP_HTTP_Response
589 */
590 public function reinvite( $request ) {
591 $id = intval( $request['id'] );
592
593 $invite = ( new Team_Member_Event_Handler() )->on_team_member_create( $id );
594
595 if ( ! $invite ) {
596 return $this->error( __( 'Team member reinvite error', 'booktics' ) );
597 }
598
599 return $this->response( array(), __( 'Team member reinvited successfully', 'booktics' ) );
600 }
601
602 /**
603 * Check if a given request has access to get team member profile.
604 *
605 * @return bool
606 */
607 public function get_team_member_profile_permission() {
608 return current_user_can( 'manage_options' );
609 }
610
611 /**
612 * Get team member profile
613 *
614 * @param $request
615 *
616 * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
617 */
618 public function get_profile( $request ) {
619 $id = get_current_user_id();
620
621 $team_member = new Team_Member_Model( $id );
622 $team_member = $team_member->find( $id );
623 if ( ! $team_member ) {
624 return $this->error( __( 'Team member not found', 'booktics' ), 404 );
625 }
626 $team_member = $team_member->to_array();
627 $schedule_record = ( new Schedule_Record() )->get_schedules( $id );
628 $team_member['schedule'] = ! empty( $schedule_record['schedule'] ) ? $schedule_record['schedule'] : $team_member['schedule'];
629 $team_member['custom'] = ! empty( $schedule_record['custom'] ) ? $schedule_record['custom'] : $team_member['custom'];
630 $team_member['holiday'] = ! empty( $schedule_record['holiday'] ) ? $schedule_record['holiday'] : $team_member['holiday'];
631
632 // Add filter to allow modifying team member data
633 $team_member = apply_filters( 'booktics_team_member_data', $team_member, $id );
634
635 return $this->response( $team_member, __( 'Team member successfully fetched', 'booktics' ) );
636 }
637 }
638