14 parent::__construct(
'Interwiki' );
29 'interwiki' :
'interwiki-title-norights' )->plain();
49 $out->addModuleStyles(
'ext.interwiki.specialpage' );
51 $action = $par ?: $request->getVal(
'action', $par );
53 if ( !in_array( $action, [
'add',
'edit',
'delete' ] ) || !$this->
canModify( $out ) ) {
68 if ( !$this->
getUser()->isAllowed(
'interwiki' ) ) {
78 $out->addWikiMsg(
'interwiki-cached' );
100 $prefix = $request->getVal(
'prefix', $request->getVal(
'hiddenPrefix' ) );
108 'label-message' =>
'interwiki-prefix-label',
114 'id' =>
'mw-interwiki-local',
115 'label-message' =>
'interwiki-local-label',
121 'id' =>
'mw-interwiki-trans',
122 'label-message' =>
'interwiki-trans-label',
128 'id' =>
'mw-interwiki-url',
129 'label-message' =>
'interwiki-url-label',
131 'name' =>
'wpInterwikiURL',
138 'id' =>
"mw-interwiki-{$action}reason",
139 'label-message' =>
'interwiki_reasonfield',
141 'name' =>
'wpInterwikiReason',
153 'default' => $prefix,
159 'label-message' =>
'interwiki_reasonfield',
166 $formDescriptor[
'hiddenPrefix'] = [
168 'name' =>
'hiddenPrefix',
169 'default' => $prefix,
172 if ( $action ===
'edit' ) {
174 $row =
$dbr->selectRow(
'interwiki',
'*', [
'iw_prefix' => $prefix ], __METHOD__ );
176 $formDescriptor[
'prefix'][
'disabled'] =
true;
177 $formDescriptor[
'prefix'][
'default'] = $prefix;
178 $hiddenFields[
'prefix'] = $prefix;
181 $status->fatal(
'interwiki_editerror', $prefix );
183 $formDescriptor[
'url'][
'default'] = $row->iw_url;
184 $formDescriptor[
'url'][
'trans'] = $row->iw_trans;
185 $formDescriptor[
'url'][
'local'] = $row->iw_local;
190 $formDescriptor = [];
195 ->addHiddenFields( $hiddenFields )
196 ->setSubmitCallback( [ $this,
'onSubmit' ] );
199 if ( $action ===
'delete' ) {
200 $htmlForm->setSubmitDestructive();
203 $htmlForm->setSubmitTextMsg( $action !==
'add' ? $action :
'interwiki_addbutton' )
204 ->setIntro( $this->
msg( $action !==
'delete' ?
"interwiki_{$action}intro" :
205 'interwiki_deleting', $prefix ) )
208 $htmlForm->suppressDefaultSubmit()
217 global $wgInterwikiCentralInterlanguageDB;
221 $prefix = $this->
getRequest()->getVal(
'prefix',
'' );
222 $do = $request->getVal(
'action' );
229 if ( $do ===
'add' && preg_match(
"/\s|[^$validPrefixChars]/", $prefix ) ) {
230 $status->fatal(
'interwiki-badprefix', htmlspecialchars( $prefix ) );
236 && $wgInterwikiCentralInterlanguageDB !==
wfWikiID()
237 && $wgInterwikiCentralInterlanguageDB !==
null
239 $status->fatal(
'interwiki-cannotaddlocallanguage', htmlspecialchars( $prefix ) );
242 $reason = $data[
'reason'];
244 $lookup = MediaWikiServices::getInstance()->getInterwikiLookup();
248 $dbw->delete(
'interwiki', [
'iw_prefix' => $prefix ], __METHOD__ );
250 if ( $dbw->affectedRows() === 0 ) {
251 $status->fatal(
'interwiki_delfailed', $prefix );
253 $this->
getOutput()->addWikiMsg(
'interwiki_deleted', $prefix );
254 $log =
new LogPage(
'interwiki' );
255 $log->addEntry(
'iw_delete', $selfTitle, $reason, [ $prefix ] );
256 $lookup->invalidateCache( $prefix );
261 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
262 $prefix = $contLang->lc( $prefix );
264 $theurl = $data[
'url'];
265 $local = $data[
'local'] ? 1 : 0;
266 $trans = $data[
'trans'] ? 1 : 0;
268 'iw_prefix' => $prefix,
270 'iw_local' => $local,
274 if ( $prefix ===
'' || $theurl ===
'' ) {
275 $status->fatal(
'interwiki-submit-empty' );
283 $status->fatal(
'interwiki-submit-invalidurl' );
287 if ( $do ===
'add' ) {
288 $dbw->insert(
'interwiki', $rows, __METHOD__, [
'IGNORE' ] );
290 $dbw->update(
'interwiki', $rows, [
'iw_prefix' => $prefix ], __METHOD__, [
'IGNORE' ] );
294 if ( $dbw->affectedRows() === 0 ) {
295 $status->fatal(
"interwiki_{$do}failed", $prefix );
297 $this->
getOutput()->addWikiMsg(
"interwiki_{$do}ed", $prefix );
298 $log =
new LogPage(
'interwiki' );
299 $log->addEntry(
'iw_' . $do, $selfTitle, $reason, [ $prefix, $theurl, $trans, $local ] );
300 $lookup->invalidateCache( $prefix );
309 global $wgInterwikiCentralDB, $wgInterwikiCentralInterlanguageDB, $wgInterwikiViewOnly;
314 $lookup = MediaWikiServices::getInstance()->getInterwikiLookup();
315 $iwPrefixes = $lookup->getAllPrefixes(
null );
316 $iwGlobalPrefixes = [];
317 $iwGlobalLanguagePrefixes = [];
318 if ( $wgInterwikiCentralDB !==
null && $wgInterwikiCentralDB !==
wfWikiID() ) {
321 $res = $dbrCentralDB->select(
'interwiki',
'*',
false, __METHOD__ );
323 foreach (
$res as $row ) {
329 $iwGlobalPrefixes = $retval;
334 $usingGlobalInterlangLinks = ( $wgInterwikiCentralInterlanguageDB !== null );
335 $isGlobalInterlanguageDB = ( $wgInterwikiCentralInterlanguageDB ===
wfWikiID() );
336 $usingGlobalLanguages = $usingGlobalInterlangLinks && !$isGlobalInterlanguageDB;
337 if ( $usingGlobalLanguages ) {
339 $dbrCentralLangDB =
wfGetDB(
DB_REPLICA, [], $wgInterwikiCentralInterlanguageDB );
340 $res = $dbrCentralLangDB->select(
'interwiki',
'*',
false, __METHOD__ );
342 foreach (
$res as $row ) {
350 $iwGlobalLanguagePrefixes = $retval2;
354 $iwLocalPrefixes = [];
355 $iwLanguagePrefixes = [];
356 foreach ( $iwPrefixes as $iwPrefix ) {
358 $iwLanguagePrefixes[] = $iwPrefix;
360 $iwLocalPrefixes[] = $iwPrefix;
366 if ( $usingGlobalInterlangLinks ) {
367 unset( $iwLanguagePrefixes );
368 $iwLanguagePrefixes = $iwGlobalLanguagePrefixes;
372 $this->
getOutput()->addWikiMsg(
'interwiki_intro' );
375 if ( $wgInterwikiViewOnly ===
false ) {
378 $this->
msg(
'interwiki-logtext' )->text()
380 $this->
getOutput()->addHTML(
'<p class="mw-interwiki-log">' . $logLink .
'</p>' );
385 if ( count( $iwGlobalPrefixes ) !== 0 ) {
386 if ( $usingGlobalLanguages ) {
387 $addtext =
'interwiki-addtext-local-nolang';
389 $addtext =
'interwiki-addtext-local';
392 if ( $usingGlobalLanguages ) {
393 $addtext =
'interwiki-addtext-nolang';
395 $addtext =
'interwiki_addtext';
398 $addtext = $this->
msg( $addtext )->text();
402 '<p class="mw-interwiki-addlink">' . $addlink .
'</p>' );
405 $this->
getOutput()->addWikiMsg(
'interwiki-legend' );
407 if ( ( !is_array( $iwPrefixes ) || count( $iwPrefixes ) === 0 ) &&
408 ( !is_array( $iwGlobalPrefixes ) || count( $iwGlobalPrefixes ) === 0 )
411 $this->
error(
'interwiki_error' );
416 if ( count( $iwGlobalPrefixes ) !== 0 ) {
418 '<h2 id="interwikitable-global">' .
419 $this->
msg(
'interwiki-global-links' )->parse() .
422 $this->
getOutput()->addWikiMsg(
'interwiki-global-description' );
425 $this->
makeTable(
false, $iwGlobalPrefixes );
429 if ( count( $iwLocalPrefixes ) !== 0 ) {
430 if ( count( $iwGlobalPrefixes ) !== 0 ) {
432 '<h2 id="interwikitable-local">' .
433 $this->
msg(
'interwiki-local-links' )->parse() .
436 $this->
getOutput()->addWikiMsg(
'interwiki-local-description' );
439 '<h2 id="interwikitable-local">' .
440 $this->
msg(
'interwiki-links' )->parse() .
443 $this->
getOutput()->addWikiMsg(
'interwiki-description' );
445 $this->
makeTable( $canModify, $iwLocalPrefixes );
449 if ( count( $iwLanguagePrefixes ) !== 0 ) {
450 if ( $usingGlobalLanguages ) {
451 $header =
'interwiki-global-language-links';
452 $description =
'interwiki-global-language-description';
454 $header =
'interwiki-language-links';
455 $description =
'interwiki-language-description';
459 '<h2 id="interwikitable-language">' .
463 $this->
getOutput()->addWikiMsg( $description );
467 $canModify = ( $usingGlobalLanguages ? false : $canModify );
468 $this->
makeTable( $canModify, $iwLanguagePrefixes );
472 protected function makeTable( $canModify, $iwPrefixes ) {
475 $out .= Html::openElement(
477 [
'class' =>
'mw-interwikitable wikitable sortable body' ]
479 $out .= Html::openElement(
'thead' ) .
480 Html::openElement(
'tr', [
'class' =>
'interwikitable-header' ] ) .
481 Html::element(
'th',
null, $this->
msg(
'interwiki_prefix' )->text() ) .
482 Html::element(
'th',
null, $this->
msg(
'interwiki_url' )->text() ) .
483 Html::element(
'th',
null, $this->
msg(
'interwiki_local' )->text() ) .
484 Html::element(
'th',
null, $this->
msg(
'interwiki_trans' )->text() ) .
488 [
'class' =>
'unsortable' ],
489 $this->
msg(
'interwiki_edit' )->text()
493 $out .= Html::closeElement(
'tr' ) .
494 Html::closeElement(
'thead' ) .
"\n" .
495 Html::openElement(
'tbody' );
500 foreach ( $iwPrefixes as $iwPrefix ) {
501 $out .= Html::openElement(
'tr', [
'class' =>
'mw-interwikitable-row' ] );
502 $out .= Html::element(
'td', [
'class' =>
'mw-interwikitable-prefix' ],
503 $iwPrefix[
'iw_prefix'] );
504 $out .= Html::element(
506 [
'class' =>
'mw-interwikitable-url' ],
509 $attribs = [
'class' =>
'mw-interwikitable-local' ];
511 if ( isset( $iwPrefix[
'iw_local'] ) && $iwPrefix[
'iw_local'] ) {
512 $attribs[
'class'] .=
' mw-interwikitable-local-yes';
515 $contents = isset( $iwPrefix[
'iw_local'] ) ?
516 $this->
msg(
'interwiki_' . $iwPrefix[
'iw_local'] )->text() :
518 $out .= Html::element(
'td', $attribs, $contents );
519 $attribs = [
'class' =>
'mw-interwikitable-trans' ];
521 if ( isset( $iwPrefix[
'iw_trans'] ) && $iwPrefix[
'iw_trans'] ) {
522 $attribs[
'class'] .=
' mw-interwikitable-trans-yes';
525 $contents = isset( $iwPrefix[
'iw_trans'] ) ?
526 $this->
msg(
'interwiki_' . $iwPrefix[
'iw_trans'] )->text() :
528 $out .= Html::element(
'td', $attribs, $contents );
532 $out .= Html::rawElement(
'td', [
'class' =>
'mw-interwikitable-modify' ],
535 $this->
msg(
'edit' )->text(),
537 [
'action' =>
'edit',
'prefix' => $iwPrefix[
'iw_prefix'] ]
539 $this->
msg(
'comma-separator' )->escaped() .
542 $this->
msg(
'delete' )->text(),
544 [
'action' =>
'delete',
'prefix' => $iwPrefix[
'iw_prefix'] ]
548 $out .= Html::closeElement(
'tr' ) .
"\n";
550 $out .= Html::closeElement(
'tbody' ) .
551 Html::closeElement(
'table' );
554 $this->
getOutput()->addModuleStyles(
'jquery.tablesorter.styles' );
555 $this->
getOutput()->addModules(
'jquery.tablesorter' );
562 $this->
getOutput()->wrapWikiMsg(
"<p class='error'>$1</p>",
$args );