Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.22% covered (success)
93.22%
55 / 59
70.00% covered (warning)
70.00%
7 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Customer
93.22% covered (success)
93.22%
55 / 59
70.00% covered (warning)
70.00%
7 / 10
24.18
0.00% covered (danger)
0.00%
0 / 1
 infos
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 logins
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 optInHistory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 brands
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 answers
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 info
92.86% covered (success)
92.86%
13 / 14
0.00% covered (danger)
0.00%
0 / 1
6.01
 login
92.86% covered (success)
92.86%
13 / 14
0.00% covered (danger)
0.00%
0 / 1
6.01
 loadBrandData
84.62% covered (warning)
84.62%
11 / 13
0.00% covered (danger)
0.00%
0 / 1
5.09
 setOptIn
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 getAnswers
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Builder;
6use Illuminate\Database\Eloquent\Collection;
7use Illuminate\Database\Eloquent\Factories\HasFactory;
8use Illuminate\Database\Eloquent\Model;
9use Illuminate\Database\Eloquent\ModelNotFoundException;
10use Illuminate\Database\Eloquent\Relations\HasMany;
11
12/**
13 * @property integer $id                                   Id.
14 * @property string  $email                                Email.
15 * @property-read \Illuminate\Support\Carbon $created_at   Created date.
16 * @property-read \Illuminate\Support\Carbon $updated_at   Updated date.
17 *
18 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\CustomerInfo>
19 * $infos CustomerInfo HasMany relation.
20 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\CustomerLogin>
21 * $logins CustomerLogin HasMany relation.
22 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\CustomerOptInHistory>
23 * $optInHistory CustomerOptInHistory HasMany relation.
24 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\Brand>
25 * $brands Brand BelongsToMany relation.
26 * @property-read \Illuminate\Database\Eloquent\Collection<App\Models\Answer>
27 * $answers Answer BelongsToMany relation.
28 */
29class Customer extends Model
30{
31    use HasFactory;
32
33    public const FIRST_OR_NULL = 0;
34    public const FIRST_OR_NEW  = 1;
35    public const FIRST_OR_FAIL = 2;
36
37    /**
38     * The attributes that are mass assignable.
39     *
40     * @var string[]
41     */
42    protected $fillable = [
43        'email',
44    ];
45
46    // * RELATIONS
47
48    /**
49     * CustomerInfo hasMany relation.
50     *
51     * @return \Illuminate\Database\Eloquent\Relations\HasMany
52     */
53    public function infos(): \Illuminate\Database\Eloquent\Relations\HasMany
54    {
55        return $this->hasMany(CustomerInfo::class);
56    }
57
58    /**
59     * CustomerLogin hasMany relation.
60     *
61     * @return \Illuminate\Database\Eloquent\Relations\HasMany
62     */
63    public function logins(): \Illuminate\Database\Eloquent\Relations\HasMany
64    {
65        return $this->hasMany(CustomerLogin::class);
66    }
67
68    /**
69     * CustomerOptInHistory hasMany relation.
70     *
71     * @return \Illuminate\Database\Eloquent\Relations\HasMany
72     */
73    public function optInHistory(): \Illuminate\Database\Eloquent\Relations\HasMany
74    {
75        return $this->hasMany(CustomerOptInHistory::class);
76    }
77
78    /**
79     * Customer Brand belongsToMany relation.
80     *
81     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
82     */
83    public function brands(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
84    {
85        return $this->belongsToMany(Brand::class, CustomerInfo::class);
86    }
87
88    /**
89     * Answers belongsToMany relation.
90     *
91     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
92     */
93    public function answers(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
94    {
95        return $this->belongsToMany(Answer::class, 'customer_answer');
96    }
97
98    // * METHODS
99
100    /**
101     * Get the CustomerInfo from a specific brand
102     * or create a New one if $firstOrNewOrFail is 1
103     * throw model not found exception if firstOrNewOrFail = 2.
104     *
105     * @param \App\Models\Brand $brand
106     * @param integer           $firstOrNewOrFail
107     * @return \App\Models\CustomerLogin|null
108     */
109    public function info(Brand $brand, int $firstOrNewOrFail = self::FIRST_OR_NULL): ?CustomerInfo
110    {
111        if (isset($this->relations['infos'])) {
112            /** @var \App\Models\CustomerInfo $info */
113            foreach ($this->relations['infos'] as $info) {
114                if ($info->brand_id === $brand->id) {
115                    return $info;
116                }
117            }
118        }
119        $query = CustomerInfo::query()->whereHas('brand', function (Builder $q) use ($brand) {
120            $q->where('id', $brand->id);
121        })->whereHas('customer', function (Builder $q) {
122            $q->where('id', $this->id);
123        });
124        if ($firstOrNewOrFail === self::FIRST_OR_NEW) {
125            return $query->firstOrNew();
126        }
127        if ($firstOrNewOrFail === self::FIRST_OR_FAIL) {
128            return $query->firstOrFail();
129        }
130        return $query->first();
131    }
132
133    /**
134     * Get the CustomerLogin from a specific brand
135     * or create a New one if $firstOrNewOrFail is 1
136     * throw model not found exception if firstOrNewOrFail = 2.
137     *
138     * @param \App\Models\Brand $brand
139     * @param integer           $firstOrNewOrFail
140     * @return \App\Models\CustomerLogin|null
141     */
142    public function login(Brand $brand, int $firstOrNewOrFail = self::FIRST_OR_NULL): ?CustomerLogin
143    {
144        if (isset($this->relations['logins'])) {
145            /** @var \App\Models\CustomerLogin $login */
146            foreach ($this->relations['logins'] as $login) {
147                if ($login->brand_id === $brand->id) {
148                    return $login;
149                }
150            }
151        }
152        $query = CustomerLogin::query()->whereHas('brand', function (Builder $q) use ($brand) {
153            $q->where('id', $brand->id);
154        })->whereHas('customer', function (Builder $q) {
155            $q->where('id', $this->id);
156        });
157        if ($firstOrNewOrFail === self::FIRST_OR_NEW) {
158            return $query->firstOrNew();
159        }
160        if ($firstOrNewOrFail === self::FIRST_OR_FAIL) {
161            return $query->firstOrFail();
162        }
163        return $query->first();
164    }
165
166    /**
167     * Load login and info for this customer and this specific brand.
168     *
169     * @param \App\Models\Brand $brand
170     * @param boolean           $orFail
171     * @return self
172     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException If no login or info was found for the brand.
173     */
174    public function loadBrandData(Brand $brand, bool $orFail = false): self
175    {
176        $this->load([
177            'logins' => function (HasMany $q) use ($brand) {
178                $q->where('brand_id', $brand->id);
179            },
180            'infos' => function (HasMany $q) use ($brand) {
181                $q->where('brand_id', $brand->id);
182            }
183        ]);
184        if ($orFail and !isset($this->relations['logins'][0])) {
185            throw (new ModelNotFoundException())->setModel(CustomerLogin::class);
186        }
187        if ($orFail and !isset($this->relations['infos'][0])) {
188            throw (new ModelNotFoundException())->setModel(CustomerInfo::class);
189        }
190        return $this;
191    }
192
193    /**
194     * Set this customer as optin.
195     *
196     * @param \App\Models\Brand $brand
197     * @param boolean           $optIn
198     * @return void
199     * @throws \Throwable If customer history update failed.
200     */
201    public function setOptIn(Brand $brand, bool $optIn): void
202    {
203        $this->opt_in = $optIn;
204
205        // * Ajout dans la table d'historique des opt-in de la nouvelle valeur.
206        $optInHistory            = new CustomerOptInHistory();
207        $optInHistory->new_value = $optIn;
208        $optInHistory->customer()->associate($this);
209        $optInHistory->brand()->associate($brand);
210        $optInHistory->saveOrFail();
211    }
212
213    /**
214     * Get All answers given by this customer
215     * for a specific service.
216     *
217     * @param \App\Models\Service $service
218     * @return \Illuminate\Database\Eloquent\Collection
219     */
220    public function getAnswers(Service $service): Collection
221    {
222        return Answer::query()->whereHas('customers', function (Builder $q) {
223            $q->where('id', $this->id);
224        })->whereHas('question', function (Builder $q) use ($service) {
225            $q->whereHas('brand', function (Builder $q) use ($service) {
226                $q->where('id', $service->brand->id);
227            });
228        })->get();
229    }
230}