Module:Portal

From EyeWiki

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

local p = {}

function p.getClass(text)
    if text == 'Up to Date' then
        return 'success'
    end
    if text == 'Update Pending' then
        return 'warning'
    end
    return 'danger'
end

local function toTable( value )
   local type = type(value)
   if type == 'nil' then
       return {}
   end
   if type == 'table' then
       return value
   end
   return {value}
end

local function getPortalMembers( catName )
    local res = mw.smw.ask{
        '[[Portal:' .. catName ..']]',
        '?Editor#-',
        '?Main editor#-'
    }
    if res == nil or #res ~= 1 then
        return {}
    end
    local portalMembers = toTable(res[1]['Editor'])
    for _, member in pairs( toTable(res[1]['Main editor']) ) do
       table.insert( portalMembers, member )
    end
    if #portalMembers == 0 then
       return {}
    end
    local nameRes = mw.smw.ask{
        '[[' .. table.concat( portalMembers, '||' ) .. ']]',
        '?#-', -- do not link page name
        '?Name',
        limit = 1000
    }
    local memberMapping = {}
    if nameRes then
        for _, member in pairs( nameRes ) do
            if member[1] and member['Name'] then
                memberMapping[member[1]] = member['Name']
            end
        end
    end
    -- Some people might not have a userpage
    if portalMembers then
        for _, member in pairs( portalMembers ) do
            if not memberMapping[member] then
                memberMapping[member] = string.gsub( member, '^User:', '' )
            end
        end
    end
    return memberMapping
end

local userLookupCache = {}
local function userLookup( userpage )
    if userLookupCache[userpage] then
        return userLookupCache[userpage]
    end

    local res = mw.smw.ask{
        '[[' .. userpage .. ']]',
        '?Name#-',
        limit = 1
    }

    if res and #res == 1 and res[1]['Name'] then
        userLookupCache[userpage] = res[1]['Name']
    else
       userLookupCache[userpage] = string.gsub( userpage, '^User:', '' )
    end
    return userLookupCache[userpage]
end

-- Give the pages object that includes what categories a page is in
-- get only the categories that are not the catName and are a subcategory of Articles
local function getCategories( catNameToExclude, pages )
   local cats = {}
   local catsAssoc = {}
   for _, page in pairs( pages ) do
       for _, cat in pairs( toTable( page['Category'] ) ) do
           -- Too many categories can cause a query error here. Ignore some common ones we know we don't need
           if not catsAssoc[cat] and cat ~= ( 'Category:' .. catNameToExclude ) and cat ~= 'Category:Articles' and cat ~= 'Category:Pages with ignored display title' then
               catsAssoc[cat] = true
               table.insert( cats, cat )
           end
       end
   end

   res = mw.smw.ask{
       '[[:' .. table.concat( cats, '||:' ) .. ']][[Subcategory of::Category:Articles]]',
       '?#-',
       limit = 2000
   }

   local catList = {}
   for _, item in pairs( toTable(res) ) do
       catList[item[1]] = true
   end
   return catList
end

function p.portal(frame)
   local pargs = frame:getParent().args
   local status = pargs['Article status']
   local catName = pargs['Category'] or mw.title.getCurrentTitle().text
   local curTime = mw.getContentLanguage():formatDate( 'd F Y', nil, true )
   local catEntry = '[[Category:' .. catName .. ']] '
   local assignedCriteria = ''
   if pargs['Assigned editor'] then
       assignedCriteria = '[[Assigned editor::User:' .. pargs['Assigned editor'] .. ']]'
   end
   local fields
   if status then
       if status == 'Up to Date' then
           fields = catEntry
           fields = fields .. '[[Review expiration date::≥' .. curTime ..']] [[Article status::Up to Date]]' .. assignedCriteria
           fields = fields .. 'OR ' .. catEntry .. ' [[Has review::No]] [[Article status::Up to Date]]' .. assignedCriteria
       else
           fields = catEntry
           fields = fields .. '[[Review expiration date::<' .. curTime ..']]' .. assignedCriteria
           fields = fields .. 'OR ' .. catEntry .. '[[Review expiration date::≥' .. curTime .. ']][[Article status::Update Pending]]' .. assignedCriteria
           fields = fields .. 'OR ' .. catEntry .. '[[Has review::No]] [[Article status::Update Pending]]' .. assignedCriteria
       end
   else -- no status
       fields = catEntry .. assignedCriteria
   end
   local pages = mw.smw.ask{
       fields,
       '?#-', -- Page name no link
       '?Article status',
       '?Date reviewed#-F[F j, Y]',
       '?Assigned editor#-',
       '?Category#-',
       '?Review expiration date',
       limit = 1000
   }

   if pages == nil or #pages == 0 then
      return 'No results' -- FIXME, what is proper return here.
   end

   local portalMemberMapping = getPortalMembers( catName )
   local categories = getCategories( catName, pages )

   local out = [==[ <table class="smwtable-clean compact sortable display striped">
<tr>
<th class="headerSort" tabindex="0" role="columnheader button" title="Sort ascending">Page name</th>
<th class="Article-status headerSort" tabindex="0" role="columnheader button" title="Sort ascending">Article status</th>
<th class="Date-reviewed headerSort" tabindex="0" role="columnheader button" title="Sort ascending">Date reviewed</th>
<th class="Assigned-editor headerSort" tabindex="0" role="columnheader button" title="Sort ascending">Assigned editor (portal member)</th>
<th class="Assigned-editor-other headerSort" tabindex="0" role="columnheader button" title="Sort ascending">Assigned editor (other)</th>
<th class="Other-assigned-sections headerSort" tabindex="0" role="columnheader button" title="Sort ascending">Other assigned sections</th>
</tr>
]==]

   return out .. p.doBody( catName, pages, portalMemberMapping, categories ) .. '</table>'
end

local function isExpired( date )
    local lang = mw.language.getContentLanguage()
    -- xNU = unix epoch, no translate numerals.
    -- local time (Third argument true) doesn't apply to U format, so we do in two layers.
    local now = tonumber( lang:formatDate( 'xNU', lang:formatDate( "F j, Y", "today", true ) ) )
    local givenDate = tonumber( lang:formatDate( 'xNU', date ) )
    -- everything is a float in lua, so sometimes 0 > 0
    return (now-givenDate)>0.1
end

function p.doBody( catName, pages, memberMapping, categories )
    local out = ''
    for _, page in ipairs( pages ) do
        out = out .. '<tr><td>[[' .. page[1] .. ']]</td>'
        -- The Article status property is not reliable and if the review is expired it still can show Up to Date if originally set by editor
        if isExpired( page['Review expiration date'] or 'Jan 1 2100' ) then
            out = out .. '<td class="bg-warning">Update pending</td>'
        else
            local articleStatus = page['Article status'] or ''
            out = out .. '<td class="bg-' .. p.getClass( articleStatus ) .. '">' .. articleStatus .. '</td>'
        end
        out = out .. '<td>' .. ( page['Date reviewed'] or '' ) .. '</td>'

        local memberEditors = {}
        local nonmemberEditors = {}
        for _, member in ipairs( toTable( page['Assigned editor'] ) ) do
            if memberMapping[member] then
                table.insert( memberEditors, '[[' .. member .. '|' .. memberMapping[member] .. ']]' )
            else -- The assigned editor is not a member of the portal
                table.insert( nonmemberEditors, '[[' .. member .. '|' .. userLookup( member ) .. ']]' )
            end
        end
        out = out .. '<td>' .. table.concat( memberEditors, ', ' ) .. '</td>'
        out = out .. '<td>' .. table.concat( nonmemberEditors, ', ' ) .. '</td>'
        out = out .. '<td>'
        for _, cat in ipairs( toTable( page['Category'] ) ) do
            -- For some reason, MW * syntax creates <ul> incorrectly in tables.
            local list = ''
            if categories[cat] then
                local pName = mw.title.new( cat ).text
                list = list .. '\n<li>[[Portal:' .. pName .. '|' .. pName .. ']]</li>'
            end
            if list ~= '' then
                out = out .. '<ul>' .. list .. '</ul>'
            end
        end
        out = out .. '</td></tr>'
    end
    return out
end

return p
The Academy uses cookies to analyze performance and provide relevant personalized content to users of our website.