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