Issues (12)

src/RandomToFile.php (1 issue)

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'];
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
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
        if ($lim_depth < 1
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
            if ($v > $threshold || $lim_depth < 2 || $this->lim_elements < 2) {
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) {
0 ignored issues
show
$oh is of type null|resource, thus it always evaluated to false.
Loading history...
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;
275
        }
276
    }
277
}
278