From: Philipp Holzer Date: Thu, 2 May 2019 21:17:35 +0000 (+0200) Subject: Move Console namespace one level up X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=d716a3326f4e7846e19ec2454054f6d20a71507a;p=friendica.git Move Console namespace one level up --- diff --git a/src/Console/ArchiveContact.php b/src/Console/ArchiveContact.php new file mode 100644 index 0000000000..cf177cf2e2 --- /dev/null +++ b/src/Console/ArchiveContact.php @@ -0,0 +1,75 @@ + [-h|--help|-?] [-v] + +Description + Archive a contact when you know that it isn't existing anymore. Normally this does happen automatically after a few days. + +Options + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + $a = \Friendica\BaseObject::getApp(); + + if ($this->getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + if (count($this->args) > 1) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + if ($a->getMode()->isInstall()) { + throw new RuntimeException('Friendica isn\'t properly installed yet.'); + } + + $nurl = Strings::normaliseLink($this->getArgument(0)); + if (!DBA::exists('contact', ['nurl' => $nurl, 'archive' => false])) { + throw new RuntimeException(L10n::t('Could not find any unarchived contact entry for this URL (%s)', $nurl)); + } + if (DBA::update('contact', ['archive' => true], ['nurl' => $nurl])) { + $this->out(L10n::t('The contact entries have been archived')); + } else { + throw new RuntimeException('The contact archival failed.'); + } + + return 0; + } +} diff --git a/src/Console/AutomaticInstallation.php b/src/Console/AutomaticInstallation.php new file mode 100644 index 0000000000..718573d27a --- /dev/null +++ b/src/Console/AutomaticInstallation.php @@ -0,0 +1,265 @@ + prepared config file (e.g. "config/local.config.php" itself) which will override every other config option - except the environment variables) + -s|--savedb Save the DB credentials to the file (if environment variables is used) + -H|--dbhost The host of the mysql/mariadb database (env MYSQL_HOST) + -p|--dbport The port of the mysql/mariadb database (env MYSQL_PORT) + -d|--dbdata The name of the mysql/mariadb database (env MYSQL_DATABASE) + -U|--dbuser The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME) + -P|--dbpass The password of the mysql/mariadb database login (env MYSQL_PASSWORD) + -U|--url The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL) + -B|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) + -b|--basepath The basepath of Friendica (env FRIENDICA_BASE_PATH) + -t|--tz The timezone of Friendica (env FRIENDICA_TZ) + -L|--lang The language of Friendica (env FRIENDICA_LANG) + +Environment variables + MYSQL_HOST The host of the mysql/mariadb database (mandatory if mysql and environment is used) + MYSQL_PORT The port of the mysql/mariadb database + MYSQL_USERNAME|MYSQL_USER The username of the mysql/mariadb database login (MYSQL_USERNAME is for mysql, MYSQL_USER for mariadb) + MYSQL_PASSWORD The password of the mysql/mariadb database login + MYSQL_DATABASE The name of the mysql/mariadb database + FRIENDICA_URL The full base URL of Friendica - f.e. 'https://friendica.local/sub' + FRIENDICA_PHP_PATH The path of the PHP binary - leave empty for auto detection + FRIENDICA_BASE_PATH The basepath of Friendica - leave empty for auto detection + FRIENDICA_ADMIN_MAIL The admin email address of Friendica (this email will be used for admin access) + FRIENDICA_TZ The timezone of Friendica + FRIENDICA_LANG The langauge of Friendica + +Examples + bin/console autoinstall -f 'input.config.php + Installs Friendica with the prepared 'input.config.php' file + + bin/console autoinstall --savedb + Installs Friendica with environment variables and saves them to the 'config/local.config.php' file + + bin/console autoinstall -h localhost -p 3365 -U user -P passwort1234 -d friendica + Installs Friendica with a local mysql database with credentials +HELP; + } + + protected function doExecute() + { + // Initialise the app + $this->out("Initializing setup...\n"); + + $a = BaseObject::getApp(); + + $installer = new Installer(); + + $configCache = $a->getConfigCache(); + $installer->setUpCache($configCache, BasePath::create($a->getBasePath(), $_SERVER)); + + $this->out(" Complete!\n\n"); + + // Check Environment + $this->out("Checking environment...\n"); + + $installer->resetChecks(); + + if (!$this->runBasicChecks($installer, $configCache)) { + $errorMessage = $this->extractErrors($installer->getChecks()); + throw new RuntimeException($errorMessage); + } + + $this->out(" Complete!\n\n"); + + // if a config file is set, + $config_file = $this->getOption(['f', 'file']); + + if (!empty($config_file)) { + if ($config_file != 'config' . DIRECTORY_SEPARATOR . 'local.config.php') { + // Copy config file + $this->out("Copying config file...\n"); + if (!copy($a->getBasePath() . DIRECTORY_SEPARATOR . $config_file, $a->getBasePath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.config.php')) { + throw new RuntimeException("ERROR: Saving config file failed. Please copy '$config_file' to '" . $a->getBasePath() . "'" . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "local.config.php' manually.\n"); + } + } + + //reload the config cache + $loader = new ConfigFileLoader($a->getBasePath(), $a->getMode()); + $loader->setupCache($configCache); + + } else { + // Creating config file + $this->out("Creating config file...\n"); + + $save_db = $this->getOption(['s', 'savedb'], false); + + $db_host = $this->getOption(['H', 'dbhost'], ($save_db) ? (getenv('MYSQL_HOST')) : Installer::DEFAULT_HOST); + $db_port = $this->getOption(['p', 'dbport'], ($save_db) ? getenv('MYSQL_PORT') : null); + $configCache->set('database', 'hostname', $db_host . (!empty($db_port) ? ':' . $db_port : '')); + $configCache->set('database', 'database', + $this->getOption(['d', 'dbdata'], + ($save_db) ? getenv('MYSQL_DATABASE') : '')); + $configCache->set('database', 'username', + $this->getOption(['U', 'dbuser'], + ($save_db) ? getenv('MYSQL_USER') . getenv('MYSQL_USERNAME') : '')); + $configCache->set('database', 'password', + $this->getOption(['P', 'dbpass'], + ($save_db) ? getenv('MYSQL_PASSWORD') : '')); + + $php_path = $this->getOption(['b', 'phppath'], !empty('FRIENDICA_PHP_PATH') ? getenv('FRIENDICA_PHP_PATH') : null); + if (!empty($php_path)) { + $configCache->set('config', 'php_path', $php_path); + } else { + $configCache->set('config', 'php_path', $installer->getPHPPath()); + } + + $configCache->set('config', 'admin_email', + $this->getOption(['A', 'admin'], + !empty(getenv('FRIENDICA_ADMIN_MAIL')) ? getenv('FRIENDICA_ADMIN_MAIL') : '')); + $configCache->set('system', 'default_timezone', + $this->getOption(['T', 'tz'], + !empty(getenv('FRIENDICA_TZ')) ? getenv('FRIENDICA_TZ') : Installer::DEFAULT_TZ)); + $configCache->set('system', 'language', + $this->getOption(['L', 'lang'], + !empty(getenv('FRIENDICA_LANG')) ? getenv('FRIENDICA_LANG') : Installer::DEFAULT_LANG)); + + $basepath = $this->getOption(['b', 'basepath'], !empty(getenv('FRIENDICA_BASE_PATH')) ? getenv('FRIENDICA_BASE_PATH') : null); + if (!empty($basepath)) { + $configCache->set('system', 'basepath', $basepath); + } + + $url = $this->getOption(['U', 'url'], !empty(getenv('FRIENDICA_URL')) ? getenv('FRIENDICA_URL') : null); + + if (empty($url)) { + $this->out('The Friendica URL has to be set during CLI installation.'); + return 1; + } else { + $baseUrl = new BaseURL($a->getConfig(), []); + $baseUrl->saveByURL($url); + } + + $installer->createConfig($configCache); + } + + $this->out(" Complete!\n\n"); + + // Check database connection + $this->out("Checking database...\n"); + + $installer->resetChecks(); + + if (!$installer->checkDB($configCache, $a->getProfiler())) { + $errorMessage = $this->extractErrors($installer->getChecks()); + throw new RuntimeException($errorMessage); + } + + $this->out(" Complete!\n\n"); + + // Install database + $this->out("Inserting data into database...\n"); + + $installer->resetChecks(); + + if (!$installer->installDatabase($a->getBasePath())) { + $errorMessage = $this->extractErrors($installer->getChecks()); + throw new RuntimeException($errorMessage); + } + + $this->out(" Complete!\n\n"); + + // Install theme + $this->out("Installing theme\n"); + if (!empty(Config::get('system', 'theme'))) { + Theme::install(Config::get('system', 'theme')); + $this->out(" Complete\n\n"); + } else { + $this->out(" Theme setting is empty. Please check the file 'config/local.config.php'\n\n"); + } + + $this->out("\nInstallation is finished\n"); + + return 0; + } + + /** + * @param Installer $installer The Installer instance + * @param Config\Cache\IConfigCache $configCache The config cache + * + * @return bool true if checks were successfully, otherwise false + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + private function runBasicChecks(Installer $installer, Config\Cache\IConfigCache $configCache) + { + $checked = true; + + $installer->resetChecks(); + if (!$installer->checkFunctions()) { + $checked = false; + } + if (!$installer->checkImagick()) { + $checked = false; + } + if (!$installer->checkLocalIni()) { + $checked = false; + } + if (!$installer->checkSmarty3()) { + $checked = false; + } + if (!$installer->checkKeys()) { + $checked = false; + } + + $php_path = $configCache->get('config', 'php_path'); + + if (!$installer->checkPHP($php_path, true)) { + $checked = false; + } + + $this->out(" NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.\n"); + + return $checked; + } + + /** + * @param array $results + * @return string + */ + private function extractErrors($results) + { + $errorMessage = ''; + $allChecksRequired = $this->getOption('a') !== null; + + foreach ($results as $result) { + if (($allChecksRequired || $result['required'] === true) && $result['status'] === false) { + $errorMessage .= "--------\n"; + $errorMessage .= $result['title'] . ': ' . $result['help'] . "\n"; + } + } + + return $errorMessage; + } +} diff --git a/src/Console/Cache.php b/src/Console/Cache.php new file mode 100644 index 0000000000..eefb6cc60b --- /dev/null +++ b/src/Console/Cache.php @@ -0,0 +1,178 @@ + + */ +class Cache extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = << [-h|--help|-?] [-v] + bin/console cache set [-h|--help|-?] [-v] + bin/console cache flush [-h|--help|-?] [-v] + bin/console cache clear [-h|--help|-?] [-v] + +Description + bin/console cache list [] + List all cache keys, optionally filtered by a prefix + + bin/console cache get + Shows the value of the provided cache key + + bin/console cache set [] + Sets the value of the provided cache key, optionally with the provided TTL (time to live) with a default of five minutes. + + bin/console cache flush + Clears expired cache keys + + bin/console cache clear + Clears all cache keys + +Options + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + $a = \Friendica\BaseObject::getApp(); + + if ($this->getOption('v')) { + $this->out('Executable: ' . $this->executable); + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if ($a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { + $this->out('Database isn\'t ready or populated yet, database cache won\'t be available'); + } + + Core\Cache::init(); + + if ($this->getOption('v')) { + $this->out('Cache Driver Name: ' . Core\Cache::$driver_name); + $this->out('Cache Driver Class: ' . Core\Cache::$driver_class); + } + + switch ($this->getArgument(0)) { + case 'list': + $this->executeList(); + break; + case 'get': + $this->executeGet(); + break; + case 'set': + $this->executeSet(); + break; + case 'flush': + $this->executeFlush(); + break; + case 'clear': + $this->executeClear(); + break; + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + return 0; + } + + private function executeList() + { + $prefix = $this->getArgument(1); + $keys = Core\Cache::getAllKeys($prefix); + + if (empty($prefix)) { + $this->out('Listing all cache keys:'); + } else { + $this->out('Listing all cache keys starting with "' . $prefix . '":'); + } + + $count = 0; + foreach ($keys as $key) { + $this->out($key); + $count++; + } + + $this->out($count . ' keys found'); + } + + private function executeGet() + { + if (count($this->args) >= 2) { + $key = $this->getArgument(1); + $value = Core\Cache::get($key); + + $this->out("{$key} => " . var_export($value, true)); + } else { + throw new CommandArgsException('Too few arguments for get'); + } + } + + private function executeSet() + { + if (count($this->args) >= 3) { + $key = $this->getArgument(1); + $value = $this->getArgument(2); + $duration = intval($this->getArgument(3, Core\Cache::FIVE_MINUTES)); + + if (is_array(Core\Cache::get($key))) { + throw new RuntimeException("$key is an array and can't be set using this command."); + } + + $result = Core\Cache::set($key, $value, $duration); + if ($result) { + $this->out("{$key} <= " . Core\Cache::get($key)); + } else { + $this->out("Unable to set {$key}"); + } + } else { + throw new CommandArgsException('Too few arguments for set'); + } + } + + private function executeFlush() + { + $result = Core\Cache::clear(); + if ($result) { + $this->out('Cache successfully flushed'); + } else { + $this->out('Unable to flush the cache'); + } + } + + private function executeClear() + { + $result = Core\Cache::clear(false); + if ($result) { + $this->out('Cache successfully cleared'); + } else { + $this->out('Unable to flush the cache'); + } + } +} diff --git a/src/Console/Config.php b/src/Console/Config.php new file mode 100644 index 0000000000..a27ca13498 --- /dev/null +++ b/src/Console/Config.php @@ -0,0 +1,171 @@ + + * @author Hypolite Petovan + */ +class Config extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = << [-h|--help|-?] [-v] + bin/console config [-h|--help|-?] [-v] + bin/console config [-h|--help|-?] [-v] + +Description + bin/console config + Lists all config values + + bin/console config + Lists all config values in the provided category + + bin/console config + Shows the value of the provided key in the category + + bin/console config + Sets the value of the provided key in the category + +Notes: + Setting config entries which are manually set in config/local.config.php may result in + conflict between database settings and the manual startup settings. + +Options + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + $a = \Friendica\BaseObject::getApp(); + + if ($this->getOption('v')) { + $this->out('Executable: ' . $this->executable); + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) > 3) { + throw new CommandArgsException('Too many arguments'); + } + + if (!$a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { + $this->out('Database isn\'t ready or populated yet, showing file config only'); + } + + if (count($this->args) == 3) { + $cat = $this->getArgument(0); + $key = $this->getArgument(1); + $value = $this->getArgument(2); + + if (is_array(Core\Config::get($cat, $key))) { + throw new RuntimeException("$cat.$key is an array and can't be set using this command."); + } + + $result = Core\Config::set($cat, $key, $value); + if ($result) { + $this->out("{$cat}.{$key} <= " . + Core\Config::get($cat, $key)); + } else { + $this->out("Unable to set {$cat}.{$key}"); + } + } + + if (count($this->args) == 2) { + $cat = $this->getArgument(0); + $key = $this->getArgument(1); + $value = Core\Config::get($this->getArgument(0), $this->getArgument(1)); + + if (is_array($value)) { + foreach ($value as $k => $v) { + $this->out("{$cat}.{$key}[{$k}] => " . (is_array($v) ? implode(', ', $v) : $v)); + } + } else { + $this->out("{$cat}.{$key} => " . $value); + } + } + + if (count($this->args) == 1) { + $cat = $this->getArgument(0); + Core\Config::load($cat); + + if ($a->getConfigCache()->get($cat) !== null) { + $this->out("[{$cat}]"); + $catVal = $a->getConfigCache()->get($cat); + foreach ($catVal as $key => $value) { + if (is_array($value)) { + foreach ($value as $k => $v) { + $this->out("{$key}[{$k}] => " . (is_array($v) ? implode(', ', $v) : $v)); + } + } else { + $this->out("{$key} => " . $value); + } + } + } else { + $this->out('Config section ' . $this->getArgument(0) . ' returned nothing'); + } + } + + if (count($this->args) == 0) { + Core\Config::load(); + + if (Core\Config::get('system', 'config_adapter') == 'jit' && $a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { + $this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only'); + } + + $config = $a->getConfigCache()->getAll(); + foreach ($config as $cat => $section) { + if (is_array($section)) { + foreach ($section as $key => $value) { + if (is_array($value)) { + foreach ($value as $k => $v) { + $this->out("{$cat}.{$key}[{$k}] => " . (is_array($v) ? implode(', ', $v) : $v)); + } + } else { + $this->out("{$cat}.{$key} => " . $value); + } + } + } else { + $this->out("config.{$cat} => " . $section); + } + } + } + + return 0; + } +} diff --git a/src/Console/CreateDoxygen.php b/src/Console/CreateDoxygen.php new file mode 100644 index 0000000000..0196839e3d --- /dev/null +++ b/src/Console/CreateDoxygen.php @@ -0,0 +1,148 @@ + + */ +class CreateDoxygen extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = << [-h|--help|-?] [-v] + +Description + Outputs the provided file with added Doxygen headers to functions + +Options + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + if ($this->getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + if (count($this->args) > 1) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + $file = $this->getArgument(0); + if (!file_exists($file)) { + throw new \RuntimeException('Unable to find specified file.'); + } + + $data = file_get_contents($file); + + $lines = explode("\n", $data); + + $previous = ""; + + foreach ($lines AS $line) { + $line = rtrim(trim($line, "\r")); + + if (strstr(strtolower($line), "function")) { + $detect = strtolower(trim($line)); + $detect = implode(" ", explode(" ", $detect)); + + $found = false; + + if (substr($detect, 0, 9) == "function ") { + $found = true; + } + + if (substr($detect, 0, 19) == "protected function ") { + $found = true; + } + + if (substr($detect, 0, 17) == "private function ") { + $found = true; + } + + if (substr($detect, 0, 23) == "public static function ") { + $found = true; + } + + if (substr($detect, 0, 24) == "private static function ") { + $found = true; + } + + if (substr($detect, 0, 10) == "function (") { + $found = false; + } + + if ($found && ( trim($previous) == "*/")) { + $found = false; + } + + if ($found) { + $this->out($this->addDocumentation($line)); + } + } + $this->out($line); + $previous = $line; + } + + return 0; + } + + /** + * @brief Adds a doxygen header + * + * @param string $line The current line of the document + * + * @return string added doxygen header + */ + private function addDocumentation($line) + { + $trimmed = ltrim($line); + $length = strlen($line) - strlen($trimmed); + $space = substr($line, 0, $length); + + $block = $space . "/**\n" . + $space . " * @brief \n" . + $space . " *\n"; /**/ + + + $left = strpos($line, "("); + $line = substr($line, $left + 1); + + $right = strpos($line, ")"); + $line = trim(substr($line, 0, $right)); + + if ($line != "") { + $parameters = explode(",", $line); + foreach ($parameters AS $parameter) { + $parameter = trim($parameter); + $splitted = explode("=", $parameter); + + $block .= $space . " * @param " . trim($splitted[0], "& ") . "\n"; + } + if (count($parameters) > 0) $block .= $space . " *\n"; + } + + $block .= $space . " * @return \n" . + $space . " */\n"; + + return $block; + } + +} diff --git a/src/Console/DatabaseStructure.php b/src/Console/DatabaseStructure.php new file mode 100644 index 0000000000..3feaa64d60 --- /dev/null +++ b/src/Console/DatabaseStructure.php @@ -0,0 +1,94 @@ + + */ +class DatabaseStructure extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = << [-h|--help|-?] |-f|--force] [-v] + +Commands + dryrun Show database update schema queries without running them + update Update database schema + dumpsql Dump database schema + toinnodb Convert all tables from MyISAM to InnoDB + +Options + -h|--help|-? Show help information + -v Show more debug information. + -f|--force Force the update command (Even if the database structure matches) + -o|--override Override running or stalling updates +HELP; + return $help; + } + + protected function doExecute() + { + if ($this->getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + if (count($this->args) > 1) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + if (!DBA::connected()) { + throw new RuntimeException('Unable to connect to database'); + } + + Core\Config::load(); + + $a = get_app(); + + switch ($this->getArgument(0)) { + case "dryrun": + $output = DBStructure::update($a->getBasePath(), true, false); + break; + case "update": + $force = $this->getOption(['f', 'force'], false); + $override = $this->getOption(['o', 'override'], false); + $output = Update::run($a->getBasePath(), $force, $override,true, false); + break; + case "dumpsql": + ob_start(); + DBStructure::printStructure($a->getBasePath()); + $output = ob_get_clean(); + break; + case "toinnodb": + ob_start(); + DBStructure::convertToInnoDB(); + $output = ob_get_clean(); + break; + default: + $output = 'Unknown command: ' . $this->getArgument(0); + } + + $this->out($output); + + return 0; + } +} diff --git a/src/Console/DocBloxErrorChecker.php b/src/Console/DocBloxErrorChecker.php new file mode 100644 index 0000000000..4393e99b18 --- /dev/null +++ b/src/Console/DocBloxErrorChecker.php @@ -0,0 +1,186 @@ + + */ +class DocBloxErrorChecker extends \Asika\SimpleConsole\Console +{ + + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = <<getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) > 0) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + if (!$this->commandExists('docblox')) { + throw new \RuntimeException('DocBlox isn\'t available.'); + } + + $dir = \get_app()->getBasePath(); + + //stack for dirs to search + $dirstack = []; + //list of source files + $filelist = []; + + //loop over all files in $dir + while ($dh = opendir($dir)) { + while ($file = readdir($dh)) { + if (is_dir($dir . "/" . $file)) { + //add to directory stack + if (strpos($file, '.') !== 0) { + array_push($dirstack, $dir . "/" . $file); + $this->out('dir ' . $dir . '/' . $file); + } + } else { + //test if it is a source file and add to filelist + if (substr($file, strlen($file) - 4) == ".php") { + array_push($filelist, $dir . "/" . $file); + $this->out($dir . '/' . $file); + } + } + } + //look at the next dir + $dir = array_pop($dirstack); + } + + //check the entire set + if ($this->runs($filelist)) { + throw new \RuntimeException("I can not detect a problem."); + } + + //check half of the set and discard if that half is okay + $res = $filelist; + $i = count($res); + do { + $this->out($i . '/' . count($filelist) . ' elements remaining.'); + $res = $this->reduce($res, count($res) / 2); + shuffle($res); + $i = count($res); + } while (count($res) < $i); + + //check one file after another + $needed = []; + + while (count($res) != 0) { + $file = array_pop($res); + + if ($this->runs(array_merge($res, $needed))) { + $this->out('needs: ' . $file . ' and file count ' . count($needed)); + array_push($needed, $file); + } + } + + $this->out('Smallest Set is: ' . $this->namesList($needed) . ' with ' . count($needed) . ' files. '); + + return 0; + } + + private function commandExists($command) + { + $prefix = strpos(strtolower(PHP_OS),'win') > -1 ? 'where' : 'which'; + exec("{$prefix} {$command}", $output, $returnVal); + return $returnVal === 0; + } + + /** + * This function generates a comma separated list of file names. + * + * @param array $fileset Set of file names + * + * @return string comma-separated list of the file names + */ + private function namesList($fileset) + { + return implode(',', $fileset); + } + + /** + * This functions runs phpdoc on the provided list of files + * + * @param array $fileset Set of filenames + * + * @return bool true, if that set can be built + */ + private function runs($fileset) + { + $fsParam = $this->namesList($fileset); + $this->exec('docblox -t phpdoc_out -f ' . $fsParam); + if (file_exists("phpdoc_out/index.html")) { + $this->out('Subset ' . $fsParam . ' is okay.'); + $this->exec('rm -r phpdoc_out'); + return true; + } else { + $this->out('Subset ' . $fsParam . ' failed.'); + return false; + } + } + + /** + * This functions cuts down a fileset by removing files until it finally works. + * it was meant to be recursive, but php's maximum stack size is to small. So it just simulates recursion. + * + * In that version, it does not necessarily generate the smallest set, because it may not alter the elements order enough. + * + * @param array $fileset set of filenames + * @param int $ps number of files in subsets + * + * @return array a part of $fileset, that crashes + */ + private function reduce($fileset, $ps) + { + //split array... + $parts = array_chunk($fileset, $ps); + //filter working subsets... + $parts = array_filter($parts, [$this, 'runs']); + //melt remaining parts together + if (is_array($parts)) { + return array_reduce($parts, "array_merge", []); + } + return []; + } + +} diff --git a/src/Console/Extract.php b/src/Console/Extract.php new file mode 100644 index 0000000000..7fac598fe9 --- /dev/null +++ b/src/Console/Extract.php @@ -0,0 +1,140 @@ + + */ +class Extract extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = <<getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) > 0) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + $s = 'globRecursive('src') + ); + + foreach ($files as $file) { + $str = file_get_contents($file); + + $pat = '|L10n::t\(([^\)]*+)[\)]|'; + $patt = '|L10n::tt\(([^\)]*+)[\)]|'; + + $matches = []; + $matchestt = []; + + preg_match_all($pat, $str, $matches); + preg_match_all($patt, $str, $matchestt); + + if (count($matches) || count($matchestt)) { + $s .= '// ' . $file . PHP_EOL; + } + + if (!empty($matches[1])) { + foreach ($matches[1] as $long_match) { + $match_arr = preg_split('/(?<=[\'"])\s*,/', $long_match); + $match = $match_arr[0]; + if (!in_array($match, $arr)) { + if (substr($match, 0, 1) == '$') { + continue; + } + + $arr[] = $match; + + $s .= '$a->strings[' . $match . '] = ' . $match . ';' . "\n"; + } + } + } + if (!empty($matchestt[1])) { + foreach ($matchestt[1] as $match) { + $matchtkns = preg_split("|[ \t\r\n]*,[ \t\r\n]*|", $match); + if (count($matchtkns) == 3 && !in_array($matchtkns[0], $arr)) { + if (substr($matchtkns[1], 0, 1) == '$') { + continue; + } + + $arr[] = $matchtkns[0]; + + $s .= '$a->strings[' . $matchtkns[0] . "] = array(\n"; + $s .= "\t0 => " . $matchtkns[0] . ",\n"; + $s .= "\t1 => " . $matchtkns[1] . ",\n"; + $s .= ");\n"; + } + } + } + } + + $s .= '// Timezones' . PHP_EOL; + + $zones = timezone_identifiers_list(); + foreach ($zones as $zone) { + $s .= '$a->strings[\'' . $zone . '\'] = \'' . $zone . '\';' . "\n"; + } + + $this->out($s); + + return 0; + } + + private function globRecursive($path) { + $dir_iterator = new \RecursiveDirectoryIterator($path); + $iterator = new \RecursiveIteratorIterator($dir_iterator, \RecursiveIteratorIterator::SELF_FIRST); + + $return = []; + foreach ($iterator as $file) { + if ($file->getBasename() != '.' && $file->getBasename() != '..') { + $return[] = $file->getPathname(); + } + } + + return $return; + } +} diff --git a/src/Console/GlobalCommunityBlock.php b/src/Console/GlobalCommunityBlock.php new file mode 100644 index 0000000000..bc067dada6 --- /dev/null +++ b/src/Console/GlobalCommunityBlock.php @@ -0,0 +1,75 @@ + + * @author Hypolite Petovan + */ +class GlobalCommunityBlock extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = << [-h|--help|-?] [-v] + +Description + Blocks an account in such a way that no postings or comments this account writes are accepted to this node. + +Options + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + $a = \get_app(); + + if ($this->getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + if (count($this->args) > 1) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + if ($a->getMode()->isInstall()) { + throw new \RuntimeException('Database isn\'t ready or populated yet'); + } + + $contact_id = Contact::getIdForURL($this->getArgument(0)); + if (!$contact_id) { + throw new \RuntimeException(L10n::t('Could not find any contact entry for this URL (%s)', $this->getArgument(0))); + } + if(Contact::block($contact_id)) { + $this->out(L10n::t('The contact has been blocked from the node')); + } else { + throw new \RuntimeException('The contact block failed.'); + } + + return 0; + } +} diff --git a/src/Console/GlobalCommunitySilence.php b/src/Console/GlobalCommunitySilence.php new file mode 100644 index 0000000000..daaf551499 --- /dev/null +++ b/src/Console/GlobalCommunitySilence.php @@ -0,0 +1,92 @@ + + * @author Hypolite Petovan + */ +class GlobalCommunitySilence extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = << [-h|--help|-?] [-v] + +Description + With this tool, you can silence an account on the global community page. + Postings from silenced accounts will not be displayed on the community page. + This silencing does only affect the display on the community page, accounts + following the silenced accounts will still get their postings. + +Options + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + $a = \get_app(); + + if ($this->getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + if (count($this->args) > 1) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + if ($a->getMode()->isInstall()) { + throw new RuntimeException('Database isn\'t ready or populated yet'); + } + + /** + * 1. make nurl from last parameter + * 2. check DB (contact) if there is a contact with uid=0 and that nurl, get the ID + * 3. set the flag hidden=1 for the contact entry with the found ID + * */ + $net = Probe::uri($this->getArgument(0)); + if (in_array($net['network'], [Protocol::PHANTOM, Protocol::MAIL])) { + throw new RuntimeException('This account seems not to exist.'); + } + + $nurl = Strings::normaliseLink($net['url']); + $contact = DBA::selectFirst("contact", ["id"], ["nurl" => $nurl, "uid" => 0]); + if (DBA::isResult($contact)) { + DBA::update("contact", ["hidden" => true], ["id" => $contact["id"]]); + $this->out('NOTICE: The account should be silenced from the global community page'); + } else { + throw new RuntimeException('NOTICE: Could not find any entry for this URL (' . $nurl . ')'); + } + + return 0; + } +} diff --git a/src/Console/Maintenance.php b/src/Console/Maintenance.php new file mode 100644 index 0000000000..080eb092b7 --- /dev/null +++ b/src/Console/Maintenance.php @@ -0,0 +1,95 @@ + + */ +class Maintenance extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = << [] [-h|--help|-?] [-v] + +Description + cen be either 0 or 1 to disabled or enable the maintenance mode on this node. + + is a quote-enclosed string with the optional reason for the maintenance mode. + +Examples + bin/console maintenance 1 + Enables the maintenance mode without setting a reason message + + bin/console maintenance 1 "SSL certification update" + Enables the maintenance mode with setting a reason message + + bin/console maintenance 0 + Disables the maintenance mode + +Options + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + $a = \Friendica\BaseObject::getApp(); + + if ($this->getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + if (count($this->args) > 2) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + if ($a->getMode()->isInstall()) { + throw new \RuntimeException('Database isn\'t ready or populated yet'); + } + + $enabled = intval($this->getArgument(0)); + + Core\Config::set('system', 'maintenance', $enabled); + + $reason = $this->getArgument(1); + + if ($enabled && $this->getArgument(1)) { + Core\Config::set('system', 'maintenance_reason', $this->getArgument(1)); + } else { + Core\Config::set('system', 'maintenance_reason', ''); + } + + if ($enabled) { + $mode_str = "maintenance mode"; + } else { + $mode_str = "normal mode"; + } + + $this->out('System set in ' . $mode_str); + + if ($enabled && $reason != '') { + $this->out('Maintenance reason: ' . $reason); + } + + return 0; + } + +} diff --git a/src/Console/NewPassword.php b/src/Console/NewPassword.php new file mode 100644 index 0000000000..dc6943817f --- /dev/null +++ b/src/Console/NewPassword.php @@ -0,0 +1,90 @@ + + */ +class NewPassword extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = << [] [-h|--help|-?] [-v] + +Description + Creates a new password for a user without using the "forgot password" functionality. + +Options + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + $a = \get_app(); + + if ($this->getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + if (count($this->args) > 2) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + if ($a->getMode()->isInstall()) { + throw new RuntimeException('Database isn\'t ready or populated yet'); + } + + $nick = $this->getArgument(0); + + $user = DBA::selectFirst('user', ['uid'], ['nickname' => $nick]); + if (!DBA::isResult($user)) { + throw new RuntimeException(L10n::t('User not found')); + } + + $password = $this->getArgument(1); + if (is_null($password)) { + $this->out(L10n::t('Enter new password: '), false); + $password = \Seld\CliPrompt\CliPrompt::hiddenPrompt(true); + } + + try { + $result = User::updatePassword($user['uid'], $password); + + if (!DBA::isResult($result)) { + throw new \Exception(L10n::t('Password update failed. Please try again.')); + } + + $this->out(L10n::t('Password changed.')); + } catch (\Exception $e) { + throw new RuntimeException($e->getMessage(), $e->getCode(), $e); + } + + return 0; + } +} diff --git a/src/Console/PhpToPo.php b/src/Console/PhpToPo.php new file mode 100644 index 0000000000..d73c7f4ab6 --- /dev/null +++ b/src/Console/PhpToPo.php @@ -0,0 +1,237 @@ + + */ +class PhpToPo extends \Asika\SimpleConsole\Console +{ + + protected $helpOptions = ['h', 'help', '?']; + + private $normBaseMsgIds = []; + const NORM_REGEXP = "|[\\\]|"; + + protected function getHelp() + { + $help = <<] [--base ] [-h|--help|-?] [-v] + +Description + Read a strings.php file and create the according messages.po in the same directory + +Options + -p Number of plural forms. Default: 2 + --base Path to base messages.po file. Default: view/lang/C/messages.po + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + if ($this->getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + if (count($this->args) > 1) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + $a = \get_app(); + + $phpfile = realpath($this->getArgument(0)); + + if (!file_exists($phpfile)) { + throw new \RuntimeException('Supplied file path doesn\'t exist.'); + } + + if (!is_writable(dirname($phpfile))) { + throw new \RuntimeException('Supplied directory isn\'t writable.'); + } + + $pofile = dirname($phpfile) . DIRECTORY_SEPARATOR . 'messages.po'; + + // start ! + include_once($phpfile); + + $out = ''; + $out .= "# FRIENDICA Distributed Social Network\n"; + $out .= "# Copyright (C) 2010, 2011, 2012, 2013 the Friendica Project\n"; + $out .= "# This file is distributed under the same license as the Friendica package.\n"; + $out .= "# \n"; + $out .= 'msgid ""' . "\n"; + $out .= 'msgstr ""' . "\n"; + $out .= '"Project-Id-Version: friendica\n"' . "\n"; + $out .= '"Report-Msgid-Bugs-To: \n"' . "\n"; + $out .= '"POT-Creation-Date: ' . date("Y-m-d H:i:sO") . '\n"' . "\n"; + $out .= '"MIME-Version: 1.0\n"' . "\n"; + $out .= '"Content-Type: text/plain; charset=UTF-8\n"' . "\n"; + $out .= '"Content-Transfer-Encoding: 8bit\n"' . "\n"; + + // search for plural info + $lang = ""; + $lang_logic = ""; + $lang_pnum = $this->getOption('p', 2); + + $infile = file($phpfile); + foreach ($infile as $l) { + $l = trim($l); + if ($this->startsWith($l, 'function string_plural_select_')) { + $lang = str_replace('function string_plural_select_', '', str_replace('($n){', '', $l)); + } + if ($this->startsWith($l, 'return')) { + $lang_logic = str_replace('$', '', trim(str_replace('return ', '', $l), ';')); + break; + } + } + + $this->out('Language: ' . $lang); + $this->out('Plural forms: ' . $lang_pnum); + $this->out('Plural forms: ' . $lang_logic); + + $out .= sprintf('"Language: %s\n"', $lang) . "\n"; + $out .= sprintf('"Plural-Forms: nplurals=%s; plural=%s;\n"', $lang_pnum, $lang_logic) . "\n"; + $out .= "\n"; + + $base_path = $this->getOption('base', 'view/lang/C/messages.po'); + + // load base messages.po and extract msgids + $base_msgids = []; + $base_f = file($base_path); + if (!$base_f) { + throw new \RuntimeException('The base ' . $base_path . ' file is missing or unavailable to read.'); + } + + $this->out('Loading base file ' . $base_path . '...'); + + $_f = 0; + $_mid = ""; + $_mids = []; + foreach ($base_f as $l) { + $l = trim($l); + + if ($this->startsWith($l, 'msgstr')) { + if ($_mid != '""') { + $base_msgids[$_mid] = $_mids; + $this->normBaseMsgIds[preg_replace(self::NORM_REGEXP, "", $_mid)] = $_mid; + } + + $_f = 0; + $_mid = ""; + $_mids = []; + } + + if ($this->startsWith($l, '"') && $_f == 2) { + $_mids[count($_mids) - 1] .= "\n" . $l; + } + if ($this->startsWith($l, 'msgid_plural ')) { + $_f = 2; + $_mids[] = str_replace('msgid_plural ', '', $l); + } + + if ($this->startsWith($l, '"') && $_f == 1) { + $_mid .= "\n" . $l; + $_mids[count($_mids) - 1] .= "\n" . $l; + } + if ($this->startsWith($l, 'msgid ')) { + $_f = 1; + $_mid = str_replace('msgid ', '', $l); + $_mids = [$_mid]; + } + } + + $this->out('Creating ' . $pofile . '...'); + + // create msgid and msgstr + $warnings = ""; + foreach ($a->strings as $key => $str) { + $msgid = $this->massageString($key); + + if (preg_match("|%[sd0-9](\$[sn])*|", $msgid)) { + $out .= "#, php-format\n"; + } + $msgid = $this->findOriginalMsgId($msgid); + $out .= 'msgid ' . $msgid . "\n"; + + if (is_array($str)) { + if (array_key_exists($msgid, $base_msgids) && isset($base_msgids[$msgid][1])) { + $out .= 'msgid_plural ' . $base_msgids[$msgid][1] . "\n"; + } else { + $out .= 'msgid_plural ' . $msgid . "\n"; + $warnings .= "[W] No source plural form for msgid:\n" . str_replace("\n", "\n\t", $msgid) . "\n\n"; + } + foreach ($str as $n => $msgstr) { + $out .= 'msgstr[' . $n . '] ' . $this->massageString($msgstr) . "\n"; + } + } else { + $out .= 'msgstr ' . $this->massageString($str) . "\n"; + } + + $out .= "\n"; + } + + if (!file_put_contents($pofile, $out)) { + throw new \RuntimeException('Unable to write to ' . $pofile); + } + + if ($warnings != '') { + $this->out($warnings); + } + + return 0; + } + + private function startsWith($haystack, $needle) + { + // search backwards starting from haystack length characters from the end + return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE; + } + + /** + * Get a string and retun a message.po ready text + * - replace " with \" + * - replace tab char with \t + * - manage multiline strings + * + * @param string $str + * @return string + */ + private function massageString($str) + { + $str = str_replace('\\', '\\\\', $str); + $str = str_replace('"', '\"', $str); + $str = str_replace("\t", '\t', $str); + $str = str_replace("\n", '\n"' . "\n" . '"', $str); + if (strpos($str, "\n") !== false && $str[0] !== '"') { + $str = '"' . "\n" . $str; + } + + $str = preg_replace("|\n([^\"])|", "\n\"$1", $str); + return sprintf('"%s"', $str); + } + + private function findOriginalMsgId($str) + { + $norm_str = preg_replace(self::NORM_REGEXP, "", $str); + if (array_key_exists($norm_str, $this->normBaseMsgIds)) { + return $this->normBaseMsgIds[$norm_str]; + } + + return $str; + } + +} diff --git a/src/Console/PoToPhp.php b/src/Console/PoToPhp.php new file mode 100644 index 0000000000..c4ba42ccc4 --- /dev/null +++ b/src/Console/PoToPhp.php @@ -0,0 +1,198 @@ + + */ +class PoToPhp extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + const DQ_ESCAPE = "__DQ__"; + + protected function getHelp() + { + $help = << [-h|--help|-?] [-v] + +Description + Read a messages.po file and create the according strings.php in the same directory + +Options + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + if ($this->getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + if (count($this->args) > 1) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + $pofile = realpath($this->getArgument(0)); + + if (!file_exists($pofile)) { + throw new \RuntimeException('Supplied file path doesn\'t exist.'); + } + + if (!is_writable(dirname($pofile))) { + throw new \RuntimeException('Supplied directory isn\'t writable.'); + } + + $outfile = dirname($pofile) . DIRECTORY_SEPARATOR . 'strings.php'; + + if (basename(dirname($pofile)) == 'C') { + $lang = 'en'; + } else { + $lang = str_replace('-', '_', basename(dirname($pofile))); + } + + $this->out('Out to ' . $outfile); + + $out = "strings["' . $k . '"] = '; + } + + if ($inv) { + $out .= '"' . $v . '"'; + } + + $v = substr($l, 8, $len - 10); + $v = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $v); + + $inv = true; + } + + if ($k != "" && substr($l, 0, 7) == 'msgstr[') { + if ($ink) { + $ink = false; + $out .= '$a->strings["' . $k . '"] = '; + } + if ($inv) { + $inv = false; + $out .= '"' . $v . '"'; + } + + if (!$arr) { + $arr = true; + $out .= "[\n"; + } + + $match = []; + preg_match("|\[([0-9]*)\] (.*)|", $l, $match); + $out .= "\t" + . preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $match[1]) + . ' => ' + . preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $match[2]) + . ",\n"; + } + + if (substr($l, 0, 6) == 'msgid_') { + $ink = false; + $out .= '$a->strings["' . $k . '"] = '; + } + + if ($ink) { + $k .= trim($l, "\"\r\n"); + $k = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $k); + } + + if (substr($l, 0, 6) == 'msgid ') { + if ($inv) { + $inv = false; + $out .= '"' . $v . '"'; + } + + if ($k != "") { + $out .= ($arr) ? "];\n" : ";\n"; + } + + $arr = false; + $k = str_replace("msgid ", "", $l); + if ($k != '""') { + $k = trim($k, "\"\r\n"); + } else { + $k = ''; + } + + $k = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $k); + $ink = true; + } + + if ($inv && substr($l, 0, 6) != "msgstr") { + $v .= trim($l, "\"\r\n"); + $v = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $v); + } + } + + if ($inv) { + $out .= '"' . $v . '"'; + } + + if ($k != '') { + $out .= ($arr ? "];\n" : ";\n"); + } + + $out = str_replace(self::DQ_ESCAPE, '\"', $out); + if (!file_put_contents($outfile, $out)) { + throw new \RuntimeException('Unable to write to ' . $outfile); + } + + return 0; + } + + private function escapeDollar($match) + { + return str_replace('$', '\$', $match[0]); + } +} diff --git a/src/Console/PostUpdate.php b/src/Console/PostUpdate.php new file mode 100644 index 0000000000..4d7246d90b --- /dev/null +++ b/src/Console/PostUpdate.php @@ -0,0 +1,72 @@ + + * @author Hypolite Petovan + */ +class PostUpdate extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = <<] + +Options + -h|--help|-? Show help information + --reset Reset the post update version +HELP; + return $help; + } + + protected function doExecute() + { + $a = \Friendica\BaseObject::getApp(); + + if ($this->getOption($this->helpOptions)) { + $this->out($this->getHelp()); + return 0; + } + + $reset_version = $this->getOption('reset'); + if (is_bool($reset_version)) { + $this->out($this->getHelp()); + return 0; + } elseif ($reset_version) { + Config::set('system', 'post_update_version', $reset_version); + echo L10n::t('Post update version number has been set to %s.', $reset_version) . "\n"; + return 0; + } + + if ($a->getMode()->isInstall()) { + throw new \RuntimeException('Database isn\'t ready or populated yet'); + } + + echo L10n::t('Check for pending update actions.') . "\n"; + Update::run($a->getBasePath(), true, false, true, false); + echo L10n::t('Done.') . "\n"; + + echo L10n::t('Execute pending post updates.') . "\n"; + + while (!\Friendica\Database\PostUpdate::update()) { + echo '.'; + } + + echo "\n" . L10n::t('All pending post updates are done.') . "\n"; + + return 0; + } +} diff --git a/src/Console/ServerBlock.php b/src/Console/ServerBlock.php new file mode 100644 index 0000000000..7e45f108bb --- /dev/null +++ b/src/Console/ServerBlock.php @@ -0,0 +1,171 @@ + [-h|--help|-?] [-v] + bin/console serverblock remove [-h|--help|-?] [-v] + +Description + With this tool, you can list the current blocked servers + or you can add / remove a blocked server from the list + +Options + -h|--help|-? Show help information + -v Show more debug information. +HELP; + return $help; + } + + protected function doExecute() + { + $a = BaseObject::getApp(); + + if (count($this->args) == 0) { + $this->printBlockedServers($a->getConfig()); + return 0; + } + + switch ($this->getArgument(0)) { + case 'add': + return $this->addBlockedServer($a->getConfig()); + case 'remove': + return $this->removeBlockedServer($a->getConfig()); + default: + throw new CommandArgsException('Unknown command.'); + break; + } + } + + /** + * Prints the whole list of blocked domains including the reason + * + * @param Configuration $config + */ + private function printBlockedServers(Configuration $config) + { + $table = new Console_Table(); + $table->setHeaders(['Domain', 'Reason']); + $blocklist = $config->get('system', 'blocklist'); + foreach ($blocklist as $domain) { + $table->addRow($domain); + } + $this->out($table->getTable()); + } + + /** + * Adds a server to the blocked list + * + * @param Configuration $config + * + * @return int The return code (0 = success, 1 = failed) + */ + private function addBlockedServer(Configuration $config) + { + if (count($this->args) < 2 || count($this->args) > 3) { + throw new CommandArgsException('Add needs a domain and optional a reason.'); + } + + $domain = $this->getArgument(1); + $reason = (count($this->args) === 3) ? $this->getArgument(2) : self::DEFAULT_REASON; + + $update = false; + + $currBlocklist = $config->get('system', 'blocklist'); + $newBlockList = []; + foreach ($currBlocklist as $blocked) { + if ($blocked['domain'] === $domain) { + $update = true; + $newBlockList[] = [ + 'domain' => $domain, + 'reason' => $reason, + ]; + } else { + $newBlockList[] = $blocked; + } + } + + if (!$update) { + $newBlockList[] = [ + 'domain' => $domain, + 'reason' => $reason, + ]; + } + + if ($config->set('system', 'blocklist', $newBlockList)) { + if ($update) { + $this->out(sprintf("The domain '%s' is now updated. (Reason: '%s')", $domain, $reason)); + } else { + $this->out(sprintf("The domain '%s' is now blocked. (Reason: '%s')", $domain, $reason)); + } + return 0; + } else { + $this->out(sprintf("Couldn't save '%s' as blocked server", $domain)); + return 1; + } + } + + /** + * Removes a server from the blocked list + * + * @param Configuration $config + * + * @return int The return code (0 = success, 1 = failed) + */ + private function removeBlockedServer(Configuration $config) + { + if (count($this->args) !== 2) { + throw new CommandArgsException('Remove needs a second parameter.'); + } + + $domain = $this->getArgument(1); + + $found = false; + + $currBlocklist = $config->get('system', 'blocklist'); + $newBlockList = []; + foreach ($currBlocklist as $blocked) { + if ($blocked['domain'] === $domain) { + $found = true; + } else { + $newBlockList[] = $blocked; + } + } + + if (!$found) { + $this->out(sprintf("The domain '%s' is not blocked.", $domain)); + return 1; + } + + if ($config->set('system', 'blocklist', $newBlockList)) { + $this->out(sprintf("The domain '%s' is not more blocked", $domain)); + return 0; + } else { + $this->out(sprintf("Couldn't remove '%s' from blocked servers", $domain)); + return 1; + } + } +} diff --git a/src/Console/Storage.php b/src/Console/Storage.php new file mode 100644 index 0000000000..30b5567823 --- /dev/null +++ b/src/Console/Storage.php @@ -0,0 +1,147 @@ + + Set current storage backend + name storage backend to use. see "list". + + bin/console storage move [table] [-n 5000] + Move stored data to current storage backend. + table one of "photo" or "attach". default to both + -n limit of processed entry batch size +HELP; + return $help; + } + + protected function doExecute() + { + if ($this->getOption('v')) { + $this->out('Executable: ' . $this->executable); + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return -1; + } + + switch ($this->args[0]) { + case 'list': + return $this->doList(); + break; + case 'set': + return $this->doSet(); + break; + case 'move': + return $this->doMove(); + break; + } + + $this->out(sprintf('Invalid action "%s"', $this->args[0])); + return -1; + } + + protected function doList() + { + $rowfmt = ' %-3s | %-20s'; + $current = StorageManager::getBackend(); + $this->out(sprintf($rowfmt, 'Sel', 'Name')); + $this->out('-----------------------'); + $isregisterd = false; + foreach (StorageManager::listBackends() as $name => $class) { + $issel = ' '; + if ($current === $class) { + $issel = '*'; + $isregisterd = true; + }; + $this->out(sprintf($rowfmt, $issel, $name)); + } + + if ($current === '') { + $this->out(); + $this->out('This system is using legacy storage system'); + } + if ($current !== '' && !$isregisterd) { + $this->out(); + $this->out('The current storage class (' . $current . ') is not registered!'); + } + return 0; + } + + protected function doSet() + { + if (count($this->args) !== 2) { + throw new CommandArgsException('Invalid arguments'); + } + + $name = $this->args[1]; + $class = StorageManager::getByName($name); + + if ($class === '') { + $this->out($name . ' is not a registered backend.'); + return -1; + } + + if (!StorageManager::setBackend($class)) { + $this->out($class . ' is not a valid backend storage class.'); + return -1; + } + + return 0; + } + + protected function doMove() + { + $tables = null; + if (count($this->args) < 1 || count($this->args) > 2) { + throw new CommandArgsException('Invalid arguments'); + } + + if (count($this->args) == 2) { + $table = strtolower($this->args[1]); + if (!in_array($table, ['photo', 'attach'])) { + throw new CommandArgsException('Invalid table'); + } + $tables = [$table]; + } + + $current = StorageManager::getBackend(); + $total = 0; + + do { + $moved = StorageManager::move($current, $tables, $this->getOption('n', 5000)); + if ($moved) { + $this->out(date('[Y-m-d H:i:s] ') . sprintf('Moved %d files', $moved)); + } + + $total += $moved; + } while ($moved); + + $this->out(sprintf(date('[Y-m-d H:i:s] ') . 'Moved %d files total', $total)); + } +} diff --git a/src/Console/Typo.php b/src/Console/Typo.php new file mode 100644 index 0000000000..5f5fa0ba68 --- /dev/null +++ b/src/Console/Typo.php @@ -0,0 +1,117 @@ + + */ +class Typo extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = <<getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) > 0) { + throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + } + + $php_path = BaseObject::getApp()->getConfigCache()->get('config', 'php_path', 'php'); + + if ($this->getOption('v')) { + $this->out('Directory: src'); + } + + $Iterator = new \RecursiveDirectoryIterator('src'); + + foreach (new \RecursiveIteratorIterator($Iterator) as $file) { + if (substr($file, -4) === '.php') { + $this->checkFile($php_path, $file); + } + } + + if ($this->getOption('v')) { + $this->out('Directory: mod'); + } + + $files = glob('mod/*.php'); + $this->checkFiles($php_path, $files); + + if ($this->getOption('v')) { + $this->out('Directory: include'); + } + + $files = glob('include/*.php'); + $this->checkFiles($php_path, $files); + + if ($this->getOption('v')) { + $this->out('Directory: addon'); + } + + $dirs = glob('addon/*'); + foreach ($dirs as $dir) { + $addon = basename($dir); + $files = glob($dir . '/' . $addon . '.php'); + $this->checkFiles($php_path, $files); + } + + if ($this->getOption('v')) { + $this->out('String files'); + } + + $files = glob('view/lang/*/strings.php'); + $this->checkFiles($php_path, $files); + + $this->out('No errors.'); + + return 0; + } + + private function checkFiles($php_path, array $files) + { + foreach ($files as $file) { + $this->checkFile($php_path, $file); + } + } + + private function checkFile($php_path, $file) + { + if ($this->getOption('v')) { + $this->out('Checking ' . $file); + } + + $output = []; + $ret = 0; + exec("$php_path -l $file", $output, $ret); + if ($ret !== 0) { + throw new \RuntimeException('Parse error found in ' . $file . ', scan stopped.'); + } + } +} diff --git a/src/Core/Console.php b/src/Core/Console.php index 0cc63a5913..2893c27b23 100644 --- a/src/Core/Console.php +++ b/src/Core/Console.php @@ -2,6 +2,8 @@ namespace Friendica\Core; +use Friendica; + /** * Description of Console * @@ -47,24 +49,24 @@ HELP; } protected $subConsoles = [ - 'cache' => __NAMESPACE__ . '\Console\Cache', - 'config' => __NAMESPACE__ . '\Console\Config', - 'createdoxygen' => __NAMESPACE__ . '\Console\CreateDoxygen', - 'docbloxerrorchecker' => __NAMESPACE__ . '\Console\DocBloxErrorChecker', - 'dbstructure' => __NAMESPACE__ . '\Console\DatabaseStructure', - 'extract' => __NAMESPACE__ . '\Console\Extract', - 'globalcommunityblock' => __NAMESPACE__ . '\Console\GlobalCommunityBlock', - 'globalcommunitysilence' => __NAMESPACE__ . '\Console\GlobalCommunitySilence', - 'archivecontact' => __NAMESPACE__ . '\Console\ArchiveContact', - 'autoinstall' => __NAMESPACE__ . '\Console\AutomaticInstallation', - 'maintenance' => __NAMESPACE__ . '\Console\Maintenance', - 'newpassword' => __NAMESPACE__ . '\Console\NewPassword', - 'php2po' => __NAMESPACE__ . '\Console\PhpToPo', - 'po2php' => __NAMESPACE__ . '\Console\PoToPhp', - 'typo' => __NAMESPACE__ . '\Console\Typo', - 'postupdate' => __NAMESPACE__ . '\Console\PostUpdate', - 'serverblock' => __NAMESPACE__ . '\Console\ServerBlock', - 'storage' => __NAMESPACE__ . '\Console\Storage', + 'cache' => Friendica\Console\Cache::class, + 'config' => Friendica\Console\Config::class, + 'createdoxygen' => Friendica\Console\CreateDoxygen::class, + 'docbloxerrorchecker' => Friendica\Console\DocBloxErrorChecker::class, + 'dbstructure' => Friendica\Console\DatabaseStructure::class, + 'extract' => Friendica\Console\Extract::class, + 'globalcommunityblock' => Friendica\Console\GlobalCommunityBlock::class, + 'globalcommunitysilence' => Friendica\Console\GlobalCommunitySilence::class, + 'archivecontact' => Friendica\Console\ArchiveContact::class, + 'autoinstall' => Friendica\Console\AutomaticInstallation::class, + 'maintenance' => Friendica\Console\Maintenance::class, + 'newpassword' => Friendica\Console\NewPassword::class, + 'php2po' => Friendica\Console\PhpToPo::class, + 'po2php' => Friendica\Console\PoToPhp::class, + 'typo' => Friendica\Console\Typo::class, + 'postupdate' => Friendica\Console\PostUpdate::class, + 'serverblock' => Friendica\Console\ServerBlock::class, + 'storage' => Friendica\Console\Storage::class, ]; protected function doExecute() diff --git a/src/Core/Console/ArchiveContact.php b/src/Core/Console/ArchiveContact.php deleted file mode 100644 index b93c079b96..0000000000 --- a/src/Core/Console/ArchiveContact.php +++ /dev/null @@ -1,75 +0,0 @@ - [-h|--help|-?] [-v] - -Description - Archive a contact when you know that it isn't existing anymore. Normally this does happen automatically after a few days. - -Options - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - $a = \Friendica\BaseObject::getApp(); - - if ($this->getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return 0; - } - - if (count($this->args) > 1) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - if ($a->getMode()->isInstall()) { - throw new RuntimeException('Friendica isn\'t properly installed yet.'); - } - - $nurl = Strings::normaliseLink($this->getArgument(0)); - if (!DBA::exists('contact', ['nurl' => $nurl, 'archive' => false])) { - throw new RuntimeException(L10n::t('Could not find any unarchived contact entry for this URL (%s)', $nurl)); - } - if (DBA::update('contact', ['archive' => true], ['nurl' => $nurl])) { - $this->out(L10n::t('The contact entries have been archived')); - } else { - throw new RuntimeException('The contact archival failed.'); - } - - return 0; - } -} diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php deleted file mode 100644 index e2857d6517..0000000000 --- a/src/Core/Console/AutomaticInstallation.php +++ /dev/null @@ -1,265 +0,0 @@ - prepared config file (e.g. "config/local.config.php" itself) which will override every other config option - except the environment variables) - -s|--savedb Save the DB credentials to the file (if environment variables is used) - -H|--dbhost The host of the mysql/mariadb database (env MYSQL_HOST) - -p|--dbport The port of the mysql/mariadb database (env MYSQL_PORT) - -d|--dbdata The name of the mysql/mariadb database (env MYSQL_DATABASE) - -U|--dbuser The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME) - -P|--dbpass The password of the mysql/mariadb database login (env MYSQL_PASSWORD) - -U|--url The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL) - -B|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) - -b|--basepath The basepath of Friendica (env FRIENDICA_BASE_PATH) - -t|--tz The timezone of Friendica (env FRIENDICA_TZ) - -L|--lang The language of Friendica (env FRIENDICA_LANG) - -Environment variables - MYSQL_HOST The host of the mysql/mariadb database (mandatory if mysql and environment is used) - MYSQL_PORT The port of the mysql/mariadb database - MYSQL_USERNAME|MYSQL_USER The username of the mysql/mariadb database login (MYSQL_USERNAME is for mysql, MYSQL_USER for mariadb) - MYSQL_PASSWORD The password of the mysql/mariadb database login - MYSQL_DATABASE The name of the mysql/mariadb database - FRIENDICA_URL The full base URL of Friendica - f.e. 'https://friendica.local/sub' - FRIENDICA_PHP_PATH The path of the PHP binary - leave empty for auto detection - FRIENDICA_BASE_PATH The basepath of Friendica - leave empty for auto detection - FRIENDICA_ADMIN_MAIL The admin email address of Friendica (this email will be used for admin access) - FRIENDICA_TZ The timezone of Friendica - FRIENDICA_LANG The langauge of Friendica - -Examples - bin/console autoinstall -f 'input.config.php - Installs Friendica with the prepared 'input.config.php' file - - bin/console autoinstall --savedb - Installs Friendica with environment variables and saves them to the 'config/local.config.php' file - - bin/console autoinstall -h localhost -p 3365 -U user -P passwort1234 -d friendica - Installs Friendica with a local mysql database with credentials -HELP; - } - - protected function doExecute() - { - // Initialise the app - $this->out("Initializing setup...\n"); - - $a = BaseObject::getApp(); - - $installer = new Installer(); - - $configCache = $a->getConfigCache(); - $installer->setUpCache($configCache, BasePath::create($a->getBasePath(), $_SERVER)); - - $this->out(" Complete!\n\n"); - - // Check Environment - $this->out("Checking environment...\n"); - - $installer->resetChecks(); - - if (!$this->runBasicChecks($installer, $configCache)) { - $errorMessage = $this->extractErrors($installer->getChecks()); - throw new RuntimeException($errorMessage); - } - - $this->out(" Complete!\n\n"); - - // if a config file is set, - $config_file = $this->getOption(['f', 'file']); - - if (!empty($config_file)) { - if ($config_file != 'config' . DIRECTORY_SEPARATOR . 'local.config.php') { - // Copy config file - $this->out("Copying config file...\n"); - if (!copy($a->getBasePath() . DIRECTORY_SEPARATOR . $config_file, $a->getBasePath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.config.php')) { - throw new RuntimeException("ERROR: Saving config file failed. Please copy '$config_file' to '" . $a->getBasePath() . "'" . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "local.config.php' manually.\n"); - } - } - - //reload the config cache - $loader = new ConfigFileLoader($a->getBasePath(), $a->getMode()); - $loader->setupCache($configCache); - - } else { - // Creating config file - $this->out("Creating config file...\n"); - - $save_db = $this->getOption(['s', 'savedb'], false); - - $db_host = $this->getOption(['H', 'dbhost'], ($save_db) ? (getenv('MYSQL_HOST')) : Installer::DEFAULT_HOST); - $db_port = $this->getOption(['p', 'dbport'], ($save_db) ? getenv('MYSQL_PORT') : null); - $configCache->set('database', 'hostname', $db_host . (!empty($db_port) ? ':' . $db_port : '')); - $configCache->set('database', 'database', - $this->getOption(['d', 'dbdata'], - ($save_db) ? getenv('MYSQL_DATABASE') : '')); - $configCache->set('database', 'username', - $this->getOption(['U', 'dbuser'], - ($save_db) ? getenv('MYSQL_USER') . getenv('MYSQL_USERNAME') : '')); - $configCache->set('database', 'password', - $this->getOption(['P', 'dbpass'], - ($save_db) ? getenv('MYSQL_PASSWORD') : '')); - - $php_path = $this->getOption(['b', 'phppath'], !empty('FRIENDICA_PHP_PATH') ? getenv('FRIENDICA_PHP_PATH') : null); - if (!empty($php_path)) { - $configCache->set('config', 'php_path', $php_path); - } else { - $configCache->set('config', 'php_path', $installer->getPHPPath()); - } - - $configCache->set('config', 'admin_email', - $this->getOption(['A', 'admin'], - !empty(getenv('FRIENDICA_ADMIN_MAIL')) ? getenv('FRIENDICA_ADMIN_MAIL') : '')); - $configCache->set('system', 'default_timezone', - $this->getOption(['T', 'tz'], - !empty(getenv('FRIENDICA_TZ')) ? getenv('FRIENDICA_TZ') : Installer::DEFAULT_TZ)); - $configCache->set('system', 'language', - $this->getOption(['L', 'lang'], - !empty(getenv('FRIENDICA_LANG')) ? getenv('FRIENDICA_LANG') : Installer::DEFAULT_LANG)); - - $basepath = $this->getOption(['b', 'basepath'], !empty(getenv('FRIENDICA_BASE_PATH')) ? getenv('FRIENDICA_BASE_PATH') : null); - if (!empty($basepath)) { - $configCache->set('system', 'basepath', $basepath); - } - - $url = $this->getOption(['U', 'url'], !empty(getenv('FRIENDICA_URL')) ? getenv('FRIENDICA_URL') : null); - - if (empty($url)) { - $this->out('The Friendica URL has to be set during CLI installation.'); - return 1; - } else { - $baseUrl = new BaseURL($a->getConfig(), []); - $baseUrl->saveByURL($url); - } - - $installer->createConfig($configCache); - } - - $this->out(" Complete!\n\n"); - - // Check database connection - $this->out("Checking database...\n"); - - $installer->resetChecks(); - - if (!$installer->checkDB($configCache, $a->getProfiler())) { - $errorMessage = $this->extractErrors($installer->getChecks()); - throw new RuntimeException($errorMessage); - } - - $this->out(" Complete!\n\n"); - - // Install database - $this->out("Inserting data into database...\n"); - - $installer->resetChecks(); - - if (!$installer->installDatabase($a->getBasePath())) { - $errorMessage = $this->extractErrors($installer->getChecks()); - throw new RuntimeException($errorMessage); - } - - $this->out(" Complete!\n\n"); - - // Install theme - $this->out("Installing theme\n"); - if (!empty(Config::get('system', 'theme'))) { - Theme::install(Config::get('system', 'theme')); - $this->out(" Complete\n\n"); - } else { - $this->out(" Theme setting is empty. Please check the file 'config/local.config.php'\n\n"); - } - - $this->out("\nInstallation is finished\n"); - - return 0; - } - - /** - * @param Installer $installer The Installer instance - * @param Config\Cache\IConfigCache $configCache The config cache - * - * @return bool true if checks were successfully, otherwise false - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - */ - private function runBasicChecks(Installer $installer, Config\Cache\IConfigCache $configCache) - { - $checked = true; - - $installer->resetChecks(); - if (!$installer->checkFunctions()) { - $checked = false; - } - if (!$installer->checkImagick()) { - $checked = false; - } - if (!$installer->checkLocalIni()) { - $checked = false; - } - if (!$installer->checkSmarty3()) { - $checked = false; - } - if (!$installer->checkKeys()) { - $checked = false; - } - - $php_path = $configCache->get('config', 'php_path'); - - if (!$installer->checkPHP($php_path, true)) { - $checked = false; - } - - $this->out(" NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.\n"); - - return $checked; - } - - /** - * @param array $results - * @return string - */ - private function extractErrors($results) - { - $errorMessage = ''; - $allChecksRequired = $this->getOption('a') !== null; - - foreach ($results as $result) { - if (($allChecksRequired || $result['required'] === true) && $result['status'] === false) { - $errorMessage .= "--------\n"; - $errorMessage .= $result['title'] . ': ' . $result['help'] . "\n"; - } - } - - return $errorMessage; - } -} diff --git a/src/Core/Console/Cache.php b/src/Core/Console/Cache.php deleted file mode 100644 index 510c05b04a..0000000000 --- a/src/Core/Console/Cache.php +++ /dev/null @@ -1,178 +0,0 @@ - - */ -class Cache extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = << [-h|--help|-?] [-v] - bin/console cache set [-h|--help|-?] [-v] - bin/console cache flush [-h|--help|-?] [-v] - bin/console cache clear [-h|--help|-?] [-v] - -Description - bin/console cache list [] - List all cache keys, optionally filtered by a prefix - - bin/console cache get - Shows the value of the provided cache key - - bin/console cache set [] - Sets the value of the provided cache key, optionally with the provided TTL (time to live) with a default of five minutes. - - bin/console cache flush - Clears expired cache keys - - bin/console cache clear - Clears all cache keys - -Options - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - $a = \Friendica\BaseObject::getApp(); - - if ($this->getOption('v')) { - $this->out('Executable: ' . $this->executable); - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if ($a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - $this->out('Database isn\'t ready or populated yet, database cache won\'t be available'); - } - - Core\Cache::init(); - - if ($this->getOption('v')) { - $this->out('Cache Driver Name: ' . Core\Cache::$driver_name); - $this->out('Cache Driver Class: ' . Core\Cache::$driver_class); - } - - switch ($this->getArgument(0)) { - case 'list': - $this->executeList(); - break; - case 'get': - $this->executeGet(); - break; - case 'set': - $this->executeSet(); - break; - case 'flush': - $this->executeFlush(); - break; - case 'clear': - $this->executeClear(); - break; - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return 0; - } - - return 0; - } - - private function executeList() - { - $prefix = $this->getArgument(1); - $keys = Core\Cache::getAllKeys($prefix); - - if (empty($prefix)) { - $this->out('Listing all cache keys:'); - } else { - $this->out('Listing all cache keys starting with "' . $prefix . '":'); - } - - $count = 0; - foreach ($keys as $key) { - $this->out($key); - $count++; - } - - $this->out($count . ' keys found'); - } - - private function executeGet() - { - if (count($this->args) >= 2) { - $key = $this->getArgument(1); - $value = Core\Cache::get($key); - - $this->out("{$key} => " . var_export($value, true)); - } else { - throw new CommandArgsException('Too few arguments for get'); - } - } - - private function executeSet() - { - if (count($this->args) >= 3) { - $key = $this->getArgument(1); - $value = $this->getArgument(2); - $duration = intval($this->getArgument(3, Core\Cache::FIVE_MINUTES)); - - if (is_array(Core\Cache::get($key))) { - throw new RuntimeException("$key is an array and can't be set using this command."); - } - - $result = Core\Cache::set($key, $value, $duration); - if ($result) { - $this->out("{$key} <= " . Core\Cache::get($key)); - } else { - $this->out("Unable to set {$key}"); - } - } else { - throw new CommandArgsException('Too few arguments for set'); - } - } - - private function executeFlush() - { - $result = Core\Cache::clear(); - if ($result) { - $this->out('Cache successfully flushed'); - } else { - $this->out('Unable to flush the cache'); - } - } - - private function executeClear() - { - $result = Core\Cache::clear(false); - if ($result) { - $this->out('Cache successfully cleared'); - } else { - $this->out('Unable to flush the cache'); - } - } -} diff --git a/src/Core/Console/Config.php b/src/Core/Console/Config.php deleted file mode 100644 index cf5c09fc0a..0000000000 --- a/src/Core/Console/Config.php +++ /dev/null @@ -1,171 +0,0 @@ - - * @author Hypolite Petovan - */ -class Config extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = << [-h|--help|-?] [-v] - bin/console config [-h|--help|-?] [-v] - bin/console config [-h|--help|-?] [-v] - -Description - bin/console config - Lists all config values - - bin/console config - Lists all config values in the provided category - - bin/console config - Shows the value of the provided key in the category - - bin/console config - Sets the value of the provided key in the category - -Notes: - Setting config entries which are manually set in config/local.config.php may result in - conflict between database settings and the manual startup settings. - -Options - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - $a = \Friendica\BaseObject::getApp(); - - if ($this->getOption('v')) { - $this->out('Executable: ' . $this->executable); - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) > 3) { - throw new CommandArgsException('Too many arguments'); - } - - if (!$a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - $this->out('Database isn\'t ready or populated yet, showing file config only'); - } - - if (count($this->args) == 3) { - $cat = $this->getArgument(0); - $key = $this->getArgument(1); - $value = $this->getArgument(2); - - if (is_array(Core\Config::get($cat, $key))) { - throw new RuntimeException("$cat.$key is an array and can't be set using this command."); - } - - $result = Core\Config::set($cat, $key, $value); - if ($result) { - $this->out("{$cat}.{$key} <= " . - Core\Config::get($cat, $key)); - } else { - $this->out("Unable to set {$cat}.{$key}"); - } - } - - if (count($this->args) == 2) { - $cat = $this->getArgument(0); - $key = $this->getArgument(1); - $value = Core\Config::get($this->getArgument(0), $this->getArgument(1)); - - if (is_array($value)) { - foreach ($value as $k => $v) { - $this->out("{$cat}.{$key}[{$k}] => " . (is_array($v) ? implode(', ', $v) : $v)); - } - } else { - $this->out("{$cat}.{$key} => " . $value); - } - } - - if (count($this->args) == 1) { - $cat = $this->getArgument(0); - Core\Config::load($cat); - - if ($a->getConfigCache()->get($cat) !== null) { - $this->out("[{$cat}]"); - $catVal = $a->getConfigCache()->get($cat); - foreach ($catVal as $key => $value) { - if (is_array($value)) { - foreach ($value as $k => $v) { - $this->out("{$key}[{$k}] => " . (is_array($v) ? implode(', ', $v) : $v)); - } - } else { - $this->out("{$key} => " . $value); - } - } - } else { - $this->out('Config section ' . $this->getArgument(0) . ' returned nothing'); - } - } - - if (count($this->args) == 0) { - Core\Config::load(); - - if (Core\Config::get('system', 'config_adapter') == 'jit' && $a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - $this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only'); - } - - $config = $a->getConfigCache()->getAll(); - foreach ($config as $cat => $section) { - if (is_array($section)) { - foreach ($section as $key => $value) { - if (is_array($value)) { - foreach ($value as $k => $v) { - $this->out("{$cat}.{$key}[{$k}] => " . (is_array($v) ? implode(', ', $v) : $v)); - } - } else { - $this->out("{$cat}.{$key} => " . $value); - } - } - } else { - $this->out("config.{$cat} => " . $section); - } - } - } - - return 0; - } -} diff --git a/src/Core/Console/CreateDoxygen.php b/src/Core/Console/CreateDoxygen.php deleted file mode 100644 index 1de2cee040..0000000000 --- a/src/Core/Console/CreateDoxygen.php +++ /dev/null @@ -1,148 +0,0 @@ - - */ -class CreateDoxygen extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = << [-h|--help|-?] [-v] - -Description - Outputs the provided file with added Doxygen headers to functions - -Options - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - if ($this->getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return 0; - } - - if (count($this->args) > 1) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - $file = $this->getArgument(0); - if (!file_exists($file)) { - throw new \RuntimeException('Unable to find specified file.'); - } - - $data = file_get_contents($file); - - $lines = explode("\n", $data); - - $previous = ""; - - foreach ($lines AS $line) { - $line = rtrim(trim($line, "\r")); - - if (strstr(strtolower($line), "function")) { - $detect = strtolower(trim($line)); - $detect = implode(" ", explode(" ", $detect)); - - $found = false; - - if (substr($detect, 0, 9) == "function ") { - $found = true; - } - - if (substr($detect, 0, 19) == "protected function ") { - $found = true; - } - - if (substr($detect, 0, 17) == "private function ") { - $found = true; - } - - if (substr($detect, 0, 23) == "public static function ") { - $found = true; - } - - if (substr($detect, 0, 24) == "private static function ") { - $found = true; - } - - if (substr($detect, 0, 10) == "function (") { - $found = false; - } - - if ($found && ( trim($previous) == "*/")) { - $found = false; - } - - if ($found) { - $this->out($this->addDocumentation($line)); - } - } - $this->out($line); - $previous = $line; - } - - return 0; - } - - /** - * @brief Adds a doxygen header - * - * @param string $line The current line of the document - * - * @return string added doxygen header - */ - private function addDocumentation($line) - { - $trimmed = ltrim($line); - $length = strlen($line) - strlen($trimmed); - $space = substr($line, 0, $length); - - $block = $space . "/**\n" . - $space . " * @brief \n" . - $space . " *\n"; /**/ - - - $left = strpos($line, "("); - $line = substr($line, $left + 1); - - $right = strpos($line, ")"); - $line = trim(substr($line, 0, $right)); - - if ($line != "") { - $parameters = explode(",", $line); - foreach ($parameters AS $parameter) { - $parameter = trim($parameter); - $splitted = explode("=", $parameter); - - $block .= $space . " * @param " . trim($splitted[0], "& ") . "\n"; - } - if (count($parameters) > 0) $block .= $space . " *\n"; - } - - $block .= $space . " * @return \n" . - $space . " */\n"; - - return $block; - } - -} diff --git a/src/Core/Console/DatabaseStructure.php b/src/Core/Console/DatabaseStructure.php deleted file mode 100644 index dededa9b3a..0000000000 --- a/src/Core/Console/DatabaseStructure.php +++ /dev/null @@ -1,94 +0,0 @@ - - */ -class DatabaseStructure extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = << [-h|--help|-?] |-f|--force] [-v] - -Commands - dryrun Show database update schema queries without running them - update Update database schema - dumpsql Dump database schema - toinnodb Convert all tables from MyISAM to InnoDB - -Options - -h|--help|-? Show help information - -v Show more debug information. - -f|--force Force the update command (Even if the database structure matches) - -o|--override Override running or stalling updates -HELP; - return $help; - } - - protected function doExecute() - { - if ($this->getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return 0; - } - - if (count($this->args) > 1) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - if (!DBA::connected()) { - throw new RuntimeException('Unable to connect to database'); - } - - Core\Config::load(); - - $a = get_app(); - - switch ($this->getArgument(0)) { - case "dryrun": - $output = DBStructure::update($a->getBasePath(), true, false); - break; - case "update": - $force = $this->getOption(['f', 'force'], false); - $override = $this->getOption(['o', 'override'], false); - $output = Update::run($a->getBasePath(), $force, $override,true, false); - break; - case "dumpsql": - ob_start(); - DBStructure::printStructure($a->getBasePath()); - $output = ob_get_clean(); - break; - case "toinnodb": - ob_start(); - DBStructure::convertToInnoDB(); - $output = ob_get_clean(); - break; - default: - $output = 'Unknown command: ' . $this->getArgument(0); - } - - $this->out($output); - - return 0; - } -} diff --git a/src/Core/Console/DocBloxErrorChecker.php b/src/Core/Console/DocBloxErrorChecker.php deleted file mode 100644 index 506e48f0fd..0000000000 --- a/src/Core/Console/DocBloxErrorChecker.php +++ /dev/null @@ -1,186 +0,0 @@ - - */ -class DocBloxErrorChecker extends \Asika\SimpleConsole\Console -{ - - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = <<getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) > 0) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - if (!$this->commandExists('docblox')) { - throw new \RuntimeException('DocBlox isn\'t available.'); - } - - $dir = \get_app()->getBasePath(); - - //stack for dirs to search - $dirstack = []; - //list of source files - $filelist = []; - - //loop over all files in $dir - while ($dh = opendir($dir)) { - while ($file = readdir($dh)) { - if (is_dir($dir . "/" . $file)) { - //add to directory stack - if (strpos($file, '.') !== 0) { - array_push($dirstack, $dir . "/" . $file); - $this->out('dir ' . $dir . '/' . $file); - } - } else { - //test if it is a source file and add to filelist - if (substr($file, strlen($file) - 4) == ".php") { - array_push($filelist, $dir . "/" . $file); - $this->out($dir . '/' . $file); - } - } - } - //look at the next dir - $dir = array_pop($dirstack); - } - - //check the entire set - if ($this->runs($filelist)) { - throw new \RuntimeException("I can not detect a problem."); - } - - //check half of the set and discard if that half is okay - $res = $filelist; - $i = count($res); - do { - $this->out($i . '/' . count($filelist) . ' elements remaining.'); - $res = $this->reduce($res, count($res) / 2); - shuffle($res); - $i = count($res); - } while (count($res) < $i); - - //check one file after another - $needed = []; - - while (count($res) != 0) { - $file = array_pop($res); - - if ($this->runs(array_merge($res, $needed))) { - $this->out('needs: ' . $file . ' and file count ' . count($needed)); - array_push($needed, $file); - } - } - - $this->out('Smallest Set is: ' . $this->namesList($needed) . ' with ' . count($needed) . ' files. '); - - return 0; - } - - private function commandExists($command) - { - $prefix = strpos(strtolower(PHP_OS),'win') > -1 ? 'where' : 'which'; - exec("{$prefix} {$command}", $output, $returnVal); - return $returnVal === 0; - } - - /** - * This function generates a comma separated list of file names. - * - * @param array $fileset Set of file names - * - * @return string comma-separated list of the file names - */ - private function namesList($fileset) - { - return implode(',', $fileset); - } - - /** - * This functions runs phpdoc on the provided list of files - * - * @param array $fileset Set of filenames - * - * @return bool true, if that set can be built - */ - private function runs($fileset) - { - $fsParam = $this->namesList($fileset); - $this->exec('docblox -t phpdoc_out -f ' . $fsParam); - if (file_exists("phpdoc_out/index.html")) { - $this->out('Subset ' . $fsParam . ' is okay.'); - $this->exec('rm -r phpdoc_out'); - return true; - } else { - $this->out('Subset ' . $fsParam . ' failed.'); - return false; - } - } - - /** - * This functions cuts down a fileset by removing files until it finally works. - * it was meant to be recursive, but php's maximum stack size is to small. So it just simulates recursion. - * - * In that version, it does not necessarily generate the smallest set, because it may not alter the elements order enough. - * - * @param array $fileset set of filenames - * @param int $ps number of files in subsets - * - * @return array a part of $fileset, that crashes - */ - private function reduce($fileset, $ps) - { - //split array... - $parts = array_chunk($fileset, $ps); - //filter working subsets... - $parts = array_filter($parts, [$this, 'runs']); - //melt remaining parts together - if (is_array($parts)) { - return array_reduce($parts, "array_merge", []); - } - return []; - } - -} diff --git a/src/Core/Console/Extract.php b/src/Core/Console/Extract.php deleted file mode 100644 index e7c751f942..0000000000 --- a/src/Core/Console/Extract.php +++ /dev/null @@ -1,140 +0,0 @@ - - */ -class Extract extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = <<getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) > 0) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - $s = 'globRecursive('src') - ); - - foreach ($files as $file) { - $str = file_get_contents($file); - - $pat = '|L10n::t\(([^\)]*+)[\)]|'; - $patt = '|L10n::tt\(([^\)]*+)[\)]|'; - - $matches = []; - $matchestt = []; - - preg_match_all($pat, $str, $matches); - preg_match_all($patt, $str, $matchestt); - - if (count($matches) || count($matchestt)) { - $s .= '// ' . $file . PHP_EOL; - } - - if (!empty($matches[1])) { - foreach ($matches[1] as $long_match) { - $match_arr = preg_split('/(?<=[\'"])\s*,/', $long_match); - $match = $match_arr[0]; - if (!in_array($match, $arr)) { - if (substr($match, 0, 1) == '$') { - continue; - } - - $arr[] = $match; - - $s .= '$a->strings[' . $match . '] = ' . $match . ';' . "\n"; - } - } - } - if (!empty($matchestt[1])) { - foreach ($matchestt[1] as $match) { - $matchtkns = preg_split("|[ \t\r\n]*,[ \t\r\n]*|", $match); - if (count($matchtkns) == 3 && !in_array($matchtkns[0], $arr)) { - if (substr($matchtkns[1], 0, 1) == '$') { - continue; - } - - $arr[] = $matchtkns[0]; - - $s .= '$a->strings[' . $matchtkns[0] . "] = array(\n"; - $s .= "\t0 => " . $matchtkns[0] . ",\n"; - $s .= "\t1 => " . $matchtkns[1] . ",\n"; - $s .= ");\n"; - } - } - } - } - - $s .= '// Timezones' . PHP_EOL; - - $zones = timezone_identifiers_list(); - foreach ($zones as $zone) { - $s .= '$a->strings[\'' . $zone . '\'] = \'' . $zone . '\';' . "\n"; - } - - $this->out($s); - - return 0; - } - - private function globRecursive($path) { - $dir_iterator = new \RecursiveDirectoryIterator($path); - $iterator = new \RecursiveIteratorIterator($dir_iterator, \RecursiveIteratorIterator::SELF_FIRST); - - $return = []; - foreach ($iterator as $file) { - if ($file->getBasename() != '.' && $file->getBasename() != '..') { - $return[] = $file->getPathname(); - } - } - - return $return; - } -} diff --git a/src/Core/Console/GlobalCommunityBlock.php b/src/Core/Console/GlobalCommunityBlock.php deleted file mode 100644 index d99d99ceea..0000000000 --- a/src/Core/Console/GlobalCommunityBlock.php +++ /dev/null @@ -1,75 +0,0 @@ - - * @author Hypolite Petovan - */ -class GlobalCommunityBlock extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = << [-h|--help|-?] [-v] - -Description - Blocks an account in such a way that no postings or comments this account writes are accepted to this node. - -Options - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - $a = \get_app(); - - if ($this->getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return 0; - } - - if (count($this->args) > 1) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - if ($a->getMode()->isInstall()) { - throw new \RuntimeException('Database isn\'t ready or populated yet'); - } - - $contact_id = Contact::getIdForURL($this->getArgument(0)); - if (!$contact_id) { - throw new \RuntimeException(L10n::t('Could not find any contact entry for this URL (%s)', $this->getArgument(0))); - } - if(Contact::block($contact_id)) { - $this->out(L10n::t('The contact has been blocked from the node')); - } else { - throw new \RuntimeException('The contact block failed.'); - } - - return 0; - } -} diff --git a/src/Core/Console/GlobalCommunitySilence.php b/src/Core/Console/GlobalCommunitySilence.php deleted file mode 100644 index b0281241e3..0000000000 --- a/src/Core/Console/GlobalCommunitySilence.php +++ /dev/null @@ -1,92 +0,0 @@ - - * @author Hypolite Petovan - */ -class GlobalCommunitySilence extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = << [-h|--help|-?] [-v] - -Description - With this tool, you can silence an account on the global community page. - Postings from silenced accounts will not be displayed on the community page. - This silencing does only affect the display on the community page, accounts - following the silenced accounts will still get their postings. - -Options - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - $a = \get_app(); - - if ($this->getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return 0; - } - - if (count($this->args) > 1) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - if ($a->getMode()->isInstall()) { - throw new RuntimeException('Database isn\'t ready or populated yet'); - } - - /** - * 1. make nurl from last parameter - * 2. check DB (contact) if there is a contact with uid=0 and that nurl, get the ID - * 3. set the flag hidden=1 for the contact entry with the found ID - * */ - $net = Probe::uri($this->getArgument(0)); - if (in_array($net['network'], [Protocol::PHANTOM, Protocol::MAIL])) { - throw new RuntimeException('This account seems not to exist.'); - } - - $nurl = Strings::normaliseLink($net['url']); - $contact = DBA::selectFirst("contact", ["id"], ["nurl" => $nurl, "uid" => 0]); - if (DBA::isResult($contact)) { - DBA::update("contact", ["hidden" => true], ["id" => $contact["id"]]); - $this->out('NOTICE: The account should be silenced from the global community page'); - } else { - throw new RuntimeException('NOTICE: Could not find any entry for this URL (' . $nurl . ')'); - } - - return 0; - } -} diff --git a/src/Core/Console/Maintenance.php b/src/Core/Console/Maintenance.php deleted file mode 100644 index 0cb0da9c60..0000000000 --- a/src/Core/Console/Maintenance.php +++ /dev/null @@ -1,95 +0,0 @@ - - */ -class Maintenance extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = << [] [-h|--help|-?] [-v] - -Description - cen be either 0 or 1 to disabled or enable the maintenance mode on this node. - - is a quote-enclosed string with the optional reason for the maintenance mode. - -Examples - bin/console maintenance 1 - Enables the maintenance mode without setting a reason message - - bin/console maintenance 1 "SSL certification update" - Enables the maintenance mode with setting a reason message - - bin/console maintenance 0 - Disables the maintenance mode - -Options - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - $a = \Friendica\BaseObject::getApp(); - - if ($this->getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return 0; - } - - if (count($this->args) > 2) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - if ($a->getMode()->isInstall()) { - throw new \RuntimeException('Database isn\'t ready or populated yet'); - } - - $enabled = intval($this->getArgument(0)); - - Core\Config::set('system', 'maintenance', $enabled); - - $reason = $this->getArgument(1); - - if ($enabled && $this->getArgument(1)) { - Core\Config::set('system', 'maintenance_reason', $this->getArgument(1)); - } else { - Core\Config::set('system', 'maintenance_reason', ''); - } - - if ($enabled) { - $mode_str = "maintenance mode"; - } else { - $mode_str = "normal mode"; - } - - $this->out('System set in ' . $mode_str); - - if ($enabled && $reason != '') { - $this->out('Maintenance reason: ' . $reason); - } - - return 0; - } - -} diff --git a/src/Core/Console/NewPassword.php b/src/Core/Console/NewPassword.php deleted file mode 100644 index 3cd96ad322..0000000000 --- a/src/Core/Console/NewPassword.php +++ /dev/null @@ -1,90 +0,0 @@ - - */ -class NewPassword extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = << [] [-h|--help|-?] [-v] - -Description - Creates a new password for a user without using the "forgot password" functionality. - -Options - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - $a = \get_app(); - - if ($this->getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return 0; - } - - if (count($this->args) > 2) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - if ($a->getMode()->isInstall()) { - throw new RuntimeException('Database isn\'t ready or populated yet'); - } - - $nick = $this->getArgument(0); - - $user = DBA::selectFirst('user', ['uid'], ['nickname' => $nick]); - if (!DBA::isResult($user)) { - throw new RuntimeException(L10n::t('User not found')); - } - - $password = $this->getArgument(1); - if (is_null($password)) { - $this->out(L10n::t('Enter new password: '), false); - $password = \Seld\CliPrompt\CliPrompt::hiddenPrompt(true); - } - - try { - $result = User::updatePassword($user['uid'], $password); - - if (!DBA::isResult($result)) { - throw new \Exception(L10n::t('Password update failed. Please try again.')); - } - - $this->out(L10n::t('Password changed.')); - } catch (\Exception $e) { - throw new RuntimeException($e->getMessage(), $e->getCode(), $e); - } - - return 0; - } -} diff --git a/src/Core/Console/PhpToPo.php b/src/Core/Console/PhpToPo.php deleted file mode 100644 index 93d8274877..0000000000 --- a/src/Core/Console/PhpToPo.php +++ /dev/null @@ -1,237 +0,0 @@ - - */ -class PhpToPo extends \Asika\SimpleConsole\Console -{ - - protected $helpOptions = ['h', 'help', '?']; - - private $normBaseMsgIds = []; - const NORM_REGEXP = "|[\\\]|"; - - protected function getHelp() - { - $help = <<] [--base ] [-h|--help|-?] [-v] - -Description - Read a strings.php file and create the according messages.po in the same directory - -Options - -p Number of plural forms. Default: 2 - --base Path to base messages.po file. Default: view/lang/C/messages.po - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - if ($this->getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return 0; - } - - if (count($this->args) > 1) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - $a = \get_app(); - - $phpfile = realpath($this->getArgument(0)); - - if (!file_exists($phpfile)) { - throw new \RuntimeException('Supplied file path doesn\'t exist.'); - } - - if (!is_writable(dirname($phpfile))) { - throw new \RuntimeException('Supplied directory isn\'t writable.'); - } - - $pofile = dirname($phpfile) . DIRECTORY_SEPARATOR . 'messages.po'; - - // start ! - include_once($phpfile); - - $out = ''; - $out .= "# FRIENDICA Distributed Social Network\n"; - $out .= "# Copyright (C) 2010, 2011, 2012, 2013 the Friendica Project\n"; - $out .= "# This file is distributed under the same license as the Friendica package.\n"; - $out .= "# \n"; - $out .= 'msgid ""' . "\n"; - $out .= 'msgstr ""' . "\n"; - $out .= '"Project-Id-Version: friendica\n"' . "\n"; - $out .= '"Report-Msgid-Bugs-To: \n"' . "\n"; - $out .= '"POT-Creation-Date: ' . date("Y-m-d H:i:sO") . '\n"' . "\n"; - $out .= '"MIME-Version: 1.0\n"' . "\n"; - $out .= '"Content-Type: text/plain; charset=UTF-8\n"' . "\n"; - $out .= '"Content-Transfer-Encoding: 8bit\n"' . "\n"; - - // search for plural info - $lang = ""; - $lang_logic = ""; - $lang_pnum = $this->getOption('p', 2); - - $infile = file($phpfile); - foreach ($infile as $l) { - $l = trim($l); - if ($this->startsWith($l, 'function string_plural_select_')) { - $lang = str_replace('function string_plural_select_', '', str_replace('($n){', '', $l)); - } - if ($this->startsWith($l, 'return')) { - $lang_logic = str_replace('$', '', trim(str_replace('return ', '', $l), ';')); - break; - } - } - - $this->out('Language: ' . $lang); - $this->out('Plural forms: ' . $lang_pnum); - $this->out('Plural forms: ' . $lang_logic); - - $out .= sprintf('"Language: %s\n"', $lang) . "\n"; - $out .= sprintf('"Plural-Forms: nplurals=%s; plural=%s;\n"', $lang_pnum, $lang_logic) . "\n"; - $out .= "\n"; - - $base_path = $this->getOption('base', 'view/lang/C/messages.po'); - - // load base messages.po and extract msgids - $base_msgids = []; - $base_f = file($base_path); - if (!$base_f) { - throw new \RuntimeException('The base ' . $base_path . ' file is missing or unavailable to read.'); - } - - $this->out('Loading base file ' . $base_path . '...'); - - $_f = 0; - $_mid = ""; - $_mids = []; - foreach ($base_f as $l) { - $l = trim($l); - - if ($this->startsWith($l, 'msgstr')) { - if ($_mid != '""') { - $base_msgids[$_mid] = $_mids; - $this->normBaseMsgIds[preg_replace(self::NORM_REGEXP, "", $_mid)] = $_mid; - } - - $_f = 0; - $_mid = ""; - $_mids = []; - } - - if ($this->startsWith($l, '"') && $_f == 2) { - $_mids[count($_mids) - 1] .= "\n" . $l; - } - if ($this->startsWith($l, 'msgid_plural ')) { - $_f = 2; - $_mids[] = str_replace('msgid_plural ', '', $l); - } - - if ($this->startsWith($l, '"') && $_f == 1) { - $_mid .= "\n" . $l; - $_mids[count($_mids) - 1] .= "\n" . $l; - } - if ($this->startsWith($l, 'msgid ')) { - $_f = 1; - $_mid = str_replace('msgid ', '', $l); - $_mids = [$_mid]; - } - } - - $this->out('Creating ' . $pofile . '...'); - - // create msgid and msgstr - $warnings = ""; - foreach ($a->strings as $key => $str) { - $msgid = $this->massageString($key); - - if (preg_match("|%[sd0-9](\$[sn])*|", $msgid)) { - $out .= "#, php-format\n"; - } - $msgid = $this->findOriginalMsgId($msgid); - $out .= 'msgid ' . $msgid . "\n"; - - if (is_array($str)) { - if (array_key_exists($msgid, $base_msgids) && isset($base_msgids[$msgid][1])) { - $out .= 'msgid_plural ' . $base_msgids[$msgid][1] . "\n"; - } else { - $out .= 'msgid_plural ' . $msgid . "\n"; - $warnings .= "[W] No source plural form for msgid:\n" . str_replace("\n", "\n\t", $msgid) . "\n\n"; - } - foreach ($str as $n => $msgstr) { - $out .= 'msgstr[' . $n . '] ' . $this->massageString($msgstr) . "\n"; - } - } else { - $out .= 'msgstr ' . $this->massageString($str) . "\n"; - } - - $out .= "\n"; - } - - if (!file_put_contents($pofile, $out)) { - throw new \RuntimeException('Unable to write to ' . $pofile); - } - - if ($warnings != '') { - $this->out($warnings); - } - - return 0; - } - - private function startsWith($haystack, $needle) - { - // search backwards starting from haystack length characters from the end - return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE; - } - - /** - * Get a string and retun a message.po ready text - * - replace " with \" - * - replace tab char with \t - * - manage multiline strings - * - * @param string $str - * @return string - */ - private function massageString($str) - { - $str = str_replace('\\', '\\\\', $str); - $str = str_replace('"', '\"', $str); - $str = str_replace("\t", '\t', $str); - $str = str_replace("\n", '\n"' . "\n" . '"', $str); - if (strpos($str, "\n") !== false && $str[0] !== '"') { - $str = '"' . "\n" . $str; - } - - $str = preg_replace("|\n([^\"])|", "\n\"$1", $str); - return sprintf('"%s"', $str); - } - - private function findOriginalMsgId($str) - { - $norm_str = preg_replace(self::NORM_REGEXP, "", $str); - if (array_key_exists($norm_str, $this->normBaseMsgIds)) { - return $this->normBaseMsgIds[$norm_str]; - } - - return $str; - } - -} diff --git a/src/Core/Console/PoToPhp.php b/src/Core/Console/PoToPhp.php deleted file mode 100644 index d539eae5b6..0000000000 --- a/src/Core/Console/PoToPhp.php +++ /dev/null @@ -1,198 +0,0 @@ - - */ -class PoToPhp extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - const DQ_ESCAPE = "__DQ__"; - - protected function getHelp() - { - $help = << [-h|--help|-?] [-v] - -Description - Read a messages.po file and create the according strings.php in the same directory - -Options - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - if ($this->getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return 0; - } - - if (count($this->args) > 1) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - $pofile = realpath($this->getArgument(0)); - - if (!file_exists($pofile)) { - throw new \RuntimeException('Supplied file path doesn\'t exist.'); - } - - if (!is_writable(dirname($pofile))) { - throw new \RuntimeException('Supplied directory isn\'t writable.'); - } - - $outfile = dirname($pofile) . DIRECTORY_SEPARATOR . 'strings.php'; - - if (basename(dirname($pofile)) == 'C') { - $lang = 'en'; - } else { - $lang = str_replace('-', '_', basename(dirname($pofile))); - } - - $this->out('Out to ' . $outfile); - - $out = "strings["' . $k . '"] = '; - } - - if ($inv) { - $out .= '"' . $v . '"'; - } - - $v = substr($l, 8, $len - 10); - $v = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $v); - - $inv = true; - } - - if ($k != "" && substr($l, 0, 7) == 'msgstr[') { - if ($ink) { - $ink = false; - $out .= '$a->strings["' . $k . '"] = '; - } - if ($inv) { - $inv = false; - $out .= '"' . $v . '"'; - } - - if (!$arr) { - $arr = true; - $out .= "[\n"; - } - - $match = []; - preg_match("|\[([0-9]*)\] (.*)|", $l, $match); - $out .= "\t" - . preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $match[1]) - . ' => ' - . preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $match[2]) - . ",\n"; - } - - if (substr($l, 0, 6) == 'msgid_') { - $ink = false; - $out .= '$a->strings["' . $k . '"] = '; - } - - if ($ink) { - $k .= trim($l, "\"\r\n"); - $k = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $k); - } - - if (substr($l, 0, 6) == 'msgid ') { - if ($inv) { - $inv = false; - $out .= '"' . $v . '"'; - } - - if ($k != "") { - $out .= ($arr) ? "];\n" : ";\n"; - } - - $arr = false; - $k = str_replace("msgid ", "", $l); - if ($k != '""') { - $k = trim($k, "\"\r\n"); - } else { - $k = ''; - } - - $k = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $k); - $ink = true; - } - - if ($inv && substr($l, 0, 6) != "msgstr") { - $v .= trim($l, "\"\r\n"); - $v = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $v); - } - } - - if ($inv) { - $out .= '"' . $v . '"'; - } - - if ($k != '') { - $out .= ($arr ? "];\n" : ";\n"); - } - - $out = str_replace(self::DQ_ESCAPE, '\"', $out); - if (!file_put_contents($outfile, $out)) { - throw new \RuntimeException('Unable to write to ' . $outfile); - } - - return 0; - } - - private function escapeDollar($match) - { - return str_replace('$', '\$', $match[0]); - } -} diff --git a/src/Core/Console/PostUpdate.php b/src/Core/Console/PostUpdate.php deleted file mode 100644 index a903cd7dd4..0000000000 --- a/src/Core/Console/PostUpdate.php +++ /dev/null @@ -1,72 +0,0 @@ - - * @author Hypolite Petovan - */ -class PostUpdate extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = <<] - -Options - -h|--help|-? Show help information - --reset Reset the post update version -HELP; - return $help; - } - - protected function doExecute() - { - $a = \Friendica\BaseObject::getApp(); - - if ($this->getOption($this->helpOptions)) { - $this->out($this->getHelp()); - return 0; - } - - $reset_version = $this->getOption('reset'); - if (is_bool($reset_version)) { - $this->out($this->getHelp()); - return 0; - } elseif ($reset_version) { - Config::set('system', 'post_update_version', $reset_version); - echo L10n::t('Post update version number has been set to %s.', $reset_version) . "\n"; - return 0; - } - - if ($a->getMode()->isInstall()) { - throw new \RuntimeException('Database isn\'t ready or populated yet'); - } - - echo L10n::t('Check for pending update actions.') . "\n"; - Update::run($a->getBasePath(), true, false, true, false); - echo L10n::t('Done.') . "\n"; - - echo L10n::t('Execute pending post updates.') . "\n"; - - while (!\Friendica\Database\PostUpdate::update()) { - echo '.'; - } - - echo "\n" . L10n::t('All pending post updates are done.') . "\n"; - - return 0; - } -} diff --git a/src/Core/Console/ServerBlock.php b/src/Core/Console/ServerBlock.php deleted file mode 100644 index 94c97e1ddd..0000000000 --- a/src/Core/Console/ServerBlock.php +++ /dev/null @@ -1,171 +0,0 @@ - [-h|--help|-?] [-v] - bin/console serverblock remove [-h|--help|-?] [-v] - -Description - With this tool, you can list the current blocked servers - or you can add / remove a blocked server from the list - -Options - -h|--help|-? Show help information - -v Show more debug information. -HELP; - return $help; - } - - protected function doExecute() - { - $a = BaseObject::getApp(); - - if (count($this->args) == 0) { - $this->printBlockedServers($a->getConfig()); - return 0; - } - - switch ($this->getArgument(0)) { - case 'add': - return $this->addBlockedServer($a->getConfig()); - case 'remove': - return $this->removeBlockedServer($a->getConfig()); - default: - throw new CommandArgsException('Unknown command.'); - break; - } - } - - /** - * Prints the whole list of blocked domains including the reason - * - * @param Configuration $config - */ - private function printBlockedServers(Configuration $config) - { - $table = new Console_Table(); - $table->setHeaders(['Domain', 'Reason']); - $blocklist = $config->get('system', 'blocklist'); - foreach ($blocklist as $domain) { - $table->addRow($domain); - } - $this->out($table->getTable()); - } - - /** - * Adds a server to the blocked list - * - * @param Configuration $config - * - * @return int The return code (0 = success, 1 = failed) - */ - private function addBlockedServer(Configuration $config) - { - if (count($this->args) < 2 || count($this->args) > 3) { - throw new CommandArgsException('Add needs a domain and optional a reason.'); - } - - $domain = $this->getArgument(1); - $reason = (count($this->args) === 3) ? $this->getArgument(2) : self::DEFAULT_REASON; - - $update = false; - - $currBlocklist = $config->get('system', 'blocklist'); - $newBlockList = []; - foreach ($currBlocklist as $blocked) { - if ($blocked['domain'] === $domain) { - $update = true; - $newBlockList[] = [ - 'domain' => $domain, - 'reason' => $reason, - ]; - } else { - $newBlockList[] = $blocked; - } - } - - if (!$update) { - $newBlockList[] = [ - 'domain' => $domain, - 'reason' => $reason, - ]; - } - - if ($config->set('system', 'blocklist', $newBlockList)) { - if ($update) { - $this->out(sprintf("The domain '%s' is now updated. (Reason: '%s')", $domain, $reason)); - } else { - $this->out(sprintf("The domain '%s' is now blocked. (Reason: '%s')", $domain, $reason)); - } - return 0; - } else { - $this->out(sprintf("Couldn't save '%s' as blocked server", $domain)); - return 1; - } - } - - /** - * Removes a server from the blocked list - * - * @param Configuration $config - * - * @return int The return code (0 = success, 1 = failed) - */ - private function removeBlockedServer(Configuration $config) - { - if (count($this->args) !== 2) { - throw new CommandArgsException('Remove needs a second parameter.'); - } - - $domain = $this->getArgument(1); - - $found = false; - - $currBlocklist = $config->get('system', 'blocklist'); - $newBlockList = []; - foreach ($currBlocklist as $blocked) { - if ($blocked['domain'] === $domain) { - $found = true; - } else { - $newBlockList[] = $blocked; - } - } - - if (!$found) { - $this->out(sprintf("The domain '%s' is not blocked.", $domain)); - return 1; - } - - if ($config->set('system', 'blocklist', $newBlockList)) { - $this->out(sprintf("The domain '%s' is not more blocked", $domain)); - return 0; - } else { - $this->out(sprintf("Couldn't remove '%s' from blocked servers", $domain)); - return 1; - } - } -} diff --git a/src/Core/Console/Storage.php b/src/Core/Console/Storage.php deleted file mode 100644 index 805ef0aea9..0000000000 --- a/src/Core/Console/Storage.php +++ /dev/null @@ -1,147 +0,0 @@ - - Set current storage backend - name storage backend to use. see "list". - - bin/console storage move [table] [-n 5000] - Move stored data to current storage backend. - table one of "photo" or "attach". default to both - -n limit of processed entry batch size -HELP; - return $help; - } - - protected function doExecute() - { - if ($this->getOption('v')) { - $this->out('Executable: ' . $this->executable); - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) == 0) { - $this->out($this->getHelp()); - return -1; - } - - switch ($this->args[0]) { - case 'list': - return $this->doList(); - break; - case 'set': - return $this->doSet(); - break; - case 'move': - return $this->doMove(); - break; - } - - $this->out(sprintf('Invalid action "%s"', $this->args[0])); - return -1; - } - - protected function doList() - { - $rowfmt = ' %-3s | %-20s'; - $current = StorageManager::getBackend(); - $this->out(sprintf($rowfmt, 'Sel', 'Name')); - $this->out('-----------------------'); - $isregisterd = false; - foreach (StorageManager::listBackends() as $name => $class) { - $issel = ' '; - if ($current === $class) { - $issel = '*'; - $isregisterd = true; - }; - $this->out(sprintf($rowfmt, $issel, $name)); - } - - if ($current === '') { - $this->out(); - $this->out('This system is using legacy storage system'); - } - if ($current !== '' && !$isregisterd) { - $this->out(); - $this->out('The current storage class (' . $current . ') is not registered!'); - } - return 0; - } - - protected function doSet() - { - if (count($this->args) !== 2) { - throw new CommandArgsException('Invalid arguments'); - } - - $name = $this->args[1]; - $class = StorageManager::getByName($name); - - if ($class === '') { - $this->out($name . ' is not a registered backend.'); - return -1; - } - - if (!StorageManager::setBackend($class)) { - $this->out($class . ' is not a valid backend storage class.'); - return -1; - } - - return 0; - } - - protected function doMove() - { - $tables = null; - if (count($this->args) < 1 || count($this->args) > 2) { - throw new CommandArgsException('Invalid arguments'); - } - - if (count($this->args) == 2) { - $table = strtolower($this->args[1]); - if (!in_array($table, ['photo', 'attach'])) { - throw new CommandArgsException('Invalid table'); - } - $tables = [$table]; - } - - $current = StorageManager::getBackend(); - $total = 0; - - do { - $moved = StorageManager::move($current, $tables, $this->getOption('n', 5000)); - if ($moved) { - $this->out(date('[Y-m-d H:i:s] ') . sprintf('Moved %d files', $moved)); - } - - $total += $moved; - } while ($moved); - - $this->out(sprintf(date('[Y-m-d H:i:s] ') . 'Moved %d files total', $total)); - } -} diff --git a/src/Core/Console/Typo.php b/src/Core/Console/Typo.php deleted file mode 100644 index 8d07051e83..0000000000 --- a/src/Core/Console/Typo.php +++ /dev/null @@ -1,117 +0,0 @@ - - */ -class Typo extends \Asika\SimpleConsole\Console -{ - protected $helpOptions = ['h', 'help', '?']; - - protected function getHelp() - { - $help = <<getOption('v')) { - $this->out('Class: ' . __CLASS__); - $this->out('Arguments: ' . var_export($this->args, true)); - $this->out('Options: ' . var_export($this->options, true)); - } - - if (count($this->args) > 0) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); - } - - $php_path = BaseObject::getApp()->getConfigCache()->get('config', 'php_path', 'php'); - - if ($this->getOption('v')) { - $this->out('Directory: src'); - } - - $Iterator = new \RecursiveDirectoryIterator('src'); - - foreach (new \RecursiveIteratorIterator($Iterator) as $file) { - if (substr($file, -4) === '.php') { - $this->checkFile($php_path, $file); - } - } - - if ($this->getOption('v')) { - $this->out('Directory: mod'); - } - - $files = glob('mod/*.php'); - $this->checkFiles($php_path, $files); - - if ($this->getOption('v')) { - $this->out('Directory: include'); - } - - $files = glob('include/*.php'); - $this->checkFiles($php_path, $files); - - if ($this->getOption('v')) { - $this->out('Directory: addon'); - } - - $dirs = glob('addon/*'); - foreach ($dirs as $dir) { - $addon = basename($dir); - $files = glob($dir . '/' . $addon . '.php'); - $this->checkFiles($php_path, $files); - } - - if ($this->getOption('v')) { - $this->out('String files'); - } - - $files = glob('view/lang/*/strings.php'); - $this->checkFiles($php_path, $files); - - $this->out('No errors.'); - - return 0; - } - - private function checkFiles($php_path, array $files) - { - foreach ($files as $file) { - $this->checkFile($php_path, $file); - } - } - - private function checkFile($php_path, $file) - { - if ($this->getOption('v')) { - $this->out('Checking ' . $file); - } - - $output = []; - $ret = 0; - exec("$php_path -l $file", $output, $ret); - if ($ret !== 0) { - throw new \RuntimeException('Parse error found in ' . $file . ', scan stopped.'); - } - } -} diff --git a/tests/src/Console/AutomaticInstallationConsoleTest.php b/tests/src/Console/AutomaticInstallationConsoleTest.php new file mode 100644 index 0000000000..5ea349f8b1 --- /dev/null +++ b/tests/src/Console/AutomaticInstallationConsoleTest.php @@ -0,0 +1,646 @@ +root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')) { + $this->root->getChild('config') + ->removeChild('local.config.php'); + } + + $this->mockL10nT(); + + $this->configCache = new ConfigCache(); + $this->configCache->set('system', 'basepath', $this->root->url()); + $this->configCache->set('config', 'php_path', trim(shell_exec('which php'))); + $this->configCache->set('system', 'theme', 'smarty3'); + + $this->mockApp($this->root, true); + + $this->configMock->shouldReceive('set')->andReturnUsing(function ($cat, $key, $value) { + if ($key !== 'basepath') { + return $this->configCache->set($cat, $key, $value); + } else { + return true; + } + }); + + $this->configMock->shouldReceive('has')->andReturn(true); + $this->configMock->shouldReceive('get')->andReturnUsing(function ($cat, $key) { + return $this->configCache->get($cat, $key); + }); + $this->configMock->shouldReceive('load')->andReturnUsing(function ($config, $overwrite = false) { + return $this->configCache->load($config, $overwrite); + }); + + $this->mode->shouldReceive('isInstall')->andReturn(true); + Logger::init(new VoidLogger()); + } + + /** + * Returns the dataset for each automatic installation test + * + * @return array the dataset + */ + public function dataInstaller() + { + return [ + 'empty' => [ + 'data' => [ + 'database' => [ + 'hostname' => '', + 'username' => '', + 'password' => '', + 'database' => '', + 'port' => '', + ], + 'config' => [ + 'php_path' => '', + 'hostname' => 'friendica.local', + 'admin_email' => '', + ], + 'system' => [ + 'basepath' => '', + 'urlpath' => '', + 'url' => 'http://friendica.local', + 'ssl_policy' => 0, + 'default_timezone' => '', + 'language' => '', + ], + ], + ], + 'normal' => [ + 'data' => [ + 'database' => [ + 'hostname' => 'testhost', + 'port' => 3306, + 'username' => 'friendica', + 'password' => 'a password', + 'database' => 'database', + ], + 'config' => [ + 'php_path' => '', + 'hostname' => 'friendica.local', + 'admin_email' => 'admin@philipp.info', + ], + 'system' => [ + 'urlpath' => 'test/it', + 'url' => 'http://friendica.local/test/it', + 'basepath' => '', + 'ssl_policy' => '2', + 'default_timezone' => 'en', + 'language' => 'Europe/Berlin', + ], + ], + ], + 'special' => [ + 'data' => [ + 'database' => [ + 'hostname' => 'testhost.new.domain', + 'port' => 3341, + 'username' => 'fr"§%ica', + 'password' => '$%\"gse', + 'database' => 'db', + ], + 'config' => [ + 'php_path' => '', + 'hostname' => 'friendica.local', + 'admin_email' => 'admin@philipp.info', + ], + 'system' => [ + 'urlpath' => 'test/it', + 'url' => 'https://friendica.local/test/it', + 'basepath' => '', + 'ssl_policy' => '1', + 'default_timezone' => 'en', + 'language' => 'Europe/Berlin', + ], + ], + ], + ]; + } + + private function assertFinished($txt, $withconfig = false, $copyfile = false) + { + $cfg = ''; + + if ($withconfig) { + $cfg = <<assertEquals($finished, $txt); + } + + private function assertStuckDB($txt) + { + $finished = <<assertEquals($finished, $txt); + } + + private function assertStuckURL($txt) + { + $finished = <<assertEquals($finished, $txt); + } + + /** + * Asserts one config entry + * + * @param string $cat The category to test + * @param string $key The key to test + * @param null|array $assertion The asserted value (null = empty, or array/string) + * @param string $default_value The default value + */ + public function assertConfigEntry($cat, $key, $assertion = null, $default_value = null) + { + if (!empty($assertion[$cat][$key])) { + $this->assertEquals($assertion[$cat][$key], $this->configCache->get($cat, $key)); + } elseif (!empty($assertion) && !is_array($assertion)) { + $this->assertEquals($assertion, $this->configCache->get($cat, $key)); + } elseif (!empty($default_value)) { + $this->assertEquals($default_value, $this->configCache->get($cat, $key)); + } else { + $this->assertEmpty($this->configCache->get($cat, $key), $this->configCache->get($cat, $key)); + } + } + + /** + * Asserts all config entries + * + * @param null|array $assertion The optional assertion array + * @param boolean $saveDb True, if the db credentials should get saved to the file + * @param boolean $default True, if we use the default values + * @param boolean $defaultDb True, if we use the default value for the DB + * @param boolean $realBasepath True, if we use the real basepath of the installation, not the mocked one + */ + public function assertConfig($assertion = null, $saveDb = false, $default = true, $defaultDb = true, $realBasepath = false) + { + if (!empty($assertion['database']['hostname'])) { + $assertion['database']['hostname'] .= (!empty($assertion['database']['port']) ? ':' . $assertion['database']['port'] : ''); + } + + $this->assertConfigEntry('database', 'hostname', ($saveDb) ? $assertion : null, (!$saveDb || $defaultDb) ? Installer::DEFAULT_HOST : null); + $this->assertConfigEntry('database', 'username', ($saveDb) ? $assertion : null); + $this->assertConfigEntry('database', 'password', ($saveDb) ? $assertion : null); + $this->assertConfigEntry('database', 'database', ($saveDb) ? $assertion : null); + + $this->assertConfigEntry('config', 'admin_email', $assertion); + $this->assertConfigEntry('config', 'php_path', trim(shell_exec('which php'))); + $this->assertConfigEntry('config', 'hostname', $assertion); + + $this->assertConfigEntry('system', 'default_timezone', $assertion, ($default) ? Installer::DEFAULT_TZ : null); + $this->assertConfigEntry('system', 'language', $assertion, ($default) ? Installer::DEFAULT_LANG : null); + $this->assertConfigEntry('system', 'url', $assertion); + $this->assertConfigEntry('system', 'urlpath', $assertion); + $this->assertConfigEntry('system', 'ssl_policy', $assertion, ($default) ? BaseURL::DEFAULT_SSL_SCHEME : null); + $this->assertConfigEntry('system', 'basepath', ($realBasepath) ? $this->root->url() : $assertion); + } + + /** + * Test the automatic installation without any parameter/setting + * Should stuck because of missing hostname + */ + public function testEmpty() + { + $console = new AutomaticInstallation($this->consoleArgv); + + $txt = $this->dumpExecute($console); + + $this->assertStuckURL($txt); + } + + /** + * Test the automatic installation without any parameter/setting + * except URL + */ + public function testEmptyWithURL() + { + $this->mockConnect(true, 1); + $this->mockConnected(true, 1); + $this->mockExistsTable('user', false, 1); + $this->mockUpdate([$this->root->url(), false, true, true], null, 1); + + $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); + $this->mockReplaceMacros('testTemplate', \Mockery::any(), false, '', 1); + + $console = new AutomaticInstallation($this->consoleArgv); + $console->setOption('url', 'http://friendica.local'); + + $txt = $this->dumpExecute($console); + + $this->assertFinished($txt, true, false); + $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')); + + $this->assertConfig(['config' => ['hostname' => 'friendica.local'], 'system' => ['url' => 'http://friendica.local', 'ssl_policy' => 0, 'urlPath' => '']], false, true, true, true); + } + + /** + * Test the automatic installation with a prepared config file + * @dataProvider dataInstaller + */ + public function testWithConfig(array $data) + { + $this->mockConnect(true, 1); + $this->mockConnected(true, 1); + $this->mockExistsTable('user', false, 1); + $this->mockUpdate([$this->root->url(), false, true, true], null, 1); + + $conf = function ($cat, $key) use ($data) { + if ($cat == 'database' && $key == 'hostname' && !empty($data['database']['port'])) { + return $data[$cat][$key] . ':' . $data['database']['port']; + } + return $data[$cat][$key]; + }; + + $config = << [ + 'hostname' => '{$conf('database', 'hostname')}', + 'username' => '{$conf('database', 'username')}', + 'password' => '{$conf('database', 'password')}', + 'database' => '{$conf('database', 'database')}', + 'charset' => 'utf8mb4', + ], + + // **************************************************************** + // The configuration below will be overruled by the admin panel. + // Changes made below will only have an effect if the database does + // not contain any configuration for the friendica system. + // **************************************************************** + + 'config' => [ + 'admin_email' => '{$conf('config', 'admin_email')}', + 'hostname' => '{$conf('config', 'hostname')}', + 'sitename' => 'Friendica Social Network', + 'register_policy' => \Friendica\Module\Register::OPEN, + 'register_text' => '', + ], + 'system' => [ + 'basepath' => '{$conf('system', 'basepath')}', + 'urlpath' => '{$conf('system', 'urlpath')}', + 'url' => '{$conf('system', 'url')}', + 'ssl_policy' => '{$conf('system', 'ssl_policy')}', + 'default_timezone' => '{$conf('system', 'default_timezone')}', + 'language' => '{$conf('system', 'language')}', + ], +]; +CONF; + + vfsStream::newFile('prepared.config.php') + ->at($this->root) + ->setContent($config); + + $console = new AutomaticInstallation($this->consoleArgv); + $console->setOption('f', 'prepared.config.php'); + + $txt = $this->dumpExecute($console); + + $this->assertFinished($txt, false, true); + + $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')); + $this->assertEquals($config, file_get_contents($this->root->getChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')->url())); + + $this->assertConfig($data, true, false, false); + } + + /** + * Test the automatic installation with environment variables + * Includes saving the DB credentials to the file + * @dataProvider dataInstaller + */ + public function testWithEnvironmentAndSave(array $data) + { + $this->mockConnect(true, 1); + $this->mockConnected(true, 1); + $this->mockExistsTable('user', false, 1); + $this->mockUpdate([$this->root->url(), false, true, true], null, 1); + + $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); + $this->mockReplaceMacros('testTemplate', \Mockery::any(), false, '', 1); + + $this->assertTrue(putenv('MYSQL_HOST=' . $data['database']['hostname'])); + $this->assertTrue(putenv('MYSQL_PORT=' . $data['database']['port'])); + $this->assertTrue(putenv('MYSQL_DATABASE=' . $data['database']['database'])); + $this->assertTrue(putenv('MYSQL_USERNAME=' . $data['database']['username'])); + $this->assertTrue(putenv('MYSQL_PASSWORD=' . $data['database']['password'])); + + $this->assertTrue(putenv('FRIENDICA_HOSTNAME=' . $data['config']['hostname'])); + $this->assertTrue(putenv('FRIENDICA_BASE_PATH=' . $data['system']['basepath'])); + $this->assertTrue(putenv('FRIENDICA_URL=' . $data['system']['url'])); + $this->assertTrue(putenv('FRIENDICA_PHP_PATH=' . $data['config']['php_path'])); + $this->assertTrue(putenv('FRIENDICA_ADMIN_MAIL=' . $data['config']['admin_email'])); + $this->assertTrue(putenv('FRIENDICA_TZ=' . $data['system']['default_timezone'])); + $this->assertTrue(putenv('FRIENDICA_LANG=' . $data['system']['language'])); + + $console = new AutomaticInstallation($this->consoleArgv); + $console->setOption('savedb', true); + + $txt = $this->dumpExecute($console); + + $this->assertFinished($txt, true); + $this->assertConfig($data, true, true, false, true); + } + + /** + * Test the automatic installation with environment variables + * Don't save the db credentials to the file + * @dataProvider dataInstaller + */ + public function testWithEnvironmentWithoutSave(array $data) + { + $this->mockConnect(true, 1); + $this->mockConnected(true, 1); + $this->mockExistsTable('user', false, 1); + $this->mockUpdate([$this->root->url(), false, true, true], null, 1); + + $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); + $this->mockReplaceMacros('testTemplate', \Mockery::any(), false, '', 1); + + $this->assertTrue(putenv('MYSQL_HOST=' . $data['database']['hostname'])); + $this->assertTrue(putenv('MYSQL_PORT=' . $data['database']['port'])); + $this->assertTrue(putenv('MYSQL_DATABASE=' . $data['database']['database'])); + $this->assertTrue(putenv('MYSQL_USERNAME=' . $data['database']['username'])); + $this->assertTrue(putenv('MYSQL_PASSWORD=' . $data['database']['password'])); + + $this->assertTrue(putenv('FRIENDICA_HOSTNAME=' . $data['config']['hostname'])); + $this->assertTrue(putenv('FRIENDICA_BASE_PATH=' . $data['system']['basepath'])); + $this->assertTrue(putenv('FRIENDICA_URL=' . $data['system']['url'])); + $this->assertTrue(putenv('FRIENDICA_PHP_PATH=' . $data['config']['php_path'])); + $this->assertTrue(putenv('FRIENDICA_ADMIN_MAIL=' . $data['config']['admin_email'])); + $this->assertTrue(putenv('FRIENDICA_TZ=' . $data['system']['default_timezone'])); + $this->assertTrue(putenv('FRIENDICA_LANG=' . $data['system']['language'])); + + $console = new AutomaticInstallation($this->consoleArgv); + + $txt = $this->dumpExecute($console); + + $this->assertFinished($txt, true); + $this->assertConfig($data, false, true, false, true); + } + + /** + * Test the automatic installation with arguments + * @dataProvider dataInstaller + */ + public function testWithArguments(array $data) + { + $this->mockConnect(true, 1); + $this->mockConnected(true, 1); + $this->mockExistsTable('user', false, 1); + $this->mockUpdate([$this->root->url(), false, true, true], null, 1); + + $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); + $this->mockReplaceMacros('testTemplate', \Mockery::any(), false, '', 1); + + $console = new AutomaticInstallation($this->consoleArgv); + + $option = function($var, $cat, $key) use ($data, $console) { + if (!empty($data[$cat][$key])) { + $console->setOption($var, $data[$cat][$key]); + } + }; + $option('dbhost' , 'database', 'hostname'); + $option('dbport' , 'database', 'port'); + $option('dbuser' , 'database', 'username'); + $option('dbpass' , 'database', 'password'); + $option('dbdata' , 'database', 'database'); + $option('url' , 'system' , 'url'); + $option('phppath' , 'config' , 'php_path'); + $option('admin' , 'config' , 'admin_email'); + $option('tz' , 'system' , 'default_timezone'); + $option('lang' , 'system' , 'language'); + $option('basepath' , 'system' , 'basepath'); + + $txt = $this->dumpExecute($console); + + $this->assertFinished($txt, true); + $this->assertConfig($data, true, true, true, true); + } + + /** + * Test the automatic installation with a wrong database connection + */ + public function testNoDatabaseConnection() + { + $this->mockConnect(false, 1); + + $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); + $this->mockReplaceMacros('testTemplate', \Mockery::any(), false, '', 1); + + $console = new AutomaticInstallation($this->consoleArgv); + $console->setOption('url', 'http://friendica.local'); + + $txt = $this->dumpExecute($console); + + $this->assertStuckDB($txt); + $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')); + + $this->assertConfig(['config' => ['hostname' => 'friendica.local'], 'system' => ['url' => 'http://friendica.local', 'ssl_policy' => 0, 'urlpath' => '']], false, true, false, true); + } + + public function testGetHelp() + { + // Usable to purposely fail if new commands are added without taking tests into account + $theHelp = << prepared config file (e.g. "config/local.config.php" itself) which will override every other config option - except the environment variables) + -s|--savedb Save the DB credentials to the file (if environment variables is used) + -H|--dbhost The host of the mysql/mariadb database (env MYSQL_HOST) + -p|--dbport The port of the mysql/mariadb database (env MYSQL_PORT) + -d|--dbdata The name of the mysql/mariadb database (env MYSQL_DATABASE) + -U|--dbuser The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME) + -P|--dbpass The password of the mysql/mariadb database login (env MYSQL_PASSWORD) + -U|--url The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL) + -B|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) + -b|--basepath The basepath of Friendica (env FRIENDICA_BASE_PATH) + -t|--tz The timezone of Friendica (env FRIENDICA_TZ) + -L|--lang The language of Friendica (env FRIENDICA_LANG) + +Environment variables + MYSQL_HOST The host of the mysql/mariadb database (mandatory if mysql and environment is used) + MYSQL_PORT The port of the mysql/mariadb database + MYSQL_USERNAME|MYSQL_USER The username of the mysql/mariadb database login (MYSQL_USERNAME is for mysql, MYSQL_USER for mariadb) + MYSQL_PASSWORD The password of the mysql/mariadb database login + MYSQL_DATABASE The name of the mysql/mariadb database + FRIENDICA_URL The full base URL of Friendica - f.e. 'https://friendica.local/sub' + FRIENDICA_PHP_PATH The path of the PHP binary - leave empty for auto detection + FRIENDICA_BASE_PATH The basepath of Friendica - leave empty for auto detection + FRIENDICA_ADMIN_MAIL The admin email address of Friendica (this email will be used for admin access) + FRIENDICA_TZ The timezone of Friendica + FRIENDICA_LANG The langauge of Friendica + +Examples + bin/console autoinstall -f 'input.config.php + Installs Friendica with the prepared 'input.config.php' file + + bin/console autoinstall --savedb + Installs Friendica with environment variables and saves them to the 'config/local.config.php' file + + bin/console autoinstall -h localhost -p 3365 -U user -P passwort1234 -d friendica + Installs Friendica with a local mysql database with credentials + +HELP; + + $console = new AutomaticInstallation($this->consoleArgv); + $console->setOption('help', true); + + $txt = $this->dumpExecute($console); + + $this->assertEquals($theHelp, $txt); + } +} diff --git a/tests/src/Console/ConfigConsoleTest.php b/tests/src/Console/ConfigConsoleTest.php new file mode 100644 index 0000000000..8658097f9a --- /dev/null +++ b/tests/src/Console/ConfigConsoleTest.php @@ -0,0 +1,193 @@ +mockApp($this->root); + + \Mockery::getConfiguration()->setConstantsMap([ + Mode::class => [ + 'DBCONFIGAVAILABLE' => 0 + ] + ]); + + $this->mode + ->shouldReceive('has') + ->andReturn(true); + + } + + function testSetGetKeyValue() { + $this->configMock + ->shouldReceive('set') + ->with('config', 'test', 'now') + ->andReturn(true) + ->once(); + $this->configMock + ->shouldReceive('get') + ->with('config', 'test') + ->andReturn('now') + ->twice(); + + $console = new Config($this->consoleArgv); + $console->setArgument(0, 'config'); + $console->setArgument(1, 'test'); + $console->setArgument(2, 'now'); + $txt = $this->dumpExecute($console); + $this->assertEquals("config.test <= now\n", $txt); + + $this->configMock + ->shouldReceive('get') + ->with('config', 'test') + ->andReturn('now') + ->once(); + + $console = new Config($this->consoleArgv); + $console->setArgument(0, 'config'); + $console->setArgument(1, 'test'); + $txt = $this->dumpExecute($console); + $this->assertEquals("config.test => now\n", $txt); + + $this->configMock + ->shouldReceive('get') + ->with('config', 'test') + ->andReturn(null) + ->once(); + + $console = new Config($this->consoleArgv); + $console->setArgument(0, 'config'); + $console->setArgument(1, 'test'); + $txt = $this->dumpExecute($console); + $this->assertEquals("config.test => \n", $txt); + } + + function testSetArrayValue() { + $testArray = [1, 2, 3]; + $this->configMock + ->shouldReceive('get') + ->with('config', 'test') + ->andReturn($testArray) + ->once(); + + $console = new Config($this->consoleArgv); + $console->setArgument(0, 'config'); + $console->setArgument(1, 'test'); + $console->setArgument(2, 'now'); + $txt = $this->dumpExecute($console); + + $this->assertEquals("[Error] config.test is an array and can't be set using this command.\n", $txt); + } + + function testTooManyArguments() { + $console = new Config($this->consoleArgv); + $console->setArgument(0, 'config'); + $console->setArgument(1, 'test'); + $console->setArgument(2, 'it'); + $console->setArgument(3, 'now'); + $txt = $this->dumpExecute($console); + $assertion = '[Warning] Too many arguments'; + $firstline = substr($txt, 0, strlen($assertion)); + $this->assertEquals($assertion, $firstline); + } + + function testVerbose() { + $this->configMock + ->shouldReceive('get') + ->with('test', 'it') + ->andReturn('now') + ->once(); + $console = new Config($this->consoleArgv); + $console->setArgument(0, 'test'); + $console->setArgument(1, 'it'); + $console->setOption('v', 1); + $executable = $this->consoleArgv[0]; + $assertion = << 'test', + 1 => 'it', +) +Options: array ( + 'v' => 1, +) +test.it => now + +CONF; + $txt = $this->dumpExecute($console); + $this->assertEquals($assertion, $txt); + } + + function testUnableToSet() { + $this->configMock + ->shouldReceive('set') + ->with('test', 'it', 'now') + ->andReturn(false) + ->once(); + $this->configMock + ->shouldReceive('get') + ->with('test', 'it') + ->andReturn(NULL) + ->once(); + $console = new Config(); + $console->setArgument(0, 'test'); + $console->setArgument(1, 'it'); + $console->setArgument(2, 'now'); + $txt = $this->dumpExecute($console); + $this->assertSame("Unable to set test.it\n", $txt); + } + + public function testGetHelp() + { + // Usable to purposely fail if new commands are added without taking tests into account + $theHelp = << [-h|--help|-?] [-v] + bin/console config [-h|--help|-?] [-v] + bin/console config [-h|--help|-?] [-v] + +Description + bin/console config + Lists all config values + + bin/console config + Lists all config values in the provided category + + bin/console config + Shows the value of the provided key in the category + + bin/console config + Sets the value of the provided key in the category + +Notes: + Setting config entries which are manually set in config/local.config.php may result in + conflict between database settings and the manual startup settings. + +Options + -h|--help|-? Show help information + -v Show more debug information. + +HELP; + $console = new Config($this->consoleArgv); + $console->setOption('help', true); + + $txt = $this->dumpExecute($console); + + $this->assertEquals($txt, $theHelp); + } +} diff --git a/tests/src/Console/ConsoleTest.php b/tests/src/Console/ConsoleTest.php new file mode 100644 index 0000000000..21979e72b2 --- /dev/null +++ b/tests/src/Console/ConsoleTest.php @@ -0,0 +1,46 @@ +setUpVfsDir(); + } + + /** + * Dumps the execution of an console output to a string and returns it + * + * @param Console $console The current console instance + * + * @return string the output of the execution + */ + protected function dumpExecute($console) + { + Intercept::reset(); + $console->execute(); + $returnStr = Intercept::$cache; + Intercept::reset(); + + return $returnStr; + } +} diff --git a/tests/src/Console/ServerBlockConsoleTest.php b/tests/src/Console/ServerBlockConsoleTest.php new file mode 100644 index 0000000000..11856eac16 --- /dev/null +++ b/tests/src/Console/ServerBlockConsoleTest.php @@ -0,0 +1,337 @@ + 'social.nobodyhasthe.biz', + 'reason' => 'Illegal content', + ], + [ + 'domain' => 'pod.ordoevangelistarum.com', + 'reason' => 'Illegal content', + ] + ]; + + protected function setUp() + { + parent::setUp(); + + $this->mockApp($this->root); + } + + /** + * Test to list the default blocked servers + */ + public function testBlockedServersList() + { + $this->configMock + ->shouldReceive('get') + ->with('system', 'blocklist') + ->andReturn($this->defaultBlockList) + ->once(); + + $console = new ServerBlock($this->consoleArgv); + $txt = $this->dumpExecute($console); + + $output = <<assertEquals($output, $txt); + } + + /** + * Test blockedservers add command + */ + public function testAddBlockedServer() + { + $this->configMock + ->shouldReceive('get') + ->with('system', 'blocklist') + ->andReturn($this->defaultBlockList) + ->once(); + + $newBlockList = $this->defaultBlockList; + $newBlockList[] = [ + 'domain' => 'testme.now', + 'reason' => 'I like it!', + ]; + + $this->configMock + ->shouldReceive('set') + ->with('system', 'blocklist', $newBlockList) + ->andReturn(true) + ->once(); + + $console = new ServerBlock($this->consoleArgv); + $console->setArgument(0, 'add'); + $console->setArgument(1, 'testme.now'); + $console->setArgument(2, 'I like it!'); + $txt = $this->dumpExecute($console); + + $this->assertEquals('The domain \'testme.now\' is now blocked. (Reason: \'I like it!\')' . PHP_EOL, $txt); + } + + /** + * Test blockedservers add command with the default reason + */ + public function testAddBlockedServerWithDefaultReason() + { + $this->configMock + ->shouldReceive('get') + ->with('system', 'blocklist') + ->andReturn($this->defaultBlockList) + ->once(); + + $newBlockList = $this->defaultBlockList; + $newBlockList[] = [ + 'domain' => 'testme.now', + 'reason' => ServerBlock::DEFAULT_REASON, + ]; + + $this->configMock + ->shouldReceive('set') + ->with('system', 'blocklist', $newBlockList) + ->andReturn(true) + ->once(); + + $console = new ServerBlock($this->consoleArgv); + $console->setArgument(0, 'add'); + $console->setArgument(1, 'testme.now'); + $txt = $this->dumpExecute($console); + + $this->assertEquals('The domain \'testme.now\' is now blocked. (Reason: \'' . ServerBlock::DEFAULT_REASON . '\')' . PHP_EOL, $txt); + } + + /** + * Test blockedservers add command on existed domain + */ + public function testUpdateBlockedServer() + { + $this->configMock + ->shouldReceive('get') + ->with('system', 'blocklist') + ->andReturn($this->defaultBlockList) + ->once(); + + $newBlockList = [ + [ + 'domain' => 'social.nobodyhasthe.biz', + 'reason' => 'Illegal content', + ], + [ + 'domain' => 'pod.ordoevangelistarum.com', + 'reason' => 'Other reason', + ] + ]; + + $this->configMock + ->shouldReceive('set') + ->with('system', 'blocklist', $newBlockList) + ->andReturn(true) + ->once(); + + $console = new ServerBlock($this->consoleArgv); + $console->setArgument(0, 'add'); + $console->setArgument(1, 'pod.ordoevangelistarum.com'); + $console->setArgument(2, 'Other reason'); + $txt = $this->dumpExecute($console); + + $this->assertEquals('The domain \'pod.ordoevangelistarum.com\' is now updated. (Reason: \'Other reason\')' . PHP_EOL, $txt); + } + + /** + * Test blockedservers remove command + */ + public function testRemoveBlockedServer() + { + $this->configMock + ->shouldReceive('get') + ->with('system', 'blocklist') + ->andReturn($this->defaultBlockList) + ->once(); + + $newBlockList = [ + [ + 'domain' => 'social.nobodyhasthe.biz', + 'reason' => 'Illegal content', + ], + ]; + + $this->configMock + ->shouldReceive('set') + ->with('system', 'blocklist', $newBlockList) + ->andReturn(true) + ->once(); + + $console = new ServerBlock($this->consoleArgv); + $console->setArgument(0, 'remove'); + $console->setArgument(1, 'pod.ordoevangelistarum.com'); + $txt = $this->dumpExecute($console); + + $this->assertEquals('The domain \'pod.ordoevangelistarum.com\' is not more blocked' . PHP_EOL, $txt); + } + + /** + * Test blockedservers with a wrong command + */ + public function testBlockedServersWrongCommand() + { + $console = new ServerBlock($this->consoleArgv); + $console->setArgument(0, 'wrongcommand'); + $txt = $this->dumpExecute($console); + + $this->assertStringStartsWith('[Warning] Unknown command', $txt); + } + + /** + * Test blockedservers remove with not existing domain + */ + public function testRemoveBlockedServerNotExist() + { + $this->configMock + ->shouldReceive('get') + ->with('system', 'blocklist') + ->andReturn($this->defaultBlockList) + ->once(); + + $console = new ServerBlock($this->consoleArgv); + $console->setArgument(0, 'remove'); + $console->setArgument(1, 'not.exiting'); + $txt = $this->dumpExecute($console); + + $this->assertEquals('The domain \'not.exiting\' is not blocked.' . PHP_EOL, $txt); + } + + /** + * Test blockedservers add command without argument + */ + public function testAddBlockedServerMissingArgument() + { + $console = new ServerBlock($this->consoleArgv); + $console->setArgument(0, 'add'); + $txt = $this->dumpExecute($console); + + $this->assertStringStartsWith('[Warning] Add needs a domain and optional a reason.', $txt); + } + + /** + * Test blockedservers add command without save + */ + public function testAddBlockedServerNoSave() + { + $this->configMock + ->shouldReceive('get') + ->with('system', 'blocklist') + ->andReturn($this->defaultBlockList) + ->once(); + + $newBlockList = $this->defaultBlockList; + $newBlockList[] = [ + 'domain' => 'testme.now', + 'reason' => ServerBlock::DEFAULT_REASON, + ]; + + $this->configMock + ->shouldReceive('set') + ->with('system', 'blocklist', $newBlockList) + ->andReturn(false) + ->once(); + + $console = new ServerBlock($this->consoleArgv); + $console->setArgument(0, 'add'); + $console->setArgument(1, 'testme.now'); + $txt = $this->dumpExecute($console); + + $this->assertEquals('Couldn\'t save \'testme.now\' as blocked server' . PHP_EOL, $txt); + } + + /** + * Test blockedservers remove command without save + */ + public function testRemoveBlockedServerNoSave() + { + $this->configMock + ->shouldReceive('get') + ->with('system', 'blocklist') + ->andReturn($this->defaultBlockList) + ->once(); + + $newBlockList = [ + [ + 'domain' => 'social.nobodyhasthe.biz', + 'reason' => 'Illegal content', + ], + ]; + + $this->configMock + ->shouldReceive('set') + ->with('system', 'blocklist', $newBlockList) + ->andReturn(false) + ->once(); + + $console = new ServerBlock($this->consoleArgv); + $console->setArgument(0, 'remove'); + $console->setArgument(1, 'pod.ordoevangelistarum.com'); + $txt = $this->dumpExecute($console); + + $this->assertEquals('Couldn\'t remove \'pod.ordoevangelistarum.com\' from blocked servers' . PHP_EOL, $txt); + } + + /** + * Test blockedservers remove command without argument + */ + public function testRemoveBlockedServerMissingArgument() + { + $console = new ServerBlock($this->consoleArgv); + $console->setArgument(0, 'remove'); + $txt = $this->dumpExecute($console); + + $this->assertStringStartsWith('[Warning] Remove needs a second parameter.', $txt); + } + + /** + * Test the blockedservers help + */ + public function testBlockedServersHelp() + { + $console = new ServerBlock($this->consoleArgv); + $console->setOption('help', true); + $txt = $this->dumpExecute($console); + + $help = << [-h|--help|-?] [-v] + bin/console serverblock remove [-h|--help|-?] [-v] + +Description + With this tool, you can list the current blocked servers + or you can add / remove a blocked server from the list + +Options + -h|--help|-? Show help information + -v Show more debug information. + +HELP; + + $this->assertEquals($help, $txt); + } +} diff --git a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php deleted file mode 100644 index 9ed3d404f2..0000000000 --- a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php +++ /dev/null @@ -1,646 +0,0 @@ -root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')) { - $this->root->getChild('config') - ->removeChild('local.config.php'); - } - - $this->mockL10nT(); - - $this->configCache = new ConfigCache(); - $this->configCache->set('system', 'basepath', $this->root->url()); - $this->configCache->set('config', 'php_path', trim(shell_exec('which php'))); - $this->configCache->set('system', 'theme', 'smarty3'); - - $this->mockApp($this->root, true); - - $this->configMock->shouldReceive('set')->andReturnUsing(function ($cat, $key, $value) { - if ($key !== 'basepath') { - return $this->configCache->set($cat, $key, $value); - } else { - return true; - } - }); - - $this->configMock->shouldReceive('has')->andReturn(true); - $this->configMock->shouldReceive('get')->andReturnUsing(function ($cat, $key) { - return $this->configCache->get($cat, $key); - }); - $this->configMock->shouldReceive('load')->andReturnUsing(function ($config, $overwrite = false) { - return $this->configCache->load($config, $overwrite); - }); - - $this->mode->shouldReceive('isInstall')->andReturn(true); - Logger::init(new VoidLogger()); - } - - /** - * Returns the dataset for each automatic installation test - * - * @return array the dataset - */ - public function dataInstaller() - { - return [ - 'empty' => [ - 'data' => [ - 'database' => [ - 'hostname' => '', - 'username' => '', - 'password' => '', - 'database' => '', - 'port' => '', - ], - 'config' => [ - 'php_path' => '', - 'hostname' => 'friendica.local', - 'admin_email' => '', - ], - 'system' => [ - 'basepath' => '', - 'urlpath' => '', - 'url' => 'http://friendica.local', - 'ssl_policy' => 0, - 'default_timezone' => '', - 'language' => '', - ], - ], - ], - 'normal' => [ - 'data' => [ - 'database' => [ - 'hostname' => 'testhost', - 'port' => 3306, - 'username' => 'friendica', - 'password' => 'a password', - 'database' => 'database', - ], - 'config' => [ - 'php_path' => '', - 'hostname' => 'friendica.local', - 'admin_email' => 'admin@philipp.info', - ], - 'system' => [ - 'urlpath' => 'test/it', - 'url' => 'http://friendica.local/test/it', - 'basepath' => '', - 'ssl_policy' => '2', - 'default_timezone' => 'en', - 'language' => 'Europe/Berlin', - ], - ], - ], - 'special' => [ - 'data' => [ - 'database' => [ - 'hostname' => 'testhost.new.domain', - 'port' => 3341, - 'username' => 'fr"§%ica', - 'password' => '$%\"gse', - 'database' => 'db', - ], - 'config' => [ - 'php_path' => '', - 'hostname' => 'friendica.local', - 'admin_email' => 'admin@philipp.info', - ], - 'system' => [ - 'urlpath' => 'test/it', - 'url' => 'https://friendica.local/test/it', - 'basepath' => '', - 'ssl_policy' => '1', - 'default_timezone' => 'en', - 'language' => 'Europe/Berlin', - ], - ], - ], - ]; - } - - private function assertFinished($txt, $withconfig = false, $copyfile = false) - { - $cfg = ''; - - if ($withconfig) { - $cfg = <<assertEquals($finished, $txt); - } - - private function assertStuckDB($txt) - { - $finished = <<assertEquals($finished, $txt); - } - - private function assertStuckURL($txt) - { - $finished = <<assertEquals($finished, $txt); - } - - /** - * Asserts one config entry - * - * @param string $cat The category to test - * @param string $key The key to test - * @param null|array $assertion The asserted value (null = empty, or array/string) - * @param string $default_value The default value - */ - public function assertConfigEntry($cat, $key, $assertion = null, $default_value = null) - { - if (!empty($assertion[$cat][$key])) { - $this->assertEquals($assertion[$cat][$key], $this->configCache->get($cat, $key)); - } elseif (!empty($assertion) && !is_array($assertion)) { - $this->assertEquals($assertion, $this->configCache->get($cat, $key)); - } elseif (!empty($default_value)) { - $this->assertEquals($default_value, $this->configCache->get($cat, $key)); - } else { - $this->assertEmpty($this->configCache->get($cat, $key), $this->configCache->get($cat, $key)); - } - } - - /** - * Asserts all config entries - * - * @param null|array $assertion The optional assertion array - * @param boolean $saveDb True, if the db credentials should get saved to the file - * @param boolean $default True, if we use the default values - * @param boolean $defaultDb True, if we use the default value for the DB - * @param boolean $realBasepath True, if we use the real basepath of the installation, not the mocked one - */ - public function assertConfig($assertion = null, $saveDb = false, $default = true, $defaultDb = true, $realBasepath = false) - { - if (!empty($assertion['database']['hostname'])) { - $assertion['database']['hostname'] .= (!empty($assertion['database']['port']) ? ':' . $assertion['database']['port'] : ''); - } - - $this->assertConfigEntry('database', 'hostname', ($saveDb) ? $assertion : null, (!$saveDb || $defaultDb) ? Installer::DEFAULT_HOST : null); - $this->assertConfigEntry('database', 'username', ($saveDb) ? $assertion : null); - $this->assertConfigEntry('database', 'password', ($saveDb) ? $assertion : null); - $this->assertConfigEntry('database', 'database', ($saveDb) ? $assertion : null); - - $this->assertConfigEntry('config', 'admin_email', $assertion); - $this->assertConfigEntry('config', 'php_path', trim(shell_exec('which php'))); - $this->assertConfigEntry('config', 'hostname', $assertion); - - $this->assertConfigEntry('system', 'default_timezone', $assertion, ($default) ? Installer::DEFAULT_TZ : null); - $this->assertConfigEntry('system', 'language', $assertion, ($default) ? Installer::DEFAULT_LANG : null); - $this->assertConfigEntry('system', 'url', $assertion); - $this->assertConfigEntry('system', 'urlpath', $assertion); - $this->assertConfigEntry('system', 'ssl_policy', $assertion, ($default) ? BaseURL::DEFAULT_SSL_SCHEME : null); - $this->assertConfigEntry('system', 'basepath', ($realBasepath) ? $this->root->url() : $assertion); - } - - /** - * Test the automatic installation without any parameter/setting - * Should stuck because of missing hostname - */ - public function testEmpty() - { - $console = new AutomaticInstallation($this->consoleArgv); - - $txt = $this->dumpExecute($console); - - $this->assertStuckURL($txt); - } - - /** - * Test the automatic installation without any parameter/setting - * except URL - */ - public function testEmptyWithURL() - { - $this->mockConnect(true, 1); - $this->mockConnected(true, 1); - $this->mockExistsTable('user', false, 1); - $this->mockUpdate([$this->root->url(), false, true, true], null, 1); - - $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); - $this->mockReplaceMacros('testTemplate', \Mockery::any(), false, '', 1); - - $console = new AutomaticInstallation($this->consoleArgv); - $console->setOption('url', 'http://friendica.local'); - - $txt = $this->dumpExecute($console); - - $this->assertFinished($txt, true, false); - $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')); - - $this->assertConfig(['config' => ['hostname' => 'friendica.local'], 'system' => ['url' => 'http://friendica.local', 'ssl_policy' => 0, 'urlPath' => '']], false, true, true, true); - } - - /** - * Test the automatic installation with a prepared config file - * @dataProvider dataInstaller - */ - public function testWithConfig(array $data) - { - $this->mockConnect(true, 1); - $this->mockConnected(true, 1); - $this->mockExistsTable('user', false, 1); - $this->mockUpdate([$this->root->url(), false, true, true], null, 1); - - $conf = function ($cat, $key) use ($data) { - if ($cat == 'database' && $key == 'hostname' && !empty($data['database']['port'])) { - return $data[$cat][$key] . ':' . $data['database']['port']; - } - return $data[$cat][$key]; - }; - - $config = << [ - 'hostname' => '{$conf('database', 'hostname')}', - 'username' => '{$conf('database', 'username')}', - 'password' => '{$conf('database', 'password')}', - 'database' => '{$conf('database', 'database')}', - 'charset' => 'utf8mb4', - ], - - // **************************************************************** - // The configuration below will be overruled by the admin panel. - // Changes made below will only have an effect if the database does - // not contain any configuration for the friendica system. - // **************************************************************** - - 'config' => [ - 'admin_email' => '{$conf('config', 'admin_email')}', - 'hostname' => '{$conf('config', 'hostname')}', - 'sitename' => 'Friendica Social Network', - 'register_policy' => \Friendica\Module\Register::OPEN, - 'register_text' => '', - ], - 'system' => [ - 'basepath' => '{$conf('system', 'basepath')}', - 'urlpath' => '{$conf('system', 'urlpath')}', - 'url' => '{$conf('system', 'url')}', - 'ssl_policy' => '{$conf('system', 'ssl_policy')}', - 'default_timezone' => '{$conf('system', 'default_timezone')}', - 'language' => '{$conf('system', 'language')}', - ], -]; -CONF; - - vfsStream::newFile('prepared.config.php') - ->at($this->root) - ->setContent($config); - - $console = new AutomaticInstallation($this->consoleArgv); - $console->setOption('f', 'prepared.config.php'); - - $txt = $this->dumpExecute($console); - - $this->assertFinished($txt, false, true); - - $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')); - $this->assertEquals($config, file_get_contents($this->root->getChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')->url())); - - $this->assertConfig($data, true, false, false); - } - - /** - * Test the automatic installation with environment variables - * Includes saving the DB credentials to the file - * @dataProvider dataInstaller - */ - public function testWithEnvironmentAndSave(array $data) - { - $this->mockConnect(true, 1); - $this->mockConnected(true, 1); - $this->mockExistsTable('user', false, 1); - $this->mockUpdate([$this->root->url(), false, true, true], null, 1); - - $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); - $this->mockReplaceMacros('testTemplate', \Mockery::any(), false, '', 1); - - $this->assertTrue(putenv('MYSQL_HOST=' . $data['database']['hostname'])); - $this->assertTrue(putenv('MYSQL_PORT=' . $data['database']['port'])); - $this->assertTrue(putenv('MYSQL_DATABASE=' . $data['database']['database'])); - $this->assertTrue(putenv('MYSQL_USERNAME=' . $data['database']['username'])); - $this->assertTrue(putenv('MYSQL_PASSWORD=' . $data['database']['password'])); - - $this->assertTrue(putenv('FRIENDICA_HOSTNAME=' . $data['config']['hostname'])); - $this->assertTrue(putenv('FRIENDICA_BASE_PATH=' . $data['system']['basepath'])); - $this->assertTrue(putenv('FRIENDICA_URL=' . $data['system']['url'])); - $this->assertTrue(putenv('FRIENDICA_PHP_PATH=' . $data['config']['php_path'])); - $this->assertTrue(putenv('FRIENDICA_ADMIN_MAIL=' . $data['config']['admin_email'])); - $this->assertTrue(putenv('FRIENDICA_TZ=' . $data['system']['default_timezone'])); - $this->assertTrue(putenv('FRIENDICA_LANG=' . $data['system']['language'])); - - $console = new AutomaticInstallation($this->consoleArgv); - $console->setOption('savedb', true); - - $txt = $this->dumpExecute($console); - - $this->assertFinished($txt, true); - $this->assertConfig($data, true, true, false, true); - } - - /** - * Test the automatic installation with environment variables - * Don't save the db credentials to the file - * @dataProvider dataInstaller - */ - public function testWithEnvironmentWithoutSave(array $data) - { - $this->mockConnect(true, 1); - $this->mockConnected(true, 1); - $this->mockExistsTable('user', false, 1); - $this->mockUpdate([$this->root->url(), false, true, true], null, 1); - - $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); - $this->mockReplaceMacros('testTemplate', \Mockery::any(), false, '', 1); - - $this->assertTrue(putenv('MYSQL_HOST=' . $data['database']['hostname'])); - $this->assertTrue(putenv('MYSQL_PORT=' . $data['database']['port'])); - $this->assertTrue(putenv('MYSQL_DATABASE=' . $data['database']['database'])); - $this->assertTrue(putenv('MYSQL_USERNAME=' . $data['database']['username'])); - $this->assertTrue(putenv('MYSQL_PASSWORD=' . $data['database']['password'])); - - $this->assertTrue(putenv('FRIENDICA_HOSTNAME=' . $data['config']['hostname'])); - $this->assertTrue(putenv('FRIENDICA_BASE_PATH=' . $data['system']['basepath'])); - $this->assertTrue(putenv('FRIENDICA_URL=' . $data['system']['url'])); - $this->assertTrue(putenv('FRIENDICA_PHP_PATH=' . $data['config']['php_path'])); - $this->assertTrue(putenv('FRIENDICA_ADMIN_MAIL=' . $data['config']['admin_email'])); - $this->assertTrue(putenv('FRIENDICA_TZ=' . $data['system']['default_timezone'])); - $this->assertTrue(putenv('FRIENDICA_LANG=' . $data['system']['language'])); - - $console = new AutomaticInstallation($this->consoleArgv); - - $txt = $this->dumpExecute($console); - - $this->assertFinished($txt, true); - $this->assertConfig($data, false, true, false, true); - } - - /** - * Test the automatic installation with arguments - * @dataProvider dataInstaller - */ - public function testWithArguments(array $data) - { - $this->mockConnect(true, 1); - $this->mockConnected(true, 1); - $this->mockExistsTable('user', false, 1); - $this->mockUpdate([$this->root->url(), false, true, true], null, 1); - - $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); - $this->mockReplaceMacros('testTemplate', \Mockery::any(), false, '', 1); - - $console = new AutomaticInstallation($this->consoleArgv); - - $option = function($var, $cat, $key) use ($data, $console) { - if (!empty($data[$cat][$key])) { - $console->setOption($var, $data[$cat][$key]); - } - }; - $option('dbhost' , 'database', 'hostname'); - $option('dbport' , 'database', 'port'); - $option('dbuser' , 'database', 'username'); - $option('dbpass' , 'database', 'password'); - $option('dbdata' , 'database', 'database'); - $option('url' , 'system' , 'url'); - $option('phppath' , 'config' , 'php_path'); - $option('admin' , 'config' , 'admin_email'); - $option('tz' , 'system' , 'default_timezone'); - $option('lang' , 'system' , 'language'); - $option('basepath' , 'system' , 'basepath'); - - $txt = $this->dumpExecute($console); - - $this->assertFinished($txt, true); - $this->assertConfig($data, true, true, true, true); - } - - /** - * Test the automatic installation with a wrong database connection - */ - public function testNoDatabaseConnection() - { - $this->mockConnect(false, 1); - - $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); - $this->mockReplaceMacros('testTemplate', \Mockery::any(), false, '', 1); - - $console = new AutomaticInstallation($this->consoleArgv); - $console->setOption('url', 'http://friendica.local'); - - $txt = $this->dumpExecute($console); - - $this->assertStuckDB($txt); - $this->assertTrue($this->root->hasChild('config' . DIRECTORY_SEPARATOR . 'local.config.php')); - - $this->assertConfig(['config' => ['hostname' => 'friendica.local'], 'system' => ['url' => 'http://friendica.local', 'ssl_policy' => 0, 'urlpath' => '']], false, true, false, true); - } - - public function testGetHelp() - { - // Usable to purposely fail if new commands are added without taking tests into account - $theHelp = << prepared config file (e.g. "config/local.config.php" itself) which will override every other config option - except the environment variables) - -s|--savedb Save the DB credentials to the file (if environment variables is used) - -H|--dbhost The host of the mysql/mariadb database (env MYSQL_HOST) - -p|--dbport The port of the mysql/mariadb database (env MYSQL_PORT) - -d|--dbdata The name of the mysql/mariadb database (env MYSQL_DATABASE) - -U|--dbuser The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME) - -P|--dbpass The password of the mysql/mariadb database login (env MYSQL_PASSWORD) - -U|--url The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL) - -B|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) - -b|--basepath The basepath of Friendica (env FRIENDICA_BASE_PATH) - -t|--tz The timezone of Friendica (env FRIENDICA_TZ) - -L|--lang The language of Friendica (env FRIENDICA_LANG) - -Environment variables - MYSQL_HOST The host of the mysql/mariadb database (mandatory if mysql and environment is used) - MYSQL_PORT The port of the mysql/mariadb database - MYSQL_USERNAME|MYSQL_USER The username of the mysql/mariadb database login (MYSQL_USERNAME is for mysql, MYSQL_USER for mariadb) - MYSQL_PASSWORD The password of the mysql/mariadb database login - MYSQL_DATABASE The name of the mysql/mariadb database - FRIENDICA_URL The full base URL of Friendica - f.e. 'https://friendica.local/sub' - FRIENDICA_PHP_PATH The path of the PHP binary - leave empty for auto detection - FRIENDICA_BASE_PATH The basepath of Friendica - leave empty for auto detection - FRIENDICA_ADMIN_MAIL The admin email address of Friendica (this email will be used for admin access) - FRIENDICA_TZ The timezone of Friendica - FRIENDICA_LANG The langauge of Friendica - -Examples - bin/console autoinstall -f 'input.config.php - Installs Friendica with the prepared 'input.config.php' file - - bin/console autoinstall --savedb - Installs Friendica with environment variables and saves them to the 'config/local.config.php' file - - bin/console autoinstall -h localhost -p 3365 -U user -P passwort1234 -d friendica - Installs Friendica with a local mysql database with credentials - -HELP; - - $console = new AutomaticInstallation($this->consoleArgv); - $console->setOption('help', true); - - $txt = $this->dumpExecute($console); - - $this->assertEquals($theHelp, $txt); - } -} diff --git a/tests/src/Core/Console/ConfigConsoleTest.php b/tests/src/Core/Console/ConfigConsoleTest.php deleted file mode 100644 index c58b05ec39..0000000000 --- a/tests/src/Core/Console/ConfigConsoleTest.php +++ /dev/null @@ -1,193 +0,0 @@ -mockApp($this->root); - - \Mockery::getConfiguration()->setConstantsMap([ - Mode::class => [ - 'DBCONFIGAVAILABLE' => 0 - ] - ]); - - $this->mode - ->shouldReceive('has') - ->andReturn(true); - - } - - function testSetGetKeyValue() { - $this->configMock - ->shouldReceive('set') - ->with('config', 'test', 'now') - ->andReturn(true) - ->once(); - $this->configMock - ->shouldReceive('get') - ->with('config', 'test') - ->andReturn('now') - ->twice(); - - $console = new Config($this->consoleArgv); - $console->setArgument(0, 'config'); - $console->setArgument(1, 'test'); - $console->setArgument(2, 'now'); - $txt = $this->dumpExecute($console); - $this->assertEquals("config.test <= now\n", $txt); - - $this->configMock - ->shouldReceive('get') - ->with('config', 'test') - ->andReturn('now') - ->once(); - - $console = new Config($this->consoleArgv); - $console->setArgument(0, 'config'); - $console->setArgument(1, 'test'); - $txt = $this->dumpExecute($console); - $this->assertEquals("config.test => now\n", $txt); - - $this->configMock - ->shouldReceive('get') - ->with('config', 'test') - ->andReturn(null) - ->once(); - - $console = new Config($this->consoleArgv); - $console->setArgument(0, 'config'); - $console->setArgument(1, 'test'); - $txt = $this->dumpExecute($console); - $this->assertEquals("config.test => \n", $txt); - } - - function testSetArrayValue() { - $testArray = [1, 2, 3]; - $this->configMock - ->shouldReceive('get') - ->with('config', 'test') - ->andReturn($testArray) - ->once(); - - $console = new Config($this->consoleArgv); - $console->setArgument(0, 'config'); - $console->setArgument(1, 'test'); - $console->setArgument(2, 'now'); - $txt = $this->dumpExecute($console); - - $this->assertEquals("[Error] config.test is an array and can't be set using this command.\n", $txt); - } - - function testTooManyArguments() { - $console = new Config($this->consoleArgv); - $console->setArgument(0, 'config'); - $console->setArgument(1, 'test'); - $console->setArgument(2, 'it'); - $console->setArgument(3, 'now'); - $txt = $this->dumpExecute($console); - $assertion = '[Warning] Too many arguments'; - $firstline = substr($txt, 0, strlen($assertion)); - $this->assertEquals($assertion, $firstline); - } - - function testVerbose() { - $this->configMock - ->shouldReceive('get') - ->with('test', 'it') - ->andReturn('now') - ->once(); - $console = new Config($this->consoleArgv); - $console->setArgument(0, 'test'); - $console->setArgument(1, 'it'); - $console->setOption('v', 1); - $executable = $this->consoleArgv[0]; - $assertion = << 'test', - 1 => 'it', -) -Options: array ( - 'v' => 1, -) -test.it => now - -CONF; - $txt = $this->dumpExecute($console); - $this->assertEquals($assertion, $txt); - } - - function testUnableToSet() { - $this->configMock - ->shouldReceive('set') - ->with('test', 'it', 'now') - ->andReturn(false) - ->once(); - $this->configMock - ->shouldReceive('get') - ->with('test', 'it') - ->andReturn(NULL) - ->once(); - $console = new Config(); - $console->setArgument(0, 'test'); - $console->setArgument(1, 'it'); - $console->setArgument(2, 'now'); - $txt = $this->dumpExecute($console); - $this->assertSame("Unable to set test.it\n", $txt); - } - - public function testGetHelp() - { - // Usable to purposely fail if new commands are added without taking tests into account - $theHelp = << [-h|--help|-?] [-v] - bin/console config [-h|--help|-?] [-v] - bin/console config [-h|--help|-?] [-v] - -Description - bin/console config - Lists all config values - - bin/console config - Lists all config values in the provided category - - bin/console config - Shows the value of the provided key in the category - - bin/console config - Sets the value of the provided key in the category - -Notes: - Setting config entries which are manually set in config/local.config.php may result in - conflict between database settings and the manual startup settings. - -Options - -h|--help|-? Show help information - -v Show more debug information. - -HELP; - $console = new Config($this->consoleArgv); - $console->setOption('help', true); - - $txt = $this->dumpExecute($console); - - $this->assertEquals($txt, $theHelp); - } -} diff --git a/tests/src/Core/Console/ConsoleTest.php b/tests/src/Core/Console/ConsoleTest.php deleted file mode 100644 index e142e60066..0000000000 --- a/tests/src/Core/Console/ConsoleTest.php +++ /dev/null @@ -1,46 +0,0 @@ -setUpVfsDir(); - } - - /** - * Dumps the execution of an console output to a string and returns it - * - * @param Console $console The current console instance - * - * @return string the output of the execution - */ - protected function dumpExecute($console) - { - Intercept::reset(); - $console->execute(); - $returnStr = Intercept::$cache; - Intercept::reset(); - - return $returnStr; - } -} diff --git a/tests/src/Core/Console/ServerBlockConsoleTest.php b/tests/src/Core/Console/ServerBlockConsoleTest.php deleted file mode 100644 index 512a416f5e..0000000000 --- a/tests/src/Core/Console/ServerBlockConsoleTest.php +++ /dev/null @@ -1,337 +0,0 @@ - 'social.nobodyhasthe.biz', - 'reason' => 'Illegal content', - ], - [ - 'domain' => 'pod.ordoevangelistarum.com', - 'reason' => 'Illegal content', - ] - ]; - - protected function setUp() - { - parent::setUp(); - - $this->mockApp($this->root); - } - - /** - * Test to list the default blocked servers - */ - public function testBlockedServersList() - { - $this->configMock - ->shouldReceive('get') - ->with('system', 'blocklist') - ->andReturn($this->defaultBlockList) - ->once(); - - $console = new ServerBlock($this->consoleArgv); - $txt = $this->dumpExecute($console); - - $output = <<assertEquals($output, $txt); - } - - /** - * Test blockedservers add command - */ - public function testAddBlockedServer() - { - $this->configMock - ->shouldReceive('get') - ->with('system', 'blocklist') - ->andReturn($this->defaultBlockList) - ->once(); - - $newBlockList = $this->defaultBlockList; - $newBlockList[] = [ - 'domain' => 'testme.now', - 'reason' => 'I like it!', - ]; - - $this->configMock - ->shouldReceive('set') - ->with('system', 'blocklist', $newBlockList) - ->andReturn(true) - ->once(); - - $console = new ServerBlock($this->consoleArgv); - $console->setArgument(0, 'add'); - $console->setArgument(1, 'testme.now'); - $console->setArgument(2, 'I like it!'); - $txt = $this->dumpExecute($console); - - $this->assertEquals('The domain \'testme.now\' is now blocked. (Reason: \'I like it!\')' . PHP_EOL, $txt); - } - - /** - * Test blockedservers add command with the default reason - */ - public function testAddBlockedServerWithDefaultReason() - { - $this->configMock - ->shouldReceive('get') - ->with('system', 'blocklist') - ->andReturn($this->defaultBlockList) - ->once(); - - $newBlockList = $this->defaultBlockList; - $newBlockList[] = [ - 'domain' => 'testme.now', - 'reason' => ServerBlock::DEFAULT_REASON, - ]; - - $this->configMock - ->shouldReceive('set') - ->with('system', 'blocklist', $newBlockList) - ->andReturn(true) - ->once(); - - $console = new ServerBlock($this->consoleArgv); - $console->setArgument(0, 'add'); - $console->setArgument(1, 'testme.now'); - $txt = $this->dumpExecute($console); - - $this->assertEquals('The domain \'testme.now\' is now blocked. (Reason: \'' . ServerBlock::DEFAULT_REASON . '\')' . PHP_EOL, $txt); - } - - /** - * Test blockedservers add command on existed domain - */ - public function testUpdateBlockedServer() - { - $this->configMock - ->shouldReceive('get') - ->with('system', 'blocklist') - ->andReturn($this->defaultBlockList) - ->once(); - - $newBlockList = [ - [ - 'domain' => 'social.nobodyhasthe.biz', - 'reason' => 'Illegal content', - ], - [ - 'domain' => 'pod.ordoevangelistarum.com', - 'reason' => 'Other reason', - ] - ]; - - $this->configMock - ->shouldReceive('set') - ->with('system', 'blocklist', $newBlockList) - ->andReturn(true) - ->once(); - - $console = new ServerBlock($this->consoleArgv); - $console->setArgument(0, 'add'); - $console->setArgument(1, 'pod.ordoevangelistarum.com'); - $console->setArgument(2, 'Other reason'); - $txt = $this->dumpExecute($console); - - $this->assertEquals('The domain \'pod.ordoevangelistarum.com\' is now updated. (Reason: \'Other reason\')' . PHP_EOL, $txt); - } - - /** - * Test blockedservers remove command - */ - public function testRemoveBlockedServer() - { - $this->configMock - ->shouldReceive('get') - ->with('system', 'blocklist') - ->andReturn($this->defaultBlockList) - ->once(); - - $newBlockList = [ - [ - 'domain' => 'social.nobodyhasthe.biz', - 'reason' => 'Illegal content', - ], - ]; - - $this->configMock - ->shouldReceive('set') - ->with('system', 'blocklist', $newBlockList) - ->andReturn(true) - ->once(); - - $console = new ServerBlock($this->consoleArgv); - $console->setArgument(0, 'remove'); - $console->setArgument(1, 'pod.ordoevangelistarum.com'); - $txt = $this->dumpExecute($console); - - $this->assertEquals('The domain \'pod.ordoevangelistarum.com\' is not more blocked' . PHP_EOL, $txt); - } - - /** - * Test blockedservers with a wrong command - */ - public function testBlockedServersWrongCommand() - { - $console = new ServerBlock($this->consoleArgv); - $console->setArgument(0, 'wrongcommand'); - $txt = $this->dumpExecute($console); - - $this->assertStringStartsWith('[Warning] Unknown command', $txt); - } - - /** - * Test blockedservers remove with not existing domain - */ - public function testRemoveBlockedServerNotExist() - { - $this->configMock - ->shouldReceive('get') - ->with('system', 'blocklist') - ->andReturn($this->defaultBlockList) - ->once(); - - $console = new ServerBlock($this->consoleArgv); - $console->setArgument(0, 'remove'); - $console->setArgument(1, 'not.exiting'); - $txt = $this->dumpExecute($console); - - $this->assertEquals('The domain \'not.exiting\' is not blocked.' . PHP_EOL, $txt); - } - - /** - * Test blockedservers add command without argument - */ - public function testAddBlockedServerMissingArgument() - { - $console = new ServerBlock($this->consoleArgv); - $console->setArgument(0, 'add'); - $txt = $this->dumpExecute($console); - - $this->assertStringStartsWith('[Warning] Add needs a domain and optional a reason.', $txt); - } - - /** - * Test blockedservers add command without save - */ - public function testAddBlockedServerNoSave() - { - $this->configMock - ->shouldReceive('get') - ->with('system', 'blocklist') - ->andReturn($this->defaultBlockList) - ->once(); - - $newBlockList = $this->defaultBlockList; - $newBlockList[] = [ - 'domain' => 'testme.now', - 'reason' => ServerBlock::DEFAULT_REASON, - ]; - - $this->configMock - ->shouldReceive('set') - ->with('system', 'blocklist', $newBlockList) - ->andReturn(false) - ->once(); - - $console = new ServerBlock($this->consoleArgv); - $console->setArgument(0, 'add'); - $console->setArgument(1, 'testme.now'); - $txt = $this->dumpExecute($console); - - $this->assertEquals('Couldn\'t save \'testme.now\' as blocked server' . PHP_EOL, $txt); - } - - /** - * Test blockedservers remove command without save - */ - public function testRemoveBlockedServerNoSave() - { - $this->configMock - ->shouldReceive('get') - ->with('system', 'blocklist') - ->andReturn($this->defaultBlockList) - ->once(); - - $newBlockList = [ - [ - 'domain' => 'social.nobodyhasthe.biz', - 'reason' => 'Illegal content', - ], - ]; - - $this->configMock - ->shouldReceive('set') - ->with('system', 'blocklist', $newBlockList) - ->andReturn(false) - ->once(); - - $console = new ServerBlock($this->consoleArgv); - $console->setArgument(0, 'remove'); - $console->setArgument(1, 'pod.ordoevangelistarum.com'); - $txt = $this->dumpExecute($console); - - $this->assertEquals('Couldn\'t remove \'pod.ordoevangelistarum.com\' from blocked servers' . PHP_EOL, $txt); - } - - /** - * Test blockedservers remove command without argument - */ - public function testRemoveBlockedServerMissingArgument() - { - $console = new ServerBlock($this->consoleArgv); - $console->setArgument(0, 'remove'); - $txt = $this->dumpExecute($console); - - $this->assertStringStartsWith('[Warning] Remove needs a second parameter.', $txt); - } - - /** - * Test the blockedservers help - */ - public function testBlockedServersHelp() - { - $console = new ServerBlock($this->consoleArgv); - $console->setOption('help', true); - $txt = $this->dumpExecute($console); - - $help = << [-h|--help|-?] [-v] - bin/console serverblock remove [-h|--help|-?] [-v] - -Description - With this tool, you can list the current blocked servers - or you can add / remove a blocked server from the list - -Options - -h|--help|-? Show help information - -v Show more debug information. - -HELP; - - $this->assertEquals($help, $txt); - } -}