user_id ?? 0; } private function setId(int $userId): void { $this->user_id = $userId; } public function getUsername(): string { return $this->username ?? ''; } public static function byId(int $userId): self { $getUser = DB::prepare(' SELECT `user_id`, `username`, `email`, `password`, `user_created` FROM `ytkns_users` WHERE `user_id` = :user '); $getUser->bindValue('user', $userId); $getUser->execute(); $user = $getUser->fetchObject(self::class); if($user === false) throw new UserNotFoundException; return $user; } public static function forLogin(string $usernameOrEmail): self { $getUser = DB::prepare(' SELECT `user_id`, `username`, `email`, `password`, `user_created` FROM `ytkns_users` WHERE LOWER(`username`) = LOWER(:username) OR LOWER(`email`) = LOWER(:email) '); $getUser->bindValue('username', $usernameOrEmail); $getUser->bindValue('email', $usernameOrEmail); $getUser->execute(); $user = $getUser->fetchObject(self::class); if($user === false) throw new UserNotFoundException; return $user; } public static function forProfile(string $username): self { $getUser = DB::prepare(' SELECT `user_id`, `username`, `email`, `password`, `user_created` FROM `ytkns_users` WHERE LOWER(`username`) = LOWER(:username) '); $getUser->bindValue('username', $username); $getUser->execute(); $user = $getUser->fetchObject(self::class); if($user === false) throw new UserNotFoundException; return $user; } public static function validatePassword(string $password): bool { $chars = []; $length = mb_strlen($password); for($i = 0; $i < $length; $i++) { $current = mb_substr($password, $i, 1); if(!in_array($current, $chars, true)) $chars[] = $current; } return count($chars) >= 6; } public static function hashPassword(string $password): string { return password_hash($password, PASSWORD_ARGON2ID); } public static function create(string $userName, string $password, string $email): self { if(!preg_match('#^([a-zA-Z0-9-_]{1,20})$#', $userName)) throw new UserCreationInvalidNameException; if(!filter_var($email, FILTER_VALIDATE_EMAIL)) throw new UserCreationInvalidMailException; if(!self::validatePassword($password)) throw new UserCreationInvalidPasswordException; $password = self::hashPassword($password); $createUser = DB::prepare(' INSERT INTO `ytkns_users` ( `username`, `email`, `password` ) VALUES ( :username, :email, :password ) '); $createUser->bindValue('username', $userName); $createUser->bindValue('email', $email); $createUser->bindValue('password', $password); $userId = $createUser->execute() ? (int)DB::lastInsertId() : 0; try { return self::byId($userId); } catch(UserNotFoundException $ex) { throw new UserCreationFailedException; } } }