JtiService::deleteAllExpired()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 0
cts 0
cp 0
rs 9.552
c 0
b 0
f 0
cc 3
nc 4
nop 0
crap 12
1
<?php
2
/**
3
 * JtiService.php
4
 *
5
 * PHP version 5.6+
6
 *
7
 * @author Philippe Gaultier <[email protected]>
8
 * @copyright 2010-2017 Philippe Gaultier
9
 * @license http://www.sweelix.net/license license
10
 * @version 1.2.0
11
 * @link http://www.sweelix.net
12
 * @package sweelix\oauth2\server\services\redis
13
 */
14
15
namespace sweelix\oauth2\server\services\redis;
16
17
use sweelix\oauth2\server\exceptions\DuplicateIndexException;
18
use sweelix\oauth2\server\exceptions\DuplicateKeyException;
19
use sweelix\oauth2\server\interfaces\JtiModelInterface;
20
use sweelix\oauth2\server\interfaces\JtiServiceInterface;
21
use yii\db\Exception as DatabaseException;
22
use Yii;
23
24
/**
25
 * This is the jti service for redis
26
 *  database structure
27
 *    * oauth2:jti:<jid> : hash (Jti)
28
 *
29
 * @author Philippe Gaultier <[email protected]>
30
 * @copyright 2010-2017 Philippe Gaultier
31
 * @license http://www.sweelix.net/license license
32
 * @version 1.2.0
33
 * @link http://www.sweelix.net
34
 * @package sweelix\oauth2\server\services\redis
35
 * @since 1.0.0
36
 */
37
class JtiService extends BaseService implements JtiServiceInterface
38
{
39
    /**
40
     * @var string subject namespace (collection for jtis)
41
     */
42
    public $subjectNamespace = '';
43
44
    /**
45
     * @var string client namespace (collection for jtis)
46 4
     */
47
    public $clientNamespace = '';
48 4
49
    /**
50
     * @param string $jid jti ID
51
     * @return string access token Key
52
     * @since 1.0.0
53
     */
54 4
    public function getJtiKey($jid)
55
    {
56 4
        return $this->namespace . ':' . $jid;
57 4
    }
58 4
59 1
    /**
60
     * @param string $sid subject ID
61 4
     * @return string user jtis collection Key
62
     */
63
    public function getSubjectJtisKey($sid)
64
    {
65
        return $this->subjectNamespace . ':' . $sid . ':jtis';
66
    }
67
68
    /**
69
     * @param string $cid client ID
70
     * @return string client jtis collection Key
71
     */
72
    public function getClientJtisKey($cid)
73
    {
74 4
        return $this->clientNamespace . ':' . $cid . ':jtis';
75
    }
76 4
77 4
    /**
78
     * @return string key of all jtis list
79
     */
80 4
    public function getJtiListKey()
81
    {
82 4
        return $this->namespace . ':keys';
83 4
    }
84 2
85
    /**
86
     * @return string key of all subjects list
87 4
     */
88 4
    public function getSubjectListKey()
89 4
    {
90 4
        return $this->subjectNamespace . ':keys';
91
    }
92 4
93 4
    /**
94 4
     * @inheritdoc
95 4
     */
96 4
    public function save(JtiModelInterface $jti, $attributes)
97
    {
98 4
        if ($jti->getIsNewRecord()) {
99 4
            $result = $this->insert($jti, $attributes);
100
        } else {
101 4
            $result = $this->update($jti, $attributes);
102 4
        }
103 4
        return $result;
104
    }
105
106
    /**
107
     * Save Jti
108
     * @param JtiModelInterface $jti
109
     * @param null|array $attributes attributes to save
110 4
     * @return bool
111 4
     * @throws DatabaseException
112 4
     * @throws DuplicateIndexException
113 4
     * @throws DuplicateKeyException
114 4
     * @since 1.0.0
115 4
     */
116
    protected function insert(JtiModelInterface $jti, $attributes)
117
    {
118
        $result = false;
119
        if (!$jti->beforeSave(true)) {
120
            return $result;
121
        }
122
        $jtiId = $jti->getKey();
123
        $jtiKey = $this->getJtiKey($jtiId);
124
        if (empty($jti->subject) === false) {
0 ignored issues
show
Bug introduced by
Accessing subject on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
125
            $subjectJtisKey = $this->getSubjectJtisKey($jti->subject);
0 ignored issues
show
Bug introduced by
Accessing subject on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
126
        } else {
127
            $subjectJtisKey = null;
128 1
        }
129
        $clientJtisKey = $this->getClientJtisKey($jti->clientId);
0 ignored issues
show
Bug introduced by
Accessing clientId on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
130 1
        $jtiListKey = $this->getJtiListKey();
131
        $subjectListKey = $this->getSubjectListKey();
132
133
        //check if record exists
134 1
        $entityStatus = (int)$this->db->executeCommand('EXISTS', [$jtiKey]);
135 1
        if ($entityStatus === 1) {
136 1
            throw new DuplicateKeyException('Duplicate key "' . $jtiKey . '"');
137 1
        }
138
139
        $values = $jti->getDirtyAttributes($attributes);
0 ignored issues
show
Bug introduced by
It seems like $attributes defined by parameter $attributes on line 116 can also be of type array; however, sweelix\oauth2\server\in...e::getDirtyAttributes() does only seem to accept array<integer,string>|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
140 1
        $redisParameters = [$jtiKey];
141 1
        $this->setAttributesDefinitions($jti->attributesDefinition());
142 1
        $expire = null;
143 1
        foreach ($values as $key => $value) {
144 1
            if (($key === 'expires') && ($value > 0)) {
145
                $expire = $value;
146 1
            }
147
            if ($value !== null) {
148 1
                $redisParameters[] = $key;
149
                $redisParameters[] = $this->convertToDatabase($key, $value);
150 1
            }
151 1
        }
152 1
        //TODO: use EXEC/MULTI to avoid errors
153
        $transaction = $this->db->executeCommand('MULTI');
154 1
        if ($transaction === true) {
155 1
            try {
156
                $this->db->executeCommand('HMSET', $redisParameters);
157 1
                if ($expire !== null) {
158 1
                    $this->db->executeCommand('EXPIREAT', [$jtiKey, $expire]);
159 1
                }
160 1
                if ($subjectJtisKey !== null) {
161
                    $this->db->executeCommand('ZADD', [$subjectJtisKey, $expire === false ? -1 : $expire, $jtiId]);
162 1
                }
163
                $this->db->executeCommand('ZADD', [$clientJtisKey, $expire === false ? -1 : $expire, $jtiId]);
164
                $this->db->executeCommand('ZADD', [$jtiListKey, $expire === false ? -1 : $expire, $jtiId]);
165 1
                $this->db->executeCommand('SADD', [$subjectListKey, $jti->subject]);
0 ignored issues
show
Bug introduced by
Accessing subject on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
166 1
                $this->db->executeCommand('EXEC');
167
            } catch (DatabaseException $e) {
168 1
                // @codeCoverageIgnoreStart
169 1
                // we have a REDIS exception, we should not discard
170
                Yii::debug('Error while inserting entity', __METHOD__);
171
                throw $e;
172 1
                // @codeCoverageIgnoreEnd
173 1
            }
174 1
        }
175
        $changedAttributes = array_fill_keys(array_keys($values), null);
176 1
        $jti->setOldAttributes($values);
177 1
        $jti->afterSave(true, $changedAttributes);
178
        $result = true;
179
        return $result;
180
    }
181
182
183
    /**
184
     * Update Jti
185 1
     * @param JtiModelInterface $jti
186 1
     * @param null|array $attributes attributes to save
187 1
     * @return bool
188 1
     * @throws DatabaseException
189 1
     * @throws DuplicateIndexException
190 1
     * @throws DuplicateKeyException
191 1
     */
192 1
    protected function update(JtiModelInterface $jti, $attributes)
193
    {
194
        if (!$jti->beforeSave(false)) {
195
            return false;
196
        }
197
198 3
        $values = $jti->getDirtyAttributes($attributes);
0 ignored issues
show
Bug introduced by
It seems like $attributes defined by parameter $attributes on line 192 can also be of type array; however, sweelix\oauth2\server\in...e::getDirtyAttributes() does only seem to accept array<integer,string>|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
199
        $modelKey = $jti->key();
200 3
        $jtiId = isset($values[$modelKey]) ? $values[$modelKey] : $jti->getKey();
201 3
        $jtiKey = $this->getJtiKey($jtiId);
202 3
        $jtiListKey = $this->getJtiListKey();
203 3
        $subjectListKey = $this->getSubjectListKey();
204 3
205 3
        if (empty($jti->subject) === false) {
0 ignored issues
show
Bug introduced by
Accessing subject on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
206
            $subjectJtisKey = $this->getSubjectJtisKey($jti->subject);
0 ignored issues
show
Bug introduced by
Accessing subject on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
207 3
        } else {
208 3
            $subjectJtisKey = null;
209 3
        }
210 3
        $clientJtisKey = $this->getClientJtisKey($jti->clientId);
0 ignored issues
show
Bug introduced by
Accessing clientId on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
211 3
212 3
        if (isset($values[$modelKey]) === true) {
213 3
            $newJtiKey = $this->getJtiKey($values[$modelKey]);
214 3
            $entityStatus = (int)$this->db->executeCommand('EXISTS', [$newJtiKey]);
215
            if ($entityStatus === 1) {
216
                throw new DuplicateKeyException('Duplicate key "' . $newJtiKey . '"');
217
            }
218
        }
219
220
        $this->db->executeCommand('MULTI');
221 3
        try {
222 3
            $reAddKeyInList = false;
223 3
            if (array_key_exists($modelKey, $values) === true) {
224 3
                $oldId = $jti->getOldKey();
225 3
                $oldJtiKey = $this->getJtiKey($oldId);
226 3
227 3
                $this->db->executeCommand('RENAMENX', [$oldJtiKey, $jtiKey]);
228
                if ($subjectJtisKey !== null) {
229
                    $this->db->executeCommand('ZREM', [$subjectJtisKey, $oldJtiKey]);
230
                }
231
                $this->db->executeCommand('ZREM', [$clientJtisKey, $oldJtiKey]);
232
                $this->db->executeCommand('ZREM', [$jtiListKey, $oldJtiKey]);
233 1
                $reAddKeyInList = true;
234
            }
235 1
236 1
            $redisUpdateParameters = [$jtiKey];
237 1
            $redisDeleteParameters = [$jtiKey];
238 1
            $this->setAttributesDefinitions($jti->attributesDefinition());
239 1
            $expire = $jti->expires;
0 ignored issues
show
Bug introduced by
Accessing expires on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
240
            foreach ($values as $key => $value) {
241 1
                if ($value === null) {
242
                    if ($key === 'expires') {
243 1
                        $expire = false;
244 1
                    }
245 1
                    $redisDeleteParameters[] = $key;
246 1
                } else {
247 1
                    if (($key === 'expires') && ($value > 0)) {
248 1
                        $expire = $value;
249
                    }
250
                    $redisUpdateParameters[] = $key;
251
                    $redisUpdateParameters[] = $this->convertToDatabase($key, $value);
252
                }
253
            }
254
            if (count($redisDeleteParameters) > 1) {
255
                $this->db->executeCommand('HDEL', $redisDeleteParameters);
256
            }
257
            if (count($redisUpdateParameters) > 1) {
258
                $this->db->executeCommand('HMSET', $redisUpdateParameters);
259
            }
260
            if ($expire === false) {
261
                $this->db->executeCommand('PERSIST', [$jtiKey]);
262
            } elseif ($expire > 0) {
263
                $this->db->executeCommand('EXPIREAT', [$jtiKey, $expire]);
264
            }
265
266
            if ($reAddKeyInList === true) {
267
                if ($subjectJtisKey !== null) {
268
                    $this->db->executeCommand('ZADD', [$subjectJtisKey, $expire === false ? -1 : $expire, $jtiKey]);
269
                }
270
                $this->db->executeCommand('ZADD', [$clientJtisKey, $expire === false ? -1 : $expire, $jtiKey]);
271
                $this->db->executeCommand('ZADD', [$jtiListKey, $expire === false ? -1 : $expire, $jtiKey]);
272
            }
273
            $this->db->executeCommand('SADD', [$subjectListKey, $jti->subject]);
0 ignored issues
show
Bug introduced by
Accessing subject on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
274
275
            $this->db->executeCommand('EXEC');
276
        } catch (DatabaseException $e) {
277
            // @codeCoverageIgnoreStart
278
            // we have a REDIS exception, we should not discard
279
            Yii::debug('Error while updating entity', __METHOD__);
280
            throw $e;
281
            // @codeCoverageIgnoreEnd
282
        }
283
284
        $changedAttributes = [];
285
        foreach ($values as $name => $value) {
286
            $oldAttributes = $jti->getOldAttributes();
287
            $changedAttributes[$name] = isset($oldAttributes[$name]) ? $oldAttributes[$name] : null;
288
            $jti->setOldAttribute($name, $value);
289
        }
290
        $jti->afterSave(false, $changedAttributes);
291
        return true;
292
    }
293
294
    /**
295
     * @inheritdoc
296
     */
297
    public function findOne($key)
298
    {
299
        $record = null;
300
        $jtiKey = $this->getJtiKey($key);
301
        $jtiExists = (bool)$this->db->executeCommand('EXISTS', [$jtiKey]);
302
        if ($jtiExists === true) {
303
            $jtiData = $this->db->executeCommand('HGETALL', [$jtiKey]);
304
            $record = Yii::createObject('sweelix\oauth2\server\interfaces\JtiModelInterface');
305
            /** @var JtiModelInterface $record */
306
            $properties = $record->attributesDefinition();
307
            $this->setAttributesDefinitions($properties);
308
            $attributes = [];
309
            for ($i = 0; $i < count($jtiData); $i += 2) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
310
                if (isset($properties[$jtiData[$i]]) === true) {
311
                    $jtiData[$i + 1] = $this->convertToModel($jtiData[$i], $jtiData[($i + 1)]);
312
                    $record->setAttribute($jtiData[$i], $jtiData[$i + 1]);
313
                    $attributes[$jtiData[$i]] = $jtiData[$i + 1];
314
                    // @codeCoverageIgnoreStart
315
                } elseif ($record->canSetProperty($jtiData[$i])) {
316
                    // TODO: find a way to test attribute population
317
                    $record->{$jtiData[$i]} = $jtiData[$i + 1];
318
                }
319
                // @codeCoverageIgnoreEnd
320
            }
321
            if (empty($attributes) === false) {
322
                $record->setOldAttributes($attributes);
323
            }
324
            $record->afterFind();
325
        }
326
        return $record;
327
    }
328
329
    /**
330
     * @inheritdoc
331
     */
332
    public function findAllBySubject($subject)
333
    {
334
        $subjectJtisKey = $this->getSubjectJtisKey($subject);
335
        $subjectJtis = $this->db->executeCommand('ZRANGE', [$subjectJtisKey, 0, -1]);
336
        $jtis = [];
337
        if ((is_array($subjectJtis) === true) && (count($subjectJtis) > 0)) {
338
            foreach ($subjectJtis as $subjectJtiId) {
339
                $jtis[] = $this->findOne($subjectJtiId);
340
            }
341
        }
342
        return $jtis;
343
    }
344
345
    /**
346
     * @inheritdoc
347
     */
348
    public function deleteAllBySubject($subject)
349
    {
350
        $subjectJtisKey = $this->getSubjectJtisKey($subject);
351
        $subjectJtis = $this->db->executeCommand('ZRANGE', [$subjectJtisKey, 0, -1]);
352
        foreach ($subjectJtis as $subjectJtiId) {
353
            $subjectJti = $this->findOne($subjectJtiId);
354
            if ($subjectJti instanceof JtiModelInterface) {
355
                $this->delete($subjectJti);
356
            }
357
        }
358
        return true;
359
    }
360
361
    /**
362
     * @inheritdoc
363
     */
364
    public function findAllByClientId($clientId)
365
    {
366
        $clientJtisKey = $this->getClientJtisKey($clientId);
367
        $clientJtis = $this->db->executeCommand('ZRANGE', [$clientJtisKey, 0, -1]);
368
        $jtis = [];
369
        if ((is_array($clientJtis) === true) && (count($clientJtis) > 0)) {
370
            foreach ($clientJtis as $clientJtiId) {
371
                $jtis[] = $this->findOne($clientJtiId);
372
            }
373
        }
374
        return $jtis;
375
    }
376
377
    /**
378
     * @inheritdoc
379
     */
380
    public function deleteAllByClientId($clientId)
381
    {
382
        $clientJtisKey = $this->getClientJtisKey($clientId);
383
        $clientJtis = $this->db->executeCommand('ZRANGE', [$clientJtisKey, 0, -1]);
384
        foreach ($clientJtis as $clientJtiId) {
385
            $clientJti = $this->findOne($clientJtiId);
386
            if ($clientJti instanceof JtiModelInterface) {
387
                $this->delete($clientJti);
388
            }
389
        }
390
        return true;
391
    }
392
393
    /**
394
     * @inheritdoc
395
     */
396
    public function delete(JtiModelInterface $jti)
397
    {
398
        $result = false;
399
        if ($jti->beforeDelete()) {
400
            if (empty($jti->subject) === false) {
0 ignored issues
show
Bug introduced by
Accessing subject on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
401
                $subjectJtisKey = $this->getSubjectJtisKey($jti->subject);
0 ignored issues
show
Bug introduced by
Accessing subject on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
402
            } else {
403
                $subjectJtisKey = null;
404
            }
405
            $clientJtisKey = $this->getClientJtisKey($jti->clientId);
0 ignored issues
show
Bug introduced by
Accessing clientId on the interface sweelix\oauth2\server\interfaces\JtiModelInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
406
            $jtiListKey = $this->getJtiListKey();
407
408
            $this->db->executeCommand('MULTI');
409
            $id = $jti->getOldKey();
410
            $jtiKey = $this->getJtiKey($id);
411
412
            $this->db->executeCommand('DEL', [$jtiKey]);
413
            if ($subjectJtisKey !== null) {
414
                $this->db->executeCommand('ZREM', [$subjectJtisKey, $id]);
415
            }
416
            $this->db->executeCommand('ZREM', [$clientJtisKey, $id]);
417
            $this->db->executeCommand('ZREM', [$jtiListKey, $id]);
418
            //TODO: check results to return correct information
419
            $this->db->executeCommand('EXEC');
420
            $jti->setIsNewRecord(true);
421
            $jti->afterDelete();
422
            $result = true;
423
        }
424
        return $result;
425
    }
426
427
    /**
428
     * @inheritdoc
429
     */
430
    public function deleteAllExpired()
431
    {
432
        $date = time();
433
        $jtiListKey = $this->getJtiListKey();
434
        $this->db->executeCommand('ZREMRANGEBYSCORE', [$jtiListKey, -1, $date]);
435
436
        $client = Yii::createObject('sweelix\oauth2\server\interfaces\ClientModelInterface');
437
        $clientClass = get_class($client);
438
        /* @var \sweelix\oauth2\server\interfaces\ClientModelInterface[] $clientList */
439
        $clientList = $clientClass::findAll();
440
        foreach ($clientList as $client) {
441
            $clientJtisKey = $this->getClientJtisKey($client->getKey());
442
            $this->db->executeCommand('ZREMRANGEBYSCORE', [$clientJtisKey, -1, $date]);
443
        }
444
445
        $subjectListKey = $this->getSubjectListKey();
446
        $subjects = $this->db->executeCommand('SMEMBERS', [$subjectListKey]);
447
        foreach ($subjects as $subject) {
448
            $subjectJtisKey = $this->getSubjectJtisKey($subject);
449
            $this->db->executeCommand('ZREMRANGEBYSCORE', [$subjectJtisKey, '-inf', $date]);
450
        }
451
        return true;
452
    }
453
454
    /**
455
     * @inheritdoc
456
     */
457
    public function findAll()
458
    {
459
        $jtiListKey = $this->getJtiListKey();
460
        $jtiList = $this->db->executeCommand('ZRANGE', [$jtiListKey, 0, -1]);
461
        $jtis = [];
462
        if ((is_array($jtiList) === true) && (count($jtiList) > 0)) {
463
            foreach ($jtiList as $jtiId) {
464
                $jtis[] = $this->findOne($jtiId);
465
            }
466
        }
467
        return $jtis;
468
    }
469
}
470