Completed
Push — master ( c9a55e...7dd42c )
by Peter
05:55
created

Base64UID::random()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 32
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 23.461

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 32
ccs 3
cts 14
cp 0.2143
rs 8.439
cc 6
eloc 17
nc 6
nop 2
crap 23.461
1
<?php
2
3
/**
4
 * GpsLab component.
5
 *
6
 * @author    Peter Gribanov <[email protected]>
7
 * @copyright Copyright (c) 2011, Peter Gribanov
8
 * @license   http://opensource.org/licenses/MIT
9
 */
10
11
namespace GpsLab\Component\Base64UID;
12
13
class Base64UID
14
{
15
    /**
16
     * @var string
17
     */
18
    private static $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
19
20
    /**
21
     * @param int $length
22
     *
23
     * @return string
24
     */
25 1
    public static function generate($length = 10)
26
    {
27 1
        $uid = '';
28 1
        while ($length-- > 0) {
29 1
            $uid .= self::$chars[self::random(0, 63)];
30
        }
31
32 1
        return $uid;
33
    }
34
35
    /**
36
     * Generates cryptographically secure pseudo-random integers.
37
     *
38
     * Follback for PHP < 7.0
39
     *
40
     * @see http://php.net/manual/en/function.random-int.php#119670
41
     *
42
     * @throws \Exception
43
     *
44
     * @param int $min
45
     * @param int $max
46
     *
47
     * @return int|null
48
     */
49 1
    private static function random($min, $max)
50
    {
51 1
        if (function_exists('random_int')) {
52 1
            return random_int($min, $max);
53
        }
54
55
        // @codeCoverageIgnoreStart
56
        if (!function_exists('mcrypt_create_iv')) {
57
            throw new \Exception('mcrypt must be loaded for random_int to work');
58
        }
59
        // @codeCoverageIgnoreEnd
60
61
        $range = $counter = $max - $min;
62
        $bits = 1;
63
64
        while ($counter >>= 1) {
65
            ++$bits;
66
        }
67
68
        $bytes = (int) max(ceil($bits / 8), 1);
69
        $bitmask = pow(2, $bits) - 1;
70
71
        if ($bitmask >= PHP_INT_MAX) {
72
            $bitmask = PHP_INT_MAX;
73
        }
74
75
        do {
76
            $result = hexdec(bin2hex(mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM))) & $bitmask;
77
        } while ($result > $range);
78
79
        return $result + $min;
80
    }
81
}
82