engelsystem/src/Models/User/User.php

284 lines
8.4 KiB
PHP

<?php
declare(strict_types=1);
namespace Engelsystem\Models\User;
use Carbon\Carbon;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\BaseModel;
use Engelsystem\Models\Group;
use Engelsystem\Models\Message;
use Engelsystem\Models\News;
use Engelsystem\Models\NewsComment;
use Engelsystem\Models\OAuth;
use Engelsystem\Models\Privilege;
use Engelsystem\Models\Question;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftEntry;
use Engelsystem\Models\UserAngelType;
use Engelsystem\Models\Worklog;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Support\Collection as SupportCollection;
/**
* @property int $id
* @property string $name
* @property string $email
* @property string $password
* @property string $api_key
* @property Carbon|null $last_login_at
* @property Carbon $created_at
* @property Carbon $updated_at
*
* @property-read QueryBuilder|Contact $contact
* @property-read QueryBuilder|License $license
* @property-read QueryBuilder|PersonalData $personalData
* @property-read QueryBuilder|Settings $settings
* @property-read QueryBuilder|State $state
* @property-read string $displayName
*
* @property-read Collection|Group[] $groups
* @property-read Collection|News[] $news
* @property-read Collection|NewsComment[] $newsComments
* @property-read Collection|OAuth[] $oauth
* @property-read SupportCollection|Privilege[] $privileges
* @property-read Collection|AngelType[] $userAngelTypes
* @property-read UserAngelType $pivot
* @property-read Collection|ShiftEntry[] $shiftEntries
* @property-read Collection|Worklog[] $worklogs
* @property-read Collection|Worklog[] $worklogsCreated
* @property-read Collection|Question[] $questionsAsked
* @property-read Collection|Question[] $questionsAnswered
* @property-read Collection|Message[] $messagesReceived
* @property-read Collection|Message[] $messagesSent
* @property-read Collection|Message[] $messages
* @property-read Collection|Shift[] $shiftsCreated
* @property-read Collection|Shift[] $shiftsUpdated
*
* @method static QueryBuilder|User[] whereId($value)
* @method static QueryBuilder|User[] whereName($value)
* @method static QueryBuilder|User[] whereEmail($value)
* @method static QueryBuilder|User[] wherePassword($value)
* @method static QueryBuilder|User[] whereApiKey($value)
* @method static QueryBuilder|User[] whereLastLoginAt($value)
* @method static QueryBuilder|User[] whereCreatedAt($value)
* @method static QueryBuilder|User[] whereUpdatedAt($value)
*/
class User extends BaseModel
{
use HasFactory;
/** @var bool enable timestamps */
public $timestamps = true; // phpcs:ignore
/**
* The attributes that are mass assignable.
*
* @var array<string>
*/
protected $fillable = [ // phpcs:ignore
'name',
'password',
'email',
'api_key',
'last_login_at',
];
/** @var array<string> The attributes that should be hidden for serialization */
protected $hidden = [ // phpcs:ignore
'api_key',
'password',
];
/** @var array<string> The attributes that should be mutated to dates */
protected $dates = [ // phpcs:ignore
'last_login_at',
];
public function contact(): HasOne
{
return $this
->hasOne(Contact::class)
->withDefault();
}
public function groups(): BelongsToMany
{
return $this->belongsToMany(Group::class, 'users_groups');
}
public function isFreeloader(): bool
{
return $this->shiftEntries()
->where('freeloaded', true)
->count()
>= config('max_freeloadable_shifts');
}
public function license(): HasOne
{
return $this
->hasOne(License::class)
->withDefault();
}
public function privileges(): Builder
{
/** @var Builder $builder */
$builder = Privilege::query()
->whereIn('id', function ($query): void {
/** @var QueryBuilder $query */
$query->select('privilege_id')
->from('group_privileges')
->join('users_groups', 'users_groups.group_id', '=', 'group_privileges.group_id')
->where('users_groups.user_id', '=', $this->id)
->distinct();
});
return $builder;
}
public function getPrivilegesAttribute(): SupportCollection
{
return $this->privileges()->get();
}
public function personalData(): HasOne
{
return $this
->hasOne(PersonalData::class)
->withDefault();
}
public function settings(): HasOne
{
return $this
->hasOne(Settings::class)
->withDefault();
}
public function state(): HasOne
{
return $this
->hasOne(State::class)
->withDefault();
}
public function userAngelTypes(): BelongsToMany
{
return $this
->belongsToMany(AngelType::class, 'user_angel_type')
->using(UserAngelType::class)
->withPivot(UserAngelType::getPivotAttributes());
}
public function isAngelTypeSupporter(AngelType $angelType): bool
{
return $this->userAngelTypes()
->wherePivot('angel_type_id', $angelType->id)
->wherePivot('supporter', true)
->exists();
}
public function news(): HasMany
{
return $this->hasMany(News::class);
}
public function newsComments(): HasMany
{
return $this->hasMany(NewsComment::class);
}
public function oauth(): HasMany
{
return $this->hasMany(OAuth::class);
}
public function shiftEntries(): HasMany
{
return $this->hasMany(ShiftEntry::class);
}
public function worklogs(): HasMany
{
return $this->hasMany(Worklog::class);
}
public function worklogsCreated(): HasMany
{
return $this->hasMany(Worklog::class, 'creator_id');
}
public function questionsAsked(): HasMany
{
return $this->hasMany(Question::class, 'user_id')
->where('user_id', $this->id);
}
public function questionsAnswered(): HasMany
{
return $this->hasMany(Question::class, 'answerer_id')
->where('answerer_id', $this->id);
}
public function messagesSent(): HasMany
{
return $this->hasMany(Message::class, 'user_id')
->orderBy('created_at', 'DESC')
->orderBy('id', 'DESC');
}
public function messagesReceived(): HasMany
{
return $this->hasMany(Message::class, 'receiver_id')
->orderBy('read')
->orderBy('created_at', 'DESC')
->orderBy('id', 'DESC');
}
/**
* Returns a HasMany relation for all messages sent or received by the user.
*/
public function messages(): HasMany
{
return $this->messagesSent()
->union($this->messagesReceived())
->orderBy('read')
->orderBy('id', 'DESC');
}
public function shiftsCreated(): HasMany
{
return $this->hasMany(Shift::class, 'created_by');
}
public function shiftsUpdated(): HasMany
{
return $this->hasMany(Shift::class, 'updated_by');
}
public function getDisplayNameAttribute(): string
{
if (
config('display_full_name')
&& !empty(trim($this->personalData->first_name . $this->personalData->last_name))
) {
return trim(
trim((string) $this->personalData->first_name)
. ' ' .
trim((string) $this->personalData->last_name)
);
}
return $this->name;
}
}