Provide a standard way to get the target of a redirect page

The new Scribunto_LuaTitleLibrary::redirectTarget() method is
used by mw.title objects as read-only attribute 'redirectTarget'.

If the page does not exist or it is not a redirect, the value
of the attribute is `false`; otherwise, it is the target of the
redirect page, as mw.title object.

This is a proper alternative to parsing wikitext as it is done in:
https://en.wikipedia.org/wiki/Module:Redirect

Bug: T68974
Change-Id: Id4d9b0f8c1cd09ebc42c031d4d3fc0c33eea44aa
This commit is contained in:
Ricordisamoa 2014-10-23 15:15:52 +02:00
parent 10ebda4a73
commit 1573bee81a
4 changed files with 73 additions and 14 deletions

View file

@ -18,6 +18,7 @@ class Scribunto_LuaTitleLibrary extends Scribunto_LuaLibraryBase {
'getFileInfo' => array( $this, 'getFileInfo' ), 'getFileInfo' => array( $this, 'getFileInfo' ),
'protectionLevels' => array( $this, 'protectionLevels' ), 'protectionLevels' => array( $this, 'protectionLevels' ),
'cascadingProtection' => array( $this, 'cascadingProtection' ), 'cascadingProtection' => array( $this, 'cascadingProtection' ),
'redirectTarget' => array( $this, 'redirectTarget' ),
); );
return $this->getEngine()->registerInterface( 'mw.title.lua', $lib, array( return $this->getEngine()->registerInterface( 'mw.title.lua', $lib, array(
'thisTitle' => $this->getInexpensiveTitleData( $this->getTitle() ), 'thisTitle' => $this->getInexpensiveTitleData( $this->getTitle() ),
@ -241,11 +242,18 @@ class Scribunto_LuaTitleLibrary extends Scribunto_LuaLibraryBase {
return array( call_user_func_array( array( $title, $func ), $args ) ); return array( call_user_func_array( array( $title, $func ), $args ) );
} }
function getContent( $text ) { /**
$this->checkType( 'getContent', 1, $text, 'string' ); * Utility to get a Content object from a title
*
* The title is counted as a transclusion.
*
* @param $text string Title text
* @return Content|null The Content object of the title, null if missing
*/
private function getContentInternal( $text ) {
$title = Title::newFromText( $text ); $title = Title::newFromText( $text );
if ( !$title ) { if ( !$title ) {
return array( null ); return null;
} }
// Record in templatelinks, so edits cause the page to be refreshed // Record in templatelinks, so edits cause the page to be refreshed
@ -261,14 +269,13 @@ class Scribunto_LuaTitleLibrary extends Scribunto_LuaLibraryBase {
} else { } else {
$rev = Revision::newFromTitle( $title ); $rev = Revision::newFromTitle( $title );
} }
if ( !$rev ) { return $rev ? $rev->getContent() : null;
return array( null );
} }
$content = $rev->getContent();
if ( !$content ) { function getContent( $text ) {
return array( null ); $this->checkType( 'getContent', 1, $text, 'string' );
} $content = $this->getContentInternal( $text );
return array( $content->serialize() ); return array( $content ? $content->serialize() : null );
} }
function getFileInfo( $text ) { function getFileInfo( $text ) {
@ -355,4 +362,11 @@ class Scribunto_LuaTitleLibrary extends Scribunto_LuaLibraryBase {
'restrictions' => array_map( 'Scribunto_LuaTitleLibrary::makeArrayOneBased', $restrictions ) 'restrictions' => array_map( 'Scribunto_LuaTitleLibrary::makeArrayOneBased', $restrictions )
) ); ) );
} }
public function redirectTarget( $text ) {
$this->checkType( 'redirectTarget', 1, $text, 'string' );
$content = $this->getContentInternal( $text );
$redirTitle = $content ? $content->getRedirectTarget() : null;
return array( $redirTitle ? $this->getInexpensiveTitleData( $redirTitle ) : null );
}
} }

View file

@ -173,6 +173,7 @@ local function makeTitleObject( data )
isRedirect = 'e', isRedirect = 'e',
contentModel = 'e', contentModel = 'e',
id = 'e', id = 'e',
redirectTarget = true,
} }
for k in pairs( data ) do for k in pairs( data ) do
readOnlyFields[k] = true readOnlyFields[k] = true
@ -259,6 +260,12 @@ local function makeTitleObject( data )
end end
return data.cascadingProtection return data.cascadingProtection
end end
if k == 'redirectTarget' then
if data.redirectTarget == nil then
data.redirectTarget = makeTitleObject( php.redirectTarget( data.prefixedText ) ) or false
end
return data.redirectTarget
end
return data[k] return data[k]
end, end,

View file

@ -48,6 +48,19 @@ class Scribunto_LuaTitleLibraryTests extends Scribunto_LuaEngineTestBase {
new WikitextContent( '{{int:mainpage}}<includeonly>...</includeonly><noinclude>...</noinclude>' ), new WikitextContent( '{{int:mainpage}}<includeonly>...</includeonly><noinclude>...</noinclude>' ),
'Summary' 'Summary'
); );
$testPageId = $page->getId();
// Pages for redirectTarget tests
$page = WikiPage::factory( Title::newFromText( 'ScribuntoTestRedirect' ) );
$page->doEditContent(
new WikitextContent( '#REDIRECT [[ScribuntoTestTarget]]' ),
'Summary'
);
$page = WikiPage::factory( Title::newFromText( 'ScribuntoTestNonRedirect' ) );
$page->doEditContent(
new WikitextContent( 'Not a redirect.' ),
'Summary'
);
// Set restrictions for protectionLevels and cascadingProtection tests // Set restrictions for protectionLevels and cascadingProtection tests
// Since mRestrictionsLoaded is true, they don't count as expensive // Since mRestrictionsLoaded is true, they don't count as expensive
@ -88,7 +101,7 @@ class Scribunto_LuaTitleLibraryTests extends Scribunto_LuaEngineTestBase {
// Indicate to the tests that it's safe to create the title objects // Indicate to the tests that it's safe to create the title objects
$interpreter = $this->getEngine()->getInterpreter(); $interpreter = $this->getEngine()->getInterpreter();
$interpreter->callFunction( $interpreter->callFunction(
$interpreter->loadString( "mw.title.testPageId = {$page->getId()}", 'fortest' ) $interpreter->loadString( "mw.title.testPageId = $testPageId", 'fortest' )
); );
$this->setMwGlobals( array( $this->setMwGlobals( array(

View file

@ -71,7 +71,25 @@ local function test_inexpensive()
end end
local function test_getContent() local function test_getContent()
return mw.title.new( 'ScribuntoTestPage' ):getContent() return mw.title.new( 'ScribuntoTestPage' ):getContent(),
mw.title.new( 'ScribuntoTestNonExistingPage' ):getContent()
end
local function test_redirectTarget()
local targets = {}
local titles = {
'ScribuntoTestRedirect',
'ScribuntoTestNonRedirect',
'ScribuntoTestNonExistingPage'
}
for _, title in ipairs( titles ) do
local target = mw.title.new( title ).redirectTarget
if title.prefixedText ~= nil then
target = title.prefixedText
end
table.insert( targets, target )
end
return unpack( targets )
end end
local function test_getCurrentTitle_fragment() local function test_getCurrentTitle_fragment()
@ -372,7 +390,14 @@ local tests = {
}, },
{ name = '.getContent()', func = test_getContent, { name = '.getContent()', func = test_getContent,
expect = { '{{int:mainpage}}<includeonly>...</includeonly><noinclude>...</noinclude>' } expect = {
'{{int:mainpage}}<includeonly>...</includeonly><noinclude>...</noinclude>',
nil,
}
},
{ name = '.redirectTarget', func = test_redirectTarget, type = 'ToString',
expect = { 'ScribuntoTestTarget', false, false }
}, },
{ name = 'not quite too many expensive functions', func = test_expensive_10, { name = 'not quite too many expensive functions', func = test_expensive_10,