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