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 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 181
installer
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 6
1122.00
0.00% covered (danger)
0.00%
0 / 181
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 8
 set_modules
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 set_iohandler
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 set_purge_cache_before
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 run
0.00% covered (danger)
0.00%
0 / 1
812.00
0.00% covered (danger)
0.00%
0 / 160
 recover_progress
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 4
<?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;
use phpbb\cache\driver\driver_interface;
use phpbb\di\ordered_service_collection;
use phpbb\install\exception\cannot_build_container_exception;
use phpbb\install\exception\installer_config_not_writable_exception;
use phpbb\install\exception\jump_to_restart_point_exception;
use phpbb\install\exception\resource_limit_reached_exception;
use phpbb\install\exception\user_interaction_required_exception;
use phpbb\install\helper\config;
use phpbb\install\helper\container_factory;
use phpbb\install\helper\iohandler\ajax_iohandler;
use phpbb\install\helper\iohandler\cli_iohandler;
use phpbb\install\helper\iohandler\iohandler_interface;
use phpbb\path_helper;
class installer
{
    /**
     * @var driver_interface
     */
    protected $cache;
    /**
     * @var container_factory
     */
    protected $container_factory;
    /**
     * @var config
     */
    protected $install_config;
    /**
     * @var ordered_service_collection
     */
    protected $installer_modules;
    /**
     * @var iohandler_interface
     */
    protected $iohandler;
    /**
     * @var string
     */
    protected $web_root;
    /**
     * Stores the number of steps that a given module has
     *
     * @var array
     */
    protected $module_step_count;
    /**
     * @var bool
     */
    protected $purge_cache_before;
    /**
     * Constructor
     *
     * @param driver_interface    $cache            Cache service
     * @param config            $config            Installer config handler
     * @param path_helper        $path_helper    Path helper
     * @param container_factory    $container        Container
     */
    public function __construct(driver_interface $cache, config $config, path_helper $path_helper, container_factory $container)
    {
        $this->cache                = $cache;
        $this->install_config        = $config;
        $this->container_factory    = $container;
        $this->installer_modules    = null;
        $this->web_root                = $path_helper->get_web_root_path();
        $this->purge_cache_before    = false;
    }
    /**
     * Sets modules to execute
     *
     * Note: The installer will run modules in the order they are set in
     * the array.
     *
     * @param ordered_service_collection    $modules    Service collection of module service names
     */
    public function set_modules(ordered_service_collection $modules)
    {
        $this->installer_modules = $modules;
    }
    /**
     * Sets input-output handler objects
     *
     * @param iohandler_interface    $iohandler
     */
    public function set_iohandler(iohandler_interface $iohandler)
    {
        $this->iohandler = $iohandler;
    }
    /**
     * Sets whether to purge cache before the installation process
     *
     * @param bool    $purge_cache_before
     */
    public function set_purge_cache_before($purge_cache_before)
    {
        $this->purge_cache_before = $purge_cache_before;
    }
    /**
     * Run phpBB installer
     */
    public function run()
    {
        if ($this->iohandler instanceof ajax_iohandler)
        {
            $this->iohandler->acquire_lock();
        }
        // Load install progress
        $this->install_config->load_config();
        if (!$this->install_config->get('cache_purged_before', false) && $this->purge_cache_before)
        {
            /** @var driver_interface $cache */
            $cache = $this->container_factory->get('cache.driver');
            $cache->purge();
            $this->install_config->set('cache_purged_before', true);
        }
        // Recover install progress
        $module_index = $this->recover_progress();
        // Variable used to check if the install process have been finished
        $install_finished    = false;
        $fail_cleanup        = false;
        $send_refresh        = false;
        // We are installing something, so the introduction stage can go now...
        $this->install_config->set_finished_navigation_stage(array('install', 0, 'introduction'));
        $this->iohandler->set_finished_stage_menu(array('install', 0, 'introduction'));
        if ($this->install_config->get_task_progress_count() === 0)
        {
            // Count all tasks in the current installer modules
            $step_count = 0;
            /** @var \phpbb\install\module_interface $module */
            foreach ($this->installer_modules as $name => $module)
            {
                $module_step_count = $module->get_step_count();
                $step_count += $module_step_count;
                $this->module_step_count[$name] = $module_step_count;
            }
            // Set task count
            $this->install_config->set_task_progress_count($step_count);
        }
        // Set up progress information
        $this->iohandler->set_task_count(
            $this->install_config->get_task_progress_count()
        );
        try
        {
            $iterator = $this->installer_modules->getIterator();
            if ($module_index < $iterator->count())
            {
                $iterator->seek($module_index);
            }
            else
            {
                $iterator->seek($module_index - 1);
                $iterator->next();
            }
            while ($iterator->valid())
            {
                $module    = $iterator->current();
                $name    = $iterator->key();
                // Check if module should be executed
                if (!$module->is_essential() && !$module->check_requirements())
                {
                    $this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path());
                    $this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path());
                    $this->iohandler->add_log_message(array(
                        'SKIP_MODULE',
                        $name,
                    ));
                    $this->install_config->increment_current_task_progress($this->module_step_count[$name]);
                }
                else
                {
                    // Set the correct stage in the navigation bar
                    $this->install_config->set_active_navigation_stage($module->get_navigation_stage_path());
                    $this->iohandler->set_active_stage_menu($module->get_navigation_stage_path());
                    $this->iohandler->send_response();
                    $module->run();
                    $this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path());
                    $this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path());
                }
                $module_index++;
                $iterator->next();
                // Save progress
                $this->install_config->set_active_module($name, $module_index);
                if ($iterator->valid() && ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0))
                {
                    throw new resource_limit_reached_exception();
                }
            }
            // Installation finished
            $install_finished = true;
            if ($this->iohandler instanceof cli_iohandler)
            {
                $this->iohandler->add_success_message('INSTALLER_FINISHED');
            }
            else
            {
                // Start session if not installing and get user object
                // to allow redirecting to ACP
                $user = $this->container_factory->get('user');
                if (!isset($module) || !($module instanceof \phpbb\install\module\install_finish\module))
                {
                    $auth = $this->container_factory->get('auth');
                    $user->session_begin();
                    $auth->acl($user->data);
                    $user->setup();
                }
                $phpbb_root_path = $this->container_factory->get_parameter('core.root_path');
                $acp_url = append_sid($phpbb_root_path . 'adm/index.php', 'i=acp_help_phpbb&mode=help_phpbb', true, $user->session_id);
                $this->iohandler->add_success_message('INSTALLER_FINISHED', array(
                    'ACP_LINK',
                    $acp_url,
                ));
            }
        }
        catch (user_interaction_required_exception $e)
        {
            $this->iohandler->send_response(true);
        }
        catch (resource_limit_reached_exception $e)
        {
            $send_refresh = true;
        }
        catch (jump_to_restart_point_exception $e)
        {
            $this->install_config->jump_to_restart_point($e->get_restart_point_name());
            $send_refresh = true;
        }
        catch (\Exception $e)
        {
            $this->iohandler->add_error_message($e->getMessage());
            $this->iohandler->send_response(true);
            $fail_cleanup = true;
        }
        if ($this->iohandler instanceof ajax_iohandler)
        {
            $this->iohandler->release_lock();
        }
        if ($install_finished)
        {
            // Send install finished message
            $this->iohandler->set_progress('INSTALLER_FINISHED', $this->install_config->get_task_progress_count());
            $this->iohandler->send_response(true);
        }
        else if ($send_refresh)
        {
            $this->iohandler->request_refresh();
            $this->iohandler->send_response(true);
        }
        // Save install progress
        try
        {
            if ($install_finished || $fail_cleanup)
            {
                $this->install_config->clean_up_config_file();
                $this->cache->purge();
                try
                {
                    /** @var driver_interface $cache */
                    $cache = $this->container_factory->get('cache.driver');
                    $cache->purge();
                }
                catch (cannot_build_container_exception $e)
                {
                    // Do not do anything, this just means there is no config.php yet
                }
            }
            else
            {
                $this->install_config->save_config();
            }
        }
        catch (installer_config_not_writable_exception $e)
        {
            // It is allowed to fail this test during requirements testing
            $progress_data = $this->install_config->get_progress_data();
            if ($progress_data['last_task_module_name'] !== 'installer.module.requirements_install')
            {
                $this->iohandler->add_error_message('INSTALLER_CONFIG_NOT_WRITABLE');
            }
        }
    }
    /**
     * Recover install progress
     *
     * @return string    Index of the next installer module to execute
     */
    protected function recover_progress()
    {
        $progress_array = $this->install_config->get_progress_data();
        return $progress_array['last_task_module_index'];
    }
}