<?php/* * This file is part of the SymfonyCasts ResetPasswordBundle package. * Copyright (c) SymfonyCasts <https://symfonycasts.com/> * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */namespace SymfonyCasts\Bundle\ResetPassword\Model;/** * @author Jesse Rushlow <jr@rushlow.dev> * @author Ryan Weaver <ryan@symfonycasts.com> */final class ResetPasswordToken{ /** * @var string|null selector + non-hashed verifier token */ private $token; /** * @var \DateTimeInterface */ private $expiresAt; /** * @var int|null timestamp when the token was created */ private $generatedAt; /** * @var int expiresAt translator interval */ private $transInterval = 0; public function __construct(string $token, \DateTimeInterface $expiresAt, int $generatedAt = null) { $this->token = $token; $this->expiresAt = $expiresAt; $this->generatedAt = $generatedAt; if (null === $generatedAt) { $this->triggerDeprecation(); } } /** * Returns the full token the user should use. * * Internally, this consists of two parts - the selector and * the hashed token - but that's an implementation detail * of how the token will later be parsed. */ public function getToken(): string { if (null === $this->token) { throw new \RuntimeException('The token property is not set. Calling getToken() after calling clearToken() is not allowed.'); } return $this->token; } /** * Allow the token object to be safely persisted in a session. */ public function clearToken(): void { $this->token = null; } public function getExpiresAt(): \DateTimeInterface { return $this->expiresAt; } /** * Get the translation message for when a token expires. * * This is used in conjunction with getExpirationMessageData() method. * Example usage in a Twig template: * * <p>{{ components.expirationMessageKey|trans(components.expirationMessageData) }}</p> * * symfony/translation is required to translate into a non-English locale. * * @throws \LogicException */ public function getExpirationMessageKey(): string { $interval = $this->getExpiresAtIntervalInstance(); switch ($interval) { case $interval->y > 0: $this->transInterval = $interval->y; return '%count% year|%count% years'; case $interval->m > 0: $this->transInterval = $interval->m; return '%count% month|%count% months'; case $interval->d > 0: $this->transInterval = $interval->d; return '%count% day|%count% days'; case $interval->h > 0: $this->transInterval = $interval->h; return '%count% hour|%count% hours'; default: $this->transInterval = $interval->i; return '%count% minute|%count% minutes'; } } /** * @throws \LogicException */ public function getExpirationMessageData(): array { $this->getExpirationMessageKey(); return ['%count%' => $this->transInterval]; } /** * Get the interval that the token is valid for. * * @throws \LogicException * * @psalm-suppress PossiblyFalseArgument */ public function getExpiresAtIntervalInstance(): \DateInterval { if (null === $this->generatedAt) { throw new \LogicException(sprintf('%s initialized without setting the $generatedAt timestamp.', self::class)); } $createdAtTime = \DateTimeImmutable::createFromFormat('U', (string) $this->generatedAt); return $this->expiresAt->diff($createdAtTime); } private function triggerDeprecation(): void { trigger_deprecation( 'symfonycasts/reset-password-bundle', '1.2', 'Initializing the %s without setting the "$generatedAt" constructor argument is deprecated. The default "null" will be removed in the future.', self::class ); }}