Passed
Push — master ( 697e18...d2ffa6 )
by Alexander
02:44
created

RandomToFile::genTempFileName()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 7
nc 2
nop 2
dl 0
loc 11
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
namespace ierusalim\Random;
4
5
/**
6
 * This class contains RandomToFile
7
 *
8
 * PHP Version 5.6
9
 *
10
 * @package    ierusalim\RandomToFile
11
 * @author     Alexander Jer <[email protected]>
12
 * @copyright  2017, Ierusalim
13
 * @license    https://opensource.org/licenses/Apache-2.0 Apache-2.0
14
 */
15
class RandomToFile extends RandomArray
16
{
17
    /**
18
     * Function for processing data and output to a file
19
     *
20
     * @var callable
21
     */
22
    public $fn_file_output;
23
    
24
    /**
25
     * File name for data output
26
     *
27
     * @var string
28
     */
29
    public $full_file_name;
30
    
31
    /**
32
     * Handler of file opened for write
33
     *
34
     * @var resource|null
35
     */
36
    public $file_handler;
37
    
38
    /**
39
     * Default extention for make file names
40
     *
41
     * @var string
42
     */
43
    public $default_ext = '.json';
44
45
    /**
46
     * Main parameter of this class - function for processing and write data
47
     * By default, this hook is set as a function 'writeFileOutputExample',
48
     * which does the following function: output PHP code for assigning array.
49
     * By analogy, write the necessary output functions for the desired format
50
     *
51
     * @param callable|null $fn_write
52
     */
53
    public function __construct(callable $fn_write = null)
54
    {
55
        parent::__construct();
56
        if (is_null($fn_write)) {
57
            $this->fn_file_output = [$this, 'writeFileOutputExample'];
0 ignored issues
show
Documentation Bug introduced by
It seems like array($this, 'writeFileOutputExample') of type array<integer,string|ier...im\Random\RandomToFile> is incompatible with the declared type callable of property $fn_file_output.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
58
            $this->default_ext = '.php';
59
        } else {
60
            $this->fn_file_output = $fn_write;
61
        }
62
    }
63
64
    public function writeFileOutputExample($parr)
65
    {
66
        static $keys = [];
67
68
        //extracting following work variables:
69
        \extract($parr); //$signal, $k, $v, $lim_depth, $root
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
70
71
        //begin formin output string
72
        $out_str = '$x';
73
74
        switch ($signal) {
75
            //siglan 'next' - when output next scalar element of array [$k]=>$v
76
            case 'next':
77
                if (!\is_numeric($k)) {
78
                    $k = "'" . \addcslashes($k, "'\\") . "'";
79
                }
80
                if (!\is_numeric($v)) {
81
                    $v = "'" . \addcslashes($v, "'\\") . "'";
82
                }
83
                $out_str .= (count($keys) ?
84
                    '[' . implode('][', $keys) . ']'
85
                    :
86
                    ''
87
                    ) . '[' . $k . ']=' . $v . ";\r\n";
88
89
                break;
90
            
91
            //signal 'open' - when root or nested array beginning
92
            case 'open':
93
                if (count($keys) || !empty($root)) {
94
                    //nested array beginned
95
                    if (!is_numeric($root)) {
96
                        $root = "'" . \addcslashes($root, "'\\") . "'";
97
                    }
98
                    array_push($keys, $root);
99
                    $out_str .= '[' . implode('][', $keys) . ']';
100
                    $out_str .= "=[]; /* Create sub-array in key $out_str */\r\n";
101
                } else {
102
                    //root array beginned
103
                    $out_str .= "=[]; /* CREATE ROOT OF ARRAY */\r\n";
104
                    $out_str = '<' . "?php\n" . $out_str;
105
                }
106
                break;
107
                
108
            //signal 'close' - when root or nested array ended
109
            case 'close':
110
                if (count($keys)) {
111
                    //nested array ended
112
                    $out_str = "/* end $out_str"
113
                                .'[' . \implode('][', $keys) . ']'
114
                                . "*/\r\n";
115
                    \array_pop($keys);
116
                } else {
117
                    //root array ended
118
                    $out_str = " /*  END OF ARRAY */\r\n";
119
                }
120
                break;
121
122
            //signal 'init' - when file open for write
123
            case 'init':
124
                $keys = [];
125
                $out_str = '';
126
        }
127
        //write formed string to output file
128
        \fwrite($fh, $out_str);
129
    }
130
    
131
    public function genRandomToFile(
132
        $min_elem_cnt = 3,
133
        $max_elem_cnt = 10,
134
        $threshold = 32768,
135
        $lim_depth = 3,
136
        $lim_elements = 10000,
137
        $root = ''
138
    ) {
139
        if ($lim_elements) {
140
            $this->lim_elements = $lim_elements;
141
        }
142 View Code Duplication
        if ($lim_depth < 1
0 ignored issues
show
Duplication introduced by
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...
143
            || $this->lim_elements < 0
144
            || $this->max_arr_key < 0
145
            || $this->max_arr_key < $this->min_arr_key
146
            || $this->max_arr_val < 0
147
            || $this->max_arr_val < $this->min_arr_val
148
        ) {
149
            return false;
150
        }
151
        
152
        if (!$oh = $fh = $this->file_handler) {
153
            $this->openOutputFile();
154
            $fh = $this->file_handler;
155
            $signal = 'init';
156
            \call_user_func($this->fn_file_output,
157
                \compact('signal', 'fh', 'threshold', 'lim_depth', 'root')
158
            );
159
        }
160
161
        $elem_cnt = mt_rand($min_elem_cnt, $max_elem_cnt);
162
        if ($elem_cnt > $this->lim_elements) {
163
            $elem_cnt = $this->lim_elements;
164
        }
165
166
        $this->lim_elements -= $elem_cnt;
167
        
168
        $signal = 'open';
169
        \call_user_func($this->fn_file_output,
170
            \compact('signal', 'fh', 'elem_cnt', 'lim_depth', 'root')
171
        );
172
         
173
        $signal = 'next';
174
175
        foreach ($this->genBigRange($elem_cnt) as $k => $v) {
176
            if ($this->keys_model) {
177
                if ($this->keys_model === 3) {
178
                    $k = \call_user_func($this->fn_gen_key,
179
                        \compact('k', 'v', 'threshold', 'lim_depth', 'root')
180
                        );
181
                } else {
182
                    $k = \mt_rand($this->min_arr_key, $this->max_arr_key);
183
                    if ($this->keys_model === 2) {
184
                        $k = $this->genRandomStr($k, 1);
185
                    }
186
                }
187
            }
188
            
189 View Code Duplication
            if ($v > $threshold || $lim_depth < 2 || $this->lim_elements < 2) {
0 ignored issues
show
Duplication introduced by
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...
190
                if ($this->values_model) {
191
                    if ($this->values_model == 3) {
192
                        $v = \call_user_func($this->fn_gen_value,
193
                            \compact('k', 'v', 'threshold', 'lim_depth', 'root')
194
                        );
195
                    } else {
196
                        $v = mt_rand($this->min_arr_val, $this->max_arr_val);
197
                        if ($this->values_model == 2) {
198
                            $v = $this->genRandomStr($v, 2);
199
                        }
200
                    }
201
                }
202
            } else {
203
                $this->genRandomToFile(
204
                    $min_elem_cnt,
205
                    $max_elem_cnt,
206
                    $threshold,
207
                    $lim_depth - 1,
208
                    0,
209
                    $k
210
                );
211
                continue;
212
            }
213
214
            \call_user_func($this->fn_file_output,
215
                \compact('signal', 'k', 'v', 'fh', 'lim_depth', 'root')
216
            );
217
        }
218
219
        $signal = 'close';
220
            \call_user_func($this->fn_file_output,
221
            \compact('signal', 'fh', 'elem_cnt', 'lim_depth', 'root')
222
            );
223
224
        if (!$oh) {
225
            $this->closeOutputFile();
226
        }
227
        return true;
228
    }
229
230
    public function genBigRange($total_elements)
231
    {
232
        for ($k = 1; $k <= $total_elements; $k++) {
233
            $v = \mt_rand(0, 65535);
234
            yield $k => $v;
235
        }
236
    }
237
238
    public function genTempFileName($ext = null, $test_exception = false)
239
    {
240
        $file_name = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'genRandom';
241
        if ($test_exception || (!is_dir($file_name) && !\mkdir($file_name))) {
242
            throw new \Exception("Can't mkdir $file_name for random file");
243
        }
244
        if (is_null($ext)) {
245
            $ext = $this->default_ext;
246
        }
247
        $file_name .= DIRECTORY_SEPARATOR . md5(microtime()) . $ext;
248
        return $file_name;
249
    }
250
251
    public function setOutputFile($file_name = null, $ext = null)
252
    {
253
        if (empty($file_name) || !is_string($file_name)) {
254
            if (is_null($ext)) {
255
                $ext = $this->default_ext;
256
            }
257
            $file_name = $this->genTempFileName($ext);
258
        }
259
        return $this->full_file_name = $file_name;
260
    }
261
262
    public function openOutputFile()
263
    {
264
        if (!$this->file_handler = @\fopen($this->full_file_name, 'w')) {
265
            throw new \Exception("Error write file " . $this->full_file_name);
266
        }
267
        return $this->file_handler;
268
    }
269
270
    public function closeOutputFile()
271
    {
272
        if ($this->file_handler) {
273
            \fclose($this->file_handler);
274
            $this->file_handler = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type resource|null of property $file_handler.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
275
        }
276
    }
277
}
278