Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 108 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
| installer | |
0.00% |
0 / 108 |
|
0.00% |
0 / 6 |
1122 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
| set_modules | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| set_iohandler | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| set_purge_cache_before | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| run | |
0.00% |
0 / 97 |
|
0.00% |
0 / 1 |
812 | |||
| recover_progress | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| 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; |
| 15 | |
| 16 | use phpbb\cache\driver\driver_interface; |
| 17 | use phpbb\di\ordered_service_collection; |
| 18 | use phpbb\install\exception\cannot_build_container_exception; |
| 19 | use phpbb\install\exception\installer_config_not_writable_exception; |
| 20 | use phpbb\install\exception\jump_to_restart_point_exception; |
| 21 | use phpbb\install\exception\resource_limit_reached_exception; |
| 22 | use phpbb\install\exception\user_interaction_required_exception; |
| 23 | use phpbb\install\helper\config; |
| 24 | use phpbb\install\helper\container_factory; |
| 25 | use phpbb\install\helper\iohandler\ajax_iohandler; |
| 26 | use phpbb\install\helper\iohandler\cli_iohandler; |
| 27 | use phpbb\install\helper\iohandler\iohandler_interface; |
| 28 | use phpbb\path_helper; |
| 29 | |
| 30 | class installer |
| 31 | { |
| 32 | /** |
| 33 | * @var driver_interface |
| 34 | */ |
| 35 | protected $cache; |
| 36 | |
| 37 | /** |
| 38 | * @var container_factory |
| 39 | */ |
| 40 | protected $container_factory; |
| 41 | |
| 42 | /** |
| 43 | * @var config |
| 44 | */ |
| 45 | protected $install_config; |
| 46 | |
| 47 | /** |
| 48 | * @var ordered_service_collection|null |
| 49 | */ |
| 50 | protected $installer_modules; |
| 51 | |
| 52 | /** |
| 53 | * @var iohandler_interface |
| 54 | */ |
| 55 | protected $iohandler; |
| 56 | |
| 57 | /** |
| 58 | * @var string |
| 59 | */ |
| 60 | protected $web_root; |
| 61 | |
| 62 | /** |
| 63 | * Stores the number of steps that a given module has |
| 64 | * |
| 65 | * @var array |
| 66 | */ |
| 67 | protected $module_step_count; |
| 68 | |
| 69 | /** |
| 70 | * @var bool |
| 71 | */ |
| 72 | protected $purge_cache_before; |
| 73 | |
| 74 | /** |
| 75 | * Constructor |
| 76 | * |
| 77 | * @param driver_interface $cache Cache service |
| 78 | * @param config $config Installer config handler |
| 79 | * @param path_helper $path_helper Path helper |
| 80 | * @param container_factory $container Container |
| 81 | */ |
| 82 | public function __construct(driver_interface $cache, config $config, path_helper $path_helper, container_factory $container) |
| 83 | { |
| 84 | $this->cache = $cache; |
| 85 | $this->install_config = $config; |
| 86 | $this->container_factory = $container; |
| 87 | $this->installer_modules = null; |
| 88 | $this->web_root = $path_helper->get_web_root_path(); |
| 89 | $this->purge_cache_before = false; |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Sets modules to execute |
| 94 | * |
| 95 | * Note: The installer will run modules in the order they are set in |
| 96 | * the array. |
| 97 | * |
| 98 | * @param ordered_service_collection $modules Service collection of module service names |
| 99 | */ |
| 100 | public function set_modules(ordered_service_collection $modules) |
| 101 | { |
| 102 | $this->installer_modules = $modules; |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | * Sets input-output handler objects |
| 107 | * |
| 108 | * @param iohandler_interface $iohandler |
| 109 | */ |
| 110 | public function set_iohandler(iohandler_interface $iohandler) |
| 111 | { |
| 112 | $this->iohandler = $iohandler; |
| 113 | } |
| 114 | |
| 115 | /** |
| 116 | * Sets whether to purge cache before the installation process |
| 117 | * |
| 118 | * @param bool $purge_cache_before |
| 119 | */ |
| 120 | public function set_purge_cache_before($purge_cache_before) |
| 121 | { |
| 122 | $this->purge_cache_before = $purge_cache_before; |
| 123 | } |
| 124 | |
| 125 | /** |
| 126 | * Run phpBB installer |
| 127 | */ |
| 128 | public function run() |
| 129 | { |
| 130 | if ($this->iohandler instanceof ajax_iohandler) |
| 131 | { |
| 132 | $this->iohandler->acquire_lock(); |
| 133 | } |
| 134 | |
| 135 | // Load install progress |
| 136 | $this->install_config->load_config(); |
| 137 | |
| 138 | if (!$this->install_config->get('cache_purged_before', false) && $this->purge_cache_before) |
| 139 | { |
| 140 | /** @var driver_interface $cache */ |
| 141 | $cache = $this->container_factory->get('cache.driver'); |
| 142 | $cache->purge(); |
| 143 | $this->install_config->set('cache_purged_before', true); |
| 144 | } |
| 145 | |
| 146 | // Recover install progress |
| 147 | $module_index = $this->recover_progress(); |
| 148 | |
| 149 | // Variable used to check if the install process have been finished |
| 150 | $install_finished = false; |
| 151 | $fail_cleanup = false; |
| 152 | $send_refresh = false; |
| 153 | |
| 154 | // We are installing something, so the introduction stage can go now... |
| 155 | $this->install_config->set_finished_navigation_stage(array('install', 0, 'introduction')); |
| 156 | $this->iohandler->set_finished_stage_menu(array('install', 0, 'introduction')); |
| 157 | |
| 158 | if ($this->install_config->get_task_progress_count() === 0) |
| 159 | { |
| 160 | // Count all tasks in the current installer modules |
| 161 | $step_count = 0; |
| 162 | |
| 163 | /** @var \phpbb\install\module_interface $module */ |
| 164 | foreach ($this->installer_modules as $name => $module) |
| 165 | { |
| 166 | $module_step_count = $module->get_step_count(); |
| 167 | $step_count += $module_step_count; |
| 168 | $this->module_step_count[$name] = $module_step_count; |
| 169 | } |
| 170 | |
| 171 | // Set task count |
| 172 | $this->install_config->set_task_progress_count($step_count); |
| 173 | } |
| 174 | |
| 175 | // Set up progress information |
| 176 | $this->iohandler->set_task_count( |
| 177 | $this->install_config->get_task_progress_count() |
| 178 | ); |
| 179 | |
| 180 | try |
| 181 | { |
| 182 | /** @psalm-suppress InvalidTemplateParam */ |
| 183 | $iterator = $this->installer_modules->getIterator(); |
| 184 | |
| 185 | if ($module_index < $iterator->count()) |
| 186 | { |
| 187 | $iterator->seek($module_index); |
| 188 | } |
| 189 | else |
| 190 | { |
| 191 | $iterator->seek($module_index - 1); |
| 192 | $iterator->next(); |
| 193 | } |
| 194 | |
| 195 | while ($iterator->valid()) |
| 196 | { |
| 197 | $module = $iterator->current(); |
| 198 | $name = $iterator->key(); |
| 199 | |
| 200 | // Check if module should be executed |
| 201 | if (!$module->is_essential() && !$module->check_requirements()) |
| 202 | { |
| 203 | $this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path()); |
| 204 | $this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path()); |
| 205 | |
| 206 | $this->iohandler->add_log_message(array( |
| 207 | 'SKIP_MODULE', |
| 208 | $name, |
| 209 | )); |
| 210 | $this->install_config->increment_current_task_progress($this->module_step_count[$name]); |
| 211 | } |
| 212 | else |
| 213 | { |
| 214 | // Set the correct stage in the navigation bar |
| 215 | $this->install_config->set_active_navigation_stage($module->get_navigation_stage_path()); |
| 216 | $this->iohandler->set_active_stage_menu($module->get_navigation_stage_path()); |
| 217 | |
| 218 | $this->iohandler->send_response(); |
| 219 | |
| 220 | $module->run(); |
| 221 | |
| 222 | $this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path()); |
| 223 | $this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path()); |
| 224 | } |
| 225 | |
| 226 | $module_index++; |
| 227 | $iterator->next(); |
| 228 | |
| 229 | // Save progress |
| 230 | $this->install_config->set_active_module($name, $module_index); |
| 231 | |
| 232 | if ($iterator->valid() && ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0)) |
| 233 | { |
| 234 | throw new resource_limit_reached_exception(); |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | // Installation finished |
| 239 | $install_finished = true; |
| 240 | |
| 241 | if ($this->iohandler instanceof cli_iohandler) |
| 242 | { |
| 243 | $this->iohandler->add_success_message('INSTALLER_FINISHED'); |
| 244 | } |
| 245 | else |
| 246 | { |
| 247 | // Start session if not installing and get user object |
| 248 | // to allow redirecting to ACP |
| 249 | $user = $this->container_factory->get('user'); |
| 250 | if (!isset($module) || !($module instanceof \phpbb\install\module\install_finish\module)) |
| 251 | { |
| 252 | $auth = $this->container_factory->get('auth'); |
| 253 | |
| 254 | $user->session_begin(); |
| 255 | $auth->acl($user->data); |
| 256 | $user->setup(); |
| 257 | } |
| 258 | |
| 259 | $phpbb_root_path = $this->container_factory->get_parameter('core.root_path'); |
| 260 | |
| 261 | $acp_url = append_sid($phpbb_root_path . 'adm/index.php', 'i=acp_help_phpbb&mode=help_phpbb', true, $user->session_id); |
| 262 | $this->iohandler->add_success_message('INSTALLER_FINISHED', array( |
| 263 | 'ACP_LINK', |
| 264 | $acp_url, |
| 265 | )); |
| 266 | } |
| 267 | } |
| 268 | catch (user_interaction_required_exception $e) |
| 269 | { |
| 270 | $this->iohandler->send_response(true); |
| 271 | } |
| 272 | catch (resource_limit_reached_exception $e) |
| 273 | { |
| 274 | $send_refresh = true; |
| 275 | } |
| 276 | catch (jump_to_restart_point_exception $e) |
| 277 | { |
| 278 | $this->install_config->jump_to_restart_point($e->get_restart_point_name()); |
| 279 | $send_refresh = true; |
| 280 | } |
| 281 | catch (\Exception $e) |
| 282 | { |
| 283 | $stack_trace = phpbb_filter_root_path(str_replace("\n", '<br>', $e->getTraceAsString())); |
| 284 | $message = $e->getMessage(); |
| 285 | $this->iohandler->add_error_message($message, $stack_trace); |
| 286 | $this->iohandler->send_response(true); |
| 287 | $fail_cleanup = true; |
| 288 | } |
| 289 | |
| 290 | if ($this->iohandler instanceof ajax_iohandler) |
| 291 | { |
| 292 | $this->iohandler->release_lock(); |
| 293 | } |
| 294 | |
| 295 | if ($install_finished) |
| 296 | { |
| 297 | // Send install finished message |
| 298 | $this->iohandler->set_progress('INSTALLER_FINISHED', $this->install_config->get_task_progress_count()); |
| 299 | $this->iohandler->send_response(true); |
| 300 | } |
| 301 | else if ($send_refresh) |
| 302 | { |
| 303 | $this->iohandler->request_refresh(); |
| 304 | $this->iohandler->send_response(true); |
| 305 | } |
| 306 | |
| 307 | // Save install progress |
| 308 | try |
| 309 | { |
| 310 | if ($install_finished || $fail_cleanup) |
| 311 | { |
| 312 | $this->install_config->clean_up_config_file(); |
| 313 | $this->cache->purge(); |
| 314 | |
| 315 | try |
| 316 | { |
| 317 | /** @var driver_interface $cache */ |
| 318 | $cache = $this->container_factory->get('cache.driver'); |
| 319 | $cache->purge(); |
| 320 | } |
| 321 | catch (cannot_build_container_exception $e) |
| 322 | { |
| 323 | // Do not do anything, this just means there is no config.php yet |
| 324 | } |
| 325 | } |
| 326 | else |
| 327 | { |
| 328 | $this->install_config->save_config(); |
| 329 | } |
| 330 | } |
| 331 | catch (installer_config_not_writable_exception $e) |
| 332 | { |
| 333 | // It is allowed to fail this test during requirements testing |
| 334 | $progress_data = $this->install_config->get_progress_data(); |
| 335 | |
| 336 | if ($progress_data['last_task_module_name'] !== 'installer.module.requirements_install') |
| 337 | { |
| 338 | $this->iohandler->add_error_message('INSTALLER_CONFIG_NOT_WRITABLE'); |
| 339 | } |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | /** |
| 344 | * Recover install progress |
| 345 | * |
| 346 | * @return int Index of the next installer module to execute |
| 347 | */ |
| 348 | protected function recover_progress(): int |
| 349 | { |
| 350 | $progress_array = $this->install_config->get_progress_data(); |
| 351 | return (int) $progress_array['last_task_module_index']; |
| 352 | } |
| 353 | } |