RandomArray::setKeysModelFn()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace ierusalim\Random;
4
5
/**
6
 * This class RandomArray is intended for generating Random Arrays
7
 *
8
 * PHP Version 5.6
9
 *
10
 * @package    ierusalim\RandomArray
11
 * @author     Alexander Jer <[email protected]>
12
 * @copyright  2017, Ierusalim
13
 * @license    https://opensource.org/licenses/Apache-2.0 Apache-2.0
14
 *
15
 * Examples of use:
16
 *  Initialize:
17
 *    $g = new RandomArray();
18
 *
19
 *  //Generate random array with default parameters:
20
 *    $arr = $g->genRandomArray();
21
 *    print_r($arr);
22
 *
23
 *  //Generate random array with string keys from listed chars, 3-9 chars length
24
 *    $g->setKeysModel(3,9,'abcdefghijklmnopqrstuvwxyz');
25
 *    $g->setValuesModel(0,100); //random numeric values range from 0 to 100
26
 *    $arr = $g->genRandomArray(10,15,0); //generate 10-15 elements (not nested)
27
 *    print_r($arr);
28
 *
29
 */
30
class RandomArray extends RandomStr
31
{
32
    /**
33
     * Set this limit to avoid generation unexpected too large arrays
34
     *
35
     * @var integer
36
     */
37
    public $lim_elements = 10000;
38
    
39
     /**
40
     * Model number for generation random Keys for Arrays
41
     * if 0 then array keys will be simple 1,2,3... numeric
42
     * if 1 then array keys will be numeric from min_arr_key to max_arr_key
43
     * if 2 then array keys will be string len from min_arr_key to max_arr_key
44
     * This value setting by function setKeysModel()
45
     *
46
     * @var integer
47
     */
48
    protected $keys_model;
49
50
    /**
51
     * Model number for generation random Values for Arrays
52
     * if 0 then array values will be numeric from 0 to 65535
53
     * if 1 then array values will be numeric from min_arr_val to max_arr_val
54
     * if 2 then array values will be string len from min_arr_val to max_arr_val
55
     *  This value setting by function setValuesModel()
56
     *
57
     * @var integer
58
     */
59
    protected $values_model;
60
    
61
    /**
62
     * Value for generation random Keys for Arrays
63
     * This is minimal number for random numbers generation,
64
     * or minimal length of string for random string array-keys generation
65
     * This value setting by function setValuesModel()
66
     *
67
     * @var integer
68
     */
69
    protected $min_arr_key;
70
71
    /**
72
     * Value for generation random Keys for Arrays
73
     * This is maximal number for random numbers generation,
74
     * or maximal length of string for random string array-keys generation
75
     * This value setting by function setKeysModel()
76
     *
77
     * @var integer
78
     */
79
    protected $max_arr_key;
80
81
    /**
82
     * Value for generation random Values for Arrays
83
     * This is minimal number for random numbers generation,
84
     * or minimal length of string for random string array-values generation
85
     * This value setting by function setValuesModel()
86
     *
87
     * @var integer
88
     */
89
    protected $min_arr_val;
90
    
91
    /**
92
     * Value for generation random Values for Arrays
93
     * This is maximal number for random numbers generation,
94
     * or maximal length of string for random string array-values generation
95
     *
96
     * @var integer
97
     */
98
    protected $max_arr_val;
99
    
100
    /**
101
     * Value generate function
102
     * calling if values_model == 3
103
     *
104
     * @var callable
105
     */
106
    public $fn_gen_value;
107
    
108
    /**
109
     * Key generate function
110
     * calling if keys_model == 3
111
     *
112
     * @var callable
113
     */
114
    public $fn_gen_key;
115
116
    /**
117
     * Init parameter - string of chars for generation array values
118
     * Prefer to leave blank and use function setValuesModel for set it.
119
     *
120
     * @param string|null $init_charset_for_val
121
     */
122
    public function __construct($init_charset_for_val = null, $utf8mode = false)
123
    {
124
        parent::__construct($init_charset_for_val, $utf8mode);
125
        $this->setKeysModel();
126
        if (\is_null($init_charset_for_val)) {
127
            $this->setValuesModel(1, 16, $this->char_sets[0]);
128
        } else {
129
            $this->setValuesModel(1, 16, $init_charset_for_val);
130
        }
131
    }
132
133
    /**
134
     * Counting all values in array (recursive)
135
     *
136
     * @param array   $arr
137
     * @param integer $cnt
138
     *
139
     * @return integer
140
     */
141
    public function countArrayValuesRecursive(&$arr, $cnt = 0)
142
    {
143
        \array_walk_recursive($arr, function ($v, $k) use (&$cnt) {
0 ignored issues
show
Unused Code introduced by
The parameter $v is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

143
        \array_walk_recursive($arr, function (/** @scrutinizer ignore-unused */ $v, $k) use (&$cnt) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $k is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

143
        \array_walk_recursive($arr, function ($v, /** @scrutinizer ignore-unused */ $k) use (&$cnt) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
144
            $cnt++;
145
        });
146
        return $cnt;
147
    }
148
    
149
    /**
150
     * Counting the maximum depth of nesting of arrays in an array (recursive)
151
     *
152
     * @param array $arr
153
     * @param integer $c_depth
154
     *
155
     * @return integer
156
     */
157
    public function countArrayMaxDepth($arr, $c_depth = 0)
158
    {
159
        if (!is_array($arr)) {
0 ignored issues
show
introduced by
The condition is_array($arr) is always true.
Loading history...
160
            return false;
161
        }
162
        $m_depth = $c_depth;
163
        \array_walk($arr, function ($v, $k) use ($c_depth, &$m_depth) {
0 ignored issues
show
Unused Code introduced by
The parameter $k is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

163
        \array_walk($arr, function ($v, /** @scrutinizer ignore-unused */ $k) use ($c_depth, &$m_depth) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
164
            if (is_array($v)) {
165
                $new_depth = $this->countArrayMaxDepth($v, $c_depth+1);
166
                if ($new_depth > $m_depth) {
167
                    $m_depth = $new_depth;
168
                }
169
            }
170
        });
171
        return $m_depth;
172
    }
173
    
174
    /**
175
     * Set model for generation keys for random arrays
176
     *
177
     * @param integer      $min
178
     * @param integer      $max
179
     * @param string|null  $chars
180
     */
181
    public function setKeysModel(
182
        $min = 1,
183
        $max = null,
184
        $chars = null,
185
        $utf8mode = false
186
    ) {
187
        if (empty($chars)) {
188
            //Numeric keys model
189
            $this->keys_model = 1;
190
            if ($min == 1 && (\is_null($max))) {
191
                //Non-changes key model (numeric 0,1,2...)
192
                $this->keys_model = 0;
193
            }
194
            if (\is_null($max)) {
195
                $max = 65535;
196
            }
197
        } else {
198
            //Random-string keys model
199
            $this->keys_model = 2;
200
            //set $chars as charset number 1
201
            $this->char_sets[1] = $chars;
202
            if ($utf8mode) {
203
                $this->explodeUtf8();
204
            }
205
        }
206
        $this->min_arr_key = $min;
207
        $this->max_arr_key = is_null($max) ? 16 : $max;
208
    }
209
    
210
    /**
211
     * Set model for generation values for random arrays
212
     *
213
     * @param integer     $min
214
     * @param integer     $max
215
     * @param string|null $chars
216
     */
217
    public function setValuesModel(
218
        $min = 0,
219
        $max = 65535,
220
        $chars = null,
221
        $utf8mode = false
222
    ) {
223
        if (empty($chars)) {
224
            //Numeric values model
225
            $this->values_model = 1;
226
            if (!$min && $max==65535) {
227
                //Non-changes values model (random number from 0 to 65535)
228
                $this->values_model=0;
229
            }
230
        } else {
231
            //Random-string values model
232
            $this->values_model = 2;
233
            //set $chars as charset number 2
234
            $this->char_sets[2] = $chars;
235
            if ($utf8mode) {
236
                $this->explodeUtf8();
237
            }
238
        }
239
        $this->min_arr_val = $min;
240
        $this->max_arr_val = $max;
241
    }
242
    
243
    /**
244
     * Set function for generate values for random array
245
     *
246
     * @param callable $gen_fn
247
     */
248
    public function setValuesModelFn(callable $gen_fn)
249
    {
250
        $this->values_model = 3;
251
        $this->fn_gen_value = $gen_fn;
252
    }
253
254
    /**
255
     * Set function for generate keys for random array
256
     *
257
     * @param callable $gen_fn
258
     */
259
    public function setKeysModelFn(callable $gen_fn)
260
    {
261
        $this->keys_model = 3;
262
        $this->fn_gen_key = $gen_fn;
263
    }
264
265
    /**
266
     * Random Array generate
267
     *
268
     * Parameters $min_elem_cnt and $max_elem_cnt define the minimum and
269
     *   maximum number of elements of generated arrays
270
     *
271
     * Parameter $theshold define chance of generating scalar or nested array
272
     * If 0 is specified, scalar will always be generated, never nested array
273
     * if 65535 specified, nested array will be generated until reach $lim_depth
274
     * if 32768 specified the probability of generating array or scalar is 50/50
275
     * Only scalar generate if the depth of array nesting reached $lim_depth
276
     *
277
     * No more than $lim_elements of elements will be generated total
278
     *
279
     * @param integer $min_elem_cnt Min.count of elements in array (and nested)
280
     * @param integer $max_elem_cnt Max.count of elements in array (and nested)
281
     * @param integer $threshold Chance array or string generation (0-65535)
282
     * @param integer $lim_depth Depth limit of nesting arrays
283
     * @param integer $lim_elements Limit number of generated elements
284
     * @param string  $root Key of this array (may be needed for nested arrays)
285
     *
286
     * @return array
287
     */
288
    public function genRandomArray(
289
        $min_elem_cnt = 3,
290
        $max_elem_cnt = 10,
291
        $threshold = 32768,
292
        $lim_depth = 3,
293
        $lim_elements = 10000,
294
        $root = ''
295
    ) {
296
        if ($lim_elements) {
297
            $this->lim_elements = $lim_elements;
298
        }
299
        if ($lim_depth<1
300
            || $this->lim_elements < 0
301
            || $this->max_arr_key < 0
302
            || $this->max_arr_key < $this->min_arr_key
303
            || $this->max_arr_val < 0
304
            || $this->max_arr_val < $this->min_arr_val
305
        ) {
306
            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 array.
Loading history...
307
        }
308
309
        $elem_cnt = mt_rand($min_elem_cnt, $max_elem_cnt);
310
        if ($elem_cnt > $this->lim_elements) {
311
            $elem_cnt = $this->lim_elements;
312
        }
313
        $r_arr = [];
314
        $gen_arr = \unpack('v*', \call_user_func($this->rnd_fn, $elem_cnt*2));
315
        $this->lim_elements-=$elem_cnt;
316
        
317
        foreach ($gen_arr as $k => $v) {
318
            if ($v > $threshold || $lim_depth<2 || $this->lim_elements <2) {
319
                if ($this->values_model) {
320
                    if ($this->values_model == 3) {
321
                        $v = \call_user_func($this->fn_gen_value,
322
                            \compact('k', 'v', 'threshold', 'lim_depth', 'root')
323
                        );
324
                    } else {
325
                        $v = mt_rand($this->min_arr_val, $this->max_arr_val);
326
                        if ($this->values_model == 2) {
327
                            $v = $this->genRandomStr($v, 2);
328
                        }
329
                    }
330
                } else {
331
                    if (!$this->keys_model) {
332
                        continue;
333
                    }
334
                }
335
            } else {
336
                $v = $this->genRandomArray(
337
                    $min_elem_cnt,
338
                    $max_elem_cnt,
339
                    $threshold,
340
                    $lim_depth - 1,
341
                    0
342
                );
343
            }
344
            if ($this->keys_model) {
345
                if ($this->keys_model === 3) {
346
                    $k = \call_user_func($this->fn_gen_key,
347
                            \compact('k', 'v', 'threshold', 'lim_depth', 'root')
348
                        );
349
                } else {
350
                    $k = \mt_rand($this->min_arr_key, $this->max_arr_key);
351
                    if ($this->keys_model === 2) {
352
                        $k = $this->genRandomStr($k, 1);
353
                    }
354
                }
355
                $r_arr[$k] = $v;
356
            } else {
357
                $gen_arr[$k] = $v;
358
            }
359
        }
360
        
361
        return $this->keys_model ? $r_arr : $gen_arr;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->keys_model ? $r_arr : $gen_arr could also return false which is incompatible with the documented return type array. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
362
    }
363
}
364