Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
CustomerController
n/a
0 / 0
n/a
0 / 0
69
n/a
0 / 0
 store
n/a
0 / 0
12
n/a
0 / 0
 show
n/a
0 / 0
6
n/a
0 / 0
 update
n/a
0 / 0
22
n/a
0 / 0
 authenticate
n/a
0 / 0
6
n/a
0 / 0
 changePassword
n/a
0 / 0
5
n/a
0 / 0
 activateAccount
n/a
0 / 0
4
n/a
0 / 0
 delete
n/a
0 / 0
4
n/a
0 / 0
 toggleOptin
n/a
0 / 0
4
n/a
0 / 0
 removeOptin
n/a
0 / 0
2
n/a
0 / 0
 addSingleOptin
n/a
0 / 0
4
n/a
0 / 0
1<?php
2
3namespace App\Http\Controllers\Api\V1;
4
5use App\Enums\Country;
6use App\Http\Controllers\Controller;
7use App\Http\Resources\CustomerResource;
8use App\Http\Resources\StatusResource;
9use App\Models\Customer;
10use App\Models\CustomerInfo;
11use App\Models\CustomerLogin;
12use App\Models\CustomerOptInHistory;
13use App\Models\SingleOptin;
14use Illuminate\Http\Request;
15use Illuminate\Support\Facades\Hash;
16use Illuminate\Support\Facades\Validator;
17use Illuminate\Support\Str;
18
19/**
20 * @codeCoverageIgnore
21 */
22class CustomerController extends Controller
23{
24    /**
25     * Store a newly created resource in storage
26     * @param Request $request
27     * @return CustomerResource|StatusResource
28     */
29    // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh, Squiz.Commenting.FunctionComment.Missing
30    public function store(Request $request)
31    {
32        $validator = Validator::make($request->all(), [
33            'email' => 'required|email',
34            'password' => 'required',
35            'firstname' => 'required',
36            'lastname' => 'required',
37            'opt_in' => 'required',
38            'birth_date' => 'date_format:Y-m-d'
39        ]);
40
41        if ($validator->fails()) {
42            return new StatusResource([
43                'status' => 'KO', 'code' => 102,
44                'message' => 'Error on required fields.', 'errors' => $validator->errors()
45            ]);
46        }
47
48        $brandId   = $request->brand_id;
49        $email     = strtolower(filter_var($request->email, FILTER_SANITIZE_EMAIL));
50        $firstname = filter_var($request->firstname, FILTER_SANITIZE_STRING);
51        $lastname  = filter_var($request->lastname, FILTER_SANITIZE_STRING);
52        $optIn     = filter_var($request->opt_in, FILTER_SANITIZE_STRING);
53        $hashcode  = Str::uuid();
54
55        // Récupère le customer s'il existe déjà.
56        $customer = Customer::where('email', $email)->first();
57
58        // Si le customer n'existe pas déjà.
59        if (!$customer) {
60            $customer        = new Customer();
61            $customer->email = $email;
62            $customer->save();
63            $singleOptin = SingleOptin::where([['email', $email], ['brand_id', $brandId]])->first();
64            if ($singleOptin) {
65                $singleOptin->delete();
66            }
67        } else {
68            // Récupère les infos s'ils existent déjà.
69            $CustomerInfo = CustomerInfo::where([['customer_id', $customer->id], ['brand_id', $brandId]])->first();
70            if ($CustomerInfo) {
71                return new StatusResource([
72                    'status' => 'KO', 'code' => 103,
73                    'message' => 'User already registered on this site.'
74                ]);
75            }
76        }
77
78        $customerInfos             = new CustomerInfo();
79        $customerInfos->firstname  = ucfirst(strtolower($firstname));
80        $customerInfos->lastname   = ucfirst(strtolower($lastname));
81        $customerInfos->birth_date = !empty($request->birth_date) ?
82        filter_var($request->birth_date, FILTER_SANITIZE_STRING) : null;
83        $customerInfos->address    = !empty($request->address) ?
84        filter_var($request->address, FILTER_SANITIZE_STRING) : null;
85        $customerInfos->address2   = !empty($request->address2) ?
86        filter_var($request->address2, FILTER_SANITIZE_STRING) : null;
87        $customerInfos->phone      = !empty($request->phone) ?
88        filter_var($request->phone, FILTER_SANITIZE_STRING) : null;
89        try {
90            $customerInfos->country = Country::make(filter_var($request->country, FILTER_SANITIZE_STRING));
91        } catch (\Exception $e) {
92            $customerInfos->country = Country::france();
93        }
94        $customerInfos->city        = !empty($request->city) ?
95        filter_var($request->city, FILTER_SANITIZE_STRING) : null;
96        $customerInfos->postcode    = !empty($request->postcode) ?
97        filter_var($request->postcode, FILTER_SANITIZE_STRING) : null;
98        $customerInfos->opt_in      = $optIn;
99        $customerInfos->hashcode    = $hashcode;
100        $customerInfos->brand_id    = $brandId;
101        $customerInfos->customer_id = $customer->id;
102
103        $customer->infos()->save($customerInfos);
104
105        // Création du login pour cet utilisateur sur ce service.
106        $customerLogin                  = new CustomerLogin();
107        $customerLogin->customer_id     = $customer->id;
108        $customerLogin->password        = Hash::make(trim($request->password));
109        $customerLogin->last_connection = now();
110        $customerLogin->brand_id        = $brandId;
111        $customerLogin->status          = 0;
112
113        $customer->logins()->save($customerLogin);
114
115        // Ajout dans la table d'historique des opt-in de la nouvelle valeur.
116        $optInHistory              = new CustomerOptInHistory();
117        $optInHistory->customer_id = $customer->id;
118        $optInHistory->brand_id    = $brandId;
119        $optInHistory->new_value   = $optIn;
120        $optInHistory->save();
121
122        return new CustomerResource($customer, $brandId);
123    }
124
125    /**
126     * Display the specified resource.
127     *
128     * @param  Illuminate\Http\Request $request
129     * @param  mixed                   $type
130     * @param  mixed                   $value
131     * @return CustomerResource | StatusResource
132     */
133    public function show(Request $request, $type, $value)
134    {
135        $brandId = $request->brand_id;
136
137        if ($type === 'id') {
138            $customer = Customer::find($value);
139            if (!$customer) {
140                return new StatusResource(['status' => 'KO', 'code' => 101, 'message' => 'User not found.']);
141            }
142        } elseif ($type === 'email') {
143            $customer = Customer::where('email', $value)->first();
144            if (!$customer) {
145                return new StatusResource(['status' => 'KO', 'code' => 101, 'message' => 'User not found.']);
146            }
147
148            $CustomerInfo = $customer->infos()->where('brand_id', $brandId)->first();
149
150            if (!$CustomerInfo) {
151                return new StatusResource(['status' => 'KO', 'code' => 101, 'message' => 'User not found.']);
152            }
153        } else {
154            return new StatusResource(['status' => 'KO', 'code' => 101, 'message' => 'User not found.']);
155        }
156
157        return new CustomerResource($customer, $brandId);
158    }
159
160    /**
161     * Update the specified resource in storage.
162     *
163     * @param  \Illuminate\Http\Request  $request
164     * @param  int  $id
165     * @return CustomerResource|StatusResource
166     */
167    // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Squiz.Commenting.FunctionComment.Missing
168    public function update(Request $request, $id)
169    {
170        $validator = Validator::make($request->all(), [
171            'birth_date' => 'date_format:Y-m-d'
172        ]);
173
174        if ($validator->fails()) {
175            return new StatusResource([
176                'status' => 'KO', 'code' => 104,
177                'message' => 'Error on required fields.', 'errors' => $validator->errors()
178            ]);
179        }
180
181        $brandId  = $request->brand_id;
182        $customer = Customer::find($id);
183
184        if (!$customer) {
185            return new StatusResource(['status' => 'KO', 'code' => 105, 'message' => 'User not found.']);
186        }
187
188        $CustomerInfo = $customer->infos()->where('brand_id', $brandId)->first();
189        if (!$CustomerInfo) {
190            return new StatusResource(['status' => 'KO', 'code' => 105, 'message' => 'User not found.']);
191        }
192
193        if ($request->has('firstname')) {
194            $CustomerInfo->firstname = filter_var($request->firstname, FILTER_SANITIZE_STRING);
195        }
196
197        if ($request->has('lastname')) {
198            $CustomerInfo->lastname = filter_var($request->lastname, FILTER_SANITIZE_STRING);
199        }
200
201        if ($request->has('birth_date')) {
202            if (!empty($request->birth_date)) {
203                $CustomerInfo->birth_date = filter_var($request->birth_date, FILTER_SANITIZE_STRING);
204            } else {
205                $CustomerInfo->birth_date = null;
206            }
207        }
208
209        if ($request->has('address')) {
210            if (!empty($request->address)) {
211                $CustomerInfo->address = filter_var($request->address, FILTER_SANITIZE_STRING);
212            } else {
213                $CustomerInfo->address = null;
214            }
215        }
216
217        if ($request->has('address2')) {
218            if (!empty($request->address2)) {
219                $CustomerInfo->address2 = filter_var($request->address2, FILTER_SANITIZE_STRING);
220            } else {
221                $CustomerInfo->address2 = null;
222            }
223        }
224
225        if ($request->has('phone')) {
226            if (!empty($request->phone)) {
227                $CustomerInfo->phone = filter_var($request->phone, FILTER_SANITIZE_STRING);
228            } else {
229                $CustomerInfo->phone = null;
230            }
231        }
232
233        if ($request->has('country')) {
234            try {
235                $CustomerInfo->country = Country::make(filter_var($request->country, FILTER_SANITIZE_STRING));
236            } catch (\Exception $e) {
237                $CustomerInfo->country = Country::france();
238            }
239        }
240
241        if ($request->has('city')) {
242            if (!empty($request->city)) {
243                $CustomerInfo->city = filter_var($request->city, FILTER_SANITIZE_STRING);
244            } else {
245                $CustomerInfo->city = null;
246            }
247        }
248
249        if ($request->has('postcode')) {
250            if (!empty($request->postcode)) {
251                $CustomerInfo->postcode = filter_var($request->postcode, FILTER_SANITIZE_STRING);
252            } else {
253                $CustomerInfo->postcode = null;
254            }
255        }
256
257        if ($request->has('opt_in')) {
258            $optIn = filter_var($request->opt_in, FILTER_SANITIZE_STRING);
259
260            if ($CustomerInfo->opt_in != $optIn) {
261                // Ajout dans la table d'historique des opt-in de la nouvelle valeur.
262                $optInHistory              = new CustomerOptInHistory();
263                $optInHistory->customer_id = $customer->id;
264                $optInHistory->brand_id    = $brandId;
265                $optInHistory->new_value   = $optIn;
266                $optInHistory->save();
267            }
268
269            $CustomerInfo->opt_in = $optIn;
270        }
271
272        $CustomerInfo->save();
273
274        return new CustomerResource($customer, $brandId);
275    }
276
277    /**
278     * Authenticate the user
279     * @param Request $request
280     * @return CustomerResource|StatusResource
281     */
282    public function authenticate(Request $request)
283    {
284        $validator = Validator::make($request->all(), [
285            'email' => 'required|email',
286            'password' => 'required',
287        ]);
288
289        if ($validator->fails()) {
290            return new StatusResource([
291                'status' => 'KO', 'code' => 115,
292                'message' => 'Error on required fields.', 'errors' => $validator->errors()
293            ]);
294        }
295
296        $brandId  = $request->brand_id;
297        $email    = filter_var($request->email, FILTER_SANITIZE_EMAIL);
298        $password = trim($request->password);
299        $customer = Customer::where('email', $email)->first();
300        if ($customer) {
301            $login = $customer->logins()->where('brand_id', $brandId)->first();
302            if ($login) {
303                if (Hash::check($password, $login->password)) {
304                    if ($login->status === false) {
305                        $infos = $customer->infos()->where('brand_id', $brandId)->first();
306                        // "Le compte de l'utilisateur n'est pas activé"
307                        return new StatusResource(
308                            [
309                                'status' => 'KO',
310                                'code' => 116,
311                                'message' => 'Account not activated.',
312                                'user' => [
313                                    'crm_id' => $customer->id,
314                                    'firstname' => $infos->firstname,
315                                    'lastname' => $infos->lastname,
316                                    'email' => $customer->email,
317                                    'birth_date' => $infos->birth_date,
318                                    'address' => $infos->address,
319                                    'address2' => $infos->address2,
320                                    'phone' => $infos->phone,
321                                    'country' => $infos->country->label,
322                                    'city' => $infos->city,
323                                    'postcode' => $infos->postcode,
324                                    'opt_in' => $infos->opt_in,
325                                    'hashcode' => $infos->hashcode,
326                                    'status' => $login->status,
327                                ]
328                            ]
329                        );
330                    }//end if
331
332                    $login->last_connection = now();
333                    $customer->logins()->save($login);
334                    return new CustomerResource($customer, $brandId);
335                }//end if
336                // "Mot de passe incorrect"
337                return new StatusResource(['status' => 'KO', 'code' => 117, 'message' => 'Authentication failed.']);
338            } else {
339                // "Ce compte n'est pas enregistré pour cette marque"
340                return new StatusResource(['status' => 'KO', 'code' => 118, 'message' => 'User not found.']);
341            }//end if
342        } else {
343            // "Ce compte n'existe pas dans la CRM"
344            return new StatusResource(['status' => 'KO', 'code' => 119, 'message' => 'User not found.']);
345        }//end if
346    }
347
348    /**
349     * Change the password of the user for the brand
350     * @param Request $request
351     * @param mixed   $id
352     * @return StatusResource
353     */
354    public function changePassword(Request $request, $id)
355    {
356        $validator = Validator::make($request->all(), [
357            'password' => 'required',
358        ]);
359
360        if ($validator->fails()) {
361            return new StatusResource([
362                'status' => 'KO', 'code' => 107,
363                'message' => 'Error on required fields.', 'errors' => $validator->errors()
364            ]);
365        }
366
367        $brandId  = $request->brand_id;
368        $customer = Customer::find($id);
369        $password = trim($request->password);
370
371        if ($customer) {
372            $customerLogin = $customer->logins()->where('brand_id', $brandId)->first();
373            if ($customerLogin) {
374                // Check if same password.
375                if (Hash::check($password, $customerLogin->password)) {
376                    return new StatusResource(['status' => 'KO', 'code' => 123, 'message' => 'Same password.']);
377                }
378
379                $customerLogin->password = Hash::make($password);
380                $customerLogin->save();
381            } else {
382                // "Ce compte n'est pas enregistré pour cette marque"
383                return new StatusResource(['status' => 'KO', 'code' => 108, 'message' => 'User not found.']);
384            }
385        } else {
386            // "Ce compte n'existe pas"
387            return new StatusResource(['status' => 'KO', 'code' => 109, 'message' => 'User not found.']);
388        }
389        return new StatusResource(['status' => 'OK', 'message' => 'Update complete.']);
390    }
391
392    /**
393     * Activate the account of the user
394     * @param Request $request
395     * @param mixed   $id
396     * @return StatusResource
397     */
398    public function activateAccount(Request $request, $id)
399    {
400        $brandId = $request->brand_id;
401
402        $customer = Customer::find($id);
403        if ($customer) {
404            $login = $customer->logins()->where('brand_id', $brandId)->first();
405            if ($login) {
406                if ($login->status === false) {
407                    $login->status = true;
408                    $login->save();
409                    // "Le compte a bien été activé"
410                    return new StatusResource(['status' => 'OK', 'message' => 'Update complete.']);
411                } else {
412                    // "Ce compte est déjà activé"
413                    return new StatusResource(['status' => 'KO', 'code' => 110, 'message' => 'User already active.']);
414                }
415            } else {
416                // "Ce compte n'est pas enregistré pour cette marque"
417                return new StatusResource(['status' => 'KO', 'code' => 111, 'message' => 'User not found.']);
418            }
419        } else {
420            // "Cet utilisateur n'existe pas dans la CRM"
421            return new StatusResource(['status' => 'KO', 'code' => 112, 'message' => 'User not found.']);
422        }
423    }
424
425    /**
426     * Delete the user account for the brand
427     * @param Request $request
428     * @param mixed   $id
429     */
430    // phpcs:disable Squiz.PHP.NonExecutableCode.Unreachable, Squiz.Commenting.FunctionComment.Missing
431    public function delete(Request $request, $id)
432    {
433        die("Not implemented yet");
434        // TODO : Gestion avec mesBR.
435        $brandId = $request->brand_id;
436
437        $customer = Customer::find($id);
438        if ($customer) {
439            $customer->infos()->where('brand_id', $brandId)->first()->delete();
440            $customer->logins()->where('brand_id', $brandId)->first()->delete();
441
442            if (count($customer->infos) === 0 && count($customer->logins) === 0) {
443                $customer->optInHistory()->delete();
444                $customer->delete();
445                // Suppression du compte de la CRM terminée.
446                return new StatusResource(['status' => 'OK', 'message' => 'Deletion complete.']);
447            } else {
448                // Suppression des informations du compte pour la marque terminée.
449                return new StatusResource(['status' => 'OK', 'message' => 'Deletion complete.']);
450            }
451        } else {
452            return new StatusResource(['status' => 'KO', 'code' => 106, 'message' => 'User not found.']);
453        }
454        // phpcs:enable Squiz.PHP.NonExecutableCode.Unreachable, Squiz.Commenting.FunctionComment.Missing
455    }
456
457    /**
458     * Change the status of the opt-in for the customer on this brand
459     * @param Request $request
460     * @param mixed   $id
461     * @return StatusResource
462     */
463    public function toggleOptin(Request $request, $id)
464    {
465        // TODO : Liaison des opt-in avec MailJet.
466        $brandId = $request->brand_id;
467
468        $customer = Customer::find($id);
469        if ($customer) {
470            $infos = $customer->infos()->where('brand_id', $brandId)->first();
471            if ($infos) {
472                $infos->opt_in = $infos->opt_in === 0 ? 1 : 0;
473
474                // On enregistre l'historique du changement d'optin.
475                $optinHistory              = new CustomerOptInHistory();
476                $optinHistory->customer_id = $customer->id;
477                $optinHistory->new_value   = $infos->opt_in;
478                $optinHistory->brand_id    = $brandId;
479                $optinHistory->save();
480
481                $infos->save();
482                // "Changement effectué"
483                return new StatusResource(['status' => 'OK', 'message' => 'Update complete.']);
484            } else {
485                // "Ce compte n'a pas d'information liés à cette marque"
486                return new StatusResource(['status' => 'KO', 'code' => 113, 'message' => 'User not found.']);
487            }
488        } else {
489            // "Cet utilisateur n'existe pas dans la CRM"
490            return new StatusResource(['status' => 'KO', 'code' => 114, 'message' => 'User not found.']);
491        }//end if
492    }
493
494    /**
495     * Remove opt-in for the customer on this brand
496     * @param Request $request
497     * @param mixed   $hashcode
498     * @return StatusResource
499     */
500    public function removeOptin(Request $request, $hashcode)
501    {
502        // TODO : Liaison des opt-in avec MailJet.
503        $brandId = $request->brand_id;
504
505        $infos = CustomerInfo::where([
506            ['brand_id', $brandId],
507            ['hashcode', $hashcode]
508        ])->first();
509
510        if ($infos) {
511            $infos->opt_in = 0;
512
513            // On enregistre l'historique du changement d'optin.
514            $optinHistory              = new CustomerOptInHistory();
515            $optinHistory->customer_id = $infos->customer_id;
516            $optinHistory->new_value   = 0;
517            $optinHistory->brand_id    = $brandId;
518            $optinHistory->save();
519
520            $infos->save();
521            // "Changement effectué"
522            return new StatusResource(['status' => 'OK', 'message' => 'Update complete.']);
523        } else {
524            // "Ce compte n'a pas d'information liés à cette marque"
525            return new StatusResource(['status' => 'KO', 'code' => 122, 'message' => 'User not found.']);
526        }
527    }
528
529    /**
530     * @param Request $request
531     * @return void
532     */
533    // phpcs:ignore Squiz.PHP.NonExecutableCode.Unreachable, Squiz.Commenting.FunctionComment.Missing
534    public function addSingleOptin(Request $request)
535    {
536        $validator = Validator::make($request->all(), [
537            'email' => 'required|email',
538        ]);
539
540        if ($validator->fails()) {
541            return new StatusResource([
542                'status' => 'KO', 'code' => 120,
543                'message' => 'Error on required fields.', 'errors' => $validator->errors()
544            ]);
545        }
546
547        $brandId = $request->brand_id;
548        $email   = filter_var($request->email, FILTER_SANITIZE_EMAIL);
549
550        // Check si le customer ou l'optin simple existe avant de l'ajouter en optin simple.
551        if (
552            !SingleOptin::where([['email', $email], ['brand_id', $brandId]])->exists() &&
553            !CustomerInfo::join("customers", "customer_infos.customer_id", "=", "customers.id")->where([
554                ['brand_id', $brandId], ['email', $email]
555            ])->exists()
556        ) {
557            $singleOptin           = new SingleOptin();
558            $singleOptin->email    = $email;
559            $singleOptin->brand_id = $brandId;
560            $singleOptin->save();
561        } else {
562            // "Cet utilisateur est déjà inscrit à la newsletter pour cette marque"
563            return new StatusResource([
564                'status' => 'KO', 'code' => 121,
565                'message' => 'This user is already subscribed to the newsletter for this brand.'
566            ]);
567        }
568        return new StatusResource(['status' => 'OK', 'message' => 'Optin added.']);
569    }
570}