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  $res = $dbr->select( 'page',
166  [ 'page_namespace', 'page_title' ],
167  [ 'page_namespace' => [ NS_MEDIAWIKI, NS_MEDIAWIKI_TALK ] ],
168  __METHOD__,
169  [ 'USE INDEX' => 'page_name_title' ]
170  );
171  $xNames = array_fill_keys( $messageNames, true );
172 
173  $pageFlags = $talkFlags = [];
174 
175  foreach ( $res as $s ) {
176  $exists = false;
177 
178  if ( $foreign ) {
179  $titleParts = explode( '/', $s->page_title );
180  if ( count( $titleParts ) === 2 &&
181  $langcode === $titleParts[1] &&
182  isset( $xNames[$titleParts[0]] )
183  ) {
184  $exists = $titleParts[0];
185  }
186  } elseif ( isset( $xNames[$s->page_title] ) ) {
187  $exists = $s->page_title;
188  }
189 
191  if ( $exists && $title->inNamespace( NS_MEDIAWIKI ) ) {
192  $pageFlags[$exists] = true;
193  } elseif ( $exists && $title->inNamespace( NS_MEDIAWIKI_TALK ) ) {
194  $talkFlags[$exists] = true;
195  }
196  }
197 
198  return [ 'pages' => $pageFlags, 'talks' => $talkFlags ];
199  }
200 
209  public function reallyDoQuery( $offset, $limit, $order ) {
210  $asc = ( $order === self::QUERY_ASCENDING );
211 
212  $messageNames = $this->getAllMessages( $order );
213  $statuses = self::getCustomisedStatuses(
214  $messageNames,
215  $this->langcode,
216  $this->foreign,
217  $this->getDatabase()
218  );
219 
220  $rows = [];
221  $count = 0;
222  foreach ( $messageNames as $key ) {
223  $customised = isset( $statuses['pages'][$key] );
224  if ( $customised !== $this->custom &&
225  ( $asc && ( $key < $offset || !$offset ) || !$asc && $key > $offset ) &&
226  ( ( $this->prefix && preg_match( $this->prefix, $key ) ) || $this->prefix === false )
227  ) {
228  $actual = $this->msg( $key )->inLanguage( $this->lang )->plain();
229  $default = $this->msg( $key )->inLanguage( $this->lang )->useDatabase( false )->plain();
230  $rows[] = [
231  'am_title' => $key,
232  'am_actual' => $actual,
233  'am_default' => $default,
234  'am_customised' => $customised,
235  'am_talk_exists' => isset( $statuses['talks'][$key] )
236  ];
237  $count++;
238  }
239 
240  if ( $count === $limit ) {
241  break;
242  }
243  }
244 
245  return new FakeResultWrapper( $rows );
246  }
247 
248  protected function getStartBody() {
249  $tableClass = $this->getTableClass();
250  return Xml::openElement( 'table', [
251  'class' => "mw-datatable $tableClass",
252  'id' => 'mw-allmessagestable'
253  ] ) .
254  "\n" .
255  "<thead><tr>
256  <th rowspan=\"2\">" .
257  $this->msg( 'allmessagesname' )->escaped() . "
258  </th>
259  <th>" .
260  $this->msg( 'allmessagesdefault' )->escaped() .
261  "</th>
262  </tr>\n
263  <tr>
264  <th>" .
265  $this->msg( 'allmessagescurrent' )->escaped() .
266  "</th>
267  </tr></thead>\n";
268  }
269 
270  protected function getEndBody() {
271  return Html::closeElement( 'table' );
272  }
273 
279  public function formatValue( $field, $value ) {
280  $linkRenderer = $this->getLinkRenderer();
281  switch ( $field ) {
282  case 'am_title':
283  $title = Title::makeTitle( NS_MEDIAWIKI, $value . $this->suffix );
284  $talk = Title::makeTitle( NS_MEDIAWIKI_TALK, $value . $this->suffix );
285  $translation = Linker::makeExternalLink(
286  'https://translatewiki.net/w/i.php?' . wfArrayToCgi( [
287  'title' => 'Special:SearchTranslations',
288  'group' => 'mediawiki',
289  'grouppath' => 'mediawiki',
290  'language' => $this->getLanguage()->getCode(),
291  'query' => $value . ' ' . $this->msg( $value )->plain()
292  ] ),
293  $this->msg( 'allmessages-filter-translate' )->text()
294  );
295  $talkLink = $this->msg( 'talkpagelinktext' )->text();
296 
297  if ( $this->mCurrentRow->am_customised ) {
298  $title = $linkRenderer->makeKnownLink( $title, $this->getLanguage()->lcfirst( $value ) );
299  } else {
301  $title, $this->getLanguage()->lcfirst( $value )
302  );
303  }
304  if ( $this->mCurrentRow->am_talk_exists ) {
305  $talk = $linkRenderer->makeKnownLink( $talk, $talkLink );
306  } else {
307  $talk = $linkRenderer->makeBrokenLink(
308  $talk,
309  $talkLink
310  );
311  }
312 
313  return $title . ' ' .
314  $this->msg( 'parentheses' )->rawParams( $talk )->escaped() .
315  ' ' .
316  $this->msg( 'parentheses' )->rawParams( $translation )->escaped();
317 
318  case 'am_default':
319  case 'am_actual':
320  return Sanitizer::escapeHtmlAllowEntities( $value );
321  }
322 
323  return '';
324  }
325 
330  public function formatRow( $row ) {
331  // Do all the normal stuff
332  $s = parent::formatRow( $row );
333 
334  // But if there's a customised message, add that too.
335  if ( $row->am_customised ) {
336  $s .= Html::openElement( 'tr', $this->getRowAttrs( $row ) );
337  $formatted = strval( $this->formatValue( 'am_actual', $row->am_actual ) );
338 
339  if ( $formatted === '' ) {
340  $formatted = "\u{00A0}";
341  }
342 
343  $s .= Html::rawElement( 'td', $this->getCellAttrs( 'am_actual', $row->am_actual ), $formatted )
344  . Html::closeElement( 'tr' );
345  }
346 
347  return Html::rawElement( 'tbody', [], $s );
348  }
349 
350  protected function getRowAttrs( $row ) {
351  return [];
352  }
353 
359  protected function getCellAttrs( $field, $value ) {
360  $attr = [];
361  if ( $field === 'am_title' ) {
362  if ( $this->mCurrentRow->am_customised ) {
363  $attr += [ 'rowspan' => '2' ];
364  }
365  } else {
366  $attr += [
367  'lang' => $this->lang->getHtmlCode(),
368  'dir' => $this->lang->getDir(),
369  ];
370  if ( $this->mCurrentRow->am_customised ) {
371  // CSS class: am_default, am_actual
372  $attr += [ 'class' => $field ];
373  }
374  }
375  return $attr;
376  }
377 
378  // This is not actually used, as getStartBody is overridden above
379  protected function getFieldNames() {
380  return [
381  'am_title' => $this->msg( 'allmessagesname' )->text(),
382  'am_default' => $this->msg( 'allmessagesdefault' )->text()
383  ];
384  }
385 
386  public function getTitle() {
387  return SpecialPage::getTitleFor( 'Allmessages', false );
388  }
389 
390  protected function isFieldSortable( $x ) {
391  return false;
392  }
393 
394  public function getDefaultSort() {
395  return '';
396  }
397 
398  public function getQueryInfo() {
399  return [];
400  }
401 
402 }
AllMessagesTablePager\getCellAttrs
getCellAttrs( $field, $value)
Definition: AllMessagesTablePager.php:359
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:39
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:279
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:43
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:330
$res
$res
Definition: testCompression.php:57
Wikimedia\Rdbms\FakeResultWrapper
Overloads the relevant methods of the real ResultWrapper so it doesn't go anywhere near an actual dat...
Definition: FakeResultWrapper.php:12
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:386
$dbr
$dbr
Definition: testCompression.php:54
ContextSource\getLanguage
getLanguage()
Definition: ContextSource.php:153
Html\closeElement
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:318
AllMessagesTablePager\$prefix
string $prefix
Definition: AllMessagesTablePager.php:49
AllMessagesTablePager\getStartBody
getStartBody()
Definition: AllMessagesTablePager.php:248
MediaWiki\Linker\LinkRenderer\makeBrokenLink
makeBrokenLink( $target, $text=null, array $extraAttribs=[], array $query=[])
Definition: LinkRenderer.php:266
AllMessagesTablePager\getEndBody
getEndBody()
Definition: AllMessagesTablePager.php:270
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:612
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2226
AllMessagesTablePager\$foreign
bool $foreign
Definition: AllMessagesTablePager.php:44
TablePager
Table-based display with a user-selectable sort order.
Definition: TablePager.php:31
AllMessagesTablePager\getDefaultSort
getDefaultSort()
The database field name used as a default sort order.
Definition: AllMessagesTablePager.php:394
wfGetLangObj
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
Definition: GlobalFunctions.php:1132
$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:1015
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:680
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:379
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:197
MediaWiki\Linker\LinkRenderer\makeKnownLink
makeKnownLink( $target, $text=null, array $extraAttribs=[], array $query=[])
Definition: LinkRenderer.php:229
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:706
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:206
AllMessagesTablePager\getQueryInfo
getQueryInfo()
Provides all parameters needed for the main paged query.
Definition: AllMessagesTablePager.php:398
AllMessagesTablePager\isFieldSortable
isFieldSortable( $x)
Return true if the named field should be sortable by the UI, false otherwise.
Definition: AllMessagesTablePager.php:390
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:58
IndexPager\DIR_DESCENDING
const DIR_DESCENDING
Backwards-compatible constant for $mDefaultDirection field (do not change)
Definition: IndexPager.php:80
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:350
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:42
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:987
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:330
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:209