From f7a6b34a97b3f6bb02a827903851c06199404439 Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Mon, 17 Aug 2026 00:39:46 +0200 Subject: [PATCH] sadsd --- src/App/CommunityAccess.php | 88 +++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 32 deletions(-) diff --git a/src/App/CommunityAccess.php b/src/App/CommunityAccess.php index 63c4580..b67366c 100644 --- a/src/App/CommunityAccess.php +++ b/src/App/CommunityAccess.php @@ -298,44 +298,68 @@ final class CommunityAccess } $limit = max(1, min(50, $limit)); + $rowsById = []; + $tokens = array_values(array_filter(preg_split('/\s+/u', mb_strtolower($query)) ?: [], static fn(string $token): bool => $token !== '')); - if ($tokens === []) { - return []; + if ($tokens !== []) { + $conditions = []; + $params = []; + foreach ($tokens as $index => $token) { + $displayKey = ':display_' . $index; + $conditions[] = 'LOWER(COALESCE(up.display_name, "")) LIKE ' . $displayKey; + $params[$displayKey] = '%' . $token . '%'; + } + + $sql = ' + SELECT u.id, u.email, u.status, up.display_name, up.first_name, up.last_name + FROM users u + LEFT JOIN user_profiles up ON up.user_id = u.id + WHERE ' . implode(' AND ', $conditions) . ' + ORDER BY + CASE + WHEN LOWER(COALESCE(up.display_name, "")) = :exactDisplayQuery THEN 0 + ELSE 1 + END, + COALESCE(up.display_name, ""), + u.id DESC + LIMIT ' . $limit; + $params[':exactDisplayQuery'] = mb_strtolower($query); + + $stmt = $this->pdo->prepare($sql); + $stmt->execute($params); + foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) ?: [] as $row) { + $rowsById[(int)($row['id'] ?? 0)] = $row; + } } - $conditions = []; - $params = []; - foreach ($tokens as $index => $token) { - $displayKey = ':display_' . $index; - $nameKey = ':name_' . $index; - $emailKey = ':email_' . $index; - $conditions[] = '(LOWER(COALESCE(up.display_name, "")) LIKE ' . $displayKey . ' OR LOWER(CONCAT_WS(" ", COALESCE(up.first_name, ""), COALESCE(up.last_name, ""))) LIKE ' . $nameKey . ' OR LOWER(COALESCE(u.email, "")) LIKE ' . $emailKey . ')'; - $needle = '%' . $token . '%'; - $params[$displayKey] = $needle; - $params[$nameKey] = $needle; - $params[$emailKey] = $needle; + if (str_contains($query, '@')) { + $emailRow = $this->emailStore()->findUserByEmail($query, 'id, email, status'); + if (is_array($emailRow)) { + $profileStmt = $this->pdo->prepare('SELECT display_name, first_name, last_name FROM user_profiles WHERE user_id = :uid LIMIT 1'); + $profileStmt->execute(['uid' => (int)$emailRow['id']]); + $profileRow = $profileStmt->fetch(\PDO::FETCH_ASSOC) ?: []; + $emailRow['display_name'] = (string)($profileRow['display_name'] ?? ''); + $emailRow['first_name'] = (string)($profileRow['first_name'] ?? ''); + $emailRow['last_name'] = (string)($profileRow['last_name'] ?? ''); + $rowsById[(int)$emailRow['id']] = $emailRow; + } } - $sql = ' - SELECT u.id, u.email, u.status, up.display_name, up.first_name, up.last_name - FROM users u - LEFT JOIN user_profiles up ON up.user_id = u.id - WHERE ' . implode(' AND ', $conditions) . ' - ORDER BY - CASE - 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[':exactDisplayQuery'] = mb_strtolower($query); - $params[':exactEmailQuery'] = mb_strtolower($query); + $rows = array_values($rowsById); + usort($rows, static function (array $left, array $right) use ($query): int { + $leftDisplay = mb_strtolower((string)($left['display_name'] ?? '')); + $rightDisplay = mb_strtolower((string)($right['display_name'] ?? '')); + $needle = mb_strtolower($query); + $leftRank = $leftDisplay === $needle ? 0 : 1; + $rightRank = $rightDisplay === $needle ? 0 : 1; + if ($leftRank !== $rightRank) { + return $leftRank <=> $rightRank; + } + return ((int)($right['id'] ?? 0)) <=> ((int)($left['id'] ?? 0)); + }); - $stmt = $this->pdo->prepare($sql); - $stmt->execute($params); - return $this->emailStore()->decryptRowEmails($stmt->fetchAll(\PDO::FETCH_ASSOC) ?: [], 'id'); + $rows = array_slice($rows, 0, $limit); + return $this->emailStore()->decryptRowEmails($rows, 'id'); } public function setRestriction(int $actingUserId, int $targetUserId, string $type, string $reason): void