MediaWiki 1.42.0-rc.0
SpecialStatistics.php
Go to the documentation of this file.
1<?php
24namespace MediaWiki\Specials;
25
34use Xml;
35
43 private $edits, $good, $images, $total, $users,
44 $activeUsers = 0;
45
46 private UserGroupManager $userGroupManager;
47
51 public function __construct( UserGroupManager $userGroupManager ) {
52 parent::__construct( 'Statistics' );
53 $this->userGroupManager = $userGroupManager;
54 }
55
56 public function execute( $par ) {
57 $this->setHeaders();
58 $this->outputHeader();
59 $this->getOutput()->addModuleStyles( 'mediawiki.special' );
60
61 $this->edits = SiteStats::edits();
62 $this->good = SiteStats::articles();
63 $this->images = SiteStats::images();
64 $this->total = SiteStats::pages();
65 $this->users = SiteStats::users();
66 $this->activeUsers = SiteStats::activeUsers();
67
68 $text = Xml::openElement( 'table', [ 'class' => 'wikitable mw-statistics-table' ] );
69
70 # Statistic - pages
71 $text .= $this->getPageStats();
72
73 # Statistic - edits
74 $text .= $this->getEditStats();
75
76 # Statistic - users
77 $text .= $this->getUserStats();
78
79 # Statistic - usergroups
80 $text .= $this->getGroupStats();
81
82 # Statistic - other
83 $extraStats = [];
84 if ( $this->getHookRunner()->onSpecialStatsAddExtra(
85 $extraStats, $this->getContext() )
86 ) {
87 $text .= $this->getOtherStats( $extraStats );
88 }
89
90 $text .= Xml::closeElement( 'table' );
91
92 # Customizable footer
93 $footer = $this->msg( 'statistics-footer' );
94 if ( !$footer->isBlank() ) {
95 $text .= "\n" . $footer->parse();
96 }
97
98 $this->getOutput()->addHTML( $text );
99 }
100
110 private function formatRow( $text, $number, $trExtraParams = [],
111 $descMsg = '', $descMsgParam = ''
112 ) {
113 if ( $descMsg ) {
114 $msg = $this->msg( $descMsg, $descMsgParam );
115 if ( !$msg->isDisabled() ) {
116 $descriptionHtml = $this->msg( 'parentheses' )->rawParams( $msg->parse() )
117 ->escaped();
118 $text .= "<br />" . Html::rawElement(
119 'small',
120 [ 'class' => 'mw-statistic-desc' ],
121 " $descriptionHtml"
122 );
123 }
124 }
125
126 return Html::rawElement( 'tr', $trExtraParams,
127 Html::rawElement( 'td', [], $text ) .
128 Html::rawElement( 'td', [ 'class' => 'mw-statistics-numbers' ], $number )
129 );
130 }
131
137 private function getPageStats() {
138 $linkRenderer = $this->getLinkRenderer();
139
140 $specialAllPagesTitle = SpecialPage::getTitleFor( 'Allpages' );
141 $pageStatsHtml = Xml::openElement( 'tr' ) .
142 Xml::tags( 'th', [ 'colspan' => '2' ], $this->msg( 'statistics-header-pages' )
143 ->parse() ) .
144 Xml::closeElement( 'tr' ) .
145 $this->formatRow(
147 ? $this->msg( 'statistics-articles' )->escaped()
148 : $linkRenderer->makeKnownLink(
149 $specialAllPagesTitle,
150 $this->msg( 'statistics-articles' )->text(),
151 [], [ 'hideredirects' => 1 ] ),
152 $this->getLanguage()->formatNum( $this->good ),
153 [ 'class' => 'mw-statistics-articles' ],
154 'statistics-articles-desc' ) .
155 $this->formatRow( $linkRenderer->makeKnownLink( $specialAllPagesTitle,
156 $this->msg( 'statistics-pages' )->text() ),
157 $this->getLanguage()->formatNum( $this->total ),
158 [ 'class' => 'mw-statistics-pages' ],
159 'statistics-pages-desc' );
160
161 // Show the image row only, when there are files or upload is possible
162 if ( $this->images !== 0 || $this->getConfig()->get( MainConfigNames::EnableUploads ) ) {
163 $pageStatsHtml .= $this->formatRow(
164 $linkRenderer->makeKnownLink( SpecialPage::getTitleFor( 'MediaStatistics' ),
165 $this->msg( 'statistics-files' )->text() ),
166 $this->getLanguage()->formatNum( $this->images ),
167 [ 'class' => 'mw-statistics-files' ], 'statistics-files-desc' );
168 }
169
170 return $pageStatsHtml;
171 }
172
173 private function getEditStats() {
174 return Xml::openElement( 'tr' ) .
175 Xml::tags( 'th', [ 'colspan' => '2' ],
176 $this->msg( 'statistics-header-edits' )->parse() ) .
177 Xml::closeElement( 'tr' ) .
178 $this->formatRow( $this->msg( 'statistics-edits' )->parse(),
179 $this->getLanguage()->formatNum( $this->edits ),
180 [ 'class' => 'mw-statistics-edits' ]
181 ) .
182 $this->formatRow( $this->msg( 'statistics-edits-average' )->parse(),
183 $this->getLanguage()->formatNum(
184 sprintf( '%.2f', $this->total ? $this->edits / $this->total : 0 )
185 ), [ 'class' => 'mw-statistics-edits-average' ]
186 );
187 }
188
189 private function getUserStats() {
190 return Xml::openElement( 'tr' ) .
191 Xml::tags( 'th', [ 'colspan' => '2' ],
192 $this->msg( 'statistics-header-users' )->parse() ) .
193 Xml::closeElement( 'tr' ) .
194 $this->formatRow( $this->msg( 'statistics-users' )->parse() . ' ' .
195 $this->getLinkRenderer()->makeKnownLink(
196 SpecialPage::getTitleFor( 'Listusers' ),
197 $this->msg( 'listgrouprights-members' )->text()
198 ),
199 $this->getLanguage()->formatNum( $this->users ),
200 [ 'class' => 'mw-statistics-users' ]
201 ) .
202 $this->formatRow( $this->msg( 'statistics-users-active' )->parse() . ' ' .
203 $this->getLinkRenderer()->makeKnownLink(
204 SpecialPage::getTitleFor( 'Activeusers' ),
205 $this->msg( 'listgrouprights-members' )->text()
206 ),
207 $this->getLanguage()->formatNum( $this->activeUsers ),
208 [ 'class' => 'mw-statistics-users-active' ],
209 'statistics-users-active-desc',
210 $this->getLanguage()->formatNum(
212 );
213 }
214
215 private function getGroupStats() {
216 $linkRenderer = $this->getLinkRenderer();
217 $lang = $this->getLanguage();
218 $text = '';
219 foreach ( $this->userGroupManager->listAllGroups() as $group ) {
220 $groupnameLocalized = $lang->getGroupName( $group );
221 $linkTarget = UserGroupMembership::getGroupPage( $group )
222 ?: Title::makeTitleSafe( NS_PROJECT, $group );
223
224 if ( $linkTarget ) {
225 $grouppage = $linkRenderer->makeLink(
226 $linkTarget,
227 $groupnameLocalized
228 );
229 } else {
230 $grouppage = htmlspecialchars( $groupnameLocalized );
231 }
232
233 $grouplink = $linkRenderer->makeKnownLink(
234 SpecialPage::getTitleFor( 'Listusers' ),
235 $this->msg( 'listgrouprights-members' )->text(),
236 [],
237 [ 'group' => $group ]
238 );
239 # Add a class when a usergroup contains no members to allow hiding these rows
240 $classZero = '';
241 $countUsers = SiteStats::numberingroup( $group );
242 if ( $countUsers == 0 ) {
243 $classZero = ' statistics-group-zero';
244 }
245 $text .= $this->formatRow( $grouppage . ' ' . $grouplink,
246 $this->getLanguage()->formatNum( $countUsers ),
247 [ 'class' => 'statistics-group-' . Sanitizer::escapeClass( $group ) .
248 $classZero ] );
249 }
250
251 return $text;
252 }
253
261 private function getOtherStats( array $stats ) {
262 $return = '';
263
264 foreach ( $stats as $header => $items ) {
265 // Identify the structure used
266 if ( is_array( $items ) ) {
267 // Ignore headers that are recursively set as legacy header
268 if ( $header !== 'statistics-header-hooks' ) {
269 $return .= $this->formatRowHeader( $header );
270 }
271
272 // Collect all items that belong to the same header
273 foreach ( $items as $key => $value ) {
274 if ( is_array( $value ) ) {
275 $name = $value['name'];
276 $number = $value['number'];
277 } else {
278 $name = $this->msg( $key )->parse();
279 $number = $value;
280 }
281
282 $return .= $this->formatRow(
283 $name,
284 $this->getLanguage()->formatNum( htmlspecialchars( $number ) ),
285 [ 'class' => 'mw-statistics-hook', 'id' => 'mw-' . $key ]
286 );
287 }
288 } else {
289 // Create the legacy header only once
290 if ( $return === '' ) {
291 $return .= $this->formatRowHeader( 'statistics-header-hooks' );
292 }
293
294 // Recursively remap the legacy structure
295 $return .= $this->getOtherStats( [ 'statistics-header-hooks' =>
296 [ $header => $items ] ] );
297 }
298 }
299
300 return $return;
301 }
302
309 private function formatRowHeader( $header ) {
310 return Xml::openElement( 'tr' ) .
311 Xml::tags( 'th', [ 'colspan' => '2' ], $this->msg( $header )->parse() ) .
312 Xml::closeElement( 'tr' );
313 }
314
315 protected function getGroupName() {
316 return 'wiki';
317 }
318}
319
324class_alias( SpecialStatistics::class, 'SpecialStatistics' );
const NS_PROJECT
Definition Defines.php:68
This class is a collection of static functions that serve two purposes:
Definition Html.php:56
A class containing constants representing the names of configuration variables.
const EnableUploads
Name constant for the EnableUploads setting, for use with Config::get()
const MiserMode
Name constant for the MiserMode setting, for use with Config::get()
const ActiveUserDays
Name constant for the ActiveUserDays setting, for use with Config::get()
HTML sanitizer for MediaWiki.
Definition Sanitizer.php:46
Static accessor class for site_stats and related things.
Definition SiteStats.php:36
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
getConfig()
Shortcut to get main config object.
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getLanguage()
Shortcut to get user's language.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
Special page lists various statistics, including the contents of site_stats, plus page view details i...
execute( $par)
Default execute method Checks user permissions.
__construct(UserGroupManager $userGroupManager)
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Represents a title within MediaWiki.
Definition Title.php:78
Represents a "user group membership" – a specific instance of a user belonging to a group.
Module of static functions for generating XML.
Definition Xml.php:33
static closeElement( $element)
Shortcut to close an XML element.
Definition Xml.php:124
static openElement( $element, $attribs=null)
This opens an XML element.
Definition Xml.php:115
static tags( $element, $attribs, $contents)
Same as Xml::element(), but does not escape contents.
Definition Xml.php:141
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
$header
$footer