PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.3
Yatra – Travel Booking & Tour Operator Software v3.0.3
3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 2.0.10 2.0.11 All 82 releases
yatra / app / Controllers / CustomerController.php

CustomerController.php in Yatra – Travel Booking & Tour Operator Software 3.0.3, at app/Controllers/CustomerController.php

523 lines 16.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Yatra\Controllers;
6
7 use WP_REST_Request;
8 use WP_REST_Response;
9 use WP_Error;
10 use Yatra\Services\CustomerService;
11 use Yatra\Validators\CustomerValidator;
12 use Yatra\Exceptions\ValidationException;
13 use Yatra\Utils\Logger;
14
15 /**
16 * Customer REST API Controller
17 *
18 * Handles HTTP requests only - delegates business logic to CustomerService.
19 *
20 * NO DATABASE QUERIES OR BUSINESS LOGIC IN THIS FILE.
21 *
22 * @package Yatra\Controllers
23 */
24 class CustomerController extends BaseController
25 {
26 /**
27 * Customer service instance
28 */
29 private CustomerService $customerService;
30
31 /**
32 * Constructor
33 */
34 public function __construct()
35 {
36 $this->customerService = new CustomerService();
37 }
38
39 /**
40 * Register routes
41 */
42 public function register_routes(): void
43 {
44 $namespace = 'yatra/v1';
45 $base = 'customers';
46
47 // =====================
48 // CUSTOMER (FRONTEND) ROUTES
49 // =====================
50
51 // Get current customer profile
52 register_rest_route($namespace, '/' . $base . '/me', [
53 [
54 'methods' => \WP_REST_Server::READABLE,
55 'callback' => [$this, 'getMe'],
56 'permission_callback' => [$this, 'checkCustomerPermission'],
57 ],
58 [
59 'methods' => \WP_REST_Server::EDITABLE,
60 'callback' => [$this, 'updateMe'],
61 'permission_callback' => [$this, 'checkCustomerPermission'],
62 ],
63 ]);
64
65 // Current customer's bookings
66 register_rest_route($namespace, '/' . $base . '/my-bookings', [
67 [
68 'methods' => \WP_REST_Server::READABLE,
69 'callback' => [$this, 'getMyBookings'],
70 'permission_callback' => [$this, 'checkCustomerPermission'],
71 ],
72 ]);
73
74 register_rest_route($namespace, '/' . $base . '/my-bookings/(?P<id>\d+)', [
75 [
76 'methods' => \WP_REST_Server::READABLE,
77 'callback' => [$this, 'getMyBooking'],
78 'permission_callback' => [$this, 'checkCustomerPermission'],
79 'args' => [
80 'id' => [
81 'required' => true,
82 'type' => 'integer',
83 'sanitize_callback' => 'absint',
84 ],
85 ],
86 ],
87 ]);
88
89 // Current customer's payments
90 register_rest_route($namespace, '/' . $base . '/my-payments', [
91 [
92 'methods' => \WP_REST_Server::READABLE,
93 'callback' => [$this, 'getMyPayments'],
94 'permission_callback' => [$this, 'checkCustomerPermission'],
95 ],
96 ]);
97
98 // Current customer's documents
99 register_rest_route($namespace, '/' . $base . '/my-documents', [
100 [
101 'methods' => \WP_REST_Server::READABLE,
102 'callback' => [$this, 'getMyDocuments'],
103 'permission_callback' => [$this, 'checkCustomerPermission'],
104 ],
105 ]);
106
107 // Current customer's support tickets
108 register_rest_route($namespace, '/' . $base . '/my-support-tickets', [
109 [
110 'methods' => \WP_REST_Server::READABLE,
111 'callback' => [$this, 'getMySupportTickets'],
112 'permission_callback' => [$this, 'checkCustomerPermission'],
113 ],
114 ]);
115
116 // =====================
117 // ADMIN ROUTES
118 // =====================
119
120 // List & Create customers
121 register_rest_route($namespace, '/' . $base, [
122 [
123 'methods' => \WP_REST_Server::READABLE,
124 'callback' => [$this, 'getCustomers'],
125 'permission_callback' => [$this, 'checkAdminPermission'],
126 ],
127 [
128 'methods' => \WP_REST_Server::CREATABLE,
129 'callback' => [$this, 'createCustomer'],
130 'permission_callback' => [$this, 'checkAdminPermission'],
131 ],
132 ]);
133
134 // Single customer operations
135 register_rest_route($namespace, '/' . $base . '/(?P<id>\d+)', [
136 [
137 'methods' => \WP_REST_Server::READABLE,
138 'callback' => [$this, 'getCustomer'],
139 'permission_callback' => [$this, 'checkAdminPermission'],
140 ],
141 [
142 'methods' => \WP_REST_Server::EDITABLE,
143 'callback' => [$this, 'updateCustomer'],
144 'permission_callback' => [$this, 'checkAdminPermission'],
145 ],
146 [
147 'methods' => \WP_REST_Server::DELETABLE,
148 'callback' => [$this, 'deleteCustomer'],
149 'permission_callback' => [$this, 'checkAdminPermission'],
150 ],
151 ]);
152
153 // Customer's bookings (admin)
154 register_rest_route($namespace, '/' . $base . '/(?P<id>\d+)/bookings', [
155 [
156 'methods' => \WP_REST_Server::READABLE,
157 'callback' => [$this, 'getCustomerBookings'],
158 'permission_callback' => [$this, 'checkAdminPermission'],
159 ],
160 ]);
161
162 // Merge customers
163 register_rest_route($namespace, '/' . $base . '/merge', [
164 [
165 'methods' => \WP_REST_Server::CREATABLE,
166 'callback' => [$this, 'mergeCustomers'],
167 'permission_callback' => [$this, 'checkAdminPermission'],
168 ],
169 ]);
170
171 // Customer statistics
172 register_rest_route($namespace, '/' . $base . '/stats', [
173 [
174 'methods' => \WP_REST_Server::READABLE,
175 'callback' => [$this, 'getCustomerStats'],
176 'permission_callback' => [$this, 'checkAdminPermission'],
177 ],
178 ]);
179 }
180
181 /**
182 * Check if user is logged in
183 */
184 public function checkCustomerPermission(): bool
185 {
186 return is_user_logged_in();
187 }
188
189 /**
190 * Check admin permission
191 */
192 public function checkAdminPermission(): bool
193 {
194 return current_user_can('manage_options') || current_user_can('yatra_manage_customers');
195 }
196
197 // =========================================================================
198 // FRONTEND ENDPOINTS (Current User)
199 // =========================================================================
200
201 /**
202 * GET /customers/me - Get current customer profile
203 */
204 public function getMe(WP_REST_Request $request): WP_REST_Response
205 {
206 $userId = get_current_user_id();
207
208 $profile = $this->customerService->getAccountProfileForUser($userId);
209
210 if ($profile === null) {
211 return new WP_REST_Response([
212 'success' => false,
213 'message' => __('Customer profile not found.', 'yatra'),
214 ], 404);
215 }
216
217 return new WP_REST_Response([
218 'success' => true,
219 'data' => $profile,
220 ]);
221 }
222
223 /**
224 * PUT /customers/me - Update current customer profile
225 */
226 public function updateMe(WP_REST_Request $request)
227 {
228 try {
229 $userId = get_current_user_id();
230 $data = $request->get_json_params();
231
232 Logger::apiRequest('/customers/me', 'PUT', $data);
233
234 $customer = $this->customerService->getCustomerByUserId($userId);
235
236 if (!$customer) {
237 Logger::warning("Customer profile not found for user", ['user_id' => $userId]);
238 return $this->not_found(__('Customer profile not found', 'yatra'));
239 }
240
241 $customerId = (int) $customer['id'];
242
243 // Validate and sanitize input data
244 CustomerValidator::validateUpdate($data, $customerId);
245 $data = CustomerValidator::sanitize($data);
246
247 $result = $this->customerService->updateCustomer($customerId, $data);
248
249 if (!$result['success']) {
250 Logger::warning("Customer profile update failed", ['customer_id' => $customerId, 'user_id' => $userId, 'result' => $result]);
251 return $this->error_response($result['message'] ?? 'Failed to update customer profile', 400);
252 }
253
254 Logger::info("Customer profile updated successfully", ['customer_id' => $customerId, 'user_id' => $userId]);
255 return $this->success_response($result['data']);
256
257 } catch (\Exception $e) {
258 Logger::error("Failed to update customer profile", ['user_id' => $userId ?? 0, 'data' => $data ?? [], 'error' => $e->getMessage()]);
259 return $this->handle_exception($e);
260 }
261 }
262
263 /**
264 * GET /customers/my-bookings - Get current customer's bookings
265 */
266 public function getMyBookings(WP_REST_Request $request): WP_REST_Response
267 {
268 $userId = get_current_user_id();
269
270 // Get bookings by user ID (checks both customer_id and user_id)
271 $bookings = $this->customerService->getBookingsByUserId($userId);
272
273 return new WP_REST_Response([
274 'success' => true,
275 'data' => $bookings,
276 ]);
277 }
278
279 public function getMyBooking(WP_REST_Request $request): WP_REST_Response
280 {
281 $userId = get_current_user_id();
282 $bookingId = (int) $request->get_param('id');
283
284 $booking = $this->customerService->getBookingDetailsForUser($userId, $bookingId);
285
286 if (!$booking) {
287 return new WP_REST_Response([
288 'success' => false,
289 'message' => __('Booking not found.', 'yatra'),
290 ], 404);
291 }
292
293 return new WP_REST_Response([
294 'success' => true,
295 'data' => $booking,
296 ]);
297 }
298
299 /**
300 * GET /customers/my-payments - Get current customer's payments
301 */
302 public function getMyPayments(WP_REST_Request $request): WP_REST_Response
303 {
304 $userId = get_current_user_id();
305
306 $customer = $this->customerService->getCustomerByUserId($userId);
307
308 if ($customer) {
309 $payments = $this->customerService->getCustomerPayments((int) $customer['id']);
310 } else {
311 $payments = $this->customerService->getPaymentsByUserId($userId);
312 }
313
314 return new WP_REST_Response([
315 'success' => true,
316 'data' => $payments,
317 ]);
318 }
319
320 /**
321 * GET /customers/my-documents - Get current customer's documents
322 */
323 public function getMyDocuments(WP_REST_Request $request): WP_REST_Response
324 {
325 $userId = get_current_user_id();
326
327 $customer = $this->customerService->getCustomerByUserId($userId);
328
329 if (!$customer) {
330 $bookings = $this->customerService->getBookingsByUserId($userId, 1000);
331 $documents = $this->customerService->getDocumentsForBookings($bookings, 0);
332
333 return new WP_REST_Response([
334 'success' => true,
335 'data' => is_array($documents) ? $documents : [],
336 ]);
337 }
338
339 $documents = $this->customerService->getCustomerDocuments((int) $customer['id']);
340
341 return new WP_REST_Response([
342 'success' => true,
343 'data' => $documents,
344 ]);
345 }
346
347 /**
348 * GET /customers/my-support-tickets - Get current customer's support tickets
349 */
350 public function getMySupportTickets(WP_REST_Request $request): WP_REST_Response
351 {
352 $userId = get_current_user_id();
353
354 $customer = $this->customerService->getCustomerByUserId($userId);
355
356 if (!$customer) {
357 return new WP_REST_Response([
358 'success' => true,
359 'data' => [],
360 ]);
361 }
362
363 $tickets = $this->customerService->getCustomerSupportTickets((int) $customer['id']);
364
365 return new WP_REST_Response([
366 'success' => true,
367 'data' => $tickets,
368 ]);
369 }
370
371 // =========================================================================
372 // ADMIN ENDPOINTS
373 // =========================================================================
374
375 /**
376 * GET /customers - List all customers
377 */
378 public function getCustomers(WP_REST_Request $request): WP_REST_Response
379 {
380 $filters = [
381 'page' => (int) ($request->get_param('page') ?: 1),
382 'per_page' => (int) ($request->get_param('per_page') ?: 20),
383 'status' => $request->get_param('status') ?: '',
384 'search' => $request->get_param('search') ?: '',
385 'orderby' => $request->get_param('orderby') ?: 'created_at',
386 'order' => $request->get_param('order') ?: 'desc',
387 ];
388
389 $result = $this->customerService->getCustomers($filters);
390
391 return new WP_REST_Response([
392 'success' => true,
393 'data' => $result['data'],
394 'total' => $result['total'],
395 'page' => $result['page'],
396 'per_page' => $result['per_page'],
397 'pages' => $result['pages'] ?? $result['total_pages'] ?? 1,
398 ]);
399 }
400
401 /**
402 * GET /customers/{id} - Get single customer
403 */
404 public function getCustomer(WP_REST_Request $request): WP_REST_Response
405 {
406 $id = (int) $request->get_param('id');
407
408 $customer = $this->customerService->getCustomer($id);
409
410 if (!$customer) {
411 return new WP_REST_Response([
412 'success' => false,
413 'message' => __('Customer not found.', 'yatra'),
414 ], 404);
415 }
416
417 // Return both legacy flat fields and wrapped data for UI compatibility
418 return new WP_REST_Response(array_merge([
419 'success' => true,
420 'data' => $customer,
421 ], is_array($customer) ? $customer : []));
422 }
423
424 /**
425 * POST /customers - Create customer
426 */
427 public function createCustomer(WP_REST_Request $request): WP_REST_Response
428 {
429 $data = $request->get_json_params();
430
431 $result = $this->customerService->createCustomer($data);
432
433 if (!$result['success']) {
434 return new WP_REST_Response($result, 400);
435 }
436
437 return new WP_REST_Response($result, 201);
438 }
439
440 /**
441 * PUT /customers/{id} - Update customer
442 */
443 public function updateCustomer(WP_REST_Request $request): WP_REST_Response
444 {
445 $id = (int) $request->get_param('id');
446 $data = $request->get_json_params();
447
448 $result = $this->customerService->updateCustomer($id, $data);
449
450 if (!$result['success']) {
451 return new WP_REST_Response($result, 400);
452 }
453
454 return new WP_REST_Response($result);
455 }
456
457 /**
458 * DELETE /customers/{id} - Delete customer
459 */
460 public function deleteCustomer(WP_REST_Request $request): WP_REST_Response
461 {
462 $id = (int) $request->get_param('id');
463
464 $result = $this->customerService->deleteCustomer($id);
465
466 if (!$result['success']) {
467 return new WP_REST_Response($result, 400);
468 }
469
470 return new WP_REST_Response($result);
471 }
472
473 /**
474 * GET /customers/{id}/bookings - Get customer's bookings (admin)
475 */
476 public function getCustomerBookings(WP_REST_Request $request): WP_REST_Response
477 {
478 $id = (int) $request->get_param('id');
479 $limit = (int) ($request->get_param('limit') ?: 10);
480
481 $bookings = $this->customerService->getCustomerBookings($id, $limit);
482
483 return new WP_REST_Response([
484 'success' => true,
485 'data' => $bookings,
486 ]);
487 }
488
489 /**
490 * POST /customers/merge - Merge two customers
491 */
492 public function mergeCustomers(WP_REST_Request $request): WP_REST_Response
493 {
494 $data = $request->get_json_params();
495 $sourceId = (int) ($data['source_id'] ?? 0);
496 $targetId = (int) ($data['target_id'] ?? 0);
497
498 if (!$sourceId || !$targetId) {
499 return new WP_REST_Response([
500 'success' => false,
501 'message' => __('Both source and target customer IDs are required.', 'yatra'),
502 ], 400);
503 }
504
505 $result = $this->customerService->mergeCustomers($sourceId, $targetId);
506
507 if (!$result['success']) {
508 return new WP_REST_Response($result, 400);
509 }
510
511 return new WP_REST_Response($result);
512 }
513
514 /**
515 * GET /customers/stats - Get customer statistics
516 */
517 public function getCustomerStats(WP_REST_Request $request): WP_REST_Response
518 {
519 $stats = $this->customerService->getStats();
520 return new WP_REST_Response($stats ?? []);
521 }
522 }
523