RandomStr::setChars()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 11
nc 6
nop 2
dl 0
loc 17
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
namespace ierusalim\Random;
4
5
/**
6
 * This class RandomStr is intended for generating random strings of any chars
7
 * Can generate following types:
8
 *  - random bytes  (as random_bytes PHP7-function)
9
 *  - ASCII chars from specified lists
10
 *  - any UTF-8 chars from specified lists (multibyte supported)
11
 *
12
 * PHP Version 5.6
13
 *
14
 *
15
 * @package   ierusalim\RandomGen
16
 * @author    Alexander Jer <[email protected]>
17
 * @copyright 2017, Ierusalim
18
 * @license   https://opensource.org/licenses/Apache-2.0 Apache-2.0
19
 *
20
 *
21
 * Example of use:
22
 *
23
 *  $r = new RandomStr(); //initialized with default characters list (66 chars)
24
 *  echo $r->genRandomStr(99); //generate random 99 characters from default list
25
 *
26
 *  //It works fast. No problem for create random string of 1 million chars
27
 *  $str = $r->genRandomStr(1000000);
28
 *  echo "\nGenerated bytes: " . strlen($str);
29
 *
30
 *  //Need multibyte characters? No problems, set flag $utf8mode = true
31
 *  $r->setChars("神會貓性少女 迪克和陰部", true);
32
 *  echo $r->genRandomStr(888);
33
 *
34
 */
35
class RandomStr
36
{
37
    /**
38
     * @var array
39
     */
40
    public $char_sets;
41
    /**
42
     * Function for generation random bytes
43
     *
44
     * @var callable
45
     */
46
    public $rnd_fn;
47
48
    /**
49
     * When creating an object, can specify a list of characters for generation.
50
     * Two formats are possible:
51
     *  - one string of chars;
52
     *  - strings array for many chars_set.
53
     *
54
     * When specified one string, it is means a list of character set nmb=0
55
     * When specified array, it is considered many character sets by array keys.
56
     *
57
     * Its need for genRandomStr($len, $char_set_num=0) function.
58
     *
59
     * For using multibyte UTF-8 characters set $utf8mode parameter to true
60
     *
61
     * @param string|array $init_charset
62
     * @param boolean      $utf8
63
     */
64
    public function __construct($init_charset = null, $utf8mode = false)
65
    {
66
        // set default function for generation random bytes
67
        $this->rnd_fn = [$this, 'md5RandomBytes'];
68
69
        //check available function for quick-generation random bytes
70
        foreach ([
71
            '\random_bytes', //for PHP7
72
            '\openssl_random_pseudo_bytes', // better for PHP5, need OpenSSL ext
73
            '\mcrypt_create_iv', // need MCRypt
74
        ] as $fn) {
75
            if (\function_exists($fn)) {
76
                $this->rnd_fn = $fn;
77
                break;
78
            }
79
        }
80
        $this->setChars($init_charset, $utf8mode);
81
    }
82
83
    /**
84
     * See description this parameters in description for __construct
85
     *
86
     * @param string|array $init_charset
87
     * @param boolean      $utf8
88
     */
89
    public function setChars($init_charset = null, $utf8mode = false)
90
    {
91
        if (\is_array($init_charset)) {
92
            $this->char_sets = $init_charset;
93
        } elseif (is_string($init_charset)) {
94
            $this->char_sets = [$init_charset];
95
        } else {
96
            //by default used this characters
97
            $this->char_sets = [
98
                'abcdefghijklmnopqrstuvwxyz' .
99
                'ABCDEFGHIJKLMNOPQRSTUVWXYZ' .
100
                '01234567890_-.'
101
                ];
102
        }
103
104
        if ($utf8mode) {
105
            $this->explodeUtf8();
106
        }
107
    }
108
109
    protected function explodeUtf8()
110
    {
111
        foreach ($this->char_sets as $k => $chars) {
112
            if (\is_array($chars)) {
113
                continue;
114
            }
115
            $len = \mb_strlen($chars, "UTF-8");
116
            if ($len == \strlen($chars)) {
117
                continue;
118
            }
119
            $arr=[];
120
            for ($i = 0; $i < $len; $i++) {
121
                $arr[] = \mb_substr($chars, $i, 1, "UTF-8");
122
            }
123
            $this->char_sets[$k]=$arr;
124
        }
125
    }
126
127
    /**
128
     * Random string generate (specified length and optional characters-set nmb)
129
     *
130
     * Available characters placed in the strings array $this->char_sets
131
     * This array initializing when creating new RandomStr object.
132
     * This array is available as a public parameter and can modified like
133
     *  $r->char_sets[nmb] = 'string of avaliable characters for nmb'
134
     *
135
     * @param integer $len Length of generate string
136
     * @param integer $char_set_num Number of char_set selected for use
137
     *
138
     * @api
139
     * @staticvar string $chars
140
     *
141
     * @return string
142
     */
143
    public function genRandomStr($len = 10, $char_set_num = 0)
144
    {
145
        if (!isset($this->char_sets[$char_set_num]) || $len < 1) {
146
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
147
        } elseif (is_array($this->char_sets[$char_set_num])) {
148
            $l = count($this->char_sets[$char_set_num]);
149
        } else {
150
            $l = \strlen($this->char_sets[$char_set_num]);
151
        }
152
        $outstr = '';
153
        if ($l) {
154
            foreach (\unpack('v*', call_user_func($this->rnd_fn, $len * 2)) as $n) {
155
                $outstr .= $this->char_sets[$char_set_num][$n % $l];
156
            }
157
        }
158
        return $outstr;
159
    }
160
161
    /**
162
     * Analog of PHP7-function random_bytes($length) for using under PHP5
163
     *
164
     * @param integer $length
165
     * @return string
166
     */
167
    public function genRandomBytes($length)
168
    {
169
        if ($length > 0) {
170
            return \call_user_func($this->rnd_fn, $length);
171
        }
172
    }
173
174
    /**
175
     * This function is used to generate bytes if the best functions not found
176
     *
177
     * @param integer $len
178
     * @return string
179
     */
180
    public function md5RandomBytes($len)
181
    {
182
        if ($len>0) {
183
            $start = mt_rand(9, PHP_INT_MAX);
184
            $output = '';
185
            while ($len > 16) {
186
                $output .= md5($start++, true);
187
                $len-=16;
188
            }
189
            $output .= substr( md5($start, true), 0, $len);
190
            return $output;
191
        }
192
    }
193
}
194