232 lines
7.7 KiB
PHP
232 lines
7.7 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
/**
|
|
* @property integer $id Id.
|
|
* @property string $email Email.
|
|
* @property-read \Illuminate\Support\Carbon $created_at Created date.
|
|
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
|
|
*
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<App\Models\CustomerInfo>
|
|
* $infos CustomerInfo HasMany relation.
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<App\Models\CustomerLogin>
|
|
* $logins CustomerLogin HasMany relation.
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<App\Models\CustomerOptInHistory>
|
|
* $optInHistory CustomerOptInHistory HasMany relation.
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<App\Models\Brand>
|
|
* $brands Brand BelongsToMany relation.
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<App\Models\Answer>
|
|
* $answers Answer morph many relation.
|
|
*/
|
|
class Customer extends Model
|
|
{
|
|
use HasFactory;
|
|
|
|
public const FIRST_OR_NULL = 0;
|
|
public const FIRST_OR_NEW = 1;
|
|
public const FIRST_OR_FAIL = 2;
|
|
|
|
/**
|
|
* The attributes that are mass assignable.
|
|
*
|
|
* @var string[]
|
|
*/
|
|
protected $fillable = [
|
|
'email',
|
|
];
|
|
|
|
// * RELATIONS
|
|
|
|
/**
|
|
* CustomerInfo hasMany relation.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function infos(): \Illuminate\Database\Eloquent\Relations\HasMany
|
|
{
|
|
return $this->hasMany(CustomerInfo::class);
|
|
}
|
|
|
|
/**
|
|
* CustomerLogin hasMany relation.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function logins(): \Illuminate\Database\Eloquent\Relations\HasMany
|
|
{
|
|
return $this->hasMany(CustomerLogin::class);
|
|
}
|
|
|
|
/**
|
|
* CustomerOptInHistory hasMany relation.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function optInHistory(): \Illuminate\Database\Eloquent\Relations\HasMany
|
|
{
|
|
return $this->hasMany(CustomerOptInHistory::class);
|
|
}
|
|
|
|
/**
|
|
* Customer Brand belongsToMany relation.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function brands(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
{
|
|
return $this->belongsToMany(Brand::class, CustomerInfo::class);
|
|
}
|
|
|
|
/**
|
|
* Answers morph to many relation.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
|
*/
|
|
public function answers(): \Illuminate\Database\Eloquent\Relations\MorphToMany
|
|
{
|
|
return $this->morphToMany(Answer::class, 'model', 'model_answer', 'model_id', 'answer_id');
|
|
}
|
|
|
|
// * METHODS
|
|
|
|
/**
|
|
* Get the CustomerInfo from a specific brand
|
|
* or create a New one if $firstOrNewOrFail is 1
|
|
* throw model not found exception if firstOrNewOrFail = 2.
|
|
*
|
|
* @param \App\Models\Brand $brand
|
|
* @param integer $firstOrNewOrFail
|
|
* @return \App\Models\CustomerLogin|null
|
|
*/
|
|
public function info(Brand $brand, int $firstOrNewOrFail = self::FIRST_OR_NULL): ?CustomerInfo
|
|
{
|
|
if (isset($this->relations['infos'])) {
|
|
/** @var \App\Models\CustomerInfo $info */
|
|
foreach ($this->relations['infos'] as $info) {
|
|
if ($info->brand_id === $brand->id) {
|
|
return $info;
|
|
}
|
|
}
|
|
}
|
|
$query = CustomerInfo::query()->whereHas('brand', function (Builder $q) use ($brand) {
|
|
$q->where('id', $brand->id);
|
|
})->whereHas('customer', function (Builder $q) {
|
|
$q->where('id', $this->id);
|
|
});
|
|
if ($firstOrNewOrFail === self::FIRST_OR_NEW) {
|
|
return $query->firstOrNew();
|
|
}
|
|
if ($firstOrNewOrFail === self::FIRST_OR_FAIL) {
|
|
return $query->firstOrFail();
|
|
}
|
|
return $query->first();
|
|
}
|
|
|
|
/**
|
|
* Get the CustomerLogin from a specific brand
|
|
* or create a New one if $firstOrNewOrFail is 1
|
|
* throw model not found exception if firstOrNewOrFail = 2.
|
|
*
|
|
* @param \App\Models\Brand $brand
|
|
* @param integer $firstOrNewOrFail
|
|
* @return \App\Models\CustomerLogin|null
|
|
*/
|
|
public function login(Brand $brand, int $firstOrNewOrFail = self::FIRST_OR_NULL): ?CustomerLogin
|
|
{
|
|
if (isset($this->relations['logins'])) {
|
|
/** @var \App\Models\CustomerLogin $login */
|
|
foreach ($this->relations['logins'] as $login) {
|
|
if ($login->brand_id === $brand->id) {
|
|
return $login;
|
|
}
|
|
}
|
|
}
|
|
$query = CustomerLogin::query()->whereHas('brand', function (Builder $q) use ($brand) {
|
|
$q->where('id', $brand->id);
|
|
})->whereHas('customer', function (Builder $q) {
|
|
$q->where('id', $this->id);
|
|
});
|
|
if ($firstOrNewOrFail === self::FIRST_OR_NEW) {
|
|
return $query->firstOrNew();
|
|
}
|
|
if ($firstOrNewOrFail === self::FIRST_OR_FAIL) {
|
|
return $query->firstOrFail();
|
|
}
|
|
return $query->first();
|
|
}
|
|
|
|
/**
|
|
* Load login and info for this customer and this specific brand.
|
|
*
|
|
* @param \App\Models\Brand $brand
|
|
* @param boolean $orFail
|
|
* @return self
|
|
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException If no login or info was found for the brand.
|
|
*/
|
|
public function loadBrandData(Brand $brand, bool $orFail = false): self
|
|
{
|
|
$this->load([
|
|
'logins' => function (HasMany $q) use ($brand) {
|
|
$q->where('brand_id', $brand->id);
|
|
},
|
|
'infos' => function (HasMany $q) use ($brand) {
|
|
$q->where('brand_id', $brand->id);
|
|
}
|
|
]);
|
|
if ($orFail and !isset($this->relations['logins'][0])) {
|
|
throw (new ModelNotFoundException())->setModel(CustomerLogin::class);
|
|
}
|
|
if ($orFail and !isset($this->relations['infos'][0])) {
|
|
throw (new ModelNotFoundException())->setModel(CustomerInfo::class);
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set this customer as optin.
|
|
*
|
|
* @param \App\Models\Brand $brand
|
|
* @param boolean $optIn
|
|
* @return void
|
|
* @throws \Throwable If customer history update failed.
|
|
*/
|
|
public function setOptIn(Brand $brand, bool $optIn): void
|
|
{
|
|
$this->opt_in = $optIn;
|
|
|
|
// * Ajout dans la table d'historique des opt-in de la nouvelle valeur.
|
|
$optInHistory = new CustomerOptInHistory();
|
|
$optInHistory->new_value = $optIn;
|
|
$optInHistory->customer()->associate($this);
|
|
$optInHistory->brand()->associate($brand);
|
|
$optInHistory->saveOrFail();
|
|
}
|
|
|
|
/**
|
|
* Get All answers given by this customer
|
|
* for a specific service.
|
|
*
|
|
* @param \App\Models\Service $service
|
|
* @return \Illuminate\Database\Eloquent\Collection
|
|
*/
|
|
public function getAnswers(Service $service): \Illuminate\Database\Eloquent\Collection
|
|
{
|
|
return Answer::query()
|
|
->whereHas('customers', function (Builder $q) {
|
|
$q->where('id', $this->id);
|
|
})
|
|
->whereHas('question', function (Builder $q) use ($service) {
|
|
$q->whereHas('brand', function (Builder $q) use ($service) {
|
|
$q->where('id', $service->brand->id);
|
|
});
|
|
})
|
|
->get();
|
|
}
|
|
}
|