Module:Sandbox/Mr. Stradivarius/sandbox3: Difference between revisions

Content deleted Content added
WikiProject banner code
 
switch to an object-oriented approach
Line 1:
-- TODO:
-- define self.page
 
local htmlBuilder = require( 'Module:HtmlBuilder' )
 
----------------------------------------------------------
-- Define constants
----------------------------------------------------------
 
local currentTitleObject = mw.title.getCurrentTitle()
-- Define a custom error function for this module.
 
local function err( obj, msg, cat )
----------------------------------------------------------
if type( obj ) ~= 'table' then
-- Helper functions
error( 'no object specified to pass errors to' )
----------------------------------------------------------
end
 
if not msg then
-- Makes a simple function that raises an error if the dot syntax is used with methods.
error( 'no error message specified' )
-- It is not 100% reliable, but will catch the majority of cases, and works with inheritance.
end
local function makeCheckSelfFunction( libraryName, varName, selfObjDesc )
obj.errors = obj.errors or {}
table.insertreturn function( obj.errorsself, msgmethod )
if type( self ) ~= 'table' or type( self.new ) ~= 'function' then
if cat then
error( mw.ustring.format(
obj.errorcats = obj.errorcats or {}
'%s: invalid %s. Did you call %s with a dot instead of a colon, i.e. %s.%s() instead of %s:%s()?',
table.insert( obj.errorcats, cat )
libraryName, selfObjDesc, method, varName, method, varName, method
), 3 )
end
end
end
 
-- Checks to see if a given variable is a non-blank string. Returns the string if true,
local function yesno( val, default )
-- and returns false if not.
val = type( val ) == 'string' and mw.ustring.lower( val ) or val -- put in lower case
local function checkString( s )
if not val or val == 'no' or val == 'n' or val == 'false' or tonumber( val ) == 0 then
if type( s ) == 'string' and s ~= '' then
return s
else
return false
end
elseif val == true or val == 'yes' or val == 'y' or val == 'true' or tonumber( val ) == 1 then
end
return true
 
-- Checks to see if a given variable is an object of some kind. Returns the object if true,
-- and returns false if not.
local function checkObject( obj )
if type( obj ) == 'table' and type( obj.new ) == 'function' then
return obj
else
return defaultfalse
end
end
 
----------------------------------------------------------
-- Define the banner class
----------------------------------------------------------
 
local banner = {}
banner.__index = banner
local checkSelfBanner = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'banner', 'banner object' )
 
function banner.:new( datainit )
datainit = datatype( init ) == 'table' and init or {}
local obj = {}
function obj:err( msg, cat )
obj.objectName = init.objectName
return err( obj, msg, cat )
if not obj.objectName then
error( [[No object name specified. Please use "banner:new{ objectName = 'myObject' }".]], 2 )
end
if not data.project then
-- Set the project name and exit if its value is absent or invalid.
obj:err( 'no project specified' )
obj.project = init.project
if type( obj.project ) ~= 'string' or obj.project == '' then return end
-- Set the index metamethod and the metatable.
self.__index = self
return setmetatable( obj, self )
end
 
function banner:setImage()
checkSelfBanner( self, 'setImage' )
end
 
-- Adds one category to the banner's "categories" table.
function banner:addCategory( category )
category = checkString( category )
if category then
self.categories = self.categories or {}
table.insert( self.categories, category )
end
end
obj.project = data.project or ''
 
obj.banner_name = data.banner_name or 'Template:WikiProject ' .. obj.project
-- Adds all categories in a "categories" array to the banner's "categories" table.
obj.project_name = data.project_name or 'WikiProject ' .. obj.project
function banner:addCategories( categoryTable )
obj.project_link = data.project_link or 'Wikipedia:WikiProject ' .. obj.project
if type( categoryTable ) == 'table' then
obj.image_left = data.image_left
for i, category in ipairs( rowObject.categories ) do
obj.image_right = data.image_right
self:addCategory( category )
obj.small = yesno( data.small, false )
if obj.small then end
obj.image_left_size = data.image_left_small or '40px'
obj.image_right_size = data.image_right_small or '40px'
else
obj.image_left_size = data.image_left_large or '80px'
obj.image_right_size = data.image_right_large or '80px'
end
end
obj.main_article = data.main_article
 
obj.main_text = data.main_text
-- Returns a string of category links for the categories in obj.categories.
if not obj.main_text then
function banner:exportCategories()
obj.main_text = mw.ustring.format(
if type( self.categories ) == 'table' then
[=[This %s is within the scope of '''[[%s|%s]]''', a collaborative effort to improve the coverage of %s on Wikipedia.]=],
local ret = {}
'page', obj.project_link, obj.project_name, obj.main_article or '[[' .. obj.project .. ']]'
for i, category in ipairs( self.categories ) do
)
category = checkString( category )
if not obj.small then
if category then
obj.main_text = obj.main_text .. mw.ustring.format(
table.insert( ret, mw.ustring.format(
[=[If you would like to participate, please visit the project page, where you can join the [[%s|discussion]] and see a list of open tasks.]=],
'Wikipedia talk:WikiProject ' .. obj.project'[[Category:%s|%s]]',
) category,
type( self.page ) == 'string' and self.page or currentTitleObject.text
) )
end
end
return table.concat( ret )
end
return ''
end
 
-- Adds a row object to the banners "rows" table, and adds the row object's categories
-- to the banners "categories" table. Categories are deleted from the row object after
-- they have been transferred.
function banner:addRow( rowObject )
checkSelfBanner( self, 'addRow' )
self.rows = self.rows or {}
rowObject = checkObject( rowObject )
if rowObject then
self:addCategories( rowObject.categories )
rowObject.categories = nil -- Erase the categories from the row object to make sure we don't add the same categories twice.
table.insert( self.rows, rowObject )
end
obj.portal = data.portal
setmetatable( obj, banner )
return obj
end
 
function banner:exportRows()
local ret = {}
if type( self.rows ) == 'table' then
for i, rowObject in ipairs( self.rows ) do
rowObject = checkObject( rowObject )
if rowObject then
table.insert( ret, rowObject:export() )
end
end
end
return table.concat( ret )
end
 
function banner:export( templateArgs )
checkSelfBanner( self, 'export' )
end
 
----------------------------------------------------------
-- Define the row class
----------------------------------------------------------
 
local row = {}
row.__index = row
local checkSelfRow = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'row', 'row object' )
 
function row:new( init )
init = type( init ) == 'table' and init or {}
local obj = {}
 
-- Set the index metamethod and the metatable.
self.__index = self
return setmetatable( obj, self )
end
 
function row:addCategory( category )
checkSelfRow( self, 'addCategory' )
if type( category ) == 'string' and category ~= '' then
self.categories = self.categories or {}
table.insert( self.categories, category )
end
end
 
function row:export()
checkSelfRow( self, 'export' )
-- Get the result of the icon and content export functions, and check the results.
local rowIconOutput = type( self.exportRowIcon ) == 'function' and self:exportRowIcon()
rowIconOutput = checkString( rowIconOutput )
local rowContentOutput = type( self.exportRowContent ) == 'function' and self:exportRowContent()
rowContentOutput = checkString( rowContentOutput )
-- Export the row html.
local ret = htmlBuilder.create()
if rowIconOutput and rowContentOutput then
ret
.tag( 'tr' )
.tag( 'td' )
.wikitext( rowIconOutput )
.done()
.tag( 'td' )
.attr( 'colspan', '2' )
.wikitext( rowContentOutput )
elseif rowContentOutput and not rowIconOutput then
ret
.tag( 'tr' )
.tag( 'td' )
.attr( 'colspan', '3' )
.wikitext( rowContentOutput )
end
return tostring( ret )
end
 
----------------------------------------------------------
-- Define the taskForce class
----------------------------------------------------------
 
local taskForce = row:new()
 
-----------------------------------------------------------------
-- Export objects and functions to be used from other modules
-----------------------------------------------------------------
 
local p = {}
 
p.banner = banner
function p.main( frame )
p.row = row
local myBanner = banner.new{ project = "Foo" }
p.makeCheckSelfFunction = makeCheckSelfFunction
return myBanner.main_text
 
-----------------------------------------------------------------
-- Testing area
-----------------------------------------------------------------
 
function p.test( frame )
local myRow = row:new()
return row:export()
end
 
 
return p