Failed Conditions
Push — StorableJWKSet ( d4874f...81664d )
by Florent
03:01
created

StorableJWKSet::getFileContent()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
c 0
b 0
f 0
rs 9.4285
cc 3
eloc 8
nc 3
nop 0
1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2016 Spomky-Labs
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license.  See the LICENSE file for details.
10
 */
11
12
namespace Jose\Object;
13
14
use Assert\Assertion;
15
use Base64Url\Base64Url;
16
use Jose\Factory\JWKFactory;
17
18
/**
19
 * Class StorableJWKSet.
20
 */
21
class StorableJWKSet implements StorableJWKSetInterface
22
{
23
    /**
24
     * @var \Jose\Object\JWKSetInterface
25
     */
26
    protected $jwkset;
27
28
    /**
29
     * @var string
30
     */
31
    protected $filename;
32
33
    /**
34
     * @var int
35
     */
36
    protected $last_modification_time = null;
37
38
    /**
39
     * @var array
40
     */
41
    protected $parameters;
42
43
    /**
44
     * @var array
45
     */
46
    protected $nb_keys;
47
48
    /**
49
     * StorableJWKSet constructor.
50
     *
51
     * @param string $filename
52
     * @param array  $parameters
53
     * @param int    $nb_keys
54
     */
55
    public function __construct($filename, array $parameters, $nb_keys)
56
    {
57
        Assertion::directory(dirname($filename), 'The selected directory does not exist.');
58
        Assertion::writeable(dirname($filename), 'The selected directory is not writable.');
59
        Assertion::integer($nb_keys, 'The key set must contain at least one key.');
60
        Assertion::greaterThan($nb_keys, 0, 'The key set must contain at least one key.');
61
        $this->filename = $filename;
62
        $this->parameters = $parameters;
63
        $this->nb_keys = $nb_keys;
0 ignored issues
show
Documentation Bug introduced by
It seems like $nb_keys of type integer is incompatible with the declared type array of property $nb_keys.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    public function current()
70
    {
71
        return $this->getJWKSet()->current();
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77
    public function next()
78
    {
79
        $this->getJWKSet()->next();
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85
    public function key()
86
    {
87
        return $this->getJWKSet()->key();
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function valid()
94
    {
95
        return $this->getJWKSet()->valid();
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101
    public function rewind()
102
    {
103
        $this->getJWKSet()->rewind();
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function offsetExists($offset)
110
    {
111
        return $this->getJWKSet()->offsetExists($offset);
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117
    public function offsetGet($offset)
118
    {
119
        return $this->getJWKSet()->offsetGet($offset);
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function offsetSet($offset, $value)
126
    {
127
        return $this->getJWKSet()->offsetSet($offset, $value);
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function offsetUnset($offset)
134
    {
135
        return $this->getJWKSet()->offsetUnset($offset);
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141
    public function getKey($index)
142
    {
143
        return $this->getJWKSet()->getKey($index);
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149
    public function hasKey($index)
150
    {
151
        return $this->getJWKSet()->hasKey($index);
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157
    public function getKeys()
158
    {
159
        return $this->getJWKSet()->getKeys();
160
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165
    public function addKey(JWKInterface $key)
166
    {
167
        return $this->getJWKSet()->addKey($key);
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173
    public function removeKey($index)
174
    {
175
        return $this->getJWKSet()->removeKey($index);
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function countKeys()
182
    {
183
        return $this->getJWKSet()->countKeys();
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189
    public function selectKey($type, $algorithm = null, array $restrictions = [])
190
    {
191
        return $this->getJWKSet()->selectKey($type, $algorithm, $restrictions);
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197
    public function count()
198
    {
199
        return $this->getJWKSet()->count();
200
    }
201
202
    /**
203
     * @return string
204
     */
205
    protected function getFilename()
206
    {
207
        return $this->filename;
208
    }
209
210
    /**
211
     * {@inheritdoc}
212
     */
213
    public function jsonSerialize()
214
    {
215
        return $this->getJWKSet()->jsonSerialize();
216
    }
217
218
    /**
219
     * @return \Jose\Object\JWKSetInterface
220
     */
221
    protected function getJWKSet()
222
    {
223
        $this->loadJWKSet();
224
225
        return $this->jwkset;
226
    }
227
228
229
    protected function loadJWKSet()
230
    {
231
        if (file_exists($this->filename)) {
232
            if (false === $this->hasJWKSetBeenUpdated()) {
233
                return;
234
            }
235
            $content = $this->getFileContent();
236
            if (null === $content) {
237
                $this->createJWKSet();
238
            }
239
            $this->last_modification_time = filemtime($this->getFilename());
240
            $this->jwkset = new JWKSet($content);
0 ignored issues
show
Bug introduced by
It seems like $content defined by $this->getFileContent() on line 235 can also be of type null; however, Jose\Object\JWKSet::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
241
        } else {
242
            $this->createJWKSet();
243
        }
244
    }
245
246
    /**
247
     * @return null|string
248
     */
249
    protected function getFileContent()
250
    {
251
        $content = file_get_contents($this->filename);
252
        if (false === $content) {
253
            return null;
254
        }
255
        $content = json_decode($content, true);
256
        if (!is_array($content)) {
257
            return null;
258
        }
259
260
        return $content;
261
    }
262
263
    /**
264
     * @return bool
265
     */
266
    protected function hasJWKSetBeenUpdated()
267
    {
268
        if (null !== $this->last_modification_time) {
269
            $mtime = filemtime($this->getFilename());
270
            return $mtime !== $this->last_modification_time;
271
        }
272
273
        return true;
274
    }
275
276
    /**
277
     *
278
     */
279
    protected function createJWKSet()
280
    {
281
        $this->jwkset = new JWKSet();
282
        for ($i = 0; $i < $this->nb_keys; $i++) {
283
            $key = $this->createJWK();
284
            $this->jwkset->addKey($key);
0 ignored issues
show
Bug introduced by
It seems like $key defined by $this->createJWK() on line 283 can also be of type object<Jose\Object\JWKSet>; however, Jose\Object\JWKSet::addKey() does only seem to accept object<Jose\Object\JWKInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
285
        }
286
287
        $this->save();
288
    }
289
290
    /**
291
     * @return \Jose\Object\JWKInterface
292
     */
293
    protected function createJWK()
294
    {
295
        $data = JWKFactory::createKey($this->parameters)->getAll();
296
        $data['kid'] = Base64Url::encode(random_bytes(64));
297
298
        return JWKFactory::createFromValues($data);
299
    }
300
301
302
    protected function save()
303
    {
304
        file_put_contents($this->getFilename(), json_encode($this->jwkset));
305
    }
306
}
307