avatar 2
All checks were successful
Deploy / deploy (push) Successful in 1m43s

This commit is contained in:
2026-07-27 01:50:38 +02:00
parent 08fffd24b6
commit 32985d5785
9 changed files with 216 additions and 79 deletions

View File

@@ -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 : '';
}
}