Completed
Pull Request — master (#2)
by Jonathan
02:42
created

ItemDecorator::getKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 4
rs 10
c 1
b 0
f 1
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
namespace Jsq\CacheEncryption\Iron;
3
4
use DateInterval;
5
use DateTime;
6
use DateTimeInterface;
7
use Iron\Iron;
8
use Iron\PasswordInterface;
9
use Iron\Token;
10
use Psr\Cache\CacheItemInterface;
11
use Throwable;
12
13
class ItemDecorator implements CacheItemInterface
14
{
15
    /** @var PasswordInterface */
16
    private $password;
17
    /** @var Iron */
18
    private $iron;
19
    /** @var CacheItemInterface */
20
    private $decorated;
21
    /** @var mixed */
22
    private $plaintext;
23
    /** @var Token|null */
24
    private $token;
25
    /** @var int|null */
26
    private $expiration;
27
28 View Code Duplication
    public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
29
        CacheItemInterface $decorated,
30
        PasswordInterface $password,
31
        $cipher
32
    ) {
33
        if (!class_exists(Iron::class)) {
34
            // @codeCoverageIgnoreStart
35
            throw new \RuntimeException('You must install'
36
                . ' jsq/iron-php to use the Iron decorator.');
37
            // @codeCoverageIgnoreEnd
38
        }
39
40
        $this->decorated = $decorated;
41
        $this->password = $password;
42
        $this->iron = new Iron($cipher);
43
    }
44
45
    public function get()
46
    {
47
        if ($this->plaintext) {
48
            return $this->plaintext;
49
        }
50
        
51
        if ($this->tryToSetTokenFromDecorated()) {
52
            return json_decode(
53
                $this->iron->decryptToken($this->token, $this->password),
54
                true
55
            );
56
        }
57
    }
58
59
    public function getKey()
60
    {
61
        return $this->decorated->getKey();
62
    }
63
64
    public function isHit()
65
    {
66
        return $this->tryToSetTokenFromDecorated();
67
    }
68
69
    public function expiresAfter($time)
70
    {
71
        if ($time instanceof DateInterval) {
72
            $this->expiration = (new DateTime)->add($time)->getTimestamp();
73
        } elseif (is_int($time)) {
74
            $this->expiration = time() + $time;
75
        }
76
        
77
        $this->decorated->expiresAfter($time);
78
        
79
        return $this;
80
    }
81
82
    public function expiresAt($expiration)
83
    {
84
        if ($expiration instanceof DateTimeInterface) {
85
            $this->expiration = $expiration->getTimestamp();
86
        }
87
        
88
        $this->decorated->expiresAt($expiration);
89
        
90
        return $this;
91
    }
92
    
93
    public function set($value)
94
    {
95
        $this->plaintext = $value;   
96
        return $this;
97
    }
98
99
    public function getDecorated()
100
    {
101
        return $this->decorated;
102
    }
103
104
    public function finalize()
105
    {
106
        $this->decorated->set((string) $this->iron->encrypt(
107
            $this->password,
108
            json_encode($this->plaintext),
109
            $this->expiration ? time() - $this->expiration : 0
110
        ));
111
    }
112
113
    /**
114
     * @return bool
115
     */
116
    private function tryToSetTokenFromDecorated()
117
    {
118
        if (empty($this->token)) {
119
            try {
120
                $this->token = Token::fromSealed(
121
                    $this->password,
122
                    $this->decorated->get()
123
                );
124
            } catch (Throwable $t) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
Bug introduced by
The class Throwable does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
125
        }
126
127
        return isset($this->token);
128
    }
129
}
130