Module:Information/sandbox

--[[   __  __           _       _        ___        __                            _   _              |  \/  | ___   __| |_   _| | ___ _|_ _|_ __  / _| ___  _ __ _ __ ___   __ _| |_(_) ___  _ __   | |\/| |/ _ \ / _` | | | | |/ _ (_)| || '_ \| |_ / _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \  | |  | | (_) | (_| | |_| | |  __/_ | || | | |  _| (_) | |  | | | | | | (_| | |_| | (_) | | | | |_|  |_|\___/ \__,_|\__,_|_|\___(_)___|_| |_|_|  \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_| 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: ]] -- ======================================= -- === 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')
 * User:Jarekt - original version

-- ================================================== -- === 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(' %s: ', textLang, LangName) return mw.ustring.format(' %s %s ', 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(' %s ', args.pagename) local prmTag = mw.ustring.format(" (%s) ", 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 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('%s \n', id or '', lang, tag) cell2 = mw.ustring.format('\n%s ', param.td or , field or ) field = mw.ustring.format(' \n%s%s\n \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(' \n', style, table.concat(results)) results = mw.ustring.format(' \n%s\n%s\n ', 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 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 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; Error in '..				' template: unknown parameter "%s". ', table.concat(badField,'", "')) cats = cats .. '\n' 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 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; color: #202122; '..					'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(' %s\n%s\n ', tag1, dir, lang, tag2, tag3)}				cats = cats .. '\n'			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 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 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 work 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 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(' %s ',lang, label) end -- add 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(' %s ',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 "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 = ' (' .. core.getLabel(qual.role.id, lang) .. ')' end if qual.username and qual.authorStr then        --    author name string (P2093) & Wikimedia username (P4174) table.insert(creators, ..qual.authorStr....role) elseif qual.username and not qual.authorStr then -- no author name string (P2093) & Wikimedia username (P4174) table.insert(creators, ..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 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