PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.1
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.5.1, at app/Http/Controllers/FrontendControllers/CustomerProfileController.php

533 lines 18.9 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', 'object_id', 'post_title', 'title', 'quantity', 'payment_type', 'line_meta', 'other_info');
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 'variation_display_title' => $item->variation_display_title,
105 'quantity' => $item->quantity,
106 'payment_type' => $item->payment_type,
107 'line_meta' => [
108 'bundle_parent_item_id' => Arr::get($item, 'line_meta.bundle_parent_item_id', null),
109 ]
110 ];
111 }),
112 ];
113 });
114
115 return apply_filters('fluent_cart/customer_dashboard_data', [
116 'message' => __('Success', 'fluent-cart'),
117 'dashboard_data' => [
118 'orders' => $orders
119 ],
120 'sections_parts' => [
121 'before_orders_table' => '',
122 'after_orders_table' => ''
123 ]
124 ], [
125 'customer' => $customer
126 ]);
127 }
128
129 public function getCustomerProfileDetails()
130 {
131 // Get the current logged-in customer
132 $customer = CustomerResource::getCurrentCustomer();
133
134 if (!$customer) {
135 // get current user by id
136 $userId = get_current_user_id();
137 $currentUser = get_user_by('ID', $userId);
138
139 // get user first_name and last_name from usermeta
140 $currentUser->data->first_name = get_user_meta($userId, 'first_name', true);
141 $currentUser->data->last_name = get_user_meta($userId, 'last_name', true);
142
143
144 return $this->sendSuccess([
145 'message' => __('Success', 'fluent-cart'),
146 'data' => [
147 'first_name' => $currentUser->data->first_name,
148 'last_name' => $currentUser->data->last_name,
149 'user_login' => $currentUser->data->user_login,
150 'user_email' => $currentUser->data->user_email,
151 'email' => $currentUser->data->user_email,
152 'user_nicename' => $currentUser->data->user_nicename,
153 'display_name' => $currentUser->data->display_name,
154 'billing_address' => [],
155 'shipping_address' => [],
156 'not_a_customer' => true
157 ]
158 ]);
159 }
160
161 // Fetch the customer along with the related WordPress user
162 $customerData = Customer::query()
163 ->where('id', $customer->id)
164 ->with(['billing_address', 'shipping_address'])
165 ->first()
166 ->toArray();
167
168 $userData = Arr::only($customerData, [
169 'first_name',
170 'last_name',
171 'email',
172 'billing_address',
173 'shipping_address'
174 ]);
175 // Combine the customer and WordPress user data in the response
176 return $this->sendSuccess([
177 'message' => __('Success', 'fluent-cart'),
178 'data' => $userData
179 ]);
180 }
181
182 public function updateCustomerProfileDetails(CustomerProfileAccountDetailsRequest $request): \WP_REST_Response
183 {
184 $errorResponse = $this->checkUserLoggedIn();
185
186 // Check if there is an error response and return it if exists
187 if ($errorResponse !== null) {
188 return $errorResponse;
189 }
190 // Get the current logged-in customer
191 $customer = CustomerResource::getCurrentCustomer();
192
193 if (!$customer) {
194 return $this->sendError([
195 'message' => __('Customer not found', 'fluent-cart')
196 ]);
197 }
198
199 // Validate the request data for customer and addresses
200 $validatedData = $request->getSafe($request->sanitize());
201 $firstName = Arr::get($validatedData, 'first_name');
202 $lastName = Arr::get($validatedData, 'last_name');
203
204 // Update the customer with the validated data
205 $customer->first_name = $firstName;
206 $customer->last_name = $lastName;
207 $customerUpdate = $customer->save();
208
209
210 if (is_wp_error($customerUpdate)) {
211 return $this->sendError([
212 'message' => $customerUpdate->get_error_message()
213 ]);
214 }
215
216 // Also update the WordPress user profile
217 $name = trim($firstName . ' ' . $lastName);
218 $wpResult = wp_update_user([
219 'ID' => $customer->user_id,
220 'first_name' => $firstName,
221 'last_name' => $lastName,
222 'display_name' => $name,
223 ]);
224
225 if (is_wp_error($wpResult)) {
226 return $this->sendError([
227 'message' => $wpResult->get_error_message()
228 ]);
229 }
230
231 return $this->sendSuccess([
232 'message' => __('Profile updated successfully', 'fluent-cart'),
233 ]);
234 }
235
236 /**
237 * Helper method to validate email uniqueness
238 */
239 private function validateEmailUniqueness($email, $currentCustomerId): ?\WP_REST_Response
240 {
241 $customerId = $currentCustomerId;
242 $userId = Customer::query()->find($customerId)->user_id;
243
244 // Fetch the current customer's email to compare
245 $currentEmail = Customer::query()->find($customerId)->email;
246
247 // Check if the email is different from the current user's email and exists in WordPress users table
248 if ($email !== $currentEmail) {
249 // Check if the email exists in the WordPress users table
250 $emailExistsInWp = get_user_by('email', $email);
251
252 if ($emailExistsInWp && $emailExistsInWp->ID !== $userId) {
253 return $this->sendError([
254 'message' => __('The email address is already in use in WordPress users.', 'fluent-cart')
255 ]);
256 }
257 }
258
259 // Check if the email exists in the Customer table, excluding the current customer
260 $emailExistsInCustomer = Customer::query()->where('email', $email)->where('id', '!=', $customerId)->exists();
261
262 if ($emailExistsInCustomer) {
263 return $this->sendError([
264 'message' => __('The email address is already in use in the customer records.', 'fluent-cart')
265 ]);
266 }
267
268 return null; // Return null mean email is unique
269 }
270
271 public function createCustomerProfileAddress(CustomerProfileRequest $request): \WP_REST_Response
272 {
273 // Get the current logged-in customer
274 $customer = CustomerResource::getCurrentCustomer(true);
275
276 // Sanitize and retrieve the request data
277 $data = CustomerAddressResource::normalizeBusinessFields($request->getSafe($request->sanitize()));
278
279 // Attempt to create a new address for the logged-in customer
280 $isCreated = CustomerAddressResource::create(
281 $data,
282 ['id' => $customer->id]
283 );
284
285 // Check if there was an error during the creation process, return the error if one occurred
286 if (is_wp_error($isCreated)) {
287 return $this->sendError([
288 'message' => $isCreated->get_error_message()
289 ]);
290 }
291
292 // Return the success response
293 return $this->response->sendSuccess($isCreated);
294
295 }
296
297 public function updateCustomerProfileAddress(CustomerProfileRequest $request): \WP_REST_Response
298 {
299 // Call the method and store the response
300 $errorResponse = $this->checkUserLoggedIn();
301
302 // Check if there is an error response and return it if exists
303 if ($errorResponse !== null) {
304 return $errorResponse;
305 }
306
307 // Get the current logged-in customer
308 $customer = CustomerResource::getCurrentCustomer();
309
310 // Sanitize and retrieve the request data
311 $data = CustomerAddressResource::normalizeBusinessFields($request->getSafe($request->sanitize()));
312
313 // Retrieve the address ID from the request
314 $id = $request->getSafe('id', 'intval');
315
316
317 $address = CustomerAddresses::query()->findOrFail($id);
318
319 if ($address->customer_id != $customer->id) {
320 return $this->sendError([
321 'message' => __('You are not authorized to update this address', 'fluent-cart')
322 ]);
323 }
324
325 // Proceed with the update since IDs match
326 $isUpdated = CustomerAddressResource::update($data, $id);
327
328 // Check for errors during the update process
329 if (is_wp_error($isUpdated)) {
330 return $this->sendError([
331 'message' => $isUpdated->get_error_message()
332 ]);
333 }
334
335 // Return the success response
336 return $this->response->sendSuccess($isUpdated);
337
338 }
339
340 public function makePrimaryCustomerProfileAddress(Request $request): \WP_REST_Response
341 {
342 // Call the method and store the response
343 $errorResponse = $this->checkUserLoggedIn();
344 // Check if there is an error response and return it if exists
345 if ($errorResponse !== null) {
346 // Return error if user is not logged in
347 return $errorResponse;
348 }
349
350 $customer = CustomerResource::getCurrentCustomer();
351
352 $id = $request->getSafe('addressId', 'intval');
353
354
355 $address = CustomerAddresses::query()->findOrFail($id);
356
357 if ($address->customer_id != $customer->id) {
358 return $this->sendError([
359 'message' => __('You are not authorized to update this address', 'fluent-cart')
360 ]);
361 }
362
363 $isUpdated = CustomerAddressResource::makePrimary(
364 $customer->id,
365 $request->getSafe('addressId', 'intval'),
366 $request->getSafe('type', 'sanitize_text_field')
367 );
368
369 // Check for errors during the update process
370 if (is_wp_error($isUpdated)) {
371 return $this->sendError([
372 'message' => $isUpdated->get_error_message()
373 ]);
374 }
375
376 // Return the success response
377 return $this->response->sendSuccess($isUpdated);
378 }
379
380 public function deleteCustomerProfileAddress(Request $request)
381 {
382 // Call the method and store the response
383 $errorResponse = $this->checkUserLoggedIn();
384 if ($errorResponse !== null) {
385 return $errorResponse;
386 }
387
388 $id = $request->getSafe('addressId', 'intval');
389 if (!$id) {
390 return $this->sendError([
391 'message' => __('Address ID is required', 'fluent-cart')
392 ]);
393 }
394
395 $customer = CustomerResource::getCurrentCustomer();
396
397 $address = CustomerAddresses::query()->findOrFail($id);
398
399 if ($address->customer_id != $customer->id) {
400 return $this->sendError([
401 'message' => __('You are not authorized to update this address', 'fluent-cart')
402 ]);
403 }
404
405 $isDeleted = CustomerAddressResource::delete($id);
406
407 if (is_wp_error($isDeleted)) {
408 return $this->sendError([
409 'message' => $isDeleted->get_error_message()
410 ]);
411 }
412 return $this->response->sendSuccess($isDeleted);
413 }
414
415 public function getDownloads(Request $request): \WP_REST_Response
416 {
417 $page = $request->get('page', 1);
418 $perPage = $request->get('per_page', 10);
419
420 $errorResponse = $this->checkUserLoggedIn();
421
422 if ($errorResponse !== null) {
423 return $this->sendSuccess([
424 'message' => __('Success', 'fluent-cart'),
425 'data' => [],
426 'total' => 0,
427 'per_page' => $perPage,
428 'current_page' => $page,
429 'last_page' => 1
430 ]);
431 }
432
433 $customer = CustomerResource::getCurrentCustomer();
434
435 $orderItems = OrderItem::query()
436 ->with('variants')
437 ->withWhereHas('order', function ($query) use ($customer) {
438 $query->where('customer_id', $customer->id)
439 ->where(function (Builder $query) {
440 $query->whereIn('payment_status', Status::getOrderPaymentSuccessStatuses());
441 });
442 })
443 ->whereHas('product_downloads')
444 ->get();
445
446 $productIds = $orderItems->pluck('post_id')->unique()->values();
447 $orders = $orderItems->pluck('order');
448
449 // Extract all unique variation IDs from the customer's orders
450 $variationIds = $orders->pluck('order_items')
451 ->flatten()
452 ->pluck('variants.id')
453 ->filter()
454 ->unique()
455 ->values();
456
457 $downloads = ProductDownload::query()->whereIn('post_id', $productIds)->get()->filter(function ($download) use ($variationIds) {
458 $ids = $download->product_variation_id;
459 return empty($ids) || array_intersect($variationIds->toArray(), $ids);
460 });
461
462 $orderIdMapByPostID = [];
463 foreach ($orderItems as $orderItem) {
464 if (!isset($orderIdMapByPostID[$orderItem->post_id])) {
465 $orderIdMapByPostID[$orderItem->post_id] = [];
466 }
467 $orderIdMapByPostID[$orderItem->post_id][] = $orderItem->order_id;
468 }
469
470 $total = $downloads->count();
471 $paginated = $downloads->forPage($page, $perPage)->values();
472
473
474 $data = $paginated->map(function ($download) use ($orderIdMapByPostID) {
475 return [
476 'file_size' => $download->file_size,
477 'title' => $download->title,
478 'download_url' => Helper::generateDownloadFileLink(
479 $download,
480 Arr::get($orderIdMapByPostID, $download->post_id)
481 ),
482 ];
483 })->values();
484
485 return $this->sendSuccess([
486 'message' => __('Success', 'fluent-cart'),
487 'downloads' => [
488 'data' => $data,
489 'total' => $total,
490 'per_page' => $perPage,
491 'current_page' => $page,
492 'last_page' => (int)ceil($total / $perPage),
493 ]
494 ]);
495 }
496
497 /*
498 * Get upgradable paths for a given variation
499 */
500 public function getUpgradePaths(Request $request, $orderHash)
501 {
502
503 $currentCustomer = CustomerResource::getCurrentCustomer();
504 if (!$currentCustomer) {
505 return $this->sendError([
506 'message' => __('You must be logged in to view upgrade paths.', 'fluent-cart')
507 ]);
508 }
509
510 $order = Order::query()->where('uuid', $orderHash)
511 ->where('customer_id', $currentCustomer->id)
512 ->first();
513
514 if (!$order) {
515 return $this->sendError([
516 'message' => __('Order not found or you do not have permission to view it.', 'fluent-cart')
517 ]);
518 }
519
520 $variationId = $request->get('variation_id');
521 if (!$variationId) {
522 return [];
523 }
524
525 $upgradePaths = PlanUpgradeService::getUpgardePathsFromVariation($variationId, $orderHash);
526
527 return $this->sendSuccess([
528 'upgradePaths' => $upgradePaths
529 ]);
530 }
531
532 }
533