モジュール:Citeq

require('strict')
local wdib = require('Module:WikidataIB')
local getValue = wdib._getValue
local getPropOfProp = wdib._getPropOfProp
local followQid = wdib._followQid
local simple_properties = { -- PXXX, is multiple?, linked?
	publisher = {id="P123", maxvals=1},
	oclc = {id="P243", maxvals=1},
	place = {id="P291", maxvals=0,linked='no'},
	doi = {id="P356", maxvals=1},
	issue = {id="P433", maxvals=1, populate_from_journal = true},
	pmid = {id="P698", maxvals=1},
	arxiv = {id="P818", maxvals=1},
	bibcode = {id="P819", maxvals=1},
	jstor = {id="P888", maxvals=1},
	mr = {id="P889", maxvals=1},
	ssrn = {id="P893", maxvals=1},
	pmc = {id="P932", maxvals=1},
	lccn = {id="P1144", maxvals=1},
	hdl = {id="P1184", maxvals=1},
	ismn = {id="P1208", maxvals=1},
	journal = {id="P1433", maxvals=1},
	citeseerx = {id="P3784", maxvals=1},
	osti = {id="P3894", maxvals=1},
	biorxiv = {id="P3951", maxvals=1},
	isbn = {id="P212", maxvals=1, populate_from_journal = true}, -- ISBN 13
	issn = {id="P236", maxvals=1, populate_from_journal = true},
	chapter = {id="P792", maxvals=1},
	"date" = {id="P577", maxvals=1, populate_from_journal = true},
	series = {id="P179", maxvals=1, populate_from_journal = true},
	volume = {id="P478", maxvals=1, populate_from_journal = true},
	title = {id="P1476", maxvals=1},
	url = {id="P953", maxvals=1}, -- full work available at
	pages = {id="P304", maxvals=1, populate_from_journal = true},
	translator = {id="P655", maxvals=0}, -- does **not** go to "others" section!
	illustrator = {id="P110", maxvals=0, others=true}, -- goes to "others" section
	composer = {id="P86", maxvals=0, others=true}, -- goes to "others" section
	animator = {id="P6942", maxvals=0, others=true}, -- goes to "others" section
	director = {id="P57", maxvals=0, others=true}, -- goes to "others" section
	screenwriter = {id="P58", maxvals=0, others=true}, -- goes to "others" section
}
local citeq = {}
----------------------------------------------------------------------------------------------
Returns true if argument is set; false otherwise. Argument is 'set' when it exists (not nil) or when it is not an empty string.
local function is_set( var )
	return not (var == nil or var == );
end
--=-----------------------------------------------------------------------------
get_name_list -- adapted from getAuthors code taken from Module:RexxS
arguments:
	nl_type - type of name list to fetch: nl_type = 'author' for authors; 'editor' for editors
	args - pointer to the parameter arguments table from the template call
	qid - value from |qid= parameter; the Q-id of the source (book, etc.) in qid
	wdl - value from the |wdlinks= parameter; a boolean passed to enable links to Wikidata when no article exists
returns nothing; modifies the args table
**
local function get_name_list (nl_type, args, qid, wdl)
	local propertyID = "P50"
	local fallbackID = "P2093" -- author name string
	
	if 'author' == nl_type then
		propertyID = 'P50';														-- for authors
		fallbackID = 'P2093';
	elseif 'editor' == nl_type then
		propertyID = 'P98';														-- for editors
		fallbackID = nil;
	else
		return;																	-- not specified so return
	end
	
	-- wdlinks is a boolean passed to enable links to Wikidata when no article exists
	-- if "false" or "no" or "0" is passed set it false
	-- if nothing or an empty string is passed set it false
	if wdl and (#wdl > 0) then
		wdl = wdl:lower()
		wdl = (wdl == "false") or (wdl == "no") or (wdl == "0")
	else
		-- wdl is empty, so
		wdl = false
	end
	
	local entity = mw.wikibase.getEntity(qid)
	local props = nil
	local fallback = nil
	if entity and entity.claims then
		props = entity.claimspropertyID
		if fallbackID then
			fallback = entity.claimsfallbackID
		end
	end
	
	-- Make sure it actually has at least one of the properties requested
	if not (props and props1) and not (fallback and fallback1) then 
		return nil
	end
	
	-- So now we have something to return:
	-- table 'out' is going to store the names(s):
	-- and table 'link' will store any links to the name's article
	local out = {}
	local link = {}
	local maxpos = 0
	if props and props1 then
		for k, v in pairs(props) do
			local qnumber = "Q" .. v.mainsnak.datavalue.value"numeric-id"
			local sitelink = mw.wikibase.sitelink(qnumber)
			local label = mw.wikibase.label(qnumber)
			if label then
				label = mw.text.nowiki(label)
			else
				label = qnumber
			end
			local position = maxpos + 1 -- Default to 'next' author.
			-- use P1545 (series ordinal) instead of default position.
			if v"qualifiers" and v.qualifiers"P1545" and v.qualifiers"P1545"1 then
				position = tonumber(v.qualifiers"P1545"1.datavalue.value)
			end
			maxpos = math.max(maxpos, position)
			if sitelink then
				-- just the plain name,
				-- but keep a record of the links, using the same index
				outposition = label
				linkposition = sitelink
			else
				-- no sitelink, so check first for a redirect with that label
				-- this code works, but causes the article to appear in WhatLinksHere for the possible destination, so remove
				-- local artitle = mw.title.new(label, 0)
				-- if artitle.id > 0 then
				--	if artitle.isRedirect then
						-- no sitelink,
						-- but there's a redirect with the same title as the label;
						-- so store the link to that
				--		outposition = label
				--		linkposition = label
				--	else
						-- no sitelink and not a redirect but an article exists with the same title as the label
						-- that's probably a dab page, so output the plain label
				--		outposition = label
				--	end
				--else
				-- no article or redirect with the same title as the label
				if wdl then
					-- show that there's a Wikidata entry available
					outposition = ":d:Q" .. v.mainsnak.datavalue.value"numeric-id" .. "|" .. label .. " link="
				else
					-- no wikidata links wanted, so just give the plain label
					outposition = label
				end
				-- end
			end
		end
	end
	if fallback and fallback1 then
		-- Fallback to name-only authors / editors
		for k, v in pairs(fallback) do
			local label = v.mainsnak.datavalue"value"
			local position = maxpos + 1 -- Default to 'next' author.
			-- use P1545 (series ordinal) instead of default position.
			if v"qualifiers" and v.qualifiers"P1545" and v.qualifiers"P1545"1 then
				position = tonumber(v.qualifiers"P1545"1.datavalue.value)
			end
			maxpos = math.max(maxpos, position)
			outposition = label
		end
	end
	-- if there's anything to return, then insert the additions in the template arguments table
	-- in the form |author1=firstname secondname |author2= ...
	-- Renumber, in case we have inconsistent numbering
	local keys = {}
	for k,v in pairs(out) do
		keys#keys+1 = k
	end
	table.sort(keys) -- as they might be out of order
	for i, k in ipairs(keys) do
		mw.log(i.." "..k.." "..outk)
		argsnl_type .. i = outk												-- author-n or editor-n
		if linkk then
			argsnl_type .. '-link' .. i = linkk								-- author-linkn or editor-linkn
		end
	end
end
--author1=
are set, calls get_authors() to try to get an author name-list from wikidata.  The result is passed to 
for rendering.
local function wrap_nowiki(str)
	return mw.text.nowiki(str or )
end
function citeq.cite_q (frame)
	local citeq_args = {};
	for k, v in pairs(frame:getParent().args) do
		citeq_argsk = v
	end
	for k, v in pairs(frame.args) do
		citeq_argsk = v
	end
	
	local qid = citeq_args.qid
	local wdl = citeq_args.wdl
	citeq_args.qid = nil
	citeq_args.wdl = nil
	
	local oth = {}
	
	citeq_args.language = citeq_args.language or getPropOfProp( {qid = qid, prop1 = "P407", prop2 = "P218", ps = 1} )
	if citeq_args.language ==  then
		citeq_args.language = nil
	end
	if not citeq_args.language then
		-- try fallback to journal's language
		local journal_qid = followQid({qid = qid, props = "P1433"})
		citeq_args.language = journal_qid and getPropOfProp( {qid = journal_qid, prop1 = "P407", prop2 = "P218", ps = 1} )
	end
	for name, data in pairs(simple_properties) do
		citeq_argsname = getValue( {data.id, ps = 1, qid = qid, maxvals=data.maxvals, linked=data.linked, citeq_argsname } )
		
		if data.populate_from_journal then
			citeq_argsname = getValue( {"P1433", ps = 1, qid = qid, maxvals=0, citeq_argsname, qual=data.id, qualsonly='yes'} )
			citeq_argsname = citeq_argsname or getPropOfProp({qid = qid, prop1 = "P1433", prop2 = data.id, maxvals=data.maxvals, ps = 1})
		end
		if citeq_argsname and citeq_argsname:find(, 1, true) then
			-- try fallback to work's native language
			citeq_argsname = getValue( {data.id, ps = 1, qid = qid, maxvals=data.maxvals, linked="no", lang = citeq_args.language } )
			if citeq_argsname:find('^Q%d+$') then -- qid was returned
				-- try fallback to qid's native language
				local qid_language = getPropOfProp( {qid = citeq_argsname, prop1 = "P407", prop2 = "P218", ps = 1} )
				citeq_argsname = getValue( {data.id, ps = 1, qid = qid, maxvals=data.maxvals, linked="no", lang = qid_language } )
				if citeq_argsname:find('^Q%d+$') then -- qid was returned again
					citeq_argsname = nil
				end
			end
		end
		if data.others then
			oth#oth+1 = citeq_argsname and (name:gsub("^%l", string.upper) .. ": " .. citeq_argsname)
			citeq_argsname = nil
		end
	end
	citeq_args.others = citeq_args.others or table.concat(oth, ". ")
	citeq_args.journal = citeq_args.journal and citeq_args.journal:gsub("^", ""):gsub("$", ""):gsub("|", "|"):gsub("", "")
	citeq_args.ol = (getValue( {"P648", ps = 1, qid = qid, maxvals=1, citeq_args.ol } ) or ):gsub("^OL(.+)$", "%1")
	citeq_args.biorxiv = citeq_args.biorxiv and ("10.1101/" .. citeq_args.biorxiv)
	citeq_args.isbn = getValue( {"P957", ps = 1, qid = qid, maxvals=0, citeq_args.isbn } ) -- try ISBN 10
	
	citeq_args.url = getValue( {"P856", ps = 1, qid = qid, maxvals=0, citeq_args.url } ) -- try official website
	citeq_args.url = getValue( {"P2699", ps = 1, qid = qid, maxvals=0, citeq_args.url } ) -- try url
	local slink = mw.wikibase.getSitelink(qid)
	local label = mw.wikibase.getLabel(qid) or citeq_args.language and mw.wikibase.getLabelByLang(qid, citeq_args.language)
	if citeq_args.title then
		if slink then
			citeq_args.url = nil
			citeq_args.title =  .. wrap_nowiki(citeq_args.title) .. 
		else
			citeq_args.title = wrap_nowiki(citeq_args.title)	
		end
	else
		if slink then
			citeq_args.url = nil
			if slink:lower() == label:lower() then
				citeq_args.title =  .. slink .. 
			else
				citeq_args.title =  .. wrap_nowiki(slink:gsub("%s%(.+%)$", ""):gsub(",.+$", "")) .. 
			end
		else
			citeq_args.title = wrap_nowiki(label)
		end
	end
	if citeq_args.p or citeq_args.page then
		citeq_args.pages = nil
	end
	if citeq_args.pages then
		local _, count = string.gsub(citeq_args.pages, " %d+", "")
		if count == 1 then
			citeq_args.p = citeq_args.pages
			citeq_args.pages = nil
		end
	end
	for k, v in pairs(citeq_args) do
		if v == 'unset' or type(k) ~= 'string' then
			citeq_argsk = nil
		end
	end
	if is_set (qid) then
		if not is_set (citeq_args.author) and not is_set (citeq_args.author1) then	-- if neither are set, try to get authors from wikidata
			get_name_list ('author', citeq_args, qid, wdl);						-- modify citeq_args table with authors from wikidata
		end
		if not is_set (citeq_args.editor) and not is_set (citeq_args.editor1) then	-- if neither are set, try to get editors from wikidata
			get_name_list ('editor', citeq_args, qid, wdl);						-- modify citeq_args table with editors from wikidata
		end
	end
	
	local author_count = 0
	for k, v in pairs(citeq_args) do
		if k:find("^author%d+$") then
			author_count = author_count + 1
		end
	end
	if author_count > 8 then -- convention in astronomy journals
		citeq_args'display-authors' = citeq_args'display-authors' or 3
	end
	
	local editor_count = 0
	for k, v in pairs(citeq_args) do
		if k:find("^editor%d+$") then
			editor_count = editor_count + 1
		end
	end
	if editor_count > 8 then -- convention in astronomy journals
		citeq_args'display-editors' = citeq_args'display-editors' or 3
	end
	local returntext = frame:expandTemplate{title = 'citation', args = citeq_args}	-- render the template
	if citeq_args.mode ~= 'cs1' then
		returntext = returntext .. ','
	end
	returntext = returntext .. ' Wikidata ' .. qid ..  -- go through special "WDQ (identifier)" redirect to reduce clutter in "What links here" and improve reverse lookup. (A better name might be "QID (identifier)", but needs to be kept in sync with what's used by Template:QID.)
	return returntext
end
return citeq