app/Models/Instance/SpecialDate.php (74 lines of code) (raw):

<?php namespace App\Models\Instance; use Carbon\Carbon; use App\Helpers\DateHelper; use App\Models\Account\Account; use App\Models\Contact\Contact; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * A special date is a date that is not necessarily based on a year that we know. * This happens when we add a birthdate for instance. It can be based: * * on a real date, where we know the day, month and year * * on a date where we just know the day and the month but not the year * * on an age (we know this person is 33 but we don't know his birthdate, * so we'll give an estimation). * * Instead of adding a lot of logic in the Contact table, we've decided to * create this class that will deal with this complexity. * * @property bool $is_age_based * @property bool $is_year_unknown * @property \Carbon\Carbon|null $date */ class SpecialDate extends Model { /** * The table associated with the model. * * @var string */ protected $table = 'special_dates'; /** * The attributes that aren't mass assignable. * * @var array */ protected $guarded = ['id']; /** * All of the relationships to be touched. * * @var array */ protected $touches = ['contact']; /** * The attributes that should be mutated to dates. * * @var array */ protected $dates = ['date']; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'contact_id', 'account_id', ]; /** * The attributes that should be cast to native types. * * @var array */ protected $casts = [ 'is_age_based' => 'boolean', 'is_year_unknown' => 'boolean', ]; /** * Get the account record associated with the special date. * * @return BelongsTo */ public function account() { return $this->belongsTo(Account::class); } /** * Get the contact record associated with the special date. * * @return BelongsTo */ public function contact() { return $this->belongsTo(Contact::class); } /** * Returns a short version of the date, taking into account if the year is * unknown or not. This will return either `July 21` or `July 21, 2017`. */ public function toShortString() { if ($this->is_year_unknown) { return DateHelper::getShortDateWithoutYear($this->date); } return DateHelper::getShortDate($this->date); } /** * Returns the age that the date represents, if the date is set and if it's * not based on a year we don't know. * * @return int|null */ public function getAge(): ?int { if (is_null($this->date)) { return null; } if ($this->is_year_unknown) { return null; } return $this->date->diffInYears(now()); } /** * Create a SpecialDate from an age. * @param int $age */ public function createFromAge(int $age) { $this->is_age_based = true; $this->date = now()->subYears($age)->month(1)->day(1); $this->save(); return $this; } /** * Create a SpecialDate from an actual date, that might not contain a year. * @param int $year * @param int $month * @param int $day */ public function createFromDate(int $year, int $month, int $day) { // year 0 represents the `unknown` choice in the dropdown representing // the years if ($year != 0) { $date = Carbon::createFromDate($year, $month, $day); } else { $date = Carbon::createFromDate(now()->year, $month, $day); $this->is_year_unknown = true; } $this->date = $date; $this->save(); return $this; } /** * Associates a special date to a contact. * @param Contact $contact */ public function setToContact(Contact $contact) { $this->account_id = $contact->account_id; $this->contact_id = $contact->id; $this->save(); return $this; } }