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