Module:Wp/sms/Databox

From Wikimedia Incubator

Documentation for this module may be created at Module:Wp/sms/Databox/doc

local property_blacklist = {
    'P138', --named after
    'P301', -- category's main topic
    'P360', --is a list of
    'P373', -- Commons category
    'P460', -- said to be the same as
    'P527', -- has part
    'P910', -- topic's main category
    'P935', -- Commons gallery
    'P971', -- category combines topics
    'P972', -- catalogue
    'P973', -- described at URL English
    'P1151', -- topic's main Wikimedia portal
    'P1200', -- bodies of water basin category
    'P1204', -- Wikimedia portal's main topic
    'P1282', -- OSM tag or key
    'P1343', -- described by source
    'P1382', -- coincident with
    'P1423', -- template's main topic
    'P1424', -- topic's main template
    'P1441', -- present in work
    'P1451', -- motto
    'P1456', -- List of monuments
    'P1464', -- category for people born here
    'P1465', -- category for people who died here
    'P1472', -- Commons Creator page
    'P1482', -- Stack Exchange -ǩeâlǥal
    'P1546', -- motto
    'P1549', -- demonyym
    'P1612', -- Commons Institution page
    'P1709', -- equivalent class
    'P1740', -- category for films shot at this location
    'P1753', -- list related to category
    'P1754', -- category related to list
    'P1791', -- category of people buried here
    'P1792', -- category of associated people
    'P1813', -- vuäʹnkõs nõmm 
    'P1889', -- different from
    'P1963', -- properties for this type
    'P2033', -- Category for pictures taken with camera
    'P2445', -- metasubclass of
    'P2517', -- category for recipients of this award
    'P2559', -- Wikidata usage instructions
    'P2670', -- has parts of the class
    'P2737', -- union of
    'P2738', -- disjoint union of
    'P2860', -- cites
    'P2888', -- exact match
    'P2959', -- permanent duplicated item
    'P3113', -- does not have part
    'P3176', -- uses property
    'P3722', -- Commons maps category
    'P3876', -- category for alumni of educational institution
    'P3921', -- Wikidata SPARQL query equivalent
    'P3950', -- narrower external class
    'P4195', -- category for employees of the organization
    'P4224', --category contains
    'P4839', -- Wolfram Language entity code
    'P5008', -- on focus list of Wikimedia project
    'P5125', -- wikimedia outline
    'P5607', -- located in the ecclesiastical territorial entity
    'P5996', -- Category for films in this language
    'P6104', -- Maintained by Wikiproject
    'P7084', -- related category
    'P7561', -- Category for the interior of the item
    'P7867', -- Category for maps
    'P8596', -- Category for the exterior of the item
    'P8933', -- Category for the view from the item 
    'P8989' -- Category for the view of the item
}

function valuesToKeys(array)
	local result = {}
	for _, v in pairs(array) do
		result[v] = true
	end
	return result
end

local p = {}

local function formatItemStatementsByLang(statements, langcode)
	local values = {}
	for i = 1, #statements do
		local statement = statements[i]
		local qid = statement.mainsnak.datavalue.value.id
		local label = mw.wikibase.getLabelByLang(qid, langcode) or mw.wikibase.getLabel(qid)
		table.insert(values, label)
	end
	return table.concat(values, ', ')
end

function p.databox(frame)
    local args = frame:getParent().args
    local itemId = nil
    if args.item then
        itemId = args.item
    end
    local lang = mw.language.getContentLanguage()
	local pagelang = frame:preprocess("{{PAGELANGUAGE}}")
	if pagelang then
		lang = mw.language.new(pagelang)
	end
    if args.language then
    	lang = mw.language.new(args.language)
    end
    local item = mw.wikibase.getEntity(itemId)
    
    if item == nil then
        mw.addWarning("Wikidata item not found")
        return ""
    end
    
    local databoxRoot = mw.html.create('div')
        :addClass('infobox')
        :css({
            float = 'right',
            border = '1px solid #aaa',
            ['max-width'] = '300px',
            padding = '0 0.4em',
            margin = '0 0 0.4em 0.4em',
        })

    --Title
    databoxRoot:tag('div')
        :css({
            ['text-align'] = 'center',
            ['background-color'] = '#f5f5f5',
            padding = '0.5em 0',
            margin = '0.5em 0',
            ['font-size'] = '120%',
            ['font-weight'] = 'bold',
        })
        :wikitext(item:getLabel(lang.code) or mw.title.getCurrentTitle().text)

     --Image
    local images = item:getBestStatements('P18')
    if #images == 1 then
        databoxRoot
            :tag('div')
            :wikitext('[[File:' .. images[1].mainsnak.datavalue.value .. '|frameless|300px]]')
    end

    --Table
    local dataTable = databoxRoot
        :tag('table')
        :css({
            ['text-align'] = 'left',
            ['font-size'] = '90%',
            ['word-break'] = 'break-word',
            ['width'] = '100%',
            ['table-layout'] = 'fixed',
        })
    
    dataTable:tag('caption')
             :css({
             	['background-color'] = '#f5f5f5',
             	['font-weight'] = 'bold',
             	['margin-top'] = '0.2em',
             })
    		 :wikitext(formatItemStatementsByLang(item:getBestStatements('P31'), lang.code))
  
    local properties = mw.wikibase.orderProperties(item:getProperties())
    local property_blacklist_hash = valuesToKeys(property_blacklist)
    property_blacklist_hash['P31'] = true --Special property

	local edit_message = mw.message.new('vector-view-edit'):plain()
    for _, property in pairs(properties) do
        local datatype = item.claims[property][1].mainsnak.datatype
        if datatype ~= 'commonsMedia' and datatype ~= 'external-id' and datatype ~= 'quantity' and datatype ~= 'wikibase-property' and datatype ~= 'geo-shape' and datatype ~= 'tabular-data' and not property_blacklist_hash[property] and #item:getBestStatements(property) <= 5 then
            local propertyValue = item:formatStatements(property)
            if datatype == 'wikibase-item' then
            	propertyValue.value = lang:ucfirst(formatItemStatementsByLang(mw.wikibase.getBestStatements(itemId, property), lang.code))
            end
            dataTable:tag('tr')
                :tag('th')
                    :attr('scope', 'row')
                    :wikitext(lang:ucfirst(mw.wikibase.getLabelByLang(property, lang.code) or propertyValue.label)):done()
                :tag('td')
                    :wikitext(frame:preprocess(propertyValue.value))
                    :wikitext('&nbsp;[[File:OOjs UI icon edit-ltr.svg|' .. edit_message .. '|12px|baseline|class=noviewer|link=https://www.wikidata.org/wiki/' .. item.id .. '#' .. property .. ']]')
        end
    end
     
     --Map
    local coordinates_statements = item:getBestStatements('P625')
    if #coordinates_statements == 1 and coordinates_statements[1].mainsnak.datavalue and coordinates_statements[1].mainsnak.datavalue.value.globe == 'http://www.wikidata.org/entity/Q2' then
        --We build the call to mapframe
        local latitude = coordinates_statements[1].mainsnak.datavalue.value.latitude
        local longitude = coordinates_statements[1].mainsnak.datavalue.value.longitude
        local geojson = {
            type = 'Feature',
            geometry = {
                type = 'Point',
                coordinates = { longitude, latitude }
            },
            properties = {
                title = item:getLabel(lang.code) or mw.title.getCurrentTitle().text,
                ['marker-symbol'] = 'marker',
                ['marker-color'] =  '#224422',
            }
        }
        databoxRoot:wikitext(frame:extensionTag('mapframe', mw.text.jsonEncode(geojson), {
            height = 300,
            width = 300,
            frameless = 'frameless',
            align = 'center',
            latitude = latitude,
            longitude = longitude,
            zoom = zoom
        }))
     end
     
     return tostring(databoxRoot)
end

return p