3 namespace Friendica\Module;
6 use Friendica\BaseModule;
7 use Friendica\Database\DBA;
8 use Friendica\Database\DBStructure;
10 use Friendica\Core\L10n;
11 use Friendica\Util\Temporal;
13 class Install extends BaseModule
16 * Step one - System check
18 const SYSTEM_CHECK = 1;
20 * Step two - Database configuration
22 const DATABASE_CONFIG = 2;
24 * Step three - Adapat site settings
26 const SITE_SETTINGS = 3;
28 * Step four - All steps finished
32 // Default values for the install page
33 const DEFAULT_LANG = 'en';
34 const DEFAULT_TZ = 'America/Los_Angeles';
35 const DEFAULT_HOST = 'localhost';
38 * @var int The current step of the wizard
40 private static $currentWizardStep;
42 public static function init()
46 // route: install/testrwrite
47 // $baseurl/install/testrwrite to test if rewrite in .htaccess is working
48 if ($a->getArgumentValue(1, '') == 'testrewrite') {
49 // Status Code 204 means that it worked without content
50 Core\System::httpExit(204);
53 // We overwrite current theme css, because during install we may not have a working mod_rewrite
54 // so we may not have a css at all. Here we set a static css file for the install procedure pages
55 $a->setConfigValue('system', 'value', '../install');
56 $a->theme['stylesheet'] = $a->getBaseURL() . '/view/install/style.css';
58 self::$currentWizardStep = defaults($_POST, 'pass', self::SYSTEM_CHECK);
61 public static function post()
65 switch (self::$currentWizardStep) {
66 case self::SYSTEM_CHECK:
67 case self::DATABASE_CONFIG:
68 // Nothing to do in these steps
71 case self::SITE_SETTINGS:
72 $dbhost = notags(trim(defaults($_POST, 'dbhost', self::DEFAULT_HOST)));
73 $dbuser = notags(trim(defaults($_POST, 'dbuser', '')));
74 $dbpass = notags(trim(defaults($_POST, 'dbpass', '')));
75 $dbdata = notags(trim(defaults($_POST, 'dbdata', '')));
77 require_once 'include/dba.php';
78 if (!DBA::connect($dbhost, $dbuser, $dbpass, $dbdata)) {
79 $a->data['db_conn_failed'] = true;
85 $urlpath = $a->getURLPath();
86 $dbhost = notags(trim(defaults($_POST, 'dbhost', self::DEFAULT_HOST)));
87 $dbuser = notags(trim(defaults($_POST, 'dbuser', '')));
88 $dbpass = notags(trim(defaults($_POST, 'dbpass', '')));
89 $dbdata = notags(trim(defaults($_POST, 'dbdata', '')));
90 $phpath = notags(trim(defaults($_POST, 'phpath', '')));
91 $timezone = notags(trim(defaults($_POST, 'timezone', self::DEFAULT_TZ)));
92 $language = notags(trim(defaults($_POST, 'language', self::DEFAULT_LANG)));
93 $adminmail = notags(trim(defaults($_POST, 'adminmail', '')));
96 DBA::connect($dbhost, $dbuser, $dbpass, $dbdata);
98 $install = new Core\Install();
100 $errors = $install->createConfig($phpath, $urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $timezone, $language, $adminmail, $a->getBasePath());
102 if ($errors !== true) {
103 $a->data['txt'] = $errors;
107 $errors = DBStructure::update(false, true, true);
110 $a->data['db_failed'] = $errors;
112 $a->data['db_installed'] = true;
122 public static function content()
128 $install_title = L10n::t('Friendica Communctions Server - Setup');
129 $wizard_status = self::checkWizardStatus($a);
131 switch (self::$currentWizardStep) {
132 case self::SYSTEM_CHECK:
133 $phppath = defaults($_POST, 'phpath', null);
135 $install = new Core\Install();
136 $status = $install->checkAll($a->getBaseURL(), $phppath);
138 $tpl = get_markup_template('install_checks.tpl');
139 $output .= replace_macros($tpl, [
140 '$title' => $install_title,
141 '$pass' => L10n::t('System check'),
142 '$checks' => $install->getChecks(),
143 '$passed' => $status,
144 '$see_install' => L10n::t('Please see the file "Install.txt".'),
145 '$next' => L10n::t('Next'),
146 '$reload' => L10n::t('Check again'),
147 '$phpath' => $phppath,
148 '$baseurl' => $a->getBaseURL()
152 case self::DATABASE_CONFIG:
153 $dbhost = notags(trim(defaults($_POST, 'dbhost' , self::DEFAULT_HOST)));
154 $dbuser = notags(trim(defaults($_POST, 'dbuser' , '')));
155 $dbpass = notags(trim(defaults($_POST, 'dbpass' , '')));
156 $dbdata = notags(trim(defaults($_POST, 'dbdata' , '')));
157 $phpath = notags(trim(defaults($_POST, 'phpath' , '')));
158 $adminmail = notags(trim(defaults($_POST, 'adminmail', '')));
160 $tpl = get_markup_template('install_db.tpl');
161 $output .= replace_macros($tpl, [
162 '$title' => $install_title,
163 '$pass' => L10n::t('Database connection'),
164 '$info_01' => L10n::t('In order to install Friendica we need to know how to connect to your database.'),
165 '$info_02' => L10n::t('Please contact your hosting provider or site administrator if you have questions about these settings.'),
166 '$info_03' => L10n::t('The database you specify below should already exist. If it does not, please create it before continuing.'),
167 '$status' => $wizard_status,
168 '$dbhost' => ['dbhost',
169 L10n::t('Database Server Name'),
173 '$dbuser' => ['dbuser',
174 L10n::t('Database Login Name'),
179 '$dbpass' => ['dbpass',
180 L10n::t('Database Login Password'),
182 L10n::t("For security reasons the password must not be empty"),
184 '$dbdata' => ['dbdata',
185 L10n::t('Database Name'),
189 '$adminmail' => ['adminmail',
190 L10n::t('Site administrator email address'),
192 L10n::t('Your account email address must match this in order to use the web admin panel.'),
196 '$lbl_10' => L10n::t('Please select a default timezone for your website'),
197 '$baseurl' => $a->getBaseURL(),
198 '$phpath' => $phpath,
199 '$submit' => L10n::t('Submit')
202 case self::SITE_SETTINGS:
203 $dbhost = notags(trim(defaults($_POST, 'dbhost', self::DEFAULT_HOST)));
204 $dbuser = notags(trim(defaults($_POST, 'dbuser', '' )));
205 $dbpass = notags(trim(defaults($_POST, 'dbpass', '' )));
206 $dbdata = notags(trim(defaults($_POST, 'dbdata', '' )));
207 $phpath = notags(trim(defaults($_POST, 'phpath', '' )));
209 $adminmail = notags(trim(defaults($_POST, 'adminmail', '')));
211 $timezone = defaults($_POST, 'timezone', self::DEFAULT_TZ);
212 /* Installed langs */
213 $lang_choices = L10n::getAvailableLanguages();
215 $tpl = get_markup_template('install_settings.tpl');
216 $output .= replace_macros($tpl, [
217 '$title' => $install_title,
218 '$pass' => L10n::t('Site settings'),
219 '$status' => $wizard_status,
220 '$dbhost' => $dbhost,
221 '$dbuser' => $dbuser,
222 '$dbpass' => $dbpass,
223 '$dbdata' => $dbdata,
224 '$phpath' => $phpath,
225 '$adminmail' => ['adminmail', L10n::t('Site administrator email address'), $adminmail, L10n::t('Your account email address must match this in order to use the web admin panel.'), 'required', 'autofocus', 'email'],
226 '$timezone' => Temporal::getTimezoneField('timezone', L10n::t('Please select a default timezone for your website'), $timezone, ''),
227 '$language' => ['language',
228 L10n::t('System Language:'), #
230 L10n::t('Set the default language for your Friendica installation interface and to send emails.'),
232 '$baseurl' => $a->getBaseURL(),
233 '$submit' => L10n::t('Submit')
238 $db_return_text = "";
240 if (defaults($a->data, 'db_installed', false)) {
241 $txt = '<p style="font-size: 130%;">';
242 $txt .= L10n::t('Your Friendica site database has been installed.') . EOL;
243 $db_return_text .= $txt;
246 if (defaults($a->data, 'db_failed', false)) {
247 $txt = L10n::t('You may need to import the file "database.sql" manually using phpmyadmin or mysql.') . EOL;
248 $txt .= L10n::t('Please see the file "INSTALL.txt".') . EOL ."<hr>";
249 $txt .= "<pre>".$a->data['db_failed'] . "</pre>". EOL;
250 $db_return_text .= $txt;
253 if (isset($a->data['txt']) && strlen($a->data['txt'])) {
254 $db_return_text .= self::manualConfig($a);
257 $tpl = get_markup_template('install.tpl');
258 $output .= replace_macros($tpl, [
259 '$title' => $install_title,
261 '$text' => $db_return_text . self::whatNext($a),
271 * @param App $a The global Friendica App
273 * @return string The status of Wizard steps
275 private static function checkWizardStatus($a)
279 if (defaults($a->data, 'db_conn_failed', false)) {
280 self::$currentWizardStep = 2;
281 $wizardStatus = L10n::t('Could not connect to database.');
284 if (defaults($a->data, 'db_create_failed', false)) {
285 self::$currentWizardStep = 2;
286 $wizardStatus = L10n::t('Could not create table.');
289 if (DBA::connected()) {
290 if (DBA::count('user')) {
291 self::$currentWizardStep = 2;
292 $wizardStatus = L10n::t('Database already in use.');
296 return $wizardStatus;
300 * Creates the text for manual config
302 * @param App $a The global App
304 * @return string The manual config text
306 private static function manualConfig($a)
308 $data = htmlentities($a->data['txt'], ENT_COMPAT, 'UTF-8');
309 $output = L10n::t('The database configuration file "config/local.ini.php" could not be written. Please use the enclosed text to create a configuration file in your web server root.');
310 $output .= "<textarea rows=\"24\" cols=\"80\" >$data</textarea>";
315 * Creates the text for the next steps
317 * @param App $a The global App
319 * @return string The text for the next steps
321 private static function whatNext($a)
323 $baseurl = $a->getBaseUrl();
325 L10n::t('<h1>What next</h1>')
326 . "<p>".L10n::t('IMPORTANT: You will need to [manually] setup a scheduled task for the worker.')
327 . L10n::t('Please see the file "INSTALL.txt".')
329 . L10n::t('Go to your new Friendica node <a href="%s/register">registration page</a> and register as new user. Remember to use the same email you have entered as administrator email. This will allow you to enter the site admin panel.', $baseurl)