]> git.mxchange.org Git - friendica.git/commitdiff
Refactoring Installation
authorPhilipp Holzer <admin@philipp.info>
Mon, 29 Oct 2018 17:44:39 +0000 (18:44 +0100)
committerPhilipp Holzer <admin@philipp.info>
Mon, 29 Oct 2018 17:44:39 +0000 (18:44 +0100)
- centralized installation
- renamed Core\Install to Core\Installer
- avoid using $a->data[] for states
- removed unnecessary code

src/Core/Console/AutomaticInstallation.php
src/Core/Install.php [deleted file]
src/Core/Installer.php [new file with mode: 0644]
src/Module/Install.php
tests/src/Core/InstallTest.php [deleted file]
tests/src/Core/InstallerTest.php [new file with mode: 0644]
view/templates/install.tpl [deleted file]
view/templates/install_db.tpl
view/templates/install_finished.tpl [new file with mode: 0644]
view/templates/install_settings.tpl

index c4e542e762738a674e3f3213f68d88b69c875273..491e826039bbf458d1e32ab626fc73fe644a46fc 100644 (file)
@@ -5,7 +5,7 @@ namespace Friendica\Core\Console;
 use Asika\SimpleConsole\Console;
 use Friendica\BaseObject;
 use Friendica\Core\Config;
-use Friendica\Core\Install;
+use Friendica\Core\Installer;
 use Friendica\Core\Theme;
 use Friendica\Database\DBA;
 use Friendica\Database\DBStructure;
@@ -76,7 +76,7 @@ HELP;
 
                $a = BaseObject::getApp();
 
-               $install = new Install();
+               $installer = new Installer();
 
                // if a config file is set,
                $config_file = $this->getOption(['f', 'file']);
@@ -111,7 +111,7 @@ HELP;
                        $tz = $this->getOption(['T', 'tz'], (!empty('FRIENDICA_TZ')) ? getenv('FRIENDICA_TZ') : '');
                        $lang = $this->getOption(['L', 'lang'], (!empty('FRIENDICA_LANG')) ? getenv('FRIENDICA_LANG') : '');
 
-                       $install->createConfig(
+                       $installer->createConfig(
                                $php_path,
                                $url_path,
                                ((!empty($db_port)) ? $db_host . ':' . $db_port : $db_host),
@@ -130,14 +130,10 @@ HELP;
                // Check basic setup
                $this->out("Checking basic setup...\n");
 
-               $checkResults = [];
+               $installer->resetChecks();
 
-               $this->runBasicChecks($install);
-
-               $checkResults['basic'] = $install->getChecks();
-               $errorMessage = $this->extractErrors($checkResults['basic']);
-
-               if ($errorMessage !== '') {
+               if (!$this->runBasicChecks($installer)) {
+                       $errorMessage = $this->extractErrors($installer->getChecks());
                        throw new RuntimeException($errorMessage);
                }
 
@@ -146,11 +142,10 @@ HELP;
                // Check database connection
                $this->out("Checking database...\n");
 
-               $checkResults['db'] = array();
-               $checkResults['db'][] = $this->runDatabaseCheck($db_host, $db_user, $db_pass, $db_data);
-               $errorMessage = $this->extractErrors($checkResults['db']);
+               $installer->resetChecks();
 
-               if ($errorMessage !== '') {
+               if (!$installer->checkDB($db_host, $db_user, $db_pass, $db_data)) {
+                       $errorMessage = $this->extractErrors($installer->getChecks());
                        throw new RuntimeException($errorMessage);
                }
 
@@ -159,10 +154,11 @@ HELP;
                // Install database
                $this->out("Inserting data into database...\n");
 
-               $checkResults['data'] = DBStructure::update(false, true, true);
+               $installer->resetChecks();
 
-               if ($checkResults['data'] !== '') {
-                       throw new RuntimeException("ERROR: DB Database creation error. Is the DB empty?\n");
+               if (!$installer->installDatabase()) {
+                       $errorMessage = $this->extractErrors($installer->getChecks());
+                       throw new RuntimeException($errorMessage);
                }
 
                $this->out(" Complete!\n\n");
@@ -182,16 +178,30 @@ HELP;
        }
 
        /**
-        * @param Install $install the Installer instance
+        * @param Installer $install the Installer instance
+        *
+        * @return bool true if checks were successfully, otherwise false
         */
-       private function runBasicChecks(Install $install)
+       private function runBasicChecks(Installer $install)
        {
+               $checked = true;
+
                $install->resetChecks();
-               $install->checkFunctions();
-               $install->checkImagick();
-               $install->checkLocalIni();
-               $install->checkSmarty3();
-               $install->checkKeys();
+               if (!$install->checkFunctions())                {
+                       $checked = false;
+               }
+               if (!$install->checkImagick()) {
+                       $checked = false;
+               }
+               if (!$install->checkLocalIni()) {
+                       $checked = false;
+               }
+               if (!$install->checkSmarty3()) {
+                       $checked = false;
+               }
+               if ($install->checkKeys()) {
+                       $checked = false;
+               }
 
                if (!empty(Config::get('config', 'php_path'))) {
                        if (!$install->checkPHP(Config::get('config', 'php_path'), true)) {
@@ -202,32 +212,8 @@ HELP;
                }
 
                $this->out(" NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.\n");
-       }
-
-       /**
-        * @param $db_host
-        * @param $db_user
-        * @param $db_pass
-        * @param $db_data
-        *
-        * @return array
-        */
-       private function runDatabaseCheck($db_host, $db_user, $db_pass, $db_data)
-       {
-               $result = array(
-                       'title' => 'MySQL Connection',
-                       'required' => true,
-                       'status' => true,
-                       'help' => '',
-               );
-
-
-               if (!DBA::connect($db_host, $db_user, $db_pass, $db_data)) {
-                       $result['status'] = false;
-                       $result['help'] = 'Failed, please check your MySQL settings and credentials.';
-               }
 
-               return $result;
+               return $checked;
        }
 
        /**
diff --git a/src/Core/Install.php b/src/Core/Install.php
deleted file mode 100644 (file)
index 0a97e93..0000000
+++ /dev/null
@@ -1,511 +0,0 @@
-<?php
-/**
- * @file src/Core/Install.php
- */
-namespace Friendica\Core;
-
-use DOMDocument;
-use Exception;
-use Friendica\Object\Image;
-use Friendica\Util\Network;
-
-/**
- * Contains methods for installation purpose of Friendica
- */
-class Install
-{
-       /**
-        * @var array the check outcomes
-        */
-       private $checks;
-
-       /**
-        * Returns all checks made
-        *
-        * @return array the checks
-        */
-       public function getChecks()
-       {
-               return $this->checks;
-       }
-
-       /**
-        * Resets all checks
-        */
-       public function resetChecks()
-       {
-               $this->checks = [];
-       }
-
-       /**
-        * Install constructor.
-        *
-        */
-       public function __construct()
-       {
-               $this->checks = [];
-       }
-
-       /**
-        * Checks the current installation environment. There are optional and mandatory checks.
-        *
-        * @param string $baseurl     The baseurl of Friendica
-        * @param string $phpath      Optional path to the PHP binary
-        *
-        * @return bool if the check succeed
-        */
-       public function checkAll($baseurl, $phpath = null)
-       {
-               $returnVal = true;
-
-               if (isset($phpath)) {
-                       if (!$this->checkPHP($phpath)) {
-                               $returnVal = false;
-                       }
-               }
-
-               if (!$this->checkFunctions()) {
-                       $returnVal = false;
-               }
-
-               if (!$this->checkImagick()) {
-                       $returnVal = false;
-               }
-
-               if (!$this->checkLocalIni()) {
-                       $returnVal = false;
-               }
-
-               if (!$this->checkSmarty3()) {
-                       $returnVal = false;
-               }
-
-               if (!$this->checkKeys()) {
-                       $returnVal = false;
-               }
-
-               if (!$this->checkHtAccess($baseurl)) {
-                       $returnVal = false;
-               }
-
-               return $returnVal;
-       }
-
-       /**
-        * Executes the installation of Friendica in the given environment.
-        * - Creates `config/local.ini.php`
-        * - Installs Database Structure
-        *
-        * @param string        $phppath        Path to the PHP-Binary (optional, if not set e.g. 'php' or '/usr/bin/php')
-        * @param string        $urlpath        Path based on the URL of Friendica (e.g. '/friendica')
-        * @param string        $dbhost         Hostname/IP of the Friendica Database
-        * @param string        $dbuser         Username of the Database connection credentials
-        * @param string        $dbpass         Password of the Database connection credentials
-        * @param string        $dbdata         Name of the Database
-        * @param string        $timezone       Timezone of the Friendica Installaton (e.g. 'Europe/Berlin')
-        * @param string        $language       2-letter ISO 639-1 code (eg. 'en')
-        * @param string        $adminmail      Mail-Adress of the administrator
-        * @param string        $basepath   The basepath of Friendica
-        *
-        * @return bool|string true if the config was created, the text if something went wrong
-        */
-       public function createConfig($phppath, $urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $timezone, $language, $adminmail, $basepath)
-       {
-               $tpl = get_markup_template('local.ini.tpl');
-               $txt = replace_macros($tpl,[
-                       '$phpath' => $phppath,
-                       '$dbhost' => $dbhost,
-                       '$dbuser' => $dbuser,
-                       '$dbpass' => $dbpass,
-                       '$dbdata' => $dbdata,
-                       '$timezone' => $timezone,
-                       '$language' => $language,
-                       '$urlpath' => $urlpath,
-                       '$adminmail' => $adminmail,
-               ]);
-
-               $result = file_put_contents($basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php', $txt);
-
-               if (!$result) {
-                       return $txt;
-               } else {
-                       return true;
-               }
-       }
-
-       /**
-        * Adds new checks to the array $checks
-        *
-        * @param string $title The title of the current check
-        * @param bool $status 1 = check passed, 0 = check not passed
-        * @param bool $required 1 = check is mandatory, 0 = check is optional
-        * @param string $help A help-string for the current check
-        * @param string $error_msg Optional. A error message, if the current check failed
-        */
-       private function addCheck($title, $status, $required, $help, $error_msg = "")
-       {
-               array_push($this->checks, [
-                       'title' => $title,
-                       'status' => $status,
-                       'required' => $required,
-                       'help' => $help,
-                       'error_msg' => $error_msg,
-               ]);
-       }
-
-       /**
-        * PHP Check
-        *
-        * Checks the PHP environment.
-        *
-        * - Checks if a PHP binary is available
-        * - Checks if it is the CLI version
-        * - Checks if "register_argc_argv" is enabled
-        *
-        * @param string $phppath Optional. The Path to the PHP-Binary
-        * @param bool   $required Optional. If set to true, the PHP-Binary has to exist (Default false)
-        *
-        * @return bool false if something required failed
-        */
-       public function checkPHP($phppath = null, $required = false)
-       {
-               $passed = $passed2 = $passed3 = false;
-               if (isset($phppath)) {
-                       $passed = file_exists($phppath);
-               } else {
-                       $phppath = trim(shell_exec('which php'));
-                       $passed = strlen($phppath);
-               }
-
-               $help = "";
-               if (!$passed) {
-                       $help .= L10n::t('Could not find a command line version of PHP in the web server PATH.') . EOL;
-                       $help .= L10n::t("If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-worker'>'Setup the worker'</a>") . EOL;
-                       $help .= EOL . EOL;
-                       $tpl = get_markup_template('field_input.tpl');
-                       $help .= replace_macros($tpl, [
-                               '$field' => ['phpath', L10n::t('PHP executable path'), $phppath, L10n::t('Enter full path to php executable. You can leave this blank to continue the installation.')],
-                       ]);
-                       $phppath = "";
-               }
-
-               $this->addCheck(L10n::t('Command line PHP') . ($passed ? " (<tt>$phppath</tt>)" : ""), $passed, false, $help);
-
-               if ($passed) {
-                       $cmd = "$phppath -v";
-                       $result = trim(shell_exec($cmd));
-                       $passed2 = (strpos($result, "(cli)") !== false);
-                       list($result) = explode("\n", $result);
-                       $help = "";
-                       if (!$passed2) {
-                               $help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . EOL;
-                               $help .= L10n::t('Found PHP version: ') . "<tt>$result</tt>";
-                       }
-                       $this->addCheck(L10n::t('PHP cli binary'), $passed2, true, $help);
-               } else {
-                       // return if it was required
-                       return $required;
-               }
-
-               if ($passed2) {
-                       $str = autoname(8);
-                       $cmd = "$phppath testargs.php $str";
-                       $result = trim(shell_exec($cmd));
-                       $passed3 = $result == $str;
-                       $help = "";
-                       if (!$passed3) {
-                               $help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.') . EOL;
-                               $help .= L10n::t('This is required for message delivery to work.');
-                       } else {
-                               $this->phppath = $phppath;
-                       }
-
-                       $this->addCheck(L10n::t('PHP register_argc_argv'), $passed3, true, $help);
-               }
-
-               // passed2 & passed3 are required if first check passed
-               return $passed2 && $passed3;
-       }
-
-       /**
-        * OpenSSL Check
-        *
-        * Checks the OpenSSL Environment
-        *
-        * - Checks, if the command "openssl_pkey_new" is available
-        *
-        * @return bool false if something required failed
-        */
-       public function checkKeys()
-       {
-               $help = '';
-               $res = false;
-               $status = true;
-
-               if (function_exists('openssl_pkey_new')) {
-                       $res = openssl_pkey_new([
-                               'digest_alg' => 'sha1',
-                               'private_key_bits' => 4096,
-                               'encrypt_key' => false
-                       ]);
-               }
-
-               // Get private key
-               if (!$res) {
-                       $help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys') . EOL;
-                       $help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
-                       $status = false;
-               }
-               $this->addCheck(L10n::t('Generate encryption keys'), $res, true, $help);
-
-               return $status;
-       }
-
-       /**
-        * PHP basic function check
-        *
-        * @param string $name The name of the function
-        * @param string $title The (localized) title of the function
-        * @param string $help The (localized) help of the function
-        * @param boolean $required If true, this check is required
-        *
-        * @return bool false, if the check failed
-        */
-       private function checkFunction($name, $title, $help, $required)
-       {
-               $currHelp = '';
-               $status = true;
-               if (!function_exists($name)) {
-                       $currHelp = $help;
-                       $status = false;
-               }
-               $this->addCheck($title, $status, $required, $currHelp);
-
-               return $status || (!$status && !$required);
-       }
-
-       /**
-        * PHP functions Check
-        *
-        * Checks the following PHP functions
-        * - libCurl
-        * - GD Graphics
-        * - OpenSSL
-        * - PDO or MySQLi
-        * - mb_string
-        * - XML
-        * - iconv
-        * - POSIX
-        *
-        * @return bool false if something required failed
-        */
-       public function checkFunctions()
-       {
-               $returnVal = true;
-
-               $help = '';
-               $status = true;
-               if (function_exists('apache_get_modules')) {
-                       if (!in_array('mod_rewrite', apache_get_modules())) {
-                               $help = L10n::t('Error: Apache webserver mod-rewrite module is required but not installed.');
-                               $status = false;
-                               $returnVal = false;
-                       }
-               }
-               $this->addCheck(L10n::t('Apache mod_rewrite module'), $status, true, $help);
-
-               $help = '';
-               $status = true;
-               if (!function_exists('mysqli_connect') && !class_exists('pdo')) {
-                       $status = false;
-                       $help = L10n::t('Error: PDO or MySQLi PHP module required but not installed.');
-                       $returnVal = false;
-               } else {
-                       if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', \PDO::getAvailableDrivers())) {
-                               $status = false;
-                               $help = L10n::t('Error: The MySQL driver for PDO is not installed.');
-                               $returnVal = false;
-                       }
-               }
-               $this->addCheck(L10n::t('PDO or MySQLi PHP module'), $status, true, $help);
-
-               // check for XML DOM Documents being able to be generated
-               $help = '';
-               $status = true;
-               try {
-                       $xml = new DOMDocument();
-               } catch (Exception $e) {
-                       $help = L10n::t('Error, XML PHP module required but not installed.');
-                       $status = false;
-                       $returnVal = false;
-               }
-               $this->addCheck(L10n::t('XML PHP module'), $status, true, $help);
-
-               $status = $this->checkFunction('curl_init',
-                       L10n::t('libCurl PHP module'),
-                       L10n::t('Error: libCURL PHP module required but not installed.'),
-                       true
-               );
-               $returnVal = $returnVal ? $status : false;
-
-               $status = $this->checkFunction('imagecreatefromjpeg',
-                       L10n::t('GD graphics PHP module'),
-                       L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'),
-                       true
-               );
-               $returnVal = $returnVal ? $status : false;
-
-               $status = $this->checkFunction('openssl_public_encrypt',
-                       L10n::t('OpenSSL PHP module'),
-                       L10n::t('Error: openssl PHP module required but not installed.'),
-                       true
-               );
-               $returnVal = $returnVal ? $status : false;
-
-               $status = $this->checkFunction('mb_strlen',
-                       L10n::t('mb_string PHP module'),
-                       L10n::t('Error: mb_string PHP module required but not installed.'),
-                       true
-               );
-               $returnVal = $returnVal ? $status : false;
-
-               $status = $this->checkFunction('iconv_strlen',
-                       L10n::t('iconv PHP module'),
-                       L10n::t('Error: iconv PHP module required but not installed.'),
-                       true
-               );
-               $returnVal = $returnVal ? $status : false;
-
-               $status = $this->checkFunction('posix_kill',
-                       L10n::t('POSIX PHP module'),
-                       L10n::t('Error: POSIX PHP module required but not installed.'),
-                       true
-               );
-               $returnVal = $returnVal ? $status : false;
-
-               return $returnVal;
-       }
-
-       /**
-        * "config/local.ini.php" - Check
-        *
-        * Checks if it's possible to create the "config/local.ini.php"
-        *
-        * @return bool false if something required failed
-        */
-       public function checkLocalIni()
-       {
-               $status = true;
-               $help = "";
-               if ((file_exists('config/local.ini.php') && !is_writable('config/local.ini.php')) ||
-                       (!file_exists('config/local.ini.php') && !is_writable('.'))) {
-
-                       $status = false;
-                       $help = L10n::t('The web installer needs to be able to create a file called "local.ini.php" in the "config" folder of your web server and it is unable to do so.') . EOL;
-                       $help .= L10n::t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.') . EOL;
-                       $help .= L10n::t('At the end of this procedure, we will give you a text to save in a file named local.ini.php in your Friendica "config" folder.') . EOL;
-                       $help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.') . EOL;
-               }
-
-               $this->addCheck(L10n::t('config/local.ini.php is writable'), $status, false, $help);
-
-               // Local INI File is not required
-               return true;
-       }
-
-       /**
-        * Smarty3 Template Check
-        *
-        * Checks, if the directory of Smarty3 is writable
-        *
-        * @return bool false if something required failed
-        */
-       public function checkSmarty3()
-       {
-               $status = true;
-               $help = "";
-               if (!is_writable('view/smarty3')) {
-
-                       $status = false;
-                       $help = L10n::t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') . EOL;
-                       $help .= L10n::t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.') . EOL;
-                       $help .= L10n::t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.") . EOL;
-                       $help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.") . EOL;
-               }
-
-               $this->addCheck(L10n::t('view/smarty3 is writable'), $status, true, $help);
-
-               return $status;
-       }
-
-       /**
-        * ".htaccess" - Check
-        *
-        * Checks, if "url_rewrite" is enabled in the ".htaccess" file
-        *
-        * @param string $baseurl    The baseurl of the app
-        * @return bool false if something required failed
-        */
-       public function checkHtAccess($baseurl)
-       {
-               $status = true;
-               $help = "";
-               $error_msg = "";
-               if (function_exists('curl_init')) {
-                       $fetchResult = Network::fetchUrlFull($baseurl . "/install/testrewrite");
-
-                       $url = normalise_link($baseurl . "/install/testrewrite");
-                       if ($fetchResult->getReturnCode() != 204) {
-                               $fetchResult = Network::fetchUrlFull($url);
-                       }
-
-                       if ($fetchResult->getReturnCode() != 204) {
-                               $status = false;
-                               $help = L10n::t('Url rewrite in .htaccess is not working. Make sure you copied .htaccess-dist to .htaccess.');
-                               $error_msg = [];
-                               $error_msg['head'] = L10n::t('Error message from Curl when fetching');
-                               $error_msg['url'] = $fetchResult->getRedirectUrl();
-                               $error_msg['msg'] = $fetchResult->getError();
-                       }
-
-                       $this->addCheck(L10n::t('Url rewrite is working'), $status, true, $help, $error_msg);
-               } else {
-                       // cannot check modrewrite if libcurl is not installed
-                       /// @TODO Maybe issue warning here?
-               }
-
-               return $status;
-       }
-
-       /**
-        * Imagick Check
-        *
-        * Checks, if the imagick module is available
-        *
-        * @return bool false if something required failed
-        */
-       public function checkImagick()
-       {
-               $imagick = false;
-               $gif = false;
-
-               if (class_exists('Imagick')) {
-                       $imagick = true;
-                       $supported = Image::supportedTypes();
-                       if (array_key_exists('image/gif', $supported)) {
-                               $gif = true;
-                       }
-               }
-               if (!$imagick) {
-                       $this->addCheck(L10n::t('ImageMagick PHP extension is not installed'), $imagick, false, "");
-               } else {
-                       $this->addCheck(L10n::t('ImageMagick PHP extension is installed'), $imagick, false, "");
-                       if ($imagick) {
-                               $this->addCheck(L10n::t('ImageMagick supports GIF'), $gif, false, "");
-                       }
-               }
-
-               // Imagick is not required
-               return true;
-       }
-}
diff --git a/src/Core/Installer.php b/src/Core/Installer.php
new file mode 100644 (file)
index 0000000..03d888b
--- /dev/null
@@ -0,0 +1,569 @@
+<?php
+/**
+ * @file src/Core/Install.php
+ */
+namespace Friendica\Core;
+
+use DOMDocument;
+use Exception;
+use Friendica\Database\DBA;
+use Friendica\Database\DBStructure;
+use Friendica\Object\Image;
+use Friendica\Util\Network;
+
+/**
+ * Contains methods for installation purpose of Friendica
+ */
+class Installer
+{
+       // Default values for the install page
+       const DEFAULT_LANG = 'en';
+       const DEFAULT_TZ   = 'America/Los_Angeles';
+       const DEFAULT_HOST = 'localhost';
+
+       /**
+        * @var array the check outcomes
+        */
+       private $checks;
+
+       /**
+        * Returns all checks made
+        *
+        * @return array the checks
+        */
+       public function getChecks()
+       {
+               return $this->checks;
+       }
+
+       /**
+        * Resets all checks
+        */
+       public function resetChecks()
+       {
+               $this->checks = [];
+       }
+
+       /**
+        * Install constructor.
+        *
+        */
+       public function __construct()
+       {
+               $this->checks = [];
+       }
+
+       /**
+        * Checks the current installation environment. There are optional and mandatory checks.
+        *
+        * @param string $baseurl     The baseurl of Friendica
+        * @param string $phpath      Optional path to the PHP binary
+        *
+        * @return bool if the check succeed
+        */
+       public function checkEnvironment($baseurl, $phpath = null)
+       {
+               $returnVal = true;
+
+               if (isset($phpath)) {
+                       if (!$this->checkPHP($phpath)) {
+                               $returnVal = false;
+                       }
+               }
+
+               if (!$this->checkFunctions()) {
+                       $returnVal = false;
+               }
+
+               if (!$this->checkImagick()) {
+                       $returnVal = false;
+               }
+
+               if (!$this->checkLocalIni()) {
+                       $returnVal = false;
+               }
+
+               if (!$this->checkSmarty3()) {
+                       $returnVal = false;
+               }
+
+               if (!$this->checkKeys()) {
+                       $returnVal = false;
+               }
+
+               if (!$this->checkHtAccess($baseurl)) {
+                       $returnVal = false;
+               }
+
+               return $returnVal;
+       }
+
+       /**
+        * Executes the installation of Friendica in the given environment.
+        * - Creates `config/local.ini.php`
+        * - Installs Database Structure
+        *
+        * @param string        $phppath        Path to the PHP-Binary (optional, if not set e.g. 'php' or '/usr/bin/php')
+        * @param string        $urlpath        Path based on the URL of Friendica (e.g. '/friendica')
+        * @param string        $dbhost         Hostname/IP of the Friendica Database
+        * @param string        $dbuser         Username of the Database connection credentials
+        * @param string        $dbpass         Password of the Database connection credentials
+        * @param string        $dbdata         Name of the Database
+        * @param string        $timezone       Timezone of the Friendica Installaton (e.g. 'Europe/Berlin')
+        * @param string        $language       2-letter ISO 639-1 code (eg. 'en')
+        * @param string        $adminmail      Mail-Adress of the administrator
+        * @param string        $basepath   The basepath of Friendica
+        *
+        * @return bool true if the config was created, otherwise false
+        */
+       public function createConfig($phppath, $urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $timezone, $language, $adminmail, $basepath)
+       {
+               $tpl = get_markup_template('local.ini.tpl');
+               $txt = replace_macros($tpl, [
+                       '$phpath' => $phppath,
+                       '$dbhost' => $dbhost,
+                       '$dbuser' => $dbuser,
+                       '$dbpass' => $dbpass,
+                       '$dbdata' => $dbdata,
+                       '$timezone' => $timezone,
+                       '$language' => $language,
+                       '$urlpath' => $urlpath,
+                       '$adminmail' => $adminmail,
+               ]);
+
+               $result = file_put_contents($basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php', $txt);
+
+               if (!$result) {
+                       $this->addCheck(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.'), false, false, htmlentities($txt, ENT_COMPAT, 'UTF-8'));
+               }
+
+               return $result;
+       }
+
+       /***
+        * Installs the DB-Scheme for Friendica
+        *
+        * @return bool true if the installation was successful, otherwise false
+        */
+       public function installDatabase()
+       {
+               $result = DBStructure::update(false, true, true);
+
+               if ($result) {
+                       $txt = L10n::t('You may need to import the file "database.sql" manually using phpmyadmin or mysql.') . EOL;
+                       $txt .= L10n::t('Please see the file "INSTALL.txt".');
+
+                       $this->addCheck($txt, false, true, htmlentities($result, ENT_COMPAT, 'UTF-8'));
+
+                       return false;
+               }
+
+               return true;
+       }
+
+       /**
+        * Adds new checks to the array $checks
+        *
+        * @param string $title The title of the current check
+        * @param bool $status 1 = check passed, 0 = check not passed
+        * @param bool $required 1 = check is mandatory, 0 = check is optional
+        * @param string $help A help-string for the current check
+        * @param string $error_msg Optional. A error message, if the current check failed
+        */
+       private function addCheck($title, $status, $required, $help, $error_msg = "")
+       {
+               array_push($this->checks, [
+                       'title' => $title,
+                       'status' => $status,
+                       'required' => $required,
+                       'help' => $help,
+                       'error_msg' => $error_msg,
+               ]);
+       }
+
+       /**
+        * PHP Check
+        *
+        * Checks the PHP environment.
+        *
+        * - Checks if a PHP binary is available
+        * - Checks if it is the CLI version
+        * - Checks if "register_argc_argv" is enabled
+        *
+        * @param string $phppath Optional. The Path to the PHP-Binary
+        * @param bool   $required Optional. If set to true, the PHP-Binary has to exist (Default false)
+        *
+        * @return bool false if something required failed
+        */
+       public function checkPHP($phppath = null, $required = false)
+       {
+               $passed = $passed2 = $passed3 = false;
+               if (isset($phppath)) {
+                       $passed = file_exists($phppath);
+               } else {
+                       $phppath = trim(shell_exec('which php'));
+                       $passed = strlen($phppath);
+               }
+
+               $help = "";
+               if (!$passed) {
+                       $help .= L10n::t('Could not find a command line version of PHP in the web server PATH.') . EOL;
+                       $help .= L10n::t("If you don't have a command line version of PHP installed on your server, you will not be able to run the background processing. See <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-worker'>'Setup the worker'</a>") . EOL;
+                       $help .= EOL . EOL;
+                       $tpl = get_markup_template('field_input.tpl');
+                       $help .= replace_macros($tpl, [
+                               '$field' => ['phpath', L10n::t('PHP executable path'), $phppath, L10n::t('Enter full path to php executable. You can leave this blank to continue the installation.')],
+                       ]);
+                       $phppath = "";
+               }
+
+               $this->addCheck(L10n::t('Command line PHP') . ($passed ? " (<tt>$phppath</tt>)" : ""), $passed, false, $help);
+
+               if ($passed) {
+                       $cmd = "$phppath -v";
+                       $result = trim(shell_exec($cmd));
+                       $passed2 = (strpos($result, "(cli)") !== false);
+                       list($result) = explode("\n", $result);
+                       $help = "";
+                       if (!$passed2) {
+                               $help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . EOL;
+                               $help .= L10n::t('Found PHP version: ') . "<tt>$result</tt>";
+                       }
+                       $this->addCheck(L10n::t('PHP cli binary'), $passed2, true, $help);
+               } else {
+                       // return if it was required
+                       return $required;
+               }
+
+               if ($passed2) {
+                       $str = autoname(8);
+                       $cmd = "$phppath testargs.php $str";
+                       $result = trim(shell_exec($cmd));
+                       $passed3 = $result == $str;
+                       $help = "";
+                       if (!$passed3) {
+                               $help .= L10n::t('The command line version of PHP on your system does not have "register_argc_argv" enabled.') . EOL;
+                               $help .= L10n::t('This is required for message delivery to work.');
+                       } else {
+                               $this->phppath = $phppath;
+                       }
+
+                       $this->addCheck(L10n::t('PHP register_argc_argv'), $passed3, true, $help);
+               }
+
+               // passed2 & passed3 are required if first check passed
+               return $passed2 && $passed3;
+       }
+
+       /**
+        * OpenSSL Check
+        *
+        * Checks the OpenSSL Environment
+        *
+        * - Checks, if the command "openssl_pkey_new" is available
+        *
+        * @return bool false if something required failed
+        */
+       public function checkKeys()
+       {
+               $help = '';
+               $res = false;
+               $status = true;
+
+               if (function_exists('openssl_pkey_new')) {
+                       $res = openssl_pkey_new([
+                               'digest_alg' => 'sha1',
+                               'private_key_bits' => 4096,
+                               'encrypt_key' => false
+                       ]);
+               }
+
+               // Get private key
+               if (!$res) {
+                       $help .= L10n::t('Error: the "openssl_pkey_new" function on this system is not able to generate encryption keys') . EOL;
+                       $help .= L10n::t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
+                       $status = false;
+               }
+               $this->addCheck(L10n::t('Generate encryption keys'), $res, true, $help);
+
+               return $status;
+       }
+
+       /**
+        * PHP basic function check
+        *
+        * @param string $name The name of the function
+        * @param string $title The (localized) title of the function
+        * @param string $help The (localized) help of the function
+        * @param boolean $required If true, this check is required
+        *
+        * @return bool false, if the check failed
+        */
+       private function checkFunction($name, $title, $help, $required)
+       {
+               $currHelp = '';
+               $status = true;
+               if (!function_exists($name)) {
+                       $currHelp = $help;
+                       $status = false;
+               }
+               $this->addCheck($title, $status, $required, $currHelp);
+
+               return $status || (!$status && !$required);
+       }
+
+       /**
+        * PHP functions Check
+        *
+        * Checks the following PHP functions
+        * - libCurl
+        * - GD Graphics
+        * - OpenSSL
+        * - PDO or MySQLi
+        * - mb_string
+        * - XML
+        * - iconv
+        * - POSIX
+        *
+        * @return bool false if something required failed
+        */
+       public function checkFunctions()
+       {
+               $returnVal = true;
+
+               $help = '';
+               $status = true;
+               if (function_exists('apache_get_modules')) {
+                       if (!in_array('mod_rewrite', apache_get_modules())) {
+                               $help = L10n::t('Error: Apache webserver mod-rewrite module is required but not installed.');
+                               $status = false;
+                               $returnVal = false;
+                       }
+               }
+               $this->addCheck(L10n::t('Apache mod_rewrite module'), $status, true, $help);
+
+               $help = '';
+               $status = true;
+               if (!function_exists('mysqli_connect') && !class_exists('pdo')) {
+                       $status = false;
+                       $help = L10n::t('Error: PDO or MySQLi PHP module required but not installed.');
+                       $returnVal = false;
+               } else {
+                       if (!function_exists('mysqli_connect') && class_exists('pdo') && !in_array('mysql', \PDO::getAvailableDrivers())) {
+                               $status = false;
+                               $help = L10n::t('Error: The MySQL driver for PDO is not installed.');
+                               $returnVal = false;
+                       }
+               }
+               $this->addCheck(L10n::t('PDO or MySQLi PHP module'), $status, true, $help);
+
+               // check for XML DOM Documents being able to be generated
+               $help = '';
+               $status = true;
+               try {
+                       $xml = new DOMDocument();
+               } catch (Exception $e) {
+                       $help = L10n::t('Error, XML PHP module required but not installed.');
+                       $status = false;
+                       $returnVal = false;
+               }
+               $this->addCheck(L10n::t('XML PHP module'), $status, true, $help);
+
+               $status = $this->checkFunction('curl_init',
+                       L10n::t('libCurl PHP module'),
+                       L10n::t('Error: libCURL PHP module required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               $status = $this->checkFunction('imagecreatefromjpeg',
+                       L10n::t('GD graphics PHP module'),
+                       L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               $status = $this->checkFunction('openssl_public_encrypt',
+                       L10n::t('OpenSSL PHP module'),
+                       L10n::t('Error: openssl PHP module required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               $status = $this->checkFunction('mb_strlen',
+                       L10n::t('mb_string PHP module'),
+                       L10n::t('Error: mb_string PHP module required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               $status = $this->checkFunction('iconv_strlen',
+                       L10n::t('iconv PHP module'),
+                       L10n::t('Error: iconv PHP module required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               $status = $this->checkFunction('posix_kill',
+                       L10n::t('POSIX PHP module'),
+                       L10n::t('Error: POSIX PHP module required but not installed.'),
+                       true
+               );
+               $returnVal = $returnVal ? $status : false;
+
+               return $returnVal;
+       }
+
+       /**
+        * "config/local.ini.php" - Check
+        *
+        * Checks if it's possible to create the "config/local.ini.php"
+        *
+        * @return bool false if something required failed
+        */
+       public function checkLocalIni()
+       {
+               $status = true;
+               $help = "";
+               if ((file_exists('config/local.ini.php') && !is_writable('config/local.ini.php')) ||
+                       (!file_exists('config/local.ini.php') && !is_writable('.'))) {
+
+                       $status = false;
+                       $help = L10n::t('The web installer needs to be able to create a file called "local.ini.php" in the "config" folder of your web server and it is unable to do so.') . EOL;
+                       $help .= L10n::t('This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can.') . EOL;
+                       $help .= L10n::t('At the end of this procedure, we will give you a text to save in a file named local.ini.php in your Friendica "config" folder.') . EOL;
+                       $help .= L10n::t('You can alternatively skip this procedure and perform a manual installation. Please see the file "INSTALL.txt" for instructions.') . EOL;
+               }
+
+               $this->addCheck(L10n::t('config/local.ini.php is writable'), $status, false, $help);
+
+               // Local INI File is not required
+               return true;
+       }
+
+       /**
+        * Smarty3 Template Check
+        *
+        * Checks, if the directory of Smarty3 is writable
+        *
+        * @return bool false if something required failed
+        */
+       public function checkSmarty3()
+       {
+               $status = true;
+               $help = "";
+               if (!is_writable('view/smarty3')) {
+
+                       $status = false;
+                       $help = L10n::t('Friendica uses the Smarty3 template engine to render its web views. Smarty3 compiles templates to PHP to speed up rendering.') . EOL;
+                       $help .= L10n::t('In order to store these compiled templates, the web server needs to have write access to the directory view/smarty3/ under the Friendica top level folder.') . EOL;
+                       $help .= L10n::t("Please ensure that the user that your web server runs as \x28e.g. www-data\x29 has write access to this folder.") . EOL;
+                       $help .= L10n::t("Note: as a security measure, you should give the web server write access to view/smarty3/ only--not the template files \x28.tpl\x29 that it contains.") . EOL;
+               }
+
+               $this->addCheck(L10n::t('view/smarty3 is writable'), $status, true, $help);
+
+               return $status;
+       }
+
+       /**
+        * ".htaccess" - Check
+        *
+        * Checks, if "url_rewrite" is enabled in the ".htaccess" file
+        *
+        * @param string $baseurl    The baseurl of the app
+        * @return bool false if something required failed
+        */
+       public function checkHtAccess($baseurl)
+       {
+               $status = true;
+               $help = "";
+               $error_msg = "";
+               if (function_exists('curl_init')) {
+                       $fetchResult = Network::fetchUrlFull($baseurl . "/install/testrewrite");
+
+                       $url = normalise_link($baseurl . "/install/testrewrite");
+                       if ($fetchResult->getReturnCode() != 204) {
+                               $fetchResult = Network::fetchUrlFull($url);
+                       }
+
+                       if ($fetchResult->getReturnCode() != 204) {
+                               $status = false;
+                               $help = L10n::t('Url rewrite in .htaccess is not working. Make sure you copied .htaccess-dist to .htaccess.');
+                               $error_msg = [];
+                               $error_msg['head'] = L10n::t('Error message from Curl when fetching');
+                               $error_msg['url'] = $fetchResult->getRedirectUrl();
+                               $error_msg['msg'] = $fetchResult->getError();
+                       }
+
+                       $this->addCheck(L10n::t('Url rewrite is working'), $status, true, $help, $error_msg);
+               } else {
+                       // cannot check modrewrite if libcurl is not installed
+                       /// @TODO Maybe issue warning here?
+               }
+
+               return $status;
+       }
+
+       /**
+        * Imagick Check
+        *
+        * Checks, if the imagick module is available
+        *
+        * @return bool false if something required failed
+        */
+       public function checkImagick()
+       {
+               $imagick = false;
+               $gif = false;
+
+               if (class_exists('Imagick')) {
+                       $imagick = true;
+                       $supported = Image::supportedTypes();
+                       if (array_key_exists('image/gif', $supported)) {
+                               $gif = true;
+                       }
+               }
+               if (!$imagick) {
+                       $this->addCheck(L10n::t('ImageMagick PHP extension is not installed'), $imagick, false, "");
+               } else {
+                       $this->addCheck(L10n::t('ImageMagick PHP extension is installed'), $imagick, false, "");
+                       if ($imagick) {
+                               $this->addCheck(L10n::t('ImageMagick supports GIF'), $gif, false, "");
+                       }
+               }
+
+               // Imagick is not required
+               return true;
+       }
+
+       /**
+        * Checking the Database connection and if it is available for the current installation
+        *
+        * @param string        $dbhost         Hostname/IP of the Friendica Database
+        * @param string        $dbuser         Username of the Database connection credentials
+        * @param string        $dbpass         Password of the Database connection credentials
+        * @param string        $dbdata         Name of the Database
+        *
+        * @return bool true if the check was successful, otherwise false
+        */
+       public function checkDB($dbhost, $dbuser, $dbpass, $dbdata)
+       {
+               require_once 'include/dba.php';
+               if (!DBA::connect($dbhost, $dbuser, $dbpass, $dbdata)) {
+                       $this->addCheck(L10n::t('Could not connect to database.'), false, true, '');
+
+                       return false;
+               }
+
+               if (DBA::connected()) {
+                       if (DBA::count('user') > 0) {
+                               $this->addCheck(L10n::t('Database already in use.'), false, true, '');
+
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+}
index 3622559744b9e9c4a7b8240287cd2f28fbe96d3d..e09f23a18daa6715227bac3596daedd8c6f744a2 100644 (file)
@@ -29,16 +29,16 @@ class Install extends BaseModule
         */
        const FINISHED = 4;
 
-       // Default values for the install page
-       const DEFAULT_LANG = 'en';
-       const DEFAULT_TZ   = 'America/Los_Angeles';
-       const DEFAULT_HOST = 'localhost';
-
        /**
         * @var int The current step of the wizard
         */
        private static $currentWizardStep;
 
+       /**
+        * @var Core\Installer The installer
+        */
+       private static $installer;
+
        public static function init()
        {
                $a = self::getApp();
@@ -52,9 +52,9 @@ class Install extends BaseModule
 
                // We overwrite current theme css, because during install we may not have a working mod_rewrite
                // so we may not have a css at all. Here we set a static css file for the install procedure pages
-               $a->setConfigValue('system', 'value', '../install');
                $a->theme['stylesheet'] = $a->getBaseURL() . '/view/install/style.css';
 
+               self::$installer = new Core\Installer();
                self::$currentWizardStep = defaults($_POST, 'pass', self::SYSTEM_CHECK);
        }
 
@@ -66,56 +66,44 @@ class Install extends BaseModule
                        case self::SYSTEM_CHECK:
                        case self::DATABASE_CONFIG:
                                // Nothing to do in these steps
-                               return;
+                               break;
 
                        case self::SITE_SETTINGS:
-                               $dbhost  = notags(trim(defaults($_POST, 'dbhost', self::DEFAULT_HOST)));
+                               $dbhost  = notags(trim(defaults($_POST, 'dbhost', Core\Installer::DEFAULT_HOST)));
                                $dbuser  = notags(trim(defaults($_POST, 'dbuser', '')));
                                $dbpass  = notags(trim(defaults($_POST, 'dbpass', '')));
                                $dbdata  = notags(trim(defaults($_POST, 'dbdata', '')));
 
-                               require_once 'include/dba.php';
-                               if (!DBA::connect($dbhost, $dbuser, $dbpass, $dbdata)) {
-                                       $a->data['db_conn_failed'] = true;
+                               // If we cannot connect to the database, return to the previous step
+                               if (!self::$installer->checkDB($dbhost, $dbuser, $dbpass, $dbdata)) {
+                                       self::$currentWizardStep = self::DATABASE_CONFIG;
                                }
 
-                               return;
+                               break;
 
                        case self::FINISHED:
                                $urlpath   = $a->getURLPath();
-                               $dbhost    = notags(trim(defaults($_POST, 'dbhost', self::DEFAULT_HOST)));
+                               $dbhost    = notags(trim(defaults($_POST, 'dbhost', Core\Installer::DEFAULT_HOST)));
                                $dbuser    = notags(trim(defaults($_POST, 'dbuser', '')));
                                $dbpass    = notags(trim(defaults($_POST, 'dbpass', '')));
                                $dbdata    = notags(trim(defaults($_POST, 'dbdata', '')));
                                $phpath    = notags(trim(defaults($_POST, 'phpath', '')));
-                               $timezone  = notags(trim(defaults($_POST, 'timezone', self::DEFAULT_TZ)));
-                               $language  = notags(trim(defaults($_POST, 'language', self::DEFAULT_LANG)));
+                               $timezone  = notags(trim(defaults($_POST, 'timezone', Core\Installer::DEFAULT_TZ)));
+                               $language  = notags(trim(defaults($_POST, 'language', Core\Installer::DEFAULT_LANG)));
                                $adminmail = notags(trim(defaults($_POST, 'adminmail', '')));
 
-                               // connect to db
-                               DBA::connect($dbhost, $dbuser, $dbpass, $dbdata);
-
-                               $install = new Core\Install();
-
-                               $errors = $install->createConfig($phpath, $urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $timezone, $language, $adminmail, $a->getBasePath());
-
-                               if ($errors !== true) {
-                                       $a->data['txt'] = $errors;
-                                       return;
+                               // If we cannot connect to the database, return to the Database config wizard
+                               if (!self::$installer->checkDB($dbhost, $dbuser, $dbpass, $dbdata)) {
+                                       self::$currentWizardStep = self::DATABASE_CONFIG;
                                }
 
-                               $errors = DBStructure::update(false, true, true);
-
-                               if ($errors) {
-                                       $a->data['db_failed'] = $errors;
-                               } else {
-                                       $a->data['db_installed'] = true;
+                               if (!self::$installer->createConfig($phpath, $urlpath, $dbhost, $dbuser, $dbpass, $dbdata, $timezone, $language, $adminmail, $a->getBasePath())) {
+                                       return;
                                }
 
-                               return;
+                               self::$installer->installDatabase();
 
-                       default:
-                               return;
+                               break;
                }
        }
 
@@ -126,20 +114,18 @@ class Install extends BaseModule
                $output = '';
 
                $install_title = L10n::t('Friendica Communctions Server - Setup');
-               $wizard_status = self::checkWizardStatus($a);
 
                switch (self::$currentWizardStep) {
                        case self::SYSTEM_CHECK:
                                $phppath = defaults($_POST, 'phpath', null);
 
-                               $install = new Core\Install();
-                               $status = $install->checkAll($a->getBaseURL(), $phppath);
+                               $status = self::$installer->checkEnvironment($a->getBaseURL(), $phppath);
 
                                $tpl = get_markup_template('install_checks.tpl');
                                $output .= replace_macros($tpl, [
                                        '$title'                => $install_title,
                                        '$pass'                 => L10n::t('System check'),
-                                       '$checks'               => $install->getChecks(),
+                                       '$checks'               => self::$installer->getChecks(),
                                        '$passed'               => $status,
                                        '$see_install'  => L10n::t('Please see the file "Install.txt".'),
                                        '$next'                 => L10n::t('Next'),
@@ -150,12 +136,12 @@ class Install extends BaseModule
                                break;
 
                        case self::DATABASE_CONFIG:
-                               $dbhost    = notags(trim(defaults($_POST, 'dbhost'   , self::DEFAULT_HOST)));
-                               $dbuser    = notags(trim(defaults($_POST, 'dbuser'   , '')));
-                               $dbpass    = notags(trim(defaults($_POST, 'dbpass'   , '')));
-                               $dbdata    = notags(trim(defaults($_POST, 'dbdata'   , '')));
-                               $phpath    = notags(trim(defaults($_POST, 'phpath'   , '')));
-                               $adminmail = notags(trim(defaults($_POST, 'adminmail', '')));
+                               $dbhost    = notags(trim(defaults($_POST, 'dbhost'   , Core\Installer::DEFAULT_HOST)));
+                               $dbuser    = notags(trim(defaults($_POST, 'dbuser'   , ''                          )));
+                               $dbpass    = notags(trim(defaults($_POST, 'dbpass'   , ''                          )));
+                               $dbdata    = notags(trim(defaults($_POST, 'dbdata'   , ''                          )));
+                               $phpath    = notags(trim(defaults($_POST, 'phpath'   , ''                          )));
+                               $adminmail = notags(trim(defaults($_POST, 'adminmail', ''                          )));
 
                                $tpl = get_markup_template('install_db.tpl');
                                $output .= replace_macros($tpl, [
@@ -164,7 +150,7 @@ class Install extends BaseModule
                                        '$info_01'      => L10n::t('In order to install Friendica we need to know how to connect to your database.'),
                                        '$info_02'      => L10n::t('Please contact your hosting provider or site administrator if you have questions about these settings.'),
                                        '$info_03'      => L10n::t('The database you specify below should already exist. If it does not, please create it before continuing.'),
-                                       '$status'       => $wizard_status,
+                                       'checks'        => self::$installer->getChecks(),
                                        '$dbhost'       => ['dbhost',
                                                                        L10n::t('Database Server Name'),
                                                                        $dbhost,
@@ -199,24 +185,25 @@ class Install extends BaseModule
                                        '$submit'       => L10n::t('Submit')
                                ]);
                                break;
+
                        case self::SITE_SETTINGS:
-                               $dbhost = notags(trim(defaults($_POST, 'dbhost', self::DEFAULT_HOST)));
-                               $dbuser = notags(trim(defaults($_POST, 'dbuser', ''                )));
-                               $dbpass = notags(trim(defaults($_POST, 'dbpass', ''                )));
-                               $dbdata = notags(trim(defaults($_POST, 'dbdata', ''                )));
-                               $phpath = notags(trim(defaults($_POST, 'phpath', ''                )));
+                               $dbhost = notags(trim(defaults($_POST, 'dbhost', Core\Installer::DEFAULT_HOST)));
+                               $dbuser = notags(trim(defaults($_POST, 'dbuser', ''                          )));
+                               $dbpass = notags(trim(defaults($_POST, 'dbpass', ''                          )));
+                               $dbdata = notags(trim(defaults($_POST, 'dbdata', ''                          )));
+                               $phpath = notags(trim(defaults($_POST, 'phpath', ''                          )));
 
                                $adminmail = notags(trim(defaults($_POST, 'adminmail', '')));
 
-                               $timezone = defaults($_POST, 'timezone', self::DEFAULT_TZ);
+                               $timezone = defaults($_POST, 'timezone', Core\Installer::DEFAULT_TZ);
                                /* Installed langs */
                                $lang_choices = L10n::getAvailableLanguages();
 
                                $tpl = get_markup_template('install_settings.tpl');
                                $output .= replace_macros($tpl, [
                                        '$title'                => $install_title,
+                                       '$checks'               => self::$installer->getChecks(),
                                        '$pass'                 => L10n::t('Site settings'),
-                                       '$status'               => $wizard_status,
                                        '$dbhost'               => $dbhost,
                                        '$dbuser'               => $dbuser,
                                        '$dbpass'               => $dbpass,
@@ -225,8 +212,8 @@ class Install extends BaseModule
                                        '$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'],
                                        '$timezone'     => Temporal::getTimezoneField('timezone', L10n::t('Please select a default timezone for your website'), $timezone, ''),
                                        '$language'     => ['language',
-                                                                               L10n::t('System Language:'), #
-                                                                               self::DEFAULT_LANG,
+                                                                               L10n::t('System Language:'),
+                                                                               Core\Installer::DEFAULT_LANG,
                                                                                L10n::t('Set the default language for your Friendica installation interface and to send emails.'),
                                                                                $lang_choices],
                                        '$baseurl'              => $a->getBaseURL(),
@@ -237,28 +224,18 @@ class Install extends BaseModule
                        case self::FINISHED:
                                $db_return_text = "";
 
-                               if (defaults($a->data, 'db_installed', false)) {
+                               if (count(self::$installer->getChecks()) == 0) {
                                        $txt = '<p style="font-size: 130%;">';
                                        $txt .= L10n::t('Your Friendica site database has been installed.') . EOL;
                                        $db_return_text .= $txt;
                                }
 
-                               if (defaults($a->data, 'db_failed', false)) {
-                                       $txt = L10n::t('You may need to import the file "database.sql" manually using phpmyadmin or mysql.') . EOL;
-                                       $txt .= L10n::t('Please see the file "INSTALL.txt".') . EOL ."<hr>";
-                                       $txt .= "<pre>".$a->data['db_failed'] . "</pre>". EOL;
-                                       $db_return_text .= $txt;
-                               }
-
-                               if (isset($a->data['txt']) && strlen($a->data['txt'])) {
-                                       $db_return_text .= self::manualConfig($a);
-                               }
-
-                               $tpl = get_markup_template('install.tpl');
+                               $tpl = get_markup_template('install_finished.tpl');
                                $output .= replace_macros($tpl, [
-                                       '$title' => $install_title,
-                                       '$pass' => "",
-                                       '$text' => $db_return_text . self::whatNext($a),
+                                       '$title'  => $install_title,
+                                       '$checks' => self::$installer->getChecks(),
+                                       '$pass'   => L10n::t('Installation finished'),
+                                       '$text'   => $db_return_text . self::whatNext($a),
                                ]);
 
                                break;
@@ -267,50 +244,6 @@ class Install extends BaseModule
                return $output;
        }
 
-       /**
-        * @param App $a The global Friendica App
-        *
-        * @return string The status of Wizard steps
-        */
-       private static function checkWizardStatus($a)
-       {
-               $wizardStatus = "";
-
-               if (defaults($a->data, 'db_conn_failed', false)) {
-                       self::$currentWizardStep = 2;
-                       $wizardStatus = L10n::t('Could not connect to database.');
-               }
-
-               if (defaults($a->data, 'db_create_failed', false)) {
-                       self::$currentWizardStep = 2;
-                       $wizardStatus = L10n::t('Could not create table.');
-               }
-
-               if (DBA::connected()) {
-                       if (DBA::count('user')) {
-                               self::$currentWizardStep = 2;
-                               $wizardStatus = L10n::t('Database already in use.');
-                       }
-               }
-
-               return $wizardStatus;
-       }
-
-       /**
-        * Creates the text for manual config
-        *
-        * @param App $a The global App
-        *
-        * @return string The manual config text
-        */
-       private static function manualConfig($a)
-       {
-               $data = htmlentities($a->data['txt'], ENT_COMPAT,  'UTF-8');
-               $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.');
-               $output .= "<textarea rows=\"24\" cols=\"80\" >$data</textarea>";
-               return $output;
-       }
-
        /**
         * Creates the text for the next steps
         *
diff --git a/tests/src/Core/InstallTest.php b/tests/src/Core/InstallTest.php
deleted file mode 100644 (file)
index b44104d..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-<?php
-
-// this is in the same namespace as Install for mocking 'function_exists'
-namespace Friendica\Core;
-
-use Friendica\Test\Util\VFSTrait;
-use PHPUnit\Framework\TestCase;
-
-/**
- * @runTestsInSeparateProcesses
- * @preserveGlobalState disabled
- */
-class InstallTest extends TestCase
-{
-       use VFSTrait;
-
-       public function setUp()
-       {
-               parent::setUp(); // TODO: Change the autogenerated stub
-
-               $this->setUpVfsDir();
-       }
-
-       private function assertCheckExist($position, $title, $help, $status, $required, $assertionArray)
-       {
-               $this->assertArraySubset([$position => [
-                       'title' => $title,
-                       'status' => $status,
-                       'required' => $required,
-                       'error_msg' => null,
-                       'help' => $help]
-               ], $assertionArray);
-       }
-
-       /**
-        * Replaces function_exists results with given mocks
-        *
-        * @param array $functions a list from function names and their result
-        */
-       private function setFunctions($functions)
-       {
-               global $phpMock;
-               $phpMock['function_exists'] = function($function) use ($functions) {
-                       foreach ($functions as $name => $value) {
-                               if ($function == $name) {
-                                       return $value;
-                               }
-                       }
-                       return '__phpunit_continue__';
-               };
-       }
-
-       /**
-        * Replaces class_exist results with given mocks
-        *
-        * @param array $classes a list from class names and their results
-        */
-       private function setClasses($classes)
-       {
-               global $phpMock;
-               $phpMock['class_exists'] = function($class) use ($classes) {
-                       foreach ($classes as $name => $value) {
-                               if ($class == $name) {
-                                       return $value;
-                               }
-                       }
-                       return '__phpunit_continue__';
-               };
-       }
-
-       /**
-        * @small
-        */
-       public function testCheckKeys()
-       {
-               $this->setFunctions(['openssl_pkey_new' => false]);
-               $install = new Install();
-               $this->assertFalse($install->checkKeys());
-
-               $this->setFunctions(['openssl_pkey_new' => true]);
-               $install = new Install();
-               $this->assertTrue($install->checkKeys());
-       }
-
-       /**
-        * @small
-        */
-       public function testCheckFunctions()
-       {
-               $this->setFunctions(['curl_init' => false]);
-               $install = new Install();
-               $this->assertFalse($install->checkFunctions());
-               $this->assertCheckExist(3,
-                       L10n::t('libCurl PHP module'),
-                       L10n::t('Error: libCURL PHP module required but not installed.'),
-                       false,
-                       true,
-                       $install->getChecks());
-
-               $this->setFunctions(['imagecreatefromjpeg' => false]);
-               $install = new Install();
-               $this->assertFalse($install->checkFunctions());
-               $this->assertCheckExist(4,
-                       L10n::t('GD graphics PHP module'),
-                       L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'),
-                       false,
-                       true,
-                       $install->getChecks());
-
-               $this->setFunctions(['openssl_public_encrypt' => false]);
-               $install = new Install();
-               $this->assertFalse($install->checkFunctions());
-               $this->assertCheckExist(5,
-                       L10n::t('OpenSSL PHP module'),
-                       L10n::t('Error: openssl PHP module required but not installed.'),
-                       false,
-                       true,
-                       $install->getChecks());
-
-               $this->setFunctions(['mb_strlen' => false]);
-               $install = new Install();
-               $this->assertFalse($install->checkFunctions());
-               $this->assertCheckExist(6,
-                       L10n::t('mb_string PHP module'),
-                       L10n::t('Error: mb_string PHP module required but not installed.'),
-                       false,
-                       true,
-                       $install->getChecks());
-
-               $this->setFunctions(['iconv_strlen' => false]);
-               $install = new Install();
-               $this->assertFalse($install->checkFunctions());
-               $this->assertCheckExist(7,
-                       L10n::t('iconv PHP module'),
-                       L10n::t('Error: iconv PHP module required but not installed.'),
-                       false,
-                       true,
-                       $install->getChecks());
-
-               $this->setFunctions(['posix_kill' => false]);
-               $install = new Install();
-               $this->assertFalse($install->checkFunctions());
-               $this->assertCheckExist(8,
-                       L10n::t('POSIX PHP module'),
-                       L10n::t('Error: POSIX PHP module required but not installed.'),
-                       false,
-                       true,
-                       $install->getChecks());
-
-               $this->setFunctions([
-                       'curl_init' => true,
-                       'imagecreatefromjpeg' => true,
-                       'openssl_public_encrypt' => true,
-                       'mb_strlen' => true,
-                       'iconv_strlen' => true,
-                       'posix_kill' => true
-               ]);
-               $install = new Install();
-               $this->assertTrue($install->checkFunctions());
-       }
-
-       /**
-        * @small
-        */
-       public function testCheckLocalIni()
-       {
-               $this->assertTrue($this->root->hasChild('config/local.ini.php'));
-
-               $install = new Install();
-               $this->assertTrue($install->checkLocalIni());
-
-               $this->delConfigFile('local.ini.php');
-
-               $this->assertFalse($this->root->hasChild('config/local.ini.php'));
-
-               $install = new Install();
-               $this->assertTrue($install->checkLocalIni());
-       }
-
-       /**
-        * @small
-        */
-       public function testCheckHtAccessFail()
-       {
-               // Mocking the CURL Response
-               $curlResult = \Mockery::mock('Friendica\Network\CurlResult');
-               $curlResult
-                       ->shouldReceive('getReturnCode')
-                       ->andReturn('404');
-               $curlResult
-                       ->shouldReceive('getRedirectUrl')
-                       ->andReturn('');
-               $curlResult
-                       ->shouldReceive('getError')
-                       ->andReturn('test Error');
-
-               // Mocking the CURL Request
-               $networkMock = \Mockery::mock('alias:Friendica\Util\Network');
-               $networkMock
-                       ->shouldReceive('fetchUrlFull')
-                       ->with('https://test/install/testrewrite')
-                       ->andReturn($curlResult);
-               $networkMock
-                       ->shouldReceive('fetchUrlFull')
-                       ->with('http://test/install/testrewrite')
-                       ->andReturn($curlResult);
-
-               // Mocking that we can use CURL
-               $this->setFunctions(['curl_init' => true]);
-
-               // needed because of "normalise_link"
-               require_once __DIR__ . '/../../../include/text.php';
-
-               $install = new Install();
-
-               $this->assertFalse($install->checkHtAccess('https://test'));
-               $this->assertSame('test Error', $install->getChecks()[0]['error_msg']['msg']);
-       }
-
-       /**
-        * @small
-        */
-       public function testCheckHtAccessWork()
-       {
-               // Mocking the failed CURL Response
-               $curlResultF = \Mockery::mock('Friendica\Network\CurlResult');
-               $curlResultF
-                       ->shouldReceive('getReturnCode')
-                       ->andReturn('404');
-
-               // Mocking the working CURL Response
-               $curlResultW = \Mockery::mock('Friendica\Network\CurlResult');
-               $curlResultW
-                       ->shouldReceive('getReturnCode')
-                       ->andReturn('204');
-
-               // Mocking the CURL Request
-               $networkMock = \Mockery::mock('alias:Friendica\Util\Network');
-               $networkMock
-                       ->shouldReceive('fetchUrlFull')
-                       ->with('https://test/install/testrewrite')
-                       ->andReturn($curlResultF);
-               $networkMock
-                       ->shouldReceive('fetchUrlFull')
-                       ->with('http://test/install/testrewrite')
-                       ->andReturn($curlResultW);
-
-               // Mocking that we can use CURL
-               $this->setFunctions(['curl_init' => true]);
-
-               // needed because of "normalise_link"
-               require_once __DIR__ . '/../../../include/text.php';
-
-               $install = new Install();
-
-               $this->assertTrue($install->checkHtAccess('https://test'));
-       }
-
-       /**
-        * @small
-        */
-       public function testImagick()
-       {
-               $imageMock = \Mockery::mock('alias:Friendica\Object\Image');
-               $imageMock
-                       ->shouldReceive('supportedTypes')
-                       ->andReturn(['image/gif' => 'gif']);
-
-               $this->setClasses(['Imagick' => true]);
-
-               $install = new Install();
-
-               // even there is no supported type, Imagick should return true (because it is not required)
-               $this->assertTrue($install->checkImagick());
-
-               $this->assertCheckExist(1,
-                       L10n::t('ImageMagick supports GIF'),
-                       '',
-                       true,
-                       false,
-                       $install->getChecks());
-       }
-
-       /**
-        * @small
-        */
-       public function testImagickNotFound()
-       {
-               $imageMock = \Mockery::mock('alias:Friendica\Object\Image');
-               $imageMock
-                       ->shouldReceive('supportedTypes')
-                       ->andReturn([]);
-
-               $this->setClasses(['Imagick' => true]);
-
-               $install = new Install();
-
-               // even there is no supported type, Imagick should return true (because it is not required)
-               $this->assertTrue($install->checkImagick());
-               $this->assertCheckExist(1,
-                       L10n::t('ImageMagick supports GIF'),
-                       '',
-                       false,
-                       false,
-                       $install->getChecks());
-       }
-
-       public function testImagickNotInstalled()
-       {
-               $this->setClasses(['Imagick' => false]);
-
-               $install = new Install();
-
-               // even there is no supported type, Imagick should return true (because it is not required)
-               $this->assertTrue($install->checkImagick());
-               $this->assertCheckExist(0,
-                       L10n::t('ImageMagick PHP extension is not installed'),
-                       '',
-                       false,
-                       false,
-                       $install->getChecks());
-       }
-}
-
-/**
- * A workaround to replace the PHP native function_exists with a mocked function
- *
- * @param string $function_name the Name of the function
- *
- * @return bool true or false
- */
-function function_exists($function_name)
-{
-       global $phpMock;
-       if (isset($phpMock['function_exists'])) {
-               $result = call_user_func_array($phpMock['function_exists'], func_get_args());
-               if ($result !== '__phpunit_continue__') {
-                       return $result;
-               }
-       }
-       return call_user_func_array('\function_exists', func_get_args());
-}
-
-function class_exists($class_name)
-{
-       global $phpMock;
-       if (isset($phpMock['class_exists'])) {
-               $result = call_user_func_array($phpMock['class_exists'], func_get_args());
-               if ($result !== '__phpunit_continue__') {
-                       return $result;
-               }
-       }
-       return call_user_func_array('\class_exists', func_get_args());
-}
diff --git a/tests/src/Core/InstallerTest.php b/tests/src/Core/InstallerTest.php
new file mode 100644 (file)
index 0000000..a4ee20b
--- /dev/null
@@ -0,0 +1,354 @@
+<?php
+
+// this is in the same namespace as Install for mocking 'function_exists'
+namespace Friendica\Core;
+
+use Friendica\Test\Util\VFSTrait;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @runTestsInSeparateProcesses
+ * @preserveGlobalState disabled
+ */
+class InstallerTest extends TestCase
+{
+       use VFSTrait;
+
+       public function setUp()
+       {
+               parent::setUp(); // TODO: Change the autogenerated stub
+
+               $this->setUpVfsDir();
+       }
+
+       private function assertCheckExist($position, $title, $help, $status, $required, $assertionArray)
+       {
+               $this->assertArraySubset([$position => [
+                       'title' => $title,
+                       'status' => $status,
+                       'required' => $required,
+                       'error_msg' => null,
+                       'help' => $help]
+               ], $assertionArray);
+       }
+
+       /**
+        * Replaces function_exists results with given mocks
+        *
+        * @param array $functions a list from function names and their result
+        */
+       private function setFunctions($functions)
+       {
+               global $phpMock;
+               $phpMock['function_exists'] = function($function) use ($functions) {
+                       foreach ($functions as $name => $value) {
+                               if ($function == $name) {
+                                       return $value;
+                               }
+                       }
+                       return '__phpunit_continue__';
+               };
+       }
+
+       /**
+        * Replaces class_exist results with given mocks
+        *
+        * @param array $classes a list from class names and their results
+        */
+       private function setClasses($classes)
+       {
+               global $phpMock;
+               $phpMock['class_exists'] = function($class) use ($classes) {
+                       foreach ($classes as $name => $value) {
+                               if ($class == $name) {
+                                       return $value;
+                               }
+                       }
+                       return '__phpunit_continue__';
+               };
+       }
+
+       /**
+        * @small
+        */
+       public function testCheckKeys()
+       {
+               $this->setFunctions(['openssl_pkey_new' => false]);
+               $install = new Installer();
+               $this->assertFalse($install->checkKeys());
+
+               $this->setFunctions(['openssl_pkey_new' => true]);
+               $install = new Installer();
+               $this->assertTrue($install->checkKeys());
+       }
+
+       /**
+        * @small
+        */
+       public function testCheckFunctions()
+       {
+               $this->setFunctions(['curl_init' => false]);
+               $install = new Installer();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(3,
+                       L10n::t('libCurl PHP module'),
+                       L10n::t('Error: libCURL PHP module required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions(['imagecreatefromjpeg' => false]);
+               $install = new Installer();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(4,
+                       L10n::t('GD graphics PHP module'),
+                       L10n::t('Error: GD graphics PHP module with JPEG support required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions(['openssl_public_encrypt' => false]);
+               $install = new Installer();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(5,
+                       L10n::t('OpenSSL PHP module'),
+                       L10n::t('Error: openssl PHP module required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions(['mb_strlen' => false]);
+               $install = new Installer();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(6,
+                       L10n::t('mb_string PHP module'),
+                       L10n::t('Error: mb_string PHP module required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions(['iconv_strlen' => false]);
+               $install = new Installer();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(7,
+                       L10n::t('iconv PHP module'),
+                       L10n::t('Error: iconv PHP module required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions(['posix_kill' => false]);
+               $install = new Installer();
+               $this->assertFalse($install->checkFunctions());
+               $this->assertCheckExist(8,
+                       L10n::t('POSIX PHP module'),
+                       L10n::t('Error: POSIX PHP module required but not installed.'),
+                       false,
+                       true,
+                       $install->getChecks());
+
+               $this->setFunctions([
+                       'curl_init' => true,
+                       'imagecreatefromjpeg' => true,
+                       'openssl_public_encrypt' => true,
+                       'mb_strlen' => true,
+                       'iconv_strlen' => true,
+                       'posix_kill' => true
+               ]);
+               $install = new Installer();
+               $this->assertTrue($install->checkFunctions());
+       }
+
+       /**
+        * @small
+        */
+       public function testCheckLocalIni()
+       {
+               $this->assertTrue($this->root->hasChild('config/local.ini.php'));
+
+               $install = new Installer();
+               $this->assertTrue($install->checkLocalIni());
+
+               $this->delConfigFile('local.ini.php');
+
+               $this->assertFalse($this->root->hasChild('config/local.ini.php'));
+
+               $install = new Installer();
+               $this->assertTrue($install->checkLocalIni());
+       }
+
+       /**
+        * @small
+        */
+       public function testCheckHtAccessFail()
+       {
+               // Mocking the CURL Response
+               $curlResult = \Mockery::mock('Friendica\Network\CurlResult');
+               $curlResult
+                       ->shouldReceive('getReturnCode')
+                       ->andReturn('404');
+               $curlResult
+                       ->shouldReceive('getRedirectUrl')
+                       ->andReturn('');
+               $curlResult
+                       ->shouldReceive('getError')
+                       ->andReturn('test Error');
+
+               // Mocking the CURL Request
+               $networkMock = \Mockery::mock('alias:Friendica\Util\Network');
+               $networkMock
+                       ->shouldReceive('fetchUrlFull')
+                       ->with('https://test/install/testrewrite')
+                       ->andReturn($curlResult);
+               $networkMock
+                       ->shouldReceive('fetchUrlFull')
+                       ->with('http://test/install/testrewrite')
+                       ->andReturn($curlResult);
+
+               // Mocking that we can use CURL
+               $this->setFunctions(['curl_init' => true]);
+
+               // needed because of "normalise_link"
+               require_once __DIR__ . '/../../../include/text.php';
+
+               $install = new Installer();
+
+               $this->assertFalse($install->checkHtAccess('https://test'));
+               $this->assertSame('test Error', $install->getChecks()[0]['error_msg']['msg']);
+       }
+
+       /**
+        * @small
+        */
+       public function testCheckHtAccessWork()
+       {
+               // Mocking the failed CURL Response
+               $curlResultF = \Mockery::mock('Friendica\Network\CurlResult');
+               $curlResultF
+                       ->shouldReceive('getReturnCode')
+                       ->andReturn('404');
+
+               // Mocking the working CURL Response
+               $curlResultW = \Mockery::mock('Friendica\Network\CurlResult');
+               $curlResultW
+                       ->shouldReceive('getReturnCode')
+                       ->andReturn('204');
+
+               // Mocking the CURL Request
+               $networkMock = \Mockery::mock('alias:Friendica\Util\Network');
+               $networkMock
+                       ->shouldReceive('fetchUrlFull')
+                       ->with('https://test/install/testrewrite')
+                       ->andReturn($curlResultF);
+               $networkMock
+                       ->shouldReceive('fetchUrlFull')
+                       ->with('http://test/install/testrewrite')
+                       ->andReturn($curlResultW);
+
+               // Mocking that we can use CURL
+               $this->setFunctions(['curl_init' => true]);
+
+               // needed because of "normalise_link"
+               require_once __DIR__ . '/../../../include/text.php';
+
+               $install = new Installer();
+
+               $this->assertTrue($install->checkHtAccess('https://test'));
+       }
+
+       /**
+        * @small
+        */
+       public function testImagick()
+       {
+               $imageMock = \Mockery::mock('alias:Friendica\Object\Image');
+               $imageMock
+                       ->shouldReceive('supportedTypes')
+                       ->andReturn(['image/gif' => 'gif']);
+
+               $this->setClasses(['Imagick' => true]);
+
+               $install = new Installer();
+
+               // even there is no supported type, Imagick should return true (because it is not required)
+               $this->assertTrue($install->checkImagick());
+
+               $this->assertCheckExist(1,
+                       L10n::t('ImageMagick supports GIF'),
+                       '',
+                       true,
+                       false,
+                       $install->getChecks());
+       }
+
+       /**
+        * @small
+        */
+       public function testImagickNotFound()
+       {
+               $imageMock = \Mockery::mock('alias:Friendica\Object\Image');
+               $imageMock
+                       ->shouldReceive('supportedTypes')
+                       ->andReturn([]);
+
+               $this->setClasses(['Imagick' => true]);
+
+               $install = new Installer();
+
+               // even there is no supported type, Imagick should return true (because it is not required)
+               $this->assertTrue($install->checkImagick());
+               $this->assertCheckExist(1,
+                       L10n::t('ImageMagick supports GIF'),
+                       '',
+                       false,
+                       false,
+                       $install->getChecks());
+       }
+
+       public function testImagickNotInstalled()
+       {
+               $this->setClasses(['Imagick' => false]);
+
+               $install = new Installer();
+
+               // even there is no supported type, Imagick should return true (because it is not required)
+               $this->assertTrue($install->checkImagick());
+               $this->assertCheckExist(0,
+                       L10n::t('ImageMagick PHP extension is not installed'),
+                       '',
+                       false,
+                       false,
+                       $install->getChecks());
+       }
+}
+
+/**
+ * A workaround to replace the PHP native function_exists with a mocked function
+ *
+ * @param string $function_name the Name of the function
+ *
+ * @return bool true or false
+ */
+function function_exists($function_name)
+{
+       global $phpMock;
+       if (isset($phpMock['function_exists'])) {
+               $result = call_user_func_array($phpMock['function_exists'], func_get_args());
+               if ($result !== '__phpunit_continue__') {
+                       return $result;
+               }
+       }
+       return call_user_func_array('\function_exists', func_get_args());
+}
+
+function class_exists($class_name)
+{
+       global $phpMock;
+       if (isset($phpMock['class_exists'])) {
+               $result = call_user_func_array($phpMock['class_exists'], func_get_args());
+               if ($result !== '__phpunit_continue__') {
+                       return $result;
+               }
+       }
+       return call_user_func_array('\class_exists', func_get_args());
+}
diff --git a/view/templates/install.tpl b/view/templates/install.tpl
deleted file mode 100644 (file)
index 24ae022..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-<h1><img src="{{$baseurl}}/images/friendica-32.png"> {{$title}}</h1>
-<h2>{{$pass}}</h2>
-
-
-{{if $status}}
-<h3 class="error-message">{{$status}}</h3>
-{{/if}}
-
-{{$text}}
index 6b6c1c1e64e1d01c6eff9a212a15a264b8c0e28d..6c018db722922647c8577e81992c3ea1fab98b10 100644 (file)
 {{$info_03}}
 </p>
 
-{{if $status}}
-<h3 class="error-message">{{$status}}</h3>
-{{/if}}
+<table>
+       {{foreach $checks as $check}}
+       <tr><td>{{$check.title}} </td><td>
+                       {{if ! $check.status}}
+                       <img src="{{$baseurl}}/view/install/red.png" alt="Requirement not satisfied">
+                       {{/if}}
+       {{/foreach}}
+</table>
 
 <form id="install-form" action="{{$baseurl}}/install" method="post">
 
diff --git a/view/templates/install_finished.tpl b/view/templates/install_finished.tpl
new file mode 100644 (file)
index 0000000..5c8d765
--- /dev/null
@@ -0,0 +1,13 @@
+
+
+<h1><img src="{{$baseurl}}/images/friendica-32.png"> {{$title}}</h1>
+<h2>{{$pass}}</h2>
+
+
+{{foreach $checks as $check}}
+<img src="{{$baseurl}}/view/install/red.png" alt="Requirement not satisfied">
+{{$check.title}}
+<textarea rows="24" cols="80">{{$check.help}}</textarea>
+{{/foreach}}
+
+{{$text}}
index 5584e143652beb37862e92f20be76f976345984d..55e5ea34b10e95d46bbb00afe4ce8931c230fb8f 100644 (file)
@@ -4,10 +4,6 @@
 <h2>{{$pass}}</h2>
 
 
-{{if $status}}
-<h3 class="error-message">{{$status}}</h3>
-{{/if}}
-
 <form id="install-form" action="{{$baseurl}}/install" method="post">
 
 <input type="hidden" name="phpath" value="{{$phpath|escape:'html'}}" />