Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 21
CRAP
0.00% covered (danger)
0.00%
0 / 260
ajax_iohandler
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 21
3422.00
0.00% covered (danger)
0.00%
0 / 260
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 14
 get_input
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 get_raw_input
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 get_server_variable
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 get_header_variable
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 is_secure
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 add_user_form_group
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 generate_form_render_data
0.00% covered (danger)
0.00%
0 / 1
240.00
0.00% covered (danger)
0.00%
0 / 59
 send_response
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 11
 prepare_json_array
0.00% covered (danger)
0.00%
0 / 1
240.00
0.00% covered (danger)
0.00%
0 / 76
 set_progress
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 4
 request_refresh
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 set_active_stage_menu
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 4
 set_finished_stage_menu
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 4
 set_cookie
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 6
 add_download_link
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 12
 render_update_file_status
0.00% covered (danger)
0.00%
0 / 1
30.00
0.00% covered (danger)
0.00%
0 / 22
 redirect
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 4
 acquire_lock
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 8
 release_lock
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 8
 lang_replace_callback
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 7
<?php
/**
 *
 * This file is part of the phpBB Forum Software package.
 *
 * @copyright (c) phpBB Limited <https://www.phpbb.com>
 * @license GNU General Public License, version 2 (GPL-2.0)
 *
 * For full copyright and license information, please see
 * the docs/CREDITS.txt file.
 *
 */
namespace phpbb\install\helper\iohandler;
use phpbb\path_helper;
use phpbb\routing\router;
/**
 * Input-Output handler for the AJAX frontend
 */
class ajax_iohandler extends iohandler_base
{
    /**
     * @var path_helper
     */
    protected $path_helper;
    /**
     * @var \phpbb\request\request_interface
     */
    protected $request;
    /**
     * @var \phpbb\template\template
     */
    protected $template;
    /**
     * @var router
     */
    protected $router;
    /**
     * @var string
     */
    protected $phpbb_root_path;
    /**
     * @var string
     */
    protected $file_status;
    /**
     * @var string
     */
    protected $form;
    /**
     * @var bool
     */
    protected $request_client_refresh;
    /**
     * @var array
     */
    protected $nav_data;
    /**
     * @var array
     */
    protected $cookies;
    /**
     * @var array
     */
    protected $download;
    /**
     * @var array
     */
    protected $redirect_url;
    /**
     * @var resource
     */
    protected $file_lock_pointer;
    /**
     * Constructor
     *
     * @param path_helper                        $path_helper
     * @param \phpbb\request\request_interface    $request    HTTP request interface
     * @param \phpbb\template\template            $template    Template engine
     * @param router                             $router        Router
     * @param string                             $root_path    Path to phpBB's root
     */
    public function __construct(path_helper $path_helper, \phpbb\request\request_interface $request, \phpbb\template\template $template, router $router, $root_path)
    {
        $this->path_helper = $path_helper;
        $this->request    = $request;
        $this->router    = $router;
        $this->template    = $template;
        $this->form        = '';
        $this->nav_data    = array();
        $this->cookies    = array();
        $this->download    = array();
        $this->redirect_url = array();
        $this->file_status = '';
        $this->phpbb_root_path = $root_path;
        parent::__construct();
    }
    /**
     * {@inheritdoc}
     */
    public function get_input($name, $default, $multibyte = false)
    {
        return $this->request->variable($name, $default, $multibyte);
    }
    /**
     * {@inheritdoc}
     */
    public function get_raw_input($name, $default)
    {
        return $this->request->raw_variable($name, $default);
    }
    /**
     * {@inheritdoc}
     */
    public function get_server_variable($name, $default = '')
    {
        return $this->request->server($name, $default);
    }
    /**
     * {@inheritdoc}
     */
    public function get_header_variable($name, $default = '')
    {
        return $this->request->header($name, $default);
    }
    /**
     * {@inheritdoc}
     */
    public function is_secure()
    {
        return $this->request->is_secure();
    }
    /**
     * {@inheritdoc}
     */
    public function add_user_form_group($title, $form)
    {
        $this->form = $this->generate_form_render_data($title, $form);
    }
    /**
     * {@inheritdoc}
     */
    public function generate_form_render_data($title, $form)
    {
        $this->template->assign_block_vars('options', array(
            'LEGEND'    => $this->language->lang($title),
            'S_LEGEND'    => true,
        ));
        $not_button_form = false;
        foreach ($form as $input_name => $input_options)
        {
            if (!isset($input_options['type']))
            {
                continue;
            }
            $tpl_ary = array();
            $not_button_form = ($input_options['type'] !== 'submit' || $not_button_form);
            $tpl_ary['TYPE'] = $input_options['type'];
            $tpl_ary['TITLE'] = $this->language->lang($input_options['label']);
            $tpl_ary['KEY'] = $input_name;
            $tpl_ary['S_EXPLAIN'] = false;
            $tpl_ary['DISABLED'] = isset($input_options['disabled']) ? $input_options['disabled'] : false;
            $tpl_ary['IS_SECONDARY'] = isset($input_options['is_secondary']) ? $input_options['is_secondary'] : false;
            if (isset($input_options['default']))
            {
                $default = $input_options['default'];
                $default = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', array($this, 'lang_replace_callback'), $default);
                $tpl_ary['DEFAULT'] = $default;
            }
            if (isset($input_options['description']))
            {
                $tpl_ary['TITLE_EXPLAIN'] = $this->language->lang($input_options['description']);
                $tpl_ary['S_EXPLAIN'] = true;
            }
            if (in_array($input_options['type'], array('select', 'radio'), true))
            {
                for ($i = 0, $total = count($input_options['options']); $i < $total; $i++)
                {
                    if (isset($input_options['options'][$i]['label']))
                    {
                        $input_options['options'][$i]['label'] = $this->language->lang($input_options['options'][$i]['label']);
                    }
                }
                $tpl_ary['OPTIONS'] = $input_options['options'];
            }
            $block_name = ($input_options['type'] === 'submit') ? 'submit_buttons' : 'options';
            $this->template->assign_block_vars($block_name, $tpl_ary);
        }
        if (isset($form['database_update_submit']) && !$form['database_update_submit']['disabled'])
        {
            $this->template->assign_var('FORM_TITLE', $this->language->lang('UPDATE_CONTINUE_UPDATE_PROCESS'));
        }
        $this->template->assign_var('S_NOT_ONLY_BUTTON_FORM', $not_button_form);
        if (!$not_button_form)
        {
            $this->template->destroy_block_vars('options');
        }
        $this->template->set_filenames(array(
            'form_install' => 'installer_form.html',
        ));
        return $this->template->assign_display('form_install');
    }
    /**
     * {@inheritdoc}
     */
    public function send_response($no_more_output = false)
    {
        $json_data_array = $this->prepare_json_array($no_more_output);
        if (empty($json_data_array))
        {
            return;
        }
        $json_data = json_encode($json_data_array);
        // Try to push content to the browser
        print(str_pad(' ', 4096) . "\n");
        print($json_data . "\n\n");
        flush();
    }
    /**
     * Prepares iohandler's data to be sent out to the client.
     *
     * @param bool    $no_more_output    Whether or not there will be more output in this response
     *
     * @return array
     */
    protected function prepare_json_array($no_more_output = false)
    {
        $json_array = array();
        if (!empty($this->errors))
        {
            $json_array['errors'] = $this->errors;
            $this->errors = array();
        }
        if (!empty($this->warnings))
        {
            $json_array['warnings'] = $this->warnings;
            $this->warnings = array();
        }
        if (!empty($this->logs))
        {
            $json_array['logs'] = $this->logs;
            $this->logs = array();
        }
        if (!empty($this->success))
        {
            $json_array['success'] = $this->success;
            $this->success = array();
        }
        if (!empty($this->download))
        {
            $json_array['download'] = $this->download;
            $this->download = array();
        }
        if (!empty($this->form))
        {
            $json_array['form'] = $this->form;
            $this->form = '';
        }
        if (!empty($this->file_status))
        {
            $json_array['file_status'] = $this->file_status;
            $this->file_status = '';
        }
        // If current task name is set, we push progress message to the client side
        if (!empty($this->current_task_name))
        {
            $json_array['progress'] = array(
                'task_name'        => $this->current_task_name,
                'task_num'        => $this->current_task_progress,
                'task_count'    => $this->task_progress_count,
            );
            if ($this->restart_progress_bar)
            {
                $json_array['progress']['restart'] = 1;
                $this->restart_progress_bar = false;
            }
        }
        if (!empty($this->nav_data))
        {
            $json_array['nav'] = $this->nav_data;
            $this->nav_data = array();
        }
        if ($this->request_client_refresh)
        {
            $json_array['refresh'] = true;
            $this->request_client_refresh = false;
        }
        if (!empty($this->cookies))
        {
            $json_array['cookies'] = $this->cookies;
            $this->cookies = array();
        }
        if (!empty($this->redirect_url))
        {
            $json_array['redirect'] = $this->redirect_url;
            $this->redirect_url = array();
        }
        if ($no_more_output)
        {
            $json_array['over'] = true;
        }
        return $json_array;
    }
    /**
     * {@inheritdoc}
     */
    public function set_progress($task_lang_key, $task_number)
    {
        parent::set_progress($task_lang_key, $task_number);
        $this->send_response();
    }
    /**
     * {@inheritdoc}
     */
    public function request_refresh()
    {
        $this->request_client_refresh = true;
    }
    /**
     * {@inheritdoc}
     */
    public function set_active_stage_menu($menu_path)
    {
        $this->nav_data['active'] = $menu_path[count($menu_path) - 1];
        $this->send_response();
    }
    /**
     * {@inheritdoc}
     */
    public function set_finished_stage_menu($menu_path)
    {
        $this->nav_data['finished'][] = $menu_path[count($menu_path) - 1];
        $this->send_response();
    }
    /**
     * {@inheritdoc}
     */
    public function set_cookie($cookie_name, $cookie_value)
    {
        $this->cookies[] = array(
            'name' => $cookie_name,
            'value' => $cookie_value
        );
    }
    /**
     * {@inheritdoc}
     */
    public function add_download_link($route, $title, $msg = null)
    {
        $link_properties = array(
            'href'    => $this->router->generate($route),
            'title'    => $this->language->lang($title),
            'download' => $this->language->lang('DOWNLOAD'),
        );
        if ($msg !== null)
        {
            $link_properties['msg'] = html_entity_decode($this->language->lang($msg), ENT_COMPAT);
        }
        $this->download[] = $link_properties;
    }
    /**
     * {@inheritdoc}
     */
    public function render_update_file_status($status_array)
    {
        $this->template->assign_vars(array(
            'T_IMAGE_PATH'    => $this->path_helper->get_web_root_path() . 'adm/images/',
        ));
        foreach ($status_array as $block => $list)
        {
            foreach ($list as $filename)
            {
                $dirname = dirname($filename);
                $this->template->assign_block_vars($block, array(
                    'STATUS'            => $block,
                    'FILENAME'            => $filename,
                    'DIR_PART'            => (!empty($dirname) && $dirname !== '.') ? dirname($filename) . '/' : false,
                    'FILE_PART'            => basename($filename),
                ));
            }
        }
        $this->template->set_filenames(array(
            'file_status' => 'installer_update_file_status.html',
        ));
        $this->file_status = $this->template->assign_display('file_status');
    }
    /**
     * {@inheritdoc}
     */
    public function redirect($url, $use_ajax = false)
    {
        $this->redirect_url = array('url' => $url, 'use_ajax' => $use_ajax);
        $this->send_response(true);
    }
    /**
     * Acquires a file lock
     */
    public function acquire_lock()
    {
        $lock_file = $this->phpbb_root_path . 'store/io_lock.lock';
        $this->file_lock_pointer = @fopen($lock_file, 'w+');
        if ($this->file_lock_pointer)
        {
            flock($this->file_lock_pointer, LOCK_EX);
        }
    }
    /**
     * Release file lock
     */
    public function release_lock()
    {
        if ($this->file_lock_pointer)
        {
            fwrite($this->file_lock_pointer, 'ok');
            flock($this->file_lock_pointer, LOCK_UN);
            fclose($this->file_lock_pointer);
        }
    }
    /**
     * Callback function for language replacing
     *
     * @param array    $matches
     * @return string
     */
    public function lang_replace_callback($matches)
    {
        if (!empty($matches[1]))
        {
            return $this->language->lang($matches[1]);
        }
        return '';
    }
}