1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\RateLimiter;
13
14use Symfony\Component\RateLimiter\Exception\RateLimitExceededException;
15
16/**
17 * @author Valentin Silvestre <vsilvestre.pro@gmail.com>
18 */
19class RateLimit
20{
21    private $availableTokens;
22    private $retryAfter;
23    private $accepted;
24    private $limit;
25
26    public function __construct(int $availableTokens, \DateTimeImmutable $retryAfter, bool $accepted, int $limit)
27    {
28        $this->availableTokens = $availableTokens;
29        $this->retryAfter = $retryAfter;
30        $this->accepted = $accepted;
31        $this->limit = $limit;
32    }
33
34    public function isAccepted(): bool
35    {
36        return $this->accepted;
37    }
38
39    /**
40     * @return $this
41     *
42     * @throws RateLimitExceededException if not accepted
43     */
44    public function ensureAccepted(): self
45    {
46        if (!$this->accepted) {
47            throw new RateLimitExceededException($this);
48        }
49
50        return $this;
51    }
52
53    public function getRetryAfter(): \DateTimeImmutable
54    {
55        return $this->retryAfter;
56    }
57
58    public function getRemainingTokens(): int
59    {
60        return $this->availableTokens;
61    }
62
63    public function getLimit(): int
64    {
65        return $this->limit;
66    }
67
68    public function wait(): void
69    {
70        $delta = $this->retryAfter->format('U.u') - microtime(true);
71        if ($delta <= 0) {
72            return;
73        }
74
75        usleep($delta * 1e6);
76    }
77}
78