MediaWiki REL1_37
SpecialStatistics.php
Go to the documentation of this file.
1<?php
33
34 public function __construct() {
35 parent::__construct( 'Statistics' );
36 }
37
38 public function execute( $par ) {
39 $this->setHeaders();
40 $this->outputHeader();
41 $this->getOutput()->addModuleStyles( 'mediawiki.special' );
42
43 $this->edits = SiteStats::edits();
44 $this->good = SiteStats::articles();
45 $this->images = SiteStats::images();
46 $this->total = SiteStats::pages();
47 $this->users = SiteStats::users();
48 $this->activeUsers = SiteStats::activeUsers();
49
50 $text = Xml::openElement( 'table', [ 'class' => 'wikitable mw-statistics-table' ] );
51
52 # Statistic - pages
53 $text .= $this->getPageStats();
54
55 # Statistic - edits
56 $text .= $this->getEditStats();
57
58 # Statistic - users
59 $text .= $this->getUserStats();
60
61 # Statistic - usergroups
62 $text .= $this->getGroupStats();
63
64 # Statistic - other
65 $extraStats = [];
66 if ( $this->getHookRunner()->onSpecialStatsAddExtra(
67 $extraStats, $this->getContext() )
68 ) {
69 $text .= $this->getOtherStats( $extraStats );
70 }
71
72 $text .= Xml::closeElement( 'table' );
73
74 # Customizable footer
75 $footer = $this->msg( 'statistics-footer' );
76 if ( !$footer->isBlank() ) {
77 $text .= "\n" . $footer->parse();
78 }
79
80 $this->getOutput()->addHTML( $text );
81 }
82
92 private function formatRow( $text, $number, $trExtraParams = [],
93 $descMsg = '', $descMsgParam = ''
94 ) {
95 if ( $descMsg ) {
96 $msg = $this->msg( $descMsg, $descMsgParam );
97 if ( !$msg->isDisabled() ) {
98 $descriptionHtml = $this->msg( 'parentheses' )->rawParams( $msg->parse() )
99 ->escaped();
100 $text .= "<br />" . Html::rawElement(
101 'small',
102 [ 'class' => 'mw-statistic-desc' ],
103 " $descriptionHtml"
104 );
105 }
106 }
107
108 return Html::rawElement( 'tr', $trExtraParams,
109 Html::rawElement( 'td', [], $text ) .
110 Html::rawElement( 'td', [ 'class' => 'mw-statistics-numbers' ], $number )
111 );
112 }
113
119 private function getPageStats() {
121
122 $specialAllPagesTitle = SpecialPage::getTitleFor( 'Allpages' );
123 $pageStatsHtml = Xml::openElement( 'tr' ) .
124 Xml::tags( 'th', [ 'colspan' => '2' ], $this->msg( 'statistics-header-pages' )
125 ->parse() ) .
126 Xml::closeElement( 'tr' ) .
127 $this->formatRow(
128 $this->getConfig()->get( 'MiserMode' )
129 ? $this->msg( 'statistics-articles' )->escaped()
131 $specialAllPagesTitle,
132 $this->msg( 'statistics-articles' )->text(),
133 [], [ 'hideredirects' => 1 ] ),
134 $this->getLanguage()->formatNum( $this->good ),
135 [ 'class' => 'mw-statistics-articles' ],
136 'statistics-articles-desc' ) .
137 $this->formatRow( $linkRenderer->makeKnownLink( $specialAllPagesTitle,
138 $this->msg( 'statistics-pages' )->text() ),
139 $this->getLanguage()->formatNum( $this->total ),
140 [ 'class' => 'mw-statistics-pages' ],
141 'statistics-pages-desc' );
142
143 // Show the image row only, when there are files or upload is possible
144 if ( $this->images !== 0 || $this->getConfig()->get( 'EnableUploads' ) ) {
145 $pageStatsHtml .= $this->formatRow(
147 $this->msg( 'statistics-files' )->text() ),
148 $this->getLanguage()->formatNum( $this->images ),
149 [ 'class' => 'mw-statistics-files' ], 'statistics-files-desc' );
150 }
151
152 return $pageStatsHtml;
153 }
154
155 private function getEditStats() {
156 return Xml::openElement( 'tr' ) .
157 Xml::tags( 'th', [ 'colspan' => '2' ],
158 $this->msg( 'statistics-header-edits' )->parse() ) .
159 Xml::closeElement( 'tr' ) .
160 $this->formatRow( $this->msg( 'statistics-edits' )->parse(),
161 $this->getLanguage()->formatNum( $this->edits ),
162 [ 'class' => 'mw-statistics-edits' ]
163 ) .
164 $this->formatRow( $this->msg( 'statistics-edits-average' )->parse(),
165 $this->getLanguage()->formatNum(
166 sprintf( '%.2f', $this->total ? $this->edits / $this->total : 0 )
167 ), [ 'class' => 'mw-statistics-edits-average' ]
168 );
169 }
170
171 private function getUserStats() {
172 return Xml::openElement( 'tr' ) .
173 Xml::tags( 'th', [ 'colspan' => '2' ],
174 $this->msg( 'statistics-header-users' )->parse() ) .
175 Xml::closeElement( 'tr' ) .
176 $this->formatRow( $this->msg( 'statistics-users' )->parse() . ' ' .
177 $this->getLinkRenderer()->makeKnownLink(
178 SpecialPage::getTitleFor( 'Listusers' ),
179 $this->msg( 'listgrouprights-members' )->text()
180 ),
181 $this->getLanguage()->formatNum( $this->users ),
182 [ 'class' => 'mw-statistics-users' ]
183 ) .
184 $this->formatRow( $this->msg( 'statistics-users-active' )->parse() . ' ' .
185 $this->getLinkRenderer()->makeKnownLink(
186 SpecialPage::getTitleFor( 'Activeusers' ),
187 $this->msg( 'listgrouprights-members' )->text()
188 ),
189 $this->getLanguage()->formatNum( $this->activeUsers ),
190 [ 'class' => 'mw-statistics-users-active' ],
191 'statistics-users-active-desc',
192 $this->getLanguage()->formatNum(
193 $this->getConfig()->get( 'ActiveUserDays' ) )
194 );
195 }
196
197 private function getGroupStats() {
199 $text = '';
200 foreach ( $this->getConfig()->get( 'GroupPermissions' ) as $group => $permissions ) {
201 # Skip generic * and implicit groups
202 if ( in_array( $group, $this->getConfig()->get( 'ImplicitGroups' ) )
203 || $group == '*' ) {
204 continue;
205 }
206 $groupnameLocalized = UserGroupMembership::getGroupName( $group );
207 $linkTarget = UserGroupMembership::getGroupPage( $group )
208 ?: Title::makeTitleSafe( NS_PROJECT, $group );
209
210 if ( $linkTarget ) {
211 $grouppage = $linkRenderer->makeLink(
212 $linkTarget,
213 $groupnameLocalized
214 );
215 } else {
216 $grouppage = htmlspecialchars( $groupnameLocalized );
217 }
218
219 $grouplink = $linkRenderer->makeKnownLink(
220 SpecialPage::getTitleFor( 'Listusers' ),
221 $this->msg( 'listgrouprights-members' )->text(),
222 [],
223 [ 'group' => $group ]
224 );
225 # Add a class when a usergroup contains no members to allow hiding these rows
226 $classZero = '';
227 $countUsers = SiteStats::numberingroup( $group );
228 if ( $countUsers == 0 ) {
229 $classZero = ' statistics-group-zero';
230 }
231 $text .= $this->formatRow( $grouppage . ' ' . $grouplink,
232 $this->getLanguage()->formatNum( $countUsers ),
233 [ 'class' => 'statistics-group-' . Sanitizer::escapeClass( $group ) .
234 $classZero ] );
235 }
236
237 return $text;
238 }
239
247 private function getOtherStats( array $stats ) {
248 $return = '';
249
250 foreach ( $stats as $header => $items ) {
251 // Identify the structure used
252 if ( is_array( $items ) ) {
253 // Ignore headers that are recursively set as legacy header
254 if ( $header !== 'statistics-header-hooks' ) {
255 $return .= $this->formatRowHeader( $header );
256 }
257
258 // Collect all items that belong to the same header
259 foreach ( $items as $key => $value ) {
260 if ( is_array( $value ) ) {
261 $name = $value['name'];
262 $number = $value['number'];
263 } else {
264 $name = $this->msg( $key )->parse();
265 $number = $value;
266 }
267
268 $return .= $this->formatRow(
269 $name,
270 $this->getLanguage()->formatNum( htmlspecialchars( $number ) ),
271 [ 'class' => 'mw-statistics-hook', 'id' => 'mw-' . $key ]
272 );
273 }
274 } else {
275 // Create the legacy header only once
276 if ( $return === '' ) {
277 $return .= $this->formatRowHeader( 'statistics-header-hooks' );
278 }
279
280 // Recursively remap the legacy structure
281 $return .= $this->getOtherStats( [ 'statistics-header-hooks' =>
282 [ $header => $items ] ] );
283 }
284 }
285
286 return $return;
287 }
288
295 private function formatRowHeader( $header ) {
296 return Xml::openElement( 'tr' ) .
297 Xml::tags( 'th', [ 'colspan' => '2' ], $this->msg( $header )->parse() ) .
298 Xml::closeElement( 'tr' );
299 }
300
301 protected function getGroupName() {
302 return 'wiki';
303 }
304}
const NS_PROJECT
Definition Defines.php:68
makeKnownLink( $target, $text=null, array $extraAttribs=[], array $query=[])
makeLink( $target, $text=null, array $extraAttribs=[], array $query=[])
static articles()
static images()
static edits()
Definition SiteStats.php:94
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.
LinkRenderer null $linkRenderer
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...
getOtherStats(array $stats)
Conversion of external statistics into an internal representation Following a ([<header-message>][<it...
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
getPageStats()
Each of these methods is pretty self-explanatory, get a particular row for the table of statistics.
formatRowHeader( $header)
Format row header.
formatRow( $text, $number, $trExtraParams=[], $descMsg='', $descMsgParam='')
Format a row.
execute( $par)
Default execute method Checks user permissions.
$header
$footer