2declare( strict_types = 1 );
4namespace MediaWiki\Extension\Translate\Statistics;
11use MediaWiki\MediaWikiServices;
12use Wikimedia\Rdbms\IDatabase;
22 protected array $seenUsers = [];
23 protected array $groups = [];
24 private Language $dateFormatter;
25 private array $formatCache = [];
29 parent::__construct( $opts );
31 $opts->boundValue(
'days', 1, 400 );
33 $this->dateFormatter = MediaWikiServices::getInstance()->getContentLanguage();
34 $this->messageIndex = Services::getInstance()->getMessageIndex();
48 global $wgTranslateMessageNamespaces;
50 $tables = [
'recentchanges' ];
51 $fields = [
'rc_timestamp' ];
55 'rc_namespace' => $wgTranslateMessageNamespaces,
57 'rc_type != ' . RC_LOG,
60 $timeConds = self::makeTimeCondition( $database,
'rc_timestamp', $start, $end );
61 $conds = array_merge( $conds, $timeConds );
63 $options = [
'ORDER BY' =>
'rc_timestamp' ];
65 $this->groups = array_map( [ MessageGroups::class,
'normalizeId' ], $this->opts->getGroups() );
68 if ( count( $namespaces ) ) {
69 $conds[
'rc_namespace'] = $namespaces;
73 foreach ( $this->opts->getLanguages() as $code ) {
74 $languages[] =
'rc_title ' . $database->buildLike( $database->anyString(),
"/$code" );
76 if ( count( $languages ) ) {
77 $conds[] = $database->makeList( $languages, LIST_OR );
80 $fields[] =
'rc_title';
82 if ( $this->groups ) {
83 $fields[] =
'rc_namespace';
86 if ( $this->opts->getValue(
'count' ) ===
'users' ) {
87 $fields[] =
'rc_actor';
94 if ( $this->opts->getValue(
'count' ) ===
'users' ) {
97 if ( isset( $this->seenUsers[$date][$row->rc_actor] ) ) {
101 $this->seenUsers[$date][$row->rc_actor] =
true;
105 if ( !str_contains( $row->rc_title,
'/' ) ) {
110 if ( !$this->groups && !$this->opts->getLanguages() ) {
120 if ( $this->groups ) {
123 $groups = $this->messageIndex->getGroupIdsForDatabaseTitle( (
int)$row->rc_namespace, $key );
124 $groups = array_intersect( $this->groups, $groups );
127 if ( $this->opts->getLanguages() ) {
135 return $this->
combineTwoArrays( $this->groups, $this->opts->getLanguages() );
139 return $row->rc_timestamp;
150 if ( $group || $code ) {
151 return "$group@$code";
165 if ( !count( $groups ) ) {
169 if ( !count( $codes ) ) {
174 foreach ( $groups as $group ) {
175 foreach ( $codes as $code ) {
176 $items[] = $this->
makeLabel( $group, $code );
190 switch ( $this->opts->getValue(
'scale' ) ) {
205 $index = substr( $timestamp, 0, -6 );
208 $this->formatCache[$index] ??= $this->dateFormatter->sprintfDate( $this->
getDateFormat(), $timestamp );
209 return $this->formatCache[$index];
212 return substr( $timestamp, 0, -$cut );