]> git.mxchange.org Git - friendica.git/blob - src/Console/AutomaticInstallation.php
Convert class calls into DI calls
[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     -s|--dbsocket <socket>    The socket of the mysql/mariadb database (env MYSQL_SOCKET)
68     -d|--dbdata <database>    The name of the mysql/mariadb database (env MYSQL_DATABASE)
69     -u|--dbuser <username>    The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
70     -P|--dbpass <password>    The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
71     -U|--url <url>            The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL) 
72     -B|--phppath <php_path>   The path of the PHP binary (env FRIENDICA_PHP_PATH)
73     -b|--basepath <base_path> The basepath of Friendica (env FRIENDICA_BASE_PATH)
74     -t|--tz <timezone>        The timezone of Friendica (env FRIENDICA_TZ)
75     -L|--lang <language>      The language of Friendica (env FRIENDICA_LANG)
76  
77 Environment variables
78    MYSQL_HOST                  The host of the mysql/mariadb database (mandatory if mysql and environment is used)
79    MYSQL_PORT                  The port of the mysql/mariadb database
80    MYSQL_SOCKET                The socket of the mysql/mariadb database
81    MYSQL_USERNAME|MYSQL_USER   The username of the mysql/mariadb database login (MYSQL_USERNAME is for mysql, MYSQL_USER for mariadb)
82    MYSQL_PASSWORD              The password of the mysql/mariadb database login
83    MYSQL_DATABASE              The name of the mysql/mariadb database
84    FRIENDICA_URL               The full base URL of Friendica - f.e. 'https://friendica.local/sub'
85    FRIENDICA_PHP_PATH          The path of the PHP binary - leave empty for auto detection
86    FRIENDICA_BASE_PATH         The basepath of Friendica - leave empty for auto detection
87    FRIENDICA_ADMIN_MAIL        The admin email address of Friendica (this email will be used for admin access)
88    FRIENDICA_TZ                The timezone of Friendica
89    FRIENDICA_LANG              The langauge of Friendica
90    
91 Examples
92         bin/console autoinstall -f 'input.config.php
93                 Installs Friendica with the prepared 'input.config.php' file
94
95         bin/console autoinstall --savedb
96                 Installs Friendica with environment variables and saves them to the 'config/local.config.php' file
97
98         bin/console autoinstall -H localhost -p 3365 -u user -P passwort1234 -d friendica -U https://friendica.fqdn
99                 Installs Friendica with a local mysql database with credentials
100 HELP;
101         }
102
103         public function __construct(App\Mode $appMode, Cache $configCache, IManageConfigValues $config, Database $dba, array $argv = null)
104         {
105                 parent::__construct($argv);
106
107                 $this->appMode     = $appMode;
108                 $this->configCache = $configCache;
109                 $this->config      = $config;
110                 $this->dba         = $dba;
111         }
112
113         protected function doExecute()
114         {
115                 // Initialise the app
116                 $this->out("Initializing setup...");
117
118                 $installer = new Installer();
119
120                 $configCache  = $this->configCache;
121                 $basePathConf = $configCache->get('system', 'basepath');
122                 $basepath     = new BasePath($basePathConf);
123                 $installer->setUpCache($configCache, $basepath->getPath());
124
125                 $this->out(" Complete!\n");
126
127                 // Check Environment
128                 $this->out("Checking environment...");
129
130                 $installer->resetChecks();
131
132                 if (!$this->runBasicChecks($installer, $configCache)) {
133                         $errorMessage = $this->extractErrors($installer->getChecks());
134                         throw new RuntimeException($errorMessage);
135                 }
136
137                 $this->out(" Complete!\n");
138
139                 // if a config file is set,
140                 $config_file = $this->getOption(['f', 'file']);
141
142                 if (!empty($config_file)) {
143                         $this->out("Loading config file '$config_file'...");
144                         if (!file_exists($config_file)) {
145                                 throw new RuntimeException("ERROR: Config file does not exist.");
146                         }
147
148                         //append config file to the config cache
149                         $config = include($config_file);
150                         if (!is_array($config)) {
151                                 throw new Exception('Error loading config file ' . $config_file);
152                         }
153                         $configCache->load($config, Cache::SOURCE_FILE);
154                 } else {
155                         // Creating config file
156                         $this->out("Creating config file...");
157
158                         $save_db = $this->getOption(['s', 'savedb'], false);
159
160                         $db_host = $this->getOption(['H', 'dbhost'], ($save_db) ? (getenv('MYSQL_HOST')) : Installer::DEFAULT_HOST);
161                         $db_port = $this->getOption(['p', 'dbport'], ($save_db) ? getenv('MYSQL_PORT') : null);
162                         $db_socket = $this->getOption(['s', 'dbsocket'], ($save_db) ? getenv('MYSQL_SOCKET') : null);
163                         $configCache->set('database', 'hostname', $db_host . (!empty($db_port) ? ':' . $db_port : ''));
164                         $configCache->set('database', 'database',
165                                 $this->getOption(['d', 'dbdata'],
166                                         ($save_db) ? getenv('MYSQL_DATABASE') : ''));
167                         $configCache->set('database', 'username',
168                                 $this->getOption(['u', 'dbuser'],
169                                         ($save_db) ? getenv('MYSQL_USER') . getenv('MYSQL_USERNAME') : ''));
170                         $configCache->set('database', 'password',
171                                 $this->getOption(['P', 'dbpass'],
172                                         ($save_db) ? getenv('MYSQL_PASSWORD') : ''));
173
174                         $php_path = $this->getOption(['b', 'phppath'], !empty('FRIENDICA_PHP_PATH') ? getenv('FRIENDICA_PHP_PATH') : null);
175                         if (!empty($php_path)) {
176                                 $configCache->set('config', 'php_path', $php_path);
177                         } else {
178                                 $configCache->set('config', 'php_path', $installer->getPHPPath());
179                         }
180
181                         $configCache->set('config', 'admin_email',
182                                 $this->getOption(['A', 'admin'],
183                                         !empty(getenv('FRIENDICA_ADMIN_MAIL')) ? getenv('FRIENDICA_ADMIN_MAIL') : ''));
184                         $configCache->set('system', 'default_timezone',
185                                 $this->getOption(['T', 'tz'],
186                                         !empty(getenv('FRIENDICA_TZ')) ? getenv('FRIENDICA_TZ') : Installer::DEFAULT_TZ));
187                         $configCache->set('system', 'language',
188                                 $this->getOption(['L', 'lang'],
189                                         !empty(getenv('FRIENDICA_LANG')) ? getenv('FRIENDICA_LANG') : Installer::DEFAULT_LANG));
190
191                         $basepath = $this->getOption(['b', 'basepath'], !empty(getenv('FRIENDICA_BASE_PATH')) ? getenv('FRIENDICA_BASE_PATH') : null);
192                         if (!empty($basepath)) {
193                                 $configCache->set('system', 'basepath', $basepath);
194                         }
195
196                         $url = $this->getOption(['U', 'url'], !empty(getenv('FRIENDICA_URL')) ? getenv('FRIENDICA_URL') : null);
197
198                         if (empty($url)) {
199                                 $this->out('The Friendica URL has to be set during CLI installation.');
200                                 return 1;
201                         } else {
202                                 $baseUrl = new BaseURL($this->config, []);
203                                 $baseUrl->saveByURL($url);
204                         }
205
206                         $installer->createConfig($configCache);
207                 }
208
209                 $this->out(" Complete!\n");
210
211                 // Check database connection
212                 $this->out("Checking database...");
213
214                 $installer->resetChecks();
215
216                 if (!$installer->checkDB($this->dba)) {
217                         $errorMessage = $this->extractErrors($installer->getChecks());
218                         throw new RuntimeException($errorMessage);
219                 }
220
221                 $this->out(" Complete!\n");
222
223                 // Install database
224                 $this->out("Inserting data into database...\n");
225
226                 $installer->resetChecks();
227
228                 if (!$installer->installDatabase($basePathConf)) {
229                         $errorMessage = $this->extractErrors($installer->getChecks());
230                         throw new RuntimeException($errorMessage);
231                 }
232
233                 if (!empty($config_file) && $config_file != 'config' . DIRECTORY_SEPARATOR . 'local.config.php') {
234                         // Copy config file
235                         $this->out("Copying config file...");
236                         if (!copy($config_file, $basePathConf . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.config.php')) {
237                                 throw new RuntimeException("ERROR: Saving config file failed. Please copy '$config_file' to '" . $basePathConf . "'" . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "local.config.php' manually.\n");
238                         }
239                 }
240
241                 $this->out(" Complete!\n");
242
243                 // Install theme
244                 $this->out("Installing theme");
245                 if (!empty($this->config->get('system', 'theme'))) {
246                         Theme::install($this->config->get('system', 'theme'));
247                         $this->out(" Complete\n");
248                 } else {
249                         $this->out(" Theme setting is empty. Please check the file 'config/local.config.php'\n");
250                 }
251
252                 $this->out("\nInstallation is finished");
253
254                 return 0;
255         }
256
257         /**
258          * @param Installer                                $installer   The Installer instance
259          * @param \Friendica\Core\Config\ValueObject\Cache $configCache The config cache
260          *
261          * @return bool true if checks were successfully, otherwise false
262          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
263          */
264         private function runBasicChecks(Installer $installer, Cache $configCache)
265         {
266                 $checked = true;
267
268                 $installer->resetChecks();
269                 if (!$installer->checkFunctions()) {
270                         $checked = false;
271                 }
272                 if (!$installer->checkImagick()) {
273                         $checked = false;
274                 }
275                 if (!$installer->checkLocalIni()) {
276                         $checked = false;
277                 }
278                 if (!$installer->checkSmarty3()) {
279                         $checked = false;
280                 }
281                 if (!$installer->checkKeys()) {
282                         $checked = false;
283                 }
284
285                 $php_path = $configCache->get('config', 'php_path');
286
287                 if (!$installer->checkPHP($php_path, true)) {
288                         $checked = false;
289                 }
290
291                 $this->out(" NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.\n");
292
293                 return $checked;
294         }
295
296         /**
297          * @param array $results
298          *
299          * @return string
300          */
301         private function extractErrors($results)
302         {
303                 $errorMessage      = '';
304                 $allChecksRequired = $this->getOption('a') !== null;
305
306                 foreach ($results as $result) {
307                         if (($allChecksRequired || $result['required'] === true) && $result['status'] === false) {
308                                 $errorMessage .= "--------\n";
309                                 $errorMessage .= $result['title'] . ': ' . $result['help'] . "\n";
310                         }
311                 }
312
313                 return $errorMessage;
314         }
315 }