Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4174222
SpecialInterwiki.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
SpecialInterwiki.php
View Options
<?php
namespace
MediaWiki\Specials
;
use
LogicException
;
use
MediaWiki\Exception\PermissionsError
;
use
MediaWiki\Exception\ReadOnlyError
;
use
MediaWiki\Html\Html
;
use
MediaWiki\HTMLForm\HTMLForm
;
use
MediaWiki\Interwiki\InterwikiLookup
;
use
MediaWiki\Language\Language
;
use
MediaWiki\Languages\LanguageNameUtils
;
use
MediaWiki\Logging\ManualLogEntry
;
use
MediaWiki\MainConfigNames
;
use
MediaWiki\Message\Message
;
use
MediaWiki\Output\OutputPage
;
use
MediaWiki\SpecialPage\SpecialPage
;
use
MediaWiki\Status\Status
;
use
MediaWiki\Title\Title
;
use
MediaWiki\Utils\UrlUtils
;
use
Wikimedia\Rdbms\IConnectionProvider
;
/**
* Implements Special:Interwiki
*
* @since 1.44
* @ingroup SpecialPage
*/
class
SpecialInterwiki
extends
SpecialPage
{
private
Language
$contLang
;
private
InterwikiLookup
$interwikiLookup
;
private
LanguageNameUtils
$languageNameUtils
;
private
UrlUtils
$urlUtils
;
private
IConnectionProvider
$dbProvider
;
public
function
__construct
(
Language
$contLang
,
InterwikiLookup
$interwikiLookup
,
LanguageNameUtils
$languageNameUtils
,
UrlUtils
$urlUtils
,
IConnectionProvider
$dbProvider
)
{
parent
::
__construct
(
'Interwiki'
);
$this
->
contLang
=
$contLang
;
$this
->
interwikiLookup
=
$interwikiLookup
;
$this
->
languageNameUtils
=
$languageNameUtils
;
$this
->
urlUtils
=
$urlUtils
;
$this
->
dbProvider
=
$dbProvider
;
}
/** @inheritDoc */
public
function
doesWrites
()
{
return
true
;
}
/**
* Different description will be shown on Special:SpecialPage depending on
* whether the user can modify the data.
*
* @return Message
*/
public
function
getDescription
()
{
return
$this
->
msg
(
$this
->
canModify
()
?
'interwiki'
:
'interwiki-title-norights'
);
}
/** @inheritDoc */
public
function
getSubpagesForPrefixSearch
()
{
// delete, edit both require the prefix parameter.
return
[
'add'
];
}
/**
* Show the special page
*
* @param string|null $par parameter passed to the page or null
*/
public
function
execute
(
$par
)
{
$this
->
setHeaders
();
$this
->
outputHeader
();
$out
=
$this
->
getOutput
();
$request
=
$this
->
getRequest
();
$out
->
addModuleStyles
(
'mediawiki.special.interwiki'
);
$action
=
$par
??
$request
->
getRawVal
(
'action'
);
if
(
in_array
(
$action
,
[
'add'
,
'edit'
,
'delete'
]
)
&&
$this
->
canModify
(
$out
)
)
{
$this
->
showForm
(
$action
);
}
else
{
$this
->
showList
();
}
}
/**
* Returns boolean whether the user can modify the data.
*
* @param OutputPage|bool $out If an OutputPage object given, it adds the respective error message.
* @return bool
* @throws PermissionsError|ReadOnlyError
*/
private
function
canModify
(
$out
=
false
)
{
if
(
!
$this
->
getUser
()->
isAllowed
(
'interwiki'
)
)
{
// Check permissions
if
(
$out
)
{
throw
new
PermissionsError
(
'interwiki'
);
}
return
false
;
}
elseif
(
$this
->
getConfig
()->
get
(
MainConfigNames
::
InterwikiCache
)
)
{
// Editing the interwiki cache is not supported
if
(
$out
)
{
$out
->
addWikiMsg
(
'interwiki-cached'
);
}
return
false
;
}
else
{
if
(
$out
)
{
$this
->
checkReadOnly
();
}
}
return
true
;
}
/**
* @param string $action The action of the form
*/
protected
function
showForm
(
$action
)
{
$formDescriptor
=
[];
$hiddenFields
=
[
'action'
=>
$action
,
];
$status
=
Status
::
newGood
();
$request
=
$this
->
getRequest
();
$prefix
=
$request
->
getText
(
'prefix'
);
switch
(
$action
)
{
case
'add'
:
case
'edit'
:
$formDescriptor
=
[
'prefix'
=>
[
'type'
=>
'text'
,
'label-message'
=>
'interwiki-prefix-label'
,
'name'
=>
'prefix'
,
'autofocus'
=>
true
,
],
'local'
=>
[
'type'
=>
'check'
,
'id'
=>
'mw-interwiki-local'
,
'label-message'
=>
'interwiki-local-label'
,
'name'
=>
'local'
,
],
'trans'
=>
[
'type'
=>
'check'
,
'id'
=>
'mw-interwiki-trans'
,
'label-message'
=>
'interwiki-trans-label'
,
'name'
=>
'trans'
,
],
'url'
=>
[
'type'
=>
'url'
,
'id'
=>
'mw-interwiki-url'
,
'label-message'
=>
'interwiki-url-label'
,
'maxlength'
=>
200
,
'name'
=>
'url'
,
'size'
=>
60
,
],
'api'
=>
[
'type'
=>
'url'
,
'id'
=>
'mw-interwiki-api'
,
'label-message'
=>
'interwiki-api-label'
,
'maxlength'
=>
200
,
'name'
=>
'api'
,
'size'
=>
60
,
],
'reason'
=>
[
'type'
=>
'text'
,
'id'
=>
"mw-interwiki-{$action}reason"
,
'label-message'
=>
'interwiki_reasonfield'
,
'maxlength'
=>
200
,
'name'
=>
'reason'
,
'size'
=>
60
,
],
];
break
;
case
'delete'
:
$formDescriptor
=
[
'prefix'
=>
[
'type'
=>
'hidden'
,
'name'
=>
'prefix'
,
'default'
=>
$prefix
,
],
'reason'
=>
[
'type'
=>
'text'
,
'name'
=>
'reason'
,
'label-message'
=>
'interwiki_reasonfield'
,
],
];
break
;
default
:
throw
new
LogicException
(
"Unexpected action: {$action}"
);
}
if
(
$action
===
'edit'
||
$action
===
'delete'
)
{
$dbr
=
$this
->
dbProvider
->
getReplicaDatabase
();
$row
=
$dbr
->
newSelectQueryBuilder
()
->
select
(
'*'
)
->
from
(
'interwiki'
)
->
where
(
[
'iw_prefix'
=>
$prefix
]
)
->
caller
(
__METHOD__
)->
fetchRow
();
if
(
$action
===
'edit'
)
{
if
(
!
$row
)
{
$status
->
fatal
(
'interwiki_editerror'
,
$prefix
);
}
else
{
$formDescriptor
[
'prefix'
][
'disabled'
]
=
true
;
$formDescriptor
[
'prefix'
][
'default'
]
=
$prefix
;
$hiddenFields
[
'prefix'
]
=
$prefix
;
$formDescriptor
[
'url'
][
'default'
]
=
$row
->
iw_url
;
$formDescriptor
[
'api'
][
'default'
]
=
$row
->
iw_api
;
$formDescriptor
[
'trans'
][
'default'
]
=
$row
->
iw_trans
;
$formDescriptor
[
'local'
][
'default'
]
=
$row
->
iw_local
;
}
}
else
{
// $action === 'delete'
if
(
!
$row
)
{
$status
->
fatal
(
'interwiki_delfailed'
,
$prefix
);
}
}
}
if
(
!
$status
->
isOK
()
)
{
$formDescriptor
=
[];
}
$htmlForm
=
HTMLForm
::
factory
(
'ooui'
,
$formDescriptor
,
$this
->
getContext
()
);
$htmlForm
->
addHiddenFields
(
$hiddenFields
)
->
setSubmitCallback
(
$this
->
onSubmit
(
...
)
);
if
(
$status
->
isOK
()
)
{
if
(
$action
===
'delete'
)
{
$htmlForm
->
setSubmitDestructive
();
}
$htmlForm
->
setSubmitTextMsg
(
$action
!==
'add'
?
$action
:
'interwiki_addbutton'
)
->
setPreHtml
(
$this
->
msg
(
$action
!==
'delete'
?
"interwiki_{$action}intro"
:
'interwiki_deleting'
,
$prefix
)->
escaped
()
)
->
show
();
}
else
{
$htmlForm
->
suppressDefaultSubmit
()
->
prepareForm
()
->
displayForm
(
$status
);
}
$this
->
getOutput
()->
addBacklinkSubtitle
(
$this
->
getPageTitle
()
);
}
/**
* @param array $data
* @return Status
*/
private
function
onSubmit
(
array
$data
)
{
$status
=
Status
::
newGood
();
$request
=
$this
->
getRequest
();
$config
=
$this
->
getConfig
();
$prefix
=
$data
[
'prefix'
];
$do
=
$request
->
getRawVal
(
'action'
);
// Show an error if the prefix is invalid (only when adding one).
// Invalid characters for a title should also be invalid for a prefix.
// Whitespace, ':', '&' and '=' are invalid, too.
// (Bug 30599).
$validPrefixChars
=
preg_replace
(
'/[ :&=]/'
,
''
,
Title
::
legalChars
()
);
if
(
$do
===
'add'
&&
preg_match
(
"/
\s
|[^$validPrefixChars]/"
,
$prefix
)
)
{
$status
->
fatal
(
'interwiki-badprefix'
,
htmlspecialchars
(
$prefix
)
);
return
$status
;
}
$virtualDomainsMapping
=
$this
->
getConfig
()->
get
(
MainConfigNames
::
VirtualDomainsMapping
)
??
[];
// Disallow adding local interlanguage definitions if using global
if
(
$do
===
'add'
&&
$this
->
isLanguagePrefix
(
$prefix
)
&&
isset
(
$virtualDomainsMapping
[
'virtual-interwiki-interlanguage'
]
)
)
{
$status
->
fatal
(
'interwiki-cannotaddlocallanguage'
,
htmlspecialchars
(
$prefix
)
);
return
$status
;
}
$reason
=
$data
[
'reason'
];
$selfTitle
=
$this
->
getPageTitle
();
$dbw
=
$this
->
dbProvider
->
getPrimaryDatabase
();
switch
(
$do
)
{
case
'delete'
:
$dbw
->
newDeleteQueryBuilder
()
->
deleteFrom
(
'interwiki'
)
->
where
(
[
'iw_prefix'
=>
$prefix
]
)
->
caller
(
__METHOD__
)->
execute
();
if
(
$dbw
->
affectedRows
()
===
0
)
{
$status
->
fatal
(
'interwiki_delfailed'
,
$prefix
);
}
else
{
$this
->
getOutput
()->
addWikiMsg
(
'interwiki_deleted'
,
$prefix
);
$log
=
new
ManualLogEntry
(
'interwiki'
,
'iw_delete'
);
$log
->
setTarget
(
$selfTitle
);
$log
->
setComment
(
$reason
);
$log
->
setParameters
(
[
'4::prefix'
=>
$prefix
]
);
$log
->
setPerformer
(
$this
->
getUser
()
);
$log
->
insert
();
$this
->
interwikiLookup
->
invalidateCache
(
$prefix
);
}
break
;
/** @noinspection PhpMissingBreakStatementInspection */
case
'add'
:
$prefix
=
$this
->
contLang
->
lc
(
$prefix
);
// Fall through
case
'edit'
:
// T374771: Trim the URL and API URLs to reduce confusion when
// the URLs are accidentally provided with extra whitespace
$theurl
=
trim
(
$data
[
'url'
]
);
$api
=
trim
(
$data
[
'api'
]
??
''
);
$local
=
$data
[
'local'
]
?
1
:
0
;
$trans
=
$data
[
'trans'
]
?
1
:
0
;
$row
=
[
'iw_prefix'
=>
$prefix
,
'iw_url'
=>
$theurl
,
'iw_api'
=>
$api
,
'iw_wikiid'
=>
''
,
'iw_local'
=>
$local
,
'iw_trans'
=>
$trans
];
if
(
$prefix
===
''
||
$theurl
===
''
)
{
$status
->
fatal
(
'interwiki-submit-empty'
);
break
;
}
// Simple URL validation: check that the protocol is one of
// the supported protocols for this wiki.
// (T32600)
if
(
!
$this
->
urlUtils
->
parse
(
$theurl
)
)
{
$status
->
fatal
(
'interwiki-submit-invalidurl'
);
break
;
}
if
(
$do
===
'add'
)
{
$dbw
->
newInsertQueryBuilder
()
->
insertInto
(
'interwiki'
)
->
row
(
$row
)
->
ignore
()
->
caller
(
__METHOD__
)->
execute
();
}
else
{
// $do === 'edit'
$dbw
->
newUpdateQueryBuilder
()
->
update
(
'interwiki'
)
->
set
(
$row
)
->
where
(
[
'iw_prefix'
=>
$prefix
]
)
->
ignore
()
->
caller
(
__METHOD__
)->
execute
();
}
// used here: interwiki_addfailed, interwiki_added, interwiki_edited
if
(
$dbw
->
affectedRows
()
===
0
)
{
$status
->
fatal
(
"interwiki_{$do}failed"
,
$prefix
);
}
else
{
$this
->
getOutput
()->
addWikiMsg
(
"interwiki_{$do}ed"
,
$prefix
);
$log
=
new
ManualLogEntry
(
'interwiki'
,
'iw_'
.
$do
);
$log
->
setTarget
(
$selfTitle
);
$log
->
setComment
(
$reason
);
$log
->
setParameters
(
[
'4::prefix'
=>
$prefix
,
'5::url'
=>
$theurl
,
'6::trans'
=>
$trans
,
'7::local'
=>
$local
]
);
$log
->
setPerformer
(
$this
->
getUser
()
);
$log
->
insert
();
$this
->
interwikiLookup
->
invalidateCache
(
$prefix
);
}
break
;
default
:
throw
new
LogicException
(
"Unexpected action: {$do}"
);
}
return
$status
;
}
/**
* Determine whether a prefix is a language link
*
* @param string $prefix
* @return bool
*/
private
function
isLanguagePrefix
(
$prefix
)
{
return
$this
->
getConfig
()->
get
(
MainConfigNames
::
InterwikiMagic
)
&&
$this
->
languageNameUtils
->
getLanguageName
(
$prefix
);
}
protected
function
showList
()
{
$canModify
=
$this
->
canModify
();
// Build lists
$iwPrefixes
=
$this
->
interwikiLookup
->
getAllPrefixes
(
null
);
$iwGlobalPrefixes
=
[];
$iwGlobalLanguagePrefixes
=
[];
$virtualDomainsMapping
=
$this
->
getConfig
()->
get
(
MainConfigNames
::
VirtualDomainsMapping
)
??
[];
if
(
isset
(
$virtualDomainsMapping
[
'virtual-interwiki'
]
)
)
{
// Fetch list from global table
$dbrCentralDB
=
$this
->
dbProvider
->
getReplicaDatabase
(
'virtual-interwiki'
);
$res
=
$dbrCentralDB
->
newSelectQueryBuilder
()
->
select
(
'*'
)
->
from
(
'interwiki'
)
->
caller
(
__METHOD__
)->
fetchResultSet
();
$retval
=
[];
foreach
(
$res
as
$row
)
{
$row
=
(
array
)
$row
;
if
(
!
$this
->
isLanguagePrefix
(
$row
[
'iw_prefix'
]
)
)
{
$retval
[]
=
$row
;
}
}
$iwGlobalPrefixes
=
$retval
;
}
// Almost the same loop as above, but for global inter*language* links, whereas the above is for
// global inter*wiki* links
$usingGlobalLanguages
=
isset
(
$virtualDomainsMapping
[
'virtual-interwiki-interlanguage'
]
);
if
(
$usingGlobalLanguages
)
{
// Fetch list from global table
$dbrCentralLangDB
=
$this
->
dbProvider
->
getReplicaDatabase
(
'virtual-interwiki-interlanguage'
);
$res
=
$dbrCentralLangDB
->
newSelectQueryBuilder
()
->
select
(
'*'
)
->
from
(
'interwiki'
)
->
caller
(
__METHOD__
)->
fetchResultSet
();
$retval2
=
[];
foreach
(
$res
as
$row
)
{
$row
=
(
array
)
$row
;
// Note that the above DB query explicitly *excludes* interlang ones
// (which makes sense), whereas here we _only_ care about interlang ones!
if
(
$this
->
isLanguagePrefix
(
$row
[
'iw_prefix'
]
)
)
{
$retval2
[]
=
$row
;
}
}
$iwGlobalLanguagePrefixes
=
$retval2
;
}
// Split out language links
$iwLocalPrefixes
=
[];
$iwLanguagePrefixes
=
[];
foreach
(
$iwPrefixes
as
$iwPrefix
)
{
if
(
$this
->
isLanguagePrefix
(
$iwPrefix
[
'iw_prefix'
]
)
)
{
$iwLanguagePrefixes
[]
=
$iwPrefix
;
}
else
{
$iwLocalPrefixes
[]
=
$iwPrefix
;
}
}
// If using global interlanguage links, just ditch the data coming from the
// local table and overwrite it with the global data
if
(
$usingGlobalLanguages
)
{
unset
(
$iwLanguagePrefixes
);
$iwLanguagePrefixes
=
$iwGlobalLanguagePrefixes
;
}
// Page intro content
$this
->
getOutput
()->
addWikiMsg
(
'interwiki_intro'
);
// Add 'view log' link
$logLink
=
$this
->
getLinkRenderer
()->
makeLink
(
SpecialPage
::
getTitleFor
(
'Log'
,
'interwiki'
),
$this
->
msg
(
'interwiki-logtext'
)->
text
()
);
$this
->
getOutput
()->
addHTML
(
Html
::
rawElement
(
'p'
,
[
'class'
=>
'mw-interwiki-log'
],
$logLink
)
);
// Add 'add' link
if
(
$canModify
)
{
if
(
count
(
$iwGlobalPrefixes
)
!==
0
)
{
if
(
$usingGlobalLanguages
)
{
$addtext
=
'interwiki-addtext-local-nolang'
;
}
else
{
$addtext
=
'interwiki-addtext-local'
;
}
}
else
{
if
(
$usingGlobalLanguages
)
{
$addtext
=
'interwiki-addtext-nolang'
;
}
else
{
$addtext
=
'interwiki_addtext'
;
}
}
$addtext
=
$this
->
msg
(
$addtext
)->
text
();
$addlink
=
$this
->
getLinkRenderer
()->
makeKnownLink
(
$this
->
getPageTitle
(
'add'
),
$addtext
);
$this
->
getOutput
()->
addHTML
(
Html
::
rawElement
(
'p'
,
[
'class'
=>
'mw-interwiki-addlink'
],
$addlink
)
);
}
$this
->
getOutput
()->
addWikiMsg
(
'interwiki-legend'
);
if
(
$iwPrefixes
===
[]
&&
$iwGlobalPrefixes
===
[]
)
{
// If the interwiki table(s) are empty, display an error message
$this
->
error
(
'interwiki_error'
);
return
;
}
// Add the global table
if
(
count
(
$iwGlobalPrefixes
)
!==
0
)
{
$this
->
getOutput
()->
addHTML
(
Html
::
rawElement
(
'h2'
,
[
'class'
=>
'interwikitable-global'
],
$this
->
msg
(
'interwiki-global-links'
)->
parse
()
)
);
$this
->
getOutput
()->
addWikiMsg
(
'interwiki-global-description'
);
// $canModify is false here because this is just a display of remote data
$this
->
makeTable
(
false
,
$iwGlobalPrefixes
);
}
// Add the local table
if
(
count
(
$iwLocalPrefixes
)
!==
0
)
{
if
(
count
(
$iwGlobalPrefixes
)
!==
0
)
{
$this
->
getOutput
()->
addHTML
(
Html
::
rawElement
(
'h2'
,
[
'class'
=>
'interwikitable-local'
],
$this
->
msg
(
'interwiki-local-links'
)->
parse
()
)
);
$this
->
getOutput
()->
addWikiMsg
(
'interwiki-local-description'
);
}
else
{
$this
->
getOutput
()->
addHTML
(
Html
::
rawElement
(
'h2'
,
[
'class'
=>
'interwikitable-local'
],
$this
->
msg
(
'interwiki-links'
)->
parse
()
)
);
$this
->
getOutput
()->
addWikiMsg
(
'interwiki-description'
);
}
$this
->
makeTable
(
$canModify
,
$iwLocalPrefixes
);
}
// Add the language table
if
(
count
(
$iwLanguagePrefixes
)
!==
0
)
{
if
(
$usingGlobalLanguages
)
{
$header
=
'interwiki-global-language-links'
;
$description
=
'interwiki-global-language-description'
;
}
else
{
$header
=
'interwiki-language-links'
;
$description
=
'interwiki-language-description'
;
}
$this
->
getOutput
()->
addHTML
(
Html
::
rawElement
(
'h2'
,
[
'class'
=>
'interwikitable-language'
],
$this
->
msg
(
$header
)->
parse
()
)
);
$this
->
getOutput
()->
addWikiMsg
(
$description
);
// When using global interlanguage links, don't allow them to be modified
// except on the source wiki
$canModify
=
(
$usingGlobalLanguages
?
false
:
$canModify
);
$this
->
makeTable
(
$canModify
,
$iwLanguagePrefixes
);
}
}
protected
function
makeTable
(
bool
$canModify
,
array
$iwPrefixes
)
{
// Output the existing Interwiki prefixes table header
$out
=
Html
::
openElement
(
'table'
,
[
'class'
=>
'mw-interwikitable wikitable sortable'
]
)
.
"
\n
"
;
$out
.=
Html
::
openElement
(
'thead'
)
.
Html
::
openElement
(
'tr'
,
[
'class'
=>
'interwikitable-header'
]
)
.
Html
::
element
(
'th'
,
[],
$this
->
msg
(
'interwiki_prefix'
)->
text
()
)
.
Html
::
element
(
'th'
,
[],
$this
->
msg
(
'interwiki_url'
)->
text
()
)
.
Html
::
element
(
'th'
,
[],
$this
->
msg
(
'interwiki_local'
)->
text
()
)
.
Html
::
element
(
'th'
,
[],
$this
->
msg
(
'interwiki_trans'
)->
text
()
)
.
(
$canModify
?
Html
::
element
(
'th'
,
[
'class'
=>
'unsortable'
],
$this
->
msg
(
'interwiki_edit'
)->
text
()
)
:
''
);
$out
.=
Html
::
closeElement
(
'tr'
)
.
Html
::
closeElement
(
'thead'
)
.
"
\n
"
.
Html
::
openElement
(
'tbody'
);
$selfTitle
=
$this
->
getPageTitle
();
// Output the existing Interwiki prefixes table rows
foreach
(
$iwPrefixes
as
$iwPrefix
)
{
$out
.=
Html
::
openElement
(
'tr'
,
[
'class'
=>
'mw-interwikitable-row'
]
);
$out
.=
Html
::
element
(
'td'
,
[
'class'
=>
'mw-interwikitable-prefix'
],
$iwPrefix
[
'iw_prefix'
]
);
$out
.=
Html
::
element
(
'td'
,
[
'class'
=>
'mw-interwikitable-url'
],
$iwPrefix
[
'iw_url'
]
);
$attribs
=
[
'class'
=>
'mw-interwikitable-local'
];
// Green background for cells with "yes".
if
(
isset
(
$iwPrefix
[
'iw_local'
]
)
&&
$iwPrefix
[
'iw_local'
]
)
{
$attribs
[
'class'
]
.=
' mw-interwikitable-local-yes'
;
}
// The messages interwiki_0 and interwiki_1 are used here.
$contents
=
isset
(
$iwPrefix
[
'iw_local'
]
)
?
$this
->
msg
(
'interwiki_'
.
$iwPrefix
[
'iw_local'
]
)->
text
()
:
'-'
;
$out
.=
Html
::
element
(
'td'
,
$attribs
,
$contents
);
$attribs
=
[
'class'
=>
'mw-interwikitable-trans'
];
// Green background for cells with "yes".
if
(
isset
(
$iwPrefix
[
'iw_trans'
]
)
&&
$iwPrefix
[
'iw_trans'
]
)
{
$attribs
[
'class'
]
.=
' mw-interwikitable-trans-yes'
;
}
// The messages interwiki_0 and interwiki_1 are used here.
$contents
=
isset
(
$iwPrefix
[
'iw_trans'
]
)
?
$this
->
msg
(
'interwiki_'
.
$iwPrefix
[
'iw_trans'
]
)->
text
()
:
'-'
;
$out
.=
Html
::
element
(
'td'
,
$attribs
,
$contents
);
// Additional column when the interwiki table can be modified.
if
(
$canModify
)
{
$out
.=
Html
::
rawElement
(
'td'
,
[
'class'
=>
'mw-interwikitable-modify'
],
$this
->
getLinkRenderer
()->
makeKnownLink
(
$selfTitle
,
$this
->
msg
(
'edit'
)->
text
(),
[],
[
'action'
=>
'edit'
,
'prefix'
=>
$iwPrefix
[
'iw_prefix'
]
]
)
.
$this
->
msg
(
'comma-separator'
)->
escaped
()
.
$this
->
getLinkRenderer
()->
makeKnownLink
(
$selfTitle
,
$this
->
msg
(
'delete'
)->
text
(),
[],
[
'action'
=>
'delete'
,
'prefix'
=>
$iwPrefix
[
'iw_prefix'
]
]
)
);
}
$out
.=
Html
::
closeElement
(
'tr'
)
.
"
\n
"
;
}
$out
.=
Html
::
closeElement
(
'tbody'
)
.
Html
::
closeElement
(
'table'
);
$this
->
getOutput
()->
addHTML
(
$out
);
$this
->
getOutput
()->
addModuleStyles
(
'jquery.tablesorter.styles'
);
$this
->
getOutput
()->
addModules
(
'jquery.tablesorter'
);
}
/**
* @param string ...$args
*/
protected
function
error
(
...
$args
)
{
$this
->
getOutput
()->
wrapWikiMsg
(
"<p class='error'>$1</p>"
,
$args
);
}
/** @inheritDoc */
protected
function
getGroupName
()
{
return
'wiki'
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Aug 20 2026, 07:44 (11 w, 3 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
aa/2a/f1bc414b1ebc1051939c5ab9baea
Default Alt Text
SpecialInterwiki.php (19 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment