124 lines
4.1 KiB
PHP
124 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace Plugin\UserOnlineDevices\Controllers;
|
|
|
|
use App\Http\Controllers\PluginController;
|
|
use App\Models\User;
|
|
use App\Services\DeviceStateService;
|
|
use DateTimeInterface;
|
|
use Illuminate\Contracts\View\View;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Pagination\LengthAwarePaginator;
|
|
|
|
class UserOnlineDevicesController extends PluginController
|
|
{
|
|
public function __construct(
|
|
private readonly DeviceStateService $deviceStateService
|
|
) {
|
|
}
|
|
|
|
public function index(Request $request): View
|
|
{
|
|
if ($error = $this->beforePluginAction()) {
|
|
abort($error[0], $error[1]);
|
|
}
|
|
|
|
$defaultPageSize = (int) $this->getConfig('default_page_size', 20);
|
|
$pageSize = (int) $request->integer('per_page', $defaultPageSize);
|
|
$pageSize = in_array($pageSize, [20, 50, 100], true) ? $pageSize : $defaultPageSize;
|
|
|
|
$keyword = trim((string) $request->query('keyword', ''));
|
|
|
|
$query = User::query()
|
|
->select([
|
|
'id',
|
|
'email',
|
|
'plan_id',
|
|
'online_count',
|
|
'last_online_at',
|
|
'created_at',
|
|
])
|
|
->with(['plan:id,name'])
|
|
->orderByDesc('id');
|
|
|
|
if ($keyword !== '') {
|
|
$query->where(function ($builder) use ($keyword) {
|
|
$builder->where('email', 'like', '%' . $keyword . '%');
|
|
|
|
if (ctype_digit($keyword)) {
|
|
$builder->orWhere('id', (int) $keyword);
|
|
}
|
|
});
|
|
}
|
|
|
|
/** @var LengthAwarePaginator $paginator */
|
|
$paginator = $query->paginate($pageSize)->appends($request->query());
|
|
|
|
$userIds = $paginator->getCollection()->pluck('id')->all();
|
|
$devicesByUser = $this->deviceStateService->getUsersDevices($userIds);
|
|
|
|
$paginator->setCollection(
|
|
$paginator->getCollection()->map(function (User $user) use ($devicesByUser) {
|
|
$ips = array_values($devicesByUser[$user->id] ?? []);
|
|
sort($ips);
|
|
|
|
$user->online_devices = $ips;
|
|
$user->online_count_live = count($ips);
|
|
$user->subscription_name = $user->plan?->name ?: 'No subscription';
|
|
$user->last_online_text = $this->formatDateTime($user->last_online_at);
|
|
$user->created_text = $this->formatDateTime($user->created_at);
|
|
|
|
return $user;
|
|
})
|
|
);
|
|
|
|
$pageUsers = $paginator->getCollection()->count();
|
|
$usersWithOnlineIp = $paginator->getCollection()->filter(function (User $user) {
|
|
return ($user->online_count_live ?? 0) > 0;
|
|
})->count();
|
|
$totalOnlineIps = $paginator->getCollection()->sum(function (User $user) {
|
|
return (int) ($user->online_count_live ?? 0);
|
|
});
|
|
|
|
$securePath = admin_setting('secure_path', admin_setting('frontend_admin_path', hash('crc32b', config('app.key'))));
|
|
|
|
return view('UserOnlineDevices::admin-index', [
|
|
'users' => $paginator,
|
|
'filters' => [
|
|
'keyword' => $keyword,
|
|
'per_page' => $pageSize,
|
|
],
|
|
'summary' => [
|
|
'page_users' => $pageUsers,
|
|
'users_with_online_ip' => $usersWithOnlineIp,
|
|
'total_online_ips' => $totalOnlineIps,
|
|
'current_page' => $paginator->currentPage(),
|
|
],
|
|
'adminHomeUrl' => url('/' . $securePath),
|
|
]);
|
|
}
|
|
|
|
private function formatDateTime(mixed $value): string
|
|
{
|
|
if ($value instanceof DateTimeInterface) {
|
|
return $value->format('Y-m-d H:i:s');
|
|
}
|
|
|
|
if (is_numeric($value)) {
|
|
$timestamp = (int) $value;
|
|
if ($timestamp > 0) {
|
|
return date('Y-m-d H:i:s', $timestamp);
|
|
}
|
|
}
|
|
|
|
if (is_string($value) && trim($value) !== '') {
|
|
$timestamp = strtotime($value);
|
|
if ($timestamp !== false) {
|
|
return date('Y-m-d H:i:s', $timestamp);
|
|
}
|
|
}
|
|
|
|
return '-';
|
|
}
|
|
}
|