Test Failed
Pull Request — master (#43)
by
unknown
02:22
created

ApcuStorage::__construct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 2
c 2
b 0
f 1
dl 0
loc 10
rs 10
cc 3
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\RateLimiter\Storage;
6
7
use InvalidArgumentException;
8
use Yiisoft\Yii\RateLimiter\Exception\CannotUseException;
9
10
final class ApcuStorage implements StorageInterface
11
{
12
    private const DEFAULT_FIX_PRECISION_RATE = 1000;
13
14
    /**
15
     * @param int $fixPrecisionRate 
16
     * floating point is not supported by apcu_cas of ACPu, so use it to improve precision.
17
     */
18
    public function __construct(
19
        private int $fixPrecisionRate = self::DEFAULT_FIX_PRECISION_RATE
20
    ) {
21
        /**
22
         * To use this implementation class, the [APCu PHP extension](http://www.php.net/apcu) must be loaded,
23
         * And you should add "apc.enabled = 1" to your php.ini.
24
         * In order to enable APCu for CLI you should add "apc.enable_cli = 1" to your php.ini.
25
         */
26
        if (!extension_loaded('apcu') || !ini_get('apc.enabled')) {
27
            throw new CannotUseException('APCu extension is not loaded or not enabled.');
28
        }
29
    }
30
31
    public function saveIfNotExists(string $key, mixed $value, int $ttl): bool
32
    {
33
        if ((!is_int($value)) && !is_float($value)) {
34
            throw new InvalidArgumentException('The value is not supported by ApcuStorage,it must be int or float');
35
        }
36
37
        $value = (int) ($value * $this->fixPrecisionRate);
38
39
        return apcu_add($key, $value, $ttl);
0 ignored issues
show
Bug Best Practice introduced by
The expression return apcu_add($key, $value, $ttl) could return the type array which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
40
    }
41
42
    public function saveCompareAndSwap(string $key, mixed $oldValue, mixed $newValue, int $ttl): bool
43
    {
44
        if ((!is_int($oldValue)) && !is_float($oldValue)) {
45
            throw new InvalidArgumentException('The oldValue is not supported by ApcuStorage,it must be int or float');
46
        }
47
48
        if ((!is_int($newValue)) && !is_float($newValue)) {
49
            throw new InvalidArgumentException('The newValue is not supported by ApcuStorage,it must be int or float');
50
        }
51
52
        $oldValue = (int) ($oldValue * $this->fixPrecisionRate);
53
        $newValue = (int) ($newValue * $this->fixPrecisionRate);
54
55
        return apcu_cas($key, $oldValue, $newValue);
56
    }
57
58
    public function get(string $key): mixed
59
    {
60
        $value = apcu_fetch($key);
61
62
        if ((!is_int($value)) && !is_float($value) && !is_bool($value)) {
63
            throw new InvalidArgumentException('The value is not supported by ApcuStorage,it must be bool, int or float');
64
        }
65
66
        if ($value != false) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $value of type boolean|double|integer against false; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
67
            $value = (float)$value / $this->fixPrecisionRate;
68
        }
69
        return $value;
70
    }
71
}
72