PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.2.6
Yatra – Travel Booking & Tour Operator Software v3.0.2.6
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 / ReviewController.php

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

446 lines 13.1 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\ReviewService;
11
12 /**
13 * Review REST API Controller
14 *
15 * Handles HTTP requests only - delegates business logic to ReviewService.
16 *
17 * NO DATABASE QUERIES OR BUSINESS LOGIC IN THIS FILE.
18 *
19 * @package Yatra\Controllers
20 */
21 class ReviewController extends BaseController
22 {
23 /**
24 * Review service instance
25 */
26 private ReviewService $reviewService;
27
28 /**
29 * Constructor
30 */
31 public function __construct()
32 {
33 $this->reviewService = new ReviewService();
34 }
35
36 /**
37 * Register routes
38 */
39 public function register_routes(): void
40 {
41 $namespace = 'yatra/v1';
42 $base = 'reviews';
43
44 // =====================
45 // ADMIN ROUTES
46 // =====================
47
48 // List reviews
49 register_rest_route($namespace, '/' . $base, [
50 [
51 'methods' => \WP_REST_Server::READABLE,
52 'callback' => [$this, 'getReviews'],
53 'permission_callback' => [$this, 'checkAdminPermission'],
54 ],
55 ]);
56
57 // Bulk actions
58 register_rest_route($namespace, '/' . $base . '/bulk', [
59 [
60 'methods' => \WP_REST_Server::EDITABLE,
61 'callback' => [$this, 'bulkAction'],
62 'permission_callback' => [$this, 'checkAdminPermission'],
63 ],
64 ]);
65
66 // Get single review
67 register_rest_route($namespace, '/' . $base . '/(?P<id>[\d]+)', [
68 [
69 'methods' => \WP_REST_Server::READABLE,
70 'callback' => [$this, 'getReview'],
71 'permission_callback' => [$this, 'checkAdminPermission'],
72 ],
73 [
74 'methods' => \WP_REST_Server::EDITABLE,
75 'callback' => [$this, 'updateReview'],
76 'permission_callback' => [$this, 'checkAdminPermission'],
77 ],
78 [
79 'methods' => \WP_REST_Server::DELETABLE,
80 'callback' => [$this, 'deleteReview'],
81 'permission_callback' => [$this, 'checkAdminPermission'],
82 ],
83 ]);
84
85 // Update review status
86 register_rest_route($namespace, '/' . $base . '/(?P<id>[\d]+)/status', [
87 [
88 'methods' => \WP_REST_Server::EDITABLE,
89 'callback' => [$this, 'updateStatus'],
90 'permission_callback' => [$this, 'checkAdminPermission'],
91 ],
92 ]);
93
94 // Stats
95 register_rest_route($namespace, '/' . $base . '/stats', [
96 [
97 'methods' => \WP_REST_Server::READABLE,
98 'callback' => [$this, 'getStats'],
99 'permission_callback' => [$this, 'checkAdminPermission'],
100 ],
101 ]);
102
103 // =====================
104 // PUBLIC ROUTES
105 // =====================
106
107 // Get trip reviews (public)
108 register_rest_route($namespace, '/trips/(?P<trip_id>[\d]+)/reviews', [
109 [
110 'methods' => \WP_REST_Server::READABLE,
111 'callback' => [$this, 'getTripReviews'],
112 'permission_callback' => '__return_true',
113 ],
114 ]);
115
116 // Submit review (authenticated)
117 register_rest_route($namespace, '/trips/(?P<trip_id>[\d]+)/reviews', [
118 [
119 'methods' => \WP_REST_Server::CREATABLE,
120 'callback' => [$this, 'submitReview'],
121 'permission_callback' => [$this, 'checkReviewPermission'],
122 ],
123 ]);
124
125 // Check if user can review
126 register_rest_route($namespace, '/trips/(?P<trip_id>[\d]+)/can-review', [
127 [
128 'methods' => \WP_REST_Server::READABLE,
129 'callback' => [$this, 'canReview'],
130 'permission_callback' => '__return_true',
131 ],
132 ]);
133
134 // User's own review operations
135 register_rest_route($namespace, '/my-reviews/(?P<id>[\d]+)', [
136 [
137 'methods' => \WP_REST_Server::EDITABLE,
138 'callback' => [$this, 'updateMyReview'],
139 'permission_callback' => [$this, 'checkUserPermission'],
140 ],
141 ]);
142 }
143
144 /**
145 * Check admin permission
146 */
147 public function checkAdminPermission(): bool
148 {
149 return current_user_can('manage_options');
150 }
151
152 /**
153 * Check if user is logged in
154 */
155 public function checkUserPermission(): bool
156 {
157 return is_user_logged_in();
158 }
159
160 /**
161 * Check review submission permission
162 */
163 public function checkReviewPermission(): bool
164 {
165 $settings = \Yatra\Services\SettingsService::getSettings();
166 $requireLogin = $settings['reviews']['require_login'] ?? true;
167
168 if ($requireLogin) {
169 return is_user_logged_in();
170 }
171
172 return true;
173 }
174
175 // =========================================================================
176 // ADMIN ENDPOINTS
177 // =========================================================================
178
179 /**
180 * GET /reviews - List all reviews (admin)
181 */
182 public function getReviews(WP_REST_Request $request): WP_REST_Response
183 {
184 $filters = [
185 'page' => (int) ($request->get_param('page') ?: 1),
186 'per_page' => (int) ($request->get_param('per_page') ?: 20),
187 'status' => $request->get_param('status') ?: '',
188 'trip_id' => (int) $request->get_param('trip_id'),
189 'rating' => (int) $request->get_param('rating'),
190 'search' => $request->get_param('search') ?: '',
191 ];
192
193 $result = $this->reviewService->getReviews($filters);
194
195
196
197 // Map database fields to frontend expected fields
198 $mappedData = array_map(function($review) {
199 // ReviewService returns arrays, not objects
200 return (object) [
201 'id' => $review['id'] ?? null,
202 'trip_id' => $review['trip_id'] ?? null,
203 'trip_title' => $review['trip_title'] ?? '',
204 'trip_slug' => $review['trip_slug'] ?? '',
205 'customer_name' => $review['author_name'] ?? '',
206 'customer_email' => $review['author_email'] ?? '',
207 'rating' => $review['rating'] ?? 0,
208 'title' => $review['title'] ?? '',
209 'content' => $review['content'] ?? '',
210 'status' => $review['status'] ?? '',
211 'verified' => false, // TODO: Add verified field to database
212 'created_at' => $review['created_at'] ?? null,
213 ];
214 }, $result['data']);
215
216 return new WP_REST_Response([
217 'success' => true,
218 'data' => $mappedData,
219 'meta' => [
220 'total' => $result['total'],
221 'page' => $result['page'],
222 'per_page' => $result['per_page'],
223 'total_pages' => $result['total_pages'],
224 ],
225 ]);
226 }
227
228 /**
229 * GET /reviews/{id} - Get single review
230 */
231 public function getReview(WP_REST_Request $request): WP_REST_Response
232 {
233 $id = (int) $request->get_param('id');
234
235 $review = $this->reviewService->getReview($id);
236
237 if (!$review) {
238 return new WP_REST_Response([
239 'success' => false,
240 'message' => __('Review not found.', 'yatra'),
241 ], 404);
242 }
243
244 return new WP_REST_Response([
245 'success' => true,
246 'data' => $review,
247 ]);
248 }
249
250 /**
251 * PUT /reviews/{id} - Update review
252 */
253 public function updateReview(WP_REST_Request $request): WP_REST_Response
254 {
255 $id = (int) $request->get_param('id');
256 $data = $request->get_json_params();
257
258 $result = $this->reviewService->updateReview($id, $data);
259
260 if (!$result['success']) {
261 return new WP_REST_Response($result, 400);
262 }
263
264 return new WP_REST_Response($result);
265 }
266
267 /**
268 * PUT /reviews/bulk - Bulk actions
269 */
270 public function bulkAction(WP_REST_Request $request): WP_REST_Response
271 {
272 $data = $request->get_json_params();
273 $action = $data['action'] ?? '';
274 $ids = $data['ids'] ?? [];
275
276 if (empty($ids) || !is_array($ids)) {
277 return new WP_REST_Response([
278 'success' => false,
279 'message' => __('No items selected.', 'yatra'),
280 ], 400);
281 }
282
283 switch ($action) {
284 case 'delete':
285 $result = $this->reviewService->bulkDelete($ids);
286 break;
287 case 'mark_approved':
288 $result = $this->reviewService->bulkUpdateStatus($ids, 'approved');
289 break;
290 case 'mark_pending':
291 $result = $this->reviewService->bulkUpdateStatus($ids, 'pending');
292 break;
293 case 'mark_spam':
294 $result = $this->reviewService->bulkUpdateStatus($ids, 'spam');
295 break;
296 case 'mark_trash':
297 $result = $this->reviewService->bulkUpdateStatus($ids, 'trash');
298 break;
299 default:
300 return new WP_REST_Response([
301 'success' => false,
302 'message' => __('Invalid action.', 'yatra'),
303 ], 400);
304 }
305
306 return new WP_REST_Response($result);
307 }
308
309 /**
310 * DELETE /reviews/{id} - Delete review
311 */
312 public function deleteReview(WP_REST_Request $request): WP_REST_Response
313 {
314 $id = (int) $request->get_param('id');
315
316 $result = $this->reviewService->deleteReview($id);
317
318 if (!$result['success']) {
319 return new WP_REST_Response($result, 400);
320 }
321
322 return new WP_REST_Response($result);
323 }
324
325 /**
326 * PUT /reviews/{id}/status - Update status
327 */
328 public function updateStatus(WP_REST_Request $request): WP_REST_Response
329 {
330 $id = (int) $request->get_param('id');
331 $data = $request->get_json_params();
332 $status = $data['status'] ?? '';
333
334 if (empty($status)) {
335 return new WP_REST_Response([
336 'success' => false,
337 'message' => __('Status is required.', 'yatra'),
338 ], 400);
339 }
340
341 $result = $this->reviewService->updateStatus($id, $status);
342
343 if (!$result['success']) {
344 return new WP_REST_Response($result, 400);
345 }
346
347 return new WP_REST_Response($result);
348 }
349
350 /**
351 * GET /reviews/stats - Get statistics
352 */
353 public function getStats(WP_REST_Request $request): WP_REST_Response
354 {
355 $stats = $this->reviewService->getStats();
356
357 return new WP_REST_Response([
358 'success' => true,
359 'data' => $stats,
360 ]);
361 }
362
363 // =========================================================================
364 // PUBLIC ENDPOINTS
365 // =========================================================================
366
367 /**
368 * GET /trips/{trip_id}/reviews - Get trip reviews (public)
369 */
370 public function getTripReviews(WP_REST_Request $request): WP_REST_Response
371 {
372 $tripId = (int) $request->get_param('trip_id');
373 $limit = (int) ($request->get_param('limit') ?: 10);
374
375 $reviews = $this->reviewService->getTripReviews($tripId, $limit);
376 $summary = $this->reviewService->getTripRatingSummary($tripId);
377
378 return new WP_REST_Response([
379 'success' => true,
380 'data' => [
381 'reviews' => $reviews,
382 'summary' => $summary,
383 ],
384 ]);
385 }
386
387 /**
388 * POST /trips/{trip_id}/reviews - Submit review
389 */
390 public function submitReview(WP_REST_Request $request): WP_REST_Response
391 {
392 $tripId = (int) $request->get_param('trip_id');
393 $data = $request->get_json_params();
394
395 // Handle both JSON and form data
396 if (empty($data)) {
397 $data = $request->get_params();
398 }
399
400 $data['trip_id'] = $tripId;
401
402 $result = $this->reviewService->submitReview($data);
403
404 if (!$result['success']) {
405 return new WP_REST_Response($result, 400);
406 }
407
408 return new WP_REST_Response($result, 201);
409 }
410
411 /**
412 * GET /trips/{trip_id}/can-review - Check if user can review
413 */
414 public function canReview(WP_REST_Request $request): WP_REST_Response
415 {
416 $tripId = (int) $request->get_param('trip_id');
417
418 $result = $this->reviewService->canUserReview($tripId);
419
420 return new WP_REST_Response([
421 'success' => true,
422 'data' => $result,
423 ]);
424 }
425
426 /**
427 * PUT /my-reviews/{id} - Update own review
428 */
429 public function updateMyReview(WP_REST_Request $request): WP_REST_Response
430 {
431 $id = (int) $request->get_param('id');
432 $data = $request->get_json_params();
433
434 // Set user_id to enforce ownership check in service
435 $data['user_id'] = get_current_user_id();
436
437 $result = $this->reviewService->updateReview($id, $data);
438
439 if (!$result['success']) {
440 return new WP_REST_Response($result, 400);
441 }
442
443 return new WP_REST_Response($result);
444 }
445 }
446