Module:UserLinks: Difference between revisions

From the Croc Wiki, the Croc encyclopedia
Jump to navigationJump to search
Content added Content deleted
(switch the edit count link from the Toolserver to Labs, per protected edit request by User:DHeyward)
(update count link per protected edit request by User:Frietjes)
Line 66: Line 66:


local function makeCountLink()
local function makeCountLink()
return '[//tools.wmflabs.org/xtools/pcount/index.php?name=' .. u.usernameHtml
return '[//tools.wmflabs.org/supercount/index.php?user=' .. u.usernameHtml
.. '&lang=' .. u.toolLang
.. '&project=' .. u.toolLang .. '.' .. u.projectLong
.. '&wiki=' .. u.projectLong
.. ' count]'
.. ' count]'
end
end

Revision as of 02:30, March 27, 2014

Documentation for this module may be created at Module:UserLinks/doc

local ToolbarBuilder = require('Module:Toolbar')
local interwikiTable = mw.loadData("Module:InterwikiTable")

local u = {} -- Table for user-data helper strings.
local trackingCategories = {} -- Table for storing the tracking categories.
local demo

-- Define a custom error message for this module.
local function err(msg, section)
    local help
    if section then
        help = ' ([[Template:User-multi#' .. section .. '|help]])'
    else
        help = ''
    end
    local cat
    if demo == 'yes' then
        cat = ''
    else
        cat = '[[Category:UserLinks transclusions with errors]]'
    end
    return '<span class="error">[[Template:User-multi|User-multi]] error: ' .. msg 
        .. help .. '.</span>' .. cat
end

----------------------------------------------------------------------------------------------
--      To add more link types, write a function that produces an individual link, and put  --
--      it at the bottom of the list below. Then, add a link code for your function to the  --
--      "linktypes" table. Try and make the code three letters or less. There are a number  --
--      of helper strings available for writing the functions:                       --
--                                                                                          --
--      u.username          The plain username. If the username is not present then the     --
--                          module returns an error.                                        --
--      u.usernameHtml      The username html-encoded. Spaces are encoded with plus signs.  --
--      u.project           The project name. Nil if not specified.                         --
--      u.lang              The language code. Nil if not specified.                        --
--      u.interwiki         The interwiki prefix, consisting of the project and language    --
--                          values, separated by colons, e.g. ":wikt:es:". If no project    --
--                          or language values are found, this is the blank string, "".     --
--      u.projectCode       If a valid project is specified, this is the code for that      --
--                          project in [[Module:InterwikiTable]]. Otherwise this is nil.    --
--      u.projectLong       The long project name, e.g. "wikipedia" or "wikibooks". If      --
--                          not specified the default is "wikipedia".                       --
--      u.toolLang          The language code for use with toolserver or labs tools. The    --
--                          default is "en".                                                --
--                                                                                          --
--      If you want more helper strings, you can define them in the generateUserDataStrings --
--      function below.                                                                     --
----------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------
--                                LINK FUNCTIONS START                                      --
----------------------------------------------------------------------------------------------

local function makeUserLink()
    return '[[' .. u.interwiki .. 'User:' .. u.username .. '|' .. u.username .. ']]'
end

local function makeTalkLink()
    return '[[' .. u.interwiki .. 'User talk:' .. u.username .. '|talk]]'
end

local function makeContribsLink()
    return '[[' .. u.interwiki .. 'Special:Contributions/' .. u.username .. '|contribs]]'
end

local function makeCountLink()
    return '[//tools.wmflabs.org/supercount/index.php?user=' .. u.usernameHtml
        .. '&project=' .. u.toolLang .. '.' .. u.projectLong
        .. ' count]'
end

local function makeMovesLink()
    return '[[' .. u.interwiki .. 'Special:Log/move/' .. u.username .. '|page&nbsp;moves]]'
end

local function makeLogsLink()
    return '[[' .. u.interwiki .. 'Special:Log/' .. u.username .. '|logs]]'
end

local function makeBlockLogLink()
    local url = mw.uri.fullUrl(u.interwiki .. 'Special:Log/block', 'page=User:' .. u.usernameHtml)
    return '[' .. tostring(url) .. ' block&nbsp;log]'
end

local function makeBlocksLink()
    return '[[' .. u.interwiki .. 'Special:Log/block/' .. u.username .. '|blocks]]'
end

local function makeBlockUserLink()
    return '[[' .. u.interwiki .. 'Special:Block/' .. u.username .. '|block&nbsp;user]]'
end

local function makeCentralAuthLink()
    return '[[' .. u.interwiki .. 'Special:CentralAuth/' .. u.username .. '|central&nbsp;auth]]'
end

local function makeDeletedContribsLink()
    return '[[' .. u.interwiki .. 'Special:DeletedContributions/' .. u.username .. '|deleted&nbsp;contribs]]'
end

local function makeEmailLink()
    return '[[' .. u.interwiki .. 'Special:Emailuser/' .. u.username .. '|email]]'
end

local function makeEditSummariesLink()
    return '[http://tools.wmflabs.org/xtools/editsummary/index.php?name=' .. u.usernameHtml
        .. '&lang=' .. u.toolLang
        .. '&wiki=' .. u.projectLong
        .. ' edit&nbsp;summaries]'
end

local function makeDeletionsLink()
    return '[[' .. u.interwiki .. 'Special:Log/delete/' .. u.username .. '|deletions]]'
end

local function makeListUserLink()
    local url = mw.uri.fullUrl(u.interwiki .. 'Special:ListUsers', 'limit=1&username=' .. u.usernameHtml)
    return '[' .. tostring(url) .. ' list&nbsp;user]'
end

local function makeSulLink()
    return '[[sulutil:' .. u.username .. '|global&nbsp;contribs]]'
end

local function makeTargetLogsLink()
    local url = mw.uri.fullUrl(u.interwiki .. 'Special:Log', 'page=User:' .. u.usernameHtml)
    return '[' .. tostring(url) .. ' target&nbsp;logs]'
end

local function makeEditFilterLogLink()
    local url = mw.uri.fullUrl(u.interwiki .. 'Special:AbuseLog', 'wpSearchUser=' .. u.usernameHtml)
    return '[' .. tostring(url) .. ' edit&nbsp;filter&nbsp;log]'
end

local function makeProtectionsLink()
    return '[[' .. u.interwiki .. 'Special:Log/protect/' .. u.username .. '|protections]]'
end

local function makeRightsLink()
    return '[[' .. u.interwiki .. 'Special:Log/rights/' .. u.username .. '|rights]]'
end

local function makeRenamesLink()
    return '[[' .. u.interwiki .. 'Special:Log/renameuser/' .. u.username .. '|renames]]'
end

local function makeRfaLink()
    if u.project or u.lang then
        table.insert( trackingCategories, '[[Category:UserLinks transclusions with unresolvable interwiki links]]' )
    end
    return '[[Special:PrefixIndex/Wikipedia:Requests for adminship/' .. u.username .. '|RfA]]'
end

local function makeApiLink()
    -- Find the full domain, as the API can't be accessed through the interwiki system.
    local fulldomain
    local lang = u.lang or 'en'
    if u.projectCode then
        local domain = interwikiTable[u.projectCode].domain
        local takesLangPrefix = interwikiTable[u.projectCode].takes_lang_prefix
        if not takesLangPrefix then
            fulldomain = domain
        else
            fulldomain = lang .. '.' .. domain
        end
    else
        fulldomain = lang .. '.wikipedia.org'
    end
    
    -- Return the API link
    return '[//' .. fulldomain .. '/w/api.php?action=query&list=users&usprop=editcount&ususers=' .. u.usernameHtml .. ' api]'
end

local function makeUploadsLink()
    return '[[' .. u.interwiki .. 'Special:ListFiles/' .. u.username .. '|uploads]]'
end

----------------------------------------------------------------------------------------------
--                                   LINK FUNCTIONS END                                     --
--      To enable new link functions, add the code to the "linktypes" table directly below. --
----------------------------------------------------------------------------------------------

local linktypes = {
    {'t'   , makeTalkLink},
    {'c'   , makeContribsLink},
    {'ct'  , makeCountLink},
    {'m'   , makeMovesLink},
    {'l'   , makeLogsLink},
    {'bl'  , makeBlockLogLink},
    {'bls' , makeBlocksLink},
    {'bu'  , makeBlockUserLink},
    {'ca'  , makeCentralAuthLink},
    {'dc'  , makeDeletedContribsLink},
    {'e'   , makeEmailLink},
    {'es'  , makeEditSummariesLink},
    {'del' , makeDeletionsLink},
    {'lu'  , makeListUserLink},
    {'sul' , makeSulLink},
    {'tl'  , makeTargetLogsLink},
    {'efl' , makeEditFilterLogLink},
    {'pr'  , makeProtectionsLink},
    {'rl'  , makeRightsLink},
    {'ren' , makeRenamesLink},
    {'rfa' , makeRfaLink},
    {'api' , makeApiLink},
    {'up'  , makeUploadsLink}
}

local function getLink(linktype)
    local linkNumber
    for i, value in ipairs(linktypes) do
        if value[1] == linktype then
            linkNumber = i
            break
        end
    end
    if not linkNumber then
        return err('"' .. linktype .. '" is not a valid link code', 'Not a valid link code')
    end
    local result = linktypes[linkNumber][2]()
    if type(result) ~= 'string' then
        return err(
            'the function for code "' .. linktype .. '" did not return a string value',
            'Function did not return a string value'
        )
    end
    return result
end

local function makeToolbar(args)
    local targs = {}
    local numArgsExist = false
    for k, v in pairs(args) do
        if type(k) == 'number' then
            numArgsExist = true
            targs[k] = getLink(v)
        end
    end
    targs.style = args.small and 'font-size: 90%;'
    targs.separator = args.separator or 'dot'
    
    if numArgsExist == false then
        return nil -- Don't return a toolbar if no numeric arguments exist.
    else
        return ToolbarBuilder.main(targs)
    end
end

-- This function finds whether a string is a valid interwiki project prefix.
-- If the string is valid, the function outputs two values: true, and the site code
-- used in [[Module:InterwikiTable]]. If the string is valid, the function outputs
-- false and nil.
local function isKnownProject(prefix)
    for projectCode, projectVal in pairs(interwikiTable) do
        for _, iwCode in ipairs(projectVal.iw_prefix) do
            if iwCode == prefix then
                return true, projectCode
            end
        end
    end
    return false, nil
end

local function generateUserDataStrings(args)
    -- If the username is absent or blank, return an error and a tracking category.
    if args.user == '' or (not args.user and (not args.User or args.User == '')) then
        return err('no username detected', 'No username detected')
    else
        u.username = args.user or args.User
    end
    
    -- Get other basic user data strings.
    u.project = args.Project or args.project
    u.lang = args.lang or args.Lang
    if u.lang then
        if mw.language.isKnownLanguageTag(u.lang) then
            table.insert(trackingCategories, '[[Category:UserLinks transclusions with language parameters]]')
        else
            return err('"' .. u.lang .. '" is not a valid language code', 'Not a valid language code')
        end
    end
    
    -- Process the project value if it is present.
    if u.project then
        table.insert( trackingCategories, '[[Category:UserLinks transclusions with project parameters]]' )
        
        -- If u.project is a known project, we only need to get the project code. If the project 
        -- isn't known, first check whether it is a valid language code, and if not then see if it's
        -- an interwiki code separated by colons, e.g. "wikt:es".
        local uprojectIsKnownProject, uprojectProjectCode = isKnownProject(u.project)
        if uprojectIsKnownProject then
            u.projectCode = uprojectProjectCode
        else
            if mw.language.isKnownLanguageTag(u.project) then
                u.lang = u.project
                u.project = nil
            else
                local pref1, pref2 = mw.ustring.match( u.project, '^(%w+):(%w+)$' )
                if pref1 and pref2 then
                    local pref1IsKnownProject, pref1ProjectCode = isKnownProject(pref1)
                    local pref2IsKnownProject, pref2ProjectCode = isKnownProject(pref2)
                    if pref1IsKnownProject
                        and mw.language.isKnownLanguageTag(pref2)
                        and interwikiTable[pref1ProjectCode].takes_lang_prefix then
                        u.project = pref1
                        u.lang = pref2
                        u.projectCode = pref1ProjectCode
                        table.insert(
                            trackingCategories,
                            '[[Category:UserLinks transclusions with project parameters containing language codes]]'
                        )
                    elseif pref2IsKnownProject
                        and mw.language.isKnownLanguageTag(pref1)
                        and interwikiTable[pref2ProjectCode].takes_lang_prefix then
                        u.project = pref2
                        u.lang = pref1
                        u.projectCode = pref2ProjectCode
                        table.insert(
                            trackingCategories,
                            '[[Category:UserLinks transclusions with project parameters containing language codes]]'
                        )
                    else
                        return err(
                            '"' .. u.project .. '" is not a valid interwiki prefix',
                            'Not a valid interwiki prefix'
                        )
                    end
                else
                    return err(
                        '"' .. u.project .. '" is not a valid interwiki prefix',
                        'Not a valid interwiki prefix'
                    )
                end
            end
        end
    end
    
    -- Generate the interwiki prefix. This includes colons.
    if u.project or u.lang then
        u.interwiki = ''
        if u.project then
            u.interwiki = u.interwiki .. ':' .. u.project
        end
        if u.lang then
            u.interwiki = u.interwiki .. ':' .. u.lang
        end
        u.interwiki = u.interwiki .. ':'
    else
        u.interwiki = ''
    end

    -- Generate the other helper strings.
    u.usernameHtml = mw.uri.encode(u.username) -- Html-encoded username. Spaces are encoded as pluses.
    if u.project then
        local prefixes = interwikiTable[u.projectCode].iw_prefix
        u.projectLong = prefixes[2] or prefixes[1] -- A bit of a hack, but should find the long prefix name most of the time.
    else
        u.projectLong = 'wikipedia'
    end
    u.toolLang = u.lang or 'en' -- set the default language for tools on the toolserver or labs.
end

local function generateTrackingCategories()
    if demo == 'yes' then
        return ''
    else
        return table.concat(trackingCategories)
    end
end

-- This function generates a table of all available link types, with their previews.
-- It is used in the module documentation.
local function getLinkTable(args)
    demo = args.demo -- Set the demo variable.
    -- Generate the user data strings and return any errors.
    local dataStringError = generateUserDataStrings(args)
    if dataStringError then
        return dataStringError
    end
    
    -- Build a table of all of the links.
    local result = '<table class="wikitable plainlinks sortable">'
        .. '\n<tr><th>Code</th><th>Preview</th></tr>'
    for i, value in ipairs(linktypes) do
        local code = value[1]
        result = result .. "\n<tr><td>'''" .. code .. "'''</td><td>" .. getLink(code) .. '</td></tr>'
    end
    result = result .. '\n</table>'
    
    return result
end

local function getSingleLink(args)
    demo = args.demo -- Set the demo variable.
    -- Generate the user data strings and return any errors.
    local dataStringError = generateUserDataStrings(args)
    if dataStringError then
        return dataStringError
    end
    
    local linktype = args[1]
    if not linktype then 
        return err('no link type specified')
    end
    local result = getLink(linktype)
    result = result .. generateTrackingCategories()
    return result
end

local function getLinks(args)
    demo = args.demo -- Set the demo variable.
    -- Generate the user data strings and return any errors.
    local dataStringError = generateUserDataStrings(args)
    if dataStringError then
        return dataStringError
    end    
    
    -- Build the template output.
    local result = makeToolbar(args) -- Get the toolbar contents.
    if result then
        if args.sup then
            result = '<sup>' .. result .. '</sup>'
        end
        result = '&nbsp;' .. result
    else
        result = '' -- If there are no links specified, don't return the toolbar at all.
    end
    result = '<span>' .. makeUserLink() .. result .. '</span>'
    result = result .. generateTrackingCategories()
    
    return result
end

local function getExampleLinks(args)
    -- This function enables example output without having to specify any
    -- parameters to #invoke.
    args.demo = 'yes'
    args.user = 'Example'
    args.User = nil
    return getLinks(args)
end

local function makeWrapper(func)
    return function (frame)
        -- If called via #invoke, use the args passed into the invoking template.
        -- Otherwise, for testing purposes, assume args are being passed directly in.
        local origArgs
        if frame == mw.getCurrentFrame() then
            origArgs = frame:getParent().args
            for k, v in pairs(frame.args) do
                origArgs = frame.args
                break
            end
        else
            origArgs = frame
        end
 
        -- Strip whitespace, and treat blank arguments as nil.
        -- 'user', 'User', and 'separator' have different behaviour depending on
        -- whether they are blank or nil, so keep them as they are.
        local args = {}
        for k, v in pairs(origArgs) do
            v = mw.text.trim(v)
            if v ~= '' or k == 'user' or k == 'User' or k == 'separator' then
                args[k] = v
            end
        end
    
        return func(args)
    end
end

return {
    main = makeWrapper(getLinks),
    single = makeWrapper(getSingleLink),
    linktable = makeWrapper(getLinkTable),
    example = makeWrapper(getExampleLinks)
}