PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.9
Yatra – Travel Booking & Tour Operator Software v3.0.9
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 / EnquiryController.php

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

339 lines 10.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\EnquiryService;
11
12 /**
13 * Enquiry REST API Controller
14 *
15 * Handles HTTP requests only - delegates business logic to EnquiryService.
16 *
17 * NO DATABASE QUERIES OR BUSINESS LOGIC IN THIS FILE.
18 *
19 * @package Yatra\Controllers
20 */
21 class EnquiryController extends BaseController
22 {
23 /**
24 * Enquiry service instance
25 */
26 private EnquiryService $enquiryService;
27
28 /**
29 * Constructor
30 */
31 public function __construct()
32 {
33 $this->enquiryService = new EnquiryService();
34 }
35
36 /**
37 * Register routes
38 */
39 public function register_routes(): void
40 {
41 $namespace = 'yatra/v1';
42 $base = 'enquiries';
43
44 // List & Create
45 register_rest_route($namespace, '/' . $base, [
46 [
47 'methods' => \WP_REST_Server::READABLE,
48 'callback' => [$this, 'getEnquiries'],
49 'permission_callback' => [$this, 'checkCanView'],
50 ],
51 [
52 'methods' => \WP_REST_Server::CREATABLE,
53 'callback' => [$this, 'createEnquiry'],
54 'permission_callback' => '__return_true', // Public endpoint
55 ],
56 ]);
57
58 // Single enquiry operations — read uses view, write uses respond,
59 // delete uses the dedicated delete cap (high sensitivity).
60 register_rest_route($namespace, '/' . $base . '/(?P<id>[\d]+)', [
61 [
62 'methods' => \WP_REST_Server::READABLE,
63 'callback' => [$this, 'getEnquiry'],
64 'permission_callback' => [$this, 'checkCanView'],
65 ],
66 [
67 'methods' => \WP_REST_Server::EDITABLE,
68 'callback' => [$this, 'updateEnquiry'],
69 'permission_callback' => [$this, 'checkCanRespond'],
70 ],
71 [
72 'methods' => \WP_REST_Server::DELETABLE,
73 'callback' => [$this, 'deleteEnquiry'],
74 'permission_callback' => [$this, 'checkCanDelete'],
75 ],
76 ]);
77
78 // Bulk actions — operations include status change, mark-read,
79 // delete, etc. Gate on respond (the broadest mutation cap
80 // short of delete). Bulk-delete callers should re-check
81 // delete-cap inside the handler when the action is "delete".
82 register_rest_route($namespace, '/' . $base . '/bulk', [
83 [
84 'methods' => \WP_REST_Server::EDITABLE,
85 'callback' => [$this, 'bulkAction'],
86 'permission_callback' => [$this, 'checkCanRespond'],
87 ],
88 ]);
89
90 // Stats endpoint — read-only aggregation, view cap is enough.
91 register_rest_route($namespace, '/' . $base . '/stats', [
92 [
93 'methods' => \WP_REST_Server::READABLE,
94 'callback' => [$this, 'getStats'],
95 'permission_callback' => [$this, 'checkCanView'],
96 ],
97 ]);
98
99 // Respond to enquiry — explicit respond-cap.
100 register_rest_route($namespace, '/' . $base . '/(?P<id>[\d]+)/respond', [
101 [
102 'methods' => \WP_REST_Server::CREATABLE,
103 'callback' => [$this, 'respondToEnquiry'],
104 'permission_callback' => [$this, 'checkCanRespond'],
105 ],
106 ]);
107 }
108
109 /**
110 * Granular permission checks — one per operation so role bundles
111 * (Sales Agent, Front Desk, etc.) can actually use the parts of
112 * the enquiry surface their role grants. WP administrators pass
113 * every cap automatically via the Team module's admin-fallback
114 * filter, so `manage_options` doesn't need an explicit check
115 * here — it's covered by the cap.
116 */
117 public function checkCanView(): bool
118 {
119 return current_user_can('yatra_view_enquiries');
120 }
121
122 public function checkCanRespond(): bool
123 {
124 return current_user_can('yatra_respond_to_enquiries');
125 }
126
127 public function checkCanDelete(): bool
128 {
129 return current_user_can('yatra_delete_enquiries');
130 }
131
132 /**
133 * @deprecated Kept for any external code (custom snippet, third-
134 * party integration) that hooked the old method name. New code
135 * should use checkCanView/Respond/Delete. Routes the call to
136 * the view-only cap so behaviour is at-least-as-strict as before
137 * for non-admin callers, and admin users keep passing via the
138 * admin-fallback layer.
139 */
140 public function checkAdminPermission(): bool
141 {
142 return $this->checkCanView();
143 }
144
145 /**
146 * GET /enquiries - List all enquiries
147 */
148 public function getEnquiries(WP_REST_Request $request): WP_REST_Response
149 {
150 $filters = [
151 'page' => (int) ($request->get_param('page') ?: 1),
152 'per_page' => (int) ($request->get_param('per_page') ?: 20),
153 'status' => $request->get_param('status') ?: '',
154 'trip_id' => (int) $request->get_param('trip_id'),
155 'search' => $request->get_param('search') ?: '',
156 'date_from' => $request->get_param('date_from') ?: '',
157 'date_to' => $request->get_param('date_to') ?: '',
158 ];
159
160 $result = $this->enquiryService->getEnquiries($filters);
161
162 return new WP_REST_Response([
163 'success' => true,
164 'data' => $result['data'],
165 'meta' => [
166 'total' => $result['total'],
167 'page' => $result['page'],
168 'per_page' => $result['per_page'],
169 'total_pages' => $result['total_pages'],
170 ],
171 ]);
172 }
173
174 /**
175 * GET /enquiries/{id} - Get single enquiry
176 */
177 public function getEnquiry(WP_REST_Request $request): WP_REST_Response
178 {
179 $id = (int) $request->get_param('id');
180
181 $enquiry = $this->enquiryService->getEnquiry($id);
182
183 if (!$enquiry) {
184 return new WP_REST_Response([
185 'success' => false,
186 'message' => __('Enquiry not found.', 'yatra'),
187 ], 404);
188 }
189
190 return new WP_REST_Response([
191 'success' => true,
192 'data' => $enquiry,
193 ]);
194 }
195
196 /**
197 * POST /enquiries - Create enquiry (public endpoint)
198 */
199 public function createEnquiry(WP_REST_Request $request): WP_REST_Response
200 {
201 $data = $request->get_json_params();
202
203 // Handle both JSON and form data
204 if (empty($data)) {
205 $data = $request->get_params();
206 }
207
208 $result = $this->enquiryService->createEnquiry($data);
209
210 if (!$result['success']) {
211 return new WP_REST_Response($result, 400);
212 }
213
214 return new WP_REST_Response($result, 201);
215 }
216
217 /**
218 * PUT /enquiries/{id} - Update enquiry
219 */
220 public function updateEnquiry(WP_REST_Request $request): WP_REST_Response
221 {
222 $id = (int) $request->get_param('id');
223 $data = $request->get_json_params();
224
225 $result = $this->enquiryService->updateEnquiry($id, $data);
226
227 if (!$result['success']) {
228 return new WP_REST_Response($result, 400);
229 }
230
231 return new WP_REST_Response($result);
232 }
233
234 /**
235 * DELETE /enquiries/{id} - Delete enquiry
236 */
237 public function deleteEnquiry(WP_REST_Request $request): WP_REST_Response
238 {
239 $id = (int) $request->get_param('id');
240
241 $result = $this->enquiryService->deleteEnquiry($id);
242
243 if (!$result['success']) {
244 return new WP_REST_Response($result, 400);
245 }
246
247 return new WP_REST_Response($result);
248 }
249
250 /**
251 * PUT /enquiries/bulk - Bulk actions
252 */
253 public function bulkAction(WP_REST_Request $request): WP_REST_Response
254 {
255 $data = $request->get_json_params();
256 $action = $data['action'] ?? '';
257 $ids = $data['ids'] ?? [];
258
259 if (empty($ids) || !is_array($ids)) {
260 return new WP_REST_Response([
261 'success' => false,
262 'message' => __('No items selected.', 'yatra'),
263 ], 400);
264 }
265
266 switch ($action) {
267 case 'delete':
268 $result = $this->enquiryService->bulkDelete($ids);
269 break;
270
271 case 'mark_read':
272 $result = $this->enquiryService->bulkUpdateStatus($ids, 'read');
273 break;
274
275 case 'mark_pending':
276 $result = $this->enquiryService->bulkUpdateStatus($ids, 'pending');
277 break;
278
279 case 'mark_spam':
280 $result = $this->enquiryService->bulkUpdateStatus($ids, 'spam');
281 break;
282
283 case 'mark_trash':
284 $result = $this->enquiryService->bulkUpdateStatus($ids, 'trash');
285 break;
286
287 case 'archive':
288 $result = $this->enquiryService->bulkUpdateStatus($ids, 'archived');
289 break;
290
291 default:
292 return new WP_REST_Response([
293 'success' => false,
294 'message' => __('Invalid action.', 'yatra'),
295 ], 400);
296 }
297
298 return new WP_REST_Response($result);
299 }
300
301 /**
302 * GET /enquiries/stats - Get statistics
303 */
304 public function getStats(WP_REST_Request $request): WP_REST_Response
305 {
306 $stats = $this->enquiryService->getStats();
307
308 return new WP_REST_Response([
309 'success' => true,
310 'data' => $stats,
311 ]);
312 }
313
314 /**
315 * POST /enquiries/{id}/respond - Respond to enquiry
316 */
317 public function respondToEnquiry(WP_REST_Request $request): WP_REST_Response
318 {
319 $id = (int) $request->get_param('id');
320 $data = $request->get_json_params();
321 $response = $data['response'] ?? '';
322
323 if (empty(trim($response))) {
324 return new WP_REST_Response([
325 'success' => false,
326 'message' => __('Response message is required.', 'yatra'),
327 ], 400);
328 }
329
330 $result = $this->enquiryService->respondToEnquiry($id, $response);
331
332 if (!$result['success']) {
333 return new WP_REST_Response($result, 400);
334 }
335
336 return new WP_REST_Response($result);
337 }
338 }
339