Модуль:Wikidata/Places: відмінності між версіями

нема опису редагування
Немає опису редагування
Немає опису редагування
local categorizeByPlaceOfBirthAndDeathcategorizeByPlace = true;
 
local WDS = require( 'Module:WikidataSelectors' );
local Flags = require( 'Module:Wikidata/Flags' );
local p = {};
config = {
local project = 'ukwiki';
hideSameLabels = false,
hidePartOfLabels = false,
hideUnitsForCapitals = true,
reverseOrder = false,
}
};
 
local function min( prev, next )
if ( prev == nil ) then return next;
elseif ( prev > next ) then return next;
else returnelseif prev; end> next then
return next;
else
return prev;
end
end
 
local function max( prev, next )
if ( prev == nil ) then return next;
elseif ( prev < next ) then return next;
else returnelseif prev; end< next then
return next;
else
return prev;
end
end
 
local function getTimeBoundariesFromProperty( context, propertyId )
mw.log( 'Get time boundaries for ' .. propertyId .. '...');
 
local dateClaims = WDS.filter( context.entity.claims, propertyId );
if ( not dateClaims or #dateClaims == 0 ) then return nil; end
return nil;
mw.log( 'Get time boundaries for ' .. propertyId .. '... Got ' .. #dateClaims .. ' date claim(s)');
end
 
-- only support exact date so far, but need improvment
local right = nil;
for _, claim in pairs( dateClaims ) do
if ( not claim.mainsnak ) then return nil; end
local boundaries = context.parseTimeBoundariesFromSnak( claim.mainsnak );
if ( not boundaries ) then return nil; end
left = min( left, boundaries[ 1 ] );
right = max( right, boundaries[ 2 ] );
end
 
if ( not left or not right ) then return nil; end
 
mw.log( 'Time boundaries for ' .. propertyId .. ' are ' .. left .. ' and ' .. right );
return { left, right };
end
local left = nil;
local right = nil;
if ( statement.qualifiers and statement.qualifiers[qualifierId] ) then
for _, qualifier in pairs( statement.qualifiers[qualifierId] ) do
local boundaries = context.parseTimeBoundariesFromSnak( qualifier );
if ( not boundaries ) then return nil; end
left = min( left, boundaries[1] );
right = max( right, boundaries[2] );
end
 
if ( not left or not right ) then
return nil;
end
end
 
local function getParentsInBoundariesSnakImpl( context, entityentityId, boundaries, propertyIds, selectors )
local results = {};
 
return results;
end
for _, propertyId in ipairs( propertyIds ) do
if (not string.match( propertyId, '^P%d+$' )) then error('Incorrect propertyId: ' + propertyId); end
local selector;
if (selectors ~= nil) then
selector = selectors[propertyId] or propertyId;
else
selector = propertyId;
end
 
local entityClaims = {};
if entity.claims then
for _, entityClaims[propertyId] in= ipairsmw.wikibase.getAllStatements( propertyIdsentityId, propertyId ) do;
 
local filteredClaims = WDS.filter( entity.claims, propertyId .. '[rank:preferred, rank:normal]' );
local filteredClaims = WDS.filter( entityClaims, selector .. '[rank:preferred, rank:normal]' );
if filteredClaims then
for _, claim in pairs(if filteredClaims ) dothen
for _, claim in pairs( filteredClaims ) do
if not boundaries or not propertyIds or #propertyIds == 0 then
if not boundaries or not propertyIds or #propertyIds == 0 then
table.insert( results, claim.mainsnak );
else
local startBoundaries = getTimeBoundariesFromQualifiers( context, claim, 'P580' );
local endBoundaries = getTimeBoundariesFromQualifiers( context, claim, 'P582' );
if ( startBoundaries == nil or startBoundaries[2] <= boundaries[1] ) and
( endBoundaries == nil or endBoundaries[1] >= boundaries[2] )
then
table.insert( results, claim.mainsnak );
elseend
local startBoundaries = getTimeBoundariesFromQualifiers( context, claim, 'P580' );
local endBoundaries = getTimeBoundariesFromQualifiers( context, claim, 'P582' );
if ( (startBoundaries == nil or startBoundaries[2] <= boundaries[1] )
and ( endBoundaries == nil or endBoundaries[1] >= boundaries[2] ) ) then
table.insert( results, claim.mainsnak );
end
end
end
end
end
 
if #results > 0 then
break;
end
end
end
end
 
local function getParentsInBoundariesSnak( context, entityentityId, boundaries )
if ( not entity )entityId then error('entityentityId must be specified'); end
if ( type(entityentityId) ~= 'tablestring' ) then error('entityentityId must be tablestring'); end
if ( not boundaries ) then error('boundaries must be specified'); end
if ( type(boundaries) ~= 'table' ) then error('boundaries must be table'); end
 
local results = getParentsInBoundariesSnakImpl( context, entityentityId, boundaries, {'P17'} ) -- country
 
for r, result in pairs( results ) do
end
local resultId = result.datavalue.value.id;
if ( resultId == entity.id )entityId then
return nil;
end
local isCountry = false;
local isUnion = false;
if ( entity and
and entity.claims and
and entity.claims.P31 ) then
then
for c, claim in pairs( entity.claims.P31 ) do
if ( claim and
and claim.mainsnak and
and claim.mainsnak.datavalue and
and claim.mainsnak.datavalue.value and
and claim.mainsnak.datavalue.value['numeric-.id'] ) then
then
local typeId = 'Q' .. claim.mainsnak.datavalue.value['numeric-id'];
local typeId = claim.mainsnak.datavalue.value.id;
isCountry = isCountry or countries[typeId];
isUnionisCountry = isUnionisCountry or unionscountries[ typeId ];
isUnion = isUnion or unions[ typeId ];
end
end
end
 
local function isPartOfNext( prevLabel, nextLabel )
return ( mw.ustring.len( prevLabel ) > mw.ustring.len( nextLabel ) )
and ( mw.ustring.sub( prevLabel, mw.ustring.len( prevLabel ) - mw.ustring.len( nextLabel ) + 1 ) == nextLabel );
end
 
function p.formatPlaceWithQualifiers( context, options, statement )
local property = mw.ustring.upper( options.property );
 
mw.log( 'formatPlaceWithQualifiers(..., ' .. property .. ')');
local actualDateBoundariesProperties = nil;
if property == 'P19' then actualDateBoundariesProperties = {'P569','P570'}; end
if property == 'P20' then actualDateBoundariesProperties = {'P570','P569'}; end
if property == 'P119' then actualDateBoundariesProperties = {'P570','P569'}; end
 
local boundaries = nil;
if actualDateBoundariesProperties ~= nil then
boundaries = getTimeBoundariesFromProperties( context, actualDateBoundariesProperties );
end
 
local entriesToLookupCategory = {};
local result = '';
local baseResult = context.formatSnak( options, statement.mainsnak, circumstances );
if not baseResult then
return nil;
end
insertFromSnak( statement.mainsnak, entriesToLookupCategory )
 
local hasAdditionalQualifiers = false;
if ( statement.qualifiers ) then
--country
if ( statement.qualifiers.P17 ) then
for i, qualifier in ipairs( statement.qualifiers.P17 ) do
resultlocal parentOptions = result .. ', ' .. context.formatSnakcloneOptions( options, qualifier );
local qualifierEntityId = qualifier.datavalue.value.id;
parentOptions[ 'text' ] = getLabel( context, qualifierEntityId, boundaries );
local link = context.formatSnak( parentOptions, qualifier );
 
if p.config.reverseOrder then
result = link .. ', ' .. result;
else
result = result .. ', ' .. link;
end
insertFromSnak( qualifier, entriesToLookupCategory )
hasAdditionalQualifiers = true;
end
 
if ( statement.mainsnak and
and statement.mainsnak.datavalue and
and statement.mainsnak.datavalue.value and
and statement.mainsnak.datavalue.value['numeric-.id'] ) then
then
local entity = mw.wikibase.getEntity( 'Q' .. statement.mainsnak.datavalue.value['numeric-id'] );
local entityId = statement.mainsnak.datavalue.value.id;
local parentSnaks = { statement.mainsnak };
local parentEntitiesparentEntityIds = { entityentityId };
 
if actualDateBoundariesProperties ~= nil then
local actualDateBoundariesProperty = nil;
local filterCapitalOf = {
if ( property == 'P19' ) then actualDateBoundariesProperty = 'P569'; end
[ entityId ] = getParentsInBoundariesSnakImpl( context, entityId, boundaries, {'P1376'} )
if ( property == 'P20' ) then actualDateBoundariesProperty = 'P570'; end
};
if ( property == 'P119' ) then actualDateBoundariesProperty = 'P570'; end
if boundaries then
if ( actualDateBoundariesProperty ~= nil ) then
local entityOptions = context.cloneOptions( options );
local boundaries = getTimeBoundariesFromProperty( context, actualDateBoundariesProperty );
if entityOptions['text'] = getLabel( context, entityId, boundaries ) then;
local entityOptions = options;
-- local entityOptions = mw.clone( options );
entityOptions['text'] = getLabel( context, entity, boundaries );
baseResult = context.formatSnak( entityOptions, statement.mainsnak, circumstances );
 
local parentparentId = entityentityId;
while ( parentparentId ~= nil ) do
-- get parent
local newParentSnaks = getParentsInBoundariesSnak( context, parentparentId, boundaries );
if ( not newParentSnaks or #newParentSnaks == 0 ) then
parentparentId = nil;
elseif ( #newParentSnaks == 1 ) then
local parentSnak = newParentSnaks[ 1 ];
parentparentId = mw.wikibase.getEntity( 'Q' .. parentSnak.datavalue.value['numeric-.id'] );
 
table.insert( parentSnaks, parentSnak );
table.insert( parentEntitiesparentEntityIds, parentparentId );
filterCapitalOf[ parentId ] = getParentsInBoundariesSnakImpl( context, parentId, boundaries, { 'P1376' } );
else
parentparentId = nil;
result = result .. '[[Категорія:Вікіпедія:Сторінки з неоднозначними геоланками]]';
end
end
 
if ( not hasAdditionalQualifiers ) then
for i = 2, #parentSnaks, 1 do
local parentSnak = parentSnaks[ i ];
insertFromSnak( parentSnak, entriesToLookupCategory )
end
end
 
-- mw.logObject( parentSnaks );
do
local i = #parentSnaks;
while ( i > 1 ) do
local prevEntityprevEntityId = parentEntitiesparentEntityIds[ i - 1 ];
-- TODO: use English labels, if there is no current language labels
local prevLabel = getLabel( context, prevEntityprevEntityId, boundaries ) or '';
local nextEntitynextEntityId = parentEntitiesparentEntityIds[ i ];
local nextLabel = getLabel( context, nextEntitynextEntityId, boundaries ) or '';
if (p.config and p.config.hideSameLabels == true and prevLabel == nextLabel ) then
-- do not output same label twice (NY, NY, USA)
table.remove( parentSnaks, i );
table.remove( parentEntitiesparentEntityIds, i );
elseif (p.config and p.config.hidePartOfLabels == true and isPartOfNext( prevLabel, ' ' .. nextLabel ) ) then
-- do not output same label if it's part of previos
table.remove( parentSnaks, i - 1 );
table.remove( parentEntitiesparentEntityIds, i - 1 );
elseif p.config and p.config.hideUnitsForCapitals == true then
-- do not ouput items whose capital is the first item
local capitalId = nil;
for _capitalId, capitalSnaks in pairs( filterCapitalOf ) do
if #capitalSnaks > 0 then
for __, capitalSnak in pairs( capitalSnaks ) do
if parentSnaks[ i ].datavalue.value.id == capitalSnak.datavalue.value.id then
capitalId = _capitalId;
break;
end
end
end
end
if capitalId ~= nil then
if i == #parentSnaks then
i = i - 1;
end
while i > 1 and parentEntityIds[ i ] ~= capitalId do
table.remove( parentSnaks, i );
table.remove( parentEntityIds, i );
i = i - 1;
end
end
end
i = i - 1;
end
 
if ( isSkipTopLevel( parentEntitiesparentEntityIds[ #parentEntitiesparentEntityIds ] ) ) then
table.remove( parentSnaks, #parentEntitiesparentEntityIds );
table.remove( parentEntitiesparentEntityIds, #parentEntitiesparentEntityIds );
end
 
if ( not hasAdditionalQualifiers ) then
for i = 2, #parentSnaks, 1 do
local parentSnak = parentSnaks[ i ];
 
local parentOptions = context.cloneOptions( options );
-- local parentOptions['text'] = mw.clonegetLabel( optionscontext, parentEntityIds[ i ], boundaries );
parentOptions['text'] = getLabel( context, parentEntities[i], boundaries );
 
if p.config.reverseOrder then
result = result .. ', ' .. context.formatSnak( parentOptions, parentSnak );
result = context.formatSnak( parentOptions, parentSnak ) .. ', ' .. result;
else
result = result .. ', ' .. context.formatSnak( parentOptions, parentSnak );
end
end
end
end
 
if ( options[ 'thisLocationOnly'] )] then
result = baseResult .. context.formatRefs( options, statement );
elseif p.config.reverseOrder then
result = result .. baseResult .. context.formatRefs( options, statement );
else
result = baseResult .. result .. context.formatRefs( options, statement );
end
 
if categorizeByPlace then
if ( categorizeByPlaceOfBirthAndDeath ) then
if ( property == 'P19' ) then result = result .. getCategory( 'P1464', entriesToLookupCategory ); end
if ( property == 'P20' ) then result = result .. getCategory( 'P1465', entriesToLookupCategory ); end
if ( property == 'P119' ) then result = result .. getCategory( 'P1791', entriesToLookupCategory ); end
end
 
-- append entity id from snak to result
function insertFromSnak( snak, result )
if ( not categorizeByPlaceOfBirthAndDeath )categorizeByPlace then
return;
end
if ( snak and
and snak.datavalue and
and snak.datavalue.type == 'wikibase-entityid' and
and snak.datavalue.value and
and snak.datavalue.value[ 'entity-type' ] == 'item' ) then
then
table.insert( result, 'Q' .. snak.datavalue.value['numeric-id'] );
table.insert( result, snak.datavalue.value.id );
end
end
 
function getCategory( propertyToSearchpropertyId, entriesToLookupCategoryFor )
for _, placeId in pairs( entriesToLookupCategoryFor ) do
local placeEntityclaims = mw.wikibase.getEntitygetBestStatements( placeId, propertyId);
local claims = WDS.filter( placeEntity.claims, propertyToSearch );
 
if ( claims ) then
for _, claim in pairs( claims ) do
if ( claim.mainsnak and
and claim.mainsnak and
and claim.mainsnak.datavalue and
and claim.mainsnak.datavalue.type == "'wikibase-entityid" ) then'
then
local catEntityId = 'Q' .. claim.mainsnak.datavalue.value["numeric-id"];
local catEntitycatEntityId = mwclaim.wikibasemainsnak.getEntity( catEntityId )datavalue.value.id;
local catSitelink = mw.wikibase.getSitelink(catEntityId);
if ( catEntity and catEntity.sitelinks and catEntity.sitelinks[project] and catEntity.sitelinks[project].title ) then
if (catSitelink) then
return '[[' .. catEntity.sitelinks[project].title .. ']]';
return '[[' .. catSitelink .. ']]';
end
end
return '';
end
 
 
local historicNamesProperties = { 'P1813', 'P1448', 'P1705' };
 
local langCode = mw.language.getContentLanguage():getCode();
local historicNamesPropertySelectors = {
P1813 = 'P1813[language:' .. langCode .. ']',
P1448 = 'P1448[language:' .. langCode .. ']',
P1705 = 'P1705[language:' .. langCode .. ']'
};
 
-- get current of historic name of place
function getLabel( context, entityentityId, boundaries )
if not entityentityId then
return nil;
end
if (type(entityId) ~= 'string') then error('incorrect type of entityId argument'); end;
 
local lang = mw.language.getContentLanguage();
local langCode = lang:getCode();
 
-- name from label
local label = mw.wikibase.getLabel( entityId );
-- TODO: lang:getFallbackLanguages()
local label = nil;
if entity.labels then
if entity.labels[langCode] and entity.labels[langCode].value then
label = entity.labels[langCode].value;
elseif entity.labels.en and entity.labels.en.value then
label = entity.labels.en.value;
end
end
 
-- name from properties
local results = getParentsInBoundariesSnakImpl( context, entityentityId, boundaries, {
historicNamesProperties, historicNamesPropertySelectors);
'P1813[language:' .. langCode .. ']',
'P1448[language:' .. langCode .. ']',
'P1705[language:' .. langCode .. ']'
} );
 
for r, result in pairs( results ) do
if result.datavalue and
and result.datavalue.value and
and result.datavalue.value.text then
then
label = result.datavalue.value.text;
break;
 
local function calculateEndDateTimestamp( context, options, statement )
if (not context) then error( 'context not specified' ) end;
if (not options) then error( 'options not specified' ) end;
if (not options.entity) then error( 'options.entity missing' ) end;
if (not statement) then error( 'statement not specified' ) end;
 
if ( statement.qualifiers and statement.qualifiers.P582 ) then
for i, qualifier in ipairs( statement.qualifiers.P582 ) do
local parsedTime = context.parseTimeFromSnak( qualifier );
if ( parsedTime ) then
return parsedTime;
end
 
-- check death day... do we have it at all?
for h, propertyId in pairs( { "P570", "P577", "P571P576" } ) do
local dateClaims = context.selectClaims( options, propertyId );
if ( dateClaims ) then
for i, statement in ipairs( dateClaims ) do
local parsedTime = context.parseTimeFromSnak( statement.mainsnak );
if ( parsedTime ) then
return parsedTime;
end
 
function p.formatCountryClaimWithFlag( context, options, statement )
if (not context) then error('context not specified') end;
if (not options) then error('options not specified') end;
if (not options.entity) then error('options.entity is missing') end;
if (not statement) then error('statement not specified') end;
 
if not statement.mainsnak or
local countryEntityId = nil;
not statement.mainsnak.datavalue or
local countryEntity = nil;
if ( statement.mainsnak and statement.mainsnak.datavalue and not statement.mainsnak.datavalue.value and statement.mainsnak.datavalue.value["numeric-id"] ) thenor
countryEntityId = 'Q' ..not statement.mainsnak.datavalue.value["numeric-.id"];
then
countryEntity = mw.wikibase.getEntity( countryEntityId );
local result = context.formatStatementDefault( context, options, statement );
if not result then
return '';
end
return '<span class="country-name">' .. result .. '</span>';
end
local countryEntityId = statement.mainsnak.datavalue.value.id;
if not countryEntity then
return '<span class="country-name">' .. context.formatStatementDefault( context, options, statement ) .. '</span>';
end
 
local endDateTimestamp = calculateEndDateTimestamp( context, options, statement );
local boundaries = getTimeBoundariesFromProperties( context, {'P570', 'P577', 'P571'} );
 
local countryOptions = context.cloneOptions( options );
if not countryOptions['text'] or countryOptions['text'] == '' then
countryOptions['text'] = getLabel( context, countryEntitycountryEntityId, boundaries );
end
 
local flag = Flags.getFlag( context, countryEntityId, endDateTimestamp );
if ( flag ) then
return flag .. '&nbsp;<span class="country-name">' .. context.formatStatementDefault( context, countryOptions, statement ) .. '</span>';
context.formatStatementDefault( context, countryOptions, statement ) ..
'</span>';
end
 
return '<span class="country-name">' .. context.formatStatementDefault( context, countryOptions, statement ) .. '</span>';
context.formatStatementDefault( context, countryOptions, statement ) ..
'</span>';
end
 
23 873

редагування