$data Contact data. * @property string|null $notes Contact notes. * @property array> $visits Contact visits. * @property-read \Carbon\Carbon|null $created_at Created date. * @property-read \Carbon\Carbon|null $updated_at Updated date. */ class Contact extends Model { use HasFactory; use HasUuidKey; /** * The attributes that are mass assignable. * * @var list */ protected $fillable = [ 'app_user_id', 'email', 'lastname', 'firstname', 'data', 'phone', 'notes', 'visits', 'timestamp', ]; /** * The attributes that should be cast. * * @var array */ protected $casts = [ 'data' => AsArrayOfInput::class, 'timestamp' => 'immutable_datetime', 'visits' => 'array' ]; /** * Perform any actions required after the model boots. * * @return void */ protected static function booted(): void { static::creating(function (self $model) { $model->id = Str::uuid(); self::assertContactDataIsMatchingFormulary($model); }); static::deleting(function (self $model) { self::assertContactDataIsMatchingFormulary($model); }); } // * RELATIONSHIPS /** * MorphToMany Directories. * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function appUser(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(AppUser::class, 'app_user_id', 'id'); } // * METHODS /** * Get all inputs. * * @return array * @throws \RuntimeException This should not happen since data was validated on contact insertion. * ! It may happen if this model does not have an email. * ! It may only happen if input validation rules are changed. */ public function allInputs(): array { return $this->mandatoryInputs() + $this->data; } /** * Get mandatory inputs. * * @return array<\App\Lib\Inputs\Definition\Input> * @throws \RuntimeException If this model does have an email. */ public function mandatoryInputs(): array { // * firsname $data[] = InputText::make('Prénom', $this->firstname, [], false); // * lastname $data[] = InputText::make('Nom', $this->lastname, [], false); // * email $data[] = InputEmail::make('E-mail', $this->email, [], true); // * phone $data[] = InputPhone::make('Téléphone', $this->phone, [], false); return $data; } /** * Assert contact data is matching actual Formularies * * @param \App\Models\Contact $contact * @return void */ public static function assertContactDataIsMatchingFormulary(Contact $contact): void { /** @var \Illuminate\Support\Collection */ $formularies = Formulary::query()->pluck('slug')->flip(); \collect($contact->data)->each(function (Input $input) use ($formularies) { if (!$formularies->has($input->data->formSlug)) { throw new \ErrorException( "Formulary {$input->data->formSlug} does not exist, do not store this contact data prop" ); } }); } /** * Remove Data Input on All contacts * * @param \App\Models\Formulary $formulary * @return void */ public static function removeDataInputOnAllContacts(Formulary $formulary): void { DB::transaction(function () use ($formulary) { Contact::query()->select(['id', 'data'])->each(function (Contact $contact) use ($formulary) { $contact->data = \collect($contact->data)->filter(function (Input $input) use ($formulary) { return $input->data->formSlug !== $formulary->slug; })->toArray(); $contact->saveOrFail(); }); }); } }