143 lines
4.7 KiB
PHP
143 lines
4.7 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Support\Collection;
|
|
|
|
/**
|
|
* Serialises users for the Inertia pages.
|
|
*
|
|
* The presenter derived fields (avatar, formatted birthday, humanised last
|
|
* login) used to be read straight off `$user->present()` inside Blade. The Vue
|
|
* pages receive them as plain data instead, so the shapes live here rather than
|
|
* being spread across controllers.
|
|
*/
|
|
class UserPayload
|
|
{
|
|
/**
|
|
* A row of the users table.
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
public static function row(User $user): array
|
|
{
|
|
return [
|
|
'id' => $user->id,
|
|
'username' => $user->username,
|
|
'fullName' => trim("{$user->first_name} {$user->last_name}"),
|
|
'email' => $user->email,
|
|
'avatar' => $user->present()->avatar,
|
|
'nameOrEmail' => $user->present()->nameOrEmail,
|
|
'registeredAt' => $user->created_at->format(config('app.date_format')),
|
|
'status' => $user->status->value,
|
|
'statusLabel' => trans("app.status.{$user->status->value}"),
|
|
'statusVariant' => $user->present()->labelClass,
|
|
'waitingApproval' => $user->isWaitingApproval(),
|
|
'canImpersonate' => self::canImpersonate($user),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* The read only detail card.
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
public static function details(User $user): array
|
|
{
|
|
return [
|
|
'id' => $user->id,
|
|
'name' => $user->present()->name,
|
|
'nameOrEmail' => $user->present()->nameOrEmail,
|
|
'email' => $user->email,
|
|
'avatar' => $user->present()->avatar,
|
|
'phone' => $user->phone,
|
|
'birthday' => $user->present()->birthday,
|
|
'fullAddress' => $user->present()->fullAddress,
|
|
'lastLogin' => $user->present()->lastLogin,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* The editable fields behind the details and login details forms.
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
public static function form(User $user): array
|
|
{
|
|
return [
|
|
'id' => $user->id,
|
|
'nameOrEmail' => $user->present()->nameOrEmail,
|
|
'avatar' => $user->present()->avatar,
|
|
'first_name' => $user->first_name,
|
|
'last_name' => $user->last_name,
|
|
// A native date input round trips ISO, and `nullable|date` accepts it.
|
|
'birthday' => $user->birthday?->format('Y-m-d'),
|
|
'phone' => $user->phone,
|
|
'address' => $user->address,
|
|
'country_id' => $user->country_id ? (int) $user->country_id : 0,
|
|
'role_id' => (int) $user->role_id,
|
|
'status' => $user->status->value,
|
|
'email' => $user->email,
|
|
'username' => $user->username,
|
|
'force_password_change' => (bool) $user->force_password_change,
|
|
'waitingApproval' => $user->isWaitingApproval(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Every image the avatar picker can offer: the placeholder, Gravatar, and
|
|
* one per connected social account.
|
|
*
|
|
* @param Collection<int, object> $socialLogins
|
|
* @return array<int, array{label: string, url: string, external: bool}>
|
|
*/
|
|
public static function avatarSources(User $user, Collection $socialLogins): array
|
|
{
|
|
$sources = [
|
|
['label' => __('No Photo'), 'url' => url('assets/img/profile.png'), 'external' => true],
|
|
['label' => __('Gravatar'), 'url' => $user->gravatar(), 'external' => true],
|
|
];
|
|
|
|
foreach ($socialLogins as $login) {
|
|
$sources[] = [
|
|
'label' => ucfirst($login->provider),
|
|
'url' => $login->avatar,
|
|
'external' => true,
|
|
];
|
|
}
|
|
|
|
return $sources;
|
|
}
|
|
|
|
/**
|
|
* Two-factor state, mirroring the branching the Blade partial did inline.
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
public static function twoFactor(User $user): array
|
|
{
|
|
$needsVerification = session('tab') === '2fa' && $user->needsTwoFactorVerification();
|
|
|
|
return [
|
|
'enabled' => $user->twoFactorEnabled(),
|
|
'needsVerification' => $needsVerification,
|
|
'action' => match (true) {
|
|
$needsVerification => 'verify',
|
|
$user->twoFactorEnabled() => 'disable',
|
|
default => 'enable',
|
|
},
|
|
'qrCode' => $needsVerification ? $user->twoFactorQrCodeSvg() : null,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Exactly what the @canBeImpersonated Blade directive compiled to, so the
|
|
* link appears in the same cases it always did.
|
|
*/
|
|
public static function canImpersonate(User $user): bool
|
|
{
|
|
return can_be_impersonated($user);
|
|
}
|
|
}
|