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; |
||
0 ignored issues
–
show
|
|||
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')) { |
||
0 ignored issues
–
show
It seems like
@fopen($this->full_file_name, 'w') can also be of type false . However, the property $file_handler is declared as type null|resource . Maybe add an additional type check?
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 Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||
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
It seems like
false of type false is incompatible with the declared type null|resource 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.. ![]() |
|||
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.