Модуль:Навигация-мини

Материал из Викитеки — свободной библиотеки
Перейти к навигации Перейти к поиску
Документация Документация

Подгружает данные из Викиданных и интерпретирует их, показывая в шапках статей. Используется в Модуль:Отексте, Шаблон:Отексте.

local p = {};
local wd = require("Module:WD");

-- will be appended to project code
local localLanguage = 'ru';
local localProject = 'wikisource';
local argSearch = 'ПОИСК';

local preferredLanguages = { localLanguage }

-- Mapping from local arguments to 
local projects = {
	{ arg = 'ВИКИТЕКА',	name = 'Викитека',	project='wikisource',		code='s',		logo='Wikisource-logo.svg',	title='Викитека',		titlePRS='Викитека'},
	{ arg = 'ВИКИПЕДИЯ',	name = 'Википедия',	project='wiki',			code='w',		logo='Wikipedia-logo.png',	title='Википедия',		titlePRS='Википедія' },
	{ arg = 'ВИКИСКЛАД',	name = 'Викисклад',	project='commons',		code='commons',		logo='Commons-logo.svg',	title='Фото, аудио и видео',	titlePRS='Фото, аудіо и видео',	monolanguage = true },
	{ arg = 'ВИКИНОВОСТИ',	name = 'Викиновости',	project='wikinews',		code='n',		logo='Wikinews-logo.svg',	title='Новости',		titlePRS='Новости' },
	{ arg = 'ВИКИГИД',	name = 'Викигид',	project='wikivoyage',		code='voy',		logo='wikivoyage-logo.svg',	title='Гид',			titlePRS='Гидъ' },
	{ arg = 'ВИКИВИДЫ',	name = 'Викивиды',	project='specieswiki',		code='species',		logo='Wikispecies-logo.svg',	title='Виды',			titlePRS='Виды',		monolanguage = true },
	{ arg = 'ВИКИДАННЫЕ',	name = 'Викиданные',	project='wikidata',		code='d',		logo='Wikidata-logo.svg',	title='Данные',			titlePRS='Данныя',		monolanguage = true },
	{ arg = 'ВИКИСЛОВАРЬ',	name = 'Викисловарь',	project='wikidictionary',	code='wikt:',		logo='Wiktionary-logo-ru.png',	title='Словарь',		titlePRS='Словарь' },
	{ arg = 'ВИКИУЧЕБНИК',	name = 'Викиучебник',	project='wikibooks',		code='b',		logo='Wikibooks-logo.svg',	title='Учебник',		titlePRS='Учебникъ' },
	{ arg = 'ВИКИВЕРСИТЕТ',	name = 'Викиверситет',	project='wikiversity',		code='v',		logo='Wikiversity-logo.svg',	title='Викиверситет',		titlePRS='Викиверситетъ' },
	{ arg = 'ВИКИЦИТАТНИК',	name = 'Викицитатник',	project='wikiquote',		code='q',		logo='Wikiquote-logo.svg',	title='Цитаты и афоризмы',	titlePRS='Цитаты и афоризмы' }
}

local parentProperties = {
--	'P921', -- main topic link
	'P910'  -- main category
	-- 'P629', -- edition or translation of
	-- 'P361', -- part of
}

-- local currentTitleFull = mw.title.getCurrentTitle().fullText;

--[[
Функция возвращает массив значений свойства propertyId из элемента entity
Возвращаются значения "preferred", если они есть, иначе значения "normal".
]]
local function getClaimValues( entity, propertyId )
    local result = {};
    local claim = nil;
    if (entity ~= nil) and (entity.claims ~= nil) then
      claim = entity.claims[ propertyId ];
    end
    if (claim ~= nil) then
      local b_prefered_mode = false;
      for key, value in pairs(claim) do
        local snak = nil;
        if value.rank == "preferred" then          -- предпочтительный ранг
          if not b_prefered_mode then
            result = {};
            b_prefered_mode = true;
          end
          snak = value.mainsnak;
        elseif (value.rank == "normal") and (not b_prefered_mode) then    -- обычный ранг
          snak = value.mainsnak;
        end
        if (snak ~= nil) and (snak.snaktype == "value") then
          if snak.datavalue.type == "wikibase-entityid" then
            result[#result+1] = "Q" .. snak.datavalue.value["numeric-id"];
          else
            result[#result+1] = snak.datavalue.value;
          end
        end
      end
    end
    return result;
end

--[[
-- функция для тестирования
-- {{#invoke:Навигация-мини|test_getClaimValues|Q20646238|P921}}
function p.test_getClaimValues (frame)
    local s_item = frame.args[1];
    local s_property = frame.args[2];
    local entity = mw.wikibase.getEntity(s_item);
    local data = getClaimValues(entity, s_property);
    local s_result = ""
    for key, value in pairs(data) do
      s_result = s_result .. "[" .. key .. "]: " .. tostring(value) .. "<br/>"
    end
    return s_result;
end
]]
--[[
function p.populateInterwikiByEntityId( entityId, result )
    if ( result == nil ) then
        result = {};
    end
    if ( entityId == nil ) then
        return result;
    end
    local entity = mw.wikibase.getEntity( entityId );
    if ( entity == nil ) then
        return result;
    end
    return p.populateInterwikiByEntity( entity, result );
end
]]
function p.populateInterwikiByEntity(entity, result)
	-- populate from entity interwiki
	local sitelinks = entity.sitelinks;
	if sitelinks ~= nil then
		for sitecode, sitelink in pairs( sitelinks ) do
			-- mw.log("  "..sitecode.." = "..sitelink.title);
			if result[sitecode] == nil then
				result[sitecode] = sitelink.title;
			end;
		end;
	end;
    -- check if entity have main topic item
    for _, propertyCode in pairs( parentProperties ) do
	    local parentEntityIds = getClaimValues( entity, propertyCode );
	    for _, parentEntityId in pairs( parentEntityIds ) do
              local entity2 = mw.wikibase.getEntity(parentEntityId);
--	        if propertyCode == 'P921' and result['wikidata'] == nil then
--	            result['wikidata'] = entity2.id; -- entity itself is a wikidata link
--	        end
	        p.populateInterwikiByEntity(entity2, result);
	    end;
	end;
	if result['commons'] == nil then
	    local commonsCategories = getClaimValues( entity, 'P373' );
	    for _, commonsCategory in pairs( commonsCategories ) do
	    	 result[ 'commons' ] = 'Category:' .. commonsCategory;
	    	 break;
	    end;
	end;
    return result;
end

local function toLink( project, s_link, s_title )
    return "&nbsp;[[Файл:" .. project.logo .. "|13px|link=" .. s_link .. "]]&nbsp;[[" .. s_link .. "|" .. s_title .. "]]";
end

function p.render( frame )
	local args = frame:getParent().args;
	local entity = mw.wikibase.getEntity();
	local wikidataInterwiki = {};
	-- Работа с Викиданными
	if entity ~= nil then
    	if wd.has_valid_item_value (entity, "P31", 17329259) or wd.has_valid_item_value (entity, "P31", 1580166) then
    		-- для энциклопедических и словарных статей (P31 = Q17329259/Q1580166) просматриваем P921 ("основная тема произведения")
   			-- mw.log("это энциклопедическая статья");
    		local topics = getClaimValues(entity, "P921");
    		for key, s_item_id in pairs(topics) do
    			-- mw.log("просматриваем: "..s_item_id);
    			if wikidataInterwiki['wikidata'] == nil then
   					wikidataInterwiki['wikidata'] = s_item_id;
   				end;
	    		wikidataInterwiki = p.populateInterwikiByEntity(mw.wikibase.getEntity(s_item_id), wikidataInterwiki);
			end;
		else
   			-- mw.log("это не энциклопедическая статья");
   			wikidataInterwiki['wikidata'] = entity.id;
			wikidataInterwiki = p.populateInterwikiByEntity(entity, wikidataInterwiki);
			if wikidataInterwiki['ruwikisource'] == mw.title.getCurrentTitle().fullText then
				wikidataInterwiki['ruwikisource'] = nil;
			end;
		end;
	end;
	--
	local IS_PRS = require( "Module:Header" ).parse_title( mw.title.getCurrentTitle().text , "isPRS" );
	local haveResult = false;
	local result = '&nbsp;<span style=\'float:right;\'>\'\'\'Википроекты:\'\'\'';
	for _, project in pairs( projects ) do
                local s_arg = project.arg;
                local s_code = project.code;
                local s_name = project.name;
		local s_title = "";
		if ( IS_PRS ) then
			s_title = project.titlePRS;
		else
			s_title = project.title;
		end
		repeat 
			-- do we have value provided as template argument?
			local provided = args[s_arg];
			if ( provided and #provided > 0 ) then
				-- keyword to locally suppress Wikidata output
				if provided ~= '__NULL__' then
					if ( project.project == localProject ) then
						result = result .. toLink( project, provided, s_title ) .. '[[Категория:Викитека:Ручная ссылка:' .. s_name .. ']]';
					else
						if ( mw.ustring.sub( provided , 1, 1 ) == ':' ) then
							provided = mw.ustring.sub( provided , 2 );
						end
						result = result .. toLink( project, s_code .. ':' .. provided, s_title ) .. '[[Категория:Викитека:Ручная ссылка:' .. s_name .. ']]';
					end
					haveResult = true;
				end
				break; -- continue to next project
			end
	
			if ( project.monolanguage ) then
				local projectCode = project.project;
				local title = wikidataInterwiki[ projectCode ];
				if ( title ) then
					result = result .. toLink( project, s_code .. ':' .. title, s_title ) .. '[[Категория:Викитека:Ссылка из Викиданных:' .. s_name .. ']]';
					haveResult = true;
					break;
				end
			else
				--TODO: handle native/official language 
				local foundProjectLink = false;
				for _, lang in pairs( preferredLanguages ) do
					local projectCode = lang .. project.project;
					local title = wikidataInterwiki[ projectCode ];
					if ( title ) then
						if ( project.project == localProject ) then
							if ( lang == localLanguage ) then
								result = result .. toLink( project, ':' .. title, s_title );
							else
								result = result .. toLink( project, ':' .. lang .. ':' .. title, s_title );
							end
						else
							if ( lang == localLanguage ) then
								result = result .. toLink( project, s_code .. ':' .. title, s_title );
							else
								result = result .. toLink( project, s_code .. ':' .. lang .. ':' .. title, s_title );
							end
						end;
						result = result .. '[[Категория:Викитека:Ссылка из Викиданных:' .. s_name .. ']]';
						foundProjectLink = true;
						break;
					end
				end
				if ( foundProjectLink ) then
					haveResult = true;
					break;
				end
			end

			-- still no link to wiki
			if ( project.project == 'wiki' ) then
				local searchString = args[ argSearch ] or frame.args.search;
				if ( searchString and #searchString > 0 ) then
					result = result .. toLink( project, s_code .. ':Special:Search/' .. searchString, s_title );
					haveResult = true; break; -- continue to next project
				end
			end

			break;
	  	until true;
	end
	local result = result .. '</span>';

	if ( haveResult ) then
		return result;
	end

	return;
end

return p;