Modul:Information/sandbox
aus Wikipedia, der freien Enzyklopädie
Die Dokumentation für dieses Modul kann unter Modul:Information/sandbox/Doku erstellt werden
--[[
__ __ _ _ ___ __ _ _
| \/ | ___ __| |_ _| | ___ _|_ _|_ __ / _| ___ _ __ _ __ ___ __ _| |_(_) ___ _ __
| |\/| |/ _ \ / _` | | | | |/ _ (_)| || '_ \| |_ / _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
| | | | (_) | (_| | |_| | | __/_ | || | | | _| (_) | | | | | | | | (_| | |_| | (_) | | | |
|_| |_|\___/ \__,_|\__,_|_|\___(_)___|_| |_|_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
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')
-------------------------------------------------------------------------------
local function getDate(entity, lang)
local get_date = require("Module:Wikidata date")._date -- lazy loading: load only if needed
local result = get_date(entity, 'P571', lang) -- display the date in user's language
return result.str
end
-------------------------------------------------------------------------------
local function getCite()
return require("Module:Cite Wikidata") -- lazy loading: load only if needed
end
-- ==================================================
-- === Internal functions ===========================
-- ==================================================
-------------------------------------------------------------------------------
local function getProperty(entity, prop, lang, icon)
local val = (core.parseStatements(entity:getBestStatements( prop ), lang) or {nil})[1]
if icon and val then
val = val .. core.editAtSDC(prop, lang)
end
return val
end
-------------------------------------------------------------------------------
local function getAllItemProperties(item, prop)
return core.parseStatements(mw.wikibase.getBestStatements( item, prop ), nil)
end
-------------------------------------------------------------------------------
local function getAllProperties(entity, prop)
return core.parseStatements(entity:getAllStatements( prop ), nil)
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 get_citations(source_page, lang)
local Cite = getCite() -- lazy loading: load only if needed
local published_in = {}
local source
for item, page in pairs(source_page) do
if Cite.getCitationType(nil, item) then
-- load full entity and use it to create citation
local pub = Cite._citeWikidata(item, lang, page)
if pub then
table.insert(published_in, pub)
end
end
end
if #published_in>0 then
local colon = mw.message.new( "colon" ):inLanguage(lang ):plain()
table.insert(published_in, 1, getBareLabel('P1433', lang)..colon) -- i18n for "published in" string
source = table.concat(published_in, '\n* ') -- list all the publications in a list
end
return source
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='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 style="vertical-align: top">\n%s%s\n</tr>\n\n', cell1, cell2)
end
end
table.insert(results, field)
end
-- add table and outer layers
local style = mw.ustring.format('class="fileinfotpl-type-information toccolours vevent '..
'mw-content-%s" style="width: 100%%; direction: %s;" cellpadding="4"', 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</div>', 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_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()
args.pagename = page.text
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_1', 'demo', 'lang', 'strict'}
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: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
-- ====================================================
-- === alter wikitext inputs ===
-- ====================================================
args.date = p._Wikitext_Date (args.date, lang)
args.source = p._Wikitext_Source(args.source, lang)
-- ====================================================
-- === harvest structured data ===
-- ====================================================
local entity = mw.wikibase.getEntity()
if namespace==6 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; background: #ffe; '..
'margin: .75em 15%; padding: .5em; border: 1px solid #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
-------------------------------------------------------------------------------
-- Dependencies: Module:ISOdate "_ISOdate" function
-------------------------------------------------------------------------------
function p._Wikitext_Date(text, lang)
if text then
-- apply ISODate to function to date string to convert date in ISO format to translated date string
return ISOdate(text, lang, '', 'dtstart', '100-999')
end
return nil
end
-------------------------------------------------------------------------------
-- Dependencies: Module:ISOdate "_ISOdate" function
-------------------------------------------------------------------------------
function p._Wikitext_Source(text, lang)
if text and string.match(text, "^ *Q%d+[Q%d%/ ]+$") then
-- if source has wikitada item or array of wikidata items separated by "/" then interpret it as
-- source citation(s)
local source_page, items = {}, {}
for _, source in ipairs(mw.text.split(text, '/')) do
source = mw.text.trim(source)
if source and string.match(source, "^Q%d+$")then
source_page[source] = 0
else
return text
end
end -- return table.concat(items, '; ')
return get_citations(source_page, lang)
end
return text
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
local args = {user_lang = lang}
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, core.langWrapper(label.language, label.value, args))
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_str
local statement = entity:getBestStatements( 'P571' )[1]
if statement then
if (statement.mainsnak.snaktype == "value") and not statement.qualifiers then
date_str = ISOdate(core.parseSnak(statement.mainsnak, nil), lang) -- first try simple case that should cover 99% if files
end
if not date_str then -- non-trivial case: call heavy cavalery
date_str = getDate(entity, lang) -- This call loads a lot of code from [[Module:Wikidata date]]
end
end
if icon and date_str then
date_str = date_str .. core.editAtSDC('P571', lang)
end
return date_str
end
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
function p._SDC_Source(entity, lang, icon)
local source, label
-- get source from P7482 (source of file)
-- Code can handle {{Own}}a and {{Own work by the original uploader}} templates and URLs
for _,statement in ipairs(entity:getBestStatements( 'P7482' )) do
local src_item = statement.mainsnak.datavalue.value.id
-- get URL is source is " file available on the internet (Q74228490) "
if src_item=='Q74228490' then
if statement.qualifiers and statement.qualifiers.P973 then -- described at URL
source = statement.qualifiers.P973[1].datavalue.value
if statement.qualifiers and statement.qualifiers.P137 then -- "operator"
local id = statement.qualifiers.P137[1].datavalue.value.id
label = getBareLabel(id, lang)
source = '[' .. source ..' ' .. label ..']'
end
else
-- is there a list of publications at P1433?
local source_page = {}
if entity.claims and entity.claims.P1433 then
for _, statement in pairs( entity:getBestStatements( 'P1433' )) do
local source_item = core.parseSnak(statement.mainsnak, nil)
local page = ''
if statement.qualifiers and statement.qualifiers.P304 then -- page(s)
page = statement.qualifiers.P304[1].datavalue.value
end
source_page[source_item] = page
end
end
source = get_citations(source_page, lang)
if not source then
source = getBareLabel('Q74228490', lang) -- i18n for "file available on the internet" string
end
end
elseif src_item=='Q66458942' then
-- add {{own}} if source is "original creation by uploader (Q66458942)"
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)
elseif src_item=='Q87402110' then
-- add {{Own work by the original uploader}} if source is " Own work by the original uploader (Q87402110)"
label = getBareLabel('Q87402110', lang)
label = mw.language.new(lang):ucfirst(label)
source = mw.ustring.format('<span class="int-own-work" lang="%s">%s</span>',lang, label)
else
local page = ''
if statement.qualifiers and statement.qualifiers.P304 then -- page(s)
page = statement.qualifiers.P304[1].datavalue.value
end
source = get_citations({[src_item]=page}, lang)
end
if source then
break
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
local creators = {}
for _,statement in ipairs(entity:getBestStatements( '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 if multiple creators
role = ' (' .. 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 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)
local location
location = getProperty(entity, 'P276', lang, icon) -- get location P276 (location)
if location == nil then
location = getProperty(entity, 'P1071', lang, icon)
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_1', 'demo' 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
function p.Wikitext_Source(frame)
local args = core.getArgs(frame)
return p._Wikitext_Source(args.source, args.lang) or ''
end
function p.Wikitext_Date(frame)
local args = core.getArgs(frame)
return p._Wikitext_Date(args.date, args.lang) or ''
end
return p
-------------------------------------------------------------------------------
-- List of exported functions
-------------------------------------------------------------------------------
-- information
-- SDC_Description
-- SDC_Source
-- SDC_Author
-- SDC_Date
-- SDC_Location