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