Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
characterEditStats.php
Go to the documentation of this file.
1<?php
12// Standard boilerplate to define $IP
14use MediaWiki\MediaWikiServices;
15
16if ( getenv( 'MW_INSTALL_PATH' ) !== false ) {
17 $IP = getenv( 'MW_INSTALL_PATH' );
18} else {
19 $dir = __DIR__;
20 $IP = "$dir/../../..";
21}
22require_once "$IP/maintenance/Maintenance.php";
23
24class CharacterEditStats extends Maintenance {
25 public function __construct() {
26 parent::__construct();
27 $this->addDescription( 'Script to show number of characters translated .' );
28 $this->addOption(
29 'top',
30 '(optional) Show given number of language codes (default: show all)',
31 false, /*required*/
32 true /*has arg*/
33 );
34 $this->addOption(
35 'days',
36 '(optional) Calculate for given number of days (default: 30)',
37 false, /*required*/
38 true /*has arg*/
39 );
40 $this->addOption(
41 'ns',
42 '(optional) Comma separated list of namespace IDs',
43 false, /*required*/
44 true /*has arg*/
45 );
46 $this->requireExtension( 'Translate' );
47 }
48
49 public function execute() {
50 global $wgSitename, $wgTranslateMessageNamespaces;
51
52 $days = (int)$this->getOption( 'days', 30 );
53 $top = (int)$this->getOption( 'top', -1 );
54
55 $namespaces = [];
56 if ( $this->hasOption( 'ns' ) ) {
57 $input = explode( ',', $this->getOption( 'ns' ) );
58
59 foreach ( $input as $namespace ) {
60 if ( is_numeric( $namespace ) ) {
61 $namespaces[] = $namespace;
62 }
63 }
64 } else {
65 $namespaces = $wgTranslateMessageNamespaces;
66 }
67
68 // Select set of edits to report on
69 $rows = $this->getRevisionsFromHistory( $days, $namespaces );
70
71 // Get counts for edits per language code after filtering out edits by FuzzyBot
72 $codes = [];
73
74 foreach ( $rows as $_ ) {
75 // Filter out edits by FuzzyBot
76 if ( $_->user_text === FuzzyBot::getName() ) {
77 continue;
78 }
79
80 $handle = new MessageHandle( Title::newFromText( $_->title ) );
81 $code = $handle->getCode();
82
83 if ( !isset( $codes[$code] ) ) {
84 $codes[$code] = 0;
85 }
86
87 $codes[$code] += $_->length;
88 }
89
90 // Sort counts and report descending up to $top rows.
91 arsort( $codes );
92 $i = 0;
93 $total = 0;
94 $this->output( "Character edit stats for last $days days in $wgSitename\n" );
95 $this->output( "code\tname\tedit\n" );
96 $this->output( "-----------------------\n" );
97 foreach ( $codes as $code => $num ) {
98 if ( $i++ === $top ) {
99 break;
100 }
101 $language = Language::fetchLanguageName( $code );
102 if ( !$language ) {
103 // this will be very rare, but avoid division by zero in next line
104 continue;
105 }
106 $charRatio = mb_strlen( $language, 'UTF-8' ) / strlen( $language );
107 $num = (int)( $num * $charRatio );
108 $total += $num;
109 $this->output( "$code\t$language\t$num\n" );
110 }
111 $this->output( "-----------------------\n" );
112 $this->output( "Total\t\t$total\n" );
113 }
114
115 private function getRevisionsFromHistory( $days, array $namespaces ) {
116 $dbr = wfGetDB( DB_REPLICA );
117 $cutoff = $dbr->addQuotes( $dbr->timestamp( time() - $days * 24 * 3600 ) );
118
119 $revQuery = MediaWikiServices::getInstance()->getRevisionStore()->getQueryInfo( [ 'page' ] );
120 $revUserText = $revQuery['fields']['rev_user_text'] ?? 'rev_user_text';
121
122 $conds = [
123 "rev_timestamp > $cutoff",
124 'page_namespace' => $namespaces,
125 ];
126
127 $res = $dbr->select(
128 $revQuery['tables'],
129 [
130 'title' => 'page_title',
131 'user_text' => $revUserText,
132 'length' => 'rev_len',
133 ],
134 $conds,
135 __METHOD__,
136 [],
137 $revQuery['joins']
138 );
139 return iterator_to_array( $res );
140 }
141}
142
143$maintClass = CharacterEditStats::class;
144require_once RUN_MAINTENANCE_IF_MAIN;
FuzzyBot - the misunderstood workhorse.
Definition FuzzyBot.php:15
Class for pointing to messages, like Title class is for titles.