MediaWiki  master
AllMessagesTablePager.php
Go to the documentation of this file.
1 <?php
25 
33 
37  protected $langcode;
38 
42  protected $foreign;
43 
47  protected $prefix;
48 
52  protected $suffix;
53 
57  public $lang;
58 
62  public $custom;
63 
69  public function __construct( ?IContextSource $context, FormOptions $opts,
71  ) {
72  parent::__construct( $context, $linkRenderer );
73 
74  $this->mIndexField = 'am_title';
75  // FIXME: Why does this need to be set to DIR_DESCENDING to produce ascending ordering?
76  $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
77 
78  $contLang = MediaWikiServices::getInstance()->getContentLanguage();
79  $this->lang = wfGetLangObj( $opts->getValue( 'lang' ) );
80 
81  $this->langcode = $this->lang->getCode();
82  $this->foreign = !$this->lang->equals( $contLang );
83 
84  $filter = $opts->getValue( 'filter' );
85  if ( $filter === 'all' ) {
86  $this->custom = null; // So won't match in either case
87  } else {
88  $this->custom = ( $filter === 'unmodified' );
89  }
90 
91  $prefix = $this->getLanguage()->ucfirst( $opts->getValue( 'prefix' ) );
92  $prefix = $prefix !== '' ?
93  Title::makeTitleSafe( NS_MEDIAWIKI, $opts->getValue( 'prefix' ) ) :
94  null;
95 
96  if ( $prefix !== null ) {
97  $displayPrefix = $prefix->getDBkey();
98  $this->prefix = '/^' . preg_quote( $displayPrefix, '/' ) . '/i';
99  } else {
100  $this->prefix = false;
101  }
102 
103  // The suffix that may be needed for message names if we're in a
104  // different language (eg [[MediaWiki:Foo/fr]]: $suffix = '/fr'
105  if ( $this->foreign ) {
106  $this->suffix = '/' . $this->langcode;
107  } else {
108  $this->suffix = '';
109  }
110  }
111 
112  private function getAllMessages( $descending ) {
113  $messageNames = MediaWikiServices::getInstance()
114  ->getLocalisationCache()
115  ->getSubitemList( 'en', 'messages' );
116 
117  // Normalise message names so they look like page titles and sort correctly - T86139
118  $messageNames = array_map( [ $this->lang, 'ucfirst' ], $messageNames );
119 
120  if ( $descending ) {
121  rsort( $messageNames );
122  } else {
123  asort( $messageNames );
124  }
125 
126  return $messageNames;
127  }
128 
140  public static function getCustomisedStatuses( $messageNames, $langcode = 'en', $foreign = false ) {
141  // FIXME: This function should be moved to Language:: or something.
142 
143  $dbr = wfGetDB( DB_REPLICA );
144  $res = $dbr->select( 'page',
145  [ 'page_namespace', 'page_title' ],
146  [ 'page_namespace' => [ NS_MEDIAWIKI, NS_MEDIAWIKI_TALK ] ],
147  __METHOD__,
148  [ 'USE INDEX' => 'name_title' ]
149  );
150  $xNames = array_flip( $messageNames );
151 
152  $pageFlags = $talkFlags = [];
153 
154  foreach ( $res as $s ) {
155  $exists = false;
156 
157  if ( $foreign ) {
158  $titleParts = explode( '/', $s->page_title );
159  if ( count( $titleParts ) === 2 &&
160  $langcode === $titleParts[1] &&
161  isset( $xNames[$titleParts[0]] )
162  ) {
163  $exists = $titleParts[0];
164  }
165  } elseif ( isset( $xNames[$s->page_title] ) ) {
166  $exists = $s->page_title;
167  }
168 
170  if ( $exists && $title->inNamespace( NS_MEDIAWIKI ) ) {
171  $pageFlags[$exists] = true;
172  } elseif ( $exists && $title->inNamespace( NS_MEDIAWIKI_TALK ) ) {
173  $talkFlags[$exists] = true;
174  }
175  }
176 
177  return [ 'pages' => $pageFlags, 'talks' => $talkFlags ];
178  }
179 
188  public function reallyDoQuery( $offset, $limit, $order ) {
189  $asc = ( $order === self::QUERY_ASCENDING );
190 
191  $messageNames = $this->getAllMessages( $order );
192  $statuses = self::getCustomisedStatuses( $messageNames, $this->langcode, $this->foreign );
193 
194  $rows = [];
195  $count = 0;
196  foreach ( $messageNames as $key ) {
197  $customised = isset( $statuses['pages'][$key] );
198  if ( $customised !== $this->custom &&
199  ( $asc && ( $key < $offset || !$offset ) || !$asc && $key > $offset ) &&
200  ( ( $this->prefix && preg_match( $this->prefix, $key ) ) || $this->prefix === false )
201  ) {
202  $actual = $this->msg( $key )->inLanguage( $this->lang )->plain();
203  $default = $this->msg( $key )->inLanguage( $this->lang )->useDatabase( false )->plain();
204  $rows[] = [
205  'am_title' => $key,
206  'am_actual' => $actual,
207  'am_default' => $default,
208  'am_customised' => $customised,
209  'am_talk_exists' => isset( $statuses['talks'][$key] )
210  ];
211  $count++;
212  }
213 
214  if ( $count === $limit ) {
215  break;
216  }
217  }
218 
219  return new FakeResultWrapper( $rows );
220  }
221 
222  protected function getStartBody() {
223  $tableClass = $this->getTableClass();
224  return Xml::openElement( 'table', [
225  'class' => "mw-datatable $tableClass",
226  'id' => 'mw-allmessagestable'
227  ] ) .
228  "\n" .
229  "<thead><tr>
230  <th rowspan=\"2\">" .
231  $this->msg( 'allmessagesname' )->escaped() . "
232  </th>
233  <th>" .
234  $this->msg( 'allmessagesdefault' )->escaped() .
235  "</th>
236  </tr>\n
237  <tr>
238  <th>" .
239  $this->msg( 'allmessagescurrent' )->escaped() .
240  "</th>
241  </tr></thead>\n";
242  }
243 
244  protected function getEndBody() {
245  return Html::closeElement( 'table' );
246  }
247 
248  public function formatValue( $field, $value ) {
249  $linkRenderer = $this->getLinkRenderer();
250  switch ( $field ) {
251  case 'am_title' :
252  $title = Title::makeTitle( NS_MEDIAWIKI, $value . $this->suffix );
253  $talk = Title::makeTitle( NS_MEDIAWIKI_TALK, $value . $this->suffix );
254  $translation = Linker::makeExternalLink(
255  'https://translatewiki.net/w/i.php?' . wfArrayToCgi( [
256  'title' => 'Special:SearchTranslations',
257  'group' => 'mediawiki',
258  'grouppath' => 'mediawiki',
259  'language' => $this->getLanguage()->getCode(),
260  'query' => $value . ' ' . $this->msg( $value )->plain()
261  ] ),
262  $this->msg( 'allmessages-filter-translate' )->text()
263  );
264  $talkLink = $this->msg( 'talkpagelinktext' )->escaped();
265 
266  if ( $this->mCurrentRow->am_customised ) {
267  $title = $linkRenderer->makeKnownLink( $title, $this->getLanguage()->lcfirst( $value ) );
268  } else {
270  $title, $this->getLanguage()->lcfirst( $value )
271  );
272  }
273  if ( $this->mCurrentRow->am_talk_exists ) {
274  $talk = $linkRenderer->makeKnownLink( $talk, $talkLink );
275  } else {
276  $talk = $linkRenderer->makeBrokenLink(
277  $talk,
278  $talkLink
279  );
280  }
281 
282  return $title . ' ' .
283  $this->msg( 'parentheses' )->rawParams( $talk )->escaped() .
284  ' ' .
285  $this->msg( 'parentheses' )->rawParams( $translation )->escaped();
286 
287  case 'am_default' :
288  case 'am_actual' :
289  return Sanitizer::escapeHtmlAllowEntities( $value );
290  }
291 
292  return '';
293  }
294 
299  public function formatRow( $row ) {
300  // Do all the normal stuff
301  $s = parent::formatRow( $row );
302 
303  // But if there's a customised message, add that too.
304  if ( $row->am_customised ) {
305  $s .= Html::openElement( 'tr', $this->getRowAttrs( $row ) );
306  $formatted = strval( $this->formatValue( 'am_actual', $row->am_actual ) );
307 
308  if ( $formatted === '' ) {
309  $formatted = "\u{00A0}";
310  }
311 
312  $s .= Html::element( 'td', $this->getCellAttrs( 'am_actual', $row->am_actual ), $formatted )
313  . Html::closeElement( 'tr' );
314  }
315 
316  return Html::rawElement( 'tbody', [], $s );
317  }
318 
319  protected function getRowAttrs( $row ) {
320  return [];
321  }
322 
328  protected function getCellAttrs( $field, $value ) {
329  $attr = [];
330  if ( $field === 'am_title' ) {
331  if ( $this->mCurrentRow->am_customised ) {
332  $attr += [ 'rowspan' => '2' ];
333  }
334  } else {
335  $attr += [
336  'lang' => $this->lang->getHtmlCode(),
337  'dir' => $this->lang->getDir(),
338  ];
339  if ( $this->mCurrentRow->am_customised ) {
340  // CSS class: am_default, am_actual
341  $attr += [ 'class' => $field ];
342  }
343  }
344  return $attr;
345  }
346 
347  // This is not actually used, as getStartBody is overridden above
348  protected function getFieldNames() {
349  return [
350  'am_title' => $this->msg( 'allmessagesname' )->text(),
351  'am_default' => $this->msg( 'allmessagesdefault' )->text()
352  ];
353  }
354 
355  public function getTitle() {
356  return SpecialPage::getTitleFor( 'Allmessages', false );
357  }
358 
359  protected function isFieldSortable( $x ) {
360  return false;
361  }
362 
363  public function getDefaultSort() {
364  return '';
365  }
366 
367  public function getQueryInfo() {
368  return [];
369  }
370 
371 }
AllMessagesTablePager\getCellAttrs
getCellAttrs( $field, $value)
Definition: AllMessagesTablePager.php:328
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:33
AllMessagesTablePager
Use TablePager for prettified output.
Definition: AllMessagesTablePager.php:32
AllMessagesTablePager\$custom
null bool $custom
Definition: AllMessagesTablePager.php:62
AllMessagesTablePager\formatValue
formatValue( $field, $value)
Format a table cell.
Definition: AllMessagesTablePager.php:248
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:144
IndexPager\QUERY_ASCENDING
const QUERY_ASCENDING
Backwards-compatible constant for reallyDoQuery() (do not change)
Definition: IndexPager.php:79
FormOptions\getValue
getValue( $name)
Get the value for the given option name.
Definition: FormOptions.php:182
MediaWiki\Linker\LinkRenderer
Class that generates HTML links for pages.
Definition: LinkRenderer.php:42
TablePager\getTableClass
getTableClass()
TablePager relies on mw-datatable for styling, see T214208.
Definition: TablePager.php:266
$s
$s
Definition: mergeMessageFileList.php:185
IndexPager\$linkRenderer
LinkRenderer $linkRenderer
Definition: IndexPager.php:163
SpecialPage\getTitleFor
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,...
Definition: SpecialPage.php:83
AllMessagesTablePager\formatRow
formatRow( $row)
Definition: AllMessagesTablePager.php:299
$res
$res
Definition: testCompression.php:57
Wikimedia\Rdbms\FakeResultWrapper
Overloads the relevant methods of the real ResultsWrapper so it doesn't go anywhere near an actual da...
Definition: FakeResultWrapper.php:11
Xml\openElement
static openElement( $element, $attribs=null)
This opens an XML element.
Definition: Xml.php:108
AllMessagesTablePager\$langcode
string $langcode
Definition: AllMessagesTablePager.php:37
AllMessagesTablePager\getTitle
getTitle()
Definition: AllMessagesTablePager.php:355
$dbr
$dbr
Definition: testCompression.php:54
ContextSource\getLanguage
getLanguage()
Definition: ContextSource.php:128
Html\closeElement
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:315
AllMessagesTablePager\$prefix
string $prefix
Definition: AllMessagesTablePager.php:47
AllMessagesTablePager\getStartBody
getStartBody()
Definition: AllMessagesTablePager.php:222
AllMessagesTablePager\getCustomisedStatuses
static getCustomisedStatuses( $messageNames, $langcode='en', $foreign=false)
Determine which of the MediaWiki and MediaWiki_talk namespace pages exist.
Definition: AllMessagesTablePager.php:140
AllMessagesTablePager\getEndBody
getEndBody()
Definition: AllMessagesTablePager.php:244
Title\newFromRow
static newFromRow( $row)
Make a Title object from a DB row.
Definition: Title.php:527
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2463
AllMessagesTablePager\$foreign
bool $foreign
Definition: AllMessagesTablePager.php:42
NS_MEDIAWIKI_TALK
const NS_MEDIAWIKI_TALK
Definition: Defines.php:78
TablePager
Table-based display with a user-selectable sort order.
Definition: TablePager.php:30
AllMessagesTablePager\getDefaultSort
getDefaultSort()
The database field name used as a default sort order.
Definition: AllMessagesTablePager.php:363
wfGetLangObj
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
Definition: GlobalFunctions.php:1148
$title
$title
Definition: testCompression.php:38
Linker\makeExternalLink
static makeExternalLink( $url, $text, $escape=true, $linktype='', $attribs=[], $title=null)
Make an external link.
Definition: Linker.php:845
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:595
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
AllMessagesTablePager\getFieldNames
getFieldNames()
An array mapping database field names to a textual description of the field name, for use in the tabl...
Definition: AllMessagesTablePager.php:348
ContextSource\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:168
AllMessagesTablePager\$suffix
string $suffix
Definition: AllMessagesTablePager.php:52
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:621
AllMessagesTablePager\getQueryInfo
getQueryInfo()
Provides all parameters needed for the main paged query.
Definition: AllMessagesTablePager.php:367
AllMessagesTablePager\isFieldSortable
isFieldSortable( $x)
Return true if the named field should be sortable by the UI, false otherwise.
Definition: AllMessagesTablePager.php:359
IndexPager\getLinkRenderer
getLinkRenderer()
Definition: IndexPager.php:929
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:53
IndexPager\DIR_DESCENDING
const DIR_DESCENDING
Backwards-compatible constant for $mDefaultDirection field (do not change)
Definition: IndexPager.php:76
AllMessagesTablePager\__construct
__construct(?IContextSource $context, FormOptions $opts, LinkRenderer $linkRenderer)
Definition: AllMessagesTablePager.php:69
MediaWiki\Linker\LinkRenderer\makeKnownLink
makeKnownLink(LinkTarget $target, $text=null, array $extraAttribs=[], array $query=[])
Definition: LinkRenderer.php:302
Html\openElement
static openElement( $element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing '/'...
Definition: Html.php:251
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:209
AllMessagesTablePager\getAllMessages
getAllMessages( $descending)
Definition: AllMessagesTablePager.php:112
NS_MEDIAWIKI
const NS_MEDIAWIKI
Definition: Defines.php:77
FormOptions
Helper class to keep track of options when mixing links and form elements.
Definition: FormOptions.php:35
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:231
AllMessagesTablePager\getRowAttrs
getRowAttrs( $row)
Get attributes to be applied to the given row.
Definition: AllMessagesTablePager.php:319
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:39
MediaWiki\Linker\LinkRenderer\makeBrokenLink
makeBrokenLink(LinkTarget $target, $text=null, array $extraAttribs=[], array $query=[])
Definition: LinkRenderer.php:330
Sanitizer\escapeHtmlAllowEntities
static escapeHtmlAllowEntities( $html)
Given HTML input, escape with htmlspecialchars but un-escape entities.
Definition: Sanitizer.php:1275
AllMessagesTablePager\$lang
Language $lang
Definition: AllMessagesTablePager.php:57
wfArrayToCgi
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
Definition: GlobalFunctions.php:347
AllMessagesTablePager\reallyDoQuery
reallyDoQuery( $offset, $limit, $order)
This function normally does a database query to get the results; we need to make a pretend result usi...
Definition: AllMessagesTablePager.php:188