[web-doc] master: 1. Doc-base revcheck.php code injected and database production accelerated:

From: Date: Sun, 16 May 2021 21:45:46 +0000
Subject: [web-doc] master: 1. Doc-base revcheck.php code injected and database production accelerated:
Groups: php.doc.web 
Request: Send a blank email to doc-web+get-2468@lists.php.net to get a copy of this message
Author: Nilgün Belma Bugüner (nilgun) Date: 2021-05-17T00:45:45+03:00 Commit: https://github.com/php/web-doc/commit/4725e3bd17986aa84356fc41a11db60f2447cead Raw diff: https://github.com/php/web-doc/commit/4725e3bd17986aa84356fc41a11db60f2447cead.diff 1. Doc-base revcheck.php code injected and database production accelerated: dropped from 15 minutes to 2.5 seconds. 2. As in new Doc-base revcheck.php, more detailed and more accurate information is given to the teams. 3. Indentation fixed. Changed paths: M README.md M include/lib_revcheck.inc.php M scripts/gen_picture_info.php M scripts/rev.php M www/revcheck.php Diff: diff --git a/README.md b/README.md index b6cc21e..2de9e44 100644 --- a/README.md +++ b/README.md @@ -12,19 +12,19 @@ Requirements: 1. Unpack a copy of JpGraph 3.0.7 into /include/jpgraph/ ([here](http://jpgraph.net/download/download.php?p=1)) 2. Increase memory limit for PHP scripts to at least 32MB 3. Fill in two configuration files - - build-ops.php.sample (rename it to build-ops.php) - - @GITDIR@ - absolute path to dir where scripts will clone SVN repos to and then use them for generating data - - @SQLITEDIR@ - absolute path to /sqlite/ directory - - build-ops.sample (rename it to build-ops [no ext]) - - @PHP@ - path to the PHP executable file - - @GITDIR@ - absolute path to dir where scripts will clone SVN repos to and then use them and then use it for generating data - - @DOCWEB@ - absolute path to /www/ directory - - @PHDDIR@ - absolute path to directory with PhD installed from Git master - - @SCRIPTSDIR@- absolute path to /scripts/ directory - - @SQLITEDIR@ - absolute path to /sqlite/ directory - - @SRCDIR@ - path to the directory with PHP source code in SVN repo +- build-ops.php.sample (rename it to build-ops.php) +- @GITDIR@ - absolute path to dir where scripts will clone GIT repos to and then use them for generating data +- @SQLITEDIR@ - absolute path to /sqlite/ directory +- build-ops.sample (rename it to build-ops [no ext]) +- @PHP@ - path to the PHP executable file +- @GITDIR@ - absolute path to dir where scripts will clone SVN repos to and then use them and then use it for generating data +- @DOCWEB@ - absolute path to /www/ directory +- @PHDDIR@ - absolute path to directory with PhD installed from Git master +- @SCRIPTSDIR@- absolute path to /scripts/ directory +- @SQLITEDIR@ - absolute path to /sqlite/ directory +- @SRCDIR@ - path to the directory with PHP source code in GIT repo 4. You need to run the scripts/populatedocs.sh to fetch all the required documentation for the site. -6. You need to run the scripts/generation.sh to generate the database and graphs (Time of generation: 921.84918999672 s) +6. You need to run the scripts/generation.sh to generate the database and graphs (Time of generation: 2.5009639263153 s) 7. Configure the virtual host under Apache. Current suggested settings are: ``` <VirtualHost 127.0.0.1:80> diff --git a/include/lib_revcheck.inc.php b/include/lib_revcheck.inc.php index fa7eb72..72d5237 100644 --- a/include/lib_revcheck.inc.php +++ b/include/lib_revcheck.inc.php @@ -26,23 +26,16 @@ function get_dirs($idx, $lang) { b.path AS dir, a.name AS name FROM - files a, - dirs b, - enfiles c + translated a, + dirs b WHERE - a.lang= '$lang' - AND - a.id = b.id - AND - c.id = a.id - AND - a.name = c.name - AND - a.revision != c.revision - AND - a.revision != 'n/a' + a.lang = '$lang' + AND a.id = b.id + AND (a.syncStatus = 'TranslatedOld' + OR a.syncStatus = 'TranslatedCritial' + OR a.syncStatus = 'TranslatedWip') ORDER BY - b.path"; + b.id"; $result = $idx->query($sql); @@ -58,10 +51,12 @@ function get_dirs($idx, $lang) { function get_outdated_files($idx, $lang, $filter = null, $value = null) { $sql = "SELECT a.status, a.name AS file, a.maintainer, c.revision AS en_rev, a.revision AS trans_rev, b.path AS dir - FROM files a, dirs b, enfiles c + FROM translated a, dirs b, enfiles c WHERE a.lang = '$lang' - AND a.revision != c.revision AND a.revision != 'n/a' - AND c.name = a.name AND c.id = a.id AND b.id = a.id"; + AND c.name = a.name AND c.id = a.id AND b.id = a.id + AND (a.syncStatus = 'TranslatedOld' + OR a.syncStatus = 'TranslatedCritial' + OR a.syncStatus = 'TranslatedWip')"; if ($filter == 'dir') { $sql .= " AND b.path = '$value'"; @@ -90,7 +85,7 @@ function get_outdated_files($idx, $lang, $filter = null, $value = null) // Return an array of available languages for manual function revcheck_available_languages($idx) { - $result = $idx->query('SELECT lang FROM description'); + $result = $idx->query('SELECT lang FROM descriptions'); while ($row = $result->fetchArray(SQLITE3_NUM)) { $tmp[] = $row[0]; } @@ -110,24 +105,23 @@ function count_en_files($idx) function get_missfiles($idx, $lang) { - $sql = 'SELECT + $sql = "SELECT d.path as dir, - b.size as size, + a.name as file, b.revision as revision, - a.name as file + a.size as size FROM - utfiles a, + Untranslated a, + enfiles b, dirs d - LEFT JOIN - enfiles b - ON - a.id = b.id + WHERE + a.lang = '$lang' AND a.name = b.name - WHERE - a.lang="' . $lang . '" AND - a.id = d.id'; + a.id = b.id + AND + a.id = d.id"; $result = $idx->query($sql); while ($r = $result->fetchArray()) { @@ -139,38 +133,26 @@ function get_missfiles($idx, $lang) function get_oldfiles($idx, $lang) { - $sql = 'SELECT - path, file, size - - FROM - old_files - - WHERE - lang="' . $lang . '"'; + $sql = "SELECT path, name, size + FROM notinen + WHERE lang = '$lang'"; $result = $idx->query($sql); - $tmp = array(); - $special_files = array( - 'translation.xml'=>1, - ); while ($r = $result->fetchArray()) { - if (isset($special_files[$r['file']])) continue; // skip some files - $tmp[] = array('dir' => $r['path'], 'size' => $r['size'], 'file' => $r['file']); + $tmp[] = array('dir' => $r['path'], 'size' => $r['size'], 'file' => $r['name']); } return $tmp; } function get_misstags($idx, $lang) { - $sql = 'SELECT - d.path AS dir, a.size AS en_size, b.size AS trans_size, a.name AS name - FROM enfiles a, dirs d - LEFT JOIN files b ON a.id = b.id AND a.name = b.name AND a.id = d.id - WHERE b.lang="'.$lang.'" AND (b.revision IS NULL OR b.revision = "n/a") - AND b.size IS NOT NULL - ORDER BY dir, name'; + $sql = "SELECT d.path AS dir, a.size AS en_size, b.size AS trans_size, a.name AS name + FROM enfiles a, translated b, dirs d + WHERE b.lang = '$lang' AND b.syncStatus = 'RevTagProblem' + AND a.id = b.id AND a.name = b.name AND a.id = d.id + ORDER BY dir, name"; $tmp = NULL; $result = $idx->query($sql); while($row = $result->fetchArray()) { @@ -190,29 +172,22 @@ function get_misstags($idx, $lang) */ function get_translators_stats($idx, $lang, $status) { if ($status == 'wip') { // special case, ehh; does anyone still use this status? - $sql = "SELECT COUNT(name) AS total, person AS maintainer - FROM wip + $sql = "SELECT files_wip AS total, nick AS maintainer + FROM translators + WHERE lang = '$lang' + GROUP BY maintainer"; + } elseif ($status == 'uptodate') { + $sql = "SELECT files_uptodate AS total, nick AS maintainer + FROM translators + WHERE lang = '$lang' + GROUP BY maintainer"; + } elseif ($status == 'outdated') { + $sql = "SELECT files_outdated AS total, nick AS maintainer + FROM translators WHERE lang = '$lang' GROUP BY maintainer"; } - else { - $sql = "SELECT COUNT(a.name) AS total, a.maintainer - FROM files a - LEFT JOIN enfiles b ON a.name = b.name AND a.id = b.id - WHERE a.lang = '$lang' AND a.size IS NOT NULL AND "; - - if ($status == 'uptodate') { - $sql .= 'a.revision = b.revision'; - } - elseif ($status == 'outdated') { - $sql .= 'b.revision != a.revision'; - } - - $sql .= ' GROUP BY a.maintainer'; - } - $result = $idx->query($sql); - $tmp = array(); while ($r = $result->fetchArray()) { $tmp[$r['maintainer']] = $r['total']; @@ -223,11 +198,11 @@ function get_translators_stats($idx, $lang, $status) { function get_translators($idx, $lang) { - $sql = "SELECT nick, name, mail, karma FROM translators WHERE lang = '$lang' ORDER BY nick COLLATE NOCASE"; + $sql = "SELECT nick, name, mail, vcs FROM translators WHERE lang = '$lang' ORDER BY nick COLLATE NOCASE"; $persons = array(); $result = $idx->query($sql); while ($r = $result->fetchArray()) { - $persons[$r['nick']] = array('name' => $r['name'], 'mail' => $r['mail'], 'karma' => $r['karma']); + $persons[$r['nick']] = array('name' => $r['name'], 'mail' => $r['mail'], 'karma' => $r['vcs']); } return $persons; } @@ -242,33 +217,32 @@ function get_translators($idx, $lang) * @return array */ function get_stats($idx, $lang, $status) { - if ($status == 'wip') { // special case, ehh; does anyone still use this status? - $sql = "SELECT COUNT(*) AS total, 0 AS size - FROM files a, dirs b, enfiles c - WHERE lang = '$lang' AND a.status ='wip' AND b.id = a.id AND b.id = c.id AND a.name = c.name"; - } - elseif ($status == 'notrans') { - $sql = "SELECT COUNT(a.name) AS total, SUM(c.size) AS size FROM utfiles a, dirs b, enfiles c WHERE a.lang = '$lang' AND b.id = a.id AND b.id = c.id AND a.name = c.name"; - } - else { - $sql = "SELECT COUNT(a.name) AS total, SUM(b.size) AS size - FROM enfiles a - LEFT JOIN files b ON a.name = b.name AND a.id = b.id - WHERE b.lang = '$lang' AND "; + if ($status == 'wip') { + $sql = "SELECT COUNT(name) AS total, SUM(size) AS size + FROM wip + WHERE lang = '$lang' "; + } elseif ($status == 'notrans') { + $sql = "SELECT COUNT(name) AS total, SUM(size) AS size + FROM Untranslated + WHERE lang = '$lang'"; + } elseif ($status == 'uptodate') { + $sql = "SELECT COUNT(name) AS total, SUM(size) AS size + FROM translated + WHERE lang = '$lang' AND syncStatus = 'TranslatedOk'"; + } elseif ($status == 'outdated') { + $sql = "SELECT COUNT(name) AS total, SUM(size) AS size + FROM translated + WHERE lang = '$lang' AND syncStatus = 'TranslatedOld'"; + } elseif ($status == 'norev') { + $sql = "SELECT COUNT(name) AS total, SUM(size) AS size + FROM translated + WHERE lang = '$lang' AND syncStatus = 'RevTagProblem'"; + } else { //notinen + $sql = "SELECT COUNT(name) AS total, SUM(size) AS size + FROM notinen WHERE lang = '$lang'"; - if ($status == 'uptodate') { - $sql .= 'a.revision = b.revision'; - } - elseif ($status == 'outdated') { - $sql .= 'b.revision != a.revision AND a.revision != "n/a" AND a.size IS NOT NULL'; - } - elseif ($status == 'norev') { - $sql .= '(a.revision IS NULL OR a.revision = "n/a") AND a.size IS NOT NULL'; - } } - $result = $idx->query($sql)->fetchArray(); - return array($result['total'], $result['size']); } diff --git a/scripts/gen_picture_info.php b/scripts/gen_picture_info.php index c655908..c43a9f6 100644 --- a/scripts/gen_picture_info.php +++ b/scripts/gen_picture_info.php @@ -59,7 +59,7 @@ function generate_image($lang, $idx) { $legend = array($percent[0] . '%% up to date ('.$up_to_date.')', $percent[1] . '%% outdated ('.$outdated.')', $percent[2] . '%% missing ('.$missing.')', $percent[3] . '%% without EN-Revision ('.$no_tag.')'); $title = 'Details for '.$LANGUAGES[$lang].' PHP Manual'; - $graph = new PieGraph(630,400); + $graph = new PieGraph(680,300); $graph->SetShadow(); $graph->title->Set($title); diff --git a/scripts/rev.php b/scripts/rev.php index 2b56088..fd5ea34 100644 --- a/scripts/rev.php +++ b/scripts/rev.php @@ -23,7 +23,6 @@ | Maciej Sobaczewski <sobak at php dot net> | +----------------------------------------------------------------------+ */ - error_reporting(E_ALL); set_time_limit(0); @@ -49,7 +48,7 @@ $CREATE = <<<SQL -CREATE TABLE description ( +CREATE TABLE descriptions ( lang TEXT, intro TEXT, UNIQUE (lang) @@ -60,398 +59,404 @@ nick TEXT, name TEXT, mail TEXT, - karma TEXT, - editor TEXT, + vcs TEXT, + files_uptodate INT, + files_outdated INT, + files_wip INT, + files_sum INT, + files_other INT, UNIQUE (lang, nick) ); -CREATE TABLE wip ( +CREATE TABLE translated ( + id INT, lang TEXT, name TEXT, - person TEXT, - type TEXT + revision TEXT, + size INT, + maintainer TEXT, + status TEXT, + syncStatus TEXT, + UNIQUE(lang, id, name) ); +CREATE INDEX translated_1 ON translated (lang, id, name); + CREATE TABLE dirs ( id INT, path TEXT, UNIQUE (path) ); -CREATE INDEX dirs_1 ON dirs (id); +CREATE INDEX dirs_1 ON dirs (path); CREATE TABLE enfiles ( id INT, name TEXT, revision TEXT, - size TEXT, - mdate TEXT, + size INT, UNIQUE(id, name) ); CREATE INDEX enfiles_1 ON enfiles (id, name); -CREATE TABLE files ( +CREATE TABLE Untranslated ( id INT, lang TEXT, name TEXT, - revision TEXT, - size TEXT, - mdate TEXT, - maintainer TEXT, - status TEXT, + size INT, UNIQUE(lang, id, name) ); -CREATE INDEX files_1 ON files (lang, id, name, revision); -CREATE INDEX files_2 ON files (lang, id, name, mdate, revision); -CREATE INDEX files_3 ON files (lang, id, name, maintainer, mdate, revision); +CREATE INDEX Untrans_1 ON Untranslated (lang, id, name); -CREATE TABLE utfiles ( - id INT, +CREATE TABLE notinen ( lang TEXT, + path TEXT, name TEXT, - UNIQUE(lang, id, name) + size INT, + UNIQUE(lang, path, name) ); -CREATE TABLE old_files ( +CREATE INDEX notinen_1 ON notinen (lang, path, name); + +CREATE TABLE wip ( + id INT, lang TEXT, - path TEXT, - file TEXT, - size INT + name TEXT, + size INT, + person TEXT ); SQL; -$SQL_BUFF = "INSERT INTO dirs VALUES (1, '/');\n"; +$SQL_BUFF = ""; -/** -* Functions -**/ +$enFiles = populateFileTree( 'en' ); +captureGitValues( $gitData ); +foreach ($LANGS as $lang){ + $trFiles[$lang] = populateFileTree( $lang ); +} -function parse_translation($lang) +class FileStatusInfo { - global $SQL_BUFF, $DOCS, $LANGUAGES; - echo "Parsing intro..\n"; - - // Path to find translation.xml file, set default values, - // in case we can't find the translation file - $translation_xml = $DOCS . $lang . "/translation.xml"; - - $intro = "No intro available for the {$LANGUAGES[$lang]} translation of the manual."; - $charset = 'utf-8'; + public $path; + public $name; + public $size; + public $hash; + public $syncStatus; + public $maintainer; + public $completion; + public $credits; + + public function getKey() + { + return trim( $this->path . '/' . $this->name , '/' ); + } +} - if (file_exists($translation_xml)) { - // Else go on, and load in the file, replacing all - // space type chars with one space - $txml = join("", file($translation_xml)); - $txml = preg_replace("/\\s+/", " ", $txml); - - // Get encoding for the output, from the translation.xml - // file encoding (should be the same as the used encoding - // in HTML) - if (preg_match("!<\?xml(.+)\?>!U", $txml, $match)) { - $xmlinfo = parse_attr_string($match); - if (isset($xmlinfo[1]["encoding"])) { - $charset = $xmlinfo[1]["encoding"]; - } - } +class FileStatusEnum +{ + const Untranslated = 'Untranslated'; + const RevTagProblem = 'RevTagProblem'; + const TranslatedWip = 'TranslatedWip'; + const TranslatedOk = 'TranslatedOk'; + const TranslatedOld = 'TranslatedOld'; + const TranslatedCritial = 'TranslatedCritial'; + const NotInEnTree = 'NotInEnTree'; +} - // Get intro text - if (preg_match("!<intro>(.+)</intro>!s", $txml, $match)) { - $intro = SQLite3::escapeString(@iconv($charset, 'UTF-8//IGNORE', trim($match[1]))); - } +class TranslatorInfo +{ + public $name; + public $email; + public $nick; + public $vcs; + + public $files_uptodate; + public $files_outdated; + public $files_wip; + public $files_sum; + public $files_other; + + public function __construct() { + $this->files_uptodate = 0; + $this->files_outdated = 0; + $this->files_wip = 0; + $this->files_sum = 0; + $this->files_other = 0; } - $SQL_BUFF .= "INSERT INTO description VALUES ('$lang', '$intro');\n"; - - if (isset($txml)) { - // Find all persons matching the pattern - if (preg_match_all("!<person (.+)/\\s?>!U", $txml, $matches)) { - $default = array('vcs' => 'n/a', 'nick' => 'n/a', 'editor' => 'n/a', 'email' => 'n/a', 'name' => 'n/a'); - $persons = parse_attr_string($matches[1]); - - foreach ($persons as $person) { - $person = array_merge($default, $person); - $nick = SQLite3::escapeString($person['nick']); - $name = SQLite3::escapeString(@iconv($charset, 'UTF-8//IGNORE', $person['name'])); - $email = SQLite3::escapeString($person['email']); - $vcs = SQLite3::escapeString($person['vcs']); - $editor = SQLite3::escapeString($person['editor']); - $SQL_BUFF .= "INSERT INTO translators VALUES ('$lang', '$nick', '$name', '$email', '$vcs', '$editor');\n"; - } - } - - // Get list of work in progress files - if (preg_match_all("!<file(.+)/\\s?>!U", $txml, $matches)) { - $files = parse_attr_string($matches[1]); - foreach ($files as $file) { - $name = SQLite3::escapeString($file['name']); - $person = SQLite3::escapeString($file['person']); - $type = SQLite3::escapeString(isset($file['type']) ? $file['type'] : 'translation'); - $SQL_BUFF .= "INSERT INTO wip VALUES ('$lang', '$name', '$person', '$type');\n"; - } + public static function getKey( $fileStatus ) { + switch ( $fileStatus ) { + case FileStatusEnum::RevTagProblem: + case FileStatusEnum::TranslatedOld: + case FileStatusEnum::TranslatedCritial: + case FileStatusEnum::NotInEnTree: + return "files_outdated"; + break; + case FileStatusEnum::TranslatedWip: + return "files_wip"; + break; + case FileStatusEnum::TranslatedOk: + return "files_uptodate"; + break; + default: + return "files_other"; } } -} // parse_translation() function end() - +} // Get a multidimensional array with tag attributes -function parse_attr_string($tags_attrs) -{ +function parse_attr_string ( $tags_attrs ) { $tag_attrs_processed = array(); - // Go through the tag attributes - foreach ($tags_attrs as $attrib_list) { - - // Get attr name and values + foreach($tags_attrs as $attrib_list) { preg_match_all("!(.+)=\\s*([\"'])\\s*(.+)\\2!U", $attrib_list, $attribs); - // Assign all attributes to one associative array $attrib_array = array(); foreach ($attribs[1] as $num => $attrname) { $attrib_array[trim($attrname)] = trim($attribs[3][$num]); } - // Collect in order of tags received + $tag_attrs_processed[] = $attrib_array; } - // Retrun with collected attributes + return $tag_attrs_processed; } -function dir_sort($a, $b) { - global $DOCS, $dir; - $a = $DOCS . 'en' . $dir . '/' . $a; - $b = $DOCS . 'en' . $dir . '/' . $b; - if (is_dir($a) && is_dir($b)) { - return 0; - } elseif (is_file($a) && is_file($b)) { - return 0; - } elseif (is_file($a) && is_dir($b)) { - return -1; - } elseif (is_dir($a) && is_file($b)) { - return 1; - } else { - return -1; - } -} +function computeTranslatorStatus( $lang, $enFiles, $trFiles ) +{ + global $SQL_BUFF, $DOCS, $LANGUAGES; + $translation_xml = $DOCS . $lang . "/translation.xml"; + $charset = 'utf-8'; -function dir_sort_old($a, $b) { - global $DOCS, $dir, $lang; - $a = $DOCS . $lang . $dir . '/' . $a; - $b = $DOCS . $lang . $dir . '/' . $b; - if (is_dir($a) && is_dir($b)) { - return 0; - } elseif (is_file($a) && is_file($b)) { - return 0; - } elseif (is_file($a) && is_dir($b)) { - return -1; - } elseif (is_dir($a) && is_file($b)) { - return 1; - } else { - return -1; + if (!file_exists($translation_xml)) { + return []; } -} -function do_revcheck($dir = '') { - global $LANGS, $DOCS, $SQL_BUFF; - static $id = 1; - global $idx; - - if ($dh = opendir($DOCS . 'en/' . $dir)) { - - $entriesDir = array(); - $entriesFiles = array(); - - while (($file = readdir($dh)) !== false) { - if ( - (!is_dir($DOCS . 'en' . $dir.'/' .$file) && !in_array(substr($file, -3), array('xml','ent')) && substr($file, -13) != 'PHPEditBackup' ) - || strpos($file, 'entities.') === 0 - || $dir == '/chmonly' || $dir == '/internals' || $dir == '/internals2' - || $file == 'contributors.ent' || $file == 'contributors.xml' - || ($dir == '/appendices' && ($file == 'reserved.constants.xml' || $file == 'extensions.xml')) - || $file == '.editorconfig' - || $file == '.gitignore' - || $file == 'README' - || $file == 'README.md' - || $file == 'DO_NOT_TRANSLATE' - || $file == 'rsusi.txt' - || $file == 'missing-ids.xml' - || $file == 'license.xml' - || $file == 'versions.xml' - ) { - continue; - } + $txml = join("", file($translation_xml)); + $txml = preg_replace("/\\s+/", " ", $txml); - if ($file != '.' && $file != '..' && $file != '.git' && $dir != '/functions' && $dir != '/.git' && $dir != '/.github' && $file != '.github') { - - if (is_dir($DOCS . 'en' . $dir.'/' .$file)) { - $entriesDir[] = $file; - } elseif (is_file($DOCS . 'en' . $dir.'/' .$file)) { - $entriesFiles[] = $file; - } - } - } - $cwd = getcwd(); - // Files first - $maintainer = NULL; - $status = NULL; - if (sizeof($entriesFiles) > 0 ) { - foreach($entriesFiles as $file) { - $path = $DOCS . 'en' . $dir . '/'; - chdir ($path); - $size = intval(filesize($file) / 1024); - $date = filemtime($file); - $revision = git log -n1 --format=format:"%H" -- {$file};; - $revision = ($revision == 0) ? 'NULL' : "'$revision'"; - $SQL_BUFF .= "INSERT INTO enfiles VALUES ($id, '$file', $revision, '$size', '$date');\n"; - - foreach ($LANGS as $lang) { - $path = $DOCS . $lang . $dir . '/' . $file; - if (is_file($path)) { - $size = intval(filesize($path) / 1024); - $date = filemtime($path); - - list($revision, $maintainer, $status) = get_tags($path); - echo " Adding file: {$id}, {$lang}, {$file},{$revision}, {$size}, {$date}, {$maintainer}, {$status}\n"; - - $SQL_BUFF .= "INSERT INTO files VALUES ($id, '$lang', '$file', '$revision', '$size', '$date', '$maintainer', '$status');\n"; - } else { - $SQL_BUFF .= "INSERT INTO utfiles VALUES ($id, '$lang', '$file');\n"; - } - } - } - } - chdir($cwd); - - // Directories.. - if (sizeof($entriesDir) > 0) { - usort($entriesDir, 'dir_sort'); - reset($entriesDir); - - foreach ($entriesDir as $Edir) { - if ($Edir != 'figures') { - $path = $DOCS . 'en/' . $dir . '/' . $Edir; - $id++; - echo "Adding directory: $dir/$Edir (id: $id)\n"; - - $SQL_BUFF .= "INSERT INTO dirs VALUES ($id, '$dir/$Edir');\n"; - do_revcheck($dir . '/' . $Edir); - } - } - } - } - closedir($dh); -} + $intro = "No intro available for the {$LANGUAGES[$lang]} translation of the manual."; + if ( preg_match("!<intro>(.+)</intro>!s", $txml, $match) ) + $intro = SQLite3::escapeString(@iconv($charset, 'UTF-8//IGNORE', trim($match[1]))); -function check_old_files($lang, $dir = '') { - global $DOCS, $SQL_BUFF; - static $id = 1; - - if ($dh = opendir($DOCS . $lang . $dir)) { - - $entriesDir = array(); - $entriesFiles = array(); - - while (($file = readdir($dh)) !== false) { - if ( - (!is_dir($DOCS . $lang . $dir.'/' .$file) && !in_array(substr($file, -3), array('xml','ent')) && substr($file, -13) != 'PHPEditBackup' ) - || strpos($file, 'entities.') === 0 - || $dir == '/chmonly' || $dir == '/internals' || $dir == '/internals2' || $dir == '/.git' || $dir == '/.github' - || $file == 'contributors.ent' || $file == 'contributors.xml' - || ($dir == '/appendices' && ($file == 'reserved.constants.xml' || $file == 'extensions.xml')) - || $file == 'README' - || $file == 'README.md' - || $file == 'DO_NOT_TRANSLATE' - || $file == 'rsusi.txt' - || $file == 'missing-ids.xml' - || $file == 'translation.xml' - ) { - continue; - } + $SQL_BUFF .= "INSERT INTO descriptions VALUES ('$lang', '$intro');\n"; - if ($file != '.' && $file != '..' && $file != '.svn' && $dir != '/functions') { + $pattern = "!<person(.+)/\\s?>!U"; + preg_match_all($pattern, $txml, $matches); + $translators = parse_attr_string($matches[1]); - if (is_dir($DOCS . $lang . $dir.'/' .$file)) { - $entriesDir[] = $file; - } elseif (is_file($DOCS . $lang . $dir.'/' .$file)) { - $entriesFiles[] = $file; - } - } - } + $translatorInfos = []; + $unknownInfo = new TranslatorInfo(); + $unknownInfo->nick = "unknown"; + $translatorInfos["unknown"] = $unknownInfo; - // Files first - if (sizeof($entriesFiles) > 0 ) { + foreach ($translators as $key => $translator) + { + $info = new TranslatorInfo(); + $info->name = $translator["name"]; + $info->email = $translator["email"]; + $info->nick = $translator["nick"]; + $info->vcs = isset($translator["vcs"]) ? $translator["vcs"] : ''; - foreach($entriesFiles as $file) { - $path_en = $DOCS . 'en/' . $dir . '/' . $file; - $path = $DOCS . $lang . $dir . '/' . $file; + $translatorInfos[$info->nick] = $info; + } - if( !@is_file($path_en) ) { - $size = intval(filesize($path) / 1024); - $SQL_BUFF .= "INSERT INTO old_files VALUES ('$lang', '$dir', '$file', '$size');\n"; - } + foreach( $enFiles as $key => $enFile ) { + $info_exists = false; + if (array_key_exists($enFile->getKey(), $trFiles)) { + $trFile = $trFiles[$enFile->getKey()]; + $statusKey = TranslatorInfo::getKey($trFile->syncStatus); + if (array_key_exists($trFile->maintainer, $translatorInfos)) { + $translatorInfos[$trFile->maintainer]->$statusKey++; + $translatorInfos[$trFile->maintainer]->files_sum++; + $info_exists = true; } } + if (!$info_exists) { + $translatorInfos["unknown"]->$statusKey++; + $translatorInfos["unknown"]->files_sum++; + } + } + foreach ($translatorInfos as $key => $person) + { + if ($person->nick != "unknown" ) + { + $nick = SQLite3::escapeString($person->nick); + $name = SQLite3::escapeString(@iconv($charset, 'UTF-8//IGNORE', $person->name)); + $email = SQLite3::escapeString($person->email); + $vcs = SQLite3::escapeString($person->vcs); + + $SQL_BUFF .= "INSERT INTO translators VALUES ('$lang', + '$nick', '$name', '$email', '$vcs', $person->files_uptodate, + $person->files_outdated, $person->files_wip, + $person->files_sum, $person->files_other);\n"; + } + } +} - // Directories.. - if (sizeof($entriesDir) > 0) { - usort($entriesDir, 'dir_sort_old'); - reset($entriesDir); +function populateFileTree( $lang ) +{ + global $DOCS; + $dir = new \DirectoryIterator( $DOCS . $lang ); + if ( $dir === false ) + { + print "$lang is not a directory.\n"; + exit; + } + $cwd = getcwd(); + $ret = array(); + chdir( $DOCS . $lang ); + populateFileTreeRecurse( $lang , "." , $ret ); + chdir( $cwd ); + return $ret; +} - foreach ($entriesDir as $Edir) { - check_old_files($lang, $dir . '/' . $Edir); - } +function populateFileTreeRecurse( $lang , $path , & $output ) +{ + global $DOCS, $SQL_BUFF; + $dir = new DirectoryIterator( $path ); + if ( $dir === false ) + { + print "$path is not a directory.\n"; + exit; + } + $todoPaths = []; + $trimPath = ltrim( $path , "./"); + foreach( $dir as $entry ) + { + $filename = $entry->getFilename(); + if ( $filename[0] == '.' ) + continue; + if ( substr( $filename , 0 , 9 ) == "entities." ) + continue; + if ( $entry->isDir() ) + { + $todoPaths[] = $path . '/' . $entry->getFilename(); + continue; } + if ( $entry->isFile() ) + { + $ignoredFileNames = [ + 'README.md', + 'translation.xml', + 'readme.first', + 'license.xml', + 'extensions.xml', + 'versions.xml', + 'book.developer.xml', + 'contributors.ent', + 'contributors.xml', + 'README', + 'DO_NOT_TRANSLATE', + 'rsusi.txt', + 'missing-ids.xml', + ]; + + $ignoredDirectories = [ + 'chmonly', + ]; + + if( + in_array($trimPath, $ignoredDirectories, true) + || in_array($filename, $ignoredFileNames, true) + || (strpos($filename, 'entities.') === 0) + || !in_array(substr($filename, -3), ['xml','ent'], true) + || (substr($filename, -13) === 'PHPEditBackup') + || ($trimPath === 'appendices' && (in_array($filename, ['reserved.constants.xml', 'extensions.xml'], true))) + ) continue; + + $file = new FileStatusInfo; + $file->path = $trimPath; + $file->name = $filename; + $file->size = filesize( $path . '/' . $filename ); + $file->syncStatus = null; + if ( $lang != 'en' ) + { + parseRevisionTag( $entry->getPathname() , $file ); + $path_en = $DOCS . 'en/' . $trimPath . '/' . $filename; + if( !is_file($path_en) ) //notinen + { + $filesize = $file->size < 1024 ? 1 : floor( $file->size / 1024 ); + $SQL_BUFF .= "INSERT INTO notinen VALUES ('$lang', '$trimPath', '$filename', $filesize);\n"; + } else { + $output[ $file->getKey() ] = $file; + } + } else { + $output[ $file->getKey() ] = $file; + } + } } - closedir($dh); + sort( $todoPaths ); + foreach( $todoPaths as $path ) + populateFileTreeRecurse( $lang , $path , $output ); } -function get_tags($file) { - // Read the first 500 chars. The comment should be at - // the begining of the file - $fp = @fopen($file, "r") or die("Unable to read $file."); - $line = fread($fp, 1024); - fclose($fp); +function parseRevisionTag( $filename , FileStatusInfo $file ) +{ + $fp = fopen( $filename , "r" ); + $contents = fread( $fp , 1024 ); + fclose( $fp ); // No match before the preg $match = array (); - // Check for the translations "revision tag" - $regex = "/<!--\s*EN-Revision:\s*(.+)\s*Maintainer:\s*(.+)\s*Status:\s*(.+)\s*-->/U"; - if (preg_match ( $regex , $line , $match )) { - // note the simple quotes - return array(trim($match[1]),trim($match[2]),trim($match[3])); - } - - // The tag with revision number is not found so search - // for n/a revision comment (comment where revision is not known) - if (preg_match("'<!--\s*EN-Revision:\s*(n/a)\s*Maintainer:\s*(\\S*)\s*Status:\s*(.+)\s*-->'U", - $line, $match)) { - // note the simple quotes - return array("'" . trim($match[1]) . "'", "'" . trim($match[2]) . "'", "'" . trim($match[3]) . "'"); + $regex = "'<!--\s*EN-Revision:\s*(.+)\s*Maintainer:\s*(.+)\s*Status:\s*(.+)\s*-->'U"; + if (preg_match ($regex , $contents , $match )) { + $file->hash = trim( $match[1] ); + $file->maintainer = trim( $match[2] ); + $file->completion = trim( $match[3] ); } + if ( $file->hash == null or strlen( $file->hash ) != 40 or + $file->maintainer == null or + $file->completion == null ) + $file->syncStatus = FileStatusEnum::RevTagProblem; + + $regex = "/<!--\s*CREDITS:\s*(.+)\s*-->/U"; + $match = array(); + preg_match ( $regex , $contents , $match ); + if ( count( $match ) == 2 ) + $file->credits = str_replace( ' ' , '' , trim( $match[1] ) ); + else + $file->credits = ''; +} - // Nothing, return with NULL values - return array ("NULL", "NULL", "NULL"); - -} // get_tags() function end - -function get_original_rev($file) { - // Read the first 500 chars. The comment should be at - // the begining of the file - $fp = @fopen($file, "r") or die ("Unable to read $file."); - $line = fread($fp, 1024); - fclose($fp); - - // Return if this was needed (it should be there) - // . is for $ in the preg! - preg_match("/<!-- .Revision: (\d+) . -->/", $line, $match); - if (!empty($match)) { - return $match[1]; - } else { - return 0; +function captureGitValues( & $output ) +{ + global $DOCS; + $cwd = getcwd(); + chdir( $DOCS . 'en' ); + $fp = popen( "git --no-pager log --name-only" , "r" ); + $hash = null; + $date = null; + $utct = new DateTimeZone( "UTC" ); + while ( ( $line = fgets( $fp ) ) !== false ) + { + if ( substr( $line , 0 , 7 ) == "commit " ) + { + $hash = trim( substr( $line , 7 ) ); + continue; + } + if ( strpos( $line , 'Date:' ) === 0 ) + { + $date = trim( substr( $line , 5 ) ); + continue; + } + if ( trim( $line ) == "" ) + continue; + if ( substr( $line , 0 , 4 ) == ' ' ) + continue; + if ( strpos( $line , ': ' ) > 0 ) + continue; + $filename = trim( $line ); + if ( isset( $output[$filename] ) ) + continue; + $output[$filename]['hash'] = $hash; } + pclose( $fp ); + chdir( $cwd ); } /** @@ -460,6 +465,61 @@ function get_original_rev($file) { $time_start = microtime(true); +$path = null; +$id = 0; +asort( $enFiles ); +foreach( $enFiles as $key => $en ) +{ + if ( $path !== $en->path ) + { + $id++; + $path = $en->path; + $path2 = $path == '' ? '/' : $path; + $SQL_BUFF .= "INSERT INTO dirs VALUES ($id, '$path2');\n"; + } + + $size = $en->size < 1024 ? 1 : floor( $en->size / 1024 ); + $filename = $path . ($path == '' ? '' : '/') . $en->name; + $en->hash = null; + if ( isset( $gitData[ $filename ] ) ) + { + $en->hash = $gitData[ $filename ]['hash']; + } + else + print "Warn: No hash for en/$filename\n"; + + $SQL_BUFF .= "INSERT INTO enfiles VALUES ($id, '$en->name', '$en->hash', $size);\n"; + + foreach( $LANGS as $lang ) + { + $trFile = isset( $trFiles[$lang][$filename] ) ? $trFiles[$lang][$filename] : null; + if ( $trFile == null ) // Untranslated + { + $SQL_BUFF .= "INSERT INTO Untranslated VALUES ($id, '$lang', + '$en->name', $size);\n"; + } else { + if ( $trFile->completion != null && $trFile->completion != "ready" ) + { + $trFile->syncStatus = FileStatusEnum::TranslatedWip; + $SQL_BUFF .= "INSERT INTO wip VALUES ($id, '$lang', '$en->name', $size, '$trFile->maintainer');\n"; + continue; + } + if ( $en->hash == $trFile->hash ){ + $trFile->syncStatus = FileStatusEnum::TranslatedOk; + } elseif ( strlen( $trFile->hash ) == 40 ) { + $trFile->syncStatus = FileStatusEnum::TranslatedOld; + } + $SQL_BUFF .= "INSERT INTO translated VALUES ($id, '$lang', + '$en->name', '$trFile->hash', $size, '$trFile->maintainer', + '$trFile->completion', '$trFile->syncStatus');\n"; + } + } +} + +foreach( $LANGS as $lang ) { + computeTranslatorStatus( $lang, $enFiles, $trFiles[$lang] ); +} + $db_name = SQLITE_DIR . 'rev.php.sqlite'; $tmp_db = SQLITE_DIR . 'rev.php.tmp.sqlite'; @@ -491,18 +551,10 @@ function get_original_rev($file) { // 3 - Fill in the description table while cleaning the langs // without revision.xml file -foreach ($LANGS as $id => $lang) { - echo "Fetching the $lang description\n"; - parse_translation($lang); -} - // 4 - Recurse in the manual seeking for files and fill $SQL_BUFF -do_revcheck(); -// 4:1 - Recurse in the manuel seeking for old files for each language and fill $SQL_BUFF -foreach ($LANGS as $lang) { - check_old_files($lang, ''); -} + + // 5 - Query $SQL_BUFF and exit $db->exec('BEGIN TRANSACTION'); diff --git a/www/revcheck.php b/www/revcheck.php index 5205c16..87dc8ee 100644 --- a/www/revcheck.php +++ b/www/revcheck.php @@ -4,18 +4,11 @@ include '../include/init.inc.php'; include '../include/lib_revcheck.inc.php'; -// Revision marks used to flag files -define("REV_UPTODATE", 1); // Up to date files -define("REV_OUTDATED", 2); // Outdated files -define("REV_NOREV", 3); // file with revision comment without revision -define("REV_NOTRANS", 4); // file without translation (utfiles) -define("REV_WIP", 5); // Work in progress - if (isset($_GET['lang']) && in_array($_GET['lang'], array_keys($LANGUAGES))) { - $lang = $_GET['lang']; + $lang = $_GET['lang']; } else { - $lang = 'en'; + $lang = 'en'; } if ($lang != 'en' ) $lang_name = $LANGUAGES[$lang]; @@ -23,19 +16,19 @@ $tool = ''; if (isset($_GET['p'])) { - $tool = $_GET['p']; + $tool = $_GET['p']; } // Prevent viewing other tools in EN if ($lang == 'en') { - $tool = 'default'; + $tool = 'default'; } $DBLANG = SQLITE_DIR . 'rev.php.sqlite'; // Check if db connection can be established and if revcheck for requested lang exists if ($dbhandle = new SQLite3($DBLANG)) { - $check_lang_tmp = $dbhandle->query("SELECT COUNT(lang) AS count FROM description WHERE lang = '$lang'"); + $check_lang_tmp = $dbhandle->query("SELECT COUNT(lang) AS count FROM descriptions WHERE lang = '$lang'"); $check_lang = $check_lang_tmp->fetchArray(); if ($lang != 'en' && $check_lang['count'] < 0) { site_header(); @@ -45,33 +38,33 @@ } } else { - site_header(); - echo "<p>Database connection couldn't be established</p>"; - site_footer(); - die; + site_header(); + echo "<p>Database connection couldn't be established</p>"; + site_footer(); + die; } site_header(); switch($tool) { - case 'translators': - $translators = get_translators($dbhandle, $lang); - - if (empty($translators)) { - echo '<p>Error: no translators info found in database.</p>'; - } - else { - $uptodate = get_translators_stats($dbhandle, $lang, 'uptodate'); - $outdated = get_translators_stats($dbhandle, $lang, 'outdated'); - $wip = get_translators_stats($dbhandle, $lang, 'wip'); - - foreach($translators as $nick =>$data) { - $files_w[$nick] = array('uptodate' => '', 'outdated' => '', 'norev' => '', 'wip' => ''); - $files_w[$nick]['uptodate'] = isset($uptodate[$nick]) ? $uptodate[$nick] : ''; - $files_w[$nick]['wip'] = isset($wip[$nick]) ? $wip[$nick] : ''; - $files_w[$nick]['outdated'] = isset($outdated[$nick]) ? $outdated[$nick] : ''; - } - - echo <<<TRANSLATORS_HEAD + case 'translators': + $translators = get_translators($dbhandle, $lang); + + if (empty($translators)) { + echo '<p>Error: no translators info found in database.</p>'; + } + else { + $uptodate = get_translators_stats($dbhandle, $lang, 'uptodate'); + $outdated = get_translators_stats($dbhandle, $lang, 'outdated'); + $wip = get_translators_stats($dbhandle, $lang, 'wip'); + + foreach($translators as $nick =>$data) { + $files_w[$nick] = array('uptodate' => '', 'outdated' => '', 'norev' => '', 'wip' => ''); + $files_w[$nick]['uptodate'] = isset($uptodate[$nick]) ? $uptodate[$nick] : ''; + $files_w[$nick]['wip'] = isset($wip[$nick]) ? $wip[$nick] : ''; + $files_w[$nick]['outdated'] = isset($outdated[$nick]) ? $outdated[$nick] : ''; + } + + echo <<<TRANSLATORS_HEAD <table border="0" cellpadding="4" cellspacing="1"> <tr> <th rowspan="2">Name</th> @@ -87,225 +80,256 @@ </tr> TRANSLATORS_HEAD; - foreach ($translators as $nick => $data) { - echo '<tr>', - '<td><a href="mailto:'.$data['mail'].'">'.$data['name'].'</a></td>', - '<td><a href="/revcheck.php?p=files&amp;user='.$nick.'&amp;lang='.$lang.'">'.$nick.'</a></td>', - '<td>'.(($data['karma'] == 'yes') ? '✓' : '&nbsp;').'</td>', - '<td>' , @$files_w[$nick]['uptodate'], '</td>', - '<td>' , $files_w[$nick]['outdated'], '</td>', - '<td>', $files_w[$nick]['wip'], '</td>', - '<th>' , @array_sum($files_w[$nick]), '</th>', - '</tr>'; - } - echo '</table>'; - } - echo gen_date($DBLANG); - break; - - case 'missfiles': - $missfiles = get_missfiles($dbhandle, $lang); - if (!$missfiles) { - echo '<p>All files translated? Would be nice... but it\'s probably an error :(</p>'; - } - else { - $num = count($missfiles); - echo '<table border="0" cellpadding="3" cellspacing="1" style="text-align:center">'; - echo '<tr><th rowspan="1">Available for translation ('.$num.' files):</th><th>Commit Hash</th><th colspan="1">kB</th></tr>'; - - $last_dir = false; - $total_size = 0; - foreach ($missfiles as $miss) { - if (!$last_dir || $last_dir != $miss['dir']) { - echo '<tr><th colspan="3">'.$miss['dir'].'</th></tr>'; - $last_dir = $miss['dir']; - } - echo '<tr><td>'.$miss['file'].'</td><td>'.$miss['revision'].'</td><td>'.$miss['size'].'</td></tr>'; - $total_size += $miss['size']; - // flush every 200 kbytes - if (($total_size % 200) == 0) { - flush(); - } - } - echo '<tr><th colspan="3">Total Size ('.$num.' files): '.$total_size.' kB</th></tr>'; - echo '</table>'; - } - echo gen_date($DBLANG); - break; - - case 'oldfiles': - $oldfiles = get_oldfiles($dbhandle, $lang); - if (!$oldfiles) { - echo '<p>Good, it seems that this translation doesn\'t contain any file which is not present in English tree.</p>'; - } - else { - $num = count($oldfiles); - echo '<table width="400" border="0" cellpadding="3" cellspacing="1" style="text-align:center">'; - echo '<tr><th rowspan="1">Not in EN tree ('.$num.' files):</th><th colspan="1">kB</th></tr>'; - - $last_dir = false; - $total_size = 0; - foreach ($oldfiles as $old) { - if (!$last_dir || $last_dir != $old['dir']) { - echo '<tr><th colspan="2">'.$old['dir'].'</th></tr>'; - $last_dir = $old['dir']; - } - echo '<tr><td>', $old['file'], '</td><td class="r">'.$old['size'].'</td></tr>'; - $total_size += $old['size']; - // flush every 200 kbytes - if (($total_size % 200) == 0) { - flush(); - } - } - echo '<tr><th colspan="2">Total Size ('.$num.' files): '.$total_size.' kB</th></tr>'; - echo '</table>'; - } - echo gen_date($DBLANG); - break; - - case 'misstags': - $misstags = get_misstags($dbhandle, $lang); - - if ($misstags == NULL) { - echo '<p>Good, all files contain revision numbers.</p>'; - } - else { - $num = count($misstags); - echo '<table border="0" cellpadding="3" cellspacing="1" style="text-align:center">'; - echo '<tr><th rowspan="2">Files without EN-Revision number ('.$num.' files):</th><th colspan="3">Sizes in kB</th></tr>'; - echo '<tr><th>en</th><th>'.$lang.'</th><th>diff</th></</tr>'; - - $last_dir = false; - - foreach ($misstags as $row) { - if (!$last_dir || $last_dir != $row['dir']) { - echo '<tr><th colspan="4">'.$row['dir'].'</th></tr>'; - $last_dir = $row['dir']; - } - echo '<tr><td>'.$row['name'].'</td><td>'.$row['en_size'].'</td><td>'.$row['trans_size'].'</td><td>'.(intval($row['en_size'] - $row['trans_size'])).'</td></tr>'; - } - echo '</table>'; - } - echo gen_date($DBLANG); - break; - - case 'filesummary': - $file_types = array( - array (REV_UPTODATE, 'Up to date files'), - array (REV_OUTDATED, 'Outdated files'), - array (REV_WIP, 'Work in progress'), - array (REV_NOREV, 'Files without revision number'), - array (REV_NOTRANS, 'Files available for translation') - ); - - $file_summary_array = array( - REV_UPTODATE => array(0,0), - REV_OUTDATED => array(0,0), - REV_NOREV => array(0,0), - REV_NOTRANS => array(0,0), - REV_WIP => array(0,0) - ); - - $file_summary_array[REV_UPTODATE] = get_stats($dbhandle, $lang, 'uptodate'); - $file_summary_array[REV_OUTDATED] = get_stats($dbhandle, $lang, 'outdated'); - $file_summary_array[REV_NOREV] = get_stats($dbhandle, $lang, 'norev'); - $file_summary_array[REV_NOTRANS] = get_stats($dbhandle, $lang, 'notrans'); - $file_summary_array[REV_WIP] = get_stats($dbhandle, $lang, 'wip'); - - echo '<table border="0" cellpadding="4" cellspacing="1" style="text-align:center;">'; - echo '<tr><th>File status type</th><th>Number of files</th><th>Percent of files</th><th>Size of files (kB)</th><th>Percent of size</th></tr>'; - - $percent = array(0, 0); - - foreach($file_summary_array as $t => $a) { - $percent[0] += $a[0]; - $percent[1] += $a[1]; - } - - foreach ($file_types as $num => $type) { - $tmp_num_percent_0 = ($percent[0] == 0) ? 0 : number_format($file_summary_array[$type[0]][0] * 100 / $percent[0], 2 ); - $tmp_num_percent_1 = ($percent[0] == 0) ? 0 : number_format($file_summary_array[$type[0]][1] * 100 / $percent[1], 2); - - echo '<tr>'; - echo '<td>'.$type[1].'</td>'; - echo '<td>'.$file_summary_array[$type[0]][0].'</td>'; - echo '<td>'.$tmp_num_percent_0.'%</td>'; - echo '<td>'.$file_summary_array[$type[0]][1].'</td>'; - echo '<td>'.$tmp_num_percent_1.'%</td>'; - echo '</tr>'; - } - - echo '<tr><th>Files total</th><th>'.$percent[0].'</th><th>100%</th><th>'.$percent[1].'</th><th>100%</th></tr>'; - echo '</table>'; - echo gen_date($DBLANG); - break; - - - case 'files' : - // we need a dir to browse - $dirs = get_dirs($dbhandle, $lang); - $users = get_translators($dbhandle, $lang); - - if (empty($dirs)) { - echo '<p>Error: no directories found in database.</p>'; - $sidebar = nav_tools($lang); - site_footer($sidebar); - die; - } - - echo '<p>This tool allows you to check which files in your translation need updates. To show the list '; - echo 'choose a directory (it doesn\'t work recursively) or translator.</p>'; - echo '<p>When you click on the filename you will see the plaintext diff showing changes between revisions, so '; - echo 'you will know what has changed in the English version and which information you need to update.'; - echo 'You can also click on [diff] to show the colored diff.</p>'; - echo '<p>Choose a directory:</p>'; - echo '<form method="get" action="revcheck.php"><p><select name="dir">'; - foreach ($dirs as $id => $name) { - if (isset($_GET['dir']) && $_GET['dir'] == $id) { - $selected = ' selected="selected"'; - } - else { - $selected = ''; - } - echo '<option value="'.$id.'"'.$selected.'>'.$name.'</option>'; - } - echo '</select>'; - echo '<input type="hidden" name="p" value="files">'; - echo '<input type="hidden" name="lang" value="'.$lang.'">'; - echo '<input type="submit" value="See outdated files"></p></form>'; - - echo '<p>Or choose a translator:</p>'; - echo '<form method="get" action="revcheck.php"><p><select name="user">'; - foreach ($users as $id => $user) { - if (isset($_GET['user']) && $_GET['user'] == $id) { - $selected = ' selected="selected"'; - } - else { - $selected = ''; - } - echo '<option value="'.$id.'"'.$selected.'>'.$id.'</option>'; - } - echo '</select>'; - echo '<input type="hidden" name="p" value="files">'; - echo '<input type="hidden" name="lang" value="'.$lang.'">'; - echo '<input type="submit" value="See outdated files"></p></form>'; - - // Get outdated files filtered as requested - if (isset($_GET['user'])) { - $outdated = get_outdated_files($dbhandle, $lang, 'translator', $_GET['user']); - } - elseif (isset($_GET['dir'])) { - $outdated = get_outdated_files($dbhandle, $lang, 'dir', $_GET['dir']); - } - else { - $outdated = get_outdated_files($dbhandle, $lang, 'all'); - } - - if (empty($outdated)) { - echo '<p>Good, it seems that all files are up to date for these conditions.</p>'; - } - else { - echo <<<END_OF_MULTILINE + foreach ($translators as $nick => $data) { + echo '<tr>', + '<td><a href="mailto:'.$data['mail'].'">'.$data['name'].'</a></td>', + '<td><a href="/revcheck.php?p=files&amp;user='.$nick.'&amp;lang='.$lang.'">'.$nick.'</a></td>', + '<td>'.(($data['karma'] == 'yes') ? '✓' : '&nbsp;').'</td>', + '<td>' , @$files_w[$nick]['uptodate'], '</td>', + '<td>' , $files_w[$nick]['outdated'], '</td>', + '<td>', $files_w[$nick]['wip'], '</td>', + '<th>' , @array_sum($files_w[$nick]), '</th>', + '</tr>'; + } + echo '</table>'; + } + echo gen_date($DBLANG); + break; + + case 'missfiles': + $missfiles = get_missfiles($dbhandle, $lang); + if (!$missfiles) { + echo '<p>All files translated? Would be nice... but it\'s probably an error :(</p>'; + } else { + $num = count($missfiles); + echo '<table border="0" cellpadding="3" cellspacing="1" style="text-align:center">'; + echo '<tr><th rowspan="1">Available for translation ('.$num.' files):</th><th>Commit Hash</th><th colspan="1">kB</th></tr>'; + + $last_dir = false; + $total_size = 0; + foreach ($missfiles as $miss) { + if (!$last_dir || $last_dir != $miss['dir']) { + echo '<tr><th colspan="3">'.$miss['dir'].'</th></tr>'; + $last_dir = $miss['dir']; + } + $key = $miss['dir'] == '' ? "/" : $miss['dir']."/". $miss['file']; + echo "<tr><td><a href='/gitweb/?p=doc/en.git;a=blob;f=$key;hb={$miss['revision']}'>{$miss['file']}</a></td><td>{$miss['revision']}</td><td>{$miss['size']}</td></tr>"; + $total_size += $miss['size']; + // flush every 200 kbytes + if (($total_size % 200) == 0) + flush(); + } + echo "<tr><th colspan='3'>Total Size ($num files): $total_size kB</th></tr>"; + echo '</table>'; + } + echo gen_date($DBLANG); + break; + + case 'oldfiles': + $oldfiles = get_oldfiles($dbhandle, $lang); + if (!$oldfiles) { + echo '<p>Good, it seems that this translation doesn\'t contain any file which is not present in English tree.</p>'; + } else { + $num = count($oldfiles); + echo '<table width="400" border="0" cellpadding="3" cellspacing="1" style="text-align:center">'; + echo '<tr><th rowspan="1">Not in EN tree ('.$num.' files):</th><th colspan="1">kB</th></tr>'; + + $last_dir = false; + $total_size = 0; + foreach ($oldfiles as $old) { + if (!$last_dir || $last_dir != $old['dir']) { + echo '<tr><th colspan="2">'.$old['dir'].'</th></tr>'; + $last_dir = $old['dir']; + } + echo '<tr><td>', $old['file'], '</td><td class="r">'.$old['size'].'</td></tr>'; + $total_size += $old['size']; + // flush every 200 kbytes + if (($total_size % 200) == 0) + flush(); + } + echo '<tr><th colspan="2">Total Size ('.$num.' files): '.$total_size.' kB</th></tr>'; + echo '</table>'; + } + echo gen_date($DBLANG); + break; + + case 'misstags': + $misstags = get_misstags($dbhandle, $lang); + + if ($misstags == NULL) { + echo '<p>Good, all files contain revision numbers.</p>'; + } else { + $num = count($misstags); + echo '<table border="0" cellpadding="3" cellspacing="1" style="text-align:center">'; + echo '<tr><th rowspan="2">Files without EN-Revision number ('.$num.' files):</th><th colspan="3">Sizes in kB</th></tr>'; + echo '<tr><th>en</th><th>'.$lang.'</th><th>diff</th></tr>'; + + $last_dir = false; + + foreach ($misstags as $row) { + if (!$last_dir || $last_dir != $row['dir']) { + echo '<tr><th colspan="4">'.$row['dir'].'</th></tr>'; + $last_dir = $row['dir']; + } + echo '<tr><td>'.$row['name'].'</td><td>'.$row['en_size'].'</td><td>'.$row['trans_size'].'</td><td>'.(intval($row['en_size'] - $row['trans_size'])).'</td></tr>'; + } + echo '</table>'; + } + echo gen_date($DBLANG); + break; + + case 'filesummary': + $files_uptodate = get_stats($dbhandle, $lang, 'uptodate'); + $files_outdated = get_stats($dbhandle, $lang, 'outdated'); + $files_norev = get_stats($dbhandle, $lang, 'norev'); + $files_notrans = get_stats($dbhandle, $lang, 'notrans'); + $files_wip = get_stats($dbhandle, $lang, 'wip'); + $files_notinen = get_stats($dbhandle, $lang, 'notinen'); + + echo '<table border="0" cellpadding="4" cellspacing="1" style="text-align:center;">'; + echo '<tr><th>File status type</th><th>Number of files</th><th>Percent of files</th><th>Size of files (kB)</th><th>Percent of size</th></tr>'; + + $percent[0] = 0; + $percent[1] = 0; + #$percent[0] = count_en_files($dbhandle); + + $percent[0] += $files_uptodate[0]; + $percent[0] += $files_outdated[0]; + $percent[0] += $files_norev[0]; + $percent[0] += $files_notrans[0]; + $percent[0] += $files_wip[0]; + $percent[0] += $files_notinen[0]; + + $percent[1] += $files_uptodate[1]; + $percent[1] += $files_outdated[1]; + $percent[1] += $files_norev[1]; + $percent[1] += $files_notrans[1]; + $percent[1] += $files_wip[1]; + $percent[1] += $files_notinen[1]; + + + $num_uptodate_percent = number_format($files_uptodate[0] * 100 / $percent[0], 2 ); + $num_outdated_percent = number_format($files_outdated[0] * 100 / $percent[0], 2 ); + $num_wip_percent = number_format($files_wip[0] * 100 / $percent[0], 2 ); + $num_norev_percent = number_format($files_norev[0] * 100 / $percent[0], 2 ); + $num_notinen_percent = number_format($files_notinen[0] * 100 / $percent[0], 2 ); + $num_notrans_percent = number_format($files_notrans[0] * 100 / $percent[0], 2 ); + + $size_uptodate_percent = number_format($files_uptodate[1] * 100 / $percent[1], 2 ); + $size_outdated_percent = number_format($files_outdated[1] * 100 / $percent[1], 2 ); + $size_wip_percent = number_format($files_wip[1] * 100 / $percent[1], 2 ); + $size_norev_percent = number_format($files_norev[1] * 100 / $percent[1], 2 ); + $size_notinen_percent = number_format($files_notinen[1] * 100 / $percent[1], 2 ); + $size_notrans_percent = number_format($files_notrans[1] * 100 / $percent[1], 2 ); + print <<<HTML +<tr> +<td>Up to date files</td> +<td>{$files_uptodate[0]}</td> +<td>{$num_uptodate_percent}%</td> +<td>{$files_uptodate[1]}</td> +<td>{$size_uptodate_percent}%</td> +</tr><tr> +<td>Outdated files</td> +<td>{$files_outdated[0]}</td> +<td>{$num_outdated_percent}%</td> +<td>{$files_outdated[1]}</td> +<td>{$size_outdated_percent}%</td> +</tr><tr> +<td>Work in progress</td> +<td>{$files_wip[0]}</td> +<td>{$num_wip_percent}%</td> +<td>{$files_wip[1]}</td> +<td>{$size_wip_percent}%</td> +</tr><tr> +<td>Files without revision number</td> +<td>{$files_norev[0]}</td> +<td>{$num_norev_percent}%</td> +<td>{$files_norev[1]}</td> +<td>{$size_norev_percent}%</td> +</tr><tr> +<td>Not in EN tree</td> +<td>{$files_notinen[0]}</td> +<td>{$num_notinen_percent}%</td> +<td>{$files_notinen[1]}</td> +<td>{$size_notinen_percent}%</td> +</tr><tr> +<td>Files available for translation </td> +<td>{$files_notrans[0]}</td> +<td>{$num_notrans_percent}%</td> +<td>{$files_notrans[1]}</td> +<td>{$size_notrans_percent}%</td> +</tr><tr> +<th>Files total</th> +<th>{$percent[0]}</th> +<th>100%</th> +<th>{$percent[1]}</th +><th>100%</th> +</tr></table> +HTML; + echo gen_date($DBLANG); + break; + + + case 'files' : + // we need a dir to browse + $dirs = get_dirs($dbhandle, $lang); + $users = get_translators($dbhandle, $lang); + /* + if (empty($dirs)) { + echo '<p>Error: no directories found in database.</p>'; + $sidebar = nav_tools($lang); + site_footer($sidebar); + die; + } + */ + echo '<p>This tool allows you to check which files in your translation need updates. To show the list '; + echo 'choose a directory (it doesn\'t work recursively) or translator.</p>'; + echo '<p>When you click on the filename you will see the plaintext diff showing changes between revisions, so '; + echo 'you will know what has changed in the English version and which information you need to update.'; + echo 'You can also click on [diff] to show the colored diff.</p>'; + echo '<p>Choose a directory:</p>'; + echo '<form method="get" action="revcheck.php"><p><select name="dir">'; + foreach ($dirs as $id => $name) { + if (isset($_GET['dir']) && $_GET['dir'] == $id) { + $selected = ' selected="selected"'; + } else { + $selected = ''; + } + echo '<option value="'.$id.'"'.$selected.'>'.$name.'</option>'; + } + echo '</select>'; + echo '<input type="hidden" name="p" value="files">'; + echo '<input type="hidden" name="lang" value="'.$lang.'">'; + echo '<input type="submit" value="See outdated files"></p></form>'; + + echo '<p>Or choose a translator:</p>'; + echo '<form method="get" action="revcheck.php"><p><select name="user">'; + foreach ($users as $id => $user) { + if (isset($_GET['user']) && $_GET['user'] == $id) { + $selected = ' selected="selected"'; + } else { + $selected = ''; + } + echo '<option value="'.$id.'"'.$selected.'>'.$id.'</option>'; + } + echo '</select>'; + echo '<input type="hidden" name="p" value="files">'; + echo '<input type="hidden" name="lang" value="'.$lang.'">'; + echo '<input type="submit" value="See outdated files"></p></form>'; + + // Get outdated files filtered as requested + if (isset($_GET['user'])) { + $outdated = get_outdated_files($dbhandle, $lang, 'translator', $_GET['user']); + } elseif (isset($_GET['dir'])) { + $outdated = get_outdated_files($dbhandle, $lang, 'dir', $_GET['dir']); + } else { + $outdated = get_outdated_files($dbhandle, $lang, 'all'); + } + + if (empty($outdated)) { + echo '<p>Good, it seems that all files are up to date for these conditions.</p>'; + } else { + echo <<<END_OF_MULTILINE <table border="0" cellpadding="4" cellspacing="1" style="text-align:center"> <tr> <th rowspan="2">Translated file</th> @@ -319,80 +343,76 @@ </tr> <tr><th colspan="5">{$outdated[0]['name']}</th></tr> END_OF_MULTILINE; - $last_dir = false; - $prev_name = $outdated[0]['name']; - - foreach ($outdated as $r) { - if ($r['name'] != $prev_name) { - echo '<tr><th colspan="5">'.$r['name'].'</th></tr>'; - $prev_name = $r['name']; - } - - // Make the maintainer a link, if we have that maintainer in the list - if ($r['maintainer'] && $r["maintainer"] != 'nobody') { - $r["maintainer"] = '<a href="?p=translators&amp;lang=' . $lang . '">' . $r["maintainer"] . '</a>'; - } - - // Make a link to the GIT repository's diff script - $key = substr($r['name'] . '/' . $r['file'], 1); - if ($r['name'] == '/') { - $key = $r['file']; - } - //text - $d1 = "/gitweb/?p=doc/en.git;a=blobdiff_plain;f=$key;hb={$r['en_rev']};hpb={$r['trans_rev']};"; - - //html - $d2 = "/gitweb/?p=doc/en.git;a=blobdiff;f=$key;hb={$r['en_rev']};hpb={$r['trans_rev']};"; - - $nm = "<a href='$d1'>{$r['file']}</a> <a href='$d2'>(html)</a>"; - - $h1 = "<a href='/gitweb/?p=doc/en.git;a=blob;f=$key;hb={$r['en_rev']}'>{$r['en_rev']}</a>"; - - $h2 = "<a href='/gitweb/?p=doc/en.git;a=blob;f=$key;hb={$r['trans_rev']}'>{$r['trans_rev']}</a>"; - - // Write out the line for the current file (get file name shorter) - echo '<tr>'. - "<td style='white-space:nowrap'>{$nm}</td>". - "<td>{$h1}</td>" . - "<td>{$h2}</td>" . - "<td> {$r['maintainer']}</td>" . - "<td> {$r['status']}</td></tr>\n"; - } - echo '</table>'; - } - echo gen_date($DBLANG); - break; + $last_dir = false; + $prev_name = $outdated[0]['name']; + + foreach ($outdated as $r) { + if ($r['name'] != $prev_name) { + echo '<tr><th colspan="5">'.$r['name'].'</th></tr>'; + $prev_name = $r['name']; + } + + // Make the maintainer a link, if we have that maintainer in the list + if ($r['maintainer'] && $r["maintainer"] != 'nobody') { + $r["maintainer"] = '<a href="?p=translators&amp;lang=' . $lang . '">' . $r["maintainer"] . '</a>'; + } + + // Make a link to the GIT repository's diff script + $key = $r['name'] . '/' . $r['file']; + if ($r['name'] == '/') + $key = $r['file']; + + //text + $d1 = "/gitweb/?p=doc/en.git;a=blobdiff_plain;f=$key;hb={$r['en_rev']};hpb={$r['trans_rev']};"; + //html + $d2 = "/gitweb/?p=doc/en.git;a=blobdiff;f=$key;hb={$r['en_rev']};hpb={$r['trans_rev']};"; + + $h1 = "<a href='/gitweb/?p=doc/en.git;a=blob;f=$key;hb={$r['en_rev']}'>{$r['en_rev']}</a>"; + $h2 = "<a href='/gitweb/?p=doc/en.git;a=blob;f=$key;hb={$r['trans_rev']}'>{$r['trans_rev']}</a>"; + + $nm = "<a href='$d1'>{$r['file']}</a> <a href='$d2'>(html)</a>"; + + // Write out the line for the current file (get file name shorter) + echo '<tr>'. + "<td style='white-space:nowrap'>{$nm}</td>". + "<td>{$h1}</td>" . + "<td>{$h2}</td>" . + "<td> {$r['maintainer']}</td>" . + "<td> {$r['status']}</td></tr>\n"; + } + echo '</table>'; + } + echo gen_date($DBLANG); + break; case 'graph': - $path = "images/revcheck/info_revcheck_php_$lang.png"; - if (is_readable($path)) { - echo '<img src="'.$path.'" alt="info">'; - echo gen_date($DBLANG); - } - else { - echo "<p>Can't find graph.</p>"; - } - break; - - default: - if ($lang == 'en') { - echo '<img src="images/revcheck/info_revcheck_php_all_lang.png" alt="Info" class="chart">'; - echo '<p>This is all what we can show for original manual. To get more tools, please select translation language.</p>'; - echo gen_date($DBLANG); - $sidebar = nav_languages(); - site_footer($sidebar); - } - else { - $intro_result = $dbhandle->query("SELECT intro FROM description WHERE lang = '$lang'"); - $intro = $intro_result->fetchArray(); - echo '<h2>Intro for language</h2>'; - echo '<p>'.$intro[0].'</p>'; - echo '<p>Links to available tools are placed on the right sidebar.</p>'; - } + $path = "images/revcheck/info_revcheck_php_$lang.png"; + if (is_readable($path)) { + echo '<img src="'.$path.'" alt="info">'; + echo gen_date($DBLANG); + } else { + echo "<p>Can't find graph.</p>"; + } + break; + + default: + if ($lang == 'en') { + echo '<img src="images/revcheck/info_revcheck_php_all_lang.png" alt="Info" class="chart">'; + echo '<p>This is all what we can show for original manual. To get more tools, please select translation language.</p>'; + echo gen_date($DBLANG); + $sidebar = nav_languages(); + site_footer($sidebar); + } else { + $intro_result = $dbhandle->query("SELECT intro FROM descriptions WHERE lang = '$lang'"); + $intro = $intro_result->fetchArray(); + echo '<h2>Intro for language</h2>'; + echo '<p>'.$intro[0].'</p>'; + echo '<p>Links to available tools are placed on the right sidebar.</p>'; + } break; } if ($lang != 'en') { - $sidebar = nav_tools($lang); - site_footer($sidebar); + $sidebar = nav_tools($lang); + site_footer($sidebar); }

« previous php.doc.web (#2468) next »