ytkns/src/UserInvite.php
2020-06-10 16:03:13 +00:00

123 lines
3.7 KiB
PHP

<?php
namespace YTKNS;
use Exception;
class UserInviteNotFoundException extends Exception {}
class UserInviteCreationFailedException extends Exception {}
final class UserInvite {
private const TOKEN_LENGTH = 16;
public function getToken(): string {
return $this->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;
}
}
}