Module:Information



From Wikimedia Commons, the free media repository



Jump to navigation  Jump to search  

Lua

CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules

Module providing back-end for {{Information}} template.

Examples

Code Render
Test simple case:

{{#invoke:Information|information
|description    = description
|date           = 2024-07-14
|source         = {{own}}
|author         = author
|permission     = permission     
|other versions = <gallery>File:Image-x-generic - black.svg</gallery>
}}
Description description
Date
Source own
Author author
Permission
(Reusing this file)
permission
Other versions
Test case with missing source, author and description:

{{#invoke:Information|information
|description    = 
|date           = 2024-07-14   
|source         = 
|author         = 
}}
Description
Date
Source
Author

Code

--[[  
  __  __           _       _        ___        __                            _   _             
 |  \/  | ___   __| |_   _| | ___ _|_ _|_ __  / _| ___  _ __ _ __ ___   __ _| |_(_) ___  _ __  
 | |\/| |/ _ \ / _` | | | | |/ _ (_)| || '_ \| |_ / _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \ 
 | |  | | (_) | (_| | |_| | |  __/_ | || | | |  _| (_) | |  | | | | | | (_| | |_| | (_) | | | |
 |_|  |_|\___/ \__,_|\__,_|_|\___(_)___|_| |_|_|  \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
                                                                                               
This module is intended to be the engine behind "Template:Information".

Please do not modify this code without applying the changes first at
"Module:Information/sandbox" and testing at "Module:Information/testcases".

Authors and maintainers:
* User:Jarekt - original version 
]]
-- =======================================
-- === Dependencies ======================
-- =======================================
require('strict') -- used for debugging purposes as it detects cases of unintended global variables
local ISOdate = require('Module:ISOdate')._ISOdate -- date localization
local core    = require('Module:Core')

-- ==================================================
-- === Internal functions ===========================
-- ==================================================

local function langWrapper(text, textLang) 
-- code equivalent to https://commons.wikimedia.org/wiki/Template:Description
 local language = mw.language.new( textLang )
 local dir      = language:getDir()  
 local LangName = language:ucfirst(mw.language.fetchLanguageName( textLang, textLang))
 local str = mw.ustring.format('<span class="language %s"><b>%s:</b></span>', textLang, LangName)
    return mw.ustring.format('<div class="description mw-content-%s" dir="%s" lang="%s">%s %s</div>', dir, dir, textLang, str, text)
end

-------------------------------------------------------------------------------
local function getBareLabel(id, userLang) 
-- code equivalent to require("Module:Wikidata label")._getLabel with Wikidata=- option
 local label, link
 -- build language fallback list
 local langList = mw.language.getFallbacksFor(userLang)
 table.insert(langList, 1, userLang)
 for _, lang in ipairs(langList) do  -- loop over language fallback list looking for label in the specific language
  label = mw.wikibase.getLabelByLang(id, lang)
  if label then break end                    -- label found and we are done
 end 
 return label or id
end

-------------------------------------------------------------------------------
local function message(name, lang)
 return mw.message.new( 'wm-license-information-'..name ):inLanguage(lang):plain()
end

-- ====================================================================
-- === This function is just responsible for producing HTML of the  ===
-- === template. At this stage all the fields are already filed     ===
-- ====================================================================
local function Build_html(args)
 local lang = args.lang -- user's language
 local dir  = mw.language.new( lang ):getDir()    -- get text direction
 local desTag = mw.ustring.format('<span class="summary fn" style="display:none">%s</span>', args.pagename)
 local prmTag = mw.ustring.format("<br /><small>([[%s|%s]])</small>", message('permission-reusing-link', lang), 
         message('permission-reusing-text', lang))

 -- field specific preferences
 local params = {
  {field='other_fields_0'},
  {field='description'    , id='fileinfotpl_desc', tag2=desTag, td='class="description"'},
  {field='other_fields_1'},
  {field='date'           , id='fileinfotpl_date', td=mw.ustring.format('lang="%s"', lang)},
  {field='source'         , id='fileinfotpl_src'}, 
  {field='author'         , id='fileinfotpl_aut'},
  {field='permission'     , id='fileinfotpl_perm', tag2=prmTag },
  {field='other_versions' , id='fileinfotpl_ver',  tag='other-versions'}, 
  {field='other_fields'},
 }
 local results = {}
 for _, param in ipairs(params) do
  local field, tag, cell1, cell2, id
  field = args[param.field]
  if param.id then -- skip "other fields" parameter
   if type(field) == 'string' then  -- add "id" to first <td> cell only if the field is present
    id = mw.ustring.format('id="%s" ', param.id)
   elseif type(field) == 'table' then
    -- the field was initially not present, it contains only our
    -- warning text; flatten it so that mw.ustring.format() gets a string
    field = field.missing
   end
   if field or (args.demo and param.tag) then  -- skip the row if still no field
    tag   = message(param.tag or param.field, lang) .. (param.tag2 or '')
    cell1 = mw.ustring.format('<td %sclass="fileinfo-paramfield" lang="%s">%s</td>\n', id or '', lang, tag)
    cell2 = mw.ustring.format('<td %s>\n%s</td>', param.td or '', field or '')
    field = mw.ustring.format('<tr>\n%s%s\n</tr>\n\n', cell1, cell2)
   end
  end
  table.insert(results, field)
 end
 
 -- To save space in the templatelinks table, skip templatestyles in the File namespace on Commons;
 -- files get a copy of these styles via [[MediaWiki:Filepage.css]] instead.
 -- See [[Module talk:Information/styles.css]].
 local templatestyles = ''
 if args.namespace ~= 6 or not(mw.site.server:match('//commons.wikimedia.org$')) then
  templatestyles = mw.getCurrentFrame():extensionTag{
   name = 'templatestyles', args = { src = 'Module:Information/styles.css' }
  }
 end

 -- add table and outer layers
 local style = mw.ustring.format('class="fileinfotpl-type-information vevent '..
  'mw-content-%s" style="direction: %s;"', dir, dir)
 results = mw.ustring.format('<table %s>\n\n%s\n</table>\n', style, table.concat(results))
 results = mw.ustring.format('<div class="hproduct commons-file-information-table">\n%s\n%s\n</div>', templatestyles, results)
 return results
end

-- ==================================================
-- === External functions ===========================
-- ==================================================
local p = {}

-- ===========================================================================
-- === Version of the function to be called from other LUA codes
-- ===========================================================================

-------------------------------------------------------------------------------
-- _information function creates a wikicode for {{Information}} template based on
-- passed arguments (through "args") and data extracted from SDC. Allowed fields of 
-- "args" are : 'description', 'date', 'permission', 'author', 'other_versions',  
-- 'source','other_fields', 'other_fields_0', 'other_fields_1', 'demo' and 'lang'
-------------------------------------------------------------------------------
-- Dependencies: p._SDC_Description, p._SDC_Source, p._SDC_Author, p._SDC_Date, 
--    Build_html, Module:ISOdate (_date)
-------------------------------------------------------------------------------
function p._information(args)

 local cats = ''
 
 -- ============================================================================================
 -- === add [[Category:Pages using Information template with incorrect parameter]] if needed ===
 -- ============================================================================================
 local page = mw.title.getCurrentTitle()
 local lang = args.lang
 local namespace = page.namespace   -- get page namespace
 if namespace==6 or namespace==10 then
  local allowedFields = {'description', 'date', 'permission', 'author', 'other_versions',  
    'source','other_fields', 'other_fields_0', 'other_fields_1', 'demo', 'lang', 'strict','sdc'}
  local set, badField = {}, {}
  for _, field in ipairs(allowedFields) do set[field] = true end
  for field, _ in pairs( args ) do 
   if not set[field] then
    table.insert(badField, field)
   end
  end
  if #badField>0 then
   cats = mw.ustring.format('\n;<span style="color:var(--color-error,red)">Error in [[Template:Information|{{Information}}'..
    ' template]]: unknown parameter "%s".</span>',  table.concat(badField,'", "'))
   cats = cats .. '\n[[Category:Pages using Information template with incorrect parameter]]'
  end
 end
 if args.date then
  -- apply ISODate to function to date string to convert date in ISO format to translated date string
  args.date = ISOdate(args.date, lang, '', 'dtstart', '100-999')      
 end 
 args.pagename = page.text
 args.namespace = namespace

 -- ====================================================
 -- === harvest structured data                      === 
 -- ====================================================
 local entity = mw.wikibase.getEntity()
 if namespace==6 then 
  entity = mw.wikibase.getEntity()
 elseif args.sdc then
  entity = mw.wikibase.getEntity(args.sdc)
 end
 
 if (namespace==6 or args.sdc) and entity then -- file namespace
  -- call SDC functions only when needed
  local icon = true
  -- local field is missing -> get it from SDC
  args.description = args.description or p._SDC_Description(entity, lang, icon)  
  args.source      = args.source      or p._SDC_Source(entity, lang, icon)
  args.author      = args.author      or p._SDC_Author(entity, lang, icon) 
  args.date        = args.date        or p._SDC_Date(entity, lang, icon)
 end
 
 -- ====================================================
 -- === add tracking templates and categories        === 
 -- ====================================================
 -- add the template tag (all official infoboxes transclude {{Infobox template tag}} so files without that tag do not have an infobox
 mw.getCurrentFrame():expandTemplate{ title = 'Infobox template tag' } 

 -- files are required to have at least the 3 fields below
 if args.strict~=false then
  local reqFields = {description='Media lacking a description', author='Media lacking author information', source='Images without source'}
  for field, errCat in pairs(reqFields) do 
   if args[field] and mw.ustring.match(args[field],"^[%s%p]+$") then 
    args[field]=nil; 
   end -- ignore punctuation only fields
   if not args[field] then
    -- code equivalent to Template:Source missing, Template:Author missing, Template:Description missing
    local tag1 = 'class="boilerplate metadata" id="cleanup" style="text-align: center; color: inherit;background: var(--background-color-warning-subtle,#ffe); '..
     'margin: .75em 15%; padding: .5em; border: 1px solid var(--border-color-content-removed,#e3e3b0);'
    local tag2 = message(field..'-missing', lang)
    local tag3 = message(field..'-missing-request', lang)
    local dir  = mw.language.new( lang ):getDir()    -- get text direction
    args[field] = {missing =  mw.ustring.format('<div %s direction: %s;" lang="%s">%s\n%s\n</div>', tag1, dir, lang, tag2, tag3)}
    cats = cats .. '\n[[Category:'.. errCat ..']]'
   end
  end
 end
 if namespace~=6  then 
  cats = '' -- categories are added only to files
 end

 return Build_html(args) .. cats
end

-------------------------------------------------------------------------------
-- interface for other Lua codes to 5 functions for extracting description, source,
-- author, date and location information from SDC. 
-- INPUTS:
--  - "entity" - structure created by mw.wikibase.getEntity function
--  - "lang"  - users language
-------------------------------------------------------------------------------
-- Dependencies: langWrapper
-------------------------------------------------------------------------------
function p._SDC_Description(entity, lang, icon)
 -- create {{en|1=...}} template with SDC's caption
 local description, _
 if entity and entity.labels then -- get label in users language or one of that language fallback list
  local label = core.langSwitch(entity.labels, lang) 
  local labels, D = {}, {}
  if label then -- show either matching language
   labels[lang] = label
  else -- or if missing then show all
   labels = entity.labels
  end
  for _, label in pairs(labels) do -- add {{en|1=....}} like wrapper
   if icon and #D==0 then -- add editAtSDC icon to the first description
    label.value = label.value .. core.editAtSDC('ooui-php-4', lang)
   end
   table.insert(D, langWrapper(label.value, label.language, lang))
  end 
  description = table.concat(D, '\n') 
 end
 return description
end

-------------------------------------------------------------------------------
-- Dependencies: Module:Wikidata_date "_date" function, Module:ISOdate "_ISOdate" function
-------------------------------------------------------------------------------
function p._SDC_Date(entity, lang, icon)
 -- get creation date from  P571 (inception)
 -- Code can handle YYYY-MM-DD, YYYY-MM, and YYYY dates without any additional resources
 -- But can load [[Module:Wikidata date]] if needed
 local Date
 if entity and entity.claims and entity.claims.P571 then
  local snak = entity.claims.P571[1].mainsnak
  if (snak.snaktype == "value") then 
   local v = snak.datavalue.value
   if v and (v.calendarmodel=='http://www.wikidata.org/entity/Q1985727') and (mw.ustring.sub(v.time,1,1)=='+') then 
    if v.precision >= 11 then            -- day
     Date = mw.ustring.sub(v.time,2,11)   -- date in YYYY-MM-DD format
    elseif v.precision == 10 then        -- month
     Date = mw.ustring.sub(v.time,2,8)    -- date in YYYY-MM format
    elseif v.precision == 9 then         -- year
     Date = mw.ustring.sub(v.time,2,5)    -- date in YYYY format
    end
    if Date then -- translate
     Date = ISOdate(Date, lang, '', 'dtstart', '100-999')
    end
   end
  end
  if entity.claims.P571[1].qualifiers then                  -- non-trivial case: call heavy cavalery
   local getDate = require("Module:Wikidata date")._date -- lazy loading: load only if needed
   local result  = getDate(entity, 'P571', lang)         -- display the date in user's language
   Date = result.str
  end
 end
 if icon and Date then
  Date = Date .. core.editAtSDC('P571', lang)
 end
 return Date
end

-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
function p._SDC_Source(entity, lang, icon)
 -- get source from P7482 (source of file)
 -- Code can handle {{Own}} template and URLs 
 local source, label
 if entity and entity.claims and entity.claims.P7482 then
  for _,statement in ipairs(entity.claims.P7482) do
   if statement.mainsnak.datavalue then
    -- get URL is source  is " file available on the internet (Q74228490) " 
    if statement.mainsnak.datavalue.value.id=='Q74228490' and statement.qualifiers and statement.qualifiers.P973 then
     source = statement.qualifiers.P973[1].datavalue.value -- described at URL
     if statement.qualifiers.P137 then -- "operator"
      local id = statement.qualifiers.P137[1].datavalue.value.id
      label = getBareLabel(id, lang)
      source  = '[' .. source ..' ' .. label ..']'
     end
    end
    -- add {{tl|own}} if source is "original creation by uploader (Q66458942)" 
    if statement.mainsnak.datavalue.value.id=='Q66458942' then
     label = mw.message.new( 'Wm-license-own-work'):inLanguage(lang):plain()
     source = mw.ustring.format('<span class="int-own-work" lang="%s">%s</span>',lang, label)
    end
    -- add {{tl|Own work by the original uploader}} if source is " Own work by the original uploader (Q87402110)" 
    if statement.mainsnak.datavalue.value.id=='Q87402110' then
     label  = getBareLabel('Q87402110', lang)
     source = mw.ustring.format('<span class="int-own-work" lang="%s">%s</span>',lang, label)
    end
    if source then
     break
    end
   end
  end
 end
 if icon and source then
  source = source .. core.editAtSDC('P7482', lang)
 end
 return source
end

-------------------------------------------------------------------------------
-- Dependencies: Module:Core "getLabel" function
-------------------------------------------------------------------------------
function p._SDC_Author(entity, lang, icon)
 -- get author from P170 (creator)
 -- Code can handle usuall cases of "[[User:Example|Example]]" as well as users with Wikidata Item IDs
 local author
 if entity and entity.claims and entity.claims.P170 then
  local creators = {}
  for _,statement in ipairs(entity.claims.P170) do
   if statement.mainsnak.snaktype == "value" then  -- Creator has item ID    
    local val = statement.mainsnak.datavalue.value.id
    table.insert(creators, core.getLabel(val, lang))
   elseif statement.mainsnak.snaktype == "somevalue" then -- Creator defined by username
    if statement.qualifiers then -- author name string (P2093) 
        local qual = {}
     local properties = {P2093='authorStr', P4174='username', P3831='role', P2699='url'}
     for prop, field in pairs( properties ) do
      if statement.qualifiers[prop] then
       qual[field] = statement.qualifiers[prop][1].datavalue.value
      end
     end
     local role = ''
     if qual.role and entity.claims.P170[2] then -- add role only is multiple creators
      role = '&nbsp;(' .. core.getLabel(qual.role.id, lang) .. ')'
     end
     if qual.username and qual.authorStr then         --    author name string (P2093) & Wikimedia username (P4174) 
      table.insert(creators, '[[User:'..qual.username..'|'..qual.authorStr..']]'..role)
     elseif qual.username and not qual.authorStr then -- no author name string (P2093) & Wikimedia username (P4174) 
      table.insert(creators, '[[User:'..qual.username..'|'..qual.username..']]'..role)
     elseif qual.url and qual.authorStr then          --    author name string (P2093) & URL (P2699) 
      table.insert(creators, '['..qual.url..' '..qual.authorStr..']'..role)
     elseif qual.url and not qual.authorStr then      -- no author name string (P2093) & URL (P2699) 
      table.insert(creators, qual.url..role)
     elseif  qual.authorStr then                      --    author name string (P2093) 
      table.insert(creators, qual.authorStr..role)
     end
    end
   end
  end -- end for
  author = table.concat(creators, ', ')
 end
 if icon and author then
  author = author .. core.editAtSDC('P170', lang)
 end
 return author
end

-------------------------------------------------------------------------------
-- Dependencies: Module:Code "getLabel" function
-------------------------------------------------------------------------------
function p._SDC_Location(entity, lang, icon)
 -- get location  P276 (location)
 local location, prop
 if entity and entity.claims and entity.claims.P1071 then
  local snak = entity.claims.P1071[1].mainsnak
  if (snak.snaktype == "value") then 
   location = core.getLabel(snak.datavalue.value.id, lang)
   prop = 'P1071'
  end
 end
 if entity and entity.claims and entity.claims.P276 then
  local snak = entity.claims.P276[1].mainsnak
  if (snak.snaktype == "value") then 
   location = core.getLabel(snak.datavalue.value.id, lang)
   prop = 'P276'
  end
 end
 if icon and location then
  location = location .. core.editAtSDC(prop, lang)
 end
 return location
end

-- ===========================================================================
-- === Version of the functions to be called from template namespace
-- ===========================================================================

-------------------------------------------------------------------------------
-- information function creates a wikicode for {{Information}} template based on
-- passed arguments (through "frame") and data extracted from SDC. Allowed template
-- arguments are : 'description', 'date', 'permission', 'author', 'other_versions',  
-- 'source','other_fields', 'other_fields_0', 'other_fields_1', 'demo', 'sdc' and 'lang'. 
-- All inputs do not depend on capitalization and all "_" can be replaced with spaces.
-------------------------------------------------------------------------------
-- Dependencies: p._information
-------------------------------------------------------------------------------
function p.information(frame)
 local args = core.getArgs(frame)
 args.strict = true
 return p._information(args) 
end

-------------------------------------------------------------------------------
-- interface for templates to 5 functions for extracting description, source,
-- author, date and location information from SDC. 
-- INPUTS (templaate parameters):
--  * "mid"   - pageID defining a file. Optional, defaulting to the current file.
--  * "lang"  - users language. Optional defaulting to the language of the user
--  * "icon"  - add "Edit this at Wikidata" icon? boolean ( 'true'/'false', 'yes'/'no', 1/0
-------------------------------------------------------------------------------
-- Dependencies: getEntity
-------------------------------------------------------------------------------
local function parseFrame(frame)
 local args = core.getArgs(frame)
 local entity = mw.wikibase.getEntity( args.mid )
 local icon   = core.yesno(args.icon, true)
 return {entity, args.lang, icon}
end

function p.SDC_Description(frame)
 return p._SDC_Description(unpack(parseFrame(frame)))
end

function p.SDC_Source(frame)
 return p._SDC_Source(unpack(parseFrame(frame)))
end

function p.SDC_Author(frame)
 return p._SDC_Author(unpack(parseFrame(frame)))
end

function p.SDC_Date(frame)
 return p._SDC_Date(unpack(parseFrame(frame)))
end

function p.SDC_Location(frame)
 return p._SDC_Location(unpack(parseFrame(frame)))
end

return p

-------------------------------------------------------------------------------
-- List of exported functions
-------------------------------------------------------------------------------
-- information
-- SDC_Description
-- SDC_Source
-- SDC_Author
-- SDC_Date
-- SDC_Location

Retrieved from "https://commons.wikimedia.org/w/index.php?title=Module:Information&oldid=897080218"

Categories: 
Modules for general use
Modules subject to page protection
Heavily used modules
Templates using TemplateStyles
 


Navigation menu


Personal tools  




English
Not logged in
Talk
Contributions
Create account
Log in
 


Namespaces  




Module
Discussion