break;\r
case 'docbloxerrorchecker' : $subconsole = new Console\DocBloxErrorChecker($subargs);\r
break;\r
+ case 'extract' : $subconsole = new Console\Extract($subargs);\r
+ break;\r
case 'globalcommunityblock': $subconsole = new Console\GlobalCommunityBlock($subargs);\r
break;\r
+ case 'globalcommunitysilence': $subconsole = new Console\GlobalCommunitySilence($subargs);\r
+ break;\r
+ case 'maintenance': $subconsole = new Console\Maintenance($subargs);\r
+ break;\r
+ case 'php2po': $subconsole = new Console\PhpToPo($subargs);\r
+ break;\r
default:\r
throw new \Asika\SimpleConsole\CommandArgsException('Command ' . $command . ' doesn\'t exist');\r
}\r
--- /dev/null
+<?php\r
+\r
+namespace Friendica\Core\Console;\r
+\r
+/**\r
+ * Extracts translation strings from the Friendica project's files to be exported\r
+ * to Transifex for translation.\r
+ *\r
+ * Outputs a PHP file with language strings used by Friendica\r
+ *\r
+ * @author Hypolite Petovan <mrpetovan@gmail.com>\r
+ */\r
+class Extract extends \Asika\SimpleConsole\Console\r
+{\r
+ protected $helpOptions = ['h', 'help', '?'];\r
+\r
+ protected function getHelp()\r
+ {\r
+ $help = <<<HELP\r
+console extract - Generate translation string file for the Friendica project (deprecated)\r
+Usage\r
+ bin/console extract [-h|--help|-?] [-v]\r
+\r
+Description\r
+ This script was used to generate the translation string file to be exported to Transifex,\r
+ please use bin/run_xgettext.sh instead\r
+\r
+Options\r
+ -h|--help|-? Show help information\r
+ -v Show more debug information.\r
+HELP;\r
+ return $help;\r
+ }\r
+\r
+ protected function doExecute()\r
+ {\r
+ if ($this->getOption('v')) {\r
+ $this->out('Class: ' . __CLASS__);\r
+ $this->out('Arguments: ' . var_export($this->args, true));\r
+ $this->out('Options: ' . var_export($this->options, true));\r
+ }\r
+\r
+ if (count($this->args) > 0) {\r
+ throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');\r
+ }\r
+\r
+ $s = '<?php' . PHP_EOL;\r
+ $s .= '\r
+ function string_plural_select($n){\r
+ return ($n != 1);\r
+ }\r
+\r
+ ';\r
+\r
+ $arr = [];\r
+\r
+ $files = array_merge(\r
+ ['index.php', 'boot.php'],\r
+ glob('mod/*'),\r
+ glob('include/*'),\r
+ glob('addon/*/*'),\r
+ $this->globRecursive('src')\r
+ );\r
+\r
+ foreach ($files as $file) {\r
+ $str = file_get_contents($file);\r
+\r
+ $pat = '|L10n::t\(([^\)]*+)[\)]|';\r
+ $patt = '|L10n::tt\(([^\)]*+)[\)]|';\r
+\r
+ $matches = [];\r
+ $matchestt = [];\r
+\r
+ preg_match_all($pat, $str, $matches);\r
+ preg_match_all($patt, $str, $matchestt);\r
+\r
+ if (count($matches) || count($matchestt)) {\r
+ $s .= '// ' . $file . PHP_EOL;\r
+ }\r
+\r
+ if (!empty($matches[1])) {\r
+ foreach ($matches[1] as $long_match) {\r
+ $match_arr = preg_split('/(?<=[\'"])\s*,/', $long_match);\r
+ $match = $match_arr[0];\r
+ if (!in_array($match, $arr)) {\r
+ if (substr($match, 0, 1) == '$') {\r
+ continue;\r
+ }\r
+\r
+ $arr[] = $match;\r
+\r
+ $s .= '$a->strings[' . $match . '] = ' . $match . ';' . "\n";\r
+ }\r
+ }\r
+ }\r
+ if (!empty($matchestt[1])) {\r
+ foreach ($matchestt[1] as $match) {\r
+ $matchtkns = preg_split("|[ \t\r\n]*,[ \t\r\n]*|", $match);\r
+ if (count($matchtkns) == 3 && !in_array($matchtkns[0], $arr)) {\r
+ if (substr($matchtkns[1], 0, 1) == '$') {\r
+ continue;\r
+ }\r
+\r
+ $arr[] = $matchtkns[0];\r
+\r
+ $s .= '$a->strings[' . $matchtkns[0] . "] = array(\n";\r
+ $s .= "\t0 => " . $matchtkns[0] . ",\n";\r
+ $s .= "\t1 => " . $matchtkns[1] . ",\n";\r
+ $s .= ");\n";\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ $s .= '// Timezones' . PHP_EOL;\r
+\r
+ $zones = timezone_identifiers_list();\r
+ foreach ($zones as $zone) {\r
+ $s .= '$a->strings[\'' . $zone . '\'] = \'' . $zone . '\';' . "\n";\r
+ }\r
+\r
+ $this->out($s);\r
+\r
+ return 0;\r
+ }\r
+\r
+ private function globRecursive($path) {\r
+ $dir_iterator = new \RecursiveDirectoryIterator($path);\r
+ $iterator = new \RecursiveIteratorIterator($dir_iterator, \RecursiveIteratorIterator::SELF_FIRST);\r
+\r
+ $return = [];\r
+ foreach ($iterator as $file) {\r
+ if ($file->getBasename() != '.' && $file->getBasename() != '..') {\r
+ $return[] = $file->getPathname();\r
+ }\r
+ }\r
+\r
+ return $return;\r
+ }\r
+}\r
--- /dev/null
+<?php\r
+\r
+namespace Friendica\Core\Console;\r
+\r
+use Friendica\Core\Protocol;\r
+use Friendica\Database\DBM;\r
+use Friendica\Network\Probe;\r
+\r
+require_once 'include/text.php';\r
+\r
+/**\r
+ * @brief tool to silence accounts on the global community page\r
+ *\r
+ * With this tool, you can silence an account on the global community page.\r
+ * Postings from silenced accounts will not be displayed on the community\r
+ * page. This silencing does only affect the display on the community page,\r
+ * accounts following the silenced accounts will still get their postings.\r
+ *\r
+ * License: AGPLv3 or later, same as Friendica\r
+ *\r
+ * @author Tobias Diekershoff\r
+ * @author Hypolite Petovan <mrpetovan@gmail.com>\r
+ */\r
+class GlobalCommunitySilence extends \Asika\SimpleConsole\Console\r
+{\r
+ protected $helpOptions = ['h', 'help', '?'];\r
+\r
+ protected function getHelp()\r
+ {\r
+ $help = <<<HELP\r
+console globalcommunitysilence - Silence remote profile from global community page\r
+Usage\r
+ bin/console globalcommunitysilence <profile_url> [-h|--help|-?] [-v]\r
+\r
+Description\r
+ With this tool, you can silence an account on the global community page.\r
+ Postings from silenced accounts will not be displayed on the community page.\r
+ This silencing does only affect the display on the community page, accounts\r
+ following the silenced accounts will still get their postings.\r
+\r
+Options\r
+ -h|--help|-? Show help information\r
+ -v Show more debug information.\r
+HELP;\r
+ return $help;\r
+ }\r
+\r
+ protected function doExecute()\r
+ {\r
+ if ($this->getOption('v')) {\r
+ $this->out('Class: ' . __CLASS__);\r
+ $this->out('Arguments: ' . var_export($this->args, true));\r
+ $this->out('Options: ' . var_export($this->options, true));\r
+ }\r
+\r
+ if (count($this->args) == 0) {\r
+ $this->out($this->getHelp());\r
+ return 0;\r
+ }\r
+\r
+ if (count($this->args) > 1) {\r
+ throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');\r
+ }\r
+\r
+ require_once '.htconfig.php';\r
+ $result = \dba::connect($db_host, $db_user, $db_pass, $db_data);\r
+ unset($db_host, $db_user, $db_pass, $db_data);\r
+\r
+ if (!$result) {\r
+ throw new \RuntimeException('Unable to connect to database');\r
+ }\r
+\r
+ /**\r
+ * 1. make nurl from last parameter\r
+ * 2. check DB (contact) if there is a contact with uid=0 and that nurl, get the ID\r
+ * 3. set the flag hidden=1 for the contact entry with the found ID\r
+ * */\r
+ $net = Probe::uri($this->getArgument(0));\r
+ if (in_array($net['network'], [Protocol::PHANTOM, Protocol::MAIL])) {\r
+ throw new \RuntimeException('This account seems not to exist.');\r
+ }\r
+\r
+ $nurl = normalise_link($net['url']);\r
+ $contact = \dba::selectFirst("contact", ["id"], ["nurl" => $nurl, "uid" => 0]);\r
+ if (DBM::is_result($contact)) {\r
+ \dba::update("contact", ["hidden" => true], ["id" => $contact["id"]]);\r
+ $this->out('NOTICE: The account should be silenced from the global community page');\r
+ } else {\r
+ throw new \RuntimeException('NOTICE: Could not find any entry for this URL (' . $nurl . ')');\r
+ }\r
+\r
+ return 0;\r
+ }\r
+}\r
--- /dev/null
+<?php\r
+\r
+namespace Friendica\Core\Console;\r
+\r
+use Friendica\Core;\r
+\r
+require_once 'boot.php';\r
+require_once 'include/dba.php';\r
+\r
+/**\r
+ * @brief tool to silence accounts on the global community page\r
+ *\r
+ * With this tool, you can silence an account on the global community page.\r
+ * Postings from silenced accounts will not be displayed on the community\r
+ * page. This silencing does only affect the display on the community page,\r
+ * accounts following the silenced accounts will still get their postings.\r
+ *\r
+ * Usage: pass the URL of the profile to be silenced account as only parameter\r
+ * at the command line when running this tool. E.g.\r
+ *\r
+ * $> util/global_community_silence.php http://example.com/profile/bob\r
+ *\r
+ * will silence bob@example.com so that his postings won't appear at\r
+ * the global community page.\r
+ *\r
+ * License: AGPLv3 or later, same as Friendica\r
+ *\r
+ * @author Tobias Diekershoff\r
+ * @author Hypolite Petovan <mrpetovan@gmail.com>\r
+ */\r
+class Maintenance extends \Asika\SimpleConsole\Console\r
+{\r
+ protected $helpOptions = ['h', 'help', '?'];\r
+\r
+ protected function getHelp()\r
+ {\r
+ $help = <<<HELP\r
+console maintenance - Sets maintenance mode for this node\r
+Usage\r
+ bin/console maintenance <enable> [<reason>] [-h|--help|-?] [-v]\r
+\r
+Description\r
+ <enable> cen be either 0 or 1 to disabled or enable the maintenance mode on this node.\r
+\r
+ <reason> is a quote-enclosed string with the optional reason for the maintenance mode.\r
+\r
+Examples\r
+ bin/console maintenance 1\r
+ Enables the maintenance mode without setting a reason message\r
+\r
+ bin/console maintenance 1 "SSL certification update"\r
+ Enables the maintenance mode with setting a reason message\r
+\r
+ bin/console maintenance 0\r
+ Disables the maintenance mode\r
+\r
+Options\r
+ -h|--help|-? Show help information\r
+ -v Show more debug information.\r
+HELP;\r
+ return $help;\r
+ }\r
+\r
+ protected function doExecute()\r
+ {\r
+ if ($this->getOption('v')) {\r
+ $this->out('Class: ' . __CLASS__);\r
+ $this->out('Arguments: ' . var_export($this->args, true));\r
+ $this->out('Options: ' . var_export($this->options, true));\r
+ }\r
+\r
+ if (count($this->args) == 0) {\r
+ $this->out($this->getHelp());\r
+ return 0;\r
+ }\r
+\r
+ if (count($this->args) > 2) {\r
+ throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');\r
+ }\r
+\r
+ require_once '.htconfig.php';\r
+ $result = \dba::connect($db_host, $db_user, $db_pass, $db_data);\r
+ unset($db_host, $db_user, $db_pass, $db_data);\r
+\r
+ if (!$result) {\r
+ throw new \RuntimeException('Unable to connect to database');\r
+ }\r
+\r
+ Core\Config::load();\r
+\r
+ $lang = Core\L10n::getBrowserLanguage();\r
+ Core\L10n::loadTranslationTable($lang);\r
+\r
+ $enabled = intval($this->getArgument(0));\r
+\r
+ Core\Config::set('system', 'maintenance', $enabled);\r
+\r
+ $reason = $this->getArgument(1);\r
+\r
+ if ($enabled && $this->getArgument(1)) {\r
+ Core\Config::set('system', 'maintenance_reason', $this->getArgument(1));\r
+ } else {\r
+ Core\Config::set('system', 'maintenance_reason', '');\r
+ }\r
+\r
+ if ($enabled) {\r
+ $mode_str = "maintenance mode";\r
+ } else {\r
+ $mode_str = "normal mode";\r
+ }\r
+\r
+ $this->out('System set in ' . $mode_str);\r
+\r
+ if ($enabled && $reason != '') {\r
+ $this->out('Maintenance reason: ' . $reason);\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+}\r
--- /dev/null
+<?php\r
+\r
+namespace Friendica\Core\Console;\r
+\r
+/**\r
+ * Read a strings.php file and create messages.po in the same directory\r
+ *\r
+ * @author Hypolite Petovan <mrpetovan@gmail.com>\r
+ */\r
+class PhpToPo extends \Asika\SimpleConsole\Console\r
+{\r
+\r
+ protected $helpOptions = ['h', 'help', '?'];\r
+\r
+ private $normBaseMsgIds = [];\r
+ const NORM_REGEXP = "|[\\\]|";\r
+\r
+ protected function getHelp()\r
+ {\r
+ $help = <<<HELP\r
+console php2po - Generate a messages.po file from a string.php file\r
+Usage\r
+ bin/console php2po [-p <n>] <path/to/strings.php> [-h|--help|-?] [-v]\r
+\r
+Options:\r
+ -p <n> Number of plural forms/ Default: 2\r
+\r
+Description\r
+ Read a strings.php file and create the according messages.po in the same directory\r
+\r
+Options\r
+ -h|--help|-? Show help information\r
+ -v Show more debug information.\r
+HELP;\r
+ return $help;\r
+ }\r
+\r
+ protected function doExecute()\r
+ {\r
+ if ($this->getOption('v')) {\r
+ $this->out('Class: ' . __CLASS__);\r
+ $this->out('Arguments: ' . var_export($this->args, true));\r
+ $this->out('Options: ' . var_export($this->options, true));\r
+ }\r
+\r
+ if (count($this->args) == 0) {\r
+ $this->out($this->getHelp());\r
+ return 0;\r
+ }\r
+\r
+ if (count($this->args) > 1) {\r
+ throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');\r
+ }\r
+\r
+ $a = get_app();\r
+\r
+ $phpfile = realpath($this->getArgument(0));\r
+\r
+ if (!file_exists($phpfile)) {\r
+ throw new \RuntimeException('Supplied file path doesn\'t exist.');\r
+ }\r
+\r
+ if (!is_writable(dirname($phpfile))) {\r
+ throw new \RuntimeException('Supplied directory isn\'t writable.');\r
+ }\r
+\r
+ $pofile = dirname($phpfile) . '/messages.po';\r
+\r
+ // start !\r
+ include_once($phpfile);\r
+\r
+ $out = '';\r
+ $out .= "# FRIENDICA Distributed Social Network\n";\r
+ $out .= "# Copyright (C) 2010, 2011, 2012, 2013 the Friendica Project\n";\r
+ $out .= "# This file is distributed under the same license as the Friendica package.\n";\r
+ $out .= "# \n";\r
+ $out .= 'msgid ""' . "\n";\r
+ $out .= 'msgstr ""' . "\n";\r
+ $out .= '"Project-Id-Version: friendica\n"' . "\n";\r
+ $out .= '"Report-Msgid-Bugs-To: \n"' . "\n";\r
+ $out .= '"POT-Creation-Date: ' . date("Y-m-d H:i:sO") . '\n"' . "\n";\r
+ $out .= '"MIME-Version: 1.0\n"' . "\n";\r
+ $out .= '"Content-Type: text/plain; charset=UTF-8\n"' . "\n";\r
+ $out .= '"Content-Transfer-Encoding: 8bit\n"' . "\n";\r
+\r
+ // search for plural info\r
+ $lang = "";\r
+ $lang_logic = "";\r
+ $lang_pnum = 2;\r
+\r
+ $_idx = array_search('-p', $argv);\r
+ if ($_idx !== false) {\r
+ $lang_pnum = $argv[$_idx + 1];\r
+ }\r
+\r
+ $infile = file($phpfile);\r
+ foreach ($infile as $l) {\r
+ $l = trim($l);\r
+ if ($this->startsWith($l, 'function string_plural_select_')) {\r
+ $lang = str_replace('function string_plural_select_', '', str_replace('($n){', '', $l));\r
+ }\r
+ if ($this->startsWith($l, 'return')) {\r
+ $lang_logic = str_replace('$', '', trim(str_replace('return ', '', $l), ';'));\r
+ break;\r
+ }\r
+ }\r
+\r
+ $this->out('Language: ' . $lang);\r
+ $this->out('Plural forms: ' . $lang_pnum);\r
+ $this->out('Plural forms: ' . $lang_logic);\r
+\r
+ $out .= sprintf('"Language: %s\n"', $lang) . "\n";\r
+ $out .= sprintf('"Plural-Forms: nplurals=%s; plural=%s;\n"', $lang_pnum, $lang_logic) . "\n";\r
+ $out .= "\n";\r
+\r
+ $this->out('Loading base message.po...');\r
+\r
+ // load base messages.po and extract msgids\r
+ $base_msgids = [];\r
+ $base_f = file("util/messages.po");\r
+ if (!$base_f) {\r
+ throw new \RuntimeException('The base util/messages.po file is missing.');\r
+ }\r
+\r
+ $_f = 0;\r
+ $_mid = "";\r
+ $_mids = [];\r
+ foreach ($base_f as $l) {\r
+ $l = trim($l);\r
+\r
+ if ($this->startsWith($l, 'msgstr')) {\r
+ if ($_mid != '""') {\r
+ $base_msgids[$_mid] = $_mids;\r
+ $this->normBaseMsgIds[preg_replace(self::NORM_REGEXP, "", $_mid)] = $_mid;\r
+ }\r
+\r
+ $_f = 0;\r
+ $_mid = "";\r
+ $_mids = [];\r
+ }\r
+\r
+ if ($this->startsWith($l, '"') && $_f == 2) {\r
+ $_mids[count($_mids) - 1] .= "\n" . $l;\r
+ }\r
+ if ($this->startsWith($l, 'msgid_plural ')) {\r
+ $_f = 2;\r
+ $_mids[] = str_replace('msgid_plural ', '', $l);\r
+ }\r
+\r
+ if ($this->startsWith($l, '"') && $_f == 1) {\r
+ $_mid .= "\n" . $l;\r
+ $_mids[count($_mids) - 1] .= "\n" . $l;\r
+ }\r
+ if ($this->startsWith($l, 'msgid ')) {\r
+ $_f = 1;\r
+ $_mid = str_replace('msgid ', '', $l);\r
+ $_mids = [$_mid];\r
+ }\r
+ }\r
+\r
+ $this->out('Done.');\r
+ $this->out('Creating ' . $pofile . '...');\r
+\r
+ // create msgid and msgstr\r
+ $warnings = "";\r
+ foreach ($a->strings as $key => $str) {\r
+ $msgid = $this->massageString($key);\r
+\r
+ if (preg_match("|%[sd0-9](\$[sn])*|", $msgid)) {\r
+ $out .= "#, php-format\n";\r
+ }\r
+ $msgid = $this->findOriginalMsgId($msgid);\r
+ $out .= 'msgid ' . $msgid . "\n";\r
+\r
+ if (is_array($str)) {\r
+ if (array_key_exists($msgid, $base_msgids) && isset($base_msgids[$msgid][1])) {\r
+ $out .= 'msgid_plural ' . $base_msgids[$msgid][1] . "\n";\r
+ } else {\r
+ $out .= 'msgid_plural ' . $msgid . "\n";\r
+ $warnings .= "[W] No source plural form for msgid:\n" . str_replace("\n", "\n\t", $msgid) . "\n\n";\r
+ }\r
+ foreach ($str as $n => $msgstr) {\r
+ $out .= 'msgstr[' . $n . '] ' . $this->massageString($msgstr) . "\n";\r
+ }\r
+ } else {\r
+ $out .= 'msgstr ' . $this->massageString($str) . "\n";\r
+ }\r
+\r
+ $out .= "\n";\r
+ }\r
+\r
+ file_put_contents($pofile, $out);\r
+\r
+ $this->out('Done.');\r
+\r
+ if ($warnings == "") {\r
+ $this->out('No warnings.');\r
+ } else {\r
+ $this->out($warnings);\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+ private function startsWith($haystack, $needle)\r
+ {\r
+ // search backwards starting from haystack length characters from the end\r
+ return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE;\r
+ }\r
+\r
+ /**\r
+ * Get a string and retun a message.po ready text\r
+ * - replace " with \"\r
+ * - replace tab char with \t\r
+ * - manage multiline strings\r
+ */\r
+ private function massageString($str)\r
+ {\r
+ $str = str_replace('\\', '\\\\', $str);\r
+ $str = str_replace('"', '\"', $str);\r
+ $str = str_replace("\t", '\t', $str);\r
+ $str = str_replace("\n", '\n"' . "\n" . '"', $str);\r
+ if (strpos($str, "\n") !== false && $str[0] !== '"') {\r
+ $str = '"' . "\n" . $str;\r
+ }\r
+\r
+ $str = preg_replace("|\n([^\"])|", "\n\"$1", $str);\r
+ return sprintf('"%s"', $str);\r
+ }\r
+\r
+ private function findOriginalMsgId($str)\r
+ {\r
+ $norm_str = preg_replace(self::NORM_REGEXP, "", $str);\r
+ if (array_key_exists($norm_str, $this->normBaseMsgIds)) {\r
+ return $this->normBaseMsgIds[$norm_str];\r
+ }\r
+\r
+ return $str;\r
+ }\r
+\r
+}\r