<?php namespace App\Models; use AdamWathan\EloquentOAuth\OAuthIdentity; use App\Models\Concerns\InstanceCache; use App\Models\Concerns\Reportable; use Illuminate\Database\Eloquent\Collection; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notification; use MightyPork\Exceptions\ArgumentException; use MightyPork\Exceptions\NotExistException; /** * A user in the application * * @property int $id * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $updated_at * @property string $name - unique, for vanity URL * @property string $title - for display * @property string $bio - user bio * @property string $website - custom url * @property string $email - unique, for login and social auth chaining * @property string $password - hashed pw * @property bool $confirmed - user e-mail is confirmed * @property-read Proposal[]|Collection $proposals * @property-read Table[]|Collection $tables * @property-read OAuthIdentity[]|Collection $socialIdentities * @property-read TableComment[]|Collection $tableComments * @property-read Table[]|Collection $favouriteTables * @property-read Table[]|Collection $followedDiscussions * @property-read ContentReport[]|Collection $authoredReports * @property-read Notification[]|Collection $notifications * @property-read Notification[]|Collection $readNotifications * @property-read Notification[]|Collection $unreadNotifications * @property-read string $handle - user handle, including @ */ class User extends Authenticatable { use Reportable; use Notifiable; use InstanceCache; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'title', 'email', 'password', 'bio', 'website' ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; protected static function boot() { parent::boot(); static::deleting(function(User $self) { // comments are deleted via cascade $self->reportsOf()->delete(); // manually delete proposals to ensure row refcounts are updated foreach ($self->proposals as $proposal) { $proposal->delete(); } foreach ($self->tables as $table) { $table->delete(); } }); } /** Owned tables */ public function tables() { return $this->hasMany(Table::class, 'owner_id'); } /** Assigned OAuth identities */ public function socialIdentities() { return $this->hasMany(OAuthIdentity::class); } /** Authored proposals */ public function proposals() { return $this->hasMany(Proposal::class, 'author_id'); } /** Authored comments */ public function tableComments() { return $this->hasMany(TableComment::class, 'author_id'); } /** User's favourite tables (personal collection) */ public function favouriteTables() { return $this->belongsToMany(Table::class, 'table_favourites'); } /** Tables whose discussions user follows (this is similar to favourites) */ public function followedDiscussions() { return $this->belongsToMany(Table::class, 'discussion_follows'); } /** Reports sent by this user */ public function authoredReports() { return $this->hasMany(ContentReport::class, 'author_id'); } // --------- Relation Helpers --------- public function addFavourite(Table $table) { $this->favouriteTables()->attach($table); } public function removeFavourite(Table $table) { $this->favouriteTables()->detach($table); } public function followDiscussion(Table $table) { $this->followedDiscussions()->attach($table); } public function unfollowDiscussion(Table $table) { $this->followedDiscussions()->detach($table); } /** * Resolve user by a given name, id, or e-mail * * @param string $ident * @return User */ public static function resolve($ident) { $ident = "$ident"; if (strlen($ident) == 0) throw new ArgumentException("Can't find user by empty string."); if (is_numeric($ident)) { $u = static::find((int)$ident); } else if ($ident[0] == '@') { $u = static::where('name', substr($ident, 1))->first(); } else { $u = static::where('email', $ident)->first(); } if (!$u) throw new NotExistException("No user found matching \"$ident\""); return $u; } public function __get($name) { if ($name == 'handle') return "@$this->name"; return parent::__get($name); } public function ownsTable(Table $table) { return $table->owner_id == $this->id; } public function favouritesTable(Table $table) { return \DB::table('table_favourites') ->where('user_id', $this->id) ->where('table_id', $table->id)->exists(); } }