/**
  * Starts the installation
  *
  * @param array $DB
  */
 public function startInstall(array $DB = null)
 {
     $query = $uninst = $dbSetup = [];
     // Check table prefix
     $dbSetup['dbPrefix'] = $sqltblpre = PMF_Filter::filterInput(INPUT_POST, 'sqltblpre', FILTER_SANITIZE_STRING, '');
     if ('' !== $dbSetup['dbPrefix']) {
         PMF_Db::setTablePrefix($dbSetup['dbPrefix']);
     }
     // Check database entries
     $dbSetup['dbType'] = PMF_Filter::filterInput(INPUT_POST, 'sql_type', FILTER_SANITIZE_STRING);
     if (!is_null($dbSetup['dbType'])) {
         $dbSetup['dbType'] = trim($dbSetup['dbType']);
         if (!file_exists(PMF_ROOT_DIR . '/setup/assets/sql/' . $dbSetup['dbType'] . '.sql.php')) {
             printf('<p class="alert alert-danger"><strong>Error:</strong> Invalid server type: %s</p>', $dbSetup['dbType']);
             PMF_System::renderFooter(true);
         }
     } else {
         echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please select a database type.</p>\n";
         PMF_System::renderFooter(true);
     }
     $dbSetup['dbServer'] = PMF_Filter::filterInput(INPUT_POST, 'sql_server', FILTER_SANITIZE_STRING);
     if (is_null($dbSetup['dbServer']) && !PMF_System::isSqlite($dbSetup['dbType'])) {
         echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a database server.</p>\n";
         PMF_System::renderFooter(true);
     }
     $dbSetup['dbPort'] = PMF_Filter::filterInput(INPUT_POST, 'sql_port', FILTER_VALIDATE_INT);
     if (is_null($dbSetup['dbPort']) && !PMF_System::isSqlite($dbSetup['dbType'])) {
         echo "<p class=\"alert alert-error\"><strong>Error:</strong> Please add a valid database port.</p>\n";
         PMF_System::renderFooter(true);
     }
     $dbSetup['dbUser'] = PMF_Filter::filterInput(INPUT_POST, 'sql_user', FILTER_SANITIZE_STRING);
     if (is_null($dbSetup['dbUser']) && !PMF_System::isSqlite($dbSetup['dbType'])) {
         echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a database username.</p>\n";
         PMF_System::renderFooter(true);
     }
     $dbSetup['dbPassword'] = PMF_Filter::filterInput(INPUT_POST, 'sql_passwort', FILTER_UNSAFE_RAW);
     if (is_null($dbSetup['dbPassword']) && !PMF_System::isSqlite($dbSetup['dbType'])) {
         // Password can be empty...
         $dbSetup['dbPassword'] = '';
     }
     $dbSetup['dbDatabaseName'] = PMF_Filter::filterInput(INPUT_POST, 'sql_db', FILTER_SANITIZE_STRING);
     if (is_null($dbSetup['dbDatabaseName']) && !PMF_System::isSqlite($dbSetup['dbType'])) {
         echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a database name.</p>\n";
         PMF_System::renderFooter(true);
     }
     if (PMF_System::isSqlite($dbSetup['dbType'])) {
         $dbSetup['dbServer'] = PMF_Filter::filterInput(INPUT_POST, 'sql_sqlitefile', FILTER_SANITIZE_STRING);
         if (is_null($dbSetup['dbServer'])) {
             echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a SQLite database filename.</p>\n";
             PMF_System::renderFooter(true);
         }
     }
     // check database connection
     PMF_Db::setTablePrefix($dbSetup['dbPrefix']);
     $db = PMF_Db::factory($dbSetup['dbType']);
     $db->connect($dbSetup['dbServer'], $dbSetup['dbUser'], $dbSetup['dbPassword'], $dbSetup['dbDatabaseName']);
     if (!$db) {
         printf("<p class=\"alert alert-danger\"><strong>DB Error:</strong> %s</p>\n", $db->error());
         PMF_System::renderFooter(true);
     }
     $configuration = new PMF_Configuration($db);
     // check LDAP if available
     $ldapEnabled = PMF_Filter::filterInput(INPUT_POST, 'ldap_enabled', FILTER_SANITIZE_STRING);
     if (extension_loaded('ldap') && !is_null($ldapEnabled)) {
         $ldapSetup = [];
         // check LDAP entries
         $ldapSetup['ldapServer'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_server', FILTER_SANITIZE_STRING);
         if (is_null($ldapSetup['ldapServer'])) {
             echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a LDAP server.</p>\n";
             PMF_System::renderFooter(true);
         }
         $ldapSetup['ldapPort'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_port', FILTER_VALIDATE_INT);
         if (is_null($ldapSetup['ldapPort'])) {
             echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a LDAP port.</p>\n";
             PMF_System::renderFooter(true);
         }
         $ldapSetup['ldapBase'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_base', FILTER_SANITIZE_STRING);
         if (is_null($ldapSetup['ldapBase'])) {
             echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Please add a LDAP base search DN.</p>\n";
             PMF_System::renderFooter(true);
         }
         // LDAP User and LDAP password are optional
         $ldapSetup['ldapUser'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_user', FILTER_SANITIZE_STRING, '');
         $ldapSetup['ldapPassword'] = PMF_Filter::filterInput(INPUT_POST, 'ldap_password', FILTER_SANITIZE_STRING, '');
         // check LDAP connection
         require PMF_ROOT_DIR . "/inc/PMF/Ldap.php";
         $ldap = new PMF_Ldap($configuration);
         $ldap->connect($ldapSetup['ldapServer'], $ldapSetup['ldapPort'], $ldapSetup['ldapBase'], $ldapSetup['ldapUser'], $ldapSetup['ldapPassword']);
         if (!$ldap) {
             echo "<p class=\"alert alert-danger\"><strong>LDAP Error:</strong> " . $ldap->error() . "</p>\n";
             PMF_System::renderFooter(true);
         }
     }
     // check loginname
     $loginname = PMF_Filter::filterInput(INPUT_POST, 'loginname', FILTER_SANITIZE_STRING);
     if (is_null($loginname)) {
         echo '<p class="alert alert-danger"><strong>Error:</strong> Please add a loginname for your account.</p>';
         PMF_System::renderFooter(true);
     }
     // check user entries
     $password = PMF_Filter::filterInput(INPUT_POST, 'password', FILTER_SANITIZE_STRING);
     if (is_null($password)) {
         echo '<p class="alert alert-danger"><strong>Error:</strong> Please add a password for the your account.</p>';
         PMF_System::renderFooter(true);
     }
     $password_retyped = PMF_Filter::filterInput(INPUT_POST, 'password_retyped', FILTER_SANITIZE_STRING);
     if (is_null($password_retyped)) {
         echo '<p class="alert alert-danger"><strong>Error:</strong> Please add a retyped password.</p>';
         PMF_System::renderFooter(true);
     }
     if (strlen($password) <= 5 || strlen($password_retyped) <= 5) {
         echo '<p class="alert alert-danger"><strong>Error:</strong> Your password and retyped password are too short.' . ' Please set your password and your retyped password with a minimum of 6 characters.</p>';
         PMF_System::renderFooter(true);
     }
     if ($password != $password_retyped) {
         echo '<p class="alert alert-danger"><strong>Error:</strong> Your password and retyped password are not equal.' . ' Please check your password and your retyped password.</p>';
         PMF_System::renderFooter(true);
     }
     $language = PMF_Filter::filterInput(INPUT_POST, 'language', FILTER_SANITIZE_STRING, 'en');
     $realname = PMF_Filter::filterInput(INPUT_POST, 'realname', FILTER_SANITIZE_STRING, '');
     $email = PMF_Filter::filterInput(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL, '');
     $permLevel = PMF_Filter::filterInput(INPUT_POST, 'permLevel', FILTER_SANITIZE_STRING, 'basic');
     $instanceSetup = new PMF_Instance_Setup();
     $instanceSetup->setRootDir(PMF_ROOT_DIR);
     // Write the DB variables in database.php
     if (!$instanceSetup->createDatabaseFile($dbSetup)) {
         echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Setup cannot write to ./config/database.php.</p>";
         $this->_system->cleanInstallation();
         PMF_System::renderFooter(true);
     }
     // check LDAP if available
     if (extension_loaded('ldap') && !is_null($ldapEnabled)) {
         if (!$instanceSetup->createLdapFile($ldapSetup, '')) {
             echo "<p class=\"alert alert-danger\"><strong>Error:</strong> Setup cannot write to ./config/ldap.php.</p>";
             $this->_system->cleanInstallation();
             PMF_System::renderFooter(true);
         }
     }
     // connect to the database using config/database.php
     require PMF_ROOT_DIR . '/config/database.php';
     $db = PMF_Db::factory($dbSetup['dbType']);
     $db->connect($DB['server'], $DB['user'], $DB['password'], $DB['db']);
     if (!$db) {
         echo "<p class=\"alert alert-danger\"><strong>DB Error:</strong> " . $db->error() . "</p>\n";
         $this->_system->cleanInstallation();
         PMF_System::renderFooter(true);
     }
     require PMF_ROOT_DIR . '/setup/assets/sql/' . $dbSetup['dbType'] . '.sql.php';
     // CREATE TABLES
     require PMF_ROOT_DIR . '/setup/assets/sql/stopwords.sql.php';
     // INSERTs for stopwords
     $this->_system->setDatabase($db);
     echo '<p>';
     // Erase any table before starting creating the required ones
     if (!PMF_System::isSqlite($dbSetup['dbType'])) {
         $this->_system->dropTables($uninst);
     }
     // Start creating the required tables
     $count = 0;
     foreach ($query as $executeQuery) {
         $result = @$db->query($executeQuery);
         if (!$result) {
             echo '<p class="alert alert-danger"><strong>Error:</strong> Please install your version of phpMyFAQ once again or send
         us a <a href=\\"http://www.phpmyfaq.de\\" target=\\"_blank\\">bug report</a>.</p>';
             printf('<p class="alert alert-danger"><strong>DB error:</strong> %s</p>', $db->error());
             printf('<code>%s</code>', htmlentities($executeQuery));
             $this->_system->dropTables($uninst);
             $this->_system->cleanInstallation();
             PMF_System::renderFooter(true);
         }
         usleep(2500);
         $count++;
         if (!($count % 10)) {
             echo '| ';
         }
     }
     $link = new PMF_Link(null, $configuration);
     // add main configuration, add personal settings
     $this->_mainConfig['main.metaPublisher'] = $realname;
     $this->_mainConfig['main.administrationMail'] = $email;
     $this->_mainConfig['main.language'] = $language;
     $this->_mainConfig['security.permLevel'] = $permLevel;
     foreach ($this->_mainConfig as $name => $value) {
         $configuration->add($name, $value);
     }
     $configuration->update(array('main.referenceURL' => $link->getSystemUri('/setup/index.php')));
     $configuration->add('security.salt', md5($configuration->get('main.referenceURL')));
     // add admin account and rights
     $admin = new PMF_User($configuration);
     if (!$admin->createUser($loginname, $password, 1)) {
         printf("<p class=\"alert alert-danger\"><strong>Fatal installation error:</strong><br>" . "Couldn't create the admin user: %s</p>\n", $admin->error());
         $this->_system->cleanInstallation();
         PMF_System::renderFooter(true);
     }
     $admin->setStatus('protected');
     $adminData = array('display_name' => $realname, 'email' => $email);
     $admin->setUserData($adminData);
     // add default rights
     foreach ($this->_mainRights as $right) {
         $admin->perm->grantUserRight(1, $admin->perm->addRight($right));
     }
     // Add anonymous user account
     $instanceSetup->createAnonymousUser($configuration);
     // Add master instance
     $instanceData = array('url' => $link->getSystemUri($_SERVER['SCRIPT_NAME']), 'instance' => $link->getSystemRelativeUri('setup/index.php'), 'comment' => 'phpMyFAQ ' . PMF_System::getVersion());
     $faqInstance = new PMF_Instance($configuration);
     $faqInstance->addInstance($instanceData);
     $faqInstanceMaster = new PMF_Instance_Master($configuration);
     $faqInstanceMaster->createMaster($faqInstance);
     echo '</p>';
 }