Module:LocationAndCountry
Εμφάνιση
Τεκμηρίωση module[δημιουργία] [ανανέωση]
-- will display a wikidata property representing a location, followed by a comma and the name of the country, both with wikilinks
-- the first argument specifies the parameter to be displayed
-- the second argument specifies the entity ID
-- the third argument specifies a timestamp showing the moment in time for which the country is to be identified
-- the fourth argument specifies the maximum number of values to be processed (default 1)
-- the fifth argument specifies the separator to use when displaying multiple values
local getArgs = require('Module:Arguments').getArgs
local wikidata = require('Module:Wikidata')
local StringUtils = require('Module:StringUtils')
local GregorianDate = require('Module:GregorianDate')
local Date = require('Module:Date')
local TableTools = require('Module:TableTools')
local appendToString = StringUtils._appendToString
local emptyToNil = StringUtils._emptyToNil
local ESCALATABLE_LOCATION_ENTITIES = { -- if this is one of the types of the location from Wikidata, then we skip and escalate it to the administrative unit
'Q16917', --hospital
'Q1059324', -- university hospital
'Q702842', --municipal arrondissement (France)
'Q15921300', --sector of Bucharest
}
local ADMIN_UNIT_ATTRACTOR_ENTITIES = { -- if this is one of the types of the location from Wikidata, then we also pull in the administrative unit
'Q532', -- village
'Q659103', -- commune of Romania
}
local p = {}
local function extractGregorianDateFromSnak(snak, hms)
local afterDate = wikidata.extractDateFromClaim(snak)
local afterDateGregorian = GregorianDate.convertToGregorianIfInInterval(afterDate)
afterDateGregorian.hour = hms[1]
afterDateGregorian.min = hms[2]
afterDateGregorian.sec = hms[3]
after = tonumber(mw.language.getContentLanguage():formatDate('U', os.date('%d %B %Y %H:%M:%S', os.time(afterDateGregorian)), nil))
return after
end
local function getShortOrOfficialNameRetrieverClosure(ts)
return function(object)
if not object then return nil end -- just to be safe: this callback should only be called with existing objects
local correspondingShortNameClaim = wikidata.findClaimForTimestamp(object.id, 'P1813', ts)
if correspondingShortNameClaim then return correspondingShortNameClaim.mainsnak.datavalue.value.text end
local correspondingOfficialNameClaim = wikidata.findClaimForTimestamp(object.id, 'P1448', ts)
if ts and correspondingOfficialNameClaim then return correspondingOfficialNameClaim.mainsnak.datavalue.value.text end
end
end
local function getOfficialNameRetrieverClosure(ts)
return function(object)
if not object then return nil end -- just to be safe: this callback should only be called with existing objects
local correspondingOfficialNameClaim = wikidata.findClaimForTimestamp(object.id, 'P1448', ts)
if ts and correspondingOfficialNameClaim then return correspondingOfficialNameClaim.mainsnak.datavalue.value.text end
end
end
local function getShortNameRetrieverClosure(ts)
return function(object)
if not object then return nil end -- just to be safe: this callback should only be called with existing objects
local correspondingShortNameClaim = wikidata.findClaimForTimestamp(object.id, 'P1813', ts)
if correspondingShortNameClaim then return correspondingShortNameClaim.mainsnak.datavalue.value.text end
end
end
local function getAdminUnitForTimestamp(locationId, ts)
local unitClaim = wikidata.findClaimForTimestamp(locationId, 'P131', ts)
if unitClaim and unitClaim.mainsnak and unitClaim.mainsnak.snaktype == 'value' then
return unitClaim.mainsnak.datavalue.value.id
else
local unitId = wikidata.loadOneValueInChain({locationId, 'P131', 'raw'})
if unitId and mw.ustring.len(unitId) > 0 then
return unitId
end
end
return nil
end
p.displayFromParams = function(param, entity, timestamp, maxvalues, separator)
if param == nil then return '' end
local claims = nil
local workingEntityId = nil
if type(entity) == 'table' then
workingEntityId = entity.id
claims = entity:getBestStatements(param)
else
workingEntityId = entity
if not workingEntityId then workingEntityId = mw.wikibase.getEntityIdForCurrentPage() end
if type(entity) == 'number' then workingEntityId = 'Q' .. tostring(entity) end
if workingEntityId == nil then return '' end
claims = mw.wikibase.getBestStatements(workingEntityId, param)
end
local ts = nil
if timestamp then
if type(timestamp) == 'string' and mw.ustring.gmatch(timestamp, 'P%d+') then
local wdDates = wikidata.findDateValues(timestamp, workingEntityId)
if wdDates and 0 < #wdDates then
local wdDateIdx = 1
while wdDateIdx <= #wdDates and (wdDates[wdDateIdx].claim.type ~= 'statement' or wdDates[wdDateIdx].claim.mainsnak.snaktype ~= 'value') do
wdDateIdx = wdDateIdx + 1
end
if wdDateIdx <= #wdDates and (wdDates[wdDateIdx].claim.type == 'statement' and wdDates[wdDateIdx].claim.mainsnak.snaktype == 'value') then
wdDates[wdDateIdx] = GregorianDate.convertToGregorianIfInInterval(wdDates[wdDateIdx])
ts = wdDates[wdDateIdx]
end
end
end
if ts == nil and type(timestamp) == 'string' then
ts = DateUtils.parseYear(timestamp)
elseif ts == nil and type(timestamp) == 'table' and timestamp.year then
ts = timestamp
end
end
local valueList = {}
local valueCount = 0
if claims and 0 < #claims then
for claimIdx, actualClaim in pairs(claims) do
valueCount = valueCount + 1
local locationEntitiesIds = {}
local locationNames = {}
local skipActualLocation = false
if actualClaim.mainsnak and actualClaim.mainsnak.snaktype == 'value' and actualClaim.mainsnak.datavalue.type == 'wikibase-entityid' then
local locationEntityId = actualClaim.mainsnak.datavalue.value.id
local seekAdminUnit
repeat
seekAdminUnit = false
repeat
skipActualLocation = false
--what is this location?
local locationInstanceOfClaims = mw.wikibase.getBestStatements(locationEntityId, 'P31')
if locationInstanceOfClaims then for _,eachInstOfClaim in ipairs(locationInstanceOfClaims) do
if eachInstOfClaim.mainsnak and eachInstOfClaim.mainsnak.snaktype == 'value' and eachInstOfClaim.mainsnak.datavalue.type == 'wikibase-entityid' then
mw.logObject(eachInstOfClaim.mainsnak.datavalue.value.id, '[LocationAndCountry] location is a')
if TableTools.contains(ESCALATABLE_LOCATION_ENTITIES, eachInstOfClaim.mainsnak.datavalue.value.id) then --escalatable?
skipActualLocation = true
end
if TableTools.contains(ADMIN_UNIT_ATTRACTOR_ENTITIES, eachInstOfClaim.mainsnak.datavalue.value.id) then --do we also pull the admin unit?
seekAdminUnit = true
end
end
end end -- end for end if
if skipActualLocation then
locationEntityId = getAdminUnitForTimestamp(locationEntityId, ts)
else
table.insert(locationEntitiesIds, locationEntityId)
locationNames[locationEntityId] = wikidata.findLinkToItemWithCallback(locationEntityId, false, getOfficialNameRetrieverClosure(ts))
end
until not skipActualLocation
--attempt to also load administrative unit, but only if present as a qualifier
local unitQualifier = actualClaim.qualifiers and actualClaim.qualifiers['P131'] and actualClaim.qualifiers['P131'][1]
if unitQualifier and unitQualifier.snaktype == 'value' then
table.insert(locationEntitiesIds, unitQualifier.datavalue.value.id)
locationNames[unitQualifier.datavalue.value.id] = wikidata.findLinkToItemWithCallback(unitQualifier.datavalue.value.id, false, getShortOrOfficialNameRetrieverClosure(ts))
seekAdminUnit = false
end
--... or something happened that we have to look for it
if seekAdminUnit then
local adminUnitId = getAdminUnitForTimestamp(locationEntityId, ts)
if adminUnitId then
table.insert(locationEntitiesIds, adminUnitId)
locationEntityId = adminUnitId
else
seekAdminUnit = false
end
end
until not seekAdminUnit
-- attempt to identify country in the qualifier first, but if it's not, go to the entity
local countryQualifier = actualClaim.qualifiers and actualClaim.qualifiers['P17'] and actualClaim.qualifiers['P17'][1]
local countryId = nil
if countryQualifier and countryQualifier.snaktype == 'value' then
table.insert(locationEntitiesIds, countryQualifier.datavalue.value.id)
locationNames[countryQualifier.datavalue.value.id] = wikidata.findLinkToItemWithCallback(countryQualifier.datavalue.value.id, false, getShortOrOfficialNameRetrieverClosure(ts))
else
local countryClaim = nil
countryClaim = wikidata.findClaimForTimestamp(locationEntityId, 'P17', ts)
if countryClaim and countryClaim.mainsnak and countryClaim.mainsnak.snaktype == 'value' then
countryId = countryClaim.mainsnak.datavalue.value.id
table.insert(locationEntitiesIds, countryId)
elseif not countryClaim then
countryId = wikidata.loadOneValueInChain({locationEntityId, 'P17', 'raw'})
if countryId and mw.ustring.len(countryId) > 0 then
table.insert(locationEntitiesIds, countryId)
end
end
end
locationEntitiesIds = TableTools.removeDuplicates(locationEntitiesIds)
local locationNamesList = {}
for _,eachLocationId in ipairs(locationEntitiesIds) do
if not locationNames[eachLocationId] then
locationNames[eachLocationId] = wikidata.findLinkToItemWithCallback(eachLocationId, false, getShortNameRetrieverClosure(ts))
end
table.insert(locationNamesList, locationNames[eachLocationId])
end
if 0 < #locationNamesList then
table.insert(
valueList,
appendToString({
emptyToNil({table.concat(locationNamesList, ', ')}),
wikidata.outputReferences(actualClaim)
})
)
end
end
end
end
if #valueList == 0 then return '' end
if separator == nil then separator = '; ' end
if maxvalues > #valueList then maxvalues = #valueList end
return table.concat(valueList, separator, 1, maxvalues)
end
p.displayFromArgs = function(args)
local param = nil
local entity = nil
local timestamp = nil
local maxvalues = 1
local separator = '; '
if args[1] or args['param'] then
param = args[1] or args['param']
end
if args[2] or args['entityId'] then
entity = args[2] or args['entityId']
end
if args[3] or args['timestamp'] then
timestamp = args[3] or args['timestamp']
end
if args[4] or args['maxvalues'] then
maxvalues = tonumber(args[4] or args['maxvalues'])
end
if args[5] or args['separator'] then
separator = args[5] or args['separator']
end
return p.displayFromParams(param, entity, timestamp, maxvalues, separator)
end
p.displayFromFrame = function(frame)
local args = getArgs(frame, { frameOnly = true })
return p.displayFromArgs(args)
end
p.displayFromParentFrame = function(frame)
local args = getArgs(frame, { parentOnly = true})
return p.displayFromArgs(args)
end
return p