--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Friendica\Core\L10n;
+use Friendica\Database\DBA;
+use Friendica\Util\Strings;
+use RuntimeException;
+
+/**
+ * @brief tool to archive a contact on the server
+ *
+ * With this tool you can archive a contact when you know that it isn't existing anymore.
+ * Normally this does happen automatically after a few days.
+ *
+ * License: AGPLv3 or later, same as Friendica
+ *
+ */
+class ArchiveContact extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console archivecontact - archive a contact
+Usage
+ bin/console archivecontact <profile_url> [-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;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Asika\SimpleConsole\Console;
+use Friendica\BaseObject;
+use Friendica\Core\Config;
+use Friendica\Core\Installer;
+use Friendica\Core\Theme;
+use Friendica\Util\BasePath;
+use Friendica\Util\BaseURL;
+use Friendica\Util\Config\ConfigFileLoader;
+use RuntimeException;
+
+class AutomaticInstallation extends Console
+{
+ protected function getHelp()
+ {
+ return <<<HELP
+Installation - Install Friendica automatically
+Synopsis
+ bin/console autoinstall [-h|--help|-?] [-v] [-a] [-f]
+
+Description
+ Installs Friendica with data based on the local.config.php file or environment variables
+
+Notes
+ Not checking .htaccess/URL-Rewrite during CLI installation.
+
+Options
+ -h|--help|-? Show help information
+ -v Show more debug information.
+ -a All setup checks are required (except .htaccess)
+ -f|--file <config> 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 <host> The host of the mysql/mariadb database (env MYSQL_HOST)
+ -p|--dbport <port> The port of the mysql/mariadb database (env MYSQL_PORT)
+ -d|--dbdata <database> The name of the mysql/mariadb database (env MYSQL_DATABASE)
+ -U|--dbuser <username> The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
+ -P|--dbpass <password> The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
+ -U|--url <url> The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL)
+ -B|--phppath <php_path> The path of the PHP binary (env FRIENDICA_PHP_PATH)
+ -b|--basepath <base_path> The basepath of Friendica (env FRIENDICA_BASE_PATH)
+ -t|--tz <timezone> The timezone of Friendica (env FRIENDICA_TZ)
+ -L|--lang <language> 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;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Asika\SimpleConsole\CommandArgsException;
+use Friendica\App;
+use Friendica\Core;
+use RuntimeException;
+
+/**
+ * @brief tool to access the cache from the CLI
+ *
+ * With this script you can access the cache of your node from the CLI.
+ * You can read current values stored in the cache and set new values
+ * in cache keys.
+ *
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class Cache extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console cache - Manage node cache
+Synopsis
+ bin/console cache list [-h|--help|-?] [-v]
+ bin/console cache get <key> [-h|--help|-?] [-v]
+ bin/console cache set <key> <value> [-h|--help|-?] [-v]
+ bin/console cache flush [-h|--help|-?] [-v]
+ bin/console cache clear [-h|--help|-?] [-v]
+
+Description
+ bin/console cache list [<prefix>]
+ List all cache keys, optionally filtered by a prefix
+
+ bin/console cache get <key>
+ Shows the value of the provided cache key
+
+ bin/console cache set <key> <value> [<ttl>]
+ 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');
+ }
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Asika\SimpleConsole\CommandArgsException;
+use Friendica\App;
+use Friendica\Core;
+use RuntimeException;
+
+/**
+ * @brief tool to access the system config from the CLI
+ *
+ * With this script you can access the system configuration of your node from
+ * the CLI. You can do both, reading current values stored in the database and
+ * set new values to config variables.
+ *
+ * Usage:
+ * If you specify no parameters at the CLI, the script will list all config
+ * variables defined.
+ *
+ * If you specify one parameter, the script will list all config variables
+ * defined in this section of the configuration (e.g. "system").
+ *
+ * If you specify two parameters, the script will show you the current value
+ * of the named configuration setting. (e.g. "system loglevel")
+ *
+ * If you specify three parameters, the named configuration setting will be
+ * set to the value of the last parameter. (e.g. "system loglevel 0" will
+ * disable logging)
+ *
+ * @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class Config extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console config - Manage site configuration
+Synopsis
+ bin/console config [-h|--help|-?] [-v]
+ bin/console config <category> [-h|--help|-?] [-v]
+ bin/console config <category> <key> [-h|--help|-?] [-v]
+ bin/console config <category> <key> <value> [-h|--help|-?] [-v]
+
+Description
+ bin/console config
+ Lists all config values
+
+ bin/console config <category>
+ Lists all config values in the provided category
+
+ bin/console config <category> <key>
+ Shows the value of the provided key in the category
+
+ bin/console config <category> <key> <value>
+ 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;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+/**
+ * Description of CreateDoxygen
+ *
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class CreateDoxygen extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console createdoxygen - Generate Doxygen headers
+Usage
+ bin/console createdoxygen <file> [-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;
+ }
+
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Friendica\Core;
+use Friendica\Core\Update;
+use Friendica\Database\DBA;
+use Friendica\Database\DBStructure;
+use RuntimeException;
+
+/**
+ * @brief Performs database updates from the command line
+ *
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class DatabaseStructure extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console dbstructure - Performs database updates
+Usage
+ bin/console dbstructure <command> [-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;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+/**
+ * When I installed docblox, I had the experience that it does not generate any output at all.
+ * This script may be used to find that kind of problems with the documentation build process.
+ * If docblox generates output, use another approach for debugging.
+ *
+ * Basically, docblox takes a list of files to build documentation from. This script assumes there is a file or set of files
+ * breaking the build when it is included in that list. It tries to calculate the smallest list containing these files.
+ * Unfortunatly, the original problem is NP-complete, so what the script does is a best guess only.
+ *
+ * So it starts with a list of all files in the project.
+ * If that list can't be build, it cuts it in two parts and tries both parts independently. If only one of them breaks,
+ * it takes that one and tries the same independently. If both break, it assumes this is the smallest set. This assumption
+ * is not necessarily true. Maybe the smallest set consists of two files and both of them were in different parts when
+ * the list was divided, but by now it is my best guess. To make this assumption better, the list is shuffled after every step.
+ *
+ * After that, the script tries to remove a file from the list. It tests if the list breaks and if so, it
+ * assumes that the file it removed belongs to the set of erroneous files.
+ * This is done for all files, so, in the end removing one file leads to a working doc build.
+ *
+ * @author Alexander Kampmann
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class DocBloxErrorChecker extends \Asika\SimpleConsole\Console
+{
+
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console docbloxerrorchecker - Checks the file tree for docblox errors
+Usage
+ bin/console docbloxerrorchecker [-h|--help|-?] [-v]
+
+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) {
+ 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 [];
+ }
+
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+/**
+ * Extracts translation strings from the Friendica project's files to be exported
+ * to Transifex for translation.
+ *
+ * Outputs a PHP file with language strings used by Friendica
+ *
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class Extract extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console extract - Generate translation string file for the Friendica project (deprecated)
+Usage
+ bin/console extract [-h|--help|-?] [-v]
+
+Description
+ This script was used to generate the translation string file to be exported to Transifex,
+ please use bin/run_xgettext.sh instead
+
+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) {
+ throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
+ }
+
+ $s = '<?php' . PHP_EOL;
+ $s .= '
+ function string_plural_select($n){
+ return ($n != 1);
+ }
+
+ ';
+
+ $arr = [];
+
+ $files = array_merge(
+ ['index.php', 'boot.php'],
+ glob('mod/*'),
+ glob('include/*'),
+ glob('addon/*/*'),
+ $this->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;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Friendica\Core\L10n;
+use Friendica\Model\Contact;
+
+/**
+ * @brief tool to block an account from the node
+ *
+ * With this tool, you can block an account in such a way, that no postings
+ * or comments this account writes are accepted to the node.
+ *
+ * License: AGPLv3 or later, same as Friendica
+ *
+ * @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class GlobalCommunityBlock extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console globalcommunityblock - Block remote profile from interacting with this node
+Usage
+ bin/console globalcommunityblock <profile_url> [-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;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Friendica\Core\Protocol;
+use Friendica\Database\DBA;
+use Friendica\Network\Probe;
+use Friendica\Util\Strings;
+use RuntimeException;
+
+/**
+ * @brief tool to silence accounts on the global community page
+ *
+ * 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.
+ *
+ * License: AGPLv3 or later, same as Friendica
+ *
+ * @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class GlobalCommunitySilence extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console globalcommunitysilence - Silence remote profile from global community page
+Usage
+ bin/console globalcommunitysilence <profile_url> [-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;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Friendica\Core;
+
+/**
+ * @brief Sets maintenance mode for this node
+ *
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class Maintenance extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console maintenance - Sets maintenance mode for this node
+Usage
+ bin/console maintenance <enable> [<reason>] [-h|--help|-?] [-v]
+
+Description
+ <enable> cen be either 0 or 1 to disabled or enable the maintenance mode on this node.
+
+ <reason> 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;
+ }
+
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Friendica\Core\L10n;
+use Friendica\Database\DBA;
+use Friendica\Model\User;
+use RuntimeException;
+
+/**
+ * @brief tool to set a new password for a user
+ *
+ * With this tool, you can set a new password for a user
+ *
+ * License: AGPLv3 or later, same as Friendica
+ *
+ * @author Michael Vogel <heluecht@pirati.ca>
+ */
+class NewPassword extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console newpassword - Creates a new password for a given user
+Usage
+ bin/console newpassword <nickname> [<password>] [-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;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+/**
+ * Read a strings.php file and create messages.po in the same directory
+ *
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class PhpToPo extends \Asika\SimpleConsole\Console
+{
+
+ protected $helpOptions = ['h', 'help', '?'];
+
+ private $normBaseMsgIds = [];
+ const NORM_REGEXP = "|[\\\]|";
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console php2po - Generate a messages.po file from a strings.php file
+Usage
+ bin/console php2po [-p <n>] [--base <file>] <path/to/strings.php> [-h|--help|-?] [-v]
+
+Description
+ Read a strings.php file and create the according messages.po in the same directory
+
+Options
+ -p <n> Number of plural forms. Default: 2
+ --base <file> 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;
+ }
+
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+/**
+ * Read a messages.po file and create strings.php in the same directory
+ *
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class PoToPhp extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ const DQ_ESCAPE = "__DQ__";
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console php2po - Generate a strings.php file from a messages.po file
+Usage
+ bin/console php2po <path/to/messages.po> [-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 = "<?php\n\n";
+
+ $infile = file($pofile);
+ $k = '';
+ $v = '';
+ $arr = false;
+ $ink = false;
+ $inv = false;
+ $escape_s_exp = '|[^\\\\]\$[a-z]|';
+
+ foreach ($infile as $l) {
+ $l = str_replace('\"', self::DQ_ESCAPE, $l);
+ $len = strlen($l);
+ if ($l[0] == "#") {
+ $l = "";
+ }
+
+ if (substr($l, 0, 15) == '"Plural-Forms: ') {
+ $match = [];
+ preg_match("|nplurals=([0-9]*); *plural=(.*)[;\\\\]|", $l, $match);
+ $cond = str_replace('n', '$n', $match[2]);
+ // define plural select function if not already defined
+ $fnname = 'string_plural_select_' . $lang;
+ $out .= 'if(! function_exists("' . $fnname . '")) {' . "\n";
+ $out .= 'function ' . $fnname . '($n){' . "\n";
+ $out .= ' $n = intval($n);' . "\n";
+ $out .= ' return ' . $cond . ';' . "\n";
+ $out .= '}}' . "\n";
+ }
+
+ if ($k != '' && substr($l, 0, 7) == 'msgstr ') {
+ if ($ink) {
+ $ink = false;
+ $out .= '$a->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]);
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Friendica\Core\Config;
+use Friendica\Core\L10n;
+use Friendica\Core\Update;
+
+/**
+ * Performs database post updates
+ *
+ * License: AGPLv3 or later, same as Friendica
+ *
+ * @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class PostUpdate extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console postupdate - Performs database post updates
+Usage
+ bin/console postupdate [-h|--help|-?] [--reset <version>]
+
+Options
+ -h|--help|-? Show help information
+ --reset <version> 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;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Asika\SimpleConsole\CommandArgsException;
+use Asika\SimpleConsole\Console;
+use Console_Table;
+use Friendica\BaseObject;
+use Friendica\Core\Config\Configuration;
+
+/**
+ * @brief Manage blocked servers
+ *
+ * With this tool, you can list the current blocked servers
+ * or you can add / remove a blocked server from the list
+ */
+class ServerBlock extends Console
+{
+ const DEFAULT_REASON = 'blocked';
+
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console serverblock - Manage blocked servers
+Usage
+ bin/console serverblock [-h|--help|-?] [-v]
+ bin/console serverblock add <server> <reason> [-h|--help|-?] [-v]
+ bin/console serverblock remove <server> [-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;
+ }
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Asika\SimpleConsole\CommandArgsException;
+use Friendica\Core\StorageManager;
+
+/**
+ * @brief tool to manage storage backend and stored data from CLI
+ *
+ */
+class Storage extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console storage - manage storage backend and stored data
+Synopsis
+ bin/console storage [-h|--help|-?] [-v]
+ Show this help
+
+ bin/console storage list
+ List available storage backends
+
+ bin/console storage set <name>
+ 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));
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Console;
+
+use Friendica\BaseObject;
+
+/**
+ * Tired of chasing typos and finding them after a commit.
+ * Run this and quickly see if we've got any parse errors in our application files.
+ *
+ * @author Hypolite Petovan <hypolite@mrpetovan.com>
+ */
+class Typo extends \Asika\SimpleConsole\Console
+{
+ protected $helpOptions = ['h', 'help', '?'];
+
+ protected function getHelp()
+ {
+ $help = <<<HELP
+console typo - Checks for parse errors in Friendica files
+Usage
+ bin/console typo [-h|--help|-?] [-v]
+
+Description
+ Checks all PHP files in the Friendica file tree for parse errors
+
+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) {
+ 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.');
+ }
+ }
+}
namespace Friendica\Core;
+use Friendica;
+
/**
* Description of Console
*
}
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()
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Friendica\Core\L10n;
-use Friendica\Database\DBA;
-use Friendica\Util\Strings;
-use RuntimeException;
-
-/**
- * @brief tool to archive a contact on the server
- *
- * With this tool you can archive a contact when you know that it isn't existing anymore.
- * Normally this does happen automatically after a few days.
- *
- * License: AGPLv3 or later, same as Friendica
- *
- */
-class ArchiveContact extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console archivecontact - archive a contact
-Usage
- bin/console archivecontact <profile_url> [-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;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Asika\SimpleConsole\Console;
-use Friendica\BaseObject;
-use Friendica\Core\Config;
-use Friendica\Core\Installer;
-use Friendica\Core\Theme;
-use Friendica\Util\BasePath;
-use Friendica\Util\BaseURL;
-use Friendica\Util\Config\ConfigFileLoader;
-use RuntimeException;
-
-class AutomaticInstallation extends Console
-{
- protected function getHelp()
- {
- return <<<HELP
-Installation - Install Friendica automatically
-Synopsis
- bin/console autoinstall [-h|--help|-?] [-v] [-a] [-f]
-
-Description
- Installs Friendica with data based on the local.config.php file or environment variables
-
-Notes
- Not checking .htaccess/URL-Rewrite during CLI installation.
-
-Options
- -h|--help|-? Show help information
- -v Show more debug information.
- -a All setup checks are required (except .htaccess)
- -f|--file <config> 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 <host> The host of the mysql/mariadb database (env MYSQL_HOST)
- -p|--dbport <port> The port of the mysql/mariadb database (env MYSQL_PORT)
- -d|--dbdata <database> The name of the mysql/mariadb database (env MYSQL_DATABASE)
- -U|--dbuser <username> The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
- -P|--dbpass <password> The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
- -U|--url <url> The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL)
- -B|--phppath <php_path> The path of the PHP binary (env FRIENDICA_PHP_PATH)
- -b|--basepath <base_path> The basepath of Friendica (env FRIENDICA_BASE_PATH)
- -t|--tz <timezone> The timezone of Friendica (env FRIENDICA_TZ)
- -L|--lang <language> 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;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Asika\SimpleConsole\CommandArgsException;
-use Friendica\App;
-use Friendica\Core;
-use RuntimeException;
-
-/**
- * @brief tool to access the cache from the CLI
- *
- * With this script you can access the cache of your node from the CLI.
- * You can read current values stored in the cache and set new values
- * in cache keys.
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class Cache extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console cache - Manage node cache
-Synopsis
- bin/console cache list [-h|--help|-?] [-v]
- bin/console cache get <key> [-h|--help|-?] [-v]
- bin/console cache set <key> <value> [-h|--help|-?] [-v]
- bin/console cache flush [-h|--help|-?] [-v]
- bin/console cache clear [-h|--help|-?] [-v]
-
-Description
- bin/console cache list [<prefix>]
- List all cache keys, optionally filtered by a prefix
-
- bin/console cache get <key>
- Shows the value of the provided cache key
-
- bin/console cache set <key> <value> [<ttl>]
- 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');
- }
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Asika\SimpleConsole\CommandArgsException;
-use Friendica\App;
-use Friendica\Core;
-use RuntimeException;
-
-/**
- * @brief tool to access the system config from the CLI
- *
- * With this script you can access the system configuration of your node from
- * the CLI. You can do both, reading current values stored in the database and
- * set new values to config variables.
- *
- * Usage:
- * If you specify no parameters at the CLI, the script will list all config
- * variables defined.
- *
- * If you specify one parameter, the script will list all config variables
- * defined in this section of the configuration (e.g. "system").
- *
- * If you specify two parameters, the script will show you the current value
- * of the named configuration setting. (e.g. "system loglevel")
- *
- * If you specify three parameters, the named configuration setting will be
- * set to the value of the last parameter. (e.g. "system loglevel 0" will
- * disable logging)
- *
- * @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class Config extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console config - Manage site configuration
-Synopsis
- bin/console config [-h|--help|-?] [-v]
- bin/console config <category> [-h|--help|-?] [-v]
- bin/console config <category> <key> [-h|--help|-?] [-v]
- bin/console config <category> <key> <value> [-h|--help|-?] [-v]
-
-Description
- bin/console config
- Lists all config values
-
- bin/console config <category>
- Lists all config values in the provided category
-
- bin/console config <category> <key>
- Shows the value of the provided key in the category
-
- bin/console config <category> <key> <value>
- 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;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-/**
- * Description of CreateDoxygen
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class CreateDoxygen extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console createdoxygen - Generate Doxygen headers
-Usage
- bin/console createdoxygen <file> [-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;
- }
-
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Friendica\Core;
-use Friendica\Core\Update;
-use Friendica\Database\DBA;
-use Friendica\Database\DBStructure;
-use RuntimeException;
-
-/**
- * @brief Performs database updates from the command line
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class DatabaseStructure extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console dbstructure - Performs database updates
-Usage
- bin/console dbstructure <command> [-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;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-/**
- * When I installed docblox, I had the experience that it does not generate any output at all.
- * This script may be used to find that kind of problems with the documentation build process.
- * If docblox generates output, use another approach for debugging.
- *
- * Basically, docblox takes a list of files to build documentation from. This script assumes there is a file or set of files
- * breaking the build when it is included in that list. It tries to calculate the smallest list containing these files.
- * Unfortunatly, the original problem is NP-complete, so what the script does is a best guess only.
- *
- * So it starts with a list of all files in the project.
- * If that list can't be build, it cuts it in two parts and tries both parts independently. If only one of them breaks,
- * it takes that one and tries the same independently. If both break, it assumes this is the smallest set. This assumption
- * is not necessarily true. Maybe the smallest set consists of two files and both of them were in different parts when
- * the list was divided, but by now it is my best guess. To make this assumption better, the list is shuffled after every step.
- *
- * After that, the script tries to remove a file from the list. It tests if the list breaks and if so, it
- * assumes that the file it removed belongs to the set of erroneous files.
- * This is done for all files, so, in the end removing one file leads to a working doc build.
- *
- * @author Alexander Kampmann
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class DocBloxErrorChecker extends \Asika\SimpleConsole\Console
-{
-
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console docbloxerrorchecker - Checks the file tree for docblox errors
-Usage
- bin/console docbloxerrorchecker [-h|--help|-?] [-v]
-
-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) {
- 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 [];
- }
-
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-/**
- * Extracts translation strings from the Friendica project's files to be exported
- * to Transifex for translation.
- *
- * Outputs a PHP file with language strings used by Friendica
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class Extract extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console extract - Generate translation string file for the Friendica project (deprecated)
-Usage
- bin/console extract [-h|--help|-?] [-v]
-
-Description
- This script was used to generate the translation string file to be exported to Transifex,
- please use bin/run_xgettext.sh instead
-
-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) {
- throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
- }
-
- $s = '<?php' . PHP_EOL;
- $s .= '
- function string_plural_select($n){
- return ($n != 1);
- }
-
- ';
-
- $arr = [];
-
- $files = array_merge(
- ['index.php', 'boot.php'],
- glob('mod/*'),
- glob('include/*'),
- glob('addon/*/*'),
- $this->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;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Friendica\Core\L10n;
-use Friendica\Model\Contact;
-
-/**
- * @brief tool to block an account from the node
- *
- * With this tool, you can block an account in such a way, that no postings
- * or comments this account writes are accepted to the node.
- *
- * License: AGPLv3 or later, same as Friendica
- *
- * @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class GlobalCommunityBlock extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console globalcommunityblock - Block remote profile from interacting with this node
-Usage
- bin/console globalcommunityblock <profile_url> [-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;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Friendica\Core\Protocol;
-use Friendica\Database\DBA;
-use Friendica\Network\Probe;
-use Friendica\Util\Strings;
-use RuntimeException;
-
-/**
- * @brief tool to silence accounts on the global community page
- *
- * 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.
- *
- * License: AGPLv3 or later, same as Friendica
- *
- * @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class GlobalCommunitySilence extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console globalcommunitysilence - Silence remote profile from global community page
-Usage
- bin/console globalcommunitysilence <profile_url> [-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;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Friendica\Core;
-
-/**
- * @brief Sets maintenance mode for this node
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class Maintenance extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console maintenance - Sets maintenance mode for this node
-Usage
- bin/console maintenance <enable> [<reason>] [-h|--help|-?] [-v]
-
-Description
- <enable> cen be either 0 or 1 to disabled or enable the maintenance mode on this node.
-
- <reason> 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;
- }
-
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Friendica\Core\L10n;
-use Friendica\Database\DBA;
-use Friendica\Model\User;
-use RuntimeException;
-
-/**
- * @brief tool to set a new password for a user
- *
- * With this tool, you can set a new password for a user
- *
- * License: AGPLv3 or later, same as Friendica
- *
- * @author Michael Vogel <heluecht@pirati.ca>
- */
-class NewPassword extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console newpassword - Creates a new password for a given user
-Usage
- bin/console newpassword <nickname> [<password>] [-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;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-/**
- * Read a strings.php file and create messages.po in the same directory
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class PhpToPo extends \Asika\SimpleConsole\Console
-{
-
- protected $helpOptions = ['h', 'help', '?'];
-
- private $normBaseMsgIds = [];
- const NORM_REGEXP = "|[\\\]|";
-
- protected function getHelp()
- {
- $help = <<<HELP
-console php2po - Generate a messages.po file from a strings.php file
-Usage
- bin/console php2po [-p <n>] [--base <file>] <path/to/strings.php> [-h|--help|-?] [-v]
-
-Description
- Read a strings.php file and create the according messages.po in the same directory
-
-Options
- -p <n> Number of plural forms. Default: 2
- --base <file> 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;
- }
-
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-/**
- * Read a messages.po file and create strings.php in the same directory
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class PoToPhp extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- const DQ_ESCAPE = "__DQ__";
-
- protected function getHelp()
- {
- $help = <<<HELP
-console php2po - Generate a strings.php file from a messages.po file
-Usage
- bin/console php2po <path/to/messages.po> [-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 = "<?php\n\n";
-
- $infile = file($pofile);
- $k = '';
- $v = '';
- $arr = false;
- $ink = false;
- $inv = false;
- $escape_s_exp = '|[^\\\\]\$[a-z]|';
-
- foreach ($infile as $l) {
- $l = str_replace('\"', self::DQ_ESCAPE, $l);
- $len = strlen($l);
- if ($l[0] == "#") {
- $l = "";
- }
-
- if (substr($l, 0, 15) == '"Plural-Forms: ') {
- $match = [];
- preg_match("|nplurals=([0-9]*); *plural=(.*)[;\\\\]|", $l, $match);
- $cond = str_replace('n', '$n', $match[2]);
- // define plural select function if not already defined
- $fnname = 'string_plural_select_' . $lang;
- $out .= 'if(! function_exists("' . $fnname . '")) {' . "\n";
- $out .= 'function ' . $fnname . '($n){' . "\n";
- $out .= ' $n = intval($n);' . "\n";
- $out .= ' return ' . $cond . ';' . "\n";
- $out .= '}}' . "\n";
- }
-
- if ($k != '' && substr($l, 0, 7) == 'msgstr ') {
- if ($ink) {
- $ink = false;
- $out .= '$a->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]);
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Friendica\Core\Config;
-use Friendica\Core\L10n;
-use Friendica\Core\Update;
-
-/**
- * Performs database post updates
- *
- * License: AGPLv3 or later, same as Friendica
- *
- * @author Tobias Diekershoff <tobias.diekershoff@gmx.net>
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class PostUpdate extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console postupdate - Performs database post updates
-Usage
- bin/console postupdate [-h|--help|-?] [--reset <version>]
-
-Options
- -h|--help|-? Show help information
- --reset <version> 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;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Asika\SimpleConsole\CommandArgsException;
-use Asika\SimpleConsole\Console;
-use Console_Table;
-use Friendica\BaseObject;
-use Friendica\Core\Config\Configuration;
-
-/**
- * @brief Manage blocked servers
- *
- * With this tool, you can list the current blocked servers
- * or you can add / remove a blocked server from the list
- */
-class ServerBlock extends Console
-{
- const DEFAULT_REASON = 'blocked';
-
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console serverblock - Manage blocked servers
-Usage
- bin/console serverblock [-h|--help|-?] [-v]
- bin/console serverblock add <server> <reason> [-h|--help|-?] [-v]
- bin/console serverblock remove <server> [-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;
- }
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Asika\SimpleConsole\CommandArgsException;
-use Friendica\Core\StorageManager;
-
-/**
- * @brief tool to manage storage backend and stored data from CLI
- *
- */
-class Storage extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console storage - manage storage backend and stored data
-Synopsis
- bin/console storage [-h|--help|-?] [-v]
- Show this help
-
- bin/console storage list
- List available storage backends
-
- bin/console storage set <name>
- 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));
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Core\Console;
-
-use Friendica\BaseObject;
-
-/**
- * Tired of chasing typos and finding them after a commit.
- * Run this and quickly see if we've got any parse errors in our application files.
- *
- * @author Hypolite Petovan <hypolite@mrpetovan.com>
- */
-class Typo extends \Asika\SimpleConsole\Console
-{
- protected $helpOptions = ['h', 'help', '?'];
-
- protected function getHelp()
- {
- $help = <<<HELP
-console typo - Checks for parse errors in Friendica files
-Usage
- bin/console typo [-h|--help|-?] [-v]
-
-Description
- Checks all PHP files in the Friendica file tree for parse errors
-
-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) {
- 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.');
- }
- }
-}
--- /dev/null
+<?php
+
+namespace Friendica\Test\src\Console;
+
+use Friendica\Console\AutomaticInstallation;
+use Friendica\Core\Config\Cache\ConfigCache;
+use Friendica\Core\Installer;
+use Friendica\Core\Logger;
+use Friendica\Test\Util\DBAMockTrait;
+use Friendica\Test\Util\DBStructureMockTrait;
+use Friendica\Test\Util\L10nMockTrait;
+use Friendica\Test\Util\RendererMockTrait;
+use Friendica\Util\BaseURL;
+use Friendica\Util\Logger\VoidLogger;
+use org\bovigo\vfs\vfsStream;
+use org\bovigo\vfs\vfsStreamFile;
+
+/**
+ * @runTestsInSeparateProcesses
+ * @preserveGlobalState disabled
+ * @requires PHP 7.0
+ */
+class AutomaticInstallationConsoleTest extends ConsoleTest
+{
+ use L10nMockTrait;
+ use DBAMockTrait;
+ use DBStructureMockTrait;
+ use RendererMockTrait;
+
+ /**
+ * @var vfsStreamFile Assert file without DB credentials
+ */
+ private $assertFile;
+ /**
+ * @var vfsStreamFile Assert file with DB credentials
+ */
+ private $assertFileDb;
+
+ /**
+ * @var ConfigCache The configuration cache to check after each test
+ */
+ private $configCache;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ if ($this->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 = <<<CFG
+
+
+Creating config file...
+
+ Complete!
+CFG;
+ }
+
+ if ($copyfile) {
+ $cfg = <<<CFG
+
+
+Copying config file...
+
+ Complete!
+CFG;
+ }
+
+ $finished = <<<FIN
+Initializing setup...
+
+ Complete!
+
+
+Checking environment...
+
+ NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.
+
+ Complete!
+{$cfg}
+
+
+Checking database...
+
+ Complete!
+
+
+Inserting data into database...
+
+ Complete!
+
+
+Installing theme
+
+ Complete
+
+
+
+Installation is finished
+
+
+FIN;
+ $this->assertEquals($finished, $txt);
+ }
+
+ private function assertStuckDB($txt)
+ {
+ $finished = <<<FIN
+Initializing setup...
+
+ Complete!
+
+
+Checking environment...
+
+ NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.
+
+ Complete!
+
+
+Creating config file...
+
+ Complete!
+
+
+Checking database...
+
+[Error] --------
+Could not connect to database.:
+
+
+FIN;
+
+ $this->assertEquals($finished, $txt);
+ }
+
+ private function assertStuckURL($txt)
+ {
+ $finished = <<<FIN
+Initializing setup...
+
+ Complete!
+
+
+Checking environment...
+
+ NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.
+
+ Complete!
+
+
+Creating config file...
+
+The Friendica URL has to be set during CLI installation.
+
+FIN;
+
+ $this->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 = <<<CONF
+<?php
+
+// Local configuration
+
+// If you're unsure about what any of the config keys below do, please check the config/defaults.config.php for detailed
+// documentation of their data type and behavior.
+
+return [
+ 'database' => [
+ '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 = <<<HELP
+Installation - Install Friendica automatically
+Synopsis
+ bin/console autoinstall [-h|--help|-?] [-v] [-a] [-f]
+
+Description
+ Installs Friendica with data based on the local.config.php file or environment variables
+
+Notes
+ Not checking .htaccess/URL-Rewrite during CLI installation.
+
+Options
+ -h|--help|-? Show help information
+ -v Show more debug information.
+ -a All setup checks are required (except .htaccess)
+ -f|--file <config> 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 <host> The host of the mysql/mariadb database (env MYSQL_HOST)
+ -p|--dbport <port> The port of the mysql/mariadb database (env MYSQL_PORT)
+ -d|--dbdata <database> The name of the mysql/mariadb database (env MYSQL_DATABASE)
+ -U|--dbuser <username> The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
+ -P|--dbpass <password> The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
+ -U|--url <url> The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL)
+ -B|--phppath <php_path> The path of the PHP binary (env FRIENDICA_PHP_PATH)
+ -b|--basepath <base_path> The basepath of Friendica (env FRIENDICA_BASE_PATH)
+ -t|--tz <timezone> The timezone of Friendica (env FRIENDICA_TZ)
+ -L|--lang <language> 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);
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Test\src\Console;
+
+use Friendica\App\Mode;
+use Friendica\Console\Config;
+
+/**
+ * @runTestsInSeparateProcesses
+ * @preserveGlobalState disabled
+ * @requires PHP 7.0
+ */
+class ConfigConsoleTest extends ConsoleTest
+{
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->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 = <<<CONF
+Executable: {$executable}
+Class: Friendica\Console\Config
+Arguments: array (
+ 0 => '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 = <<<HELP
+console config - Manage site configuration
+Synopsis
+ bin/console config [-h|--help|-?] [-v]
+ bin/console config <category> [-h|--help|-?] [-v]
+ bin/console config <category> <key> [-h|--help|-?] [-v]
+ bin/console config <category> <key> <value> [-h|--help|-?] [-v]
+
+Description
+ bin/console config
+ Lists all config values
+
+ bin/console config <category>
+ Lists all config values in the provided category
+
+ bin/console config <category> <key>
+ Shows the value of the provided key in the category
+
+ bin/console config <category> <key> <value>
+ 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);
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Test\src\Console;
+
+use Asika\SimpleConsole\Console;
+use Friendica\Test\MockedTest;
+use Friendica\Test\Util\AppMockTrait;
+use Friendica\Test\Util\Intercept;
+use Friendica\Test\Util\VFSTrait;
+
+abstract class ConsoleTest extends MockedTest
+{
+ use VFSTrait;
+ use AppMockTrait;
+
+ /**
+ * @var array The default argv for a Console Instance
+ */
+ protected $consoleArgv = [ 'consoleTest.php' ];
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ Intercept::setUp();
+
+ $this->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;
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Test\src\Console;
+
+use Friendica\Console\ServerBlock;
+
+/**
+ * @runTestsInSeparateProcesses
+ * @preserveGlobalState disabled
+ */
+class ServerBlockConsoleTest extends ConsoleTest
+{
+ protected $defaultBlockList = [
+ [
+ 'domain' => '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 = <<<CONS
++----------------------------+-----------------+
+| Domain | Reason |
++----------------------------+-----------------+
+| social.nobodyhasthe.biz | Illegal content |
+| pod.ordoevangelistarum.com | Illegal content |
++----------------------------+-----------------+
+
+
+CONS;
+
+ $this->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 = <<<HELP
+console serverblock - Manage blocked servers
+Usage
+ bin/console serverblock [-h|--help|-?] [-v]
+ bin/console serverblock add <server> <reason> [-h|--help|-?] [-v]
+ bin/console serverblock remove <server> [-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);
+ }
+}
+++ /dev/null
-<?php
-
-namespace Friendica\Test\src\Core\Console;
-
-use Friendica\Core\Config\Cache\ConfigCache;
-use Friendica\Core\Console\AutomaticInstallation;
-use Friendica\Core\Installer;
-use Friendica\Core\Logger;
-use Friendica\Test\Util\DBAMockTrait;
-use Friendica\Test\Util\DBStructureMockTrait;
-use Friendica\Test\Util\L10nMockTrait;
-use Friendica\Test\Util\RendererMockTrait;
-use Friendica\Util\BaseURL;
-use Friendica\Util\Logger\VoidLogger;
-use org\bovigo\vfs\vfsStream;
-use org\bovigo\vfs\vfsStreamFile;
-
-/**
- * @runTestsInSeparateProcesses
- * @preserveGlobalState disabled
- * @requires PHP 7.0
- */
-class AutomaticInstallationConsoleTest extends ConsoleTest
-{
- use L10nMockTrait;
- use DBAMockTrait;
- use DBStructureMockTrait;
- use RendererMockTrait;
-
- /**
- * @var vfsStreamFile Assert file without DB credentials
- */
- private $assertFile;
- /**
- * @var vfsStreamFile Assert file with DB credentials
- */
- private $assertFileDb;
-
- /**
- * @var ConfigCache The configuration cache to check after each test
- */
- private $configCache;
-
- public function setUp()
- {
- parent::setUp();
-
- if ($this->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 = <<<CFG
-
-
-Creating config file...
-
- Complete!
-CFG;
- }
-
- if ($copyfile) {
- $cfg = <<<CFG
-
-
-Copying config file...
-
- Complete!
-CFG;
- }
-
- $finished = <<<FIN
-Initializing setup...
-
- Complete!
-
-
-Checking environment...
-
- NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.
-
- Complete!
-{$cfg}
-
-
-Checking database...
-
- Complete!
-
-
-Inserting data into database...
-
- Complete!
-
-
-Installing theme
-
- Complete
-
-
-
-Installation is finished
-
-
-FIN;
- $this->assertEquals($finished, $txt);
- }
-
- private function assertStuckDB($txt)
- {
- $finished = <<<FIN
-Initializing setup...
-
- Complete!
-
-
-Checking environment...
-
- NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.
-
- Complete!
-
-
-Creating config file...
-
- Complete!
-
-
-Checking database...
-
-[Error] --------
-Could not connect to database.:
-
-
-FIN;
-
- $this->assertEquals($finished, $txt);
- }
-
- private function assertStuckURL($txt)
- {
- $finished = <<<FIN
-Initializing setup...
-
- Complete!
-
-
-Checking environment...
-
- NOTICE: Not checking .htaccess/URL-Rewrite during CLI installation.
-
- Complete!
-
-
-Creating config file...
-
-The Friendica URL has to be set during CLI installation.
-
-FIN;
-
- $this->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 = <<<CONF
-<?php
-
-// Local configuration
-
-// If you're unsure about what any of the config keys below do, please check the config/defaults.config.php for detailed
-// documentation of their data type and behavior.
-
-return [
- 'database' => [
- '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 = <<<HELP
-Installation - Install Friendica automatically
-Synopsis
- bin/console autoinstall [-h|--help|-?] [-v] [-a] [-f]
-
-Description
- Installs Friendica with data based on the local.config.php file or environment variables
-
-Notes
- Not checking .htaccess/URL-Rewrite during CLI installation.
-
-Options
- -h|--help|-? Show help information
- -v Show more debug information.
- -a All setup checks are required (except .htaccess)
- -f|--file <config> 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 <host> The host of the mysql/mariadb database (env MYSQL_HOST)
- -p|--dbport <port> The port of the mysql/mariadb database (env MYSQL_PORT)
- -d|--dbdata <database> The name of the mysql/mariadb database (env MYSQL_DATABASE)
- -U|--dbuser <username> The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME)
- -P|--dbpass <password> The password of the mysql/mariadb database login (env MYSQL_PASSWORD)
- -U|--url <url> The full base URL of Friendica - f.e. 'https://friendica.local/sub' (env FRIENDICA_URL)
- -B|--phppath <php_path> The path of the PHP binary (env FRIENDICA_PHP_PATH)
- -b|--basepath <base_path> The basepath of Friendica (env FRIENDICA_BASE_PATH)
- -t|--tz <timezone> The timezone of Friendica (env FRIENDICA_TZ)
- -L|--lang <language> 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);
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Test\src\Core\Console;
-
-use Friendica\App\Mode;
-use Friendica\Core\Console\Config;
-
-/**
- * @runTestsInSeparateProcesses
- * @preserveGlobalState disabled
- * @requires PHP 7.0
- */
-class ConfigConsoleTest extends ConsoleTest
-{
- protected function setUp()
- {
- parent::setUp();
-
- $this->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 = <<<CONF
-Executable: {$executable}
-Class: Friendica\Core\Console\Config
-Arguments: array (
- 0 => '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 = <<<HELP
-console config - Manage site configuration
-Synopsis
- bin/console config [-h|--help|-?] [-v]
- bin/console config <category> [-h|--help|-?] [-v]
- bin/console config <category> <key> [-h|--help|-?] [-v]
- bin/console config <category> <key> <value> [-h|--help|-?] [-v]
-
-Description
- bin/console config
- Lists all config values
-
- bin/console config <category>
- Lists all config values in the provided category
-
- bin/console config <category> <key>
- Shows the value of the provided key in the category
-
- bin/console config <category> <key> <value>
- 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);
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Test\src\Core\Console;
-
-use Asika\SimpleConsole\Console;
-use Friendica\Test\MockedTest;
-use Friendica\Test\Util\AppMockTrait;
-use Friendica\Test\Util\Intercept;
-use Friendica\Test\Util\VFSTrait;
-
-abstract class ConsoleTest extends MockedTest
-{
- use VFSTrait;
- use AppMockTrait;
-
- /**
- * @var array The default argv for a Console Instance
- */
- protected $consoleArgv = [ 'consoleTest.php' ];
-
- protected function setUp()
- {
- parent::setUp();
-
- Intercept::setUp();
-
- $this->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;
- }
-}
+++ /dev/null
-<?php
-
-namespace Friendica\Test\src\Core\Console;
-
-use Friendica\Core\Console\ServerBlock;
-
-/**
- * @runTestsInSeparateProcesses
- * @preserveGlobalState disabled
- */
-class ServerBlockConsoleTest extends ConsoleTest
-{
- protected $defaultBlockList = [
- [
- 'domain' => '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 = <<<CONS
-+----------------------------+-----------------+
-| Domain | Reason |
-+----------------------------+-----------------+
-| social.nobodyhasthe.biz | Illegal content |
-| pod.ordoevangelistarum.com | Illegal content |
-+----------------------------+-----------------+
-
-
-CONS;
-
- $this->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 = <<<HELP
-console serverblock - Manage blocked servers
-Usage
- bin/console serverblock [-h|--help|-?] [-v]
- bin/console serverblock add <server> <reason> [-h|--help|-?] [-v]
- bin/console serverblock remove <server> [-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);
- }
-}