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) { |
|
|
|
|
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
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.