]> git.mxchange.org Git - friendica.git/blob - src/Console/AutomaticInstallation.php
Update copyright
[friendica.git] / src / Console / AutomaticInstallation.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2022, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Console;
23
24 use Asika\SimpleConsole\Console;
25 use Friendica\App;
26 use Friendica\App\BaseURL;
27 use Friendica\Core\Config\Capability\IManageConfigValues;
28 use Friendica\Core\Config\ValueObject\Cache;
29 use Friendica\Core\Installer;
30 use Friendica\Core\Theme;
31 use Friendica\Database\Database;
32 use Friendica\Util\BasePath;
33 use RuntimeException;
34
35 class AutomaticInstallation extends Console
36 {
37         /** @var App\Mode */
38         private $appMode;
39         /** @var \Friendica\Core\Config\ValueObject\Cache */
40         private $configCache;
41         /** @var IManageConfigValues */
42         private $config;
43         /** @var Database */
44         private $dba;
45
46         protected function getHelp()
47         {
48                 return <<<HELP
49 Installation - Install Friendica automatically
50 Synopsis
51         bin/console autoinstall [-h|--help|-?] [-v] [-a] [-f]
52
53 Description
54     Installs Friendica with data based on the local.config.php file or environment variables
55
56 Notes
57     Not checking .htaccess/URL-Rewrite during CLI installation.
58
59 Options
60     -h|--help|-?            Show help information
61     -v                      Show more debug information.
62     -a                      All setup checks are required (except .htaccess)
63     -f|--file <config>      prepared config file (e.g. "config/local.config.php" itself) which will override every other config option - except the environment variables)
64     -s|--savedb               Save the DB credentials to the file (if environment variables is used)
65     -H|--dbhost <host>        The host of the mysql/mariadb database (env MYSQL_HOST)
66     -p|--dbport <port>        The port of the mysql/mariadb database (env MYSQL_PORT)
67     -d|--dbdata <database>    The name of the mysql/mariadb database (env MYSQL_DATABASE)
68     -u|--dbuser <username>    The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
69     -P|--dbpass <password>    The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
70     -U|--url <url>            The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL) 
71     -B|--phppath <php_path>   The path of the PHP binary (env FRIENDICA_PHP_PATH)
72     -b|--basepath <base_path> The basepath of Friendica (env FRIENDICA_BASE_PATH)
73     -t|--tz <timezone>        The timezone of Friendica (env FRIENDICA_TZ)
74     -L|--lang <language>      The language of Friendica (env FRIENDICA_LANG)
75  
76 Environment variables
77    MYSQL_HOST                  The host of the mysql/mariadb database (mandatory if mysql and environment is used)
78    MYSQL_PORT                  The port of the mysql/mariadb database
79    MYSQL_USERNAME|MYSQL_USER   The username of the mysql/mariadb database login (MYSQL_USERNAME is for mysql, MYSQL_USER for mariadb)
80    MYSQL_PASSWORD              The password of the mysql/mariadb database login
81    MYSQL_DATABASE              The name of the mysql/mariadb database
82    FRIENDICA_URL               The full base URL of Friendica - f.e. 'https://friendica.local/sub'
83    FRIENDICA_PHP_PATH          The path of the PHP binary - leave empty for auto detection
84    FRIENDICA_BASE_PATH         The basepath of Friendica - leave empty for auto detection
85    FRIENDICA_ADMIN_MAIL        The admin email address of Friendica (this email will be used for admin access)
86    FRIENDICA_TZ                The timezone of Friendica
87    FRIENDICA_LANG              The langauge of Friendica
88    
89 Examples
90         bin/console autoinstall -f 'input.config.php
91                 Installs Friendica with the prepared 'input.config.php' file
92
93         bin/console autoinstall --savedb
94                 Installs Friendica with environment variables and saves them to the 'config/local.config.php' file
95
96         bin/console autoinstall -H localhost -p 3365 -u user -P passwort1234 -d friendica -U https://friendica.fqdn
97                 Installs Friendica with a local mysql database with credentials
98 HELP;
99         }
100
101         public function __construct(App\Mode $appMode, Cache $configCache, IManageConfigValues $config, Database $dba, array $argv = null)
102         {
103                 parent::__construct($argv);
104
105                 $this->appMode     = $appMode;
106                 $this->configCache = $configCache;
107                 $this->config      = $config;
108                 $this->dba         = $dba;
109         }
110
111         protected function doExecute()
112         {
113                 // Initialise the app
114                 $this->out("Initializing setup...");
115
116                 $installer = new Installer();
117
118                 $configCache  = $this->configCache;
119                 $basePathConf = $configCache->get('system', 'basepath');
120                 $basepath     = new BasePath($basePathConf);
121                 $installer->setUpCache($configCache, $basepath->getPath());
122
123                 $this->out(" Complete!\n");
124
125                 // Check Environment
126                 $this->out("Checking environment...");
127
128                 $installer->resetChecks();
129
130                 if (!$this->runBasicChecks($installer, $configCache)) {
131                         $errorMessage = $this->extractErrors($installer->getChecks());
132                         throw new RuntimeException($errorMessage);
133                 }
134
135                 $this->out(" Complete!\n");
136
137                 // if a config file is set,
138                 $config_file = $this->getOption(['f', 'file']);
139
140                 if (!empty($config_file)) {
141                         $this->out("Loading config file '$config_file'...");
142                         if (!file_exists($config_file)) {
143                                 throw new RuntimeException("ERROR: Config file does not exist.");
144                         }
145
146                         //append config file to the config cache
147                         $config = include($config_file);
148                         if (!is_array($config)) {
149                                 throw new Exception('Error loading config file ' . $config_file);
150                         }
151                         $configCache->load($config, Cache::SOURCE_FILE);
152                 } else {
153                         // Creating config file
154                         $this->out("Creating config file...");
155
156                         $save_db = $this->getOption(['s', 'savedb'], false);
157
158                         $db_host = $this->getOption(['H', 'dbhost'], ($save_db) ? (getenv('MYSQL_HOST')) : Installer::DEFAULT_HOST);
159                         $db_port = $this->getOption(['p', 'dbport'], ($save_db) ? getenv('MYSQL_PORT') : null);
160                         $configCache->set('database', 'hostname', $db_host . (!empty($db_port) ? ':' . $db_port : ''));
161                         $configCache->set('database', 'database',
162                                 $this->getOption(['d', 'dbdata'],
163                                         ($save_db) ? getenv('MYSQL_DATABASE') : ''));
164                         $configCache->set('database', 'username',
165                                 $this->getOption(['u', 'dbuser'],
166                                         ($save_db) ? getenv('MYSQL_USER') . getenv('MYSQL_USERNAME') : ''));
167                         $configCache->set('database', 'password',
168                                 $this->getOption(['P', 'dbpass'],
169                                         ($save_db) ? getenv('MYSQL_PASSWORD') : ''));
170
171                         $php_path = $this->getOption(['b', 'phppath'], !empty('FRIENDICA_PHP_PATH') ? getenv('FRIENDICA_PHP_PATH') : null);
172                         if (!empty($php_path)) {
173                                 $configCache->set('config', 'php_path', $php_path);
174                         } else {
175                                 $configCache->set('config', 'php_path', $installer->getPHPPath());
176                         }
177
178                         $configCache->set('config', 'admin_email',
179                                 $this->getOption(['A', 'admin'],
180                                         !empty(getenv('FRIENDICA_ADMIN_MAIL')) ? getenv('FRIENDICA_ADMIN_MAIL') : ''));
181                         $configCache->set('system', 'default_timezone',
182                                 $this->getOption(['T', 'tz'],
183                                         !empty(getenv('FRIENDICA_TZ')) ? getenv('FRIENDICA_TZ') : Installer::DEFAULT_TZ));
184                         $configCache->set('system', 'language',
185                                 $this->getOption(['L', 'lang'],
186                                         !empty(getenv('FRIENDICA_LANG')) ? getenv('FRIENDICA_LANG') : Installer::DEFAULT_LANG));
187
188                         $basepath = $this->getOption(['b', 'basepath'], !empty(getenv('FRIENDICA_BASE_PATH')) ? getenv('FRIENDICA_BASE_PATH') : null);
189                         if (!empty($basepath)) {
190                                 $configCache->set('system', 'basepath', $basepath);
191                         }
192
193                         $url = $this->getOption(['U', 'url'], !empty(getenv('FRIENDICA_URL')) ? getenv('FRIENDICA_URL') : null);
194
195                         if (empty($url)) {
196                                 $this->out('The Friendica URL has to be set during CLI installation.');
197                                 return 1;
198                         } else {
199                                 $baseUrl = new BaseURL($this->config, []);
200                                 $baseUrl->saveByURL($url);
201                         }
202
203                         $installer->createConfig($configCache);
204                 }
205
206                 $this->out(" Complete!\n");
207
208                 // Check database connection
209                 $this->out("Checking database...");
210
211                 $installer->resetChecks();
212
213                 if (!$installer->checkDB($this->dba)) {
214                         $errorMessage = $this->extractErrors($installer->getChecks());
215                         throw new RuntimeException($errorMessage);
216                 }
217
218                 $this->out(" Complete!\n");
219
220                 // Install database
221                 $this->out("Inserting data into database...\n");
222
223                 $installer->resetChecks();
224
225                 if (!$installer->installDatabase($basePathConf)) {
226                         $errorMessage = $this->extractErrors($installer->getChecks());
227                         throw new RuntimeException($errorMessage);
228                 }
229
230                 if (!empty($config_file) && $config_file != 'config' . DIRECTORY_SEPARATOR . 'local.config.php') {
231                         // Copy config file
232                         $this->out("Copying config file...");
233                         if (!copy($config_file, $basePathConf . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.config.php')) {
234                                 throw new RuntimeException("ERROR: Saving config file failed. Please copy '$config_file' to '" . $basePathConf . "'" . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "local.config.php' manually.\n");
235                         }
236                 }
237
238                 $this->out(" Complete!\n");
239
240                 // Install theme
241                 $this->out("Installing theme");
242                 if (!empty($this->config->get('system', 'theme'))) {
243                         Theme::install($this->config->get('system', 'theme'));
244                         $this->out(" Complete\n");
245                 } else {
246                         $this->out(" Theme setting is empty. Please check the file 'config/local.config.php'\n");
247                 }
248
249                 $this->out("\nInstallation is finished");
250
251                 return 0;
252         }
253
254         /**
255          * @param Installer                                $installer   The Installer instance
256          * @param \Friendica\Core\Config\ValueObject\Cache $configCache The config cache
257          *
258          * @return bool true if checks were successfully, otherwise false
259          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
260          */
261         private function runBasicChecks(Installer $installer, Cache $configCache)
262         {
263                 $checked = true;
264
265                 $installer->resetChecks();
266                 if (!$installer->checkFunctions()) {
267                         $checked = false;
268                 }
269                 if (!$installer->checkImagick()) {
270                         $checked = false;
271                 }
272                 if (!$installer->checkLocalIni()) {
273                         $checked = false;
274                 }
275                 if (!$installer->checkSmarty3()) {
276                         $checked = false;
277                 }
278                 if (!$installer->checkKeys()) {
279                         $checked = false;
280                 }
281
282                 $php_path = $configCache->get('config', 'php_path');
283
284                 if (!$installer->checkPHP($php_path, true)) {
285                         $checked = false;
286                 }
287
288                 $this->out(" NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.\n");
289
290                 return $checked;
291         }
292
293         /**
294          * @param array $results
295          *
296          * @return string
297          */
298         private function extractErrors($results)
299         {
300                 $errorMessage      = '';
301                 $allChecksRequired = $this->getOption('a') !== null;
302
303                 foreach ($results as $result) {
304                         if (($allChecksRequired || $result['required'] === true) && $result['status'] === false) {
305                                 $errorMessage .= "--------\n";
306                                 $errorMessage .= $result['title'] . ': ' . $result['help'] . "\n";
307                         }
308                 }
309
310                 return $errorMessage;
311         }
312 }