Difference between revisions of "Module:User:Mr. Stradivarius/sandbox3"

From blackwiki
Jump to navigation Jump to search
blackwiki>Mr. Stradivarius
(WikiProject banner code)
 
blackwiki>Mr. Stradivarius on tour
(switch to an object-oriented approach)
Line 1: Line 1:
 +
-- TODO:
 +
-- define self.page
 +
 
local htmlBuilder = require( 'Module:HtmlBuilder' )
 
local htmlBuilder = require( 'Module:HtmlBuilder' )
  
 +
----------------------------------------------------------
 +
-- Define constants
 +
----------------------------------------------------------
 +
 +
local currentTitleObject = mw.title.getCurrentTitle()
 +
 +
----------------------------------------------------------
 +
-- Helper functions
 +
----------------------------------------------------------
  
-- Define a custom error function for this module.
+
-- Makes a simple function that raises an error if the dot syntax is used with methods.
local function err( obj, msg, cat )
+
-- It is not 100% reliable, but will catch the majority of cases, and works with inheritance.
     if type( obj ) ~= 'table' then
+
local function makeCheckSelfFunction( libraryName, varName, selfObjDesc )
        error( 'no object specified to pass errors to' )
+
     return function( self, method )
 +
        if type( self ) ~= 'table' or type( self.new ) ~= 'function' then
 +
            error( mw.ustring.format(
 +
                '%s: invalid %s. Did you call %s with a dot instead of a colon, i.e. %s.%s() instead of %s:%s()?',
 +
                libraryName, selfObjDesc, method, varName, method, varName, method
 +
            ), 3 )
 +
        end
 
     end
 
     end
    if not msg then
+
end
        error( 'no error message specified' )
+
 
    end
+
-- Checks to see if a given variable is a non-blank string. Returns the string if true,
    obj.errors = obj.errors or {}
+
-- and returns false if not.
    table.insert( obj.errors, msg )
+
local function checkString( s )
     if cat then
+
     if type( s ) == 'string' and s ~= '' then
         obj.errorcats = obj.errorcats or {}
+
         return s
         table.insert( obj.errorcats, cat )
+
    else
 +
         return false
 
     end
 
     end
 
end
 
end
  
local function yesno( val, default )
+
-- Checks to see if a given variable is an object of some kind. Returns the object if true,
     val = type( val ) == 'string' and mw.ustring.lower( val ) or val -- put in lower case
+
-- and returns false if not.
    if not val or val == 'no' or val == 'n' or val == 'false' or tonumber( val ) == 0 then
+
local function checkObject( obj )
 +
     if type( obj ) == 'table' and type( obj.new ) == 'function' then
 +
        return obj
 +
    else
 
         return false
 
         return false
    elseif val == true or val == 'yes' or val == 'y' or val == 'true' or tonumber( val ) == 1 then
 
        return true
 
    else
 
        return default
 
 
     end
 
     end
 
end
 
end
 +
 +
----------------------------------------------------------
 +
-- Define the banner class
 +
----------------------------------------------------------
  
 
local banner = {}
 
local banner = {}
 
banner.__index = banner
 
banner.__index = banner
 +
local checkSelfBanner = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'banner', 'banner object' )
  
function banner.new( data )
+
function banner:new( init )
     data = data or {}
+
     init = type( init ) == 'table' and init or {}
 
     local obj = {}
 
     local obj = {}
     function obj:err( msg, cat )
+
      
         return err( obj, msg, cat )
+
    obj.objectName = init.objectName
 +
    if not obj.objectName then
 +
        error( [[No object name specified. Please use "banner:new{ objectName = 'myObject' }".]], 2 )
 +
    end
 +
   
 +
    -- Set the project name and exit if its value is absent or invalid.
 +
    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
 +
 
 +
-- Adds all categories in a "categories" array to the banner's "categories" table.
 +
function banner:addCategories( categoryTable )
 +
    if type( categoryTable ) == 'table' then
 +
        for i, category in ipairs( rowObject.categories ) do
 +
            self:addCategory( category )
 +
        end
 
     end
 
     end
     if not data.project then
+
end
         obj:err( 'no project specified' )
+
 
 +
-- Returns a string of category links for the categories in obj.categories.
 +
function banner:exportCategories()
 +
     if type( self.categories ) == 'table' then
 +
         local ret = {}
 +
        for i, category in ipairs( self.categories ) do
 +
            category = checkString( category )
 +
            if category then
 +
                table.insert( ret, mw.ustring.format(
 +
                    '[[Category:%s|%s]]',
 +
                    category,
 +
                    type( self.page ) == 'string' and self.page or currentTitleObject.text
 +
                ) )
 +
            end
 +
        end
 +
        return table.concat( ret )
 
     end
 
     end
     obj.project = data.project or ''
+
     return ''
    obj.banner_name = data.banner_name or 'Template:WikiProject ' .. obj.project
+
end       
     obj.project_name = data.project_name or 'WikiProject ' .. obj.project
+
 
     obj.project_link = data.project_link or 'Wikipedia:WikiProject ' .. obj.project
+
-- Adds a row object to the banners "rows" table, and adds the row object's categories
    obj.image_left = data.image_left
+
-- to the banners "categories" table. Categories are deleted from the row object after
    obj.image_right = data.image_right
+
-- they have been transferred.
     obj.small = yesno( data.small, false )
+
function banner:addRow( rowObject )
     if obj.small then
+
     checkSelfBanner( self, 'addRow' )
         obj.image_left_size = data.image_left_small or '40px'
+
     self.rows = self.rows or {}
         obj.image_right_size = data.image_right_small or '40px'
+
     rowObject = checkObject( rowObject )
    else
+
     if rowObject then
        obj.image_left_size = data.image_left_large or '80px'
+
         self:addCategories( rowObject.categories )
         obj.image_right_size = data.image_right_large or '80px'
+
         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
 
     end
    obj.main_article = data.main_article
+
end
     obj.main_text = data.main_text
+
 
     if not obj.main_text then
+
function banner:exportRows()
        obj.main_text = mw.ustring.format(
+
     local ret = {}
            [=[This %s is within the scope of '''[[%s|%s]]''', a collaborative effort to improve the coverage of %s on Wikipedia.]=],
+
     if type( self.rows ) == 'table' then
             'page', obj.project_link, obj.project_name, obj.main_article or '[[' .. obj.project .. ']]'
+
        for i, rowObject in ipairs( self.rows ) do
        )
+
             rowObject = checkObject( rowObject )
        if not obj.small then
+
            if rowObject then
            obj.main_text = obj.main_text .. mw.ustring.format(
+
                table.insert( ret, rowObject:export() )
                [=[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.]=],
+
             end
                'Wikipedia talk:WikiProject ' .. obj.project
 
             )
 
 
         end
 
         end
 
     end
 
     end
     obj.portal = data.portal
+
     return table.concat( ret )
     setmetatable( obj, banner )
+
end
     return obj
+
 
 +
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
 
end
 +
 +
----------------------------------------------------------
 +
-- Define the taskForce class
 +
----------------------------------------------------------
 +
 +
local taskForce = row:new()
 +
 +
-----------------------------------------------------------------
 +
-- Export objects and functions to be used from other modules
 +
-----------------------------------------------------------------
  
 
local p = {}
 
local p = {}
  
function p.main( frame )
+
p.banner = banner
     local myBanner = banner.new{ project = "Foo" }
+
p.row = row
     return myBanner.main_text
+
p.makeCheckSelfFunction = makeCheckSelfFunction
 +
 
 +
-----------------------------------------------------------------
 +
-- Testing area
 +
-----------------------------------------------------------------
 +
 
 +
function p.test( frame )
 +
     local myRow = row:new()
 +
     return row:export()
 
end
 
end
 +
  
 
return p
 
return p

Revision as of 04:43, 30 August 2013

Usage

Template:Missing documentation {{#invoke:User:Mr. Stradivarius|function_name}}



-- TODO:
-- define self.page

local htmlBuilder = require( 'Module:HtmlBuilder' )

----------------------------------------------------------
-- Define constants
----------------------------------------------------------

local currentTitleObject = mw.title.getCurrentTitle()

----------------------------------------------------------
-- Helper functions
----------------------------------------------------------

-- Makes a simple function that raises an error if the dot syntax is used with methods.
-- It is not 100% reliable, but will catch the majority of cases, and works with inheritance.
local function makeCheckSelfFunction( libraryName, varName, selfObjDesc )
    return function( self, method )
        if type( self ) ~= 'table' or type( self.new ) ~= 'function' then
            error( mw.ustring.format(
                '%s: invalid %s. Did you call %s with a dot instead of a colon, i.e. %s.%s() instead of %s:%s()?',
                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,
-- and returns false if not.
local function checkString( s )
    if type( s ) == 'string' and s ~= '' then
        return s
    else
        return false
    end
end

-- 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 false
    end
end

----------------------------------------------------------
-- Define the banner class
----------------------------------------------------------

local banner = {}
banner.__index = banner
local checkSelfBanner = makeCheckSelfFunction( 'Module:WikiProjectBanner', 'banner', 'banner object' )

function banner:new( init )
    init = type( init ) == 'table' and init or {}
    local obj = {}
    
    obj.objectName = init.objectName
    if not obj.objectName then
        error( [[No object name specified. Please use "banner:new{ objectName = 'myObject' }".]], 2 )
    end
    
    -- Set the project name and exit if its value is absent or invalid.
    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

-- Adds all categories in a "categories" array to the banner's "categories" table.
function banner:addCategories( categoryTable )
    if type( categoryTable ) == 'table' then
        for i, category in ipairs( rowObject.categories ) do
            self:addCategory( category )
        end
    end
end

-- Returns a string of category links for the categories in obj.categories.
function banner:exportCategories()
    if type( self.categories ) == 'table' then
        local ret = {}
        for i, category in ipairs( self.categories ) do
            category = checkString( category )
            if category then
                table.insert( ret, mw.ustring.format(
                    '[[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
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
p.row = row
p.makeCheckSelfFunction = makeCheckSelfFunction

-----------------------------------------------------------------
-- Testing area
-----------------------------------------------------------------

function p.test( frame )
    local myRow = row:new()
    return row:export()
end


return p