GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (142)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Cache.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * This file is part of the PHPMongo package.
5
 *
6
 * (c) Dmytro Sokil <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sokil\Mongo;
13
14
use Psr\SimpleCache\CacheInterface;
15
use Sokil\Mongo\Cache\Exception\CacheException;
16
use Sokil\Mongo\Cache\Exception\InvalidArgumentException;
17
18
class Cache implements \Countable, CacheInterface
19
{
20
    const FIELD_NAME_VALUE = 'v';
21
    const FIELD_NAME_EXPIRED = 'e';
22
    const FIELD_NAME_TAGS = 't';
23
    
24
    private $collection;
25
26
    /**
27
     * Cache constructor.
28
     * @param Database $database
29
     * @param string $collectionName namespace of cache
30
     */
31
    public function __construct(Database $database, $collectionName)
32
    {
33
        $this->collection = $database
34
            ->map($collectionName, array(
35
                'index' => array(
36
                    // date field
37
                    array(
38
                        'keys' => array(self::FIELD_NAME_EXPIRED => 1),
39
                        'expireAfterSeconds' => 0
40
                    ),
41
                )
42
            ))
43
            ->getCollection($collectionName)
44
            ->disableDocumentPool();
45
    }
46
47
    /**
48
     * @return Cache
49
     */
50
    public function init()
51
    {
52
        $this->collection->initIndexes();
53
        return $this;
54
    }
55
56
    /**
57
     * Persists a set of key => value pairs in the cache, with an optional TTL.
58
     *
59
     * @param array                     $values A list of key => value pairs for a multiple-set operation.
60
     * @param null|int|\DateInterval    $ttl    Optional. The TTL value of this item. If no value is sent and
61
     *                                          the driver supports TTL then the library may set a default value
62
     *                                          for it or let the driver take care of that.
63
     * @param array                     $tags   List of tags
64
     *
65
     * @return bool True on success and false on failure.
66
     *
67
     * @throws \Psr\SimpleCache\InvalidArgumentException
68
     * MUST be thrown if $values is neither an array nor a Traversable,
69
     * or if any of the $values are not a legal value.
70
     */
71
    public function setMultiple($values, $ttl = null, array $tags = array())
72
    {
73
        // prepare expiration
74
        if (!empty($ttl)) {
75 View Code Duplication
            if ($ttl instanceof \DateInterval) {
0 ignored issues
show
This code seems to be duplicated across 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...
76
                $ttl = $ttl->s;
77
            } elseif (!is_int($ttl)) {
78
                throw new InvalidArgumentException('Invalid TTL specified');
79
            }
80
81
            $expirationTimestamp = time() + $ttl;
82
        }
83
84
        // prepare persistence
85
        $persistence = $this->collection->getDatabase()->getClient()->createPersistence();
86
87
        // prepare documents to store
88
        foreach ($values as $key => $value) {
89
            // create document
90
            $document = array(
91
                '_id' => $key,
92
                self::FIELD_NAME_VALUE => $value,
93
            );
94
95
            // add expiration
96
            if (!empty($expirationTimestamp)) {
97
                $document[self::FIELD_NAME_EXPIRED] = new \MongoDate($expirationTimestamp);
98
            }
99
100
            // prepare tags
101
            if (!empty($tags)) {
102
                $document[self::FIELD_NAME_TAGS] = $tags;
103
            }
104
105
            // attach document
106
            $persistence->persist($this->collection->createDocument($document));
107
        }
108
109
        try {
110
            $persistence->flush();
111
        } catch (\Exception $e) {
112
            return false;
113
        }
114
115
        return true;
116
    }
117
118
    /**
119
     * Set with expiration on concrete date
120
     *
121
     * @deprecated Use self::set() with calculated ttl
122
     *
123
     * @param int|string $key
124
     * @param mixed $value
125
     * @param int $expirationTime
126
     * @param array $tags
127
     *
128
     * @throws Exception
129
     *
130
     * @return bool
131
     */
132
    public function setDueDate($key, $value, $expirationTime, array $tags = null)
133
    {
134
        return $this->set($key, $value, $expirationTime - time(), $tags);
135
    }
136
    
137
    /**
138
     * Set key that never expired
139
     *
140
     * @deprecated Use self::set() with null in ttl
141
     *
142
     * @param int|string $key
143
     * @param mixed $value
144
     * @param array $tags
145
     *
146
     * @return bool
147
     */
148
    public function setNeverExpired($key, $value, array $tags = null)
149
    {
150
        return $this->set($key, $value, null, $tags);
151
    }
152
    
153
    /**
154
     * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time.
155
     *
156
     * @param string                    $key    The key of the item to store.
157
     * @param mixed                     $value  The value of the item to store, must be serializable.
158
     * @param null|int|\DateInterval    $ttl    Optional. The TTL value of this item. If no value is sent and
159
     *                                          the driver supports TTL then the library may set a default value
160
     *                                          for it or let the driver take care of that.
161
     * @param array                     $tags   List of tags
162
     *
163
     * @return bool True on success and false on failure.
164
     *
165
     * @throws InvalidArgumentException
166
     * @throws CacheException
167
     */
168
    public function set($key, $value, $ttl = null, array $tags = null)
169
    {
170
        // create document
171
        $document = array(
172
            '_id' => $key,
173
            self::FIELD_NAME_VALUE => $value,
174
        );
175
176
        // prepare expiration
177
        if (!empty($ttl)) {
178 View Code Duplication
            if ($ttl instanceof \DateInterval) {
0 ignored issues
show
This code seems to be duplicated across 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...
179
                $ttl = $ttl->s;
180
            } elseif (!is_int($ttl)) {
181
                throw new InvalidArgumentException('Invalid TTL specified');
182
            }
183
184
            $expirationTimestamp = time() + $ttl;
185
            $document[self::FIELD_NAME_EXPIRED] = new \MongoDate((int) $expirationTimestamp);
186
        }
187
188
        // prepare tags
189
        if (!empty($tags)) {
190
            $document[self::FIELD_NAME_TAGS] = $tags;
191
        }
192
193
        // create document
194
        $result = $this
195
            ->collection
196
            ->getMongoCollection()
197
            ->update(
198
                array(
199
                    '_id' => $key,
200
                ),
201
                $document,
202
                array(
203
                    'upsert' => true,
204
                )
205
            );
206
207
        // check result
208
        return (double) 1 === $result['ok'];
209
    }
210
211
        /**
212
     * @param array $keys
213
     * @param mixed|null $default
214
     *
215
     * @return array
216
     */
217
    public function getMultiple($keys, $default = null)
218
    {
219
        // Prepare defaults
220
        $values = array_fill_keys($keys, $default);
221
222
        // Get document
223
        $documents = $this->collection->getDocuments($keys);
224
        if (empty($documents)) {
225
            return $values;
226
        }
227
228
        // Mongo deletes document not exactly when set in field
229
        // Required date checking
230
        // Expiration may be empty for keys which never expired
231
        foreach ($documents as $document) {
232
            /** @var \MongoDate $expiredAt */
233
            $expiredAt = $document->get(self::FIELD_NAME_EXPIRED);
234
            if (empty($expiredAt) || $expiredAt->sec >= time()) {
235
                $values[$document->getId()] = $document->get(self::FIELD_NAME_VALUE);
236
            } else {
237
                $values[$document->getId()] = $default;
238
            }
239
        }
240
241
        return $values;
242
    }
243
244
    /**
245
     * Get value by key
246
     *
247
     * @param string $key
248
     * @param mixed $default
249
     *
250
     * @return mixed
251
     */
252
    public function get($key, $default = null)
253
    {
254
        // Get document
255
        $document = $this->collection->getDocument($key);
256
        if (!$document) {
257
            return $default;
258
        }
259
260
        // Mongo deletes document not exactly when set in field
261
        // Required date checking
262
        // Expiration may be empty for keys which never expired
263
        $expiredAt = $document->get(self::FIELD_NAME_EXPIRED);
264
        if (!empty($expiredAt) && $expiredAt->sec < time()) {
265
            return $default;
266
        }
267
268
        // Return value
269
        return $document->get(self::FIELD_NAME_VALUE);
270
    }
271
272
273
    /**
274
     * Clear all cache
275
     *
276
     * @return bool
277
     */
278
    public function clear()
279
    {
280
        try {
281
            $this->collection->delete();
282
        } catch (\Exception $e) {
283
            return false;
284
        }
285
286
        return true;
287
    }
288
289
    /**
290
     * Delete an item from the cache by its unique key.
291
     *
292
     * @param string $key The unique cache key of the item to delete.
293
     *
294
     * @return bool True if the item was successfully removed. False if there was an error.
295
     *
296
     * @throws \Psr\SimpleCache\InvalidArgumentException
297
     * MUST be thrown if the $key string is not a legal value.
298
     */
299
    public function delete($key)
300
    {
301
        if (empty($key) || !is_string($key)) {
302
            throw new InvalidArgumentException('Key must be string');
303
        }
304
305
        try {
306
            $this->collection->batchDelete(array(
307
                '_id' => $key,
308
            ));
309
        } catch (\Exception $e) {
310
            return false;
311
        }
312
313
        return true;
314
    }
315
316
    /**
317
     * Deletes multiple cache items in a single operation.
318
     *
319
     * @param array $keys A list of string-based keys to be deleted.
320
     *
321
     * @return bool True if the items were successfully removed. False if there was an error.
322
     *
323
     * @throws \Psr\SimpleCache\InvalidArgumentException
324
     * MUST be thrown if $keys is neither an array nor a Traversable,
325
     * or if any of the $keys are not a legal value.
326
     */
327
    public function deleteMultiple($keys)
328
    {
329
        try {
330
            $this->collection->batchDelete(
331
                function(Expression $e) use($keys) {
332
                    $e->whereIn('_id', $keys);
333
                }
334
            );
335
        } catch (\Exception $e) {
336
            return false;
337
        }
338
339
        return true;
340
    }
341
    
342
    /**
343
     * Delete documents by tag
344
     */
345
    public function deleteMatchingTag($tag)
346
    {
347
        $this->collection->batchDelete(function (\Sokil\Mongo\Expression $e) use ($tag) {
348
            return $e->where(Cache::FIELD_NAME_TAGS, $tag);
349
        });
350
        
351
        return $this;
352
    }
353
    
354
    /**
355
     * Delete documents by tag
356
     */
357
    public function deleteNotMatchingTag($tag)
358
    {
359
        $this->collection->batchDelete(function (\Sokil\Mongo\Expression $e) use ($tag) {
360
            return $e->whereNotEqual(Cache::FIELD_NAME_TAGS, $tag);
361
        });
362
        
363
        return $this;
364
    }
365
    
366
    /**
367
     * Delete documents by tag
368
     * Document deletes if it contains all passed tags
369
     */
370
    public function deleteMatchingAllTags(array $tags)
371
    {
372
        $this->collection->batchDelete(function (\Sokil\Mongo\Expression $e) use ($tags) {
373
            return $e->whereAll(Cache::FIELD_NAME_TAGS, $tags);
374
        });
375
        
376
        return $this;
377
    }
378
    
379
    /**
380
     * Delete documents by tag
381
     * Document deletes if it not contains all passed tags
382
     */
383
    public function deleteMatchingNoneOfTags(array $tags)
384
    {
385
        $this->collection->batchDelete(function (\Sokil\Mongo\Expression $e) use ($tags) {
386
            return $e->whereNoneOf(Cache::FIELD_NAME_TAGS, $tags);
387
        });
388
        
389
        return $this;
390
    }
391
    
392
    /**
393
     * Delete documents by tag
394
     * Document deletes if it contains any of passed tags
395
     */
396
    public function deleteMatchingAnyTag(array $tags)
397
    {
398
        $this->collection->batchDelete(function (\Sokil\Mongo\Expression $e) use ($tags) {
399
            return $e->whereIn(Cache::FIELD_NAME_TAGS, $tags);
400
        });
401
        
402
        return $this;
403
    }
404
    
405
    /**
406
     * Delete documents by tag
407
     * Document deletes if it contains any of passed tags
408
     */
409
    public function deleteNotMatchingAnyTag(array $tags)
410
    {
411
        $this->collection->batchDelete(function (\Sokil\Mongo\Expression $e) use ($tags) {
412
            return $e->whereNotIn(Cache::FIELD_NAME_TAGS, $tags);
413
        });
414
        
415
        return $this;
416
    }
417
418
    /**
419
     * Get total count of documents in cache
420
     *
421
     * @return int
422
     */
423
    public function count()
424
    {
425
        return $this->collection->count();
426
    }
427
428
    /**
429
     * Check if cache has key
430
     *
431
     * @param string $key
432
     * @return bool
433
     */
434
    public function has($key)
435
    {
436
        return (bool)$this->get($key);
437
    }
438
}
439