276 lines
9.1 KiB
PHP
276 lines
9.1 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Enums\Departaimants\DepartaimantCollectionType;
|
|
use App\Notifications\Customer\DestroyCustomer;
|
|
use App\Notifications\Customer\DestroyedCustomer;
|
|
use App\Notifications\Customer\ResetPassword;
|
|
use App\Notifications\Customer\VerifyEmail;
|
|
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
|
use Illuminate\Contracts\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Prunable;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
|
use Illuminate\Notifications\Notifiable;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Illuminate\Validation\Rule;
|
|
|
|
/**
|
|
*
|
|
* @property-read \Illuminate\Database\Eloquent\Collection<\App\Models\DepartaimantsCollection>$departaimantsCollections
|
|
*/
|
|
class Customer extends Authenticatable implements MustVerifyEmail
|
|
{
|
|
use HasFactory;
|
|
use Notifiable;
|
|
use Prunable;
|
|
use SoftDeletes;
|
|
|
|
/**
|
|
* Perform any actions required after the model boots.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected static function booted()
|
|
{
|
|
// * EVENT CLOSURES.
|
|
self::creating(function (self $model) {
|
|
self::assertEmailIsUnique($model->id, $model->email);
|
|
});
|
|
self::updating(function (self $model) {
|
|
self::assertEmailIsUnique($model->id, $model->email);
|
|
});
|
|
self::deleted(function (self $model) {
|
|
if ($model->forceDeleting) {
|
|
$model->notify(new DestroyedCustomer());
|
|
} else {
|
|
$model->notify(new DestroyCustomer());
|
|
}
|
|
});
|
|
self::restored(function () {
|
|
\session()->flash(
|
|
'warning',
|
|
\trans('Votre compte à été réactivé.')
|
|
);
|
|
});
|
|
}
|
|
|
|
// * RELATIONSHIPS
|
|
|
|
/**
|
|
* Get all of the departaimant collections for the Customer
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function departaimantsCollections(): HasMany
|
|
{
|
|
return $this->hasMany(DepartaimantsCollection::class);
|
|
}
|
|
|
|
/**
|
|
* The notifications that belong to the Customer
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function notifications(): BelongsToMany
|
|
{
|
|
return $this->belongsToMany(Notifications::class);
|
|
}
|
|
|
|
/**
|
|
* The read notifications that belong to the Customer
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function readNotifications(): BelongsToMany
|
|
{
|
|
return $this->belongsToMany(Notifications::class, 'notifications_read', 'customer_id', 'notification_id');
|
|
}
|
|
|
|
/**
|
|
* Get all of the messages for the Customer
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function messages(): HasMany
|
|
{
|
|
return $this->hasMany(Message::class, 'to');
|
|
}
|
|
|
|
/**
|
|
* Get all of the sentMessages for the Customer
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function sentMessages(): HasMany
|
|
{
|
|
return $this->hasMany(Message::class, 'from');
|
|
}
|
|
|
|
// * METHODS
|
|
|
|
/**
|
|
* Get conversations with messages sorted by time
|
|
*
|
|
* @return array
|
|
*/
|
|
public function conversations(): array
|
|
{
|
|
$dateSort = fn (Message $a, Message $b) => $a->created_at->timestamp > $b->created_at->timestamp;
|
|
$messageFilter = fn (Collection $item) => $item->all();
|
|
$messageWith = [
|
|
'fromCustomer' => fn (Builder $q) => $q->select(['id', 'username', 'created_at']),
|
|
'toCustomer' => fn (Builder $q) => $q->select(['id', 'username', 'created_at'])
|
|
];
|
|
/**
|
|
* Hack workaround https://github.com/livewire/livewire/issues/1054
|
|
*/
|
|
$sentM = $this->sentMessages()
|
|
->where('hide_from', false)
|
|
->with($messageWith)->get()
|
|
->groupBy('toCustomer.username')
|
|
->map($messageFilter)->toBase();
|
|
$receivedM = $this->messages()
|
|
->where('hide_to', false)->with($messageWith)->get()
|
|
->groupBy('fromCustomer.username')->map($messageFilter)->toBase();
|
|
|
|
$output = $receivedM->mapWithKeys(function (array $messagesArray, string $fromUsername) use (&$sentM, $dateSort) {
|
|
// @phpstan-ignore-next-line
|
|
$responses = collect(\array_merge($sentM->pull($fromUsername) ?? [], $messagesArray))->sort($dateSort);
|
|
$last = $responses->last();
|
|
return [$fromUsername => collect([
|
|
'to' => $fromUsername,
|
|
'to_id' => collect($messagesArray)->first()->fromCustomer->id,
|
|
'id' => $last->id,
|
|
'date' => $last->created_at,
|
|
'dateRaw' => $last->getRawOriginal('created_at'),
|
|
'preview' => str($last->message)->limit(15),
|
|
'messages' => $responses->values()->all()
|
|
])];
|
|
})->toBase();
|
|
// * Map sur les message envoyés (qui n'ont pas encore eu de réponses)
|
|
$outputSentM = $sentM->mapWithKeys(function ($messagesArray) {
|
|
$sent = collect($messagesArray);
|
|
$last = $sent->last();
|
|
$toCustomer = $last->toCustomer;
|
|
$toUserName = $toCustomer->username;
|
|
return [$toUserName => collect([
|
|
'to' => $toUserName,
|
|
'to_id' => $toCustomer->id,
|
|
'id' => $last->id,
|
|
'date' => $last->created_at,
|
|
'dateRaw' => $last->getRawOriginal('created_at'),
|
|
'preview' => str($last->message)->limit(15),
|
|
'messages' => $sent->values()->all()
|
|
])];
|
|
})->toBase();
|
|
|
|
return $output->merge($outputSentM)->sort(function ($a, $b) {
|
|
return Carbon::parse(
|
|
Arr::get($a, 'dateRaw')
|
|
)->timestamp < Carbon::parse(Arr::get($b, 'dateRaw'))->timestamp;
|
|
})->toArray();
|
|
}
|
|
|
|
/**
|
|
* Asserts using validation that the email is unique
|
|
*
|
|
* @param mixed $id
|
|
* @param mixed $email
|
|
* @return void
|
|
* @throws \Illuminate\Validation\ValidationException If user email as already used.
|
|
*/
|
|
private static function assertEmailIsUnique(mixed $id, mixed $email): void
|
|
{
|
|
self::assertFieldIsUnique($id, 'email', $email);
|
|
}
|
|
|
|
/**
|
|
* Asserts that the field is unique
|
|
*
|
|
* @param mixed $id
|
|
* @param string $field
|
|
* @param mixed $value
|
|
* @return void
|
|
* @throws \Illuminate\Validation\ValidationException If the field is not unique.
|
|
*/
|
|
private static function assertFieldIsUnique(mixed $id, string $field, mixed $value): void
|
|
{
|
|
Validator::make([$field => $value], [
|
|
$field => Rule::unique('customers', $field)->ignore($id),
|
|
], [
|
|
$field . '.unique' => trans('La valeur :value pour le champ :attribute est déjà utilisé', [
|
|
'attribute' => $field,
|
|
'value' => $value
|
|
])
|
|
])->validate();
|
|
}
|
|
|
|
/**
|
|
* Get all user Departaimant collection or create them if they dont exists
|
|
*
|
|
* @return \Illuminate\Support\Collection<\App\Models\DepartaimantsCollection>
|
|
*/
|
|
public function getOrCreateAllDepartaimentsCollections(): Collection
|
|
{
|
|
$collections = $this->departaimantsCollections()->get()
|
|
->keyBy(fn (DepartaimantsCollection $el) => $el->type->value());
|
|
foreach (DepartaimantCollectionType::all() as $depColectionType) {
|
|
if (!$collections->has($depColectionType->value())) {
|
|
$depCollection = new DepartaimantsCollection([
|
|
'type' => $depColectionType->value
|
|
]);
|
|
$depCollection->customer()->associate($this);
|
|
$depCollection->save();
|
|
$collections->add($depCollection);
|
|
}
|
|
}
|
|
return $collections;
|
|
}
|
|
|
|
/**
|
|
* Get all notifications
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Collection<\App\Models\Notifications>
|
|
*/
|
|
public function getAllNotifications(): \Illuminate\Database\Eloquent\Collection
|
|
{
|
|
return Notifications::query()
|
|
->whereHas('customer', fn (Builder $q) => $q->where('id', $this->id))
|
|
->orWhere('customer_id', null)
|
|
->with('notifiable')
|
|
->orderBy('created_at', 'DESC')
|
|
->get();
|
|
}
|
|
|
|
// * --- AUTH ---
|
|
|
|
/**
|
|
* Send the email verification notification.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function sendEmailVerificationNotification()
|
|
{
|
|
$this->notify(new VerifyEmail());
|
|
}
|
|
|
|
/**
|
|
* Send the password reset notification.
|
|
*
|
|
* @param mixed $token
|
|
* @return void
|
|
*/
|
|
public function sendPasswordResetNotification(mixed $token)
|
|
{
|
|
/** @var string $token */
|
|
$this->notify(new ResetPassword($token));
|
|
}
|
|
}
|