Modiwl:WDloc
Documentation for this module may be created at Modiwl:WDloc/doc
--
-- Lua functions for returning locations
-- may be used in infoboxes, so implements whitelist, blacklist, etc.
--
p = {}
----------------------------------------
-- location returns the various different locations available in Wikidata
--
-- located on terrain feature (P706)
-- location (P276)
-- located in the administrative territorial entity (P131)
-- country (P17)
-- continent (P30)
--
p.location = function(frame)
local loc = frame.args.location or ""
if loc and (#loc == 0) then loc = nil end
-- can take a named parameter |qid which is the Wikidata ID for the article.
-- This will not normally be used because it's an expensive call.
local qid = frame.args.qid
if qid and (#qid == 0) then qid = nil end
-- The blacklist is passed in named parameter |suppressfields
local blacklist = frame.args.suppressfields
-- The whitelist is passed in named parameter |fetchwikidata
local whitelist = frame.args.fetchwikidata
-- The name of the field that this function is called from is passed in named parameter |name
local fieldname = frame.args.name
if blacklist then
-- The name is compulsory when blacklist is used, so return nil if it is not supplied
if not fieldname or (#fieldname == 0) then return nil end
-- If this field is on the blacklist, then return nil
if blacklist:find(fieldname) then return nil end
end
-- If we got this far then we're not on the blacklist
-- The blacklist overrides any locally supplied parameter as well
-- If a non-blank input parameter was supplied return it
if loc then return loc end
-- Otherwise see if this field is on the whitelist:
if not (whitelist and (whitelist == 'ALL' or whitelist:find(fieldname))) then
-- not on the whitelist so just return nil
return nil
end
-- get the full set of claims from Wikidata
local entity = mw.wikibase.getEntityObject(qid)
-- if there are no claims, return nothing
if not (entity and entity.claims) then return nil end
local sep = ", " -- internationalise / parameterise later
-- There may be multiple values for each of these five types of location
local geofeature, location, adminunit, country, continent
-- so set up tables for Qid, label, and article
-- for each of geofeature, location, adminunit, country, and continent
local geofeatureQid, locationQid, adminunitQid, countryQid, continentQid = {}, {}, {}, {}, {}
local geofeatureLbl, locationLbl, adminunitLbl, countryLbl, continentLbl = {}, {}, {}, {}, {}
local geofeatureArt, locationArt, adminunitArt, countryArt, continentArt = {}, {}, {}, {}, {}
-- located on terrain feature (P706)
if entity.claims["P706"] then
local props = entity.claims["P706"]
-- Check if any values have a preferred rank set
local prefflag = false
for k, v in pairs(props) do
if v.rank == "preferred" then prefflag = true end
end
for k, v in pairs(props) do
if v.rank == "preferred" or prefflag == false then
if v.mainsnak.datatype == "wikibase-item" and v.mainsnak.snaktype == "value" then
local wid = v.mainsnak.datavalue.value["id"]
local lbl = mw.wikibase.label(wid)
local art = mw.wikibase.sitelink(wid)
table.insert(geofeatureQid, wid)
if lbl then table.insert(geofeatureLbl, mw.text.nowiki(lbl)) end
if art then
if lbl then
table.insert(geofeatureArt, "[[" .. art .. "|" .. lbl .. "]]")
else
table.insert(geofeatureArt, "[[" .. art .. "|" .. art .. "]]")
end
end
end
end
end
if next(geofeatureArt) then
geofeature = table.concat(geofeatureArt, sep)
else
if next(geofeatureLbl) then
geofeature = table.concat(geofeatureLbl, sep)
end
end
end
-- location (P276)
if entity.claims["P276"] then
local props = entity.claims["P276"]
-- Check if any values have a preferred rank set
local prefflag = false
for k, v in pairs(props) do
if v.rank == "preferred" then prefflag = true end
end
for k, v in pairs(props) do
if v.rank == "preferred" or prefflag == false then
if v.mainsnak.datatype == "wikibase-item" and v.mainsnak.snaktype == "value" then
local wid = v.mainsnak.datavalue.value["id"]
local lbl = mw.wikibase.label(wid)
local art = mw.wikibase.sitelink(wid)
table.insert(locationQid, wid)
if lbl then table.insert(locationLbl, mw.text.nowiki(lbl)) end
if art then
if lbl then
table.insert(locationArt, "[[" .. art .. "|" .. lbl .. "]]")
else
table.insert(locationArt, "[[" .. art .. "|" .. art .. "]]")
end
end
end
end
end
if next(locationArt) then
location = table.concat(locationArt, sep)
else
if next(locationLbl) then
location = table.concat(locationLbl, sep)
end
end
end
-- located in the administrative territorial entity (P131)
if entity.claims["P131"] then
local props = entity.claims["P131"]
-- Check if any values have a preferred rank set
local prefflag = false
for k, v in pairs(props) do
if v.rank == "preferred" then prefflag = true end
end
for k, v in pairs(props) do
if v.rank == "preferred" or prefflag == false then
if v.mainsnak.datatype == "wikibase-item" and v.mainsnak.snaktype == "value" then
local wid = v.mainsnak.datavalue.value["id"]
local lbl = mw.wikibase.label(wid)
local art = mw.wikibase.sitelink(wid)
table.insert(adminunitQid, wid)
if lbl then table.insert(adminunitLbl, mw.text.nowiki(lbl)) end
if art then
if lbl then
table.insert(adminunitArt, "[[" .. art .. "|" .. lbl .. "]]")
else
table.insert(adminunitArt, "[[" .. art .. "|" .. art .. "]]")
end
end
end
end
end
if next(adminunitArt) then
adminunit = table.concat(adminunitArt, sep)
else
if next(adminunitLbl) then
adminunit = table.concat(adminunitLbl, sep)
end
end
end
-- country (P17)
if entity.claims["P17"] then
local props = entity.claims["P17"]
-- Check if any values have a preferred rank set
local prefflag = false
for k, v in pairs(props) do
if v.rank == "preferred" then prefflag = true end
end
for k, v in pairs(props) do
if v.rank == "preferred" or prefflag == false then
if v.mainsnak.datatype == "wikibase-item" and v.mainsnak.snaktype == "value" then
local wid = v.mainsnak.datavalue.value["id"]
local lbl = mw.wikibase.label(wid)
local art = mw.wikibase.sitelink(wid)
table.insert(countryQid, wid)
if lbl then table.insert(countryLbl, mw.text.nowiki(lbl)) end
if art then table.insert(countryArt, art) end
end
end
end
if next(countryArt) then
country = table.concat(countryArt, sep)
else
if next(countryLbl) then
country = table.concat(countryLbl, sep)
end
end
-- apparently it should be "US", unless there is no other location information in which case it's "United States"
if country == "United States" then country = "US" end
end
-- continent (P30)
if entity.claims["P30"] then
local props = entity.claims["P30"]
-- Check if any values have a preferred rank set
local prefflag = false
for k, v in pairs(props) do
if v.rank == "preferred" then prefflag = true end
end
for k, v in pairs(props) do
if v.rank == "preferred" or prefflag == false then
if v.mainsnak.datatype == "wikibase-item" and v.mainsnak.snaktype == "value" then
local wid = v.mainsnak.datavalue.value["id"]
local lbl = mw.wikibase.label(wid)
local art = mw.wikibase.sitelink(wid)
table.insert(continentQid, wid)
if lbl then table.insert(continentLbl, mw.text.nowiki(lbl)) end
if art then table.insert(continentArt, art) end
end
end
end
if next(continentArt) then
continent = table.concat(continentArt, sep)
else
if next(continentLbl) then
continent = table.concat(continentLbl, sep)
end
end
end
-- for now, let's construct a table of what we've found
local tbl = '<table class="wikitable">'
tbl = tbl .. '<tr><th>Type</th><th>Article</th><th>Label</th><th>QID</th></tr>'
tbl = tbl .. '<tr><th>Geo-feature</th><td>' .. (table.concat(geofeatureArt, sep) or "") .. '</td><td>' .. (table.concat(geofeatureLbl, sep) or "") .. '</td><td>' .. (table.concat(geofeatureQid, sep) or "") .. '</td></tr>'
tbl = tbl .. '<tr><th>Location</th><td>' .. (table.concat(locationArt, sep) or "") .. '</td><td>' .. (table.concat(locationLbl, sep) or "") .. '</td><td>' .. (table.concat(locationQid, sep) or "") .. '</td></tr>'
tbl = tbl .. '<tr><th>Admin unit</th><td>' .. (table.concat(adminunitArt, sep) or "") .. '</td><td>' .. (table.concat(adminunitLbl, sep) or "") .. '</td><td>' .. (table.concat(adminunitQid, sep) or "") .. '</td></tr>'
tbl = tbl .. '<tr><th>Country</th><td>' .. (table.concat(countryArt, sep) or "") .. '</td><td>' .. (table.concat(countryLbl, sep) or "") .. '</td><td>' .. (table.concat(countryQid, sep) or "") .. '</td></tr>'
tbl = tbl .. '<tr><th>Continent</th><td>' .. (table.concat(continentArt, sep) or "") .. '</td><td>' .. (table.concat(continentLbl, sep) or "") .. '</td><td>' .. (table.concat(continentQid, sep) or "") .. '</td></tr>'
tbl = tbl .. '</table>'
-- best candidate for location
local wdloc = ""
local wdloctbl = {}
-- geo-feature and location are mutually exclusive, so we order doesn't matter
-- then add the others: adminunit, country
-- if none of them, fall back to continent alone
if geofeature then table.insert(wdloctbl, geofeature) end
if location then table.insert(wdloctbl, location) end
if adminunit then table.insert(wdloctbl, adminunit) end
if country then table.insert(wdloctbl, country) end
if next(wdloctbl) then
wdloc = table.concat(wdloctbl, ", ")
else
if continent then wdloc = continent end
end
-- deal with US vs United States as sole value
if wdloc == "US" then wdloc = "United States" end
return tbl .. "<p>Location = " .. wdloc .. "</p>"
end
return p