*/ use HasFactory, SoftDeletes; /** @var array */ protected $attributes = [ 'kind' => ApplicationKind::Contribute->value, 'status' => ApplicationStatus::New->value, ]; protected function casts(): array { return [ 'kind' => ApplicationKind::class, 'status' => ApplicationStatus::class, 'hours_per_week' => 'integer', 'links' => 'array', 'handled_at' => 'datetime', ]; } /** * @return BelongsTo */ public function call(): BelongsTo { return $this->belongsTo(Call::class); } /** * @return BelongsTo */ public function handler(): BelongsTo { return $this->belongsTo(User::class, 'handled_by'); } /** * Still waiting for a human. This is the number the navigation badge * shows, and the only one that matters day to day. * * @param Builder<$this> $query * @return Builder<$this> */ public function scopePending(Builder $query): Builder { return $query->where('status', ApplicationStatus::New); } /** * @param Builder<$this> $query * @return Builder<$this> */ public function scopeNotSpam(Builder $query): Builder { return $query->where('status', '!=', ApplicationStatus::Spam); } /** * Move the submission along and record who did it, so an inbox worked by * several people does not turn into two replies or none. */ public function markAs(ApplicationStatus $status, ?User $by = null): void { $this->forceFill([ 'status' => $status, 'handled_by' => $status->isHandled() ? ($by?->id ?? $this->handled_by) : null, 'handled_at' => $status->isHandled() ? now() : null, ])->save(); } /** * What the sender is asking about, whether or not the call still exists. */ public function subject(): string { // The live title when the call is at hand — it may have been reworded // since — and the snapshot otherwise, including once the call itself // is gone. Never a lazy load: this is read inside table rows. if ($this->relationLoaded('call') && $this->call !== null) { return $this->call->getTranslation('title', $this->locale); } return $this->call_title ?? __('panel.applications.general_enquiry'); } /** * A keyed hash of the sender's address. * * Enough to spot a flood coming from one place; not enough to turn this * table into a log of who visited the site. The application key is the * secret, so the hashes are useless if the table alone leaks. */ public static function hashIp(?string $ip): ?string { if (blank($ip)) { return null; } return hash_hmac('sha256', $ip, (string) Config::get('app.key')); } }