aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMateBartus <mate.bartus@gmail.com>2015-04-17 23:17:23 +0200
committerMate Bartus <mate.bartus@gmail.com>2015-07-08 01:27:56 +0200
commit8155205ae7a5ec27ff3058137513fc480d7ee6c5 (patch)
tree75582a89e64da1477aa7f5161c15f0600c462d62
parent53c5610080d45660fc8d5528135408cb9ac293cf (diff)
downloadforums-8155205ae7a5ec27ff3058137513fc480d7ee6c5.tar
forums-8155205ae7a5ec27ff3058137513fc480d7ee6c5.tar.gz
forums-8155205ae7a5ec27ff3058137513fc480d7ee6c5.tar.bz2
forums-8155205ae7a5ec27ff3058137513fc480d7ee6c5.tar.xz
forums-8155205ae7a5ec27ff3058137513fc480d7ee6c5.zip
[ticket/13740] Implementation of the new installer framework
[ci skip] PHPBB3-13740
-rw-r--r--phpBB/install/exception/cannot_build_container_exception.php22
-rw-r--r--phpBB/install/exception/invalid_dbms_exception.php22
-rw-r--r--phpBB/install/exception/user_interaction_required_exception.php22
-rw-r--r--phpBB/install/helper/config.php259
-rw-r--r--phpBB/install/helper/container_factory.php149
-rw-r--r--phpBB/install/helper/database.php459
-rw-r--r--phpBB/install/helper/iohandler/ajax_iohandler.php202
-rw-r--r--phpBB/install/helper/iohandler/exception/iohandler_not_implemented_exception.php19
-rw-r--r--phpBB/install/helper/iohandler/factory.php72
-rw-r--r--phpBB/install/helper/iohandler/iohandler_base.php121
-rw-r--r--phpBB/install/helper/iohandler/iohandler_interface.php119
-rw-r--r--phpBB/install/helper/navigation/install_navigation.php28
-rw-r--r--phpBB/install/helper/navigation/navigation_interface.php43
-rw-r--r--phpBB/install/helper/navigation/navigation_provider.php92
-rw-r--r--phpBB/install/installer.php146
-rw-r--r--phpBB/install/module_base.php175
-rw-r--r--phpBB/install/module_interface.php56
-rw-r--r--phpBB/install/task_base.php53
-rw-r--r--phpBB/install/task_interface.php47
19 files changed, 2106 insertions, 0 deletions
diff --git a/phpBB/install/exception/cannot_build_container_exception.php b/phpBB/install/exception/cannot_build_container_exception.php
new file mode 100644
index 0000000000..11be507bc9
--- /dev/null
+++ b/phpBB/install/exception/cannot_build_container_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+/**
+ * This exception should be thrown when
+ */
+class cannot_build_container_exception extends installer_exception
+{
+
+}
diff --git a/phpBB/install/exception/invalid_dbms_exception.php b/phpBB/install/exception/invalid_dbms_exception.php
new file mode 100644
index 0000000000..ccb35bc237
--- /dev/null
+++ b/phpBB/install/exception/invalid_dbms_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+/**
+ * This exception should be thrown when
+ */
+class invalid_dbms_exception extends installer_exception
+{
+
+}
diff --git a/phpBB/install/exception/user_interaction_required_exception.php b/phpBB/install/exception/user_interaction_required_exception.php
new file mode 100644
index 0000000000..0aaae648cf
--- /dev/null
+++ b/phpBB/install/exception/user_interaction_required_exception.php
@@ -0,0 +1,22 @@
+<?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\exception;
+
+/**
+ * This exception should be thrown when user interaction is inevitable
+ */
+class user_interaction_required_exception extends installer_exception
+{
+
+}
diff --git a/phpBB/install/helper/config.php b/phpBB/install/helper/config.php
new file mode 100644
index 0000000000..b759df737e
--- /dev/null
+++ b/phpBB/install/helper/config.php
@@ -0,0 +1,259 @@
+<?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;
+
+/**
+ * Stores common settings and installation status
+ */
+class config
+{
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * Array which contains config settings for the installer
+ *
+ * The array will also store all the user input, as well as any
+ * data that is passed to other tasks by a task.
+ *
+ * @var array
+ */
+ protected $installer_config;
+
+ /**
+ * @var string
+ */
+ protected $install_config_file;
+
+ /**
+ * @var \phpbb\php\ini
+ */
+ protected $php_ini;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Array containing progress information
+ *
+ * @var array
+ */
+ protected $progress_data;
+
+ /**
+ * Array containing system information
+ *
+ * The array contains run time and memory limitations.
+ *
+ * @var array
+ */
+ protected $system_data;
+
+ /**
+ * Constructor
+ */
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, \phpbb\php\ini $php_ini, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+ $this->php_ini = $php_ini;
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ // Set up data arrays
+ $this->installer_config = array();
+ $this->system_data = array();
+ $this->progress_data = array(
+ 'last_task_module_index' => 0,
+ 'last_task_module_name' => '', // Stores the service name of the latest finished module
+ 'last_task_index' => 0,
+ 'last_task_name' => '', // Stores the service name of the latest finished task
+ );
+
+ $this->install_config_file = $this->phpbb_root_path . 'store/install_config.php';
+
+ $this->setup_system_data();
+ }
+
+ /**
+ * Returns data for a specified parameter
+ *
+ * @param string $param_name Name of the parameter to return
+ * @param mixed $default Default value to return when the specified data
+ * does not exist.
+ *
+ * @return mixed value of the specified parameter or the default value if the data
+ * cannot be recovered.
+ */
+ public function get($param_name, $default = false)
+ {
+ return (isset($this->installer_config[$param_name])) ? $this->installer_config[$param_name] : $default;
+ }
+
+ /**
+ * Sets a parameter in installer_config
+ *
+ * @param string $param_name Name of the parameter
+ * @param mixed $value Values to set the parameter
+ *
+ * @return null
+ */
+ public function set($param_name, $value)
+ {
+ $this->installer_config = array_merge($this->installer_config, array(
+ $param_name => $value,
+ ));
+ }
+
+ /**
+ * Returns system parameter
+ *
+ * @param string $param_name Name of the parameter
+ *
+ * @return mixed Returns system parameter if it is defined, false otherwise
+ */
+ public function system_get($param_name)
+ {
+ return (isset($this->system_data[$param_name])) ? $this->system_data[$param_name] : false;
+ }
+
+ /**
+ * Returns remaining time until the run time limit
+ *
+ * @return int Remaining time until the run time limit in seconds
+ */
+ public function get_time_remaining()
+ {
+ return ($this->system_data['start_time'] + $this->system_data['max_execution_time']) - time();
+ }
+
+ /**
+ * Returns remaining memory available for PHP
+ *
+ * @return int Remaining memory until reaching the limit
+ */
+ public function get_memory_remaining()
+ {
+ if (function_exists('memory_get_usage'))
+ {
+ return ($this->system_data['memory_limit'] - memory_get_usage());
+ }
+
+ // If we cannot get the information then just return a positive number (and cross fingers)
+ return 1;
+ }
+
+ /**
+ * Saves the latest executed task
+ *
+ * @param string $task_service_name Name of the installer task service
+ * @param int $task_index Index of the task in the task list array
+ *
+ * @return null
+ */
+ public function set_finished_task($task_service_name, $task_index)
+ {
+ $this->progress_data['last_task_name'] = $task_service_name;
+ $this->progress_data['last_task_index'] = $task_index;
+ }
+
+ /**
+ * Set active module
+ *
+ * @param string $module_service_name Name of the installer module service
+ * @param int $module_index Index of the module in the module list array
+ *
+ * @return null
+ */
+ public function set_active_module($module_service_name, $module_index)
+ {
+ $this->progress_data['last_task_module_name'] = $module_service_name;
+ $this->progress_data['last_task_module_index'] = $module_index;
+ }
+
+ /**
+ * Getter for progress data
+ *
+ * @return array
+ */
+ public function get_progress_data()
+ {
+ return $this->progress_data;
+ }
+
+ /**
+ * Recovers install configuration from file
+ *
+ * @return null
+ */
+ public function load_config()
+ {
+ if (!$this->filesystem->exists($this->install_config_file))
+ {
+ return;
+ }
+
+ $file_content = @file_get_contents($this->install_config_file);
+ $serialized_data = trim(substr($file_content, 8));
+ $unserialized_data = unserialize($serialized_data);
+
+ $this->installer_config = $unserialized_data['installer_config'];
+ $this->progress_data = $unserialized_data['progress_data'];
+ }
+
+ /**
+ * Dumps install configuration to disk
+ *
+ * @return null
+ */
+ public function save_config()
+ {
+ // Create array to save
+ $save_array = array(
+ 'installer_config' => $this->installer_config,
+ 'progress_data' => $this->progress_data,
+ );
+
+ // Create file content
+ $file_content = '<?php // ';
+ $file_content .= serialize($save_array);
+ $file_content .= "\n";
+
+ // Dump file_content to disk
+ $fp = fopen($this->install_config_file, 'w');
+ fwrite($fp, $file_content);
+ fclose($fp);
+ }
+
+ /**
+ * Filling up system_data array
+ *
+ * @return null
+ */
+ protected function setup_system_data()
+ {
+ // Query maximum runtime from php.ini
+ $execution_time = $this->php_ini->get_int('max_execution_time');
+ $execution_time = min(15, $execution_time / 2);
+ $this->system_data['max_execution_time'] = $execution_time;
+
+ // Set start time
+ $this->system_data['start_time'] = time();
+
+ // Get memory limit
+ $this->system_data['memory_limit'] = $this->php_ini->get_bytes('memory_limit');
+ }
+}
diff --git a/phpBB/install/helper/container_factory.php b/phpBB/install/helper/container_factory.php
new file mode 100644
index 0000000000..255f8f428e
--- /dev/null
+++ b/phpBB/install/helper/container_factory.php
@@ -0,0 +1,149 @@
+<?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;
+
+use phpbb\install\exception\cannot_build_container_exception;
+
+class container_factory
+{
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * @var \phpbb\request\request
+ */
+ protected $request;
+
+ /**
+ * The full phpBB container
+ *
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\request\request $request Request interface
+ * @param string $phpbb_root_path Path to phpBB's root
+ * @param string $php_ext Extension of PHP files
+ */
+ public function __construct(\phpbb\request\request $request, $phpbb_root_path, $php_ext)
+ {
+ $this->request = $request;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ $this->container = null;
+ }
+
+ /**
+ * Container getter
+ *
+ * @param null|string $service_name Name of the service to return
+ *
+ * @return \Symfony\Component\DependencyInjection\ContainerInterface|Object phpBB's dependency injection container
+ * or the service specified in $service_name
+ *
+ * @throws \phpbb\install\exception\cannot_build_container_exception When container cannot be built
+ * @throws \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException If the service is not defined
+ * @throws \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException When a circular reference is detected
+ * @throws \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException When the service is not defined
+ */
+ public function get($service_name = null)
+ {
+ // Check if container was built, if not try to build it
+ if ($this->container === null)
+ {
+ // Check whether container can be built
+ // We need config.php for that so let's check if it has been set up yet
+ if (filesize($this->phpbb_root_path . 'config.' . $this->php_ext))
+ {
+ $this->build_container();
+ }
+ else
+ {
+ throw new cannot_build_container_exception();
+ }
+ }
+
+ return ($service_name === null) ? $this->container : $this->container->get($service_name);
+ }
+
+ /**
+ * Returns the specified parameter from the container
+ *
+ * @param string $param_name
+ *
+ * @return mixed
+ */
+ public function get_parameter($param_name)
+ {
+ return $this->container->getParameter($param_name);
+ }
+
+ /**
+ * Build dependency injection container
+ */
+ protected function build_container()
+ {
+ // If the container has been already built just return.
+ // Although this should never happen
+ if ($this->container instanceof \Symfony\Component\DependencyInjection\ContainerInterface)
+ {
+ return;
+ }
+
+ $phpbb_config_php_file = new \phpbb\config_php_file($this->phpbb_root_path, $this->php_ext);
+ $phpbb_container_builder = new \phpbb\di\container_builder($this->phpbb_root_path, $this->php_ext);
+
+ // For BC with functions that we need during install
+ global $phpbb_container;
+
+ $disable_super_globals = $this->request->super_globals_disabled();
+
+ // This is needed because container_builder::get_env_parameters() uses $_SERVER
+ if ($disable_super_globals)
+ {
+ $this->request->enable_super_globals();
+ }
+
+ $this->container = $phpbb_container = $phpbb_container_builder
+ ->with_config($phpbb_config_php_file)
+ ->without_cache()
+ ->without_compiled_container()
+ ->get_container();
+
+ // Setting request is required for the compatibility globals as those are generated from
+ // this container
+ $this->container->register('request')->setSynthetic(true);
+ $this->container->set('request', $this->request);
+ $this->container->compile();
+
+ // Restore super globals to previous state
+ if ($disable_super_globals)
+ {
+ $this->request->disable_super_globals();
+ }
+
+ // Get compatibilty globals
+ require ($this->phpbb_root_path . 'includes/compatibility_globals.' . $this->php_ext);
+ }
+}
diff --git a/phpBB/install/helper/database.php b/phpBB/install/helper/database.php
new file mode 100644
index 0000000000..d728c8b93b
--- /dev/null
+++ b/phpBB/install/helper/database.php
@@ -0,0 +1,459 @@
+<?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;
+
+use phpbb\install\exception\invalid_dbms_exception;
+
+/**
+ * Database related general functionality for installer
+ */
+class database
+{
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var array
+ */
+ protected $supported_dbms;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem interface
+ * @param string $phpbb_root_path Path to phpBB's root
+ */
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+
+ // DBMS supported by phpBB
+ $this->supported_dbms = array(
+ // Note: php 5.5 alpha 2 deprecated mysql.
+ // Keep mysqli before mysql in this list.
+ 'mysqli' => array(
+ 'LABEL' => 'MySQL with MySQLi Extension',
+ 'SCHEMA' => 'mysql_41',
+ 'MODULE' => 'mysqli',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\mysqli',
+ 'AVAILABLE' => true,
+ '2.0.x' => true,
+ ),
+ 'mysql' => array(
+ 'LABEL' => 'MySQL',
+ 'SCHEMA' => 'mysql',
+ 'MODULE' => 'mysql',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\mysql',
+ 'AVAILABLE' => true,
+ '2.0.x' => true,
+ ),
+ 'mssql' => array(
+ 'LABEL' => 'MS SQL Server 2000+',
+ 'SCHEMA' => 'mssql',
+ 'MODULE' => 'mssql',
+ 'DELIM' => 'GO',
+ 'DRIVER' => 'phpbb\db\driver\mssql',
+ 'AVAILABLE' => true,
+ '2.0.x' => true,
+ ),
+ 'mssql_odbc'=> array(
+ 'LABEL' => 'MS SQL Server [ ODBC ]',
+ 'SCHEMA' => 'mssql',
+ 'MODULE' => 'odbc',
+ 'DELIM' => 'GO',
+ 'DRIVER' => 'phpbb\db\driver\mssql_odbc',
+ 'AVAILABLE' => true,
+ '2.0.x' => true,
+ ),
+ 'mssqlnative' => array(
+ 'LABEL' => 'MS SQL Server 2005+ [ Native ]',
+ 'SCHEMA' => 'mssql',
+ 'MODULE' => 'sqlsrv',
+ 'DELIM' => 'GO',
+ 'DRIVER' => 'phpbb\db\driver\mssqlnative',
+ 'AVAILABLE' => true,
+ '2.0.x' => false,
+ ),
+ 'oracle' => array(
+ 'LABEL' => 'Oracle',
+ 'SCHEMA' => 'oracle',
+ 'MODULE' => 'oci8',
+ 'DELIM' => '/',
+ 'DRIVER' => 'phpbb\db\driver\oracle',
+ 'AVAILABLE' => true,
+ '2.0.x' => false,
+ ),
+ 'postgres' => array(
+ 'LABEL' => 'PostgreSQL 8.3+',
+ 'SCHEMA' => 'postgres',
+ 'MODULE' => 'pgsql',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\postgres',
+ 'AVAILABLE' => true,
+ '2.0.x' => true,
+ ),
+ 'sqlite' => array(
+ 'LABEL' => 'SQLite',
+ 'SCHEMA' => 'sqlite',
+ 'MODULE' => 'sqlite',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\sqlite',
+ 'AVAILABLE' => true,
+ '2.0.x' => false,
+ ),
+ 'sqlite3' => array(
+ 'LABEL' => 'SQLite3',
+ 'SCHEMA' => 'sqlite',
+ 'MODULE' => 'sqlite3',
+ 'DELIM' => ';',
+ 'DRIVER' => 'phpbb\db\driver\sqlite3',
+ 'AVAILABLE' => true,
+ '2.0.x' => false,
+ ),
+ );
+ }
+
+ /**
+ * Returns an array of available DBMS supported by phpBB
+ *
+ * If a DBMS is specified it will only return data for that DBMS
+ * and will load its extension if necessary.
+ *
+ * @param mixed $dbms name of the DBMS that's info is required or false for all DBMS info
+ * @param bool $return_unavailable set it to true if you expect unavailable but supported DBMS
+ * returned as well
+ * @param bool $only_20x_options set it to true if you only want to recover 2.0.x options
+ *
+ * @return array Array of available and supported DBMS
+ */
+ public function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false)
+ {
+ $available_dbms = $this->supported_dbms;
+
+ if ($dbms)
+ {
+ if (isset($this->supported_dbms[$dbms]))
+ {
+ $available_dbms = array($dbms => $this->supported_dbms[$dbms]);
+ }
+ else
+ {
+ return array();
+ }
+ }
+
+ $any_dbms_available = false;
+ foreach ($available_dbms as $db_name => $db_array)
+ {
+ if ($only_20x_options && !$db_array['2.0.x'])
+ {
+ if ($return_unavailable)
+ {
+ $available_dbms[$db_name]['AVAILABLE'] = false;
+ }
+ else
+ {
+ unset($available_dbms[$db_name]);
+ }
+
+ continue;
+ }
+
+ $dll = $db_array['MODULE'];
+ if (!@extension_loaded($dll))
+ {
+ if ($return_unavailable)
+ {
+ $available_dbms[$db_name]['AVAILABLE'] = false;
+ }
+ else
+ {
+ unset($available_dbms[$db_name]);
+ }
+
+ continue;
+ }
+
+ $any_dbms_available = true;
+ }
+
+ if ($return_unavailable)
+ {
+ $available_dbms['ANY_DB_SUPPORT'] = $any_dbms_available;
+ }
+
+ return $available_dbms;
+ }
+
+ /**
+ * Removes "/* style" as well as "# style" comments from $input.
+ *
+ * @param string $sql_query Input string
+ *
+ * @return string Input string with comments removed
+ */
+ public function remove_comments($sql_query)
+ {
+ // Remove /* */ comments (http://ostermiller.org/findcomment.html)
+ $sql_query = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $sql_query);
+
+ // Remove # style comments
+ $sql_query = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql_query));
+
+ return $sql_query;
+ }
+
+ /**
+ * split_sql_file() will split an uploaded sql file into single sql statements.
+ *
+ * Note: expects trim() to have already been run on $sql.
+ *
+ * @param string $sql SQL statements
+ * @param string $delimiter Delimiter between sql statements
+ *
+ * @return array Array of sql statements
+ */
+ public function split_sql_file($sql, $delimiter)
+ {
+ $sql = str_replace("\r" , '', $sql);
+ $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql);
+
+ $data = array_map('trim', $data);
+
+ // The empty case
+ $end_data = end($data);
+
+ if (empty($end_data))
+ {
+ unset($data[key($data)]);
+ }
+
+ return $data;
+ }
+
+ /**
+ * Validates table prefix
+ *
+ * @param string $dbms The selected dbms
+ * @param string $table_prefix The table prefix to validate
+ *
+ * @return bool|array true if table prefix is valid, array of errors otherwise
+ *
+ * @throws \phpbb\install\exception\invalid_dbms_exception When $dbms is not a valid
+ */
+ public function validate_table_prefix($dbms, $table_prefix)
+ {
+ $errors = array();
+
+ if (!preg_match('#^[a-zA-Z][a-zA-Z0-9_]*$#', $table_prefix))
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_INVALID_PREFIX',
+ );
+ }
+
+ // Do dbms specific checks
+ $dbms_info = $this->get_available_dbms($dbms);
+ switch ($dbms_info[$dbms]['SCHEMA'])
+ {
+ case 'mysql':
+ case 'mysql_41':
+ $prefix_length = 36;
+ break;
+ case 'mssql':
+ $prefix_length = 90;
+ break;
+ case 'oracle':
+ $prefix_length = 6;
+ break;
+ case 'postgres':
+ $prefix_length = 36;
+ break;
+ case 'sqlite':
+ $prefix_length = 200;
+ break;
+ default:
+ throw new invalid_dbms_exception();
+ break;
+ }
+
+ // Check the prefix length to ensure that index names are not too long
+ if (strlen($table_prefix) > $prefix_length)
+ {
+ $errors[] = array(
+ 'title' => array('INST_ERR_PREFIX_TOO_LONG', $prefix_length),
+ );
+ }
+
+ return (empty($errors)) ? true : $errors;
+ }
+
+ /**
+ * Check if the user provided database parameters are correct
+ *
+ * This function checks the database connection data and also checks for
+ * any other problems that could cause an error during the installation
+ * such as if there is any database table names conflicting.
+ *
+ * Note: The function assumes that $table_prefix has been already validated
+ * with validate_table_prefix().
+ *
+ * @param string $dbms Selected database type
+ * @param string $dbhost Database host address
+ * @param int $dbport Database port number
+ * @param string $dbuser Database username
+ * @param string $dbpass Database password
+ * @param string $dbname Database name
+ * @param string $table_prefix Database table prefix
+ *
+ * @return array|bool Returns true if test is successful, array of errors otherwise
+ */
+ public function check_database_connection($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix)
+ {
+ $dbms_info = $this->get_available_dbms($dbms);
+ $dbms_info = $dbms_info[$dbms];
+ $errors = array();
+
+ // Instantiate it and set return on error true
+ /** @var \phpbb\db\driver\driver_interface $db */
+ $db = new $dbms_info['DRIVER'];
+ $db->sql_return_on_error(true);
+
+ // Check that we actually have a database name before going any further
+ if (!in_array($dbms_info['SCHEMA'], array('sqlite', 'oracle')) && $dbname === '')
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_NAME',
+ );
+ }
+
+ // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea
+ if ($dbms_info['SCHEMA'] === 'sqlite'
+ && stripos($this->filesystem->realpath($dbhost), $this->filesystem->realpath($this->phpbb_root_path) === 0))
+ {
+ $errors[] = array(
+ 'title' =>'INST_ERR_DB_FORUM_PATH',
+ );
+ }
+
+ // Try to connect to db
+ if (is_array($db->sql_connect($dbhost, $dbuser, $dbpass, $dbname, $dbport, false, true)))
+ {
+ $db_error = $db->sql_error();
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_CONNECT',
+ 'description' => ($db_error['message']) ? utf8_convert_message($db_error['message']) : 'INST_ERR_DB_NO_ERROR',
+ );
+ }
+ else
+ {
+ // Check if there is any table name collisions
+ $temp_prefix = strtolower($table_prefix);
+ $table_ary = array(
+ $temp_prefix . 'attachments',
+ $temp_prefix . 'config',
+ $temp_prefix . 'sessions',
+ $temp_prefix . 'topics',
+ $temp_prefix . 'users',
+ );
+
+ $db_tools_factory = new \phpbb\db\tools\factory();
+ $db_tools = $db_tools_factory->get($db);
+ $tables = $db_tools->sql_list_tables();
+ $tables = array_map('strtolower', $tables);
+ $table_intersect = array_intersect($tables, $table_ary);
+
+ if (sizeof($table_intersect))
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_PREFIX',
+ );
+ }
+
+ // Check if database version is supported
+ switch ($dbms)
+ {
+ case 'mysqli':
+ if (version_compare(mysqli_get_server_info($db->get_db_connect_id()), '4.1.3', '<'))
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_MYSQLI',
+ );
+ }
+ break;
+ case 'sqlite':
+ if (version_compare(sqlite_libversion(), '2.8.2', '<'))
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_SQLITE',
+ );
+ }
+ break;
+ case 'sqlite3':
+ $version = \SQLite3::version();
+ if (version_compare($version['versionString'], '3.6.15', '<'))
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_SQLITE3',
+ );
+ }
+ break;
+ case 'oracle':
+ $sql = "SELECT *
+ FROM NLS_DATABASE_PARAMETERS
+ WHERE PARAMETER = 'NLS_RDBMS_VERSION'
+ OR PARAMETER = 'NLS_CHARACTERSET'";
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $stats[$row['parameter']] = $row['value'];
+ }
+ $db->sql_freeresult($result);
+
+ if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8')
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_ORACLE',
+ );
+ }
+ break;
+ case 'postgres':
+ $sql = "SHOW server_encoding;";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
+ {
+ $errors[] = array(
+ 'title' => 'INST_ERR_DB_NO_POSTGRES',
+ );
+ }
+ break;
+ }
+ }
+
+ return (empty($errors)) ? true : $errors;
+ }
+}
diff --git a/phpBB/install/helper/iohandler/ajax_iohandler.php b/phpBB/install/helper/iohandler/ajax_iohandler.php
new file mode 100644
index 0000000000..44a185139e
--- /dev/null
+++ b/phpBB/install/helper/iohandler/ajax_iohandler.php
@@ -0,0 +1,202 @@
+<?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;
+
+/**
+ * Input-Output handler for the AJAX frontend
+ */
+class ajax_iohandler extends iohandler_base
+{
+ /**
+ * @var \phpbb\request\request_interface
+ */
+ protected $request;
+
+ /**
+ * @var \phpbb\template\template
+ */
+ protected $template;
+
+ /**
+ * @var string
+ */
+ protected $form;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\request\request_interface $request HTTP request interface
+ * @param \phpbb\template\template $template Template engine
+ */
+ public function __construct(\phpbb\request\request_interface $request, \phpbb\template\template $template)
+ {
+ $this->request = $request;
+ $this->template = $template;
+ $this->form = '';
+
+ parent::__construct();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_input($name, $default, $multibyte = false)
+ {
+ return $this->request->variable($name, $default, $multibyte);
+ }
+
+ /**
+ * {@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 code is pretty ugly... but works
+ //
+
+ $this->template->assign_block_vars('options', array(
+ 'LEGEND' => $this->language->lang($title),
+ 'S_LEGEND' => true,
+ ));
+
+ foreach ($form as $input_name => $input_options)
+ {
+ if (!isset($input_options['type']))
+ {
+ continue;
+ }
+
+ $tpl_ary = array();
+
+ $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;
+
+ 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')))
+ {
+ for ($i = 0, $total = sizeof($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'];
+ }
+
+ $this->template->assign_block_vars('options', $tpl_ary);
+ }
+
+ $this->template->set_filenames(array(
+ 'form_install' => 'installer_form.html',
+ ));
+
+ $this->form = $this->template->assign_display('form_install');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function send_response()
+ {
+ $json_data_array = $this->prepare_json_array();
+ $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.
+ *
+ * @return array
+ */
+ protected function prepare_json_array()
+ {
+ $json_array = array(
+ 'errors' => $this->errors,
+ 'warnings' => $this->warnings,
+ 'logs' => $this->logs,
+ );
+
+ if (!empty($this->form))
+ {
+ $json_array['form'] = $this->form;
+ $this->form = '';
+ }
+
+ $this->errors = array();
+ $this->warnings = array();
+ $this->logs = array();
+
+ return $json_array;
+ }
+
+ /**
+ * 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 '';
+ }
+}
diff --git a/phpBB/install/helper/iohandler/exception/iohandler_not_implemented_exception.php b/phpBB/install/helper/iohandler/exception/iohandler_not_implemented_exception.php
new file mode 100644
index 0000000000..f2ddeda6f7
--- /dev/null
+++ b/phpBB/install/helper/iohandler/exception/iohandler_not_implemented_exception.php
@@ -0,0 +1,19 @@
+<?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\exception;
+
+class iohandler_not_implemented_exception extends \Exception
+{
+
+}
diff --git a/phpBB/install/helper/iohandler/factory.php b/phpBB/install/helper/iohandler/factory.php
new file mode 100644
index 0000000000..0b59e5ec63
--- /dev/null
+++ b/phpBB/install/helper/iohandler/factory.php
@@ -0,0 +1,72 @@
+<?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\install\helper\iohandler\exception\iohandler_not_implemented_exception;
+
+/**
+ * Input-output handler factory
+ */
+class factory
+{
+ /**
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * @var string
+ */
+ protected $environment;
+
+ /**
+ * Constructor
+ *
+ * @param \Symfony\Component\DependencyInjection\ContainerInterface $container Dependency injection container
+ */
+ public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container)
+ {
+ $this->container = $container;
+ $this->environment = null;
+ }
+
+ /**
+ * @param string $environment The name of the input-output handler to use
+ */
+ public function set_environment($environment)
+ {
+ $this->environment = $environment;
+ }
+
+ /**
+ * Factory getter for iohandler
+ *
+ * @return \phpbb\install\helper\iohandler\iohandler_interface
+ *
+ * @throws \phpbb\install\helper\iohandler\exception\iohandler_not_implemented_exception
+ * When the specified iohandler_interface does not exists
+ */
+ public function get()
+ {
+ switch ($this->environment)
+ {
+ case 'ajax':
+ return $this->container->get('installer.helper.iohandler_ajax');
+ break;
+ default:
+ throw new iohandler_not_implemented_exception();
+ break;
+ }
+ }
+}
diff --git a/phpBB/install/helper/iohandler/iohandler_base.php b/phpBB/install/helper/iohandler/iohandler_base.php
new file mode 100644
index 0000000000..0d5467d202
--- /dev/null
+++ b/phpBB/install/helper/iohandler/iohandler_base.php
@@ -0,0 +1,121 @@
+<?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;
+
+/**
+ * Base class for installer input-output handlers
+ */
+abstract class iohandler_base implements iohandler_interface
+{
+ /**
+ * Array of errors
+ *
+ * Errors should be added, when the installation cannot continue without
+ * user interaction. If the aim is to notify the user about something, please
+ * use a warning instead.
+ *
+ * @var array
+ */
+ protected $errors;
+
+ /**
+ * Array of warnings
+ *
+ * @var array
+ */
+ protected $warnings;
+
+ /**
+ * Array of logs
+ *
+ * @var array
+ */
+ protected $logs;
+
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->errors = array();
+ $this->warnings = array();
+ $this->logs = array();
+ }
+
+ /**
+ * Set language service
+ *
+ * @param \phpbb\language\language $language
+ *
+ * @return null
+ */
+ public function set_language(\phpbb\language\language $language)
+ {
+ $this->language = $language;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_error_message($error_title, $error_description = false)
+ {
+ $this->errors[] = $this->translate_message($error_title, $error_description);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_warning_message($warning_title, $warning_description = false)
+ {
+ $this->warnings[] = $this->translate_message($warning_title, $warning_description);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_log_message($log_title, $log_description = false)
+ {
+ $this->logs[] = $this->translate_message($log_title, $log_description);
+ }
+
+ /**
+ * Localize message.
+ *
+ * Note: When an array is passed into the parameters below, it will be
+ * resolved as printf($param[0], $param[1], ...).
+ *
+ * @param array|string $title Title of the message
+ * @param array|string|bool $description Description of the message
+ *
+ * @return array Localized message in an array
+ */
+ protected function translate_message($title, $description)
+ {
+ $message_array = array();
+
+ $message_array['title'] = call_user_func_array(array($this->language, 'lang'), (array) $title);
+
+ if ($description !== false)
+ {
+ $message_array['description'] = call_user_func_array(array($this->language, 'lang'), (array) $description);
+ }
+
+ return $message_array;
+ }
+}
diff --git a/phpBB/install/helper/iohandler/iohandler_interface.php b/phpBB/install/helper/iohandler/iohandler_interface.php
new file mode 100644
index 0000000000..cea5610586
--- /dev/null
+++ b/phpBB/install/helper/iohandler/iohandler_interface.php
@@ -0,0 +1,119 @@
+<?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;
+
+/**
+ * Input-Output handler interface for the installer
+ */
+interface iohandler_interface
+{
+ /**
+ * Renders or returns response message
+ */
+ public function send_response();
+
+ /**
+ * Returns input variable
+ *
+ * @param string $name Name of the input variable to obtain
+ * @param mixed $default A default value that is returned if the variable was not set.
+ * This function will always return a value of the same type as the default.
+ * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters
+ * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks
+ *
+ * @return mixed Value of the input variable
+ */
+ public function get_input($name, $default, $multibyte = false);
+
+ /**
+ * Returns server variable
+ *
+ * This function should work the same as request_interterface::server().
+ *
+ * @param string $name Name of the server variable
+ * @param mixed $default Default value to return when the requested variable does not exist
+ *
+ * @return mixed Value of the server variable
+ */
+ public function get_server_variable($name, $default = '');
+
+ /**
+ * Wrapper function for request_interterface::header()
+ *
+ * @param string $name Name of the request header variable
+ * @param mixed $default Default value to return when the requested variable does not exist
+ *
+ * @return mixed
+ */
+ public function get_header_variable($name, $default = '');
+
+ /**
+ * Returns true if the connection is encrypted
+ *
+ * @return bool
+ */
+ public function is_secure();
+
+ /**
+ * Adds an error message to the rendering queue
+ *
+ * Note: When an array is passed into the parameters below, it will be
+ * resolved as printf($param[0], $param[1], ...).
+ *
+ * @param string|array $error_title Title of the error message.
+ * @param string|bool|array $error_description Description of the error (and possibly guidelines to resolve it),
+ * or false if the error description is not available.
+ *
+ * @return null
+ */
+ public function add_error_message($error_title, $error_description = false);
+
+ /**
+ * Adds a warning message to the rendering queue
+ *
+ * Note: When an array is passed into the parameters below, it will be
+ * resolved as printf($param[0], $param[1], ...).
+ *
+ * @param string|array $warning_title Title of the error message
+ * @param string|bool|array $warning_description Description of the error (and possibly guidelines to resolve it),
+ * or false if the error description is not available
+ *
+ * @return null
+ */
+ public function add_warning_message($warning_title, $warning_description = false);
+
+ /**
+ * Adds a log message to the rendering queue
+ *
+ * Note: When an array is passed into the parameters below, it will be
+ * resolved as printf($param[0], $param[1], ...).
+ *
+ * @param string|array $log_title Title of the error message
+ * @param string|bool|array $log_description Description of the error (and possibly guidelines to resolve it),
+ * or false if the error description is not available
+ *
+ * @return null
+ */
+ public function add_log_message($log_title, $log_description = false);
+
+ /**
+ * Adds a requested data group to the rendering queue
+ *
+ * @param string $title Language variable with the title of the form
+ * @param array $form An array describing the required data (options etc)
+ *
+ * @return null
+ */
+ public function add_user_form_group($title, $form);
+}
diff --git a/phpBB/install/helper/navigation/install_navigation.php b/phpBB/install/helper/navigation/install_navigation.php
new file mode 100644
index 0000000000..3e29e55038
--- /dev/null
+++ b/phpBB/install/helper/navigation/install_navigation.php
@@ -0,0 +1,28 @@
+<?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\navigation;
+
+class install_navigation implements navigation_interface
+{
+ public function get()
+ {
+ return array(
+ 'install' => array(
+ 'label' => 'INSTALL',
+ 'route' => 'phpbb_installer_install',
+ 'order' => 0,
+ ),
+ );
+ }
+}
diff --git a/phpBB/install/helper/navigation/navigation_interface.php b/phpBB/install/helper/navigation/navigation_interface.php
new file mode 100644
index 0000000000..eebdbe923f
--- /dev/null
+++ b/phpBB/install/helper/navigation/navigation_interface.php
@@ -0,0 +1,43 @@
+<?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\navigation;
+
+/**
+ * Interface for installer's navigation defining services
+ */
+interface navigation_interface
+{
+ /**
+ * Returns an array with the navigation items
+ *
+ * The returned array should have the following format:
+ * <code>
+ * array(
+ * 'parent_nav_name' => array(
+ * 'nav_name' => array(
+ * 'label' => 'MY_MENU',
+ * 'route' => 'phpbb_route_name',
+ * )
+ * )
+ * )
+ * </code>
+ *
+ * Navigation item setting options:
+ * - label: The language variable name
+ * - route: Name of the route which it is belongs to
+ *
+ * @return array
+ */
+ public function get();
+}
diff --git a/phpBB/install/helper/navigation/navigation_provider.php b/phpBB/install/helper/navigation/navigation_provider.php
new file mode 100644
index 0000000000..ddb2509348
--- /dev/null
+++ b/phpBB/install/helper/navigation/navigation_provider.php
@@ -0,0 +1,92 @@
+<?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\navigation;
+
+/**
+ * Installers navigation provider
+ */
+class navigation_provider
+{
+ /**
+ * @var array
+ */
+ private $menu_collection;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\di\service_collection $plugins
+ */
+ public function __construct(\phpbb\di\service_collection $plugins)
+ {
+ $this->menu_collection = array();
+
+ foreach ($plugins as $plugin => $plugin_instance)
+ {
+ $this->register($plugin_instance);
+ }
+ }
+
+ /**
+ * Returns navigation array
+ *
+ * @return array
+ */
+ public function get()
+ {
+ return $this->menu_collection;
+ }
+
+ /**
+ * Registers a navigation provider's navigation items
+ *
+ * @param navigation_interface $navigation
+ */
+ public function register(navigation_interface $navigation)
+ {
+ $nav_arry = $navigation->get();
+ $this->merge($nav_arry, $this->menu_collection);
+ }
+
+ /**
+ * Recursive array merge
+ *
+ * This function is necessary to be able to replace the options of
+ * already set navigation items.
+ *
+ * @param array $array_to_merge
+ * @param array $array_to_merge_into
+ */
+ private function merge(&$array_to_merge, &$array_to_merge_into)
+ {
+ foreach ($array_to_merge as $key => $value)
+ {
+ if (isset($array_to_merge_into[$key]))
+ {
+ if (is_array($array_to_merge_into[$key]) && is_array($value))
+ {
+ $this->merge($value, $array_to_merge_into[$key]);
+ }
+ else
+ {
+ $array_to_merge_into[$key] = $value;
+ }
+ }
+ else
+ {
+ $array_to_merge_into[$key] = $value;
+ }
+ }
+ }
+}
diff --git a/phpBB/install/installer.php b/phpBB/install/installer.php
new file mode 100644
index 0000000000..5a2fcc4d85
--- /dev/null
+++ b/phpBB/install/installer.php
@@ -0,0 +1,146 @@
+<?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;
+
+class installer
+{
+ /**
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var array
+ */
+ protected $installer_modules;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\config $config Installer config handler
+ * @param \Symfony\Component\DependencyInjection\ContainerInterface $container Dependency injection container
+ */
+ public function __construct(\phpbb\install\helper\config $config, \Symfony\Component\DependencyInjection\ContainerInterface $container)
+ {
+ $this->install_config = $config;
+ $this->container = $container;
+ $this->installer_modules = array();
+ }
+
+ /**
+ * Sets modules to execute
+ *
+ * Note: The installer will run modules in the order they are set in
+ * the array.
+ *
+ * @param array $modules Array of module service names
+ */
+ public function set_modules($modules)
+ {
+ $modules = (array) $modules;
+
+ $this->installer_modules = $modules;
+ }
+
+ /**
+ * Run phpBB installer
+ *
+ * @return null
+ */
+ public function run()
+ {
+ // Load install progress
+ $this->install_config->load_config();
+
+ // Recover install progress
+ $module_index = $this->recover_progress();
+
+ $install_finished = false;
+
+ try
+ {
+ // Run until there are available resources
+ while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0)
+ {
+ // Check if module exists, if not the install is completed
+ if (!isset($this->installer_modules[$module_index]))
+ {
+ $install_finished = true;
+ break;
+ }
+
+ // Log progress
+ $module_service_name = $this->installer_modules[$module_index];
+ $this->install_config->set_active_module($module_service_name, $module_index);
+
+ // Get module from container
+ /** @var \phpbb\install\module_interface $module */
+ $module = $this->container->get($module_service_name);
+
+ $module_index++;
+
+ // Check if module should be executed
+ if (!$module->is_essential() && !$module->check_requirements())
+ {
+ continue;
+ }
+
+ $module->run();
+
+ // Clear task progress
+ $this->install_config->set_finished_task('', 0);
+ }
+
+ if ($install_finished)
+ {
+ die ("install finished");
+ }
+ else
+ {
+ die ("install memory or time limit reached");
+ }
+ }
+ catch (\phpbb\install\exception\user_interaction_required_exception $e)
+ {
+ // @todo handle exception
+ }
+
+ // Save install progress
+ $this->install_config->save_config();
+ }
+
+ /**
+ * Recover install progress
+ *
+ * @return int Index of the next installer module to execute
+ */
+ protected function recover_progress()
+ {
+ $progress_array = $this->install_config->get_progress_data();
+ $module_service = $progress_array['last_task_module_name'];
+ $module_index = $progress_array['last_task_module_index'];
+
+ if ($this->installer_modules[$module_index] === $module_service)
+ {
+ return $module_index;
+ }
+
+ return 0;
+ }
+}
diff --git a/phpBB/install/module_base.php b/phpBB/install/module_base.php
new file mode 100644
index 0000000000..defccaefef
--- /dev/null
+++ b/phpBB/install/module_base.php
@@ -0,0 +1,175 @@
+<?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;
+
+/**
+ * Base class for installer module
+ */
+abstract class module_base implements module_interface
+{
+ /**
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $install_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var bool
+ */
+ protected $is_essential;
+
+ /**
+ * Array of tasks for installer module
+ *
+ * @var array
+ */
+ protected $task_collection;
+
+ /**
+ * Installer module constructor
+ *
+ * @param array $tasks array of installer tasks for installer module
+ * @param bool $essential flag that indicates if module is essential or not
+ */
+ public function __construct(array $tasks, $essential = true)
+ {
+ $this->task_collection = $tasks;
+ $this->is_essential = $essential;
+ }
+
+ /**
+ * Dependency getter
+ *
+ * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
+ * @param \phpbb\install\helper\config $config
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler
+ *
+ * @return null
+ */
+ public function setup(\Symfony\Component\DependencyInjection\ContainerInterface $container, \phpbb\install\helper\config $config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler)
+ {
+ $this->container = $container;
+ $this->install_config = $config;
+ $this->iohandler = $iohandler;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_essential()
+ {
+ return $this->is_essential;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Overwrite this method if your task is non-essential!
+ */
+ public function check_requirements()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Recover install progress
+ $task_index = $this->recover_progress();
+
+ // Run until there are available resources
+ while ($this->install_config->get_time_remaining() > 0 && $this->install_config->get_memory_remaining() > 0)
+ {
+ // Check if task exists
+ if (!isset($this->task_collection[$task_index]))
+ {
+ break;
+ }
+
+ // Recover task to be executed
+ /** @var \phpbb\install\task_interface $task */
+ $task = $this->container->get($this->task_collection[$task_index]);
+
+ // Iterate to the next task
+ $task_index++;
+
+ // Check if we can run the task
+ if (!$task->is_essential() && !$task->check_requirements())
+ {
+ continue;
+ }
+
+ $task->run();
+
+ // Increment progress
+ if ($this->get_task_count() !== 0)
+ {
+ //$this->iohandler->increment_progress();
+ }
+
+ $this->iohandler->send_response();
+
+ // Log install progress
+ $current_task_index = $task_index - 1;
+ $this->install_config->set_finished_task($this->task_collection[$current_task_index], $current_task_index);
+ }
+ }
+
+ /**
+ * Returns the next task's index
+ *
+ * @return int index of the array element of the next task
+ */
+ protected function recover_progress()
+ {
+ $progress_array = $this->install_config->get_progress_data();
+ $last_finished_task_name = $progress_array['last_task_name'];
+ $last_finished_task_index = $progress_array['last_task_index'];
+
+ // Check if the data is relevant to this module
+ if (isset($this->task_collection[$last_finished_task_index]))
+ {
+ if ($this->task_collection[$last_finished_task_index] === $last_finished_task_name)
+ {
+ // Return the task index of the next task
+ return $last_finished_task_index + 1;
+ }
+ }
+
+ // As of now if the progress has not been resolved we assume that it is because
+ // the task progress belongs to the previous module,
+ // so just default to the first task
+ // @todo make module aware of it's service name that way this can be improved
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_count()
+ {
+ return sizeof($this->task_collection);
+ }
+}
diff --git a/phpBB/install/module_interface.php b/phpBB/install/module_interface.php
new file mode 100644
index 0000000000..e0ec4e4347
--- /dev/null
+++ b/phpBB/install/module_interface.php
@@ -0,0 +1,56 @@
+<?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;
+
+/**
+ * Interface for installer modules
+ *
+ * An installer module is a task collection which executes installer tasks.
+ */
+interface module_interface
+{
+ /**
+ * Checks if the execution of the module is essential to install phpBB or it can be skipped
+ *
+ * Note: Please note that all the non-essential modules have to implement check_requirements()
+ * method.
+ *
+ * @return bool true if the module is essential, false otherwise
+ */
+ public function is_essential();
+
+ /**
+ * Checks requirements for the tasks
+ *
+ * Note: Only need to be implemented for non-essential tasks, as essential tasks
+ * requirements should be checked in the requirements install module.
+ *
+ * @return bool true if the task's requirements are met
+ */
+ public function check_requirements();
+
+ /**
+ * Executes the task
+ *
+ * @return null
+ */
+ public function run();
+
+ /**
+ * Returns the number of tasks in the module
+ *
+ * @return int
+ */
+ public function get_task_count();
+}
diff --git a/phpBB/install/task_base.php b/phpBB/install/task_base.php
new file mode 100644
index 0000000000..5946be8c52
--- /dev/null
+++ b/phpBB/install/task_base.php
@@ -0,0 +1,53 @@
+<?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;
+
+/**
+ * Base class for installer task
+ */
+abstract class task_base implements task_interface
+{
+ /**
+ * @var bool
+ */
+ protected $is_essential;
+
+ /**
+ * Constructor
+ *
+ * @param bool $essential
+ */
+ public function __construct($essential = true)
+ {
+ $this->is_essential = $essential;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function is_essential()
+ {
+ return $this->is_essential;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Overwrite this method if your task is non-essential!
+ */
+ public function check_requirements()
+ {
+ return true;
+ }
+}
diff --git a/phpBB/install/task_interface.php b/phpBB/install/task_interface.php
new file mode 100644
index 0000000000..9cfc4d19c2
--- /dev/null
+++ b/phpBB/install/task_interface.php
@@ -0,0 +1,47 @@
+<?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;
+
+/**
+ * Interface for installer tasks
+ */
+interface task_interface
+{
+ /**
+ * Checks if the task is essential to install phpBB or it can be skipped
+ *
+ * Note: Please note that all the non-essential modules have to implement check_requirements()
+ * method.
+ *
+ * @return bool true if the task is essential, false otherwise
+ */
+ public function is_essential();
+
+ /**
+ * Checks requirements for the tasks
+ *
+ * Note: Only need to be implemented for non-essential tasks, as essential tasks
+ * requirements should be checked in the requirements install module.
+ *
+ * @return bool true if the task's requirements are met
+ */
+ public function check_requirements();
+
+ /**
+ * Executes the task
+ *
+ * @return null
+ */
+ public function run();
+}