MediaWiki  master
AllMessagesTablePager.php
Go to the documentation of this file.
1 <?php
27 
35 
39  protected $langcode;
40 
44  protected $foreign;
45 
49  protected $prefix;
50 
54  protected $suffix;
55 
59  public $lang;
60 
64  public $custom;
65 
68 
77  public function __construct(
79  FormOptions $opts,
81  Language $contentLanguage,
83  ILoadBalancer $loadBalancer
84  ) {
85  // Set database before parent constructor to avoid setting it there with wfGetDB
86  $this->mDb = $loadBalancer->getConnectionRef( ILoadBalancer::DB_REPLICA );
87  parent::__construct( $context, $linkRenderer );
88  $this->localisationCache = $localisationCache;
89 
90  $this->mIndexField = 'am_title';
91  // FIXME: Why does this need to be set to DIR_DESCENDING to produce ascending ordering?
92  $this->mDefaultDirection = IndexPager::DIR_DESCENDING;
93 
94  $this->lang = wfGetLangObj( $opts->getValue( 'lang' ) );
95 
96  $this->langcode = $this->lang->getCode();
97  $this->foreign = !$this->lang->equals( $contentLanguage );
98 
99  $filter = $opts->getValue( 'filter' );
100  if ( $filter === 'all' ) {
101  $this->custom = null; // So won't match in either case
102  } else {
103  $this->custom = ( $filter === 'unmodified' );
104  }
105 
106  $prefix = $this->getLanguage()->ucfirst( $opts->getValue( 'prefix' ) );
107  $prefix = $prefix !== '' ?
108  Title::makeTitleSafe( NS_MEDIAWIKI, $opts->getValue( 'prefix' ) ) :
109  null;
110 
111  if ( $prefix !== null ) {
112  $displayPrefix = $prefix->getDBkey();
113  $this->prefix = '/^' . preg_quote( $displayPrefix, '/' ) . '/i';
114  } else {
115  $this->prefix = false;
116  }
117 
118  // The suffix that may be needed for message names if we're in a
119  // different language (eg [[MediaWiki:Foo/fr]]: $suffix = '/fr'
120  if ( $this->foreign ) {
121  $this->suffix = '/' . $this->langcode;
122  } else {
123  $this->suffix = '';
124  }
125  }
126 
127  private function getAllMessages( $descending ) {
128  $messageNames = $this->localisationCache->getSubitemList( 'en', 'messages' );
129 
130  // Normalise message names so they look like page titles and sort correctly - T86139
131  $messageNames = array_map( [ $this->lang, 'ucfirst' ], $messageNames );
132 
133  if ( $descending ) {
134  rsort( $messageNames );
135  } else {
136  asort( $messageNames );
137  }
138 
139  return $messageNames;
140  }
141 
156  public static function getCustomisedStatuses(
157  $messageNames,
158  $langcode = 'en',
159  $foreign = false,
160  IDatabase $dbr = null
161  ) {
162  // FIXME: This function should be moved to Language:: or something.
163  // Fallback to global state, if not provided
164  $dbr = $dbr ?? wfGetDB( DB_REPLICA );
165 
166  $res = $dbr->select( 'page',
167  [ 'page_namespace', 'page_title' ],
168  [ 'page_namespace' => [ NS_MEDIAWIKI, NS_MEDIAWIKI_TALK ] ],
169  __METHOD__,
170  [ 'USE INDEX' => 'name_title' ]
171  );
172  $xNames = array_flip( $messageNames );
173 
174  $pageFlags = $talkFlags = [];
175 
176  foreach ( $res as $s ) {
177  $exists = false;
178 
179  if ( $foreign ) {
180  $titleParts = explode( '/', $s->page_title );
181  if ( count( $titleParts ) === 2 &&
182  $langcode === $titleParts[1] &&
183  isset( $xNames[$titleParts[0]] )
184  ) {
185  $exists = $titleParts[0];
186  }
187  } elseif ( isset( $xNames[$s->page_title] ) ) {
188  $exists = $s->page_title;
189  }
190 
192  if ( $exists && $title->inNamespace( NS_MEDIAWIKI ) ) {
193  $pageFlags[$exists] = true;
194  } elseif ( $exists && $title->inNamespace( NS_MEDIAWIKI_TALK ) ) {
195  $talkFlags[$exists] = true;
196  }
197  }
198 
199  return [ 'pages' => $pageFlags, 'talks' => $talkFlags ];
200  }
201 
210  public function reallyDoQuery( $offset, $limit, $order ) {
211  $asc = ( $order === self::QUERY_ASCENDING );
212 
213  $messageNames = $this->getAllMessages( $order );
214  $statuses = self::getCustomisedStatuses(
215  $messageNames,
216  $this->langcode,
217  $this->foreign,
218  $this->getDatabase()
219  );
220 
221  $rows = [];
222  $count = 0;
223  foreach ( $messageNames as $key ) {
224  $customised = isset( $statuses['pages'][$key] );
225  if ( $customised !== $this->custom &&
226  ( $asc && ( $key < $offset || !$offset ) || !$asc && $key > $offset ) &&
227  ( ( $this->prefix && preg_match( $this->prefix, $key ) ) || $this->prefix === false )
228  ) {
229  $actual = $this->msg( $key )->inLanguage( $this->lang )->plain();
230  $default = $this->msg( $key )->inLanguage( $this->lang )->useDatabase( false )->plain();
231  $rows[] = [
232  'am_title' => $key,
233  'am_actual' => $actual,
234  'am_default' => $default,
235  'am_customised' => $customised,
236  'am_talk_exists' => isset( $statuses['talks'][$key] )
237  ];
238  $count++;
239  }
240 
241  if ( $count === $limit ) {
242  break;
243  }
244  }
245 
246  return new FakeResultWrapper( $rows );
247  }
248 
249  protected function getStartBody() {
250  $tableClass = $this->getTableClass();
251  return Xml::openElement( 'table', [
252  'class' => "mw-datatable $tableClass",
253  'id' => 'mw-allmessagestable'
254  ] ) .
255  "\n" .
256  "<thead><tr>
257  <th rowspan=\"2\">" .
258  $this->msg( 'allmessagesname' )->escaped() . "
259  </th>
260  <th>" .
261  $this->msg( 'allmessagesdefault' )->escaped() .
262  "</th>
263  </tr>\n
264  <tr>
265  <th>" .
266  $this->msg( 'allmessagescurrent' )->escaped() .
267  "</th>
268  </tr></thead>\n";
269  }
270 
271  protected function getEndBody() {
272  return Html::closeElement( 'table' );
273  }
274 
280  public function formatValue( $field, $value ) {
281  $linkRenderer = $this->getLinkRenderer();
282  switch ( $field ) {
283  case 'am_title':
284  $title = Title::makeTitle( NS_MEDIAWIKI, $value . $this->suffix );
285  $talk = Title::makeTitle( NS_MEDIAWIKI_TALK, $value . $this->suffix );
286  $translation = Linker::makeExternalLink(
287  'https://translatewiki.net/w/i.php?' . wfArrayToCgi( [
288  'title' => 'Special:SearchTranslations',
289  'group' => 'mediawiki',
290  'grouppath' => 'mediawiki',
291  'language' => $this->getLanguage()->getCode(),
292  'query' => $value . ' ' . $this->msg( $value )->plain()
293  ] ),
294  $this->msg( 'allmessages-filter-translate' )->text()
295  );
296  $talkLink = $this->msg( 'talkpagelinktext' )->text();
297 
298  if ( $this->mCurrentRow->am_customised ) {
299  $title = $linkRenderer->makeKnownLink( $title, $this->getLanguage()->lcfirst( $value ) );
300  } else {
302  $title, $this->getLanguage()->lcfirst( $value )
303  );
304  }
305  if ( $this->mCurrentRow->am_talk_exists ) {
306  $talk = $linkRenderer->makeKnownLink( $talk, $talkLink );
307  } else {
308  $talk = $linkRenderer->makeBrokenLink(
309  $talk,
310  $talkLink
311  );
312  }
313 
314  return $title . ' ' .
315  $this->msg( 'parentheses' )->rawParams( $talk )->escaped() .
316  ' ' .
317  $this->msg( 'parentheses' )->rawParams( $translation )->escaped();
318 
319  case 'am_default':
320  case 'am_actual':
321  return Sanitizer::escapeHtmlAllowEntities( $value );
322  }
323 
324  return '';
325  }
326 
331  public function formatRow( $row ) {
332  // Do all the normal stuff
333  $s = parent::formatRow( $row );
334 
335  // But if there's a customised message, add that too.
336  if ( $row->am_customised ) {
337  $s .= Html::openElement( 'tr', $this->getRowAttrs( $row ) );
338  $formatted = strval( $this->formatValue( 'am_actual', $row->am_actual ) );
339 
340  if ( $formatted === '' ) {
341  $formatted = "\u{00A0}";
342  }
343 
344  $s .= Html::rawElement( 'td', $this->getCellAttrs( 'am_actual', $row->am_actual ), $formatted )
345  . Html::closeElement( 'tr' );
346  }
347 
348  return Html::rawElement( 'tbody', [], $s );
349  }
350 
351  protected function getRowAttrs( $row ) {
352  return [];
353  }
354 
360  protected function getCellAttrs( $field, $value ) {
361  $attr = [];
362  if ( $field === 'am_title' ) {
363  if ( $this->mCurrentRow->am_customised ) {
364  $attr += [ 'rowspan' => '2' ];
365  }
366  } else {
367  $attr += [
368  'lang' => $this->lang->getHtmlCode(),
369  'dir' => $this->lang->getDir(),
370  ];
371  if ( $this->mCurrentRow->am_customised ) {
372  // CSS class: am_default, am_actual
373  $attr += [ 'class' => $field ];
374  }
375  }
376  return $attr;
377  }
378 
379  // This is not actually used, as getStartBody is overridden above
380  protected function getFieldNames() {
381  return [
382  'am_title' => $this->msg( 'allmessagesname' )->text(),
383  'am_default' => $this->msg( 'allmessagesdefault' )->text()
384  ];
385  }
386 
387  public function getTitle() {
388  return SpecialPage::getTitleFor( 'Allmessages', false );
389  }
390 
391  protected function isFieldSortable( $x ) {
392  return false;
393  }
394 
395  public function getDefaultSort() {
396  return '';
397  }
398 
399  public function getQueryInfo() {
400  return [];
401  }
402 
403 }
AllMessagesTablePager\getCellAttrs
getCellAttrs( $field, $value)
Definition: AllMessagesTablePager.php:360
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:38
AllMessagesTablePager
Use TablePager for prettified output.
Definition: AllMessagesTablePager.php:34
AllMessagesTablePager\$custom
null bool $custom
Definition: AllMessagesTablePager.php:64
NS_MEDIAWIKI
const NS_MEDIAWIKI
Definition: Defines.php:72
AllMessagesTablePager\formatValue
formatValue( $field, $value)
Definition: AllMessagesTablePager.php:280
IndexPager\QUERY_ASCENDING
const QUERY_ASCENDING
Backwards-compatible constant for reallyDoQuery() (do not change)
Definition: IndexPager.php:83
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:41
NS_MEDIAWIKI_TALK
const NS_MEDIAWIKI_TALK
Definition: Defines.php:73
TablePager\getTableClass
getTableClass()
TablePager relies on mw-datatable for styling, see T214208.
Definition: TablePager.php:283
IndexPager\getDatabase
getDatabase()
Get the Database object in use.
Definition: IndexPager.php:244
AllMessagesTablePager\__construct
__construct(?IContextSource $context, FormOptions $opts, LinkRenderer $linkRenderer, Language $contentLanguage, LocalisationCache $localisationCache, ILoadBalancer $loadBalancer)
Definition: AllMessagesTablePager.php:77
IndexPager\$linkRenderer
LinkRenderer $linkRenderer
Definition: IndexPager.php:167
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:107
AllMessagesTablePager\formatRow
formatRow( $row)
Definition: AllMessagesTablePager.php:331
$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
Wikimedia\Rdbms\ILoadBalancer\getConnectionRef
getConnectionRef( $i, $groups=[], $domain=false, $flags=0)
Get a live database handle reference for a server index.
Xml\openElement
static openElement( $element, $attribs=null)
This opens an XML element.
Definition: Xml.php:110
AllMessagesTablePager\$langcode
string $langcode
Definition: AllMessagesTablePager.php:39
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
AllMessagesTablePager\getTitle
getTitle()
Definition: AllMessagesTablePager.php:387
$dbr
$dbr
Definition: testCompression.php:54
ContextSource\getLanguage
getLanguage()
Definition: ContextSource.php:151
Html\closeElement
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:318
AllMessagesTablePager\$prefix
string $prefix
Definition: AllMessagesTablePager.php:49
AllMessagesTablePager\getStartBody
getStartBody()
Stable to override.
Definition: AllMessagesTablePager.php:249
AllMessagesTablePager\getEndBody
getEndBody()
Stable to override.
Definition: AllMessagesTablePager.php:271
Wikimedia\Rdbms\IResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: IResultWrapper.php:24
Title\newFromRow
static newFromRow( $row)
Make a Title object from a DB row.
Definition: Title.php:558
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2467
AllMessagesTablePager\$foreign
bool $foreign
Definition: AllMessagesTablePager.php:44
TablePager
Table-based display with a user-selectable sort order Stable to extend.
Definition: TablePager.php:31
AllMessagesTablePager\getDefaultSort
getDefaultSort()
The database field name used as a default sort order.
Definition: AllMessagesTablePager.php:395
wfGetLangObj
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
Definition: GlobalFunctions.php:1181
$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:846
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:626
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:380
AllMessagesTablePager\$localisationCache
LocalisationCache $localisationCache
Definition: AllMessagesTablePager.php:67
ContextSource\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:195
AllMessagesTablePager\$suffix
string $suffix
Definition: AllMessagesTablePager.php:54
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:652
AllMessagesTablePager\getCustomisedStatuses
static getCustomisedStatuses( $messageNames, $langcode='en', $foreign=false, IDatabase $dbr=null)
Determine which of the MediaWiki and MediaWiki_talk namespace pages exist.
Definition: AllMessagesTablePager.php:156
$s
foreach( $mmfl['setupFiles'] as $fileName) if( $queue) if(empty( $mmfl['quiet'])) $s
Definition: mergeMessageFileList.php:188
AllMessagesTablePager\getQueryInfo
getQueryInfo()
Provides all parameters needed for the main paged query.
Definition: AllMessagesTablePager.php:399
AllMessagesTablePager\isFieldSortable
isFieldSortable( $x)
Return true if the named field should be sortable by the UI, false otherwise.
Definition: AllMessagesTablePager.php:391
LocalisationCache
Class for caching the contents of localisation files, Messages*.php and *.i18n.php.
Definition: LocalisationCache.php:43
IndexPager\getLinkRenderer
getLinkRenderer()
Definition: IndexPager.php:980
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:57
IndexPager\DIR_DESCENDING
const DIR_DESCENDING
Backwards-compatible constant for $mDefaultDirection field (do not change)
Definition: IndexPager.php:80
MediaWiki\Linker\LinkRenderer\makeKnownLink
makeKnownLink(LinkTarget $target, $text=null, array $extraAttribs=[], array $query=[])
Definition: LinkRenderer.php:225
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:254
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:212
AllMessagesTablePager\getAllMessages
getAllMessages( $descending)
Definition: AllMessagesTablePager.php:127
FormOptions
Helper class to keep track of options when mixing links and form elements.
Definition: FormOptions.php:35
AllMessagesTablePager\getRowAttrs
getRowAttrs( $row)
Get attributes to be applied to the given row.
Definition: AllMessagesTablePager.php:351
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:42
MediaWiki\Linker\LinkRenderer\makeBrokenLink
makeBrokenLink(LinkTarget $target, $text=null, array $extraAttribs=[], array $query=[])
Definition: LinkRenderer.php:254
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
Sanitizer\escapeHtmlAllowEntities
static escapeHtmlAllowEntities( $html)
Given HTML input, escape with htmlspecialchars but un-escape entities.
Definition: Sanitizer.php:988
AllMessagesTablePager\$lang
Language $lang
Definition: AllMessagesTablePager.php:59
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:351
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:210