PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.3.27
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.3.27
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
fluent-cart / app / Http / Controllers / FrontendControllers / CustomerProfileController.php

CustomerProfileController.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.3.27, at app/Http/Controllers/FrontendControllers/CustomerProfileController.php

532 lines 18.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Http\Controllers\FrontendControllers;
4
5 //use FluentCart\Api\Resource\FrontendResource\CustomerResource;
6 use FluentCart\Api\Resource\CustomerAddressResource;
7 use FluentCart\Api\Resource\CustomerResource;
8 use FluentCart\Api\Resource\FrontendResource\OrderResource;
9 use FluentCart\Api\Resource\OrderDownloadPermissionResource;
10 use FluentCart\App\App;
11 use FluentCart\App\Helpers\Helper;
12 use FluentCart\App\Helpers\Status;
13 use FluentCart\App\Http\Controllers\Controller;
14 use FluentCart\App\Http\Requests\FrontendRequests\CustomerRequests\CustomerProfileAccountDetailsRequest;
15 use FluentCart\App\Http\Requests\FrontendRequests\CustomerRequests\CustomerProfileRequest;
16 use FluentCart\App\Models\Customer;
17 use FluentCart\App\Models\CustomerAddresses;
18 use FluentCart\App\Models\Meta;
19 use FluentCart\App\Models\Order;
20 use FluentCart\App\Models\OrderItem;
21 use FluentCart\App\Models\ProductDownload;
22 use FluentCart\App\Models\ProductVariation;
23 use FluentCart\App\Models\Subscription;
24 use FluentCart\App\Services\FileSystem\FileManager;
25 use FluentCart\App\Services\FrontendView;
26 use FluentCart\App\Services\Payments\PaymentHelper;
27 use FluentCart\App\Services\PlanUpgradeService;
28 use FluentCart\App\Services\URL;
29 use FluentCart\Framework\Database\Orm\Builder;
30 use FluentCart\Framework\Database\Orm\Relations\HasMany;
31 use FluentCart\Framework\Http\Request\Request;
32 use FluentCart\Framework\Support\Arr;
33 use FluentCart\Framework\Support\Collection;
34 use FluentCartPro\App\Hooks\Handlers\UpgradeHandler;
35 use FluentCartPro\App\Modules\Licensing\Models\License;
36 use FluentCartPro\App\Modules\Licensing\Models\LicenseActivation;
37 use FluentCartPro\App\Modules\Licensing\Services\LicenseHelper;
38
39
40 class CustomerProfileController extends BaseFrontendController
41 {
42
43 /**
44 * Handle the request to retrieve the customer's orders.
45 *
46 * This method checks if the user is logged in, retrieves the current customer,
47 * and searches for their orders based on the provided search parameters.
48 *
49 * @param Request $request The incoming HTTP request.
50 * @return array
51 */
52 public function index(Request $request)
53 {
54 $customer = CustomerResource::getCurrentCustomer();
55
56
57 if (!$customer) {
58 return apply_filters('fluent_cart/customer_dashboard_data', [
59 'message' => __('Success', 'fluent-cart'),
60 'dashboard_data' => [
61 'orders' => []
62 ],
63 'sections_parts' => [
64 'before_orders_table' => '',
65 'after_orders_table' => ''
66 ]
67 ], [
68 'customer' => null
69 ]);
70 }
71
72
73 $orders = Order::query()
74 ->with(['order_items' => function ($query) {
75 $query->select('id', 'order_id', 'post_title', 'title', 'quantity', 'payment_type', 'line_meta');
76 }])
77 ->where('customer_id', $customer->id)
78 ->where(function ($query) {
79 $query
80 ->where(function ($query) {
81 $query->where('parent_id', '')->orWhereNull('parent_id');
82 })
83 ->orWhere('type', '!=', 'renewal');
84 })
85 ->withCount('renewals')
86 ->orderBy('created_at', 'DESC')
87 ->limit(5)
88 ->get();
89
90 $orders = $orders->map(function ($order) {
91 return [
92 'created_at' => $order->created_at->format('Y-m-d H:i:s'),
93 'invoice_no' => $order->invoice_no,
94 'total_amount' => $order->total_amount,
95 'uuid' => $order->uuid,
96 'type' => $order->type,
97 'status' => $order->status,
98 'renewals_count' => $order->renewals_count,
99 'order_items' => $order->order_items->map(function ($item) {
100 return [
101 'id' => $item->id,
102 'post_title' => $item->post_title,
103 'title' => $item->title,
104 'quantity' => $item->quantity,
105 'payment_type' => $item->payment_type,
106 'line_meta' => [
107 'bundle_parent_item_id' => Arr::get($item, 'line_meta.bundle_parent_item_id', null),
108 ]
109 ];
110 }),
111 ];
112 });
113
114 return apply_filters('fluent_cart/customer_dashboard_data', [
115 'message' => __('Success', 'fluent-cart'),
116 'dashboard_data' => [
117 'orders' => $orders
118 ],
119 'sections_parts' => [
120 'before_orders_table' => '',
121 'after_orders_table' => ''
122 ]
123 ], [
124 'customer' => $customer
125 ]);
126 }
127
128 public function getCustomerProfileDetails()
129 {
130 // Get the current logged-in customer
131 $customer = CustomerResource::getCurrentCustomer();
132
133 if (!$customer) {
134 // get current user by id
135 $userId = get_current_user_id();
136 $currentUser = get_user_by('ID', $userId);
137
138 // get user first_name and last_name from usermeta
139 $currentUser->data->first_name = get_user_meta($userId, 'first_name', true);
140 $currentUser->data->last_name = get_user_meta($userId, 'last_name', true);
141
142
143 return $this->sendSuccess([
144 'message' => __('Success', 'fluent-cart'),
145 'data' => [
146 'first_name' => $currentUser->data->first_name,
147 'last_name' => $currentUser->data->last_name,
148 'user_login' => $currentUser->data->user_login,
149 'user_email' => $currentUser->data->user_email,
150 'email' => $currentUser->data->user_email,
151 'user_nicename' => $currentUser->data->user_nicename,
152 'display_name' => $currentUser->data->display_name,
153 'billing_address' => [],
154 'shipping_address' => [],
155 'not_a_customer' => true
156 ]
157 ]);
158 }
159
160 // Fetch the customer along with the related WordPress user
161 $customerData = Customer::query()
162 ->where('id', $customer->id)
163 ->with(['billing_address', 'shipping_address'])
164 ->first()
165 ->toArray();
166
167 $userData = Arr::only($customerData, [
168 'first_name',
169 'last_name',
170 'email',
171 'billing_address',
172 'shipping_address'
173 ]);
174 // Combine the customer and WordPress user data in the response
175 return $this->sendSuccess([
176 'message' => __('Success', 'fluent-cart'),
177 'data' => $userData
178 ]);
179 }
180
181 public function updateCustomerProfileDetails(CustomerProfileAccountDetailsRequest $request): \WP_REST_Response
182 {
183 $errorResponse = $this->checkUserLoggedIn();
184
185 // Check if there is an error response and return it if exists
186 if ($errorResponse !== null) {
187 return $errorResponse;
188 }
189 // Get the current logged-in customer
190 $customer = CustomerResource::getCurrentCustomer();
191
192 if (!$customer) {
193 return $this->sendError([
194 'message' => __('Customer not found', 'fluent-cart')
195 ]);
196 }
197
198 // Validate the request data for customer and addresses
199 $validatedData = $request->getSafe($request->sanitize());
200 $firstName = Arr::get($validatedData, 'first_name');
201 $lastName = Arr::get($validatedData, 'last_name');
202
203 // Update the customer with the validated data
204 $customer->first_name = $firstName;
205 $customer->last_name = $lastName;
206 $customerUpdate = $customer->save();
207
208
209 if (is_wp_error($customerUpdate)) {
210 return $this->sendError([
211 'message' => $customerUpdate->get_error_message()
212 ]);
213 }
214
215 // Also update the WordPress user profile
216 $name = trim($firstName . ' ' . $lastName);
217 $wpResult = wp_update_user([
218 'ID' => $customer->user_id,
219 'first_name' => $firstName,
220 'last_name' => $lastName,
221 'display_name' => $name,
222 ]);
223
224 if (is_wp_error($wpResult)) {
225 return $this->sendError([
226 'message' => $wpResult->get_error_message()
227 ]);
228 }
229
230 return $this->sendSuccess([
231 'message' => __('Profile updated successfully', 'fluent-cart'),
232 ]);
233 }
234
235 /**
236 * Helper method to validate email uniqueness
237 */
238 private function validateEmailUniqueness($email, $currentCustomerId): ?\WP_REST_Response
239 {
240 $customerId = $currentCustomerId;
241 $userId = Customer::query()->find($customerId)->user_id;
242
243 // Fetch the current customer's email to compare
244 $currentEmail = Customer::query()->find($customerId)->email;
245
246 // Check if the email is different from the current user's email and exists in WordPress users table
247 if ($email !== $currentEmail) {
248 // Check if the email exists in the WordPress users table
249 $emailExistsInWp = get_user_by('email', $email);
250
251 if ($emailExistsInWp && $emailExistsInWp->ID !== $userId) {
252 return $this->sendError([
253 'message' => __('The email address is already in use in WordPress users.', 'fluent-cart')
254 ]);
255 }
256 }
257
258 // Check if the email exists in the Customer table, excluding the current customer
259 $emailExistsInCustomer = Customer::query()->where('email', $email)->where('id', '!=', $customerId)->exists();
260
261 if ($emailExistsInCustomer) {
262 return $this->sendError([
263 'message' => __('The email address is already in use in the customer records.', 'fluent-cart')
264 ]);
265 }
266
267 return null; // Return null mean email is unique
268 }
269
270 public function createCustomerProfileAddress(CustomerProfileRequest $request): \WP_REST_Response
271 {
272 // Get the current logged-in customer
273 $customer = CustomerResource::getCurrentCustomer(true);
274
275 // Sanitize and retrieve the request data
276 $data = $request->getSafe($request->sanitize());
277
278 // Attempt to create a new address for the logged-in customer
279 $isCreated = CustomerAddressResource::create(
280 $data,
281 ['id' => $customer->id]
282 );
283
284 // Check if there was an error during the creation process, return the error if one occurred
285 if (is_wp_error($isCreated)) {
286 return $this->sendError([
287 'message' => $isCreated->get_error_message()
288 ]);
289 }
290
291 // Return the success response
292 return $this->response->sendSuccess($isCreated);
293
294 }
295
296 public function updateCustomerProfileAddress(CustomerProfileRequest $request): \WP_REST_Response
297 {
298 // Call the method and store the response
299 $errorResponse = $this->checkUserLoggedIn();
300
301 // Check if there is an error response and return it if exists
302 if ($errorResponse !== null) {
303 return $errorResponse;
304 }
305
306 // Get the current logged-in customer
307 $customer = CustomerResource::getCurrentCustomer();
308
309 // Sanitize and retrieve the request data
310 $data = $request->getSafe($request->sanitize());
311
312 // Retrieve the address ID from the request
313 $id = $request->getSafe('id', 'intval');
314
315
316 $address = CustomerAddresses::query()->findOrFail($id);
317
318 if ($address->customer_id != $customer->id) {
319 return $this->sendError([
320 'message' => __('You are not authorized to update this address', 'fluent-cart')
321 ]);
322 }
323
324 // Proceed with the update since IDs match
325 $isUpdated = CustomerAddressResource::update($data, $id);
326
327 // Check for errors during the update process
328 if (is_wp_error($isUpdated)) {
329 return $this->sendError([
330 'message' => $isUpdated->get_error_message()
331 ]);
332 }
333
334 // Return the success response
335 return $this->response->sendSuccess($isUpdated);
336
337 }
338
339 public function makePrimaryCustomerProfileAddress(Request $request): \WP_REST_Response
340 {
341 // Call the method and store the response
342 $errorResponse = $this->checkUserLoggedIn();
343 // Check if there is an error response and return it if exists
344 if ($errorResponse !== null) {
345 // Return error if user is not logged in
346 return $errorResponse;
347 }
348
349 $customer = CustomerResource::getCurrentCustomer();
350
351 $id = $request->getSafe('addressId', 'intval');
352
353
354 $address = CustomerAddresses::query()->findOrFail($id);
355
356 if ($address->customer_id != $customer->id) {
357 return $this->sendError([
358 'message' => __('You are not authorized to update this address', 'fluent-cart')
359 ]);
360 }
361
362 $isUpdated = CustomerAddressResource::makePrimary(
363 $customer->id,
364 $request->getSafe('addressId', 'intval'),
365 $request->getSafe('type', 'sanitize_text_field')
366 );
367
368 // Check for errors during the update process
369 if (is_wp_error($isUpdated)) {
370 return $this->sendError([
371 'message' => $isUpdated->get_error_message()
372 ]);
373 }
374
375 // Return the success response
376 return $this->response->sendSuccess($isUpdated);
377 }
378
379 public function deleteCustomerProfileAddress(Request $request)
380 {
381 // Call the method and store the response
382 $errorResponse = $this->checkUserLoggedIn();
383 if ($errorResponse !== null) {
384 return $errorResponse;
385 }
386
387 $id = $request->getSafe('addressId', 'intval');
388 if (!$id) {
389 return $this->sendError([
390 'message' => __('Address ID is required', 'fluent-cart')
391 ]);
392 }
393
394 $customer = CustomerResource::getCurrentCustomer();
395
396 $address = CustomerAddresses::query()->findOrFail($id);
397
398 if ($address->customer_id != $customer->id) {
399 return $this->sendError([
400 'message' => __('You are not authorized to update this address', 'fluent-cart')
401 ]);
402 }
403
404 $isDeleted = CustomerAddressResource::delete($id);
405
406 if (is_wp_error($isDeleted)) {
407 return $this->sendError([
408 'message' => $isDeleted->get_error_message()
409 ]);
410 }
411 return $this->response->sendSuccess($isDeleted);
412 }
413
414 public function getDownloads(Request $request): \WP_REST_Response
415 {
416 $page = $request->get('page', 1);
417 $perPage = $request->get('per_page', 10);
418
419 $errorResponse = $this->checkUserLoggedIn();
420
421 if ($errorResponse !== null) {
422 return $this->sendSuccess([
423 'message' => __('Success', 'fluent-cart'),
424 'data' => [],
425 'total' => 0,
426 'per_page' => $perPage,
427 'current_page' => $page,
428 'last_page' => 1
429 ]);
430 }
431
432 $customer = CustomerResource::getCurrentCustomer();
433
434 $orderItems = OrderItem::query()
435 ->with('variants')
436 ->withWhereHas('order', function ($query) use ($customer) {
437 $query->where('customer_id', $customer->id)
438 ->where(function (Builder $query) {
439 $query->whereIn('payment_status', Status::getOrderPaymentSuccessStatuses());
440 });
441 })
442 ->whereHas('product_downloads')
443 ->get();
444
445 $productIds = $orderItems->pluck('post_id')->unique()->values();
446 $orders = $orderItems->pluck('order');
447
448 // Extract all unique variation IDs from the customer's orders
449 $variationIds = $orders->pluck('order_items')
450 ->flatten()
451 ->pluck('variants.id')
452 ->filter()
453 ->unique()
454 ->values();
455
456 $downloads = ProductDownload::query()->whereIn('post_id', $productIds)->get()->filter(function ($download) use ($variationIds) {
457 $ids = $download->product_variation_id;
458 return empty($ids) || array_intersect($variationIds->toArray(), $ids);
459 });
460
461 $orderIdMapByPostID = [];
462 foreach ($orderItems as $orderItem) {
463 if (!isset($orderIdMapByPostID[$orderItem->post_id])) {
464 $orderIdMapByPostID[$orderItem->post_id] = [];
465 }
466 $orderIdMapByPostID[$orderItem->post_id][] = $orderItem->order_id;
467 }
468
469 $total = $downloads->count();
470 $paginated = $downloads->forPage($page, $perPage)->values();
471
472
473 $data = $paginated->map(function ($download) use ($orderIdMapByPostID) {
474 return [
475 'file_size' => $download->file_size,
476 'title' => $download->title,
477 'download_url' => Helper::generateDownloadFileLink(
478 $download,
479 Arr::get($orderIdMapByPostID, $download->post_id)
480 ),
481 ];
482 })->values();
483
484 return $this->sendSuccess([
485 'message' => __('Success', 'fluent-cart'),
486 'downloads' => [
487 'data' => $data,
488 'total' => $total,
489 'per_page' => $perPage,
490 'current_page' => $page,
491 'last_page' => (int)ceil($total / $perPage),
492 ]
493 ]);
494 }
495
496 /*
497 * Get upgradable paths for a given variation
498 */
499 public function getUpgradePaths(Request $request, $orderHash)
500 {
501
502 $currentCustomer = CustomerResource::getCurrentCustomer();
503 if (!$currentCustomer) {
504 return $this->sendError([
505 'message' => __('You must be logged in to view upgrade paths.', 'fluent-cart')
506 ]);
507 }
508
509 $order = Order::query()->where('uuid', $orderHash)
510 ->where('customer_id', $currentCustomer->id)
511 ->first();
512
513 if (!$order) {
514 return $this->sendError([
515 'message' => __('Order not found or you do not have permission to view it.', 'fluent-cart')
516 ]);
517 }
518
519 $variationId = $request->get('variation_id');
520 if (!$variationId) {
521 return [];
522 }
523
524 $upgradePaths = PlanUpgradeService::getUpgardePathsFromVariation($variationId, $orderHash);
525
526 return $this->sendSuccess([
527 'upgradePaths' => $upgradePaths
528 ]);
529 }
530
531 }
532