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