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