invite_token; } public function getCreatorId(): int { return $this->created_by ?? 0; } public function getCreator(): User { return User::byId($this->getCreatedById()); } public function getUserId(): ?int { return $this->used_by ?? null; } public function getUser(): ?User { $userId = $this->getUserId(); if($userId === null) return null; try { return User::byId($this->getUserId()); } catch(UserNotFoundException $ex) { return null; } } public function getCreated(): int { return $this->invite_created ?? 0; } public function getUsed(): ?int { return $this->invite_used ?? null; } public function isUsed(): bool { return !empty($this->used_by) || !empty($this->invite_used); } public function markUsed(User $user): void { $markUsed = DB::prepare(' UPDATE `ytkns_users_invites` SET `used_by` = :user WHERE `invite_token` = UNHEX(:token) '); $markUsed->bindValue('user', $user->getId()); $markUsed->bindValue('token', $this->getToken()); $markUsed->execute(); } public static function fromCreator(User $creator): array { $getInvites = DB::prepare(' SELECT `created_by`, `used_by`, LOWER(HEX(`invite_token`)) AS `invite_token`, UNIX_TIMESTAMP(`invite_created`) AS `invite_created`, UNIX_TIMESTAMP(`invite_used`) AS `invite_used` FROM `ytkns_users_invites` WHERE `created_by` = :creator '); $getInvites->bindValue('creator', $creator->getId()); $getInvites->execute(); $invites = []; while($invite = $getInvites->fetchObject(self::class)) $invites[] = $invite; return $invites; } public static function byToken(string $token, bool $isHex = true): self { $getInvite = DB::prepare(sprintf(' SELECT `created_by`, `used_by`, LOWER(HEX(`invite_token`)) AS `invite_token`, UNIX_TIMESTAMP(`invite_created`) AS `invite_created`, UNIX_TIMESTAMP(`invite_used`) AS `invite_used` FROM `ytkns_users_invites` WHERE `invite_token` = %s(:token) ', $isHex ? 'UNHEX' : '')); $getInvite->bindValue('token', $token); $invite = $getInvite->execute() ? $getInvite->fetchObject(self::class) : false; if(!$invite) throw new UserInviteNotFoundException; return $invite; } public static function generateToken(): string { return bin2hex(random_bytes(self::TOKEN_LENGTH)); } public static function create(User $creator): self { $inviteToken = self::generateToken(); $insertInvite = DB::prepare(' INSERT INTO `ytkns_users_invites` ( `invite_token`, `created_by` ) VALUES ( UNHEX(:token), :creator ) '); $insertInvite->bindValue('token', $inviteToken); $insertInvite->bindValue('creator', $creator->getId()); $insertInvite->execute(); try { return self::byToken($inviteToken); } catch(UserInviteNotFoundException $ex) { throw new UserInviteCreationFailedException; } } }