Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 156 |
|
0.00% |
0 / 21 |
CRAP | |
0.00% |
0 / 1 |
ajax_iohandler | |
0.00% |
0 / 156 |
|
0.00% |
0 / 21 |
3540 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
2 | |||
get_input | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
get_raw_input | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
get_server_variable | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
get_header_variable | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
is_secure | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
add_user_form_group | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
generate_form_render_data | |
0.00% |
0 / 40 |
|
0.00% |
0 / 1 |
272 | |||
send_response | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
prepare_json_array | |
0.00% |
0 / 46 |
|
0.00% |
0 / 1 |
240 | |||
set_progress | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
request_refresh | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
set_active_stage_menu | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
set_finished_stage_menu | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
set_cookie | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
add_download_link | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
render_update_file_status | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
30 | |||
redirect | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
acquire_lock | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
release_lock | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
lang_replace_callback | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * |
4 | * This file is part of the phpBB Forum Software package. |
5 | * |
6 | * @copyright (c) phpBB Limited <https://www.phpbb.com> |
7 | * @license GNU General Public License, version 2 (GPL-2.0) |
8 | * |
9 | * For full copyright and license information, please see |
10 | * the docs/CREDITS.txt file. |
11 | * |
12 | */ |
13 | |
14 | namespace phpbb\install\helper\iohandler; |
15 | |
16 | use phpbb\path_helper; |
17 | use phpbb\routing\router; |
18 | |
19 | /** |
20 | * Input-Output handler for the AJAX frontend |
21 | */ |
22 | class ajax_iohandler extends iohandler_base |
23 | { |
24 | /** |
25 | * @var path_helper |
26 | */ |
27 | protected $path_helper; |
28 | |
29 | /** |
30 | * @var \phpbb\request\request_interface |
31 | */ |
32 | protected $request; |
33 | |
34 | /** |
35 | * @var \phpbb\template\template |
36 | */ |
37 | protected $template; |
38 | |
39 | /** |
40 | * @var router |
41 | */ |
42 | protected $router; |
43 | |
44 | /** |
45 | * @var string |
46 | */ |
47 | protected $phpbb_root_path; |
48 | |
49 | /** |
50 | * @var string |
51 | */ |
52 | protected $file_status; |
53 | |
54 | /** |
55 | * @var string |
56 | */ |
57 | protected $form; |
58 | |
59 | /** |
60 | * @var bool |
61 | */ |
62 | protected $request_client_refresh; |
63 | |
64 | /** |
65 | * @var array |
66 | */ |
67 | protected $nav_data; |
68 | |
69 | /** |
70 | * @var array |
71 | */ |
72 | protected $cookies; |
73 | |
74 | /** |
75 | * @var array |
76 | */ |
77 | protected $download; |
78 | |
79 | /** |
80 | * @var array |
81 | */ |
82 | protected $redirect_url; |
83 | |
84 | /** |
85 | * @var resource |
86 | * @psalm-var resource|closed-resource |
87 | */ |
88 | protected $file_lock_pointer; |
89 | |
90 | /** |
91 | * Constructor |
92 | * |
93 | * @param path_helper $path_helper |
94 | * @param \phpbb\request\request_interface $request HTTP request interface |
95 | * @param \phpbb\template\template $template Template engine |
96 | * @param router $router Router |
97 | * @param string $root_path Path to phpBB's root |
98 | */ |
99 | public function __construct(path_helper $path_helper, \phpbb\request\request_interface $request, \phpbb\template\template $template, router $router, string $root_path) |
100 | { |
101 | $this->path_helper = $path_helper; |
102 | $this->request = $request; |
103 | $this->router = $router; |
104 | $this->template = $template; |
105 | $this->form = ''; |
106 | $this->nav_data = array(); |
107 | $this->cookies = array(); |
108 | $this->download = array(); |
109 | $this->redirect_url = array(); |
110 | $this->file_status = ''; |
111 | $this->phpbb_root_path = $root_path; |
112 | |
113 | parent::__construct(); |
114 | } |
115 | |
116 | /** |
117 | * {@inheritdoc} |
118 | */ |
119 | public function get_input($name, $default, $multibyte = false) |
120 | { |
121 | return $this->request->variable($name, $default, $multibyte); |
122 | } |
123 | |
124 | /** |
125 | * {@inheritdoc} |
126 | */ |
127 | public function get_raw_input($name, $default) |
128 | { |
129 | return $this->request->raw_variable($name, $default); |
130 | } |
131 | |
132 | /** |
133 | * {@inheritdoc} |
134 | */ |
135 | public function get_server_variable($name, $default = '') |
136 | { |
137 | return $this->request->server($name, $default); |
138 | } |
139 | |
140 | /** |
141 | * {@inheritdoc} |
142 | */ |
143 | public function get_header_variable($name, $default = '') |
144 | { |
145 | return $this->request->header($name, $default); |
146 | } |
147 | |
148 | /** |
149 | * {@inheritdoc} |
150 | */ |
151 | public function is_secure() |
152 | { |
153 | return $this->request->is_secure(); |
154 | } |
155 | |
156 | /** |
157 | * {@inheritdoc} |
158 | */ |
159 | public function add_user_form_group($title, $form) |
160 | { |
161 | $this->form = $this->generate_form_render_data($title, $form); |
162 | } |
163 | |
164 | /** |
165 | * {@inheritdoc} |
166 | */ |
167 | public function generate_form_render_data($title, $form) |
168 | { |
169 | $this->template->assign_block_vars('options', array( |
170 | 'LEGEND' => $this->language->lang($title), |
171 | 'S_LEGEND' => true, |
172 | )); |
173 | |
174 | $not_button_form = false; |
175 | |
176 | foreach ($form as $input_name => $input_options) |
177 | { |
178 | if (!isset($input_options['type'])) |
179 | { |
180 | continue; |
181 | } |
182 | |
183 | $tpl_ary = array(); |
184 | $not_button_form = ($input_options['type'] !== 'submit' || $not_button_form); |
185 | |
186 | $tpl_ary['TYPE'] = $input_options['type']; |
187 | $tpl_ary['TITLE'] = $this->language->lang($input_options['label']); |
188 | $tpl_ary['KEY'] = $input_name; |
189 | $tpl_ary['S_EXPLAIN'] = false; |
190 | $tpl_ary['DISABLED'] = isset($input_options['disabled']) ? $input_options['disabled'] : false; |
191 | $tpl_ary['IS_SECONDARY'] = isset($input_options['is_secondary']) ? $input_options['is_secondary'] : false; |
192 | |
193 | if (isset($input_options['default'])) |
194 | { |
195 | $default = $input_options['default']; |
196 | $default = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', array($this, 'lang_replace_callback'), $default); |
197 | $tpl_ary['DEFAULT'] = $default; |
198 | } |
199 | |
200 | if (isset($input_options['description'])) |
201 | { |
202 | $tpl_ary['TITLE_EXPLAIN'] = $this->language->lang($input_options['description']); |
203 | $tpl_ary['S_EXPLAIN'] = true; |
204 | } |
205 | |
206 | if (in_array($input_options['type'], array('select', 'radio'), true)) |
207 | { |
208 | for ($i = 0, $total = count($input_options['options']); $i < $total; $i++) |
209 | { |
210 | if (isset($input_options['options'][$i]['label'])) |
211 | { |
212 | $input_options['options'][$i]['label'] = $this->language->lang($input_options['options'][$i]['label']); |
213 | } |
214 | } |
215 | |
216 | $tpl_ary['OPTIONS'] = $input_options['options']; |
217 | } |
218 | |
219 | $block_name = ($input_options['type'] === 'submit') ? 'submit_buttons' : 'options'; |
220 | $this->template->assign_block_vars($block_name, $tpl_ary); |
221 | } |
222 | |
223 | if (isset($form['database_update_submit']) && !$form['database_update_submit']['disabled']) |
224 | { |
225 | $this->template->assign_var('FORM_TITLE', $this->language->lang('UPDATE_CONTINUE_UPDATE_PROCESS')); |
226 | } |
227 | |
228 | $this->template->assign_var('S_NOT_ONLY_BUTTON_FORM', $not_button_form); |
229 | |
230 | if (!$not_button_form) |
231 | { |
232 | $this->template->destroy_block_vars('options'); |
233 | } |
234 | |
235 | $this->template->set_filenames(array( |
236 | 'form_install' => 'installer_form.html', |
237 | )); |
238 | |
239 | $compiled_template = $this->template->assign_display('form_install'); |
240 | |
241 | return is_string($compiled_template) ? $compiled_template : ''; |
242 | } |
243 | |
244 | /** |
245 | * {@inheritdoc} |
246 | */ |
247 | public function send_response($no_more_output = false) |
248 | { |
249 | $json_data_array = $this->prepare_json_array($no_more_output); |
250 | |
251 | if (empty($json_data_array)) |
252 | { |
253 | return; |
254 | } |
255 | |
256 | $json_data = json_encode($json_data_array); |
257 | |
258 | // Try to push content to the browser |
259 | print(str_pad(' ', 4096) . "\n"); |
260 | print($json_data . "\n\n"); |
261 | flush(); |
262 | } |
263 | |
264 | /** |
265 | * Prepares iohandler's data to be sent out to the client. |
266 | * |
267 | * @param bool $no_more_output Whether or not there will be more output in this response |
268 | * |
269 | * @return array |
270 | */ |
271 | protected function prepare_json_array($no_more_output = false) |
272 | { |
273 | $json_array = array(); |
274 | |
275 | if (!empty($this->errors)) |
276 | { |
277 | $json_array['errors'] = $this->errors; |
278 | $this->errors = array(); |
279 | } |
280 | |
281 | if (!empty($this->warnings)) |
282 | { |
283 | $json_array['warnings'] = $this->warnings; |
284 | $this->warnings = array(); |
285 | } |
286 | |
287 | if (!empty($this->logs)) |
288 | { |
289 | $json_array['logs'] = $this->logs; |
290 | $this->logs = array(); |
291 | } |
292 | |
293 | if (!empty($this->success)) |
294 | { |
295 | $json_array['success'] = $this->success; |
296 | $this->success = array(); |
297 | } |
298 | |
299 | if (!empty($this->download)) |
300 | { |
301 | $json_array['download'] = $this->download; |
302 | $this->download = array(); |
303 | } |
304 | |
305 | if (!empty($this->form)) |
306 | { |
307 | $json_array['form'] = $this->form; |
308 | $this->form = ''; |
309 | } |
310 | |
311 | if (!empty($this->file_status)) |
312 | { |
313 | $json_array['file_status'] = $this->file_status; |
314 | $this->file_status = ''; |
315 | } |
316 | |
317 | // If current task name is set, we push progress message to the client side |
318 | if (!empty($this->current_task_name)) |
319 | { |
320 | $json_array['progress'] = array( |
321 | 'task_name' => $this->current_task_name, |
322 | 'task_num' => $this->current_task_progress, |
323 | 'task_count' => $this->task_progress_count, |
324 | ); |
325 | |
326 | if ($this->restart_progress_bar) |
327 | { |
328 | $json_array['progress']['restart'] = 1; |
329 | $this->restart_progress_bar = false; |
330 | } |
331 | } |
332 | |
333 | if (!empty($this->nav_data)) |
334 | { |
335 | $json_array['nav'] = $this->nav_data; |
336 | $this->nav_data = array(); |
337 | } |
338 | |
339 | if ($this->request_client_refresh) |
340 | { |
341 | $json_array['refresh'] = true; |
342 | $this->request_client_refresh = false; |
343 | } |
344 | |
345 | if (!empty($this->cookies)) |
346 | { |
347 | $json_array['cookies'] = $this->cookies; |
348 | $this->cookies = array(); |
349 | } |
350 | |
351 | if (!empty($this->redirect_url)) |
352 | { |
353 | $json_array['redirect'] = $this->redirect_url; |
354 | $this->redirect_url = array(); |
355 | } |
356 | |
357 | if ($no_more_output) |
358 | { |
359 | $json_array['over'] = true; |
360 | } |
361 | |
362 | return $json_array; |
363 | } |
364 | |
365 | /** |
366 | * {@inheritdoc} |
367 | */ |
368 | public function set_progress($task_lang_key, $task_number) |
369 | { |
370 | parent::set_progress($task_lang_key, $task_number); |
371 | $this->send_response(); |
372 | } |
373 | |
374 | /** |
375 | * {@inheritdoc} |
376 | */ |
377 | public function request_refresh() |
378 | { |
379 | $this->request_client_refresh = true; |
380 | } |
381 | |
382 | /** |
383 | * {@inheritdoc} |
384 | */ |
385 | public function set_active_stage_menu($menu_path) |
386 | { |
387 | $this->nav_data['active'] = $menu_path[count($menu_path) - 1]; |
388 | $this->send_response(); |
389 | } |
390 | |
391 | /** |
392 | * {@inheritdoc} |
393 | */ |
394 | public function set_finished_stage_menu($menu_path) |
395 | { |
396 | $this->nav_data['finished'][] = $menu_path[count($menu_path) - 1]; |
397 | $this->send_response(); |
398 | } |
399 | |
400 | /** |
401 | * {@inheritdoc} |
402 | */ |
403 | public function set_cookie($cookie_name, $cookie_value) |
404 | { |
405 | $this->cookies[] = array( |
406 | 'name' => $cookie_name, |
407 | 'value' => $cookie_value |
408 | ); |
409 | } |
410 | |
411 | /** |
412 | * {@inheritdoc} |
413 | */ |
414 | public function add_download_link($route, $title, $msg = null) |
415 | { |
416 | $link_properties = array( |
417 | 'href' => $this->router->generate($route), |
418 | 'title' => $this->language->lang($title), |
419 | 'download' => $this->language->lang('DOWNLOAD'), |
420 | ); |
421 | |
422 | if ($msg !== null) |
423 | { |
424 | $link_properties['msg'] = html_entity_decode($this->language->lang($msg), ENT_COMPAT); |
425 | } |
426 | |
427 | $this->download[] = $link_properties; |
428 | } |
429 | |
430 | /** |
431 | * {@inheritdoc} |
432 | */ |
433 | public function render_update_file_status($status_array) |
434 | { |
435 | foreach ($status_array as $block => $list) |
436 | { |
437 | foreach ($list as $filename) |
438 | { |
439 | $dirname = dirname($filename); |
440 | |
441 | $this->template->assign_block_vars($block, array( |
442 | 'STATUS' => $block, |
443 | 'FILENAME' => $filename, |
444 | 'DIR_PART' => (!empty($dirname) && $dirname !== '.') ? dirname($filename) . '/' : false, |
445 | 'FILE_PART' => basename($filename), |
446 | )); |
447 | } |
448 | } |
449 | |
450 | $this->template->set_filenames(array( |
451 | 'file_status' => 'installer_update_file_status.html', |
452 | )); |
453 | |
454 | $this->file_status = $this->template->assign_display('file_status'); |
455 | } |
456 | |
457 | /** |
458 | * {@inheritdoc} |
459 | */ |
460 | public function redirect($url, $use_ajax = false) |
461 | { |
462 | $this->redirect_url = array('url' => $url, 'use_ajax' => $use_ajax); |
463 | $this->send_response(true); |
464 | } |
465 | |
466 | /** |
467 | * Acquires a file lock |
468 | */ |
469 | public function acquire_lock() |
470 | { |
471 | $lock_file = $this->phpbb_root_path . 'store/io_lock.lock'; |
472 | $this->file_lock_pointer = @fopen($lock_file, 'w+'); |
473 | |
474 | if ($this->file_lock_pointer) |
475 | { |
476 | flock($this->file_lock_pointer, LOCK_EX); |
477 | } |
478 | } |
479 | |
480 | /** |
481 | * Release file lock |
482 | */ |
483 | public function release_lock() |
484 | { |
485 | if ($this->file_lock_pointer) |
486 | { |
487 | fwrite($this->file_lock_pointer, 'ok'); |
488 | flock($this->file_lock_pointer, LOCK_UN); |
489 | fclose($this->file_lock_pointer); |
490 | } |
491 | } |
492 | |
493 | /** |
494 | * Callback function for language replacing |
495 | * |
496 | * @param array $matches |
497 | * @return string |
498 | */ |
499 | public function lang_replace_callback($matches) |
500 | { |
501 | if (!empty($matches[1])) |
502 | { |
503 | return $this->language->lang($matches[1]); |
504 | } |
505 | |
506 | return ''; |
507 | } |
508 | } |