This commit is contained in:
@@ -341,22 +341,18 @@ final class AccountPages
|
||||
'contact_phone' => '',
|
||||
'location_tracking_preference' => 'prompt',
|
||||
'avatar_preset' => 'papa-kind-treff',
|
||||
'avatar_skin_tone' => 'warm',
|
||||
'avatar_hair_style' => 'short',
|
||||
'avatar_hair_color' => 'brown',
|
||||
'avatar_eye_color' => 'brown',
|
||||
'avatar_beard_style' => 'none',
|
||||
'avatar_glasses_style' => 'none',
|
||||
'avatar_head_shape' => 'round',
|
||||
'avatar_hat_style' => 'none',
|
||||
'avatar_hat_color' => 'navy',
|
||||
'avatar_outfit_style' => 'tee',
|
||||
'avatar_outfit_color' => 'slate',
|
||||
'avatar_lorelei_eyes_variant' => '',
|
||||
'avatar_lorelei_eyebrows_variant' => '',
|
||||
'avatar_lorelei_mouth_variant' => '',
|
||||
'avatar_lorelei_glasses_variant' => '',
|
||||
'avatar_lorelei_hair_variant' => '',
|
||||
'avatar_lorelei_beard_variant' => '',
|
||||
'avatar_lorelei_earrings_variant' => '',
|
||||
];
|
||||
if ($profileSettings) {
|
||||
$profileSettings->ensureSchema();
|
||||
}
|
||||
$stmt = $pdo?->prepare('SELECT u.email, u.status, p.display_name, p.first_name, p.last_name, p.zip, p.city, p.profession, p.languages, p.about, p.contact_phone, p.location_tracking_preference, p.avatar_preset, p.avatar_skin_tone, p.avatar_hair_style, p.avatar_hair_color, p.avatar_eye_color, p.avatar_beard_style, p.avatar_glasses_style, p.avatar_head_shape, p.avatar_hat_style, p.avatar_hat_color, p.avatar_outfit_style, p.avatar_outfit_color FROM users u LEFT JOIN user_profiles p ON p.user_id = u.id WHERE u.id = :id LIMIT 1');
|
||||
$stmt = $pdo?->prepare('SELECT u.email, u.status, p.display_name, p.first_name, p.last_name, p.zip, p.city, p.profession, p.languages, p.about, p.contact_phone, p.location_tracking_preference, p.avatar_preset, p.avatar_lorelei_eyes_variant, p.avatar_lorelei_eyebrows_variant, p.avatar_lorelei_mouth_variant, p.avatar_lorelei_glasses_variant, p.avatar_lorelei_hair_variant, p.avatar_lorelei_beard_variant, p.avatar_lorelei_earrings_variant FROM users u LEFT JOIN user_profiles p ON p.user_id = u.id WHERE u.id = :id LIMIT 1');
|
||||
$stmt?->execute(['id' => $userId]);
|
||||
$row = $stmt?->fetch(\PDO::FETCH_ASSOC);
|
||||
if ($row) {
|
||||
@@ -422,6 +418,7 @@ final class AccountPages
|
||||
if (!in_array($section, $allowedSections, true)) {
|
||||
$section = 'profile';
|
||||
}
|
||||
$avatarOptions = Lorelei::options();
|
||||
$avatarPresetOptions = Lorelei::seedChoices((string)$profile['avatar_preset']);
|
||||
|
||||
return compact(
|
||||
@@ -439,6 +436,7 @@ final class AccountPages
|
||||
'communityApplication',
|
||||
'communityCanApply',
|
||||
'communityRestrictions',
|
||||
'avatarOptions',
|
||||
'avatarPresetOptions',
|
||||
'section',
|
||||
'allowedSections'
|
||||
|
||||
@@ -9,23 +9,30 @@ final class Lorelei
|
||||
{
|
||||
return [
|
||||
'avatar_preset' => 'papa-kind-treff',
|
||||
'avatar_skin_tone' => 'warm',
|
||||
'avatar_hair_style' => 'short',
|
||||
'avatar_hair_color' => 'brown',
|
||||
'avatar_eye_color' => 'brown',
|
||||
'avatar_beard_style' => 'none',
|
||||
'avatar_glasses_style' => 'none',
|
||||
'avatar_head_shape' => 'round',
|
||||
'avatar_hat_style' => 'none',
|
||||
'avatar_hat_color' => 'navy',
|
||||
'avatar_outfit_style' => 'tee',
|
||||
'avatar_outfit_color' => 'slate',
|
||||
'avatar_lorelei_eyes_variant' => '',
|
||||
'avatar_lorelei_eyebrows_variant' => '',
|
||||
'avatar_lorelei_mouth_variant' => '',
|
||||
'avatar_lorelei_glasses_variant' => '',
|
||||
'avatar_lorelei_hair_variant' => '',
|
||||
'avatar_lorelei_beard_variant' => '',
|
||||
'avatar_lorelei_earrings_variant' => '',
|
||||
];
|
||||
}
|
||||
|
||||
public static function options(): array
|
||||
{
|
||||
return [];
|
||||
$variants24 = self::variantOptions(24);
|
||||
$optional24 = ['' => 'Automatisch'] + $variants24;
|
||||
|
||||
return [
|
||||
'avatar_lorelei_eyes_variant' => $variants24,
|
||||
'avatar_lorelei_eyebrows_variant' => $variants24,
|
||||
'avatar_lorelei_mouth_variant' => $variants24,
|
||||
'avatar_lorelei_glasses_variant' => $optional24,
|
||||
'avatar_lorelei_hair_variant' => $optional24,
|
||||
'avatar_lorelei_beard_variant' => $optional24,
|
||||
'avatar_lorelei_earrings_variant' => $optional24,
|
||||
];
|
||||
}
|
||||
|
||||
public static function selectColumns(string $alias = 'p'): string
|
||||
@@ -44,9 +51,17 @@ final class Lorelei
|
||||
|
||||
foreach ($defaults as $key => $defaultValue) {
|
||||
$value = (string)($input[$key] ?? $defaultValue);
|
||||
$normalized[$key] = $key === 'avatar_preset'
|
||||
? self::normalizeSeed($value)
|
||||
: $value;
|
||||
if ($key === 'avatar_preset') {
|
||||
$normalized[$key] = self::normalizeSeed($value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_starts_with($key, 'avatar_lorelei_')) {
|
||||
$normalized[$key] = self::normalizeVariant($value);
|
||||
continue;
|
||||
}
|
||||
|
||||
$normalized[$key] = $value;
|
||||
}
|
||||
|
||||
return $normalized;
|
||||
@@ -119,10 +134,38 @@ final class Lorelei
|
||||
return '/api/avatar?seed=' . rawurlencode(self::normalizeSeed($seed));
|
||||
}
|
||||
|
||||
public static function apiQuery(array $row): array
|
||||
{
|
||||
$avatar = self::normalize($row);
|
||||
$query = ['seed' => $avatar['avatar_preset']];
|
||||
$map = [
|
||||
'avatar_lorelei_eyes_variant' => 'eyesVariant',
|
||||
'avatar_lorelei_eyebrows_variant' => 'eyebrowsVariant',
|
||||
'avatar_lorelei_mouth_variant' => 'mouthVariant',
|
||||
'avatar_lorelei_glasses_variant' => 'glassesVariant',
|
||||
'avatar_lorelei_hair_variant' => 'hairVariant',
|
||||
'avatar_lorelei_beard_variant' => 'beardVariant',
|
||||
'avatar_lorelei_earrings_variant' => 'earringsVariant',
|
||||
];
|
||||
|
||||
foreach ($map as $key => $param) {
|
||||
if ($avatar[$key] !== '') {
|
||||
$query[$param] = $avatar[$key];
|
||||
}
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public static function buildProxyUrl(array $row): string
|
||||
{
|
||||
return '/api/avatar?' . http_build_query(self::apiQuery($row));
|
||||
}
|
||||
|
||||
public static function render(array $row, string $name = 'Mitglied', string $size = 'md'): string
|
||||
{
|
||||
$avatar = self::normalize($row);
|
||||
$src = self::dicebearUrl($avatar['avatar_preset']);
|
||||
$src = self::buildProxyUrl($avatar);
|
||||
|
||||
return sprintf(
|
||||
'<span class="%s" role="img" aria-label="%s"><img class="pkt-avatar__img" src="%s" alt=""></span>',
|
||||
@@ -153,4 +196,25 @@ final class Lorelei
|
||||
htmlspecialchars($initials, ENT_QUOTES)
|
||||
);
|
||||
}
|
||||
|
||||
private static function variantOptions(int $count): array
|
||||
{
|
||||
$options = [];
|
||||
for ($index = 1; $index <= $count; $index++) {
|
||||
$key = sprintf('variant%02d', $index);
|
||||
$options[$key] = 'Variante ' . $index;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
public static function normalizeVariant(string $value): string
|
||||
{
|
||||
$value = strtolower(trim($value));
|
||||
if ($value === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return preg_match('/^variant\d{2}$/', $value) === 1 ? $value : '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ final class Community
|
||||
|
||||
$where = $conditions ? ('AND ' . implode(' AND ', $conditions)) : '';
|
||||
|
||||
$avatarSelect = $this->hasColumn('user_profiles', 'avatar_outfit_color')
|
||||
$avatarSelect = $this->hasColumn('user_profiles', 'avatar_preset')
|
||||
? ', ' . Lorelei::selectColumns('p')
|
||||
: '';
|
||||
$sql = "SELECT ft.id, ft.title, ft.body, ft.created_at, ft.updated_at,
|
||||
@@ -208,7 +208,7 @@ final class Community
|
||||
public function getThread(int $id): ?array
|
||||
{
|
||||
$select = 'ft.*, p.display_name';
|
||||
if ($this->hasColumn('user_profiles', 'avatar_outfit_color')) {
|
||||
if ($this->hasColumn('user_profiles', 'avatar_preset')) {
|
||||
$select .= ', ' . Lorelei::selectColumns('p');
|
||||
}
|
||||
$join = '';
|
||||
@@ -228,7 +228,7 @@ final class Community
|
||||
public function listPosts(int $threadId): array
|
||||
{
|
||||
$select = 'fp.*, p.display_name';
|
||||
if ($this->hasColumn('user_profiles', 'avatar_outfit_color')) {
|
||||
if ($this->hasColumn('user_profiles', 'avatar_preset')) {
|
||||
$select .= ', ' . Lorelei::selectColumns('p');
|
||||
}
|
||||
if ($this->hasColumn('forum_posts', 'highlighted_at')) {
|
||||
|
||||
@@ -32,17 +32,13 @@ final class ProfileSettings
|
||||
|
||||
$avatarColumns = [
|
||||
'avatar_preset' => "ALTER TABLE user_profiles ADD COLUMN avatar_preset VARCHAR(64) NOT NULL DEFAULT 'papa-kind-treff' AFTER location_tracking_preference",
|
||||
'avatar_skin_tone' => "ALTER TABLE user_profiles ADD COLUMN avatar_skin_tone VARCHAR(24) NOT NULL DEFAULT 'warm' AFTER location_tracking_preference",
|
||||
'avatar_hair_style' => "ALTER TABLE user_profiles ADD COLUMN avatar_hair_style VARCHAR(24) NOT NULL DEFAULT 'short' AFTER avatar_skin_tone",
|
||||
'avatar_hair_color' => "ALTER TABLE user_profiles ADD COLUMN avatar_hair_color VARCHAR(24) NOT NULL DEFAULT 'brown' AFTER avatar_hair_style",
|
||||
'avatar_eye_color' => "ALTER TABLE user_profiles ADD COLUMN avatar_eye_color VARCHAR(24) NOT NULL DEFAULT 'brown' AFTER avatar_hair_color",
|
||||
'avatar_beard_style' => "ALTER TABLE user_profiles ADD COLUMN avatar_beard_style VARCHAR(24) NOT NULL DEFAULT 'none' AFTER avatar_eye_color",
|
||||
'avatar_glasses_style' => "ALTER TABLE user_profiles ADD COLUMN avatar_glasses_style VARCHAR(24) NOT NULL DEFAULT 'none' AFTER avatar_beard_style",
|
||||
'avatar_head_shape' => "ALTER TABLE user_profiles ADD COLUMN avatar_head_shape VARCHAR(24) NOT NULL DEFAULT 'round' AFTER avatar_glasses_style",
|
||||
'avatar_hat_style' => "ALTER TABLE user_profiles ADD COLUMN avatar_hat_style VARCHAR(24) NOT NULL DEFAULT 'none' AFTER avatar_head_shape",
|
||||
'avatar_hat_color' => "ALTER TABLE user_profiles ADD COLUMN avatar_hat_color VARCHAR(24) NOT NULL DEFAULT 'navy' AFTER avatar_hat_style",
|
||||
'avatar_outfit_style' => "ALTER TABLE user_profiles ADD COLUMN avatar_outfit_style VARCHAR(24) NOT NULL DEFAULT 'tee' AFTER avatar_hat_color",
|
||||
'avatar_outfit_color' => "ALTER TABLE user_profiles ADD COLUMN avatar_outfit_color VARCHAR(24) NOT NULL DEFAULT 'slate' AFTER avatar_hat_color",
|
||||
'avatar_lorelei_eyes_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_eyes_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_preset",
|
||||
'avatar_lorelei_eyebrows_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_eyebrows_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_eyes_variant",
|
||||
'avatar_lorelei_mouth_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_mouth_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_eyebrows_variant",
|
||||
'avatar_lorelei_glasses_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_glasses_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_mouth_variant",
|
||||
'avatar_lorelei_hair_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_hair_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_glasses_variant",
|
||||
'avatar_lorelei_beard_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_beard_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_hair_variant",
|
||||
'avatar_lorelei_earrings_variant' => "ALTER TABLE user_profiles ADD COLUMN avatar_lorelei_earrings_variant VARCHAR(24) NOT NULL DEFAULT '' AFTER avatar_lorelei_beard_variant",
|
||||
];
|
||||
foreach ($avatarColumns as $column => $sql) {
|
||||
if (!$this->hasColumn('user_profiles', $column)) {
|
||||
@@ -93,33 +89,25 @@ final class ProfileSettings
|
||||
$stmt = $this->pdo->prepare(
|
||||
'UPDATE user_profiles
|
||||
SET avatar_preset = :preset,
|
||||
avatar_skin_tone = :skin,
|
||||
avatar_hair_style = :hairStyle,
|
||||
avatar_hair_color = :hairColor,
|
||||
avatar_eye_color = :eyeColor,
|
||||
avatar_beard_style = :beardStyle,
|
||||
avatar_glasses_style = :glassesStyle,
|
||||
avatar_head_shape = :headShape,
|
||||
avatar_hat_style = :hatStyle,
|
||||
avatar_hat_color = :hatColor,
|
||||
avatar_outfit_style = :outfitStyle,
|
||||
avatar_outfit_color = :outfitColor,
|
||||
avatar_lorelei_eyes_variant = :eyesVariant,
|
||||
avatar_lorelei_eyebrows_variant = :eyebrowsVariant,
|
||||
avatar_lorelei_mouth_variant = :mouthVariant,
|
||||
avatar_lorelei_glasses_variant = :glassesVariant,
|
||||
avatar_lorelei_hair_variant = :hairVariant,
|
||||
avatar_lorelei_beard_variant = :beardVariant,
|
||||
avatar_lorelei_earrings_variant = :earringsVariant,
|
||||
updated_at = NOW()
|
||||
WHERE user_id = :id'
|
||||
);
|
||||
$stmt->execute([
|
||||
'preset' => $avatar['avatar_preset'],
|
||||
'skin' => $avatar['avatar_skin_tone'],
|
||||
'hairStyle' => $avatar['avatar_hair_style'],
|
||||
'hairColor' => $avatar['avatar_hair_color'],
|
||||
'eyeColor' => $avatar['avatar_eye_color'],
|
||||
'beardStyle' => $avatar['avatar_beard_style'],
|
||||
'glassesStyle' => $avatar['avatar_glasses_style'],
|
||||
'headShape' => $avatar['avatar_head_shape'],
|
||||
'hatStyle' => $avatar['avatar_hat_style'],
|
||||
'hatColor' => $avatar['avatar_hat_color'],
|
||||
'outfitStyle' => $avatar['avatar_outfit_style'],
|
||||
'outfitColor' => $avatar['avatar_outfit_color'],
|
||||
'eyesVariant' => $avatar['avatar_lorelei_eyes_variant'],
|
||||
'eyebrowsVariant' => $avatar['avatar_lorelei_eyebrows_variant'],
|
||||
'mouthVariant' => $avatar['avatar_lorelei_mouth_variant'],
|
||||
'glassesVariant' => $avatar['avatar_lorelei_glasses_variant'],
|
||||
'hairVariant' => $avatar['avatar_lorelei_hair_variant'],
|
||||
'beardVariant' => $avatar['avatar_lorelei_beard_variant'],
|
||||
'earringsVariant' => $avatar['avatar_lorelei_earrings_variant'],
|
||||
'id' => $userId,
|
||||
]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user