Die Dokumentation für dieses Modul kann unter Modul:Marker/doc erstellt werden

-- module variable and administration
local mk = {
	moduleInterface = {
		suite  = 'Marker',
		serial = '2022-10-22',
		item   = 40852170
	}
}

-- module import
-- require( 'strict' )
local mi = require( 'Module:Marker utilities/i18n' )
local mu = require( 'Module:Marker utilities' )
local mp = require( 'Module:Marker/Params' )
local cm = require( 'Module:CountryData' )
local wu --  for Module:Wikidata utilities

local function checkYn( keys, args )
	local s
	for i, key in ipairs( keys ) do
		args[ key ] = args[ key ] or ''
		s = mu.yesno( args[ key ] )
		if s then -- 'y' or 'n'
			args[ key ] = ''
			mp.wdContent[ key ] = s == 'y'
		elseif args[ key ] ~= '' then
			mp.wdContent[ key ] = false
		end
	end
end

local function initialParameterCheck( frame )
	local entity = nil
	local wrongQualifier = false
	local show = {}

	-- checking keys and copying values to args
	local args = mu.checkArguments( frame:getParent().args, mp.p )

	-- remove control characters
	local descrDiv
	for key, v in pairs( mp.p ) do
		if args[ key ] then
			args[ key ], descrDiv = mu.removeCtrls( args[ key ], true )
		else
			args[ key ] = ''
		end
	end

	-- checking show and format parameters
	if mu.isSet( args.show ) then
		show = mu.getShow( mp.defaultShow, args.show, mp.show )
		if show.noname then
			show.noname = nil
			show.name = nil
		end
		if not show.poi and not show.coord then
			mu.addMaintenance( mi.maintenance.showNoneUsed )
		end
	else
		show.poi = true
		show.name = true
		if args.format:match( mp.allowedFormats ) then
			show.name = nil
			mu.addMaintenance( mi.maintenance.poiMode )
		elseif mu.isSet( args.format ) then
			mu.addMaintenance( mi.maintenance.unknownFormat )
		end
	end

	-- checking Wikidata entitity
	if args.wikidata ~= '' then
		wu = require( 'Module:Wikidata utilities' )
--		args.wikidata, entity, wrongQualifier = wu.getEntityId( args.wikidata or '' )
		args.wikidata, entity, wrongQualifier = wu.getEntity( args.wikidata or '' )
		if wrongQualifier then
			mu.addMaintenance( mi.maintenance.wrongQualifier )
		elseif args.wikidata ~= '' then
			mu.addMaintenance( mi.maintenance.wikidata )
		end

		-- treatment of social media services
		if args.wikidata ~= '' and show.socialmedia then
			for i, value in ipairs( mp.socialMedia ) do
				args[ value ] = 'y'
			end
		end
	end

	-- y/n allow/disallow output
	if not mu.isSet( args.nameLocal ) then
		args.nameLocal = 'n'
	end
	checkYn( mp.ynCheckList, args )

	args.noGpx = mu.yesno( args.noGpx ) == 'y'

	args.zoom = math.floor( tonumber( args.zoom ) or mi.defaultZoomLevel )
	if args.zoom < 0 or args.zoom > mi.maxZoomLevel then
		args.zoom = mi.defaultZoomLevel
	end

	-- checking coordinates and converting DMS to decimal coordinates if necessary
	mu.checkCoordinates( args )
	-- remove namespace from category
	mu.checkCommonsCategory( args )
	for i, param in ipairs( mi.maintenance.parameters ) do
		if mu.isSet( args[ param ] ) then
			mu.addMaintenance( mw.ustring.format( mi.maintenance.parameterUsed, param ) )
		end
	end

	if mu.isSet( args.styles ) then
		args.styles = mi.nameStyles[ args.styles:lower() ] or args.styles
	else
		args.styles = nil
	end

	return args, entity, show
end

-- getting data from Wikidata
local function getDataFromWikidata( args, show, page, country, entity )
	if args.wikidata == '' then
		return
	end

	if args.type == '' then
		local p31 = wu.getValues( entity, mi.properties.instanceOf, mi.p31Limit )
		args.type = mu.typeSearch( p31, entity )
	end

	args.nameLocal = mp.wdContent.nameLocal or args.nameLocal
	mu.getNamesFromWikidata( args, mp.wdContent, page, country, entity )

	mu.getCoordinatesFromWikidata( args, mp.wdContent, entity )
	mu.getCommonsCategory( args, entity )

	if show.name then
		mu.getArticleLink( args, entity, page )
	end

	-- getting more values from Wikidata
	local c
	for key, value in pairs( mp.wdContent ) do
		if not args[ key ] or args[ key ] == '' then
			if key == 'image' or key == 'rss' then
				args[ key ] = wu.getValue( entity, mp.wd[ key ].p )
			elseif value and mp.wd[ key ] and show.name then
				c = tonumber( mp.wd[ key ].c ) or 1
				c = wu.getValues( entity, mp.wd[ key ].p, c )
				args[ key ] = table.concat( c, ', ' )
				if args[ key ] ~= '' and mp.wd[ key ].f then
					args[ key ] = mw.ustring.format( mp.wd[ key ].f, args[ key ] )
				end
			end
			mp.wdContent[ key ] = args[ key ] ~= ''
		end
	end
end

local function finalParameterCheck( args, show, country, entity )
	-- coordinates are neccessary
	show.noCoord = args.lat == '' or args.long == ''
	if show.noCoord then
		show.name  = ''
		show.poi   = false
		show.coord = false
		mu.addMaintenance( mi.maintenance.missingCoord )
	end

	-- image check
	if not mp.wdContent.image or mi.options.WDmediaCheck then 
		mu.checkImage( args, entity )
	end

	-- status check
	mu.checkStatus( args )

	-- getting Marker type and group
	mu.checkTypeAndGroup( args )
	if mi.options.useTypeCateg and args.typeTable then
		for i, tp in ipairs( args.typeTable ) do
			mu.addMaintenance( mw.ustring.format( mi.maintenance.type, tp ) )
		end
	end

	-- url check
	mu.checkUrl( args )

	-- checking name existence, splitting name and link from [[link|name]]
	if args.name == '' then
		args.name = mi.maintenance.missingName
		mu.addMaintenance( mi.maintenance.missingNameMsg )
	end
	if args.name:find( '<', 1, true ) or args.name:find( '{{', 1, true ) or
		args.alt:find( '<', 1, true ) or args.alt:find( '{{', 1, true ) then
		mu.addMaintenance( mi.maintenance.malformedName )
	end
	mu.removeStars( args, { 'alt', 'nameExtra' } )
	args.givenName = mu.getName( args.alt, args.wikiPage )
	args.displayName = mu.getName( args.name, args.wikiPage )
	if not args.givenName.exists then
		args.givenName = args.displayName
	end
	if args.nameLocal ~= '' and args.givenName.name == args.nameLocal then
		args.nameLocal = ''
	end
end

-- distinguishing marker symbols, default: number
local function makeMarkerProperties( args, show )
	args.useIcon = false -- true: add pushpin symbol
	args.symbol = args.symbol:lower()

	if args.symbol == '' and show.poi and show.symbol then
		args.symbol = mu.getMakiIconName( args.type ) or ''
	end
	if args.symbol == '' or args.symbol == 'number' then
		args.symbol = '-number-' .. args.group
	elseif args.symbol == 'letter' then
		args.symbol = '-letter-' .. args.group
	elseif args.symbol:len() == 1 and args.symbol:match( '%w' ) then
		args.text = args.symbol:upper()
		mu.addMaintenance( mi.maintenance.numberUsed )
	elseif args.symbol ~= '' and args.text == '' and mu.getMaki( args.symbol ) then
		-- check if MAKI icon is available
		local m = mu.getMaki( args.symbol )
		if m and mu.isSet( m.im ) then
			args.text = mw.ustring.format( '[[File:%s|x14px|link=|class=noviewer]]',
				m.im )
		else
			-- fallback if no image is available
			args.text = args.symbol:sub( 1, 1 ):upper()
			args.useIcon = true
		end
	elseif args.symbol ~= '' and not mu.getMaki( args.symbol ) then
		args.symbol = 'cross'
		args.group = 'error'
		args.text = mi.maintenance.closeX
		mu.addMaintenance( mi.maintenance.unknownIcon )
	end
	mu.getColor( args )
end

local function makeName( result, args, show, page, country )
	local tag

	if args.displayName.all ~= '' or args.nameExtra ~= '' or args.nameLocal ~= '' then
		local s, t
		if args.url ~= '' and args.displayName.pageTitle == '' then
			s = '[' .. args.url .. ' '
				.. mu.replaceBrackets( args.displayName.name ) .. ']'
		else
			s = args.displayName.all
		end
		if args.nameExtra ~= '' then
			s = s .. ' ' .. args.nameExtra
		end

		-- supporting right-to-left wikis
		if s ~= '' then
			t = mw.uri.anchorEncode( args.givenName.name ):gsub( '&amp;', '&' )
				:gsub( '&#039;', "'" )
			tag = mw.html.create( 'bdi' )
				:attr( 'id', 'vCard_' .. t )
				:attr( 'class', 'p-name fn org listing-name'
					.. mu.addWdClass( mp.wdContent.name ) )
				:cssText( args.styles )
				:wikitext( s )
			if not show.noCoord and not show.poi and not show.coord then
				tag:addClass( 'listing-without-marker' )
			end
			table.insert( result, tostring( tag ) )
		end

		if args.nameLocal ~= '' then
			tag = mu.languageSpan( args.nameLocal, mi.texts.hintName, page,	country,
				'listing-name-local' .. mu.addWdClass( mp.wdContent.nameLocal ) )
			table.insert( result, tag )
		end

		if args.url ~= '' and args.displayName.pageTitle ~= '' then
			-- both article and web links
			tag = mu.addLinkIcon( 'listing-url', args.url, mi.iconTitles.internet,
				'internet' )
			table.insert( result, tag )
		end
	elseif args.url ~= '' then
		tag = mw.html.create( 'span' )
			:addClass( 'listing-url' )
			:wikitext( '[' .. args.url .. ']' )
		table.insert( result, tostring( tag ) )
	end
end

local function makeNameAndAdditions( result, args, show, page, country, entity )
	local s = ''
	local rMarker = {}

	-- adding name, airport code and sister-project icons
	if show.name then
		makeName( rMarker, args, show, page, country )
		s = table.concat( rMarker, ' ' )

		local icons = {}
		local onlyWikidata = mi.options.showSisters and
			mu.makeSisterIcons( icons, args, page, country, entity )
		mu.makeSocial( icons, args, mp.wdContent, args.givenName.name )
		if #icons > 0 then
			s = s .. ( onlyWikidata and '' or ' ' ) .. table.concat( icons, '' )
		end
		mu.tableInsert( result, s )

		-- adding airport code and coordinate if requested and available
		s = {}
		if not show.noairport and args.type == mi.airportType then
			mu.tableInsert( s, mu.makeAirport( args, mp.wdContent ) )
		end
		if show.coord then
			table.insert( s, mu.dmsCoordinates( args.lat, args.long,
				args.givenName.name, mp.wdContent.lat, country.extra ) )
		end
		if #s > 0 then
			s = '<span class="listing-parenthesis">(</span>'
				.. table.concat( s, '<span class="listing-delimiter">, &#8203;</span>' )
				.. '<span class="listing-parenthesis">)</span>'
			table.insert( result, s )
		end

	-- adding coordinate only
	elseif show.coord then
		table.insert( result, mu.dmsCoordinates( args.lat, args.long,
			args.givenName.name, mp.wdContent.lat, country.extra ) )
	end
end

-- main marker function

function mk.marker( frame )
	mu.initMaintenance( mi.moduleNames.marker )
	local page = mu.getPageData()

	-- copying frame:getParent().args to template arguments, args, parameter check
	-- returning Wikidata entity and display options
	local args, mkEntity, show = initialParameterCheck( frame )
	show.inline = true

	-- get country-specific technical parameters
	local country = cm.getCountryData( mkEntity, nil, args.country )
	if country.unknownCountry then
		mu.addMaintenance( mi.maintenance.unknownCountry )
	end
	-- for map support
	country.extra = mi.defaultSiteType
	if country.iso_3166 and country.iso_3166 ~= '' then
		country.extra = country.extra .. '_region:' .. country.iso_3166
	end

	-- add additional parameters

	-- associated Wikivoyage page of the location in current Wikivoyage branch
	-- possibly modified by mu.getArticleLink()
	args.wikiPage  = ''

	getDataFromWikidata( args, show, page, country, mkEntity )
	if args.commonscat ~= '' then
		args.commonscat = args.commonscat:gsub( ' ', '_' )
	end

	-- parameter check after data import from Wikidata
	finalParameterCheck( args, show, country, mkEntity )

	-- generating output
	local result = {} -- output string table, wrapper is added later
	-- adding status icons
	mu.tableInsert( result, mu.makeStatusIcons( args ) )

	-- adding marker symbol
	makeMarkerProperties( args, show )
	mu.setCopyMarker( args, show )
	if show.poi or mu.isSet( args.copyMarker ) then
		table.insert( result, mu.makeMarkerSymbol( args, args.givenName.all, frame ) )
	end

	makeNameAndAdditions( result, args, show, page, country, mkEntity )
	result = mu.makeWrapper( result, args, page, country, show, mp.markerData, 'Marker', frame )

	local ns = page.namespace
	if ns ~= 4 and ns ~= 10 and ns ~= 828 then
		result = result .. mu.getMaintenance()
		if mi.options.usePropertyCateg then
			local m = mi.maintenance.properties -- format string
			result = result .. ( wu and wu.getCategories( m ) or '' )
				.. mu.getCategories( m ) .. cm.getCategories( m )
		end
	end
	return result
end

return mk