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  return Xml::openElement( 'table', [
250  'class' => $this->getTableClass(),
251  'id' => 'mw-allmessagestable'
252  ] ) .
253  "\n" .
254  "<thead><tr>
255  <th rowspan=\"2\">" .
256  $this->msg( 'allmessagesname' )->escaped() . "
257  </th>
258  <th>" .
259  $this->msg( 'allmessagesdefault' )->escaped() .
260  "</th>
261  </tr>\n
262  <tr>
263  <th>" .
264  $this->msg( 'allmessagescurrent' )->escaped() .
265  "</th>
266  </tr></thead>\n";
267  }
268 
269  protected function getEndBody() {
270  return Html::closeElement( 'table' );
271  }
272 
278  public function formatValue( $field, $value ) {
279  $linkRenderer = $this->getLinkRenderer();
280  switch ( $field ) {
281  case 'am_title':
282  $title = Title::makeTitle( NS_MEDIAWIKI, $value . $this->suffix );
283  $talk = Title::makeTitle( NS_MEDIAWIKI_TALK, $value . $this->suffix );
284  $translation = Linker::makeExternalLink(
285  'https://translatewiki.net/w/i.php?' . wfArrayToCgi( [
286  'title' => 'Special:SearchTranslations',
287  'group' => 'mediawiki',
288  'grouppath' => 'mediawiki',
289  'language' => $this->getLanguage()->getCode(),
290  'query' => $value . ' ' . $this->msg( $value )->plain()
291  ] ),
292  $this->msg( 'allmessages-filter-translate' )->text()
293  );
294  $talkLink = $this->msg( 'talkpagelinktext' )->text();
295 
296  if ( $this->mCurrentRow->am_customised ) {
297  $title = $linkRenderer->makeKnownLink( $title, $this->getLanguage()->lcfirst( $value ) );
298  } else {
300  $title, $this->getLanguage()->lcfirst( $value )
301  );
302  }
303  if ( $this->mCurrentRow->am_talk_exists ) {
304  $talk = $linkRenderer->makeKnownLink( $talk, $talkLink );
305  } else {
306  $talk = $linkRenderer->makeBrokenLink(
307  $talk,
308  $talkLink
309  );
310  }
311 
312  return $title . ' ' .
313  $this->msg( 'parentheses' )->rawParams( $talk )->escaped() .
314  ' ' .
315  $this->msg( 'parentheses' )->rawParams( $translation )->escaped();
316 
317  case 'am_default':
318  case 'am_actual':
319  return Sanitizer::escapeHtmlAllowEntities( $value );
320  }
321 
322  return '';
323  }
324 
329  public function formatRow( $row ) {
330  // Do all the normal stuff
331  $s = parent::formatRow( $row );
332 
333  // But if there's a customised message, add that too.
334  if ( $row->am_customised ) {
335  $s .= Html::openElement( 'tr', $this->getRowAttrs( $row ) );
336  $formatted = strval( $this->formatValue( 'am_actual', $row->am_actual ) );
337 
338  if ( $formatted === '' ) {
339  $formatted = "\u{00A0}";
340  }
341 
342  $s .= Html::rawElement( 'td', $this->getCellAttrs( 'am_actual', $row->am_actual ), $formatted )
343  . Html::closeElement( 'tr' );
344  }
345 
346  return Html::rawElement( 'tbody', [], $s );
347  }
348 
349  protected function getRowAttrs( $row ) {
350  return [];
351  }
352 
358  protected function getCellAttrs( $field, $value ) {
359  $attr = [];
360  if ( $field === 'am_title' ) {
361  if ( $this->mCurrentRow->am_customised ) {
362  $attr += [ 'rowspan' => '2' ];
363  }
364  } else {
365  $attr += [
366  'lang' => $this->lang->getHtmlCode(),
367  'dir' => $this->lang->getDir(),
368  ];
369  if ( $this->mCurrentRow->am_customised ) {
370  // CSS class: am_default, am_actual
371  $attr += [ 'class' => $field ];
372  }
373  }
374  return $attr;
375  }
376 
377  // This is not actually used, as getStartBody is overridden above
378  protected function getFieldNames() {
379  return [
380  'am_title' => $this->msg( 'allmessagesname' )->text(),
381  'am_default' => $this->msg( 'allmessagesdefault' )->text()
382  ];
383  }
384 
385  public function getTitle() {
386  return SpecialPage::getTitleFor( 'Allmessages', false );
387  }
388 
389  protected function isFieldSortable( $x ) {
390  return false;
391  }
392 
393  public function getDefaultSort() {
394  return '';
395  }
396 
397  public function getQueryInfo() {
398  return [];
399  }
400 
401 }
AllMessagesTablePager\getCellAttrs
getCellAttrs( $field, $value)
Definition: AllMessagesTablePager.php:358
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:278
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:276
IndexPager\getDatabase
getDatabase()
Get the Database object in use.
Definition: IndexPager.php:248
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:329
$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:385
$dbr
$dbr
Definition: testCompression.php:54
ContextSource\getLanguage
getLanguage()
Definition: ContextSource.php:153
Html\closeElement
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:316
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:264
AllMessagesTablePager\getEndBody
getEndBody()
Definition: AllMessagesTablePager.php:269
Wikimedia\Rdbms\IResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: IResultWrapper.php:26
Title\newFromRow
static newFromRow( $row)
Make a Title object from a DB row.
Definition: Title.php:579
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2200
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:393
wfGetLangObj
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
Definition: GlobalFunctions.php:1133
$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:1011
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:650
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:378
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:227
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:676
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:397
AllMessagesTablePager\isFieldSortable
isFieldSortable( $x)
Return true if the named field should be sortable by the UI, false otherwise.
Definition: AllMessagesTablePager.php:389
LocalisationCache
Class for caching the contents of localisation files, Messages*.php and *.i18n.php.
Definition: LocalisationCache.php:43
IndexPager\getLinkRenderer
getLinkRenderer()
Definition: IndexPager.php:991
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:252
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:210
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:349
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: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: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