Module:External links and Module:External links/sandbox: Difference between pages
Appearance
(Difference between pages)
Content deleted Content added
S.A. Julio (talk | contribs) Reduce number of links shown by default. Per WP:LINKFARM: Wikipedia is not a repository of links... excessive lists can dwarf articles and detract from the purpose of Wikipedia; Per WP:ELPOINTS: Links in the "External links" section should be kept to a minimum |
Remove paranoid checks for if linkTemplate.[x] exists but is an empty string - that should be the config's problem, and if anything this should just error in that situation |
||
Line 1: | Line 1: | ||
require('strict') |
require('strict') |
||
-- local genitive = require('Module:Genitive')._genitive |
-- local genitive = require('Module:Genitive')._genitive |
||
local |
local contLangCode = mw.language.getContentLanguage():getCode() |
||
local cmodule = {} |
local cmodule = {} |
||
local conf = require 'Module:External links/conf'( |
local conf = require 'Module:External links/conf'(contLangCode) |
||
local hasdatafromwikidata = false |
local hasdatafromwikidata = false |
||
local hasdatafromlocal = false |
local hasdatafromlocal = false |
||
local haswikidatalink = true -- we assume |
local haswikidatalink = true -- whether or not this page has a wikidata entity(?); we assume there is one at first |
||
local p = {} |
local p = {} |
||
local function getLabel(entity, use_genitive, pagetitle) |
local function getLabel(entity, use_genitive, pagetitle) |
||
local label = ( |
local label = (pagetitle ~= '') and pagetitle or nil |
||
if not label and not entity then |
if not label and not entity then |
||
label = mw.title.getCurrentTitle().text |
label = mw.title.getCurrentTitle().text |
||
elseif not label then |
elseif not label then |
||
label = mw.wikibase. |
label = mw.wikibase.getLabel(entity.id) or mw.title.getCurrentTitle().text |
||
end |
end |
||
-- return use_genitive and genitive(label, 'sitt') or label |
-- return use_genitive and genitive(label, 'sitt') or label |
||
Line 29: | Line 29: | ||
local function stringFormatter( datavalue ) |
local function stringFormatter( datavalue ) |
||
if datavalue == nil or datavalue |
if datavalue == nil or datavalue.type ~= 'string' then |
||
return nil |
return nil |
||
end |
end |
||
return datavalue.value |
return datavalue.value |
||
end |
end |
||
local pval = {} |
|||
pval.P1793 = { -- format as a regular expression |
|||
types = { |
|||
snaktype = 'value', |
|||
datatype = 'string', |
|||
}, |
|||
} |
|||
pval.P407 = { -- language of work or name |
|||
types = { |
|||
snaktype = 'value', |
|||
datatype = 'wikibase-item', |
|||
datavalue = { |
|||
type = 'wikibase-entityid', |
|||
} |
|||
}, |
|||
} |
|||
pval.P364 = { -- original language of work |
|||
types = { |
|||
snaktype = 'value', |
|||
datatype = 'wikibase-item', |
|||
datavalue = { |
|||
type = 'wikibase-entityid', |
|||
} |
|||
}, |
|||
} |
|||
pval.P218 = { -- ISO 639-1 language |
|||
types = { |
|||
snaktype = 'value', |
|||
datatype = 'external-id', |
|||
datavalue = { |
|||
type = 'string', |
|||
} |
|||
}, |
|||
} |
|||
pval.P305 = { -- IETF language tag |
|||
types = { |
|||
snaktype = 'value', |
|||
datatype = 'external-id', |
|||
datavalue = { |
|||
type = 'string', |
|||
} |
|||
}, |
|||
} |
|||
pval.P582 = { -- end time |
|||
types = { |
|||
snaktype = 'value', |
|||
datatype = 'time', |
|||
datavalue = { |
|||
type = 'string', |
|||
} |
|||
}, |
|||
} |
|||
-- This is a really makeshift crappy converter, but it'll do some basic |
-- This is a really makeshift crappy converter, but it'll do some basic |
||
-- conversion from PCRE to Lua-style patterns (note that this only work |
-- conversion from PCRE to Lua-style patterns (note that this only work |
||
-- in very few cases) |
-- in very few cases) |
||
local function |
local function regexConverterTest( regex, str ) |
||
regex = regex:gsub("\\d{(%d)}", function(num) return string.rep("%d", num) end) |
|||
local output = regex |
|||
output = string.gsub(output, "\\d{2}", "%%d%%d") |
|||
output = string.gsub(output, "\\d{3}", "%%d%%d%%d") |
|||
output = string.gsub(output, "\\d{4}", "%%d%%d%%d%%d") |
|||
output = string.gsub(output, "\\d{5}", "%%d%%d%%d%%d%%d") |
|||
output = string.gsub(output, "\\d{6}", "%%d%%d%%d%%d%%d%%d") |
|||
output = string.gsub(output, "\\d{7}", "%%d%%d%%d%%d%%d%%d%%d") |
|||
output = string.gsub(output, "\\d{8}", "%%d%%d%%d%%d%%d%%d%%d%%d") |
|||
output = string.gsub(output, "\\d", "%%d") |
|||
return string.find(str, '^' .. regex .. '$') |
|||
return output |
|||
end |
end |
||
local function getFormatterUrl( prop, value ) |
local function getFormatterUrl( prop, value ) |
||
local |
local fUrl = "" |
||
local statements = mw.wikibase.getBestStatements(prop, "P1630") |
|||
local tail = "" |
|||
local entity = mw.wikibase.getEntity(prop) |
|||
-- to avoid deep tests |
-- to avoid deep tests |
||
if |
if #statements == 0 then |
||
return |
return "" |
||
end |
end |
||
-- get the claims for this entity |
|||
local statements = entity.claims['P1630'] -- formatter URL |
|||
-- to avoid deep tests |
|||
if not statements then |
|||
return head |
|||
end |
|||
local formatters = {} |
|||
-- let's go through the claims |
-- let's go through the claims |
||
for _, claim in ipairs( statements ) do |
for _, claim in ipairs( statements ) do |
||
local mainsnak = claim.mainsnak -- nil will be indexed if it doesn't exist |
|||
-- to avoid deep tests |
|||
--[[ |
|||
if not claim then |
|||
Checks P1793 (format as a regular expression) qualifier of formatter URL to |
|||
claim = {} |
|||
check if the given string matches the formatter URL's regex; |
|||
end |
|||
will prioritize that formatter URL if true |
|||
local valid = claim['type'] == 'statement' |
|||
]] |
|||
and claim['rank'] ~= 'deprecated' |
|||
local qualifiers = claim.qualifiers or {} |
|||
if valid then |
|||
local qualid = 'P1793' -- format as a regular expression |
|||
local mainsnak = claim.mainsnak or {} |
|||
if qualifiers[qualid] then |
|||
local preferred = claim['rank'] == 'preferred' |
|||
-- we have a regex qualifier, traverse all snaks |
|||
-- get any qualifiers for this claim (we are interested in P1793 for |
|||
for _, qualsnak in ipairs( qualifiers[qualid] ) do |
|||
-- indication of which claim is correct) |
|||
if qualsnak.snaktype == 'value' |
|||
local qualifiers = claim.qualifiers or {} |
|||
and regexConverterTest(qualsnak.datavalue.value, value) |
|||
-- now let's check the qualifier we are interested in |
|||
then |
|||
local qualid = 'P1793' -- format as a regular expression |
|||
-- it matched, this is correct and overrides any other. |
|||
-- if the claim has this qualifier |
|||
fUrl = mainsnak.datavalue.value |
|||
if qualifiers[qualid] then |
|||
break |
|||
-- it's here, let's check it out! |
|||
local items = {} |
|||
-- traverse all snaks in this qualifier |
|||
for _, qualsnak in ipairs( qualifiers[qualid] ) do |
|||
if qualsnak and pval[qualid] then |
|||
--mw.log("qualsnak = " .. dump(qualsnak)) |
|||
-- check if the snak is of the correct snaktype and datatype |
|||
local valid = qualsnak.snaktype == pval[qualid].types.snaktype |
|||
and qualsnak.datatype == pval[qualid].types.datatype |
|||
if valid then |
|||
-- we'll have to convert the regex to Lua-style |
|||
local regex = regexConverter(qualsnak.datavalue.value) |
|||
local test = string.match( value, '^'..regex..'$' ) |
|||
if test then |
|||
-- it matched, this is correct and overrides any other. |
|||
if preferred then |
|||
head = mainsnak.datavalue.value |
|||
else |
|||
tail = mainsnak.datavalue.value |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
else |
|||
-- we don't have any qualifier, is it preferred? |
|||
if (head == '' and preferred) or (tail == '' and not preferred) then |
|||
-- if we don't have any other, use this one |
|||
if preferred and head == '' then |
|||
head = mainsnak.datavalue.value |
|||
elseif not preferred and tail == '' then |
|||
tail = mainsnak.datavalue.value |
|||
end |
|||
end |
end |
||
end |
end |
||
elseif fUrl == '' then -- if we don't have any other, use this one |
|||
fUrl = mainsnak.datavalue.value |
|||
end |
end |
||
end |
end |
||
return |
return fUrl |
||
end |
end |
||
local function getLanguageData(prop, qid) |
local function getLanguageData(prop, qid, separator) |
||
-- Formerly outputted a table, but this function was always run through table.concat() when invoked, so it has been simplified to yield a string |
|||
local head = {} |
|||
separator = separator or '' |
|||
local tail = {} |
|||
local output = '' |
|||
-- mw.log("getLanguageData, prop="..dump(prop).." qid="..dump(qid)) |
|||
if not mw.wikibase.entityExists(qid) then -- yield error, which would originally happen because table.concat(nil) errors |
|||
-- get the entity we are checking |
|||
error("getLanguageData was given a nonexistent entity") |
|||
local entity = mw.wikibase.getEntityObject(qid) |
|||
-- to avoid deep tests |
|||
if not entity then |
|||
return nil |
|||
end |
end |
||
-- get claims |
|||
local statements = mw.wikibase.getBestStatements(qid, prop) |
|||
return {} |
|||
end |
|||
-- get the claims for this entity |
|||
local statements = entity.claims[prop] |
|||
-- to avoid deep tests |
-- to avoid deep tests |
||
if |
if #statements == 0 then |
||
return |
return '' |
||
end |
end |
||
-- mw.log("getLanguageData going through claims="..dump(statements)) |
-- mw.log("getLanguageData going through claims="..dump(statements)) |
||
-- let's go through the claims |
-- let's go through the claims |
||
for _, claim in ipairs( statements ) do |
for _, claim in ipairs( statements ) do |
||
local mainsnak = claim.mainsnak |
|||
-- to avoid deep tests |
|||
if |
if mainsnak.snaktype == 'value' then |
||
-- if this is the correct P-value, dive into it and get P218 (ISO 639-1) |
|||
claim = {} |
|||
if prop == 'P364' then -- original language of work |
|||
end |
|||
output = output .. separator .. getLanguageData('P218', mainsnak.datavalue.value.id, conf:a('mod-filter-separator')) |
|||
local valid = claim['type'] == 'statement' |
|||
elseif prop == 'P218' or prop == 'P305' then -- ISO 639-1 code or IETF language tag |
|||
and claim['rank'] ~= 'deprecated' |
|||
output = output .. separator .. stringFormatter(mainsnak.datavalue) |
|||
if valid then |
|||
local mainsnak = claim.mainsnak or {} |
|||
local preferred = claim['rank'] == 'preferred' |
|||
-- verify the item is what we expect |
|||
local valid = mainsnak.snaktype == pval[prop].types.snaktype |
|||
and mainsnak.datatype == pval[prop].types.datatype |
|||
and mainsnak.datavalue.type == pval[prop].types.datavalue.type |
|||
if valid then |
|||
-- mw.log("getLanguageData claim is valid="..dump(claim)) |
|||
-- if this is the correct P-value, dive into it and get P218 (ISO 639-1) |
|||
if mainsnak.property == 'P364' then -- original language of work |
|||
if preferred then |
|||
head[#head+1] = table.concat(getLanguageData('P218', 'Q'..mainsnak.datavalue.value['numeric-id']), conf:a('mod-filter-separator')) |
|||
else |
|||
tail[#tail+1] = table.concat(getLanguageData('P218', 'Q'..mainsnak.datavalue.value['numeric-id']), conf:a('mod-filter-separator')) |
|||
end |
|||
elseif mainsnak.property == 'P218' or mainsnak.property == 'P305' then -- ISO 639-1 code or IETF language tag |
|||
if preferred then |
|||
head[#head+1] = stringFormatter(mainsnak.datavalue) |
|||
else |
|||
tail[#tail+1] = stringFormatter(mainsnak.datavalue) |
|||
end |
|||
end |
|||
end |
end |
||
end |
end |
||
end |
end |
||
return output |
|||
-- mw.log("getLanguageData returning head="..dump(head).." tail="..dump(tail)) |
|||
return #head>0 and head or tail |
|||
end |
end |
||
local langqvalorder = {'P407','P364'} |
local langqvalorder = {'P407','P364'} -- check `language of work or name` first, `original language of film or TV show` second |
||
local otherqvalorder = {'P582'} |
local otherqvalorder = {'P582'} |
||
local function getValuesFromWikidata( |
local function getValuesFromWikidata(linkTemplate) |
||
local |
local output = {} |
||
-- mw.log("getValuesFromWikidata, linkTemplate="..dump(linkTemplate)) |
|||
local tail = {} |
|||
-- get statements |
|||
-- mw.log("getValuesFromWikidata, props="..dump(props)) |
|||
local entity = mw.wikibase.getEntity() |
|||
-- check if the entity exists |
|||
local entity = mw.wikibase.getEntityObject() |
|||
-- TODO: check if we can skip distinguishing between no entity vs. no statements |
|||
-- to avoid deep tests |
|||
if not entity then |
if not entity then -- check if the entity exists |
||
--mw.log("getValuesFromWikidata no entity") |
|||
return nil |
return nil |
||
end |
end |
||
local statements = entity:getBestStatements(linkTemplate.prop) |
|||
if not entity.claims or not props or not props.prop or props.prop == '' then |
|||
--mw.log("getValuesFromWikidata no claims or no props") |
|||
return {} |
|||
end |
|||
-- get the claims for this entity |
|||
local statements = entity.claims[props.prop] |
|||
-- to avoid deep tests |
-- to avoid deep tests |
||
if |
if #statements == 0 then |
||
return {} |
return {} |
||
end |
end |
||
-- let's go through the claims |
-- let's go through the claims |
||
for _, claim in ipairs( statements ) do |
for _, claim in ipairs( statements ) do |
||
output[#output + 1] = { value=stringFormatter(claim.mainsnak.datavalue) } |
|||
-- to avoid deep tests |
|||
--- Check if the linkTemplate wants us to search a qualifier for languagedata |
|||
if not claim then |
|||
claim = {} |
|||
local qualifiers = claim.qualifiers or {} |
|||
end |
|||
-- get the content of the claim (the identifier) |
|||
local valid = claim['type'] == 'statement' |
|||
local langcode = linkTemplate.langcode |
|||
and claim['rank'] ~= 'deprecated' |
|||
if |
if langcode |
||
and string.find(langcode, "[pP]%d+") |
|||
-- mw.log("getValuesFromWikidata valid claim="..dump(claim)) |
|||
then |
|||
local mainsnak = claim.mainsnak or {} |
|||
-- this is a P-value for language-code, so we'll check qualifiers for languagedata |
|||
local preferred = claim['rank'] == 'preferred' |
|||
-- get the content of the claim (the identifier) |
|||
local langcode = props.langcode |
|||
local checklangcode = nil |
|||
if props.langcode and props.langcode ~= '' then |
|||
checklangcode = string.find(langcode, "([pP]%d+)") |
|||
end |
|||
if checklangcode and checklangcode ~= "" then |
|||
-- this is a P-value for language-code, so we'll check qualifiers for languagedata |
|||
-- first get any qualifiers |
|||
local qualifiers = claim.qualifiers or {} |
|||
for _, qualid in ipairs( langqvalorder ) do |
|||
-- if the claim has this qualifier |
|||
if qualifiers[qualid] then |
|||
-- it's here, let's check it out! |
|||
local items = {} |
|||
-- traverse all snaks in this qualifier |
|||
for _, qualsnak in ipairs( qualifiers[qualid] ) do |
|||
if qualsnak and pval[qualid] then |
|||
-- mw.log("qualsnak = " .. dump(qualsnak)) |
|||
-- check if the snak is of the correct snaktype and datatype |
|||
local valid = qualsnak.snaktype == pval[qualid].types.snaktype |
|||
and qualsnak.datatype == pval[qualid].types.datatype |
|||
if valid then |
|||
-- now get the actual data |
|||
langcode = table.concat(getLanguageData('P305', 'Q'..qualsnak.datavalue.value['numeric-id']), '') |
|||
end |
|||
end |
|||
end |
|||
end |
|||
-- mw.log("langcode is now="..dump(langcode)) |
|||
end |
|||
if string.find(langcode, "([pP]%d+)") then |
|||
-- we still don't have any langcode, so we default to "en" |
|||
langcode = nil |
|||
end |
|||
end |
|||
local stillvalid = true |
|||
-- we should check a couple of other qualifiers as well |
|||
-- first get any qualifiers |
-- first get any qualifiers |
||
for _, qualid in ipairs( langqvalorder ) do |
|||
local qualifiers = claim.qualifiers or {} |
|||
for _, qualid in ipairs( otherqvalorder ) do |
|||
-- if the claim has this qualifier |
-- if the claim has this qualifier |
||
if qualifiers[qualid] then |
if qualifiers[qualid] then |
||
-- it's here, let's check it out! |
-- it's here, let's check it out! |
||
local items = {} |
|||
-- traverse all snaks in this qualifier |
-- traverse all snaks in this qualifier |
||
for _, qualsnak in ipairs( qualifiers[qualid] ) do |
for _, qualsnak in ipairs( qualifiers[qualid] ) do |
||
if qualsnak |
if qualsnak.snaktype == 'value' then |
||
-- |
-- now get the actual data |
||
langcode = getLanguageData('P305', qualsnak.datavalue.value.id) |
|||
-- check if the snak is of the correct snaktype and datatype |
|||
local valid = qualsnak.snaktype == pval[qualid].types.snaktype |
|||
and qualsnak.datatype == pval[qualid].types.datatype |
|||
if not valid then |
|||
-- sorry, this is not correct |
|||
mw.log("qualsnak = INCORRECT") |
|||
stillvalid = false |
|||
end |
|||
end |
end |
||
end |
end |
||
Line 344: | Line 156: | ||
-- mw.log("langcode is now="..dump(langcode)) |
-- mw.log("langcode is now="..dump(langcode)) |
||
end |
end |
||
if |
if string.find(langcode, "[pP]%d+") then |
||
-- we still don't have any langcode, so we default to "en" |
|||
if preferred then |
|||
langcode = nil |
|||
head[#head+1] = { value=stringFormatter(mainsnak.datavalue) } |
|||
if langcode and langcode ~= '' then |
|||
head[#head]['langcode'] = langcode |
|||
end |
|||
else |
|||
tail[#tail+1] = { value=stringFormatter(mainsnak.datavalue) } |
|||
if langcode and langcode ~= '' then |
|||
tail[#tail]['langcode'] = langcode |
|||
end |
|||
end |
|||
end |
end |
||
end |
|||
--[[ EDITOR'S NOTE: |
|||
I trimmed the `stillvalid` check thinking it was just doing stuff already handled by Wikibase's built-in input constraints. |
|||
However, it would've also aborted the loop iteration if "end time" was provided with `no value` or `unknown value`. |
|||
I'm not sure if that functionality would've had any purpose, given how cryptic this function is. |
|||
]] |
|||
if langcode and langcode ~= '' then |
|||
output[#output].langcode = langcode |
|||
end |
end |
||
end |
end |
||
-- mw.log("getValuesFromWikidata returning head="..dump(head).." tail="..dump(tail)) |
-- mw.log("getValuesFromWikidata returning head="..dump(head).." tail="..dump(tail)) |
||
return |
return output |
||
end |
end |
||
local function findMainLinksOnWikidata( |
local function findMainLinksOnWikidata(linkTemplate, pagetitle, short_links) |
||
local output = {} |
local output = {} |
||
local pid = nil |
|||
-- get the entity we are checking |
-- get the entity we are checking |
||
local entity = mw.wikibase. |
local entity = mw.wikibase.getEntity() |
||
-- to avoid deep tests |
-- to avoid deep tests |
||
if not entity then |
if not entity then |
||
return nil |
return nil |
||
end |
end |
||
local values = getValuesFromWikidata( |
local values = getValuesFromWikidata(linkTemplate) |
||
for _, value in ipairs( values ) do |
for _, value in ipairs( values ) do |
||
local verified_value = |
local verified_value = value.value |
||
if |
if not (linkTemplate.regex and |
||
regexConverterTest(linkTemplate.regex, value.value)) |
|||
-- we have a local defined regex, so this will have to pass first |
|||
then |
|||
-- maybe we'll have to convert the regex to Lua-style |
|||
output[#output+1] = { |
|||
local regex = regexConverter(props.regex) |
|||
langcode = value.langcode, |
|||
category = {} |
|||
--mw.log("testing with "..regex.. " and test="..dump(test).." and value="..id) |
|||
} |
|||
if test then |
|||
-- Search for a url formatter |
|||
-- it matched, this is correct and overrides any other. |
|||
verified_value = value.value |
|||
end |
|||
else |
|||
verified_value = value.value |
|||
end |
|||
if verified_value then |
|||
local url = '' |
local url = '' |
||
if linkTemplate.url_f then |
|||
output[#output+1] = {} |
|||
-- we have a locally defined url-formatter function from the config, use it as first priority |
|||
output[#output].langcode = value.langcode |
|||
url = linkTemplate.url_f(verified_value) |
|||
output[#output].category = {} |
|||
if linkTemplate.track and not string.find(linkTemplate.langcode, "[pP]%d+") then |
|||
if props.url_f then |
|||
output[#output].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-wd'), linkTemplate.prop):plain() |
|||
-- we have a local defined url-formatter function, use it as first priority |
|||
elseif linkTemplate.track then |
|||
url = props.url_f(verified_value) |
|||
output[#output].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-wd'), linkTemplate.prop):plain() |
|||
if props.track and not string.find(props.langcode, "([pP]%d+)") then |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-wd'), props.prop):plain() |
|||
elseif props.track then |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain() |
|||
end |
end |
||
elseif |
elseif linkTemplate.url then |
||
-- we have a |
-- we have a locally defined url-formatter string from the config, use it as second priority |
||
url = mw.message.newRawMessage( |
url = mw.message.newRawMessage(linkTemplate.url, verified_value):plain() |
||
if |
if linkTemplate.track and not string.find(linkTemplate.langcode, "[pP]%d+") then |
||
output[#output].category[ |
output[#output].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-wd'), linkTemplate.prop):plain() |
||
elseif |
elseif linkTemplate.track then |
||
output[#output].category[ |
output[#output].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-wd'), linkTemplate.prop):plain() |
||
end |
end |
||
else |
else |
||
-- config has no url formatter; check if Wikidata has one on the property |
|||
-- get the formatvalue from the property, if it exists |
|||
local formatterUrl = getFormatterUrl( |
local formatterUrl = getFormatterUrl(linkTemplate.prop, verified_value) |
||
if formatterUrl ~= '' then |
if formatterUrl ~= '' then |
||
url = mw.message.newRawMessage(formatterUrl, verified_value):plain() |
url = mw.message.newRawMessage(formatterUrl, verified_value):plain() |
||
if |
if linkTemplate.track then |
||
output[#output].category[ |
output[#output].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-wd'), linkTemplate.prop):plain() |
||
end |
end |
||
end |
end |
||
end |
end |
||
if url ~= '' then |
if url ~= '' then |
||
local langlink = (value.langcode and value.langcode ~= '' and value.langcode ~= contLangCode) |
|||
local this_wiki = mw.getContentLanguage() |
|||
and mw.message.newRawMessage(conf:g('msg-langcode'), value.langcode, mw.language.fetchLanguageName(value.langcode, contLangCode)) |
|||
local this_wiki_code = this_wiki:getCode() |
|||
or "" |
|||
local langlink = (value.langcode and value.langcode ~= '' and value.langcode ~= this_wiki_code) and mw.message.newRawMessage(conf:g('msg-langcode'), value.langcode, mw.language.fetchLanguageName(value.langcode, this_wiki_code)) or "" |
|||
output[#output].text = |
|||
if short_links and props.short then |
|||
mw.message.newRawMessage(short_links and linkTemplate.short or linkTemplate.message, |
|||
output[#output].text = |
|||
getLabel(entity, linkTemplate.genitive, pagetitle), |
|||
mw.message.newRawMessage(props.short, |
|||
url, |
|||
getLabel(entity, props.genitive, pagetitle), |
|||
langlink, |
|||
verified_value, |
|||
mw.uri.encode(verified_value, 'PATH')) |
|||
:plain() |
|||
mw.uri.encode(verified_value, 'PATH')) |
|||
:plain() |
|||
else |
|||
output[#output].text = |
|||
mw.message.newRawMessage(props.message, |
|||
getLabel(entity, props.genitive, pagetitle), |
|||
url, |
|||
langlink, |
|||
verified_value, |
|||
mw.uri.encode(verified_value, 'PATH')) |
|||
:plain() |
|||
end |
|||
end |
end |
||
end |
end |
||
Line 449: | Line 239: | ||
end |
end |
||
local function |
local function getSitelinkFromWikidata(linkTemplate, entity) |
||
local output = {} |
|||
--mw.log("getSitelinksFromWikidata, props="..dump(props)) |
|||
-- to avoid deep tests |
-- to avoid deep tests |
||
if not entity then |
if not entity then |
||
entity = mw.wikibase. |
entity = mw.wikibase.getEntity() |
||
if not entity then |
if not entity then |
||
--mw.log(" |
--mw.log("getSitelinkFromWikidata no entity") |
||
return nil |
return nil |
||
end |
end |
||
end |
end |
||
local requested_sitelink = string.match( |
local requested_sitelink = string.match(linkTemplate.prop, "SL(%l+)") -- a specific wiki to be linked to can be specified by config; otherwise, default to this wiki |
||
local |
local sitelink = entity:getSitelink(requested_sitelink) |
||
return sitelink or nil |
|||
if sitelinks and sitelinks ~= '' then |
|||
output[#output+1] = { value = sitelinks } |
|||
end |
|||
--mw.log("getSitelinksFromWikidata returning output="..dump(output)) |
|||
return output |
|||
end |
end |
||
-- This function has a bug: :getSitelink does not return an object - only a string; yet this function tries to access sitelink.langcode |
|||
local function findSiteLinksOnWikidata( |
local function findSiteLinksOnWikidata(linkTemplate, pagetitle, short_links) |
||
local output = {} |
local output = {} |
||
local pid = nil |
|||
local sitelink = getSitelinkFromWikidata(linkTemplate) |
|||
-- get the entity we are checking |
|||
-- verify existence of sitelink |
|||
local entity = mw.wikibase.getEntityObject() |
|||
if not sitelink then |
|||
-- to avoid deep tests |
|||
if not entity then |
|||
return nil |
return nil |
||
end |
end |
||
if not (linkTemplate.regex and |
|||
local values = getSitelinksFromWikidata(props) |
|||
not regexConverterTest(linkTemplate.regex, sitelink)) |
|||
for _, value in ipairs( values ) do |
|||
then |
|||
local verified_value = nil |
|||
output[1] = { |
|||
if props.regex then |
|||
langcode = sitelink.langcode, |
|||
-- we have a local defined regex, so this will have to pass first |
|||
category = {} |
|||
-- maybe we'll have to convert the regex to Lua-style |
|||
} |
|||
local regex = regexConverter(props.regex) |
|||
-- Search for a url-formatter |
|||
local test = string.match( value.value, '^'..regex..'$' ) |
|||
local url = '' |
|||
--mw.log("testing with "..regex.. " and test="..dump(test).." and value="..id) |
|||
if linkTemplate.url_f then |
|||
-- we have a locally defined url-formatter function from the config, use it as first priority |
|||
-- it matched, this is correct and overrides any other. |
|||
url = linkTemplate.url_f(sitelink) |
|||
verified_value = value.value |
|||
elseif linkTemplate.url then |
|||
end |
|||
-- we have a locally defined url-formatter string from the config, use it as second priority |
|||
url = mw.message.newRawMessage(linkTemplate.url, sitelink):plain() |
|||
else |
else |
||
url = sitelink:gsub(' ','_') |
|||
verified_value = value.value |
|||
end |
end |
||
if verified_value then |
|||
if linkTemplate.track and not string.find(linkTemplate.langcode, "SL%l+") and (linkTemplate.url_f or linkTemplate.url) then |
|||
--mw.log("it's verified..") |
|||
output[1].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-wd'), linkTemplate.prop):plain() |
|||
local url = '' |
|||
elseif linkTemplate.track then |
|||
output[#output+1] = {} |
|||
output[1].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-wd'), linkTemplate.prop):plain() |
|||
output[#output].langcode = value.langcode |
|||
end |
|||
output[#output].category = {} |
|||
if props.url_f then |
|||
if url ~= '' then |
|||
-- we have a local defined url-formatter function, use it as first priority |
|||
local langlink = (sitelink.langcode and sitelink.langcode ~= '' and sitelink.langcode ~= contLangCode) |
|||
url = props.url_f(verified_value) |
|||
and mw.message.newRawMessage(conf:g('msg-langcode'), sitelink.langcode, mw.language.fetchLanguageName(sitelink.langcode, contLangCode)) |
|||
if props.track and not string.find(props.langcode, "(SL%l+)") then |
|||
or "" |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-wd'), props.prop):plain() |
|||
output[1].text = |
|||
elseif props.track then |
|||
mw.message.newRawMessage(short_links and linkTemplate.short or linkTemplate.message, |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain() |
|||
getLabel(entity, linkTemplate.genitive, pagetitle), |
|||
end |
|||
url, |
|||
langlink, |
|||
-- we have a local defined url-formatter string, use it as second priority |
|||
sitelink, |
|||
url = mw.message.newRawMessage(props.url, verified_value):plain() |
|||
mw.uri.encode(sitelink, 'PATH')) |
|||
if props.track and not string.find(props.langcode, "(SL%l+)") then |
|||
:plain() |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-wd'), props.prop):plain() |
|||
elseif props.track then |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain() |
|||
end |
|||
else |
|||
url = verified_value:gsub(' ','_') |
|||
if props.track then |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-wd'), props.prop):plain() |
|||
end |
|||
end |
|||
if url ~= '' then |
|||
local this_wiki = mw.getContentLanguage() |
|||
local this_wiki_code = this_wiki:getCode() |
|||
local langlink = (value.langcode and value.langcode ~= '' and value.langcode ~= this_wiki_code) and mw.message.newRawMessage(conf:g('msg-langcode'), value.langcode, mw.language.fetchLanguageName(value.langcode, this_wiki_code)) or "" |
|||
if short_links and props.short then |
|||
output[#output].text = |
|||
mw.message.newRawMessage(props.short, |
|||
getLabel(entity, props.genitive, pagetitle), |
|||
url, |
|||
langlink, |
|||
verified_value, |
|||
mw.uri.encode(verified_value, 'PATH')) |
|||
:plain() |
|||
else |
|||
output[#output].text = |
|||
mw.message.newRawMessage(props.message, |
|||
getLabel(entity, props.genitive, pagetitle), |
|||
url, |
|||
langlink, |
|||
verified_value, |
|||
mw.uri.encode(verified_value, 'PATH')) |
|||
:plain() |
|||
end |
|||
end |
|||
end |
end |
||
end |
end |
||
Line 554: | Line 306: | ||
local function findMainLinksLocal( |
local function findMainLinksLocal(linkTemplate, pagetitle, short_links, local_value) |
||
local output = {} |
local output = {} |
||
-- to avoid deep tests |
-- to avoid deep tests |
||
if not local_value or local_value == '' -- bail out if no value is present |
|||
if not props.prop then |
|||
or (linkTemplate.regex |
|||
return nil |
|||
and not regexConverterTest(linkTemplate.regex, local_value)) |
|||
then |
|||
return {} |
|||
end |
end |
||
local wikidata_property = string.find(linkTemplate.prop, "[pP]%d+") |
|||
if not local_value or local_value == '' then |
|||
local wikidata_values = nil |
|||
-- bail out if no value is present |
|||
return output |
|||
end |
|||
-- get the formatvalue from the property |
|||
local verified_value = local_value |
|||
if props.regex and props.regex ~= '' then |
|||
-- let's verify the id |
|||
-- maybe we'll have to convert the regex to Lua-style |
|||
local regex = regexConverter(props.regex) |
|||
local test = string.match( local_value, '^'..regex..'$' ) |
|||
if test then |
|||
-- it matched, this is correct |
|||
verified_value = local_value |
|||
else |
|||
verified_value = nil |
|||
end |
|||
end |
|||
if not verified_value then |
|||
return output |
|||
end |
|||
local wikidata_property = string.find(props.prop, "([pP]%d+)") |
|||
local wikidata_values = {} |
|||
if wikidata_property then |
if wikidata_property then |
||
-- get any wikidata values to see if they are equal to local values |
-- get any wikidata values to see if they are equal to local values |
||
wikidata_values = getValuesFromWikidata( |
wikidata_values = getValuesFromWikidata(linkTemplate) |
||
if wikidata_values then |
|||
hasdatafromwikidata = true -- signal up the chain this article has a wikidata claim |
|||
end |
|||
end |
end |
||
if wikidata_property or ( |
if wikidata_property or (linkTemplate.url) or (linkTemplate.url_f) then |
||
output[ |
output[1] = { |
||
langcode = string.find(linkTemplate.langcode, "[pP]%d+") and "" or linkTemplate.langcode, |
|||
category = {} |
|||
--mw.log("findMainLinksLocal - props="..dump(props).." langcode="..output[#output].langcode) |
|||
} |
|||
output[#output].category = {} |
|||
assert(not wikidata_values or type(wikidata_values) == 'table', "Something went wrong: wikidata_values is neither a table nor nil") |
|||
local url = '' |
|||
if |
if linkTemplate.track and wikidata_values then |
||
local local_value_in_wikidata = false |
local local_value_in_wikidata = false |
||
for _,value in ipairs( wikidata_values ) do |
for _,value in ipairs( wikidata_values ) do |
||
if value.value == |
if value.value == local_value then |
||
local_value_in_wikidata = true |
local_value_in_wikidata = true |
||
break |
|||
end |
end |
||
end |
end |
||
output[ |
output[1].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, (local_value_in_wikidata and 'track-cat-local-wd-equal' or 'track-cat-local-wd-unequal')), linkTemplate.prop):plain() |
||
end |
end |
||
-- Search for a url-formatter |
|||
if wikidata_property and wikidata_values and #wikidata_values then |
|||
local url = '' |
|||
hasdatafromwikidata = true -- signal up the chain this article has a wikidata claim |
|||
if linkTemplate.url_f then |
|||
end |
|||
-- we have a locally defined url-formatter function from the config, use it as first priority |
|||
if props.url_f then |
|||
url = linkTemplate.url_f(local_value) |
|||
-- we have a local defined url-formatter function, use it as first priority |
|||
if linkTemplate.track then |
|||
url = props.url_f(verified_value) |
|||
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-local'), linkTemplate.prop):plain() |
|||
if props.track then |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-local'), props.prop):plain() |
|||
end |
end |
||
elseif |
elseif linkTemplate.url then |
||
-- we have a |
-- we have a locally defined url-formatter string from the config, use it as second priority |
||
url = mw.message.newRawMessage( |
url = mw.message.newRawMessage(linkTemplate.url, local_value):plain() |
||
if |
if linkTemplate.track then |
||
output[ |
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-local'), linkTemplate.prop):plain() |
||
end |
end |
||
else -- we know wikidata_property exists |
|||
-- config has no url formatter; check if Wikidata has one on the property |
|||
-- get the formatvalue from the property, if it exists |
|||
local formatterUrl = getFormatterUrl( |
local formatterUrl = getFormatterUrl(linkTemplate.prop, local_value) |
||
if formatterUrl ~= '' then |
if formatterUrl ~= '' then |
||
url = mw.message.newRawMessage(formatterUrl, |
url = mw.message.newRawMessage(formatterUrl, local_value):plain() |
||
if |
if linkTemplate.track then |
||
output[ |
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-local'), linkTemplate.prop):plain() |
||
end |
end |
||
end |
end |
||
else |
|||
-- no other choice, bail out |
|||
return {} |
|||
end |
|||
local this_wiki = mw.getContentLanguage() |
|||
local this_wiki_code = this_wiki:getCode() |
|||
local langlink = (output[#output].langcode and output[#output].langcode ~= '' and output[#output].langcode ~= this_wiki_code) and mw.message.newRawMessage(conf:g('msg-langcode'), props.langcode, mw.language.fetchLanguageName(props.langcode, this_wiki_code)) or "" |
|||
if short_links and props.short then |
|||
output[#output].text = |
|||
mw.message.newRawMessage(props.short, |
|||
getLabel(nil, props.genitive, pagetitle), |
|||
url, |
|||
langlink, |
|||
verified_value, |
|||
mw.uri.encode(verified_value, 'PATH')) |
|||
:plain() |
|||
else |
|||
output[#output].text = |
|||
mw.message.newRawMessage(props.message, |
|||
getLabel(nil, props.genitive, pagetitle), |
|||
url, |
|||
langlink, |
|||
verified_value, |
|||
mw.uri.encode(verified_value, 'PATH')) |
|||
:plain() |
|||
end |
end |
||
local langlink = (output[1].langcode and output[1].langcode ~= '' and output[1].langcode ~= contLangCode) |
|||
and mw.message.newRawMessage(conf:g('msg-langcode'), linkTemplate.langcode, mw.language.fetchLanguageName(linkTemplate.langcode, contLangCode)) |
|||
or "" |
|||
output[1].text = |
|||
mw.message.newRawMessage(short_links and linkTemplate.short or linkTemplate.message, |
|||
getLabel(nil, linkTemplate.genitive, pagetitle), |
|||
url, |
|||
langlink, |
|||
local_value, |
|||
mw.uri.encode(local_value, 'PATH')) |
|||
:plain() |
|||
end |
end |
||
--mw.log("findMainLinksLocal returning="..dump(output)) |
--mw.log("findMainLinksLocal returning="..dump(output)) |
||
Line 658: | Line 380: | ||
end |
end |
||
local function findSiteLinksLocal( |
local function findSiteLinksLocal(linkTemplate, pagetitle, short_links, local_value) |
||
local output = {} |
local output = {} |
||
-- to avoid deep tests |
-- to avoid deep tests |
||
if not local_value or local_value == '' -- bail out if no value is present |
|||
if not props.prop then |
|||
or (linkTemplate.regex |
|||
return nil |
|||
and not regexConverterTest(linkTemplate.regex, local_value)) |
|||
end |
|||
then |
|||
if not local_value or local_value == '' then |
|||
return {} |
|||
-- bail out if no value is present |
|||
return output |
|||
end |
|||
-- get the formatvalue from the property |
|||
local verified_value = local_value |
|||
if props.regex and props.regex ~= '' then |
|||
-- let's verify the id |
|||
-- maybe we'll have to convert the regex to Lua-style |
|||
local regex = regexConverter(props.regex) |
|||
local test = string.match( local_value, '^'..regex..'$' ) |
|||
if test then |
|||
-- it matched, this is correct |
|||
verified_value = local_value |
|||
else |
|||
verified_value = nil |
|||
end |
|||
end |
|||
if not verified_value then |
|||
return output |
|||
end |
end |
||
local wikidata_property = string.find( |
local wikidata_property = string.find(linkTemplate.prop, "SL.+") |
||
local |
local wikidata_sitelink = nil |
||
if wikidata_property then |
if wikidata_property then |
||
-- get any wikidata values to see if they are equal to local values |
-- get any wikidata values to see if they are equal to local values |
||
wikidata_sitelink = getSitelinkFromWikidata(linkTemplate) |
|||
wikidata_values = getSitelinksFromWikidata(props) |
|||
if wikidata_sitelink then |
|||
hasdatafromwikidata = true -- signal up the chain this article has a wikidata claim |
|||
end |
|||
end |
end |
||
if wikidata_property or ( |
if wikidata_property or (linkTemplate.url) or (linkTemplate.url_f) then |
||
output[ |
output[1] = { |
||
langcode = string.find(linkTemplate.langcode, "SL.+") and "" or linkTemplate.langcode, |
|||
category = {} |
|||
--mw.log("findSiteLinksLocal - props="..dump(props).." langcode="..output[#output].langcode .." wikidata_values="..dump(wikidata_values)) |
|||
} |
|||
output[#output].category = {} |
|||
--mw.log("findSiteLinksLocal - linkTemplate="..dump(linkTemplate).." langcode="..output[#output].langcode .." wikidata_values="..dump(wikidata_values)) |
|||
if linkTemplate.track and wikidata_sitelink then |
|||
local local_value_in_wikidata = (wikidata_sitelink == local_value) |
|||
output[1].category[1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, (local_value_in_wikidata and 'track-cat-local-wd-equal' or 'track-cat-local-wd-unequal')), linkTemplate.prop):plain() |
|||
end |
|||
-- Search for a url formatter |
|||
local url = '' |
local url = '' |
||
if linkTemplate.url_f then |
|||
if props.track and wikidata_property and wikidata_values and #wikidata_values then |
|||
-- we have a locally defined url-formatter function from the config, use it as first priority |
|||
local local_value_in_wikidata = false |
|||
url = linkTemplate.url_f(local_value) |
|||
for _,value in ipairs( wikidata_values ) do |
|||
if linkTemplate.track then |
|||
if value.value == verified_value then |
|||
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-local'), linkTemplate.prop):plain() |
|||
local_value_in_wikidata = true |
|||
end |
|||
end |
end |
||
elseif linkTemplate.url then |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), (local_value_in_wikidata and 'track-cat-local-wd-equal' or 'track-cat-local-wd-unequal')), props.prop):plain() |
|||
-- we have a locally defined url-formatter string from the config, use it as second priority |
|||
end |
|||
url = mw.message.newRawMessage(linkTemplate.url, local_value):plain() |
|||
if wikidata_property and wikidata_values and #wikidata_values then |
|||
if linkTemplate.track then |
|||
hasdatafromwikidata = true -- signal up the chain this article has a wikidata claim |
|||
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-local-local'), linkTemplate.prop):plain() |
|||
end |
|||
if props.url_f then |
|||
-- we have a local defined url-formatter function, use it as first priority |
|||
url = props.url_f(verified_value) |
|||
if props.track then |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-local'), props.prop):plain() |
|||
end |
end |
||
else -- we know wikidata_property exists |
|||
elseif props.url then |
|||
url = local_value:gsub(' ','_') |
|||
-- we have a local defined url-formatter string, use it as second priority |
|||
if linkTemplate.track then |
|||
url = mw.message.newRawMessage(props.url, verified_value):plain() |
|||
output[1].category[#output[1].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLangCode, 'track-cat-wd-local'), linkTemplate.prop):plain() |
|||
if props.track then |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-local-local'), props.prop):plain() |
|||
end |
end |
||
elseif wikidata_property then |
|||
url = verified_value:gsub(' ','_') |
|||
if props.track then |
|||
output[#output].category[#output[#output].category+1] = mw.message.newRawMessage(cmodule:getMessage(contLang:getCode(), 'track-cat-wd-local'), props.prop):plain() |
|||
end |
|||
else |
|||
-- no other choice, bail out |
|||
return {} |
|||
end |
|||
local this_wiki = mw.getContentLanguage() |
|||
local this_wiki_code = this_wiki:getCode() |
|||
local langlink = (output[#output].langcode and output[#output].langcode ~= '' and output[#output].langcode ~= this_wiki_code) and mw.message.newRawMessage(conf:g('msg-langcode'), props.langcode, mw.language.fetchLanguageName(props.langcode, this_wiki_code)) or "" |
|||
if short_links and props.short then |
|||
output[#output].text = |
|||
mw.message.newRawMessage(props.short, |
|||
getLabel(nil, props.genitive, pagetitle), |
|||
url, |
|||
langlink, |
|||
verified_value, |
|||
mw.uri.encode(verified_value, 'PATH')) |
|||
:plain() |
|||
else |
|||
output[#output].text = |
|||
mw.message.newRawMessage(props.message, |
|||
getLabel(nil, props.genitive, pagetitle), |
|||
url, |
|||
langlink, |
|||
verified_value, |
|||
mw.uri.encode(verified_value, 'PATH')) |
|||
:plain() |
|||
end |
end |
||
local langlink = (output[1].langcode and output[1].langcode ~= '' and output[1].langcode ~= contLangCode) |
|||
and mw.message.newRawMessage(conf:g('msg-langcode'), linkTemplate.langcode, mw.language.fetchLanguageName(linkTemplate.langcode, contLangCode)) |
|||
or "" |
|||
output[1].text = |
|||
mw.message.newRawMessage(short_links and linkTemplate.short or linkTemplate.message, |
|||
getLabel(nil, linkTemplate.genitive, pagetitle), |
|||
url, |
|||
langlink, |
|||
local_value, |
|||
mw.uri.encode(local_value, 'PATH')) |
|||
:plain() |
|||
end |
end |
||
--mw.log("findSiteLinksLocal returning="..dump(output)) |
--mw.log("findSiteLinksLocal returning="..dump(output)) |
||
Line 760: | Line 446: | ||
local function addLinkback(str, property) |
local function addLinkback(str, property) |
||
local id = mw.wikibase. |
local id = mw.wikibase.getEntityIdForCurrentPage() |
||
if not id then |
if not id then |
||
return str |
return str |
||
end |
|||
if type(id) == 'table' then |
|||
id = id.id |
|||
end |
end |
||
Line 802: | Line 485: | ||
end |
end |
||
end |
end |
||
return args[argument] |
|||
return args[argument] |
|||
end |
|||
return nil |
|||
end |
end |
||
local function removeEntry(conf_claims, identifier, property) |
local function removeEntry(conf_claims, identifier, property) |
||
for i, |
for i, linkTemplate in ipairs(conf_claims) do |
||
if |
if linkTemplate[identifier] == property then |
||
table.remove(conf_claims, i) |
table.remove(conf_claims, i) |
||
end |
end |
||
Line 818: | Line 498: | ||
end |
end |
||
function p.getLinks(frame) |
function p.getLinks(frame, customClaims) --customClaims is a backdoor for testcases |
||
local configured_conf = getArgument(frame, conf:a('arg-conf')) |
local configured_conf = getArgument(frame, conf:a('arg-conf')) |
||
if configured_conf then |
if configured_conf then |
||
Line 825: | Line 505: | ||
error(mw.message.newRawMessage(conf:g('missing-conf'), configured_conf):plain()) |
error(mw.message.newRawMessage(conf:g('missing-conf'), configured_conf):plain()) |
||
end |
end |
||
local conf_claims = customClaims or cmodule:getConfiguredClaims(contLangCode) |
|||
local output = {} |
|||
local category = {} |
|||
local conf_claims = cmodule:getConfiguredClaims(contLang:getCode()) |
|||
local limits = cmodule:getLimits() |
local limits = cmodule:getLimits() |
||
assert(limits, mw.message.newRawMessage(conf:g('missing-limits'), configured_conf):plain()) |
assert(limits, mw.message.newRawMessage(conf:g('missing-limits'), configured_conf):plain()) |
||
local links_shown = getArgument(frame, conf:a('arg-maxlink')) |
local links_shown = tonumber(getArgument(frame, conf:a('arg-maxlink'))) or limits['links-shown'] or 10 -- maximum links to display |
||
local pagetitle = getArgument(frame, conf:a('arg-title')) |
local pagetitle = getArgument(frame, conf:a('arg-title')) |
||
-- get a list of tracked properties from the article itself |
-- get a list of tracked properties from the article itself |
||
Line 837: | Line 517: | ||
-- the properties should be written as P1234, P2345 and other |
-- the properties should be written as P1234, P2345 and other |
||
-- version corresponding to the applicable property-identifiers in the config |
-- version corresponding to the applicable property-identifiers in the config |
||
for track_prop in string.gmatch(requested_tracking," |
for track_prop in string.gmatch(requested_tracking,"[^ ,;:]+") do |
||
-- get the requested properties and be able to access them |
-- get the requested properties and be able to access them |
||
-- like req_prop['P345'] to verify if it was requested |
-- like req_prop['P345'] to verify if it was requested |
||
local remove_track = string.match(track_prop, "^ |
local remove_track = string.match(track_prop, "^%-(.*)") |
||
for i,claim in ipairs ( conf_claims ) do |
for i,claim in ipairs ( conf_claims ) do |
||
if remove_track == claim.prop or remove_track == conf:a('mod-filter-all') then |
if remove_track == claim.prop or remove_track == conf:a('mod-filter-all') then |
||
-- if a property starts with "-", then we'll simply remove that |
-- if a property starts with "-", then we'll simply remove that |
||
-- property from the conf_claims |
-- property from the conf_claims |
||
conf_claims[i] |
conf_claims[i].track = false |
||
elseif track_prop == claim.prop or track_prop == conf:a('mod-filter-all') then |
elseif track_prop == claim.prop or track_prop == conf:a('mod-filter-all') then |
||
conf_claims[i] |
conf_claims[i].track = true |
||
end |
end |
||
end |
end |
||
Line 861: | Line 541: | ||
-- the properties should be written as P1234, P2345 and other |
-- the properties should be written as P1234, P2345 and other |
||
-- version corresponding to the applicable property-identifiers in the config |
-- version corresponding to the applicable property-identifiers in the config |
||
for i in string.gmatch(requested_properties," |
for i in string.gmatch(requested_properties,"[^ ,;:]+") do |
||
-- get the requested properties and be able to access them |
-- get the requested properties and be able to access them |
||
-- like req_prop['P345'] to verify if it was requested |
-- like req_prop['P345'] to verify if it was requested |
||
Line 871: | Line 551: | ||
no_req_prop = true |
no_req_prop = true |
||
end |
end |
||
local remove_prop = string.match(i, "^ |
local remove_prop = string.match(i, "^%-(.*)") |
||
if remove_prop then |
if remove_prop then |
||
-- if a property starts with "-", then we'll simply remove that |
-- if a property starts with "-", then we'll simply remove that |
||
Line 877: | Line 557: | ||
conf_claims = removeEntry(conf_claims, 'prop', remove_prop) |
conf_claims = removeEntry(conf_claims, 'prop', remove_prop) |
||
elseif not no_req_prop then -- only if we are allowing properties to be filtered |
elseif not no_req_prop then -- only if we are allowing properties to be filtered |
||
req_prop[i] = |
req_prop[i] = true |
||
-- cheat to make #req_prop indicate populated table |
-- cheat to make #req_prop indicate populated table |
||
req_prop[1] = |
req_prop[1] = true |
||
end |
end |
||
end |
end |
||
Line 890: | Line 570: | ||
if requested_langs and requested_langs ~= '' then |
if requested_langs and requested_langs ~= '' then |
||
-- the languages should be written as langcodes as used in the conf_claims |
-- the languages should be written as langcodes as used in the conf_claims |
||
for i in string.gmatch(requested_langs," |
for i in string.gmatch(requested_langs,"[^ ,;:]+") do |
||
-- get the requested languages and be able to access them |
-- get the requested languages and be able to access them |
||
if i == conf:a('mod-filter-all') then |
if i == conf:a('mod-filter-all') then |
||
Line 900: | Line 580: | ||
end |
end |
||
-- like req_lang['en'] to verify if it was requested |
-- like req_lang['en'] to verify if it was requested |
||
local remove_lang = string.match(i, "^ |
local remove_lang = string.match(i, "^%-(.*)") |
||
if remove_lang then |
if remove_lang then |
||
-- if a language starts with "-", then we'll simply remove that |
-- if a language starts with "-", then we'll simply remove that |
||
Line 906: | Line 586: | ||
conf_claims = removeEntry(conf_claims, 'langcode', remove_lang) |
conf_claims = removeEntry(conf_claims, 'langcode', remove_lang) |
||
elseif not no_req_lang then -- only if we are allowing languages to be filtered |
elseif not no_req_lang then -- only if we are allowing languages to be filtered |
||
req_lang[i] = |
req_lang[i] = true |
||
-- cheat to make #req_lang indicate populated table |
-- cheat to make #req_lang indicate populated table |
||
req_lang[1] = |
req_lang[1] = true |
||
end |
end |
||
end |
end |
||
end |
end |
||
local short_links = getArgument(frame, conf:a('arg-short')) |
local short_links = getArgument(frame, conf:a('arg-short')) |
||
short_links = (short_links and short_links ~= '' or false) |
|||
short_links = true |
|||
else |
|||
short_links = false |
|||
end |
|||
local showinline = getArgument(frame, conf:a('arg-inline')) |
local showinline = getArgument(frame, conf:a('arg-inline')) |
||
showinline = (showinline and showinline ~= '' or false) |
|||
showinline = true |
|||
else |
|||
showinline = false |
|||
end |
|||
if not links_shown or links_shown == '' then |
|||
links_shown = limits['links-shown'] and limits['links-shown'] or 5 |
|||
else |
|||
links_shown = tonumber(links_shown) |
|||
end |
|||
local somedataonwikidata = not short_links |
local somedataonwikidata = not short_links |
||
--mw.log("conf_claims="..dump(conf_claims)) |
--mw.log("conf_claims="..dump(conf_claims)) |
||
Line 934: | Line 603: | ||
--mw.log("req_lang="..dump(req_lang)) |
--mw.log("req_lang="..dump(req_lang)) |
||
--mw.log("short_links="..dump(short_links)) |
--mw.log("short_links="..dump(short_links)) |
||
for _, props in ipairs(conf_claims) do |
|||
local output = {} |
|||
local category = {} |
|||
for _, linkTemplate in ipairs(conf_claims) do |
|||
-- if we're called with a list of approved properties or languages, check if this one is "approved" |
-- if we're called with a list of approved properties or languages, check if this one is "approved" |
||
if (#req_prop==0 or req_prop[ |
if (#req_prop==0 or req_prop[linkTemplate.prop]) and (#req_lang==0 or req_lang[linkTemplate.langcode] or string.find(linkTemplate.langcode, "[pP]%d+")) then |
||
-- Error if linkTemplate.prop is nonexistent, as it is required |
|||
--mw.log("checking claim="..dump(props)) |
|||
assert(linkTemplate.prop, "malformed linkTemplate from config (no .prop given): " .. dump(linkTemplate)) |
|||
local links = {} |
local links = {} |
||
local checkedonwikidata = false |
local checkedonwikidata = false |
||
-- get the any local overriding value from the call |
-- get the any local overriding value from the call |
||
local wikivalue = getArgument(frame, |
local wikivalue = getArgument(frame, linkTemplate.prop) |
||
if (not wikivalue or wikivalue == "") and string.find(linkTemplate.prop, "[pP]%d+") then |
|||
--mw.log("wikivalue="..dump(wikivalue)) |
|||
if (not wikivalue or wikivalue == "") and string.find(props.prop, "([pP]%d+)") then |
|||
-- the property is a Pnnn type, and therefore on Wikidata |
-- the property is a Pnnn type, and therefore on Wikidata |
||
links = findMainLinksOnWikidata( |
links = findMainLinksOnWikidata(linkTemplate, pagetitle, short_links) |
||
if links == nil then |
if links == nil then |
||
-- a nil-value indicated no wikidata-link |
-- a nil-value indicated no wikidata-link |
||
Line 953: | Line 626: | ||
checkedonwikidata = true |
checkedonwikidata = true |
||
end |
end |
||
elseif (not wikivalue or wikivalue == "") and string.find( |
elseif (not wikivalue or wikivalue == "") and string.find(linkTemplate.prop, "SL%l+") then |
||
-- this is a sitelink-type (SLspecieswiki) |
-- this is a sitelink-type (SLspecieswiki) |
||
--mw.log("finding sitelinks..") |
--mw.log("finding sitelinks..") |
||
links = findSiteLinksOnWikidata( |
links = findSiteLinksOnWikidata(linkTemplate, pagetitle, short_links) |
||
if links == nil then |
if links == nil then |
||
-- a nil-value indicated no wikidata-link |
-- a nil-value indicated no wikidata-link |
||
Line 964: | Line 637: | ||
checkedonwikidata = true |
checkedonwikidata = true |
||
end |
end |
||
elseif |
elseif string.find(linkTemplate.prop, "SL%l+") then -- we know that wikivalue is set if this is true |
||
-- this is a sitelink-type (SLspecieswiki) |
-- this is a sitelink-type (SLspecieswiki) |
||
links = findSiteLinksLocal( |
links = findSiteLinksLocal(linkTemplate, pagetitle, short_links, wikivalue) |
||
elseif wikivalue and wikivalue ~= '' then |
elseif wikivalue and wikivalue ~= '' then |
||
-- the property is of another annotation, and therefore a local construct |
-- the property is of another annotation, and therefore a local construct |
||
links = findMainLinksLocal( |
links = findMainLinksLocal(linkTemplate, pagetitle, short_links, wikivalue) |
||
end |
end |
||
--mw.log("links="..dump(links)) |
--mw.log("links="..dump(links)) |
||
Line 978: | Line 651: | ||
-- add a general tracking category for articles with data from wikidata |
-- add a general tracking category for articles with data from wikidata |
||
hasdatafromwikidata = true |
hasdatafromwikidata = true |
||
category[#category+1] = cmodule:getMessage( |
category[#category+1] = cmodule:getMessage(contLangCode, 'with-data-cat') |
||
elseif not checkedonwikidata and not hasdatafromlocal then |
elseif not checkedonwikidata and not hasdatafromlocal then -- not checkonwikidata |
||
-- add a general tracking category for articles with data from template-calls in local articles |
-- add a general tracking category for articles with data from template-calls in local articles |
||
hasdatafromlocal = true |
hasdatafromlocal = true |
||
category[#category+1] = cmodule:getMessage( |
category[#category+1] = cmodule:getMessage(contLangCode, 'with-local-cat') |
||
end |
end |
||
if short_links and |
if short_links and linkTemplate.short and v.text and v.text ~= '' then |
||
-- if short links were requested, and a short definition exists for this property, let's use it |
-- if short links were requested, and a short definition exists for this property, let's use it |
||
if #output==0 then |
if #output==0 then |
||
output[ |
output[1] = v.text |
||
else |
else |
||
output[#output] = output[#output] .. cmodule:getMessage( |
output[#output] = output[#output] .. cmodule:getMessage(contLangCode,'short-list-separator') .. v.text |
||
end |
end |
||
somedataonwikidata = true |
somedataonwikidata = true |
||
elseif not short_links and not showinline and v.text and v.text ~= '' then |
elseif not short_links and not showinline and v.text and v.text ~= '' then |
||
-- only if short links were not requested |
-- only if short links were not requested |
||
output[#output+1] = (#output |
output[#output+1] = (#output ~= 0 and conf:g('msg-ul-prepend') or '') -- if this is the first link, we won't output a list-element (msg-ul-prepend) |
||
.. (checkedonwikidata and addLinkback(v.text, |
.. (checkedonwikidata and addLinkback(v.text, linkTemplate.prop) or v.text) -- if the link comes from wikidata, also output a linkback. |
||
elseif not short_links |
elseif not short_links and v.text and v.text ~= '' then -- and showinline |
||
-- only if short links were not requested |
-- only if short links were not requested |
||
output[#output+1] = v.text |
output[#output+1] = v.text |
||
end |
end |
||
if |
if linkTemplate.track then |
||
-- add category if tracking is on for this property and a category exists in the link-result. |
-- add category if tracking is on for this property and a category exists in the link-result. |
||
for _,cats in ipairs( v.category ) do |
for _,cats in ipairs( v.category ) do |
||
Line 1,006: | Line 679: | ||
end |
end |
||
end |
end |
||
if links_shown |
if links_shown == 0 then -- abort if we've hit the maximum for number of links |
||
links_shown = links_shown - 1 |
|||
else |
|||
break |
break |
||
end |
end |
||
links_shown = links_shown - 1 |
|||
end |
end |
||
end |
end |
||
Line 1,023: | Line 695: | ||
--mw.log("somedataonwikidata="..dump(somedataonwikidata).." and output="..dump(output).." and #output="..dump(#output)) |
--mw.log("somedataonwikidata="..dump(somedataonwikidata).." and output="..dump(output).." and #output="..dump(#output)) |
||
outtext = (somedataonwikidata |
outtext = (somedataonwikidata |
||
and addLinkback(table.concat(output,cmodule:getMessage( |
and addLinkback(table.concat(output,cmodule:getMessage(contLangCode,'short-list-separator')), nil) |
||
or table.concat(output,cmodule:getMessage( |
or table.concat(output,cmodule:getMessage(contLangCode,'short-list-separator'))) |
||
elseif |
elseif not showinline and #output>0 then -- and not shortlinks |
||
outtext = table.concat(output,"\n") |
outtext = table.concat(output,"\n") |
||
elseif |
elseif #output>0 then -- and not short_links and showinline |
||
outtext = table.concat(output,conf:g('msg-inline-separator')) |
outtext = table.concat(output,conf:g('msg-inline-separator')) |
||
end |
end |
||
if not hasdatafromwikidata then |
if not hasdatafromwikidata then |
||
category[#category+1] = cmodule:getMessage( |
category[#category+1] = cmodule:getMessage(contLangCode, 'no-data-cat') |
||
if not hasdatafromlocal and not short_links then |
if not hasdatafromlocal and not short_links then |
||
outtext = cmodule:getMessage( |
outtext = cmodule:getMessage(contLangCode, 'no-data-text') |
||
end |
end |
||
end |
end |
||
if not haswikidatalink then |
if not haswikidatalink then |
||
category[#category+1] = cmodule:getMessage( |
category[#category+1] = cmodule:getMessage(contLangCode, 'no-wikilink-cat') |
||
if not hasdatafromlocal and not short_links then |
if not hasdatafromlocal and not short_links then |
||
outtext = cmodule:getMessage( |
outtext = cmodule:getMessage(contLangCode, 'no-wikilink') |
||
end |
end |
||
end |
end |
||
Line 1,051: | Line 723: | ||
function p.getLanguageCode(frame) |
function p.getLanguageCode(frame) |
||
local prop = getArgument(frame, conf:a('arg-properties')) |
local prop = getArgument(frame, conf:a('arg-properties')) |
||
return getLanguageData(prop, nil, conf:a(mod-filter-separator)) |
|||
return table.concat(output, conf:a('mod-filter-separator')) |
|||
end |
end |
||