1
0

listen ansichten verbessert

This commit is contained in:
2026-03-05 11:17:42 +01:00
parent 4b31fc7664
commit c5f657c8c8
133 changed files with 2806 additions and 636 deletions

View File

@@ -2,6 +2,7 @@
namespace MintyPHP\Repository\Stats;
use MintyPHP\DB;
use MintyPHP\Domain\Taxonomy\ImportAuditStatus;
use MintyPHP\Domain\Taxonomy\MailLogStatus;
use MintyPHP\Domain\Taxonomy\ScheduledJobRunStatus;
@@ -10,7 +11,6 @@ use MintyPHP\Domain\Taxonomy\SystemAuditOutcome;
use MintyPHP\Domain\Taxonomy\TenantStatus;
use MintyPHP\Domain\Taxonomy\UserLifecycleAction;
use MintyPHP\Domain\Taxonomy\UserLifecycleStatus;
use MintyPHP\DB;
class AdminStatsRepository implements AdminStatsRepositoryInterface
{
@@ -43,7 +43,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$inactiveDepartmentCount = (int) (DB::selectValue('select count(*) from departments where active = 0') ?? 0);
$activeRoleCount = (int) (DB::selectValue('select count(*) from roles where active = 1') ?? 0);
$inactiveRoleCount = (int) (DB::selectValue('select count(*) from roles where active = 0') ?? 0);
$rolesWithoutPermissionsCount = (int) (DB::selectValue(
'select count(*) from roles r left join role_permissions rp on rp.role_id = r.id where r.active = 1 and rp.role_id is null'
) ?? 0);
@@ -56,7 +56,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$usersWithoutTenantsCount = (int) (DB::selectValue(
'select count(*) from users u left join user_tenants ut on ut.user_id = u.id where u.active = 1 and ut.user_id is null'
) ?? 0);
$flattenStatsRow = static function ($row): array {
if (!is_array($row)) {
return [];
@@ -74,7 +74,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
}
return $flat;
};
$ssoStatsAvailable = (int) (DB::selectValue(
"select count(*) from information_schema.tables where table_schema = database() and table_name = 'tenant_auth_microsoft'"
) ?? 0) === 1;
@@ -86,7 +86,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$ssoTenantRows = [];
$usersMicrosoftOnlyRows = [];
$usersMicrosoftSyncGapRows = [];
if ($ssoStatsAvailable) {
$ssoEnabledTenantCount = (int) (DB::selectValue(
"select count(*) from tenants t " .
@@ -103,7 +103,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
if ($activeTenantCount > 0) {
$ssoEnabledTenantPercent = round(((float) $ssoEnabledTenantCount * 100) / (float) $activeTenantCount, 1);
}
$usersMicrosoftOnlyCount = (int) (DB::selectValue(
"select count(*) from users u " .
"where u.active = 1 " .
@@ -122,7 +122,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$tenantActiveStatus,
$tenantActiveStatus
) ?? 0);
$usersMicrosoftSyncGapsCount = (int) (DB::selectValue(
"select count(*) from ( " .
" select u.id, " .
@@ -147,7 +147,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
" or (x.need_mobile = 1 and x.mobile_value = '')",
$tenantActiveStatus
) ?? 0);
$ssoTenantRowsRaw = DB::select(
"select " .
" t.uuid as tenant_uuid, " .
@@ -182,7 +182,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
},
$ssoTenantRowsRaw
))) : [];
$usersMicrosoftOnlyRowsRaw = DB::select(
"select " .
" u.uuid as user_uuid, " .
@@ -217,7 +217,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
},
$usersMicrosoftOnlyRowsRaw
))) : [];
$usersMicrosoftSyncGapRowsRaw = DB::select(
"select " .
" x.user_uuid, x.user_display_name, x.user_email, " .
@@ -278,7 +278,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$usersMicrosoftSyncGapRowsRaw
))) : [];
}
$customFieldStatsAvailable = (int) (DB::selectValue(
"select count(*) from information_schema.tables " .
"where table_schema = database() " .
@@ -293,7 +293,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$customFieldsInactiveWithValuesHref = 'admin/tenants';
$customFieldsUnusedActiveHref = 'admin/tenants';
$customFieldIssueTenantRows = [];
if ($customFieldStatsAvailable) {
$loadCustomFieldIssueTenants = static function (string $query): array {
$rows = DB::select($query);
@@ -318,7 +318,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
}
return $items;
};
$customFieldsSelectionWithoutOptionsCount = (int) (DB::selectValue(
"select count(*) from ( " .
"select d.id " .
@@ -329,7 +329,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
"having count(o.id) = 0 " .
') missing_options'
) ?? 0);
$customFieldTenantsWithSelectionWithoutOptionsCount = (int) (DB::selectValue(
"select count(distinct missing_options.tenant_id) from ( " .
"select d.tenant_id " .
@@ -340,13 +340,13 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
"having count(o.id) = 0 " .
') missing_options'
) ?? 0);
$customFieldsInactiveWithValuesCount = (int) (DB::selectValue(
'select count(distinct d.id) from tenant_custom_field_definitions d ' .
'inner join user_custom_field_values v on v.definition_id = d.id ' .
'where d.active = 0'
) ?? 0);
$customFieldsUnusedActiveCount = (int) (DB::selectValue(
"select count(*) from ( " .
"select d.id " .
@@ -357,7 +357,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
"having count(v.id) = 0 " .
') unused_active'
) ?? 0);
$selectionWithoutOptionsTenantUuid = (string) (DB::selectValue(
"select t.uuid from tenants t " .
"inner join ( " .
@@ -372,7 +372,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
') issue on issue.tenant_id = t.id ' .
'limit 1'
) ?? '');
$inactiveWithValuesTenantUuid = (string) (DB::selectValue(
"select t.uuid from tenants t " .
"inner join ( " .
@@ -386,7 +386,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
') issue on issue.tenant_id = t.id ' .
'limit 1'
) ?? '');
$unusedActiveTenantUuid = (string) (DB::selectValue(
"select t.uuid from tenants t " .
"inner join ( " .
@@ -401,7 +401,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
') issue on issue.tenant_id = t.id ' .
'limit 1'
) ?? '');
if ($selectionWithoutOptionsTenantUuid !== '') {
$customFieldsSelectionWithoutOptionsHref = 'admin/tenants/edit/' . $selectionWithoutOptionsTenantUuid . '?tab=custom_fields';
$customFieldTenantsWithSelectionWithoutOptionsHref = $customFieldsSelectionWithoutOptionsHref;
@@ -412,7 +412,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
if ($unusedActiveTenantUuid !== '') {
$customFieldsUnusedActiveHref = 'admin/tenants/edit/' . $unusedActiveTenantUuid . '?tab=custom_fields';
}
$selectionIssueTenants = $loadCustomFieldIssueTenants(
"select t.uuid, t.description, count(*) as issue_count " .
"from tenants t " .
@@ -436,7 +436,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
'issue_count' => $row['issue_count'],
];
}
$inactiveIssueTenants = $loadCustomFieldIssueTenants(
"select t.uuid, t.description, count(distinct d.id) as issue_count " .
"from tenants t " .
@@ -454,7 +454,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
'issue_count' => $row['issue_count'],
];
}
$unusedIssueTenants = $loadCustomFieldIssueTenants(
"select t.uuid, t.description, count(*) as issue_count " .
"from tenants t " .
@@ -479,7 +479,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
];
}
}
$apiStatsAvailable = (int) (DB::selectValue(
"select count(*) from information_schema.tables " .
"where table_schema = database() and table_name in ('api_audit_log', 'user_api_tokens')"
@@ -493,7 +493,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$apiTokensExpiring7dCount = 0;
$apiTopErrorRows = [];
$apiSlowEndpointRows = [];
if ($apiStatsAvailable) {
$apiRequests24hCount = (int) (DB::selectValue(
'select count(*) from api_audit_log where created_at >= (NOW() - INTERVAL 24 HOUR)'
@@ -504,14 +504,14 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
if ($apiRequestsPrev24hCount > 0) {
$apiRequestTrendPercent = round((($apiRequests24hCount - $apiRequestsPrev24hCount) * 100) / $apiRequestsPrev24hCount, 1);
}
$apiErrors4xx24hCount = (int) (DB::selectValue(
'select count(*) from api_audit_log where created_at >= (NOW() - INTERVAL 24 HOUR) and status_code between 400 and 499'
) ?? 0);
$apiErrors5xx24hCount = (int) (DB::selectValue(
'select count(*) from api_audit_log where created_at >= (NOW() - INTERVAL 24 HOUR) and status_code between 500 and 599'
) ?? 0);
$durationCount = (int) (DB::selectValue(
'select count(*) from api_audit_log where created_at >= (NOW() - INTERVAL 24 HOUR) and status_code between 200 and 299 and duration_ms is not null'
) ?? 0);
@@ -523,12 +523,12 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
'order by duration_ms asc limit ' . $offset . ', 1'
) ?? 0);
}
$apiTokensExpiring7dCount = (int) (DB::selectValue(
'select count(*) from user_api_tokens ' .
'where revoked_at is null and expires_at is not null and expires_at > NOW() and expires_at <= (NOW() + INTERVAL 7 DAY)'
) ?? 0);
$apiTopErrorRowsRaw = DB::select(
"select " .
" coalesce(nullif(error_code, ''), concat('http_', status_code)) as error_label, " .
@@ -554,7 +554,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
},
$apiTopErrorRowsRaw
))) : [];
$apiSlowEndpointRowsRaw = DB::select(
"select " .
" path, " .
@@ -586,7 +586,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$apiSlowEndpointRowsRaw
))) : [];
}
$importStatsAvailable = (int) (DB::selectValue(
"select count(*) from information_schema.tables " .
"where table_schema = database() and table_name = 'import_audit_runs'"
@@ -602,7 +602,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$importRecentRunRows = [];
$importProfileRows = [];
$importTopErrorCodeRows = [];
if ($importStatsAvailable) {
$importRuns7dCount = (int) (DB::selectValue(
"select count(*) from import_audit_runs where started_at >= (NOW() - INTERVAL 7 DAY)"
@@ -613,7 +613,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
if ($importRunsPrev7dCount > 0) {
$importRunTrendPercent = round((($importRuns7dCount - $importRunsPrev7dCount) * 100) / $importRunsPrev7dCount, 1);
}
$importRowsCreated7dCount = (int) (DB::selectValue(
"select coalesce(sum(created_count), 0) from import_audit_runs where started_at >= (NOW() - INTERVAL 7 DAY)"
) ?? 0);
@@ -635,7 +635,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
if ($importRuns7dCount > 0) {
$importSuccessRate7dPercent = round(($importSuccessRuns7dCount * 100) / $importRuns7dCount, 1);
}
$importRecentRunRowsRaw = DB::select(
"select " .
" import_audit_runs.id, " .
@@ -680,7 +680,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
},
$importRecentRunRowsRaw
))) : [];
$importProfileRowsRaw = DB::select(
"select " .
" profile_key, " .
@@ -715,7 +715,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
},
$importProfileRowsRaw
))) : [];
$importTopErrorRowsRaw = DB::select(
"select error_codes_json from import_audit_runs " .
"where started_at >= (NOW() - INTERVAL 7 DAY) " .
@@ -1001,7 +1001,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$lifecycleRecentRiskRowsRaw
))) : [];
}
$scheduledStatsAvailable = (int) (DB::selectValue(
"select count(*) from information_schema.tables " .
"where table_schema = database() and table_name in ('scheduled_jobs', 'scheduled_job_runs', 'scheduler_runtime_status')"
@@ -1014,7 +1014,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$schedulerRunnerLastResult = '';
$schedulerRunnerLastErrorCode = '';
$schedulerRunnerIsActive = false;
if ($scheduledStatsAvailable) {
$scheduledEnabledJobsCount = (int) (DB::selectValue(
"select count(*) from scheduled_jobs where enabled = 1"
@@ -1034,12 +1034,12 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$schedulerTriggerScheduler,
$schedulerRunStatusFailed
) ?? 0);
$schedulerRunnerIsActive = (int) (DB::selectValue(
"select case when last_heartbeat_at >= (NOW() - INTERVAL 3 MINUTE) then 1 else 0 end " .
"from scheduler_runtime_status where id = 1"
) ?? 0) === 1;
$schedulerRuntimeRowRaw = DB::selectOne(
"select last_heartbeat_at, last_result, last_error_code from scheduler_runtime_status where id = 1 limit 1"
);
@@ -1048,7 +1048,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
$schedulerRunnerLastResult = trim((string) ($schedulerRuntimeRow['last_result'] ?? ''));
$schedulerRunnerLastErrorCode = trim((string) ($schedulerRuntimeRow['last_error_code'] ?? ''));
}
$usersUnverifiedCount = (int) (DB::selectValue(
'select count(*) from users where active = 1 and email_verified_at is null'
) ?? 0);
@@ -1069,7 +1069,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
static fn ($row) => $row['users'] ?? $row,
$neverLoggedUsers
) : [];
$mailLogFailedCount = (int) (DB::selectValue('select count(*) from mail_log where status = ?', $mailStatusFailed) ?? 0);
$mailLogSentCount = (int) (DB::selectValue('select count(*) from mail_log where status = ?', $mailStatusSent) ?? 0);
$mailLogLastSentAt = (string) (DB::selectValue('select max(sent_at) from mail_log where status = ?', $mailStatusSent) ?? '');
@@ -1081,7 +1081,7 @@ class AdminStatsRepository implements AdminStatsRepositoryInterface
static fn ($row) => $row['mail_log'] ?? $row,
$mailLogRecentFailed
) : [];
$vars = get_defined_vars();
unset($vars['this']);