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' ),
'protectionLevels' => array( $this, 'protectionLevels' ),
'cascadingProtection' => array( $this, 'cascadingProtection' ),
'redirectTarget' => array( $this, 'redirectTarget' ),
);
return $this->getEngine()->registerInterface( 'mw.title.lua', $lib, array(
'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 ) );
}
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 );
if ( !$title ) {
return array( null );
return null;
}
// Record in templatelinks, so edits cause the page to be refreshed
@ -261,14 +269,13 @@ class Scribunto_LuaTitleLibrary extends Scribunto_LuaLibraryBase {
} else {
$rev = Revision::newFromTitle( $title );
}
if ( !$rev ) {
return array( null );
}
$content = $rev->getContent();
if ( !$content ) {
return array( null );
}
return array( $content->serialize() );
return $rev ? $rev->getContent() : null;
}
function getContent( $text ) {
$this->checkType( 'getContent', 1, $text, 'string' );
$content = $this->getContentInternal( $text );
return array( $content ? $content->serialize() : null );
}
function getFileInfo( $text ) {
@ -355,4 +362,11 @@ class Scribunto_LuaTitleLibrary extends Scribunto_LuaLibraryBase {
'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',
contentModel = 'e',
id = 'e',
redirectTarget = true,
}
for k in pairs( data ) do
readOnlyFields[k] = true
@ -259,6 +260,12 @@ local function makeTitleObject( data )
end
return data.cascadingProtection
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]
end,

View file

@ -48,6 +48,19 @@ class Scribunto_LuaTitleLibraryTests extends Scribunto_LuaEngineTestBase {
new WikitextContent( '{{int:mainpage}}<includeonly>...</includeonly><noinclude>...</noinclude>' ),
'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
// 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
$interpreter = $this->getEngine()->getInterpreter();
$interpreter->callFunction(
$interpreter->loadString( "mw.title.testPageId = {$page->getId()}", 'fortest' )
$interpreter->loadString( "mw.title.testPageId = $testPageId", 'fortest' )
);
$this->setMwGlobals( array(

View file

@ -71,7 +71,25 @@ local function test_inexpensive()
end
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
local function test_getCurrentTitle_fragment()
@ -372,7 +390,14 @@ local tests = {
},
{ 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,