From 1573bee81a5bf95efa9b08903a1b130f21f5a2d5 Mon Sep 17 00:00:00 2001 From: Ricordisamoa Date: Thu, 23 Oct 2014 15:15:52 +0200 Subject: [PATCH] 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 --- engines/LuaCommon/TitleLibrary.php | 36 +++++++++++++------ engines/LuaCommon/lualib/mw.title.lua | 7 ++++ tests/engines/LuaCommon/TitleLibraryTest.php | 15 +++++++- tests/engines/LuaCommon/TitleLibraryTests.lua | 29 +++++++++++++-- 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/engines/LuaCommon/TitleLibrary.php b/engines/LuaCommon/TitleLibrary.php index d83dcc9c..d1cf89d9 100644 --- a/engines/LuaCommon/TitleLibrary.php +++ b/engines/LuaCommon/TitleLibrary.php @@ -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 ); + } } diff --git a/engines/LuaCommon/lualib/mw.title.lua b/engines/LuaCommon/lualib/mw.title.lua index 3a443182..5cd72abf 100644 --- a/engines/LuaCommon/lualib/mw.title.lua +++ b/engines/LuaCommon/lualib/mw.title.lua @@ -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, diff --git a/tests/engines/LuaCommon/TitleLibraryTest.php b/tests/engines/LuaCommon/TitleLibraryTest.php index 9a8d4997..7b9657ce 100644 --- a/tests/engines/LuaCommon/TitleLibraryTest.php +++ b/tests/engines/LuaCommon/TitleLibraryTest.php @@ -48,6 +48,19 @@ class Scribunto_LuaTitleLibraryTests extends Scribunto_LuaEngineTestBase { new WikitextContent( '{{int:mainpage}}......' ), '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( diff --git a/tests/engines/LuaCommon/TitleLibraryTests.lua b/tests/engines/LuaCommon/TitleLibraryTests.lua index b65a4f97..24342f03 100644 --- a/tests/engines/LuaCommon/TitleLibraryTests.lua +++ b/tests/engines/LuaCommon/TitleLibraryTests.lua @@ -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}}......' } + expect = { + '{{int:mainpage}}......', + nil, + } + }, + + { name = '.redirectTarget', func = test_redirectTarget, type = 'ToString', + expect = { 'ScribuntoTestTarget', false, false } }, { name = 'not quite too many expensive functions', func = test_expensive_10,