This commit is contained in:
@@ -938,9 +938,23 @@ final class AccountPages
|
||||
$communityLevelRightDefinitions = Community::membershipRightDefinitions();
|
||||
$communityRoles = $communityAccess ? $communityAccess->getUserRoles($userId) : [];
|
||||
$systemRoleAssignments = $communityAccess && $canManageProfileLevels ? $communityAccess->listRoleAssignments() : [];
|
||||
$recentHighLevelUsers = [];
|
||||
$recentHighLevelThresholdLabel = '';
|
||||
$profileLevelUserSearchQuery = '';
|
||||
$profileLevelUserSearchResults = [];
|
||||
if ($communityAccess && $community && $canManageProfileLevels) {
|
||||
$highLevelThreshold = null;
|
||||
foreach ($communityLevelDefinitions as $levelDefinition) {
|
||||
if ((string)($levelDefinition['label'] ?? '') === 'Säule der Väter-Community') {
|
||||
$highLevelThreshold = (float)($levelDefinition['min'] ?? 0.0);
|
||||
$recentHighLevelThresholdLabel = (string)($levelDefinition['label'] ?? '');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($highLevelThreshold !== null && $highLevelThreshold > 0) {
|
||||
$recentHighLevelUsers = $community->listRecentlyReachedLevelUsers($highLevelThreshold, 30, 12);
|
||||
}
|
||||
|
||||
$profileLevelUserSearchQuery = trim((string)($_GET['profile_level_user_query'] ?? ''));
|
||||
if ($profileLevelUserSearchQuery !== '') {
|
||||
foreach ($communityAccess->searchUsers($profileLevelUserSearchQuery, 12) as $searchRow) {
|
||||
@@ -1031,6 +1045,8 @@ final class AccountPages
|
||||
'communityLevelRightDefinitions',
|
||||
'communityRoles',
|
||||
'systemRoleAssignments',
|
||||
'recentHighLevelUsers',
|
||||
'recentHighLevelThresholdLabel',
|
||||
'profileLevelUserSearchQuery',
|
||||
'profileLevelUserSearchResults',
|
||||
'communityApplication',
|
||||
|
||||
@@ -447,6 +447,99 @@ final class Community
|
||||
return $amount;
|
||||
}
|
||||
|
||||
public function listRecentlyReachedLevelUsers(float $minPoints, int $days = 30, int $limit = 12): array
|
||||
{
|
||||
if ($minPoints <= 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$days = max(1, min(365, $days));
|
||||
$limit = max(1, min(100, $limit));
|
||||
$cutoff = (new \DateTimeImmutable('today 23:59:59'))->modify('-' . $days . ' days');
|
||||
|
||||
$candidateStmt = $this->pdo->prepare(
|
||||
'SELECT upt.user_id, upt.total, up.display_name, up.first_name, up.last_name
|
||||
FROM user_points_totals upt
|
||||
JOIN users u ON u.id = upt.user_id
|
||||
LEFT JOIN user_profiles up ON up.user_id = upt.user_id
|
||||
WHERE upt.total >= :minPoints
|
||||
ORDER BY upt.total DESC, upt.updated_at DESC
|
||||
LIMIT ' . $limit
|
||||
);
|
||||
$candidateStmt->execute(['minPoints' => $minPoints]);
|
||||
$candidates = $candidateStmt->fetchAll(\PDO::FETCH_ASSOC) ?: [];
|
||||
if ($candidates === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$candidateIds = array_values(array_map(static fn(array $row): int => (int)($row['user_id'] ?? 0), $candidates));
|
||||
$candidateIds = array_values(array_filter($candidateIds, static fn(int $id): bool => $id > 0));
|
||||
if ($candidateIds === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$placeholders = implode(',', array_fill(0, count($candidateIds), '?'));
|
||||
$pointsStmt = $this->pdo->prepare(
|
||||
"SELECT user_id, amount, created_at
|
||||
FROM user_points
|
||||
WHERE user_id IN ($placeholders)
|
||||
ORDER BY user_id ASC, created_at ASC, id ASC"
|
||||
);
|
||||
$pointsStmt->execute($candidateIds);
|
||||
$pointRows = $pointsStmt->fetchAll(\PDO::FETCH_ASSOC) ?: [];
|
||||
|
||||
$reachedAtByUser = [];
|
||||
$runningTotals = [];
|
||||
foreach ($pointRows as $pointRow) {
|
||||
$entryUserId = (int)($pointRow['user_id'] ?? 0);
|
||||
if ($entryUserId <= 0) {
|
||||
continue;
|
||||
}
|
||||
$runningTotals[$entryUserId] = ($runningTotals[$entryUserId] ?? 0.0) + (float)($pointRow['amount'] ?? 0.0);
|
||||
if (isset($reachedAtByUser[$entryUserId])) {
|
||||
continue;
|
||||
}
|
||||
if ($runningTotals[$entryUserId] >= $minPoints) {
|
||||
$reachedAtByUser[$entryUserId] = (string)($pointRow['created_at'] ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
$recentUsers = [];
|
||||
foreach ($candidates as $candidate) {
|
||||
$candidateUserId = (int)($candidate['user_id'] ?? 0);
|
||||
$reachedAtRaw = (string)($reachedAtByUser[$candidateUserId] ?? '');
|
||||
if ($candidateUserId <= 0 || $reachedAtRaw === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$reachedAt = new \DateTimeImmutable($reachedAtRaw);
|
||||
} catch (\Throwable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($reachedAt < $cutoff) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$recentUsers[] = [
|
||||
'user_id' => $candidateUserId,
|
||||
'display_name' => (string)($candidate['display_name'] ?? ''),
|
||||
'first_name' => (string)($candidate['first_name'] ?? ''),
|
||||
'last_name' => (string)($candidate['last_name'] ?? ''),
|
||||
'points' => (float)($candidate['total'] ?? 0.0),
|
||||
'level' => $this->membershipLevel((float)($candidate['total'] ?? 0.0)),
|
||||
'reached_at' => $reachedAt->format('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
|
||||
usort($recentUsers, static function (array $left, array $right): int {
|
||||
return strcmp((string)($right['reached_at'] ?? ''), (string)($left['reached_at'] ?? ''));
|
||||
});
|
||||
|
||||
return array_slice($recentUsers, 0, $limit);
|
||||
}
|
||||
|
||||
public function membershipLevel(float $points): array
|
||||
{
|
||||
$level = $this->membershipLevelMeta($points);
|
||||
|
||||
@@ -323,14 +323,15 @@ final class CommunityAccess
|
||||
WHERE ' . implode(' AND ', $conditions) . '
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN LOWER(COALESCE(up.display_name, "")) = :exactQuery THEN 0
|
||||
WHEN LOWER(COALESCE(u.email, "")) = :exactQuery THEN 1
|
||||
WHEN LOWER(COALESCE(up.display_name, "")) = :exactDisplayQuery THEN 0
|
||||
WHEN LOWER(COALESCE(u.email, "")) = :exactEmailQuery THEN 1
|
||||
ELSE 2
|
||||
END,
|
||||
COALESCE(up.display_name, ""),
|
||||
u.id DESC
|
||||
LIMIT ' . $limit;
|
||||
$params[':exactQuery'] = mb_strtolower($query);
|
||||
$params[':exactDisplayQuery'] = mb_strtolower($query);
|
||||
$params[':exactEmailQuery'] = mb_strtolower($query);
|
||||
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
Reference in New Issue
Block a user