मॉड्यूल:Artwork
"इस मॉड्यूल हेतु प्रलेख मॉड्यूल:Artwork/doc पर बनाया जा सकता है"
--[[
__ __ _ _ _ _ _
| \/ | ___ __| |_ _| | ___ _ / \ _ __| |___ _____ _ __| | __
| |\/| |/ _ \ / _` | | | | |/ _ (_) / _ \ | '__| __\ \ /\ / / _ \| '__| |/ /
| | | | (_) | (_| | |_| | | __/_ / ___ \| | | |_ \ V V / (_) | | | <
|_| |_|\___/ \__,_|\__,_|_|\___(_)_/ \_\_| \__| \_/\_/ \___/|_| |_|\_\
This module is intended to be the engine behind "Template:Artwork", "Template:Art photo",
"Template:Photograph" and "Template:Book".
Please do not modify this code without applying the changes first at
"Module:Artwork/sandbox" and testing at "Template:Artwork/testcases".
Authors and maintainers:
* User:Jarekt - original version
]]
require('Module:No globals') -- used for debugging purposes as it detects cases of unintended global variables
local getLabel = require("Module:Wikidata label")._getLabel -- used for creation of name based on wikidata
local getSitelinks = require("Module:Wikidata label")._sitelinks --
local getDate = require("Module:Wikidata date")._date -- used for processing of date properties
local authorityControl = require("Module:Authority control")._authorityControl -- used for formatting of Authority control row
local City = require("Module:City") -- used to add wikidata based links to names of places
local labels = require("Module:I18n/artwork") -- internationalization of labels
local ISOdate = require('Module:ISOdate')
local Size = require('Module:Size')._size -- Lua code behing {{Size}} template
local TitleFromWD = require('Module:Title').wikidata_title -- Lua code behing {{Title}} template
local Art = require('Module:Wikidata art') --
local alterName = require("Module:Name")._name
local core = require("Module:Core")
local bit32 = require("bit32")
-- ==================================================
-- === Internal functions ===========================
-- ==================================================
-------------------------------------------------------------------------------
local function isodate2timestamp(dateStr)
-- convert isodate to timestamp used by quick statements
local tStamp = nil
if string.match(dateStr,"^[0-1]%d%d%d$") then -- if YYYY format
tStamp = '+' .. dateStr .. '-00-00T00:00:00Z/9'
elseif string.match(dateStr,"^[0-1]%d%d%d%-[0-1]%d$") then -- if YYYY-MM format
tStamp = '+' .. dateStr .. '-00T00:00:00Z/10'
elseif string.match(dateStr,"^[0-1]%d%d%d%-[0-1]%d%-[0-3]%d$") then -- if YYYY-MM-DD format
tStamp = '+' .. dateStr .. 'T00:00:00Z/11'
end
return tStamp
end
local function empty2nil(str)
if str=='' then
return nil
else
return str
end
end
local function nowiki(str) -- remove all the links
if not str then
return str
end
str = mw.ustring.gsub(str, '%<div style="display: none;"%>[^%<]+%</div%>', '')
str = mw.ustring.gsub(str, '%<abbr %</abbr%>', '')
str = mw.ustring.gsub(str, "<[^>]*>", "") -- remove all html tags from str
str = mw.ustring.gsub(str, "'''", "") -- remove bold
str = mw.ustring.gsub(str, "''", "") -- remove italics
str = mw.ustring.gsub(str, "%[%[[Ff]ile:[^%]]+%]%]", "") -- remove file icons
str = mw.ustring.gsub(str, "%[%[[^|]*|", "") -- remove piped links, like "[[:en:test|"
str = mw.ustring.gsub(str, "%[[^ ]+ ", "") -- remove URL links, like "[https://www.wikidata.org/wiki/Q2706250 "
str = mw.ustring.gsub(str, "%[%[", "" ) -- remove piped links, like "[["
str = mw.ustring.gsub(str, "%]", "" ) -- remove piped links, like "]" or "]]"
return str
end
local function nowiki_title(str) -- remove all the links and url encode some characters
if not str then
return str
end
str = mw.ustring.gsub(str, "%)", "%%29" ) -- encode parenthesis
str = mw.ustring.gsub(str, "%(", "%%28" ) -- encode parenthesis
str = mw.ustring.gsub(str, " ", " " ) -- multi-space to a single one
str = mw.ustring.gsub(str, " ", "%%20" ) -- encode parenthesis
return nowiki(str)
end
local function getProperty(entity, prop, outputType)
local Output = {}
if entity.claims and entity.claims[prop] then
for _, statement in pairs( entity:getBestStatements( prop )) do
if (statement.mainsnak.snaktype == "value") then
local val = statement.mainsnak.datavalue.value
if val.id then
val = val.id
elseif val.text then
val = val.text
elseif val.amount then
val = tonumber(val.amount)
end
table.insert(Output, val)
end
end
end
if #Output==0 then
return nil
elseif outputType=='one' then
return Output[1]
else
return Output
end
end
-- ====================================================================
-- This function is responsible for producing HTML of a single row of the template
-- At this stage all the fields are already filed. There is either one or two fields
-- INPUTS:
-- * param1 and param2 - structures for 2 fields containing fields:
-- - tag - I18n tag used for localization of the field name. Usually name of page in MediaWiki namespace which was imported from translatewiki.org.
-- Alternative is to pass already translated field name.
-- - field - field content
-- - id - ID tag added to HTML's <td> cell. if IDs of 2 fields ar the same than we ignore the second one
-- - wrapper - some fields need a <span class=...> wrapper around the field content
-- ====================================================================
--All other fields
local function Build_html_row(param, args)
local LUT = {artwork=0, photograph=1, book=2}
local demo = args.demo and bit32.extract( param.demo or 0, LUT[args.infobox])==1
local field = args[param.field]
if field=='' then field=nil; end
if not (field or demo) then
return nil
end
if not param.id then -- "other fields" parameter
return field
end
local tag = param.tag or 'bad'
if string.sub(tag,1,10) == 'wm-license' then
tag = mw.message.new( tag ):inLanguage(args.lang):plain() -- label message in args.lang language
elseif string.match(tag, "^[QP]%d+$") then
tag = getLabel(tag, args.lang, "-", "ucfirst")
elseif labels[tag] then
tag = core.langSwitch(labels[tag], args.lang)
end
local cell1 = string.format('<td id="%s" class="fileinfo-paramfield" lang="%s">%s</td>\n', param.id, args.lang, tag)
local cell2 = string.format('<td>\n'.. param.wrapper ..'</td>', field or '')
return string.format('<tr valign="top">\n%s%s\n</tr>\n\n', cell1, cell2)
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, cats)
-- get text direction
local dir
if mw.language.new( args.lang ):isRTL() then
dir = 'rtl'
else
dir = 'ltr'
end
-- original_description row has a different look than other rows
if args.original_description and (args.original_description_info or args.biased) then
local tag1, tag2 = "", ""
if args.original_description_info then
tag1 = string.format('<div style="background:#dde; font-size:86%%; direction:%s;">%s</div>', dir, args.original_description_info)
end
if args.biased then
tag2 = core.langSwitch(labels.inaccurate_description, args.lang)
tag2 = string.format('<div style="padding:0.5ex; margin:0 0 0.5ex 0; border: 1px solid red;">%s: %s</div>', tag2, args.biased)
end
args.original_description = tag1 .. tag2 .. args.original_description
end
-- files with no source will be flagged
if (not args.source) and (not args.source_) and (args.strict==true) and (args.namespace==6) then
args.nosource = mw.getCurrentFrame():expandTemplate{ title = 'Source missing' }
end
local nCol = 2
if not args.image and args.demo then
args.image = args.demo_image
end
if args.image then
nCol = 3
end
-- Top line
local top, results = {}, {}
if args.name then
table.insert(top, string.format('<span class="fn" id="artwork"><bdi>%s\n</bdi></span>', args.name ) )
end
if args.linkback then -- Wikidata Link
table.insert(top, string.format('[[File:Blue pencil.svg|15px|%s|link=%s]]', args.linkback, args.linkback) )
end
if args.wikidata then -- Wikidata Link
table.insert(top, string.format('[[File:Wikidata-logo.svg|20px|wikidata:%s|link=wikidata:%s]]', args.wikidata, args.wikidata) )
table.insert(top, string.format('[[File:Wikidata-Reasonator_small_logo.svg|5px|reasonator:%s|link=https://reasonator.toolforge.org/test/?q=%s]]', args.wikidata, args.wikidata) )
end
if args.wikisource then --Wikisource link
table.insert(top, string.format('[[File:Wikisource-logo.svg|15px|%s|link=%s]]', args.wikisource, args.wikisource) )
end
if args.wikiquote then --Wikiquote link
table.insert(top, string.format('[[File:Wikiquote-logo.svg|15px|%s|link=%s]]', args.wikiquote, args.wikiquote) )
end
if args.QS then -- quick_statement link to upload missing info to wikidata
table.insert(top, string.format('%s', args.QS) )
end
if #top>0 then
local line = string.format('<th colspan="%i" style="background-color:#ccf; font-weight:bold; border:1px solid #aaa" text-align="left">%s</th>', nCol, table.concat(top, ' '))
table.insert(results, string.format('<tr valign="top">\n%s\n</tr>\n', line))
end
-- Permissions tag
local tag1 = mw.message.new( "wm-license-information-permission" ):inLanguage(args.lang):plain()
local tag2 = mw.message.new( "wm-license-information-permission-reusing-link" ):inLanguage(args.lang):plain()
local tag3 = mw.message.new( "wm-license-information-permission-reusing-text" ):inLanguage(args.lang):plain()
local permission_tag = string.format("%s<br /><small>([[%s|%s]])</small>", tag1, tag2, tag3)
-- define constants for readability
-- demo=art+photo+book will show that row in demo mode in {{artwork}, {{Photograph}} and {{Book}} templates
local none = 0
local art = 1
local photo = 2
local book = 4
-- add other fields 'author_of_foreword', 'author_of_afterword'
local param = {
-- field name machine readable tag field name i18n approach show in demo mode? field value wrapper
{field='artist' , id='fileinfotpl_aut' , tag='wm-license-artwork-artist', demo=art, wrapper='<div class="fn value">\n%s</div>'},
{field='author' , id='fileinfotpl_aut' , tag='wm-license-information-author', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='editor' , id='fileinfotpl_book_editor' , tag='wm-license-book-editor', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='translator' , id='fileinfotpl_book_translator' , tag='wm-license-book-translator', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='illustrator' , id='fileinfotpl_book_illustrator' , tag='wm-license-book-illustrator', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='author_of_foreword' , id='fileinfotpl_aut' , tag='P2679', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='author_of_afterword' , id='fileinfotpl_aut' , tag='P2680', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='architect' , id='fileinfotpl_aut' , tag='Q42973', demo=none, wrapper='<div class="fn value">\n%s</div>'},
{field='designer' , id='fileinfotpl_aut' , tag='Q5322166', demo=none, wrapper='<div class="fn value">\n%s</div>'},
{field='photographer' , id='fileinfotpl_aut' , tag='Q33231', demo= photo, wrapper='<div class="fn value">\n%s</div>'},
{field='other_fields_1'},
-- title & desctiption block
{field='title' , id='fileinfotpl_art_title' , tag='wm-license-artwork-title', demo=art+photo+book, wrapper='<div class="fn">\n%s</div>'},
{field='subtitle' , id='fileinfotpl_book_subtitle' , tag='wm-license-book-subtitle', demo= book, wrapper='%s'},
{field='series_title' , id='fileinfotpl_book_series-title' , tag='wm-license-book-series-title', demo= book, wrapper='%s'},
{field='volume' , id='fileinfotpl_book_volume' , tag='wm-license-book-volume', demo= book, wrapper='%s'},
{field='edition' , id='fileinfotpl_edition' , tag='wm-license-book-edition', demo= book, wrapper='%s'},
{field='publisher' , id='fileinfotpl_book_publisher' , tag='wm-license-book-publisher', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='printer' , id='fileinfotpl_book_printer' , tag='wm-license-book-printer', demo= book, wrapper='<div class="fn value">\n%s</div>'},
{field='object_type' , id='fileinfotpl_art_object_type' , tag='object_type', demo=art, wrapper='%s'},
{field='genre' , id='fileinfotpl_art_genre' , tag='Q483394', demo= book, wrapper='%s'},
{field='original_description' , id='fileinfotpl_desc' , tag='original_description', demo= photo, wrapper='<div class="description">\n%s</div>'},
{field='description' , id='fileinfotpl_desc' , tag='wm-license-information-description', demo=art+photo+book, wrapper='<div class="description">\n%s</div>'},
{field='pageoverview' , id='fileinfotpl_book-page-overview' , tag='wm-license-book-page-overview', demo=none, wrapper='%s'},
{field='depicted_people' , id='fileinfotpl_art_depicted_people' , tag='depicted_people', demo=art+photo, wrapper='%s'},
{field='depicted_place' , id='fileinfotpl_art_depicted_place' , tag='depicted_place', demo=art+photo, wrapper='%s'},
{field='depicted_part' , id='fileinfotpl_art_depicted_part' , tag='P5961', demo=art+photo+book, wrapper='%s'},
{field='language' , id='fileinfotpl_book_language' , tag='wm-license-book-language', demo= book, wrapper='%s'},
{field='other_fields_2'},
-- date, object outside description, history, etc.
{field='date' , id='fileinfotpl_date' , tag='wm-license-information-date', demo=art+photo, wrapper='%s'},
{field='publication_date' , id='fileinfotpl_publication_date' , tag='P577', demo= book, wrapper='%s'},
{field='medium' , id='fileinfotpl_art_medium' , tag='wm-license-artwork-medium', demo=art+photo, wrapper='%s'},
{field='dimensions' , id='fileinfotpl_art_dimensions' , tag='wm-license-artwork-dimensions', demo=art+photo, wrapper='%s'},
{field='institution' , id='fileinfotpl_art_gallery' , tag='Q2668072', demo=art+photo, wrapper='%s'},
{field='department' , id='fileinfotpl_art_location' , tag='wm-license-artwork-current-location', demo=art+photo , wrapper='<div class="locality">\n%s</div>'},
{field='id' , id='fileinfotpl_art_id' , tag='wm-license-artwork-id', demo=art+photo, wrapper='<div class="identifier">\n%s</div>'},
{field='coordinates' , id='fileinfo-paramfield' , tag='ObjectLocation', demo=art+photo, wrapper='%s'},
{field='place_of_publication' , id='fileinfotpl_book_place-of-publication' , tag='wm-license-book-place-of-publication', demo= book, wrapper='%s'},
{field='place_of_creation' , id='fileinfotpl_art_creation_place' , tag='place_of_creation', demo=art, wrapper='%s'},
{field='place_of_discovery' , id='fileinfotpl_art_discovery_place' , tag='place_of_discovery', demo=art, wrapper='%s'},
{field='object_history' , id='fileinfotpl_art_object_history' , tag='wm-license-artwork-object-history', demo=art, wrapper='%s'},
{field='exhibition_history' , id='fileinfotpl_art_exhibition_history' , tag='exhibition_history', demo=art+photo, wrapper='%s'},
{field='credit_line' , id='fileinfotpl_art_credit_line' , tag='wm-license-artwork-credit-line', demo=art, wrapper='%s'},
{field='inscriptions' , id='fileinfotpl_art_inscriptions' , tag='wm-license-artwork-inscriptions', demo=art, wrapper='%s'},
{field='notes' , id='fileinfotpl_art_notes' , tag='wm-license-artwork-notes', demo=art+photo, wrapper='%s'},
{field='other_fields_3'},
-- references, and sources
{field='references' , id='fileinfotpl_art_references' , tag='wm-license-artwork-references', demo=art+photo+book, wrapper='%s'},
{field='authority' , id='fileinfotpl_art_authority' , tag='Q36524', demo=none, wrapper='%s'},
{field='source' , id='fileinfotpl_src' , tag='wm-license-artwork-source', demo=art, wrapper='%s'}, -- source/photographer
{field='source_' , id='fileinfotpl_src' , tag='wm-license-information-source', demo= photo+book, wrapper='%s'}, -- source
{field='nosource' , id='fileinfotpl_nosrc' , tag='wm-license-information-source', demo=none, wrapper='%s'},
{field='permission' , id='fileinfotpl_perm' , tag=permission_tag, demo=art+photo+book, wrapper='%s'},
{field='other_versions' , id='fileinfotpl_ver' , tag='wm-license-information-other-versions', demo=art+photo+book, wrapper='%s'},
{field='other_fields'},
{field='camera_coord'},
}
for i=1,#param do
table.insert(results, Build_html_row(param[i], args))
end
-- add material on the right: image, wikisource icon, etc.
if args.image then
if args.image_page and args.image then -- page parameter for DjVu and PDF files
args.image = string.format('%s|page=%i', args.image, args.image_page)
end
if args.infobox=='book' then -- page parameter for DjVu and PDF files
tag1 = mw.message.new( 'wm-license-book-start-this-book' ):inLanguage(args.lang):plain()
tag2 = string.format('|thumb|[[:File:%s|%s]]', args.image, tag1)
else
tag2 = ''
end
local field = string.format('[[File:%s|250x250px|alt=%s|class=photo%s]]', args.image, args.name or '', tag2)
local nRow = #results -- number of rows below
local line = string.format('<td rowspan="%i" style="width:200px; text-align: right;" id="fileinfotpl_creator_image"><span class="wpImageAnnotatorControl wpImageAnnotatorOff">%s</span></td></tr>\n\n', nRow, field)
results[2] = mw.ustring.gsub(results[2], "</tr>%s*$", line); -- attach image section to the right side of the table, by attaching to row #2
end
-- add table and outer layers
local style = string.format('class="fileinfotpl-type-artwork toccolours vevent mw-content-%s" dir="%s" style="width: 100%%" cellpadding="4"', dir, dir)
results = string.format('<table %s>\n%s\n</table>\n', style, table.concat(results)) -- combine "results", an array of strings into a single string
results = string.format('<div class="hproduct commons-file-information-table">\n%s\n</div>\n', results)
return results
end
local function verify_input_parameters(args0)
local cats = '' -- categories
-- add [[Category:Creator templates with unknown parameter]] category, if some parameter not on the following list is used
local fields = { 'title', 'object_type', 'description', 'date', 'medium', 'permission',
'artist', 'author', 'architect', 'designer', 'illustrator', 'publisher', 'editor', 'translator', 'printer', 'photographer',
'dimensions', 'institution', 'department', 'references', 'object_history', 'genre',
'exhibition_history', 'credit_line', 'other_versions', 'source', 'strict', 'inscriptions', 'notes', 'linkback', 'camera_coord',
'other_fields', 'other_fields_1', 'other_fields_2', 'other_fields_3', 'demo', 'id', 'wikidata', 'year', 'homecat', 'authority',
'place_of_creation', 'place_of_discovery', 'source_', 'wikidata_cat', 'namespace', 'lang', 'image', 'noimage',
'depicted_people', 'depicted_place', 'original_description_info', 'original_description', 'biased', 'photo_date', 'infobox',
'place_of_publication', 'publication_date', 'language', 'subtitle', 'series_title', 'volume', 'edition', 'edition_of',
'pageoverview', 'wikisource', 'wikiquote', 'demo_image', 'image_page', 'depicted_part', 'mimeType', 'num_pages',
'author_of_foreword', 'author_of_afterword', 'infobox'}
local set = {}
for _, field in ipairs(fields) do set[field] = true end
for field, _ in pairs( args0 ) do
if not set[field] then
local LUT = {artwork='Artwork', photograph='Photograph', book='Book'}
local infobox = LUT[args0.infobox]
cats = cats .. '[[Category:Pages using ' .. infobox .. ' template with incorrect parameter]]'
cats = cats .. string.format('\n;<span style="color:red">Error in [[Template:%s|{{%s}} template]]: unknown parameter "%s".</span>', infobox, infobox, field)
end
end
return cats
end
-- ===========================================================================
-- === This function is responsible for adding maintenance categories ===
-- === which are not related to wikidata ===
-- === INPUTS: ===
-- === * args0 - data from the local arguments ===
-- === * args - merged data from the local arguments and Wikidata ===
-- ===========================================================================
local function add_maintenance_categories(args0, args)
local cats = '' -- categories
mw.getCurrentFrame():expandTemplate{ title = 'Infobox template tag' } -- add the template tag
-- ====================================================
-- === automatic tagging of pages in all namespaces ===
-- ====================================================
if args.date or args.year then
-- add an empty template which can be used as a tag in PetScan
local d = os.date('!*t') -- current date table
local current_year = tonumber(d.year) -- current year
local creation_year = tonumber(ISOdate._ISOyear(args.year or args.date))
if creation_year and current_year and (current_year-creation_year)>200 then
mw.getCurrentFrame():expandTemplate{ title ='Works created more than 200 years ago' }
end
end
if args0.namespace==0 and mw.ustring.sub(args0.pagename,1,8) == "Artwork:" then
cats = cats .. '\n[[Category:Artwork templates]]'
if args.homecat then
cats = cats .. '\n[[Category:' .. args.homecat .. ']]'
end
end
-- add categories related to accession number for artworks
if args0.id and args0.infobox=='artwork' then
local sortkey = nowiki(args0.id) -- strip any links that might be there
if #sortkey>30 then
sortkey = 'zzz'
end
cats = string.format('%s\n[[Category:Artworks with known accession number| %s]]', cats, sortkey)
end
-- add categories related to template:book transcluded into template for specific book
if args0.infobox=='book' and args0.namespace==10 then
cats = cats .. '\n[[Category:Book templates]]'
-- add homecat category
if args0.homecat~='~' then
local page = {}
if args0.homecat then
cats = string.format('%s\n[[Category:%s| ]]',cats, args0.homecat)
page = mw.title.new( args0.homecat, 'category' )
end
if not page or not page.exists or not args0.homecat then
cats = cats .. '\n[[Category:Book templates without home category]]'
end
end
end
-- add invisible template tags based on book's date of publication
if args0.infobox=='book' then
local pubYear = args.publication_year
if pubYear then
local curYear = tonumber(os.date('!*t').year) -- current year
if pubYear<year-95 then
mw.getCurrentFrame():expandTemplate{ title ='Books published more than 95 years ago' }
end
if pubYear<year-200 then
mw.getCurrentFrame():expandTemplate{ title ='Works created more than 200 years ago' }
end
end
end
return cats
end
-- ===========================================================================
-- === This function is responsible for adding maintenance categories ===
-- === to pages in creator namespace which are related to wikidata ===
-- === INPUTS: ===
-- === * args0 - local inputs from the creator template page ===
-- === * args1 - merge of local and wikidata metadata ===
-- === * data - data pulled from Wikidata ===
-- ===========================================================================
local function add_wikidata_maintenance_categories(args0, args1, data)
local cats = '' -- categories
local comp = {} -- outcome of argument vs. wikidata comparison
local OK = ((args0.infobox=='artwork' or args0.infobox=='photograph') and (args0.namespace==6 or args0.namespace==14)) -- artworks and photographs can be in file or category namespace
or (args0.infobox=='book' and (args0.namespace==10 or args0.namespace==14) ) -- books can be in template or category namespace
or (args0.infobox=='book' and args0.namespace==6 and (args0.mimeType=='application/pdf' or args0.mimeType=='image/vnd.djvu')) -- books can also be in file namespace if it is PDF or DjVu
if ( not OK or (args0.wikidata_cat==false)) then -- continue only if the namespace is a Category or file
return cats, args1
end
local LUT = {artwork='Artworks', photograph='Photographs', book='Books'}
-- skip the rest if no item ID
if not args0.wikidata then
local TypeLUT = {['grave']='Graves', ['tomb']='Graves', ['funeral chapel']='Graves', ['funeral niche']='Graves', ['painting']='Paintings' }
local oType = TypeLUT[string.lower(args0.object_type or '')] or LUT[args0.infobox]
cats = string.format('%s\n[[Category:%s without Wikidata item]]', cats, oType)
return cats, args1
end
--=======================================================================================================
--=== Categories and files with {{Artwork}} template linked to Wikidata item below
--=======================================================================================================
-- setup QuickStatements
local qsTable = {} -- table to store QuickStatements
-- default QuickStatements command
local today = '+' .. os.date('!%F') .. 'T00:00:00Z/11' -- today's date in QS format
local fname = '"https://commons.wikimedia.org/wiki/File:' .. string.gsub(args0.pagename,' ','_') .. '"'
local source = '|S143|Q565|S813|' .. today .. '|S4656|' .. fname
local qsCommand1 = '%s|%s|%s' .. source
local qsCommand2 = '%s|%s' .. source
cats = string.format('%s\n[[Category:%s with Wikidata item|%s]]', cats, LUT[args0.infobox], args0.wikidata)
-- check object_type_id against a list of incorrect values for P31 property of associated item
-- Black and white list id is of wrong type if bwLUT returns "1", bwLUT = "2" means good type
-- bad {Q5='human', Q11266439='template ', Q4167410='disambiguation', Q4167836='category', Q532='village', Q482994='album', Q16521='taxon' }
-- groups {Q15727816='painting series', sculpture series (Q19479037), artwork series (Q15709879), group of sculptures (Q27031439),
-- group of paintings (Q18573970) , polyptych (Q1278452), diptych (Q475476), triptych (Q79218) }
-- good {Q199414='bog body', Q7881='skeleton'} -- one of those overwrites "bad" flag so 'human' & 'bog body' is OK
local groupItem = false
if data.object_type_id then
local bad = false
local bwLUT = {Q5=1, Q11266439=1, Q4167410=1, Q4167836=1, Q532=1, Q482994=1, Q16521=1, Q15727816=2, Q19479037=2,
Q15709879=2, Q27031439=2, Q18573970=2, Q1278452=2, Q475476=2, Q79218 = 2, Q199414=3, Q7881=3}
for _, typeId in ipairs( data.object_type_id ) do
local v = bwLUT[typeId]
if v==1 then
bad = true
elseif v==2 then
groupItem = true
cats = string.format('%s\n[[Category:%s with group Wikidata item|%s]]', cats, LUT[args0.infobox], args0.wikidata)
break
elseif v==3 then
bad = false
break
end
end
if bad then
cats = string.format('%s\n[[Category:%s with wrong Wikidata item|%s]]', cats, LUT[args0.infobox], args0.wikidata)
end
end
-- local fields which are missing on Wikidata
local fields = {'date', 'publication_date', 'medium', 'dimensions', 'image', 'institution', 'author', 'artist'}
for _, field in ipairs( fields ) do
if not data[field] and args0[field] and not string.match(args0[field], '%<div style="display: none;"%>Unknown '..field..'<%/div%>') then
comp[field] = 'missing'
end
end
if not data.id and args0.id then
comp['accession number'] = 'missing'
local id = nowiki(args0.id) -- strip any links that might be there
if args0.institution_id and #id<20 then
table.insert( qsTable, string.format(qsCommand1, args0.wikidata, 'P217', '"' .. id.. '"|P195|'..args0.institution_id) )
end
end
if comp.artist=='missing' and string.match(args0.artist, '%<div style="display: none;"%>Unknown a%w+%<%/div%>') then
comp.artist = nil -- ignore {{Unknown|artist}}
end
-- mark local fields redundant to Wikidata
local fields = {['date']='date', medium='medium', dimensions='dimensions', institution_id='institution', author_id='author', artist_id='artist'}
for field1, field2 in ipairs( fields ) do
if data[field1] and args0[field1] and data[field1]==args0[field1] then
comp[field2] = 'redundant'
end
end
-- Redundant author and artist
if (data.author_id==args0.artist_id and data.author_id) then
comp.artist = 'redundant'
end
if (data.artist_id==args0.author_id and data.artist_id) then
comp.author = 'redundant'
end
-- handle case when creator template is a red-link but wikidata has creator item ID
if (string.match(args0.artist or '', "%[%[:Creator:") and data.artist) then
args1.artist = data.artist
comp.artist = 'redundant'
end
if (string.match(args0.author or '', "%[%[:Creator:") and data.author) then
args1.author = data.author
comp.author = 'redundant'
end
-- process "image" field
if (data.image and args0.image) then
comp.image = 'redundant'
end
if (not data.image and args0.image ) then -- QS code to help transfer image to Wikidata
local ext = string.lower(string.sub(args0.image,-4))
if (ext=='.pdf' or ext =='djvu') and args0.image_page then
table.insert( qsTable, string.format(qsCommand1, args0.wikidata, 'P996', '"' .. args0.image.. '"|P4714|'.. tostring(args0.image_page)) )
elseif (ext=='.pdf' or ext =='djvu') then
table.insert( qsTable, string.format(qsCommand1, args0.wikidata, 'P996', '"' .. args0.image.. '"') )
else
table.insert( qsTable, string.format(qsCommand1, args0.wikidata, 'P18', '"' .. args0.image.. '"') )
end
comp.image = 'missing'
elseif (not data.image and args0.namespace==6 and args0.num_pages>1 and (args0.mimeType=='application/pdf' or args0.mimeType=='image/vnd.djvu')) then -- QS code to help transfer image to Wikidata
if args0.image_page then
table.insert( qsTable, string.format(qsCommand1, args0.wikidata, 'P996', '"' .. args0.pagename.. '"|P4714|'.. tostring(args0.image_page)) )
else
table.insert( qsTable, string.format(qsCommand1, args0.wikidata, 'P996', '"' .. args0.pagename.. '"') )
end
comp.image = 'missing'
elseif (not data.image and args0.namespace==6 and args0.num_pages==1 and args0.infobox=='artwork') then -- QS code to help transfer image to Wikidata
table.insert( qsTable, string.format(qsCommand1, args0.wikidata, 'P18', '"' .. args0.pagename.. '"') )
comp.image = 'missing'
end
-- look for hidden text in various templates so they can be passed to Wikidata if needed using QS
-- copy args0['data'] to args0['era'] if it contains an "era QS"
-- because they share one parameter/field at template level input,
-- but need separate handling here
-- TODO: splitting/sorting (at an earlier stage) would be better than simply copying,
-- in cases where there is one value for each they won't be processed without splitting
if args0['date'] and string.find(args0['date'], '%<div style="display: none;"%>era QS:([^%<]+)%</div%>') then
args0['era'] = args0['date']
end
-- different fields from different tables are allowed to create QS codes to allow data transfer to Wikidata
-- some fields are often not used currectly in some templates like institution in book template and are not alowed to create QS
local fields = {object_type='artwork', era='artwork', medium='artwork', dimensions='artwork', institution='artwork', artist='artwork', reference_wga='artwork', date='all' ,
language='book', author='book', translator='book', publisher='book', printer='book', illustrator='book', editor='book', publication_date='book'}
for field, infobox in pairs( fields ) do
if args0[field] and not data[field] and (args0.infobox==infobox or infobox=='all') then
local pat = '%<div style="display: none;"%>'..field..' QS:([^%<]+)%</div%>'
local qs = string.match(args0[field], pat) -- find hidden tag with QS code
local _, nMatch = string.gsub(args0[field], pat, "") -- count matches
if qs and nMatch==1 then -- allow only single matches
qs = string.gsub(qs, ',', '|')
for _, v in ipairs( mw.text.split( qs, ';', true ) ) do
table.insert( qsTable, string.format(qsCommand2, args0.wikidata, v) )
end
end
end
end
-- add "Commons Category" (P373) if template at category page
if not data.homecat and args0.namespace==14 then
table.insert( qsTable, string.format(qsCommand1, args0.wikidata, 'P373', '"' .. args0.pagename.. '"' ))
end
-- Special case of QS codes for multilingual labels extracted from {{title}} and {{description}} templates, etc.
if args0.title then
local max_title_len = 100
-- strip titles from title field with {{title}} template: {{title|lang=...|1=...}}
local pat = '%<div style="display: none;"%>title QS:P1476,((%w+):[^%<]+)%</div%>'
for label, lang in mw.ustring.gmatch(args0.title, pat) do
label = nowiki_title(label)
if not data.title_[lang] and #label<max_title_len then
table.insert( qsTable, string.format(qsCommand1, args0.wikidata, 'P1476', label) )
end
end
-- strip titles from title field with {{title}} templates, with fields like {{en}}, {{es}}, etc.
pat = '%<div style="display: none;"%>label QS:L(%w+),([^%<]+)%</div%>'
for lang, label in mw.ustring.gmatch(args0.title, pat) do
label = nowiki_title(label)
if not(data.labels and data.labels[lang]) and #label<max_title_len then
table.insert( qsTable, string.format('%s|%s|%s', args0.wikidata, 'L'..lang, label) )
end
end
-- strip titles from title field with {{description}} templates, like {{en}}, {{es}}, etc.
-- <div class="description mw-content-ltr fr" dir="ltr" lang="fr" style=""><span class="language fr" title="Français">'''Français :'''</span> ''Les bateaux rouges, Argenteuil''</div>
--pat = '%<div class="description mw-content-[rtl]* %w+" dir="[rtl]*" lang="(%w+)" style=""%>%<span class[^%<]+%</span%> *([^%<]+)%</div%>'
pat = '%<span class="language (%w+)" [^%<]+%</span%> *([^%<]+)%</div%>'
for lang, label in mw.ustring.gmatch(args0.title, pat) do
label = nowiki_title(label)
if not(data.labels and data.labels[lang]) and #label<max_title_len then
table.insert( qsTable, string.format('%s|%s|"%s"', args0.wikidata, 'L'..lang, label) )
end
end
end
-- add categories related to accession number for artworks
if not args0.id and data.id and args0.infobox=='artwork' then
cats = string.format('%s\n[[Category:Artworks with accession number from Wikidata| %s]]', cats, args0.wikidata)
cats = string.format('%s\n[[Category:Artworks with known accession number| %s]]', cats, data.id_id or 'zzz')
end
-- ==================================================
-- === Create categories based on comp structure ====
-- ==================================================
for field, outcome in pairs( comp ) do
cats = string.format('%s\n[[Category:%s with Wikidata item %s %s|%s]]', cats, LUT[args0.infobox], outcome, field, args0.wikidata)
end
-- ==================================================
-- === Create QuickStatement codes ==================
-- ==================================================
local QS = '' -- quick_statements final string
if #qsTable>0 and not groupItem then -- do not use QS on group items
local qsWrapper = ' [[File:Commons_to_Wikidata_QuickStatements.svg|15px|link=%s]]'
QS = table.concat( qsTable, '||') -- combine multiple statements into a single command separated by \n (line feed)
QS = mw.ustring.gsub (mw.uri.encode(QS),'%%2520','%%20')
QS = 'https://quickstatements.toolforge.org/#/v1=' .. QS -- create full URL link
QS = mw.ustring.format(qsWrapper, QS) -- use URL as a link accessed by clicking Wikidata icon
cats = string.format('%s\n[[Category:%s with Wikidata item: quick statements]]', cats, LUT[args0.infobox])
end
args1.QS = QS;
return cats, args1
end
-- ===========================================================================
-- === Harvest Structured data on Commons properties ===
-- === INPUTS: ===
-- === * mid - SDC ID ===
-- === * lang - language id of the desired language ===
-- === * namespace - namespace number of the page calling the module ===
-- ===========================================================================
local function harvest_SDC(args0, lang)
local bookFlag = (args0.infobox=='book' and (args0.mimeType=='application/pdf' or args0.mimeType=='image/vnd.djvu'))
local sdc = {} -- structure similar to "args" but filled with SDC data
local cats = ''
local entity = mw.wikibase.getEntity()
if not entity then
if args0.wikidata and bookFlag then
cats = cats .. '[[Category:Books with structured data missing P6243 property]]\n'
elseif args0.wikidata and args0.infobox~='book' then
cats = cats .. '[[Category:Artworks with structured data missing P6243 property]]\n'
end
return sdc, cats
end
local property = {P6243='wikidata', P4714='image_page' }
for prop, field in pairs( property ) do
sdc[field] = getProperty(entity, prop, 'one')
end
-- get wikidata item ID from P6243
if sdc.wikidata then
local wEntity = mw.wikibase.getEntity(sdc.wikidata)
if wEntity.id~=sdc.wikidata then
cats = cats .. '[[Category:Artworks with structured data with redirected P6243 property]]'
end
end
if not sdc.wikidata and args0.wikidata then
if bookFlag then
cats = cats .. '[[Category:Books with structured data missing P6243 property]]\n'
elseif args0.infobox~='book' then
cats = cats .. '[[Category:Artworks with structured data missing P6243 property]]\n'
end
elseif sdc.wikidata and args0.wikidata and sdc.wikidata~=args0.wikidata then
cats = cats .. '[[Category:Artworks with mismatching structured data P6243 property]]\n'
end
-- get source from P7482
if entity.statements and entity.statements.P7482 then
local statement = entity.statements.P7482[1]
if statement.mainsnak.datavalue.value.id=='Q74228490' and statement.qualifiers and statement.qualifiers.P973 then
local url = statement.qualifiers.P973[1].datavalue.value
if statement.qualifiers.P137 then
local id = statement.qualifiers.P137[1].datavalue.value.id
local label = getLabel(id, lang, '-')
sdc.source_ = '[' .. url ..' ' .. label ..']' .. core.editAtSDC(args0.pagename, 'P7482', lang)
else
sdc.source_ = url .. core.editAtSDC(args0.pagename, 'P7482', lang)
end
end
end
return sdc, cats
end
-- ===========================================================================
-- === Harvest wikidata properties matching creator template fields ===
-- === INPUTS: ===
-- === * itemID1 - item id or a q-code from the template ===
-- === * itemID2 - item id or a q-code from SDC ===
-- === * lang - language id of the desired language ===
-- === * namespace - namespace number of the page calling the module ===
-- ===========================================================================
local function harvest_wikidata(itemID1, itemID2, lang, namespace, infobox)
local data = {} -- structure similar to "args" but filled with wikidata data
local cats = ''
local frame = mw.getCurrentFrame()
local entity = nil
local itemID = itemID1 or itemID2
if mw.wikibase and itemID then
local LUT = {artwork='Artworks', photograph='Photographs', book='Books'}
entity = mw.wikibase.getEntity(itemID)
if not entity then
cats = string.format('[[Category:%s with bad Wikidata link]]', LUT[infobox])
elseif entity.id~=itemID and itemID1 then
cats = string.format('[[Category:%s with redirected Wikidata link]]', LUT[infobox])
end
end
if not entity then
return data, cats
end
-- inception date: translated date and year number
local d = getDate(entity, 'P571' , lang) -- inception date
if d.str then
data.date_, data.year = d.iso, d.year
data.date = d.str .. core.editAtWikidata(entity.id, 'P571', lang)
end
-- publication date: translated date and year number
local d = getDate(entity, 'P577' , lang) -- publication date
if d.str then
data.publication_date_, data.publication_year = d.iso, d.year
data.publication_date = d.str .. core.editAtWikidata(entity.id, 'P577', lang)
end
-- harvest string properties
local Debug ={}
local property = {P10='video', P18='image', P996='scan', P4896='model3D', P373='homecat',
P2093='authorStr', P393='edition', P4714='image_page', P1957='wikisource_index', P7420='framed_image' }
for prop, field in pairs( property ) do
data[field] = getProperty(entity, prop, 'one')
end
data.image = data.image or data.scan or data.video or data.model3D or data.framed_image
data.image_page = tonumber(data.image_page)
if data.edition then
data.edition = data.edition .. core.editAtWikidata(entity.id, 'P393', lang)
end
-- harvest Q-code properties which are than converted from Q-number to labels (pick one)
local property = { P189='place_of_discovery', P2079='technique', P123='publisher', P872='printer',
P136='genre', P921='subject', P179='series_title', P291='place_of_publication', P407='language',
P629='edition_of'}
for prop, field in pairs( property ) do
local id = getProperty(entity, prop, 'one')
if id then
data[field] = getLabel(id, lang, "wikipedia") .. core.editAtWikidata(entity.id, prop, lang)
end
end
-- harvest Q-code properties which are than converted from Q-number to labels (pick all)
local property = { P31='object_type', P407='language'}
for prop, field in pairs( property ) do
local ids = getProperty(entity, prop, 'all')
if ids then
local T = {}
for _, id in ipairs( ids ) do
table.insert(T, getLabel(id, lang))
end
data[field] = table.concat(T, " / ") .. core.editAtWikidata(entity.id, prop, lang)
data[field ..'_id'] = ids
end
end
-- get era
data.era_id = getProperty(entity, 'P2348', 'all')
if data.era_id then
local periodSpan = require('Module:Period')._periodSpan
local T = {}
for _, id in ipairs( data.era_id ) do
local eraText = getLabel(id, lang)
local spanText = periodSpan(id, lang)
if spanText then
eraText = eraText .. ' ' .. spanText
end
table.insert(T, eraText)
end
data.era = table.concat(T, " / ") .. core.editAtWikidata(entity.id, 'P2348', lang)
end
if data.era and data.date then
data.date = data.date .. "<br/>" .. data.era
elseif data.era and not data.date then
data.date = data.era
end
-- get author and/or author creator template
local property = { P170='creator', P50='author', P84='architect', P287='designer', P98='editor',
P655='translator', P110='illustrator', P2679='author_of_foreword', P2680='author_of_afterword' }
for prop, field in pairs( property ) do
local d = Art.get_creator(entity, prop, lang)
data[field] = d.str
data[field.."_id"] = d.id
end
data.author = data.author or data.authorStr -- P2093='author name string'
-- get title (from 3 properties and label)
--local property = { P1476 = 'title', P1448='official_name', P1705='native_label', P1680='subtitle'}
local property = { P1476 = 'title', P1680='subtitle'}
for prop, field in pairs( property ) do
local title = {}
for _, statement in pairs( entity:getBestStatements(field)) do
if (statement.mainsnak.snaktype == "value") then
local val = statement.mainsnak.datavalue.value
title[val.language] = val.text -- look for multiple values each with a language code
end
end
if #title>0 then
data[field] = core.langSwitch(title, lang)
end
if field=='title' then
data.title_ = title
end
end
--data.title = data.title or data.official_name or data.native_label
data.title = TitleFromWD(entity, lang)
data.label = getLabel(entity, lang)
-- get labels in all the languages
data.labels = {}
if entity.labels then
for lang, val in pairs(entity.labels) do -- loop over all labels
data.labels[lang] = val.value;
data.label = data.label or data.labels[lang] -- no label in prefered language so grab any label
end
end
-- get authority control (rarely used for artworks)
local AC_cats
data.authority, AC_cats = authorityControl(entity, {wikidata = itemID}, lang, 5)
local _,nIdentifiers = string.gsub(data.authority, "*", "")
if nIdentifiers<=1 then
data.authority, AC_cats = nil, ''
end
if not (namespace == 2 or namespace == 828 or math.fmod(namespace,2)==1) then
cats = cats .. AC_cats -- lets not add authorityControl categories to user pages, modules or talk pages and concentrate on templates and categories instead
end
-- get object location
if getProperty(entity, 'P625', 'one') then
local coorFun = require('Module:Coordinates')._LocationTemplateCore
local coori18n = require('Module:i18n/coordinates')
labels.ObjectLocation = coori18n.ObjectLocation
data.coordinates = coorFun({wikidata=entity, lang=lang, globe='earth', mode='object', bare=true})
end
-- prepare fallback list of languages
local langList = mw.language.getFallbacksFor(lang)
table.insert(langList, 1, lang)
-- get wikisource or wikiquote
local projects = {s='wikisource', q='wikiquote'}
for code, project in pairs(projects) do
local sitelinks = getSitelinks(entity, project)
if sitelinks then
local lng, _ = next(sitelinks) -- get language of the first sitelink
table.insert(langList, lng) -- and add it to the list so there is at least one lang with sitelink on the list
for _, language in ipairs(langList) do
local sitelink = sitelinks[language]
if sitelink then
data[project] = string.format('%s:%s:%s', code, language, sitelink)
break
end
end
end
end
-- if no wikisource sitelink than use P1957 'wikisource_index' property
-- wikisource_index is in full url format (like https://es.wikisource.org/wiki/%C3%8Dndice:Sonetos_-_Leopoldo_Diaz.pdf)
-- instead of interlink format (like s:es:%C3%8Dndice:Sonetos_-_Leopoldo_Diaz.pdf)
data.wikisource = data.wikisource or data.wikisource_index
-- properties with functions
data.object_history = Art.get_object_history(entity, lang) -- object history
data.exhibition_history = Art.get_exhibition_history(entity, lang) -- exhibition.history
data.inscriptions = Art.get_inscription(entity, lang)
data.medium = Art.get_medium(entity, lang)
data.medium = empty2nil(data.medium) or data.technique;
data.references = Art.get_references(entity, lang)
data.reference_wga = data.references and mw.ustring.isutf8(data.references) and mw.ustring.find( data.references, 'www%.wga%.hu' ) -- is there a link to wga.hu?
data.depicted_people = Art.get_depicted_people(entity, lang)
local X = Art.get_accession_number(entity, lang)
data.id = X.str -- wikitext version of the accession number
data.id_id = X.id -- one of accession numbers, which will be used as a sortkey
X = Art.get_institution(entity, lang)
data.institution = X.institution
data.institution_id = X.id
data.department = X.location
data.dimensions = Size({entity=entity}, nil, nil, lang)
data.dimensions = empty2nil(data.dimensions);
return data, cats
end
-- ===========================================================================
-- === Adjust parameters related to books ===
-- === and resolve potential aliases ===
-- === INPUTS: ===
-- === * frame - contains imput parameters passed from the template ===
-- === OUTPUTS: ===
-- === * args - cleaned up inputs ===
-- ===========================================================================
local function header_customization(args0, data, args1)
-- get author wikidata ID based on wikidata
local creator_label, creator_id, title_label = nil, nil, nil
if args0.wikidata then
creator_id = data.creator_id or data.author_id or data.architect_id or data.designer_id or data.editor_id or data.translator_id or data.illustrator_id
title_label = data.label -- create name based on wikidata label
end
-- get author wikidata ID based on commons
if not creator_id then
if args0.infobox=='artwork' then
creator_id = args0.artist_id or args0.author_id
elseif args0.infobox=='photograph' then
creator_id = args0.photographer_id or args0.author_id
elseif args0.infobox=='book' then
creator_id = args0.author_id
end
end
-- convert wikidata ID to a label
if creator_id and creator_id:match("^Q%d+$") then
creator_label = getLabel(creator_id, args0.lang)
elseif creator_id then
-- if author was "{{Creator:Meister Theoderich von Prag|circle of}}" than creator_id will be "Q4233718,P1776,Q446631"
local res = {creator_id:match("^Q4233718,(P%d+),(Q%d+)$")}
if res and res[1] and res[2]then
creator_label = getLabel(res[2], args0.lang)
local LUT = {P1773='attributed to', P1774='workshop of', P1775='follower of', P1776='circle of', P1777='manner of', P1779='possibly', P1780='school of', P1877='after'}
creator_label = alterName(LUT[res[1]], creator_label, args0.lang) -- call [[module:Name]] with the task
if creator_label == "name not supported" then
creator_label = nil
end
else
creator_label = creator_id
end
end
-- scrape labels from {{title}} template
if not title_label and args0.title then
local labels = {}
local pat = '%<div style="display: none;"%>label QS:L(%w+),"([^%<]+)"%</div%>'
for lang, label in mw.ustring.gmatch(args0.title, pat) do
labels[lang]=label
end
title_label = core.langSwitch(labels,args0.lang)
end
-- get title based on commons
if not title_label and args0.title then
title_label = nowiki(args0.title)
end
-- if title too long than truncate it
if title_label and #title_label>250 then
title_label = nil
end
if creator_label and #creator_label>150 then
creator_label = nil
end
-- combing author and title labels
if creator_label and title_label then
local colon = mw.message.new( "Colon-separator" ):inLanguage(args0.lang):plain()
args1.name = creator_label .. colon .. title_label
else
args1.name = title_label
end
-- if we have a {{book}} template in file namespace and file of in PDF or DjVu than use it as image
if args0.infobox=='book' and args0.namespace==6 and args1.image==nil
and (args0.noimage==false or args1.image_page)
and (args0.mimeType=='application/pdf' or args0.mimeType=='image/vnd.djvu') then
args1.image = args0.pagename
end
return args1
end
-- ===========================================================================
-- === Read input "frame", normalize input parameters (lower case, etc.) ===
-- === and resolve potential aliases ===
-- === INPUTS: ===
-- === * frame - contains imput parameters passed from the template ===
-- === OUTPUTS: ===
-- === * args - cleaned up inputs ===
-- ===========================================================================
local function read_input_parameters(frame)
-- switch to lowercase parameters to make them case independent
local args = core.getArgs(frame)
-- resolve aliases
args.permission = args.permission or args.license
args.medium = args.medium or args.technique
args.date = args.date or args.year
args.dimensions = args.dimensions or args.size
args.institution = args.institution or args.gallery or args.museum
args.department = args.department or args.location
args.id = args.accession_number or args.id
args.object_type = args.object_type or args.type
args.place_of_creation = args.place_of_creation or args.place_of_origin or args.country
args.object_history = args.object_history or args.history
args.technique, args.year, args.size, args.gallery = nil, nil, nil, nil
args.location, args.type, args.museum, args.accession_number = nil, nil, nil, nil
args.place_of_origin, args.country, args.history, args.license = nil, nil, nil, nil
-- ensure the right format
args.wikidata_cat = core.yesno(args.wikidata_cat, true)
args.strict = core.yesno(args.strict, true)
args.noimage = core.yesno(args.noimage, false)
args.image_page = tonumber(args.image_page)
if args.language and #args.language==2 then
args.language = frame:callParserFunction( "#language", { args.language, args.lang } ) -- get language of the written work
end
return args
end
-- ==================================================
-- === External functions ===========================
-- ==================================================
local p = {}
-- ===========================================================================
-- === Version of the function to be called from other LUA codes
-- ===========================================================================
function p.create_infobox(args0)
local lang = args0.lang -- user's language
local cats, cats2 = '', '' -- categories
local str, data, sdc
-- ===========================================================================
-- === Step 1: clean up of template arguments "args0"
-- ===========================================================================
local page = mw.title.getCurrentTitle()
args0.namespace = page.namespace -- get page namespace
args0.url = page:canonicalUrl()
args0.pagename = page.text
if args0.namespace==6 then -- file namespace
args0.mimeType = page.file.mimeType
args0.num_pages = 1
if page.file.pages then
args0.num_pages = #page.file.pages -- in case of DjVu or PDF files count pages
end
end
if args0.date then
args0.year = empty2nil(ISOdate._ISOyear(args0.date)) -- get year
end
-- for places run them through {{City}} template
local fields = { 'depicted_people', 'depicted_place', 'place_of_discovery' }
for _, field in ipairs( fields ) do
if args0[field] and not string.find(args0[field], ' ') then
args0[field] = City._city(args0[field], lang) -- single word depicted_people will get a link
end
end
-- for dates run them through {{ISOdate}} template and add invisible QS tag if possible
local fields = { 'date', 'publication_date'}
for _, field in ipairs( fields ) do
if args0[field] then
local val = isodate2timestamp(args0[field]) -- if date is in YYYY, YYYY-MM or YYYY-MM-DD formats than it will be saved
args0[field] = ISOdate._ISOdate(args0[field], lang) -- apply ISODate to function to date string to convert date in ISO format to translated date string
if val then -- if date is in ISO format than add an invisible tag which will be used to potentially add this date to QS used to move it to Wikidata
args0[field] = string.format('%s<div style="display: none;">date QS:P,%s</div>', args0[field], val)
end
end
end
-- collapse local {{Creator}} and {{Institution}} templates and extract item ID from them
local fields = {author='creator', artist='creator', photographer='creator', architect='creator', printer='creator',
designer='creator', editor='creator', translator='creator', illustrator='creator', institution='institution'}
for field, keyword in pairs( fields ) do
if args0[field] then
args0[field] = mw.ustring.gsub (args0[field], 'table class="toccolours collapsible%s*"', 'table class="toccolours collapsible collapsed"')
local pat = '%<div style="display: none;"%>'.. keyword ..' QS:P%d+,([^%<]+)%</div%>'
--local pat = '%<div style="display: none;"%>'.. keyword ..' QS:P%d+,(Q%d+)%</div%>'
local _, nMatch = string.gsub(args0[field], pat, "")
if nMatch==1 then -- if multiple templates than skip
args0[field..'_id'] = mw.ustring.match(args0[field], pat)
args0[field] = string.gsub(args0[field], '%<div style="display: none;"%>'.. keyword ..' QS:P', '<div style="display: none;">'.. field ..' QS:P')
end
end
end
-- in case of invisible QS tags add correct property based on which field and infobox it come from
local repList = { {'author', 'book', 'creator QS:P170,', 'author QS:P50,'},
{'illustrator', 'book', 'creator QS:P170,', 'illustrator QS:P110,'},
{'editor', 'book', 'creator QS:P170,', 'editor QS:P98,'},
{'translator', 'book', 'creator QS:P170,', 'translator QS:P655,'},
{'printer', 'book', 'creator QS:P170,', 'printer QS:P872,'},
{'publication_date', 'book', 'date QS:P,', 'publication_date QS:P577,'},
{'date', 'photograph', 'date QS:P,', 'date QS:P571,'},
{'date', 'artwork', 'date QS:P,', 'date QS:P571,'}}
for _, repItem in ipairs( repList ) do
local field, infobox, oldStr, newStr = unpack(repItem)
if args0[field] and args0.infobox==infobox then
args0[field] = string.gsub(args0[field], oldStr, newStr)
end
end
if args0.source and mw.ustring.find( args0.source, 'www%.wga%.hu' ) then
-- code to help copy links to www.wga.hu to wikidata
args0.reference_wga = string.gsub(args0.source, 'http://www%.wga%.hu', 'https://www.wga.hu')
end
-- ===========================================================================
-- === Step 2: one by one merge wikidata and creator data
-- ===========================================================================
local wikidata_temp = args0.wikidata -- wikidata from template
sdc = {}
if args0.namespace==6 then -- if file namespace
sdc, cats2 = harvest_SDC(args0, lang) -- harvest Structured Data on Commons
if (args0.infobox=='photograph' and args0.demo_image=='Breezeicons-actions-22-view-preview.svg' and args0.wikidata_cat==false) then
-- get wikidata from SDC only if this is NOT the photograph infobox of {{Art Photo}} template
sdc.wikidata = nil
end
args0.source_ = args0.source_ or sdc.source_ -- if source not provided than get it from SDC
args0.wikidata = args0.wikidata or sdc.wikidata -- if wikidata not provided than get it from P6243 ("digital representation of")
args0.image_page = args0.image_page or sdc.image_page -- title image page for multipage book files
end
data, cats = harvest_wikidata(wikidata_temp, sdc.wikidata, lang, args0.namespace, args0.infobox)
cats = (cats or '') .. (cats2 or '')
-- based on the template type determine the meaning of "creator"
if args0.infobox=='photograph' then
data.photographer, data.photographer_id = data.creator, data.creator_id
elseif args0.infobox=='book' then
--data.author, data.author_id = data.creator, data.creator_id
else -- args0.infobox=='artwork'
data.artist, data.artist_id = data.creator, data.creator_id
end
-- mass merge (prioritize local values)
local args = {}
local fields = { 'artist', 'artist_id', 'author', 'author_id', 'architect', 'designer', 'illustrator',
'publisher', 'editor', 'translator', 'printer', 'photographer', 'photographer_id', 'wikisource', 'wikiquote',
'title', 'object_type', 'authority', 'image', 'id', 'homecat', 'coordinates', 'genre', 'subject', 'image_page',
'date', 'medium', 'name', 'depicted_people', 'depicted_place', 'place_of_creation', 'place_of_discovery',
'dimensions', 'institution', 'department', 'references', 'object_history', 'exhibition_history', 'inscriptions',
'place_of_publication', 'publication_date', 'language', 'subtitle', 'series_title', 'volume', 'edition', 'edition_of',
'author_of_foreword', 'author_of_afterword'
}
for _, field in ipairs( fields ) do
args[field] = args0[field] or data[field]
end
-- copy fields only defined locally
local fields = { 'wikidata', 'description', 'original_description_info', 'original_description', 'biased', 'camera_coord',
'other_versions', 'source', 'source_', 'strict', 'permission', 'demo', 'lang', 'notes', 'credit_line', 'linkback', 'pageoverview',
'other_fields', 'other_fields_1', 'other_fields_2', 'other_fields_3', 'wikidata_cat', 'namespace', 'infobox', 'demo_image', 'depicted_part'
}
for _, field in ipairs( fields ) do
args[field] = args0[field]
end
if args.artist_id and #args.artist_id>1 and args.artist_id==args.author_id then
args.author, args.author_id = nil, nil; -- if artist and author are the same than drop one
cats = cats .. '[[Category:Artworks with the same artist and author]]\n'
end
if args0.infobox=='artwork' and args0.photo_date and args0.photographer then
cats = cats .. '[[Category:Artworks with photograph information]]\n'
end
if args0.infobox=='book' and args0.publication_date and data.date then
-- some magazines have local publication date for specific issue and inception date on Wikidata for the
-- magazine (publication of the first issue) -> ignore the inception date
args.date = nil
end
-- internationalize local object_type string
if args0.object_type and args.object_type==args0.object_type then
local objectType = require('Module:I18n/objects')._object
args.object_type = objectType(args.object_type, nil, lang)
end
-- convert all empty strings to nils
for _, field in ipairs( fields ) do
if args[field] == '' then
args[field] = nil;
end
end
-- ===========================================================================
-- === Step 3: create maintenance categories and render html of the table
-- ===========================================================================
args = header_customization(args0, data, args)
cats = cats .. add_maintenance_categories(args0, args)
-- If institution namespace than add maintenance categories
args.QS = nil;
cats2, args = add_wikidata_maintenance_categories(args0, args, data)
cats = cats .. cats2
if not sdc.wikidata and args0.wikidata and (args.namespace==6) then
local oType = string.lower(args.object_type or '')
if string.find(oType, '[Pp]ainting') then
cats = cats .. '[[Category:Paintings with structured data missing P6243 property]]\n'
end
end
local results = build_html(args, cats)
return results, cats
end
-- ===========================================================================
-- === Versions of the function to be called from template namespace
-- === Each template with it's own entry point
-- ===========================================================================
function p.artwork(frame)
local args = read_input_parameters(frame)
args.infobox = 'artwork'
local cats0 = verify_input_parameters(args)
args.demo_image = 'Noun project - Mona Lisa - in frame.svg'
local results, cats1 = p.create_infobox(args) -- call the inner "core" function
return results .. cats0 .. cats1
end
function p.photograph(frame)
local args = read_input_parameters(frame)
args.infobox = 'photograph'
local cats0 = verify_input_parameters(args)
args.source_ = args.source or args.source_
args.source = nil
args.demo_image = 'Breezeicons-actions-22-view-preview.svg'
local results, cats = p.create_infobox(args) -- call the inner "core" function
-- most photographs do not have wikidata id so do not botter
cats = mw.ustring.gsub(cats,'%\n%[%[Category:Photographs without Wikidata item%]%]','')
return results .. cats
end
function p.art_photo(frame)
local args = read_input_parameters(frame) -- clean up input parameters
args.permission = args.permission or args.photo_license or args.photo_licence -- additional aliases
args.artwork_license = args.artwork_license or args.artwork_licence
args.source = args.source or args.source_
args.photo_license, args.photo_licence, args.artwork_licence, args.source_ = nil, nil, nil, nil
local results = {}
-- split input arguments
local args2 = {}
local fields = {['date']='photo_date', title='photo_title', description='photo_description', medium='photo_medium', dimensions='photo_dimensions',
institution='photo_institution', department='photo_department', id='photo_accession_number', photographer='photographer', inscriptions='photo_inscriptions',
source='source', other_versions='other_versions', other_fields ='other_fields', permission='photo_license', permission='permission'
}
for field1, field2 in pairs( fields ) do
if args[field2] then
args2[field1] = args[field2]
args [field2] = nil
end
end
for _, field in ipairs( {'lang', 'namespace', 'url', 'pagename'} ) do
args2[field] = args[field]
end
args.permission = args.artwork_license
args.artwork_license = nil
-- create object infobox
args.infobox = 'artwork'
local cats0 = verify_input_parameters(args)
local header = frame:expandTemplate{ title = 'Section header', args = { ["1"]=args.artwork_header or 'Object', lang=args.lang } }
table.insert(results, "===" .. header .. "===")
args.demo_image = 'Noun project - Mona Lisa - in frame.svg'
args.strict = false
local infobox, cats1 = p.create_infobox(args) -- call the inner "core" function
table.insert(results, infobox)
--create photograph infobox
args2.infobox = 'photograph'
local cats2 = verify_input_parameters(args2)
header = frame:expandTemplate{ title = 'Section header', args = { ["1"]='Photograph', lang=args.lang } }
table.insert(results, "===" .. header .. "===")
args2.demo_image = 'Breezeicons-actions-22-view-preview.svg'
args2.wikidata_cat = false
local infobox, cats3 = p.create_infobox(args2) -- call the inner "core" function
table.insert(results, infobox)
local fields = { title=1, medium=1, dimensions=1, institution=1, department=1, id=1, inscriptions=1 }
local cats4 = ''
for field, _ in pairs( args2 ) do
if fields[field] then
cats4 = '[[Category:Pages using "Art photo" template with rare parameters]]'
end
end
table.insert(results, cats0 .. cats1 .. cats2 .. cats3 .. cats4)
return table.concat(results, '\n')
end
function p.book(frame)
local args = read_input_parameters(frame)
args.infobox = 'book'
args.demo_image = 'Placeholder book.svg'
args.strict = false
args.place_of_publication = args.place_of_publication or args.city -- book specific aliases
args.publication_date = args.publication_date or args.date
args.source_ = args.source or args.source_
if args.isbn or args.lccn or args.oclc or args.bnf then
args.authority = frame:expandTemplate{ title = 'Book authority control', args = { ISBN=args.isbn, LCCN=args.lccn, OCLC=args.oclc, BNF=args.bnf, bare=1 } }
args.isbn, args.lccn, args.oclc, args.bnf = nil, nil, nil, nil
end
args.source, args.city, args.date = nil, nil, nil
local results, cats = p.create_infobox(args) -- call the inner "core" function
return results .. cats
end
return p