Moved birthdate into separate table.
This commit is contained in:
parent
2c4d35e2dd
commit
c28e0a90dd
12 changed files with 225 additions and 94 deletions
40
database/2025_02_08_013647_create_user_birthdates_table.php
Normal file
40
database/2025_02_08_013647_create_user_birthdates_table.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
use Index\Db\DbConnection;
|
||||
use Index\Db\Migration\DbMigration;
|
||||
|
||||
final class CreateUserBirthdatesTable_20250208_013647 implements DbMigration {
|
||||
public function migrate(DbConnection $conn): void {
|
||||
$conn->execute(<<<SQL
|
||||
CREATE TABLE msz_users_birthdates (
|
||||
user_id INT(10) UNSIGNED NOT NULL,
|
||||
birth_year SMALLINT(6) NULL DEFAULT NULL,
|
||||
birth_month TINYINT(3) UNSIGNED NOT NULL,
|
||||
birth_day TINYINT(3) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (user_id),
|
||||
INDEX users_birthdates_index (birth_month, birth_day),
|
||||
CONSTRAINT users_birthdates_users_foreign
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES msz_users (user_id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT users_birthdates_ensure_month
|
||||
CHECK (birth_month BETWEEN 1 AND 12),
|
||||
CONSTRAINT users_birthdates_ensure_day
|
||||
CHECK (birth_day BETWEEN 1 AND 31)
|
||||
) ENGINE=InnoDB COLLATE='utf8mb4_bin';
|
||||
SQL);
|
||||
|
||||
$conn->execute(<<<SQL
|
||||
INSERT INTO msz_users_birthdates
|
||||
SELECT user_id, IF(YEAR(user_birthdate) <= 1004, NULL, YEAR(user_birthdate)), MONTH(user_birthdate), DAY(user_birthdate)
|
||||
FROM msz_users
|
||||
WHERE user_birthdate IS NOT NULL
|
||||
SQL);
|
||||
|
||||
$conn->execute(<<<SQL
|
||||
ALTER TABLE msz_users
|
||||
DROP COLUMN user_birthdate,
|
||||
DROP INDEX users_birthdate_index;
|
||||
SQL);
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ use InvalidArgumentException;
|
|||
use RuntimeException;
|
||||
use Index\ByteFormat;
|
||||
use Misuzu\Parsers\Parser;
|
||||
use Misuzu\Users\User;
|
||||
use Misuzu\Users\{User,UsersContext};
|
||||
use Misuzu\Users\Assets\UserAvatarAsset;
|
||||
use Misuzu\Users\Assets\UserBackgroundAsset;
|
||||
|
||||
|
@ -93,6 +93,7 @@ if($isEditing) {
|
|||
Template::set([
|
||||
'perms' => $perms,
|
||||
'background_attachments' => UserBackgroundAsset::getAttachmentStringOptions(),
|
||||
'birthdate_info' => $msz->usersCtx->birthdates->getUserBirthdate($userInfo),
|
||||
]);
|
||||
|
||||
if(!empty($_POST)) {
|
||||
|
@ -172,11 +173,14 @@ if($isEditing) {
|
|||
$birthYear = (int)($_POST['birthdate']['year'] ?? 0);
|
||||
$birthMonth = (int)($_POST['birthdate']['month'] ?? 0);
|
||||
$birthDay = (int)($_POST['birthdate']['day'] ?? 0);
|
||||
$birthValid = $msz->usersCtx->users->validateBirthdate($birthYear, $birthMonth, $birthDay);
|
||||
$birthValid = UsersContext::validateBirthdate($birthYear, $birthMonth, $birthDay);
|
||||
|
||||
if($birthValid === '')
|
||||
$msz->usersCtx->users->updateUser($userInfo, birthYear: $birthYear, birthMonth: $birthMonth, birthDay: $birthDay);
|
||||
else
|
||||
if($birthValid === '') {
|
||||
if($birthMonth === 0 && $birthDay === 0)
|
||||
$msz->usersCtx->birthdates->deleteUserBirthdate($userInfo);
|
||||
else
|
||||
$msz->usersCtx->birthdates->updateUserBirthdate($userInfo, $birthYear === 0 ? null : $birthYear, $birthMonth, $birthDay);
|
||||
} else
|
||||
$notices[] = $msz->usersCtx->users->validateBirthdateText($birthValid);
|
||||
}
|
||||
}
|
||||
|
@ -381,4 +385,5 @@ Template::render('profile.index', [
|
|||
'profile_avatar_info' => $avatarInfo,
|
||||
'profile_background_info' => $backgroundInfo,
|
||||
'profile_can_send_messages' => $viewerPermsGlobal->check(Perm::G_MESSAGES_SEND),
|
||||
'profile_age' => $msz->usersCtx->birthdates->getUserAge($userInfo),
|
||||
]);
|
||||
|
|
|
@ -143,7 +143,7 @@ if(isset($_POST['action']) && is_string($_POST['action'])) {
|
|||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'perms_calculated', ['user_id:s:n', 'forum_id:s:n', 'perms_category:s', 'perms_calculated:i']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'profile_fields_values', ['field_id:s', 'user_id:s', 'format_id:s', 'field_value:s']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'sessions', ['session_id:s', 'user_id:s', 'session_key:n', 'session_remote_addr_first:a', 'session_remote_addr_last:a:n', 'session_user_agent:s', 'session_country:s', 'session_expires:t', 'session_expires_bump:b', 'session_created:t', 'session_active:t:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users', ['user_id:s', 'user_name:s', 'user_password:n', 'user_email:s', 'user_remote_addr_first:a', 'user_remote_addr_last:a', 'user_super:b', 'user_country:s', 'user_colour:i:n', 'user_created:t', 'user_active:t:n', 'user_deleted:t:n', 'user_display_role_id:s:n', 'user_about_content:s:n', 'user_about_parser:i', 'user_signature_content:s:n', 'user_signature_parser:i', 'user_birthdate:s:n', 'user_background_settings:i:n', 'user_title:s:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users', ['user_id:s', 'user_name:s', 'user_password:n', 'user_email:s', 'user_remote_addr_first:a', 'user_remote_addr_last:a', 'user_super:b', 'user_country:s', 'user_colour:i:n', 'user_created:t', 'user_active:t:n', 'user_deleted:t:n', 'user_display_role_id:s:n', 'user_about_content:s:n', 'user_about_parser:i', 'user_signature_content:s:n', 'user_signature_parser:i', 'user_background_settings:i:n', 'user_title:s:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users_bans', ['ban_id:s', 'user_id:s', 'mod_id:n', 'ban_severity:i', 'ban_reason_public:s', 'ban_reason_private:s', 'ban_created:t', 'ban_expires:t:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users_password_resets', ['reset_id:s', 'user_id:s', 'reset_remote_addr:a', 'reset_requested:t', 'reset_code:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users_warnings', ['warn_id:s', 'user_id:s', 'mod_id:n', 'warn_body:s', 'warn_created:t']);
|
||||
|
|
|
@ -218,6 +218,7 @@ class HomeRoutes implements RouteHandler, UrlSource {
|
|||
$birthdays[] = [
|
||||
'info' => $birthdayInfo,
|
||||
'colour' => $this->usersCtx->getUserColour($birthdayInfo),
|
||||
'age' => $this->usersCtx->birthdates->getUserAge($birthdayInfo),
|
||||
];
|
||||
|
||||
$newestMember = [];
|
||||
|
|
31
src/Users/UserBirthdateInfo.php
Normal file
31
src/Users/UserBirthdateInfo.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
namespace Misuzu\Users;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use Index\Db\DbResult;
|
||||
|
||||
class UserBirthdateInfo {
|
||||
public function __construct(
|
||||
public private(set) string $userId,
|
||||
public private(set) ?int $year,
|
||||
public private(set) int $month,
|
||||
public private(set) int $day
|
||||
) {}
|
||||
|
||||
public static function fromResult(DbResult $result): UserBirthdateInfo {
|
||||
return new UserBirthdateInfo(
|
||||
userId: $result->getString(0),
|
||||
year: $result->getIntegerOrNull(1),
|
||||
month: $result->getInteger(2),
|
||||
day: $result->getInteger(3),
|
||||
);
|
||||
}
|
||||
|
||||
public string $birthdate {
|
||||
get => sprintf('%04d-%02d-%02d', $this->year ?? 0, $this->month, $this->day);
|
||||
}
|
||||
|
||||
public CarbonImmutable $bornAt {
|
||||
get => CarbonImmutable::createFromTimestampUTC('Y-m-d', $this->birthdate, 'UTC');
|
||||
}
|
||||
}
|
68
src/Users/UserBirthdatesData.php
Normal file
68
src/Users/UserBirthdatesData.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
namespace Misuzu\Users;
|
||||
|
||||
use DateTimeInterface;
|
||||
use RuntimeException;
|
||||
use Index\Db\{DbConnection,DbStatementCache};
|
||||
|
||||
class UserBirthdatesData {
|
||||
private DbStatementCache $cache;
|
||||
|
||||
public function __construct(DbConnection $dbConn) {
|
||||
$this->cache = new DbStatementCache($dbConn);
|
||||
}
|
||||
|
||||
public function getUserBirthdate(UserInfo|string $userInfo): ?UserBirthdateInfo {
|
||||
$stmt = $this->cache->get(<<<SQL
|
||||
SELECT user_id, birth_year, birth_month, birth_day
|
||||
FROM msz_users_birthdates
|
||||
WHERE user_id = ?
|
||||
SQL);
|
||||
$stmt->nextParameter($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
return $result->next() ? UserBirthdateInfo::fromResult($result) : null;
|
||||
}
|
||||
|
||||
public function deleteUserBirthdate(UserInfo|string $userInfo): void {
|
||||
$stmt = $this->cache->get(<<<SQL
|
||||
DELETE FROM msz_users_birthdates
|
||||
WHERE user_id = ?
|
||||
SQL);
|
||||
$stmt->nextParameter($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
public function updateUserBirthdate(UserInfo|string $userInfo, ?int $year, int $month, int $day): UserBirthdateInfo {
|
||||
$stmt = $this->cache->get(<<<SQL
|
||||
REPLACE INTO msz_users_birthdates (
|
||||
user_id, birth_year, birth_month, birth_day
|
||||
) VALUES (?, ?, ?, ?)
|
||||
SQL);
|
||||
$stmt->nextParameter($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
$stmt->nextParameter($year);
|
||||
$stmt->nextParameter($month);
|
||||
$stmt->nextParameter($day);
|
||||
$stmt->execute();
|
||||
|
||||
$birthdateInfo = $this->getUserBirthdate($userInfo);
|
||||
if($birthdateInfo === null)
|
||||
throw new RuntimeException('failed to set birthdate');
|
||||
|
||||
return $birthdateInfo;
|
||||
}
|
||||
|
||||
public function getUserAge(UserInfo|string $userInfo): ?int {
|
||||
$stmt = $this->cache->get(<<<SQL
|
||||
SELECT TIMESTAMPDIFF(YEAR, CONCAT_WS('-', birth_year, birth_month, birth_day), CURDATE())
|
||||
FROM msz_users_birthdates
|
||||
WHERE user_id = ?
|
||||
SQL);
|
||||
$stmt->nextParameter($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
return $result->next() ? $result->getIntegerOrNull(0) : null;
|
||||
}
|
||||
}
|
|
@ -25,7 +25,6 @@ class UserInfo {
|
|||
public private(set) int $aboutBodyParser,
|
||||
public private(set) ?string $signatureBody,
|
||||
public private(set) int $signatureBodyParser,
|
||||
public private(set) ?string $birthdateRaw,
|
||||
public private(set) ?int $backgroundSettings,
|
||||
public private(set) ?string $title,
|
||||
) {}
|
||||
|
@ -49,9 +48,8 @@ class UserInfo {
|
|||
aboutBodyParser: $result->getInteger(14),
|
||||
signatureBody: $result->getStringOrNull(15),
|
||||
signatureBodyParser: $result->getInteger(16),
|
||||
birthdateRaw: $result->getStringOrNull(17),
|
||||
backgroundSettings: $result->getIntegerOrNull(18),
|
||||
title: $result->getString(19),
|
||||
backgroundSettings: $result->getIntegerOrNull(17),
|
||||
title: $result->getString(18),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -114,21 +112,4 @@ class UserInfo {
|
|||
public bool $isSignatureBodyMarkdown {
|
||||
get => $this->signatureBodyParser === Parser::MARKDOWN;
|
||||
}
|
||||
|
||||
public bool $hasBirthdate {
|
||||
get => $this->birthdateRaw !== null;
|
||||
}
|
||||
|
||||
public ?CarbonImmutable $birthdate {
|
||||
get => $this->birthdateRaw === null ? null : CarbonImmutable::createFromFormat('Y-m-d', $this->birthdateRaw, 'UTC');
|
||||
}
|
||||
|
||||
public int $age {
|
||||
get {
|
||||
$birthdate = $this->birthdate;
|
||||
if($birthdate === null || (int)$birthdate->format('Y') < 1900)
|
||||
return -1;
|
||||
return (int)$birthdate->diff(CarbonImmutable::now())->format('%y');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace Misuzu\Users;
|
|||
|
||||
use Index\Colour\Colour;
|
||||
use Index\Db\DbConnection;
|
||||
use Misuzu\Tools;
|
||||
|
||||
class UsersContext {
|
||||
public private(set) UsersData $users;
|
||||
|
@ -11,6 +12,7 @@ class UsersContext {
|
|||
public private(set) WarningsData $warnings;
|
||||
public private(set) ModNotesData $modNotes;
|
||||
public private(set) UserTotpsData $totps;
|
||||
public private(set) UserBirthdatesData $birthdates;
|
||||
|
||||
/** @var array<string, UserInfo> */
|
||||
private array $userInfos = [];
|
||||
|
@ -31,6 +33,7 @@ class UsersContext {
|
|||
$this->warnings = new WarningsData($dbConn);
|
||||
$this->modNotes = new ModNotesData($dbConn);
|
||||
$this->totps = new UserTotpsData($dbConn);
|
||||
$this->birthdates = new UserBirthdatesData($dbConn);
|
||||
}
|
||||
|
||||
public function getUserInfo(string $value, int|string|null $select = null): UserInfo {
|
||||
|
@ -88,4 +91,19 @@ class UsersContext {
|
|||
): bool {
|
||||
return $this->tryGetActiveBan($userInfo, $minimumSeverity) !== null;
|
||||
}
|
||||
|
||||
public static function validateBirthdate(?int $year, int $month, int $day, int $yearRange = 100): string {
|
||||
$year ??= 0;
|
||||
|
||||
if($day !== 0 && $month !== 0) {
|
||||
$currentYear = (int)date('Y');
|
||||
if($year > 0 && ($year < $currentYear - $yearRange || $year > $currentYear))
|
||||
return 'year';
|
||||
|
||||
if(!Tools::isValidDate($year, $month, $day))
|
||||
return 'date';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,19 +57,26 @@ class UsersData {
|
|||
$hasDeleted = $deleted !== null;
|
||||
|
||||
$args = 0;
|
||||
$query = 'SELECT COUNT(*) FROM msz_users';
|
||||
$query = <<<SQL
|
||||
SELECT COUNT(u.*) FROM msz_users
|
||||
SQL;
|
||||
if($hasRoleInfo)
|
||||
$query .= <<<SQL
|
||||
LEFT JOIN msz_users_roles AS ur ON u.user_id = ur.user_id
|
||||
SQL;
|
||||
|
||||
if($hasRoleInfo) {
|
||||
++$args;
|
||||
$query .= ' WHERE user_id IN (SELECT user_id FROM msz_users_roles WHERE role_id = ?)';
|
||||
$query .= ' WHERE ur.role_id = ?';
|
||||
}
|
||||
if($hasAfter)
|
||||
$query .= sprintf(' %s user_id > ?', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
$query .= sprintf(' %s u.user_id > ?', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
if($hasLastActiveInMinutes)
|
||||
$query .= sprintf(' %s user_active > NOW() - INTERVAL ? MINUTE', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
$query .= sprintf(' %s u.user_active > NOW() - INTERVAL ? MINUTE', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
if($hasNewerThanDays)
|
||||
$query .= sprintf(' %s user_created > NOW() - INTERVAL ? DAY', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
$query .= sprintf(' %s u.user_created > NOW() - INTERVAL ? DAY', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
if($hasDeleted)
|
||||
$query .= sprintf(' %s user_deleted %s NULL', ++$args > 1 ? 'AND' : 'WHERE', $deleted ? 'IS NOT' : 'IS');
|
||||
$query .= sprintf(' %s u.user_deleted %s NULL', ++$args > 1 ? 'AND' : 'WHERE', $deleted ? 'IS NOT' : 'IS');
|
||||
|
||||
$stmt = $this->cache->get($query);
|
||||
if($hasRoleInfo)
|
||||
|
@ -163,34 +170,43 @@ class UsersData {
|
|||
|
||||
$args = 0;
|
||||
$query = <<<SQL
|
||||
SELECT user_id, user_name, user_password, user_email,
|
||||
INET6_NTOA(user_remote_addr_first), INET6_NTOA(user_remote_addr_last),
|
||||
user_super, user_country, user_colour,
|
||||
UNIX_TIMESTAMP(user_created),
|
||||
UNIX_TIMESTAMP(user_active),
|
||||
UNIX_TIMESTAMP(user_deleted),
|
||||
user_display_role_id, user_about_content,
|
||||
user_about_parser, user_signature_content,
|
||||
user_signature_parser, user_birthdate,
|
||||
user_background_settings, user_title
|
||||
FROM msz_users
|
||||
SELECT u.user_id, u.user_name, u.user_password, u.user_email,
|
||||
INET6_NTOA(u.user_remote_addr_first), INET6_NTOA(u.user_remote_addr_last),
|
||||
u.user_super, u.user_country, u.user_colour,
|
||||
UNIX_TIMESTAMP(u.user_created),
|
||||
UNIX_TIMESTAMP(u.user_active),
|
||||
UNIX_TIMESTAMP(u.user_deleted),
|
||||
u.user_display_role_id,
|
||||
u.user_about_content, u.user_about_parser,
|
||||
u.user_signature_content, u.user_signature_parser,
|
||||
u.user_background_settings, u.user_title
|
||||
FROM msz_users AS u
|
||||
SQL;
|
||||
if($hasRoleInfo)
|
||||
$query .= <<<SQL
|
||||
LEFT JOIN msz_users_roles AS ur ON u.user_id = ur.user_id
|
||||
SQL;
|
||||
if($hasBirthdate)
|
||||
$query .= <<<SQL
|
||||
LEFT JOIN msz_users_birthdates AS ub ON u.user_id = ub.user_id
|
||||
SQL;
|
||||
|
||||
if($hasRoleInfo) {
|
||||
++$args;
|
||||
$query .= ' WHERE user_id IN (SELECT user_id FROM msz_users_roles WHERE role_id = ?)';
|
||||
$query .= ' WHERE ur.role_id = ?';
|
||||
}
|
||||
if($hasAfter)
|
||||
$query .= sprintf(' %s user_id > ?', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
$query .= sprintf(' %s u.user_id > ?', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
if($hasLastActiveInMinutes)
|
||||
$query .= sprintf(' %s user_active > NOW() - INTERVAL ? MINUTE', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
$query .= sprintf(' %s u.user_active > NOW() - INTERVAL ? MINUTE', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
if($hasNewerThanDays)
|
||||
$query .= sprintf(' %s user_created > NOW() - INTERVAL ? DAY', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
$query .= sprintf(' %s u.user_created > NOW() - INTERVAL ? DAY', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
if($hasDeleted)
|
||||
$query .= sprintf(' %s user_deleted %s NULL', ++$args > 1 ? 'AND' : 'WHERE', $deleted ? 'IS NOT' : 'IS');
|
||||
$query .= sprintf(' %s u.user_deleted %s NULL', ++$args > 1 ? 'AND' : 'WHERE', $deleted ? 'IS NOT' : 'IS');
|
||||
if($hasBirthdate)
|
||||
$query .= sprintf(' %s user_birthdate LIKE ?', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
$query .= sprintf(' %s (ub.birth_month = ? AND ub.birth_day = ?)', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
if($hasSearchQuery)
|
||||
$query .= sprintf(' %s user_name LIKE CONCAT("%%", ?, "%%")', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
$query .= sprintf(' %s u.user_name LIKE CONCAT("%%", ?, "%%")', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
if($hasOrderBy) {
|
||||
$query .= sprintf(' ORDER BY %s', $orderBy[0]);
|
||||
if($orderBy[1] !== null)
|
||||
|
@ -210,8 +226,10 @@ class UsersData {
|
|||
$stmt->nextParameter($lastActiveInMinutes);
|
||||
if($hasNewerThanDays)
|
||||
$stmt->nextParameter($newerThanDays);
|
||||
if($hasBirthdate)
|
||||
$stmt->nextParameter($birthdate->format('%-m-d'));
|
||||
if($hasBirthdate) {
|
||||
$stmt->nextParameter($birthdate->format('m'));
|
||||
$stmt->nextParameter($birthdate->format('d'));
|
||||
}
|
||||
if($hasSearchQuery)
|
||||
$stmt->nextParameter($searchQuery);
|
||||
if($hasPagination)
|
||||
|
@ -267,9 +285,9 @@ class UsersData {
|
|||
UNIX_TIMESTAMP(user_created),
|
||||
UNIX_TIMESTAMP(user_active),
|
||||
UNIX_TIMESTAMP(user_deleted),
|
||||
user_display_role_id, user_about_content,
|
||||
user_about_parser, user_signature_content,
|
||||
user_signature_parser, user_birthdate,
|
||||
user_display_role_id,
|
||||
user_about_content, user_about_parser,
|
||||
user_signature_content, user_signature_parser,
|
||||
user_background_settings, user_title
|
||||
FROM msz_users
|
||||
SQL;
|
||||
|
@ -343,9 +361,6 @@ class UsersData {
|
|||
?int $aboutBodyParser = null,
|
||||
?string $signatureBody = null,
|
||||
?int $signatureBodyParser = null,
|
||||
?int $birthYear = null,
|
||||
?int $birthMonth = null,
|
||||
?int $birthDay = null,
|
||||
?int $backgroundSettings = null,
|
||||
?string $title = null
|
||||
): void {
|
||||
|
@ -413,18 +428,6 @@ class UsersData {
|
|||
$values[] = $signatureBodyParser;
|
||||
}
|
||||
|
||||
if($birthMonth !== null && $birthDay !== null) {
|
||||
if(self::validateBirthdate($birthYear, $birthMonth, $birthDay) !== '')
|
||||
throw new InvalidArgumentException('$birthYear, $birthMonth and $birthDay contain invalid data!');
|
||||
|
||||
// lowest leap year MariaDB accepts, used a 'no year' value
|
||||
if($birthYear < 1004)
|
||||
$birthYear = 1004;
|
||||
|
||||
$fields[] = 'user_birthdate = ?';
|
||||
$values[] = $birthMonth < 1 || $birthDay < 1 ? null : sprintf('%04d-%02d-%02d', $birthYear, $birthMonth, $birthDay);
|
||||
}
|
||||
|
||||
if($backgroundSettings !== null) {
|
||||
$fields[] = 'user_background_settings = ?';
|
||||
$values[] = $backgroundSettings;
|
||||
|
@ -697,21 +700,6 @@ class UsersData {
|
|||
};
|
||||
}
|
||||
|
||||
public static function validateBirthdate(?int $year, int $month, int $day, int $yearRange = 100): string {
|
||||
$year ??= 0;
|
||||
|
||||
if($day !== 0 && $month !== 0) {
|
||||
$currentYear = (int)date('Y');
|
||||
if($year > 0 && ($year < $currentYear - $yearRange || $year > $currentYear))
|
||||
return 'year';
|
||||
|
||||
if(!Tools::isValidDate($year, $month, $day))
|
||||
return 'date';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function validateBirthdateText(string $error): string {
|
||||
return match($error) {
|
||||
'year' => 'The year in your birthdate is too ridiculous.',
|
||||
|
|
|
@ -77,14 +77,14 @@
|
|||
{{ container_title('<i class="fas fa-birthday-cake fa-fw"></i> Happy Birthday!') }}
|
||||
|
||||
{% for birthday in birthdays %}
|
||||
{% set age = birthday.info.age %}
|
||||
{% set age = birthday.age %}
|
||||
<a class="landing__latest" style="--user-colour: {{ birthday.colour }}" href="{{ url('user-profile', {'user': birthday.info.id}) }}">
|
||||
<div class="landing__latest__avatar">{{ avatar(birthday.info.id, 50, birthday.info.name) }}</div>
|
||||
<div class="landing__latest__content">
|
||||
<div class="landing__latest__username">
|
||||
{{ birthday.info.name }}
|
||||
</div>
|
||||
{% if age > 0 %}
|
||||
{% if age is not null %}
|
||||
<div class="landing__latest__joined">
|
||||
Turned {{ age }} today!
|
||||
</div>
|
||||
|
|
|
@ -42,13 +42,12 @@
|
|||
{% endif %}
|
||||
|
||||
{% set hasCountryCode = profile_user.countryCode != 'XX' %}
|
||||
{% set age = profile_user.age %}
|
||||
{% set hasAge = age > 0 %}
|
||||
{% set hasAge = profile_age is not null %}
|
||||
{% if hasCountryCode or hasAge %}
|
||||
<div class="profile__header__country">
|
||||
{% if hasCountryCode %}<div class="flag flag--{{ profile_user.countryCode|lower }}"></div>{% endif %}
|
||||
<div class="profile__header__country__name">
|
||||
{% if hasCountryCode %}{{ profile_user.countryCode|country_name }}{% endif %}{% if hasAge %}{% if hasCountryCode %}, {% endif %}{{ age }} year{{ age != 's' ? 's' : '' }} old{% endif %}
|
||||
{% if hasCountryCode %}{{ profile_user.countryCode|country_name }}{% endif %}{% if hasAge %}{% if hasCountryCode %}, {% endif %}{{ profile_age }} year{{ profile_age != 1 ? 's' : '' }} old{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
@ -213,14 +213,14 @@
|
|||
<div class="profile__birthdate__title">
|
||||
Day
|
||||
</div>
|
||||
{{ input_select('birthdate[day]', ['-']|merge(range(1, 31)), profile_user.hasBirthdate ? profile_user.birthdate.day : 0, '', '', true, 'profile__birthdate__select profile__birthdate__select--day') }}
|
||||
{{ input_select('birthdate[day]', ['-']|merge(range(1, 31)), birthdate_info.day|default(0), '', '', true, 'profile__birthdate__select profile__birthdate__select--day') }}
|
||||
</label>
|
||||
|
||||
<label class="profile__birthdate__label">
|
||||
<div class="profile__birthdate__title">
|
||||
Month
|
||||
</div>
|
||||
{{ input_select('birthdate[month]', ['-']|merge(range(1, 12)), profile_user.hasBirthdate ? profile_user.birthdate.month : 0, '', '', true, 'profile__birthdate__select profile__birthdate__select--month') }}
|
||||
{{ input_select('birthdate[month]', ['-']|merge(range(1, 12)), birthdate_info.month|default(0), '', '', true, 'profile__birthdate__select profile__birthdate__select--month') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
@ -229,7 +229,7 @@
|
|||
<div class="profile__birthdate__title">
|
||||
Year (may be left empty)
|
||||
</div>
|
||||
{{ input_select('birthdate[year]', ['-']|merge(range(null|date('Y'), null|date('Y') - 100)), profile_user.birthdate.year|default(0), '', '', true, 'profile__birthdate__select profile__birthdate__select--year') }}
|
||||
{{ input_select('birthdate[year]', ['-']|merge(range(null|date('Y'), null|date('Y') - 100)), birthdate_info.year|default(0), '', '', true, 'profile__birthdate__select profile__birthdate__select--year') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Reference in a new issue