mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Scribunto
synced 2024-11-27 17:50:06 +00:00
Add mw.message library
Change-Id: I12ca84f848c34f1227ee8acdc8bc04bdfd0b2d97
This commit is contained in:
parent
07d6ed437a
commit
ba09ba3fde
|
@ -107,6 +107,7 @@ $wgAutoloadClasses['Scribunto_LuaSiteLibrary'] = $dir.'engines/LuaCommon/SiteLib
|
|||
$wgAutoloadClasses['Scribunto_LuaUriLibrary'] = $dir.'engines/LuaCommon/UriLibrary.php';
|
||||
$wgAutoloadClasses['Scribunto_LuaUstringLibrary'] = $dir.'engines/LuaCommon/UstringLibrary.php';
|
||||
$wgAutoloadClasses['Scribunto_LuaLanguageLibrary'] = $dir.'engines/LuaCommon/LanguageLibrary.php';
|
||||
$wgAutoloadClasses['Scribunto_LuaMessageLibrary'] = $dir.'engines/LuaCommon/MessageLibrary.php';
|
||||
|
||||
/***** Configuration *****/
|
||||
|
||||
|
|
|
@ -301,6 +301,7 @@ WIKI;
|
|||
'engines/LuaCommon/SiteLibraryTest.php',
|
||||
'engines/LuaCommon/UriLibraryTest.php',
|
||||
'engines/LuaCommon/UstringLibraryTest.php',
|
||||
'engines/LuaCommon/MessageLibraryTest.php',
|
||||
);
|
||||
foreach ( $tests as $test ) {
|
||||
$files[] = dirname( __FILE__ ) .'/../tests/' . $test;
|
||||
|
|
|
@ -10,6 +10,7 @@ abstract class Scribunto_LuaEngine extends ScribuntoEngineBase {
|
|||
'mw.uri' => 'Scribunto_LuaUriLibrary',
|
||||
'mw.ustring' => 'Scribunto_LuaUstringLibrary',
|
||||
'mw.language' => 'Scribunto_LuaLanguageLibrary',
|
||||
'mw.message' => 'Scribunto_LuaMessageLibrary',
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
74
engines/LuaCommon/MessageLibrary.php
Normal file
74
engines/LuaCommon/MessageLibrary.php
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
class Scribunto_LuaMessageLibrary extends Scribunto_LuaLibraryBase {
|
||||
function register() {
|
||||
$lib = array(
|
||||
'toString' => array( $this, 'messageToString' ),
|
||||
'check' => array( $this, 'messageCheck' ),
|
||||
);
|
||||
|
||||
// Get the correct default language from the parser
|
||||
if ( $this->getParser() ) {
|
||||
$lang = $this->getParser()->getTargetLanguage();
|
||||
} else {
|
||||
global $wgContLang;
|
||||
$lang = $wgContLang;
|
||||
}
|
||||
|
||||
$this->getEngine()->registerInterface( 'mw.message.lua', $lib, array(
|
||||
'lang' => $lang->getCode(),
|
||||
) );
|
||||
}
|
||||
|
||||
private function makeMessage( $data, $setParams ) {
|
||||
if ( isset( $data['rawMessage'] ) ) {
|
||||
$msg = new RawMessage( $data['rawMessage'] );
|
||||
} else {
|
||||
$msg = Message::newFallbackSequence( $data['keys'] );
|
||||
}
|
||||
$msg->inLanguage( $data['lang'] )
|
||||
->useDatabase( $data['useDB'] );
|
||||
if ( $setParams ) {
|
||||
if ( isset( $data['title'] ) ) {
|
||||
$title = Title::newFromText( $data['title'] );
|
||||
} else {
|
||||
$title = $this->getTitle();
|
||||
}
|
||||
|
||||
$msg->params( array_values( $data['params'] ) )
|
||||
->title( $title );
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
function messageToString( $format, $data ) {
|
||||
if ( !in_array( $format, array( 'parse', 'text', 'plain', 'escaped', 'parseAsBlock' ) ) ) {
|
||||
throw new Scribunto_LuaError( "invalid format for 'messageToString'" );
|
||||
}
|
||||
|
||||
if ( in_array( $format, array( 'parse', 'parseAsBlock' ) ) ) {
|
||||
// Limit calls into the full parser
|
||||
$this->incrementExpensiveFunctionCount();
|
||||
}
|
||||
|
||||
try {
|
||||
$msg = $this->makeMessage( $data, true );
|
||||
return array( call_user_func( array( $msg, $format ) ) );
|
||||
} catch( MWException $ex ) {
|
||||
throw new Scribunto_LuaError( "msg:$format() failed (" . $ex->getMessage() . ")" );
|
||||
}
|
||||
}
|
||||
|
||||
function messageCheck( $what, $data ) {
|
||||
if ( !in_array( $what, array( 'exists', 'isBlank', 'isDisabled' ) ) ) {
|
||||
throw new Scribunto_LuaError( "invalid what for 'messageCheck'" );
|
||||
}
|
||||
|
||||
try {
|
||||
$msg = $this->makeMessage( $data, false );
|
||||
return array( call_user_func( array( $msg, $what ) ) );
|
||||
} catch( MWException $ex ) {
|
||||
throw new Scribunto_LuaError( "msg:$what() failed (" . $ex->getMessage() . ")" );
|
||||
}
|
||||
}
|
||||
}
|
231
engines/LuaCommon/lualib/mw.message.lua
Normal file
231
engines/LuaCommon/lualib/mw.message.lua
Normal file
|
@ -0,0 +1,231 @@
|
|||
local message = {}
|
||||
local php
|
||||
|
||||
local util = require 'libraryUtil'
|
||||
local checkType = util.checkType
|
||||
|
||||
local valuemt = {
|
||||
__tostring = function ( t )
|
||||
return tostring( t.raw or t.num )
|
||||
end
|
||||
}
|
||||
|
||||
local function checkScalar( name, argIdx, arg, level, valuemtOk )
|
||||
local tp = type( arg )
|
||||
|
||||
-- If special params are ok, detect them
|
||||
if valuemtOk and tp == 'table' and getmetatable( arg ) == valuemt then
|
||||
return arg
|
||||
end
|
||||
|
||||
-- If it's a table with a custom __tostring function, use that string
|
||||
if tp == 'table' and getmetatable( arg ) and getmetatable( arg ).__tostring then
|
||||
return tostring( arg )
|
||||
end
|
||||
|
||||
if tp ~= 'string' and tp ~= 'number' then
|
||||
error( string.format(
|
||||
"bad argument #%d to '%s' (string or number expected, got %s)",
|
||||
argIdx, name, tp
|
||||
), level + 1 )
|
||||
end
|
||||
|
||||
return arg
|
||||
end
|
||||
|
||||
local function checkParams( name, valueOk, ... )
|
||||
-- Accept an array of params, or params as individual command line arguments
|
||||
local params, nparams
|
||||
local first = select( 1, ... )
|
||||
if type( first ) == 'table' and
|
||||
not ( getmetatable( first ) and getmetatable( first ).__tostring )
|
||||
then
|
||||
if select( '#', ... ) == 1 then
|
||||
params = first
|
||||
nparams = table.maxn( params )
|
||||
else
|
||||
error(
|
||||
"bad arguments to '" .. name .. "' (pass either a table of params or params as individual arguments)",
|
||||
3
|
||||
)
|
||||
end
|
||||
else
|
||||
params = { ... }
|
||||
nparams = select( '#', ... )
|
||||
end
|
||||
for i = 1, nparams do
|
||||
params[i] = checkScalar( 'params', i, params[i], 3, valueOk )
|
||||
end
|
||||
return params
|
||||
end
|
||||
|
||||
function message.setupInterface( options )
|
||||
-- Boilerplate
|
||||
message.setupInterface = nil
|
||||
php = mw_interface
|
||||
mw_interface = nil
|
||||
php.options = options
|
||||
|
||||
-- Register this library in the "mw" global
|
||||
mw = mw or {}
|
||||
mw.message = message
|
||||
|
||||
package.loaded['mw.message'] = message
|
||||
end
|
||||
|
||||
local function makeMessage( options )
|
||||
local obj = {}
|
||||
local checkSelf = util.makeCheckSelfFunction( 'mw.message', 'msg', obj, 'message object' )
|
||||
|
||||
local data = {
|
||||
keys = options.keys,
|
||||
rawMessage = options.rawMessage,
|
||||
params = {},
|
||||
lang = php.options.lang,
|
||||
useDB = true,
|
||||
}
|
||||
local funcs = {}
|
||||
|
||||
function funcs:params( ... )
|
||||
checkSelf( self, 'params' )
|
||||
local params = checkParams( 'params', true, ... )
|
||||
local j = #data.params
|
||||
for i = 1, #params do
|
||||
data.params[j + i] = params[i]
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function funcs:rawParams( ... )
|
||||
checkSelf( self, 'rawParams' )
|
||||
local params = checkParams( 'rawParams', false, ... )
|
||||
local j = #data.params
|
||||
for i = 1, #params do
|
||||
data.params[j + i] = setmetatable( { raw = params[i] }, valuemt )
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function funcs:numParams( ... )
|
||||
checkSelf( self, 'numParams' )
|
||||
local params = checkParams( 'numParams', false, ... )
|
||||
local j = #data.params
|
||||
for i = 1, #params do
|
||||
data.params[j + i] = setmetatable( { num = params[i] }, valuemt )
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function funcs:inLanguage( lang )
|
||||
checkSelf( self, 'inLanguage' )
|
||||
if type( lang ) == 'table' and lang.getCode then
|
||||
-- probably a mw.language object
|
||||
lang = lang:getCode()
|
||||
end
|
||||
checkType( 'inLanguage', 1, lang, 'string' )
|
||||
data.lang = lang
|
||||
return self
|
||||
end
|
||||
|
||||
function funcs:useDatabase( value )
|
||||
checkSelf( self, 'useDatabase' )
|
||||
checkType( 'useDatabase', 1, value, 'boolean' )
|
||||
data.useDB = value
|
||||
return self
|
||||
end
|
||||
|
||||
function funcs:title( title )
|
||||
checkSelf( self, 'title' )
|
||||
if type( title ) == 'table' and title.prefixedText then
|
||||
-- probably a mw.title object
|
||||
title = title.prefixedText
|
||||
end
|
||||
checkType( 'title', 1, title , 'string', true )
|
||||
data.title = title
|
||||
return self
|
||||
end
|
||||
|
||||
function funcs:parse()
|
||||
checkSelf( self, 'parse' )
|
||||
return php.toString( 'parse', data )
|
||||
end
|
||||
|
||||
function funcs:text()
|
||||
checkSelf( self, 'text' )
|
||||
return php.toString( 'text', data )
|
||||
end
|
||||
|
||||
function funcs:plain()
|
||||
checkSelf( self, 'plain' )
|
||||
return php.toString( 'plain', data )
|
||||
end
|
||||
|
||||
function funcs:escaped()
|
||||
checkSelf( self, 'escaped' )
|
||||
return php.toString( 'escaped', data )
|
||||
end
|
||||
|
||||
function funcs:parseAsBlock()
|
||||
checkSelf( self, 'parseAsBlock' )
|
||||
return php.toString( 'parseAsBlock', data )
|
||||
end
|
||||
|
||||
function funcs:exists()
|
||||
checkSelf( self, 'exists' )
|
||||
return php.check( 'exists', data )
|
||||
end
|
||||
|
||||
function funcs:isBlank()
|
||||
checkSelf( self, 'isBlank' )
|
||||
return php.check( 'isBlank', data )
|
||||
end
|
||||
|
||||
function funcs:isDisabled()
|
||||
checkSelf( self, 'isDisabled' )
|
||||
return php.check( 'isDisabled', data )
|
||||
end
|
||||
|
||||
return setmetatable( obj, {
|
||||
__index = funcs,
|
||||
__tostring = function ( t )
|
||||
return t:text()
|
||||
end
|
||||
} )
|
||||
end
|
||||
|
||||
function message.new( key, ... )
|
||||
checkType( 'message.new', 1, key, 'string' )
|
||||
return makeMessage{ keys = { key } }:params( ... )
|
||||
end
|
||||
|
||||
function message.newFallbackSequence( ... )
|
||||
for i = 1, math.max( 1, select( '#', ... ) ) do
|
||||
checkType( 'message.newFallbackSequence', i, select( i, ... ), 'string' )
|
||||
end
|
||||
return makeMessage{ keys = { ... } }
|
||||
end
|
||||
|
||||
function message.newRawMessage( msg, ... )
|
||||
checkType( 'message.newRawMessage', 1, msg, 'string' )
|
||||
return makeMessage{ rawMessage = msg }:params( ... )
|
||||
end
|
||||
|
||||
function message.rawParam( value )
|
||||
value = checkScalar( 'message.rawParam', 1, value )
|
||||
return setmetatable( { raw = value }, valuemt )
|
||||
end
|
||||
|
||||
function message.numParam( value )
|
||||
value = checkScalar( 'message.numParam', 1, value )
|
||||
return setmetatable( { num = value }, valuemt )
|
||||
end
|
||||
|
||||
function message.getDefaultLanguage()
|
||||
if mw.language then
|
||||
return mw.language.new( php.options.lang )
|
||||
else
|
||||
return php.options.lang
|
||||
end
|
||||
end
|
||||
|
||||
return message
|
11
tests/engines/LuaCommon/MessageLibraryTest.php
Normal file
11
tests/engines/LuaCommon/MessageLibraryTest.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
class Scribunto_LuaMessageLibraryTests extends Scribunto_LuaEngineTestBase {
|
||||
protected static $moduleName = 'MessageLibraryTests';
|
||||
|
||||
function getTestModules() {
|
||||
return parent::getTestModules() + array(
|
||||
'MessageLibraryTests' => __DIR__ . '/MessageLibraryTests.lua',
|
||||
);
|
||||
}
|
||||
}
|
85
tests/engines/LuaCommon/MessageLibraryTests.lua
Normal file
85
tests/engines/LuaCommon/MessageLibraryTests.lua
Normal file
|
@ -0,0 +1,85 @@
|
|||
local testframework = require 'Module:TestFramework'
|
||||
|
||||
local message1 = mw.message.new( 'mainpage' )
|
||||
local message1_copy = mw.message.new( 'mainpage' )
|
||||
local message2 = mw.message.new( 'i-dont-exist-evar' )
|
||||
|
||||
function test_exists( key )
|
||||
return mw.message.new( key ):exists()
|
||||
end
|
||||
|
||||
function test_language( key )
|
||||
-- If mw.language is available, test that too
|
||||
local lang = 'ru'
|
||||
if mw.language then
|
||||
lang = mw.language.new( 'ru' )
|
||||
end
|
||||
|
||||
return mw.message.new( 'mainpage' ):useDatabase( false ):inLanguage( 'en' ):text(),
|
||||
mw.message.new( 'mainpage' ):useDatabase( false ):inLanguage( 'ru' ):text(),
|
||||
mw.message.new( 'mainpage' ):useDatabase( false ):inLanguage( lang ):text()
|
||||
end
|
||||
|
||||
function test_params( rawMessage, func, ... )
|
||||
local msg = mw.message.newRawMessage( rawMessage ):inLanguage( 'en' )
|
||||
return msg[func]( msg, ... ):parse()
|
||||
end
|
||||
|
||||
function test_title()
|
||||
-- If mw.title is available, test that too
|
||||
local title = 'Main Page'
|
||||
if mw.title then
|
||||
title = mw.title.new( title )
|
||||
end
|
||||
|
||||
return mw.message.newRawMessage( '{{PAGENAME}}' ):title( 'Main Page' ):text(),
|
||||
mw.message.newRawMessage( '{{PAGENAME}}' ):title( title ):text()
|
||||
end
|
||||
|
||||
return testframework.getTestProvider( {
|
||||
{ name = 'exists (1)', func = test_exists,
|
||||
args = { 'mainpage' },
|
||||
expect = { true }
|
||||
},
|
||||
{ name = 'exists (2)', func = test_exists,
|
||||
args = { 'i-dont-exist-evar' },
|
||||
expect = { false }
|
||||
},
|
||||
|
||||
{ name = 'inLanguage', func = test_language,
|
||||
expect = { 'Main Page', 'Заглавная страница', 'Заглавная страница' }
|
||||
},
|
||||
|
||||
{ name = 'title', func = test_title,
|
||||
expect = { 'Main Page', 'Main Page' }
|
||||
},
|
||||
|
||||
{ name = 'plain param', func = test_params,
|
||||
args = { '($1 $2)', 'params', "'''foo'''", 123456 },
|
||||
expect = { "(<b>foo</b> 123456)" }
|
||||
},
|
||||
{ name = 'raw param', func = test_params,
|
||||
args = { '($1 $2)', 'rawParams', "'''foo'''", 123456 },
|
||||
expect = { "('''foo''' 123456)" }
|
||||
},
|
||||
{ name = 'num param', func = test_params,
|
||||
args = { '($1 $2)', 'numParams', "'''foo'''", 123456 },
|
||||
expect = { "(<b>foo</b> 123,456)" }
|
||||
},
|
||||
{ name = 'mixed params', func = test_params,
|
||||
args = { '($1 $2 $3)', 'params',
|
||||
"'''foo'''", mw.message.rawParam( "'''foo'''" ), mw.message.numParam( 123456 )
|
||||
},
|
||||
expect = { "(<b>foo</b> '''foo''' 123,456)" }
|
||||
},
|
||||
|
||||
{ name = 'message as param', func = test_params,
|
||||
args = { '($1)', 'params', mw.message.newRawMessage( 'bar' ) },
|
||||
expect = { "(bar)" }
|
||||
},
|
||||
|
||||
{ name = 'different title', func = test_params,
|
||||
args = { '($1)', 'params', mw.message.newRawMessage( 'bar' ) },
|
||||
expect = { "(bar)" }
|
||||
},
|
||||
} )
|
Loading…
Reference in a new issue