Module:Statement

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Lua

CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules


This module contains functions to deal with a single statement or qualifier in structured data, whether the data comes from Wikidata or Structured Data on Commons. It can be used where you expect a property to only have a single value. If you need to support multiple statements or qualifiers for the same property ID, use a different module (such as Module:Wikidata statements) or write your own.

The module can be used both by other modules and directly from wikitext.

The module only uses best-rank statements: the preferred-rank statements (called “prominent” in Structured Data on Commons) if there are any, otherwise the normal-rank statements. Deprecated-rank statements are never used, even if they’re the only ones.

(This module is unrelated to {{Statement}}, a template to show a representation of a statement encoded in Wikitext.)

Example

[edit]

Example usage from Wikitext, getting the audio transcription (P9533) of the current file:

Recording of the word/phrase <q>{{#invoke:Statement|monolingualText|P9533}}</q>.

Example usage from Lua, doing the same thing (nil signifies the current file as the source of the statement):

local wikitext = require( 'Module:Statement' ).monolingualText( nil, 'P9533' )
return 'Recording of the word/phrase <q>' .. wikitext .. '</q>.'

On File:LL-Q188 (deu)-Natschoba-die Freiheit.wav, the result would look like this:

Recording of the word/phrase die Freiheit.

Usage

[edit]

General

[edit]

All the functions provided by this module can be called from other modules, or via {{#invoke:}} directly from Wikitext (e.g. in a template).

Wikitext usage

[edit]

When used from wikitext, the functions take one positional argument, the property ID, and three optional named arguments: |from=entityId as the entity ID to use, |somevalue=some value as the value to return in case of a somevalue statement/qualifier, and |novalue=no value as the value to return in case of a novalue statement/qualifier. The qualifier functions also take a second positional argument, the property ID of the qualifier.

For the entity ID, the alias |entityId=entityId instead of |from=entityId is also supported. If the entity ID is not specified, the entity connected to the current page is used, i.e. the MediaInfo of the current file page, or the Wikidata item linked to the current non-file page.

The returned value is generally wikitext-compatible, but as plain as is possible without losing information.

Module usage

[edit]

When used from another module, the functions in this module take two arguments:

entity
A full mw.wikibase.entity table (e.g. returned by a mw.wikibase.getEntity() call), or an entity ID as a string, or nil for the entity connected to the current page.
propertyId
The property ID of the statement to look for, as a string.

The qualifier functions take an additional third argument:

qualifierId
The property ID of the qualifier to look for, also as a string.

After this, both kinds of functions take two more optional arguments:

somevalueReturn
The value to return for a somevalue statement/qualifier (known as “unknown value” on Wikidata, or “some value” or “some value without a Wikidata item” in Structured Data on Commons). Defaults to nil.
novalueReturn
The value to return for a novalue statement/qualifier (known as “no value” on Wikidata, or “No value exists for this property” in Structured Data on Commons). Defaults to nil.

They return at least two values:

value
The same value that would be returned to wikitext, i.e. mostly-plain but wikitext-compatible, when the statement/qualifier has a proper value; or one of somevalueReturn/novalueReturn, when the statement has one of these special “values”; or nil if there is no statement/qualifier. See the individual function documentation for details on the value.
hasOther
Whether there were any additional statements (boolean). This module can’t be used to access the data of those statements, but you could use this flag to e.g. add some maintenance category like “Files with more than one something statements”.

The qualifier functions return a third value:

hasOtherQualifiers
Whether there were any additional qualifiers using the same property ID in the statement (boolean). As with hasOther for additional main statements, if this flag is true, this should probably be flagged up as unexpected, or you might want to use a different module if multiple values are genuinely expected.

Some functions return additional values, as documented below. (This does not apply when there is no statement/qualifier, or it does not have a proper value but instead somevalue/novalue.)

Main statement value functions

[edit]

These functions return the main value of the statement.

string

[edit]

Returns a string value. Note that the string data value type is used by several data types, including but not limited to string: this function can also be used with properties of some other data types, such as external identifiers. (For URLs you’ll want to use the URL functions instead, though, so the URL doesn’t get wikitext-escaped.)

Wikitext usage:

{{#invoke:Statement|string|P760|from=M96915718|somevalue=some value|novalue=no value}}

Module usage:

local wikitext, hasOther, string = statementModule.string( entity, propertyId, somevalueReturn, novalueReturn )

The returned wikitext is the string value, wikitext-escaped (but without any additional wrapping). The third return value, string, is the unescaped plain string value; if you don’t need it, you can leave it out.

url

[edit]

Returns a URL value.

Wikitext usage:

{{#invoke:Statement|url|P973|from=M85023113|somevalue=some value|novalue=no value}}

Module usage:

local url, hasOther = statementModule.url( entity, propertyId, somevalueReturn, novalueReturn )

entityId

[edit]

Returns an entity ID value. Can be used for properties of all entity types: items, properties, lexemes, senses, forms. (As of March 2022, there is no data type for MediaInfo entities.)

Wikitext usage:

{{#invoke:Statement|entityId|P6216|from=M43058895|somevalue=some value|novalue=no value}}

Module usage:

local entityId, hasOther, entityType = statementModule.entityId( entity, propertyId, somevalueReturn, novalueReturn )

The third return value, entityType, is the entity type of the value; if you don’t need it, you can leave it out.

monolingualText

[edit]

Returns a monolingual text value.

Wikitext usage:

{{#invoke:Statement|monolingualText|P1476|from=M96718296|somevalue=some value|novalue=no value}}

Module usage:

local wikitext, hasOther, text, language = statementModule.monolingualText( entity, propertyId, somevalueReturn, novalueReturn )

The returned wikitext is a string with wikitext for a language-tagged span, so that the full information is included. The third and fourth return values provide the plain text (not wikitext-escaped!) and language (as an mw.language instance) of the value.

time

[edit]

Returns a time value in full. See also the date functions, which return only the “relevant” part of the value, and can be used with the same properties.

Wikitext usage:

{{#invoke:Statement|time|P571|from=M38570|somevalue=some value|novalue=no value}}

Module usage:

local timestamp, hasOther, precision, calendar = statementModule.time( entity, propertyId, somevalueReturn, novalueReturn )

The timestamp is in ISO 8601 format. The precision is one of Wikibase’s precision constants (from 0 “billion years” to 11 “days”, or theoretically up to 14 “seconds”), and the calendar is an item ID (typically proleptic Gregorian calendar (Q1985727) or proleptic Julian calendar (Q1985786)). If you don’t need these, you can leave them out.

date

[edit]

Returns only the part of a time value that is “captured” by its precision, such as the date (without the time part), or only the year.

Wikitext usage:

{{#invoke:Statement|date|P571|from=M17811375|somevalue=some value|novalue=no value}}

Module usage:

local date, hasOther, precision, calendar, timestamp = statementModule.date( entity, propertyId, somevalueReturn, novalueReturn )

The date is typically the year, year-month, or year-month-day. The precision and calendar are as in the time functions; the original timestamp (likewise) is appended at the very end.

Qualifier functions

[edit]

These functions return the first qualifier with the given property ID of the statement. The statement is always the same one that would be returned by the main statement value functions; these functions are for returning the qualifier of that statement, not for selecting a statement based on its qualifiers. (At some point, someone™ should maybe write another module for that, but it isn’t this module.)

Generally speaking, these functions return the same format as their main statement value counterparts, except that (in module usage) the single hasOther flag is replaced by two, hasOtherStatement and hasOtherQualifier.

stringQualifier

[edit]

Returns a string qualifier.

Wikitext usage:

{{#invoke:Statement|stringQualifier|P170|P2093|from=M96915718|somevalue=some value|novalue=no value}}

Module usage:

local wikitext, hasOtherStatement, hasOtherQualifier, string = statementModule.stringQualifier( entity, propertyId, qualifierId, somevalueReturn, novalueReturn )

urlQualifier

[edit]

Returns a URL qualifier.

Wikitext usage:

{{#invoke:Statement|urlQualifier|P170|P2699|from=M79977121|somevalue=some value|novalue=no value}}

Module usage:

local url, hasOtherStatement, hasOtherQualifier = urlQualifier( entity, propertyId, qualifierId, somevalueReturn, novalueReturn )

entityIdQualifier

[edit]

Returns an entity ID qualifier.

Wikitext usage:

{{#invoke:Statement|entityIdQualifier|P170|P3831|from=M80857538|somevalue=some value|novalue=no value}}

Module usage:

local entityId, hasOtherStatement, hasOtherQualifier, entityType = statementModule.entityIdQualifier( entity, propertyId, qualifierId, somevalueReturn, novalueReturn )

monolingualTextQualifier

[edit]

Returns a monolingual text qualifier.

Wikitext usage:

{{#invoke:Statement|monolingualTextQualifier|P180|P1684|from=M107006882|somevalue=some value|novalue=no value}}

Module usage:

local wikitext, hasOtherStatement, hasOtherQualifier, text, language = statementModule.monolingualTextQualifier( entity, propertyId, qualifierId, somevalueReturn, novalueReturn )

timeQualifier

[edit]

Returns a time qualifier.

Wikitext usage:

{{#invoke:Statement|timeQualifier|P6731|P580|from=M38570|somevalue=some value|novalue=no value}}

Module usage:

local timestamp, hasOtherStatement, hasOtherQualifier, precision, calendar = statementModule.timeQualifier( entity, propertyId, qualifierId, somevalueReturn, novalueReturn )

dateQualifier

[edit]

Returns a date qualifier. See the non-qualifier functions’ documentation for the distinction between time and date.

Wikitext usage:

{{#invoke:Statement|dateQualifier|P180|P585|from=M97052174|somevalue=some value|novalue=no value}}

Module usage:

local date, hasOtherStatement, hasOtherQualifier, precision, calendar, timestamp = statementModule.dateQualifier( entity, propertyId, qualifierId, somevalueReturn, novalueReturn )

Code

local p = {}

-- Clean up an entity ID parameter.
-- - entityId (string or table or nil)
-- Returns:
-- - entityId (string or table or nil)
local function cleanupEntityId( entityId )
	if entityId == nil then
		return nil
	elseif type( entityId ) ~= 'string' then
		return entityId
	end
	entityId = mw.text.trim( entityId )
	if entityId == '' then return nil end
	return entityId
end

-- Parse the arguments to the “main statement value” functions out of the frame object.
-- See parseMainArgs for the return values.
local function parseMainFrameArg( frame )
	local args = frame.args
	local propertyId = args[ 1 ]
	local entityId = cleanupEntityId( args.from or args.entityId )
	local somevalueReturn = args.somevalue
	local novalueReturn = args.novalue

	if entityId == nil then
		entityId = mw.wikibase.getEntityIdForCurrentPage()
	end

	return entityId, propertyId, somevalueReturn, novalueReturn
end

-- Parse the arguments to the “main statement value” functions out of the positional arguments.
-- See parseMainArgs for the return values.
local function parseMainPositionalArgs( entityOrId, propertyId, somevalueReturn, novalueReturn )
	entityOrId = cleanupEntityId( entityOrId )
	if entityOrId == nil then
		entityOrId = mw.wikibase.getEntityIdForCurrentPage()
	end
	
	return entityOrId, propertyId, somevalueReturn, novalueReturn
end

-- Parse the arguments to the “main statement value” functions,
-- which may be a frame with args if called via {{#invoke:}}.
-- Returns:
-- - fromModule (bool) whether the call came from another module, or from {{#invoke:}}
-- - entityOrId (table or string or nil) an mw.wikibase.entity instance,
--   or an entity ID from which the entity data will be loaded later,
--   or nil if no custom entity ID was given and the page is not linked to an entity
-- - propertyId (string)
-- - somevalueReturn (any) value to return for a somevalue snak, default nil
-- - novalueReturn (any) value to return for a novalue snak, default nil
local function parseMainArgs( ... )
	local frame = arg[ 1 ]
	if frame.callParserFunction then
		return false, parseMainFrameArg( frame )
	else
		return true, parseMainPositionalArgs( unpack( arg ) )
	end
end

-- Parse the arguments to the “qualifier” functions out of the frame object.
-- See parseQualArgs for the return values.
local function parseQualFrameArg( frame )
	local args = frame.args
	local propertyId = args[ 1 ]
	local qualifierId = args[ 2 ]
	local entityId = cleanupEntityId( args.from or args.entityId )
	local somevalueReturn = args.somevalue
	local novalueReturn = args.novalue

	if entityId == nil then
		entityId = mw.wikibase.getEntityIdForCurrentPage()
	end

	return entityId, propertyId, qualifierId, somevalueReturn, novalueReturn
end

-- Parse the arguments to the “qualifier” functions out of the positional arguments.
-- See parseQualArgs for the return values.
local function parseQualPositionalArgs( entityOrId, propertyId, qualifierId, somevalueReturn, novalueReturn )
	entityOrId = cleanupEntityId( entityOrId )
	if entityOrId == nil then
		entityOrId = mw.wikibase.getEntityIdForCurrentPage()
	end
	
	return entityOrId, propertyId, qualifierId, somevalueReturn, novalueReturn
end

-- Parse the arguments to the “qualifier” functions,
-- which may be a frame with args if called via {{#invoke:}}.
-- Returns:
-- - fromModule (bool) whether the call came from another module, or from {{#invoke:}}
-- - entityOrId (table or string or nil) an mw.wikibase.entity instance,
--   or an entity ID from which the entity data will be loaded later,
--   or nil if no custom entity ID was given and the page is not linked to an entity
-- - propertyId (string) property ID for the main statement
-- - qualifierId (string) property ID for the qualifier
-- - somevalueReturn (any) value to return for a somevalue snak, default nil
-- - novalueReturn (any) value to return for a novalue snak, default nil
local function parseQualArgs( ... )
	local frame = arg[ 1 ]
	if frame.callParserFunction then
		return false, parseQualFrameArg( frame )
	else
		return true, parseQualPositionalArgs( unpack( arg ) )
	end
end

-- Get the first best-rank statement in the entity for the property ID.
-- - entityOrId (table or string or nil) an already loaded mw.wikibase.entity instance,
--   or an entity ID from which to load the statement, or nil
-- - propertyId (string)
-- Returns:
-- - statement (table or nil) the full statement
-- - hasOther (bool) whether there are additional best-rank statements
local function bestStatement( entityOrId, propertyId )
	if not entityOrId then return nil, false end
	
	local statements
	if type( entityOrId ) == 'string' then
		local entityId = entityOrId
		statements = mw.wikibase.getBestStatements( entityId, propertyId )
	else
		local entity = entityOrId
		statements = entity:getBestStatements( propertyId )
	end

	return statements[ 1 ], #statements > 1
end

-- Assert that the given snak has the expected data type.
-- - snak (table) the snak
-- - expectedDataType (string) the expected data type
-- - propertyId (string) the property ID, used in the assertion message
local function assertDataType( snak, expectedDataType, propertyId )
	if not snak.datatype then
		return -- T303760
	end

	assert(
		snak.datatype == expectedDataType,
		'data type of ' .. propertyId ..
			' must be ' .. expectedDataType ..
			', not ' .. snak.datatype
	)
end

-- Assert that the given data value has the expected data value type.
-- - value (table) the data value
-- - expectedDataValueType (string) the expected data value type
-- - propertyId (string) the property ID, used in the assertion message
local function assertDataValueType( value, expectedDataValueType, propertyId )
	assert(
		value.type == expectedDataValueType,
		'data value type of ' .. propertyId ..
			' must be ' .. expectedDataValueType ..
			', not ' .. value.type
	)
end

-- Assert the data value type (if it is a value snak) and, optionally,
-- the data type, of the given snak.
-- - snak (table) the snak (e.g. a statement.mainsnak)
-- - expectedDataValueType (string) the expected data value type of the snak’s data value
-- - expectedDataType (string or nil) the expected data type of the snak, if any
local function assertTypesInSnak( snak, expectedDataValueType, expectedDataType )
	if expectedDataType then
		assertDataType( snak, expectedDataType, snak.property )
	end

	if snak.snaktype == 'value' then
		local value = snak.datavalue
		assertDataValueType( value, expectedDataValueType, snak.property )
	else
		assert( snak.snaktype == 'somevalue' or snak.snaktype == 'novalue',
			'snak type must be value/somevalue/novalue, not ' .. snak.snaktype )
	end
end

-- Get the statement’s main snak,
-- asserting that it has the expected data value type,
-- and optionally that the snak has the expected data type.
-- - statement (table or nil) the full statement
-- - expectedDataValueType (string) the expected data value type of the snak’s data value
-- - expectedDataType (string or nil) the expected data type of the snak, if any
-- Returns:
-- - snak (table or nil) the snak, or nil if the whole statement is nil
local function mainSnakWithType( statement, expectedDataValueType, expectedDataType )
	if not statement then
		return nil
	end
	local snak = statement.mainsnak
	assertTypesInSnak( snak, expectedDataValueType, expectedDataType )
	return snak
end

-- Get the statement’s first qualifier snak with the given property ID,
-- asserting that it has the expected data value type,
-- and optionally that the qualifier has the expected data type.
-- - statement (table or nil) the full statement
-- - qualifierId (string) the property ID of the qualifier to get
-- - expectedDataValueType (string) the expected data value type of the snak’s data value
-- - expectedDataType (string or nil) the expected data type of the snak, if any
-- Returns:
-- - snak (table or nil) the snak, or nil if there is no such qualifier
--   or if the whole statement is nil
-- - hasOtherQualifier (bool) whether there are additional qualifiers with this property ID
local function firstQualifierWithType( statement, qualifierId, expectedDataValueType, expectedDataType )
	if not statement then
		return nil, false
	end
	local qualifiers = ( statement.qualifiers or {} )[ qualifierId ]
	if not qualifiers then
		return nil, false
	end
	local qualifier = qualifiers[ 1 ]
	if not qualifier then
		return nil, false
	end
	assertTypesInSnak( qualifier, expectedDataValueType, expectedDataType )
	return qualifier, #qualifiers > 1
end

-- Get the snak’s value value,
-- or one of the given “early return” values if it isn’t a value snak,
-- or the hard-coded “early return” value nil if the snak is nil.
-- - snak (table or nil) the snak, if any
-- - somevalueReturn (any) the “early return” value for a somevalue snak
-- - novalueReturn (any) the “early return” value for a novalue snak
-- Returns:
-- - value (table or nil) the data value (as a table with type and value members),
--   or nil to indicate an early return
-- - earlyReturn (any) the “early return” value;
--   note that nil is a valid “early return” value,
--   so the condition for “do an early return or not” must be a test on value, not earlyReturn
local function snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if snak == nil then
		return nil, nil
	end
	local snaktype = snak.snaktype
	if snaktype == 'value' then
		return snak.datavalue, nil
	elseif snaktype == 'somevalue' then
		return nil, somevalueReturn
	elseif snaktype == 'novalue' then
		return nil, novalueReturn
	else
		assert( false,
			'snak type must be value/somevalue/novalue, not ' .. snaktype )
	end
end

-- Return the given value and, if called from a module, also the other values.
-- - fromModule (bool) whether the call came from another module, or from {{#invoke:}}
-- - first (any) the first value, the only return value if fromModule is false
-- - ... (any) other return values, returned only if fromModule is true
-- Returns:
-- - first (any) always
-- - ... (any) if fromModule is true
local function returnOneOrMore( fromModule, first, ... )
	if fromModule then
		return first, unpack( arg )
	else
		return first
	end
end

-- Assemble the data that “string” functions should return for a string data value.
-- - value (table)
-- Returns:
-- - wikitext (string), wikitext-escaped
-- - string (string), not wikitext-escaped
local function processStringValue( value )
	local string = value.value
	local wikitext = mw.text.nowiki( string )

	return wikitext, string
end

-- Assemble the data that “url” functions should return for a string data value.
-- - value (table)
-- Returns:
-- - url (string), not wikitext-escaped so that auto-linking works
local function processUrlValue( value )
	local url = value.value

	return url
end

-- Assemble the data that “entityId” functions should return for an entity ID data value.
-- - value (table)
-- Returns:
-- - entityId (string)
-- - entityType (string)
local function processEntityIdValue( value )
	local entityId = value.value.id
	local entityType = value.value[ 'entity-type' ]

	return entityId, entityType
end

-- Assemble the data that “monolingualText” functions should return for a monolingual text data value.
-- - value (table)
-- Returns:
-- - wikitext (string) wikitext-escaped
-- - text (string), not wikitext-escaped
-- - language (table), mw.language instance
local function processMonolingualTextValue( value )
	local text = value.value.text
	local language = mw.language.new( value.value.language )
	local span = mw.html.create( 'span' )
	span
		:attr( 'lang', language:getCode() )
		:attr( 'dir', language:getDir() )
		:wikitext( mw.text.nowiki( text ) )
	local wikitext = tostring( span )

	return wikitext, text, language
end

-- Assemble the data that “time” functions should return for a time data value.
-- - value (table)
-- Returns:
-- - timestamp (string)
-- - precision (number)
-- - calendar (string) item ID of the calendar model on Wikidata
local function processTimeValue( value )
	local timestamp = value.value.time
	local precision = value.value.precision
	local calendarUri = value.value.calendarmodel
	local prefix = mw.ustring.sub( calendarUri, 1, 31 )
	assert( prefix == 'http://www.wikidata.org/entity/',
		'calendar URI ' .. calendarUri .. ' must have the right prefix' )
	local calendar = mw.ustring.sub( calendarUri, 32 )

	return timestamp, precision, calendar
end

-- Assemble the data that “date” functions should return for a time data value.
-- - value (table)
-- Returns:
-- - date (string)
-- - precision (number)
-- - calendar (string) item ID of the calendar model on Wikidata
-- - timestamp (string)
local function processDateValue( value )
	local timestamp, precision, calendar = processTimeValue( value )

	-- trim away leading + (but not -!), trailing Z,
	-- and parts of the timestamp beyond the precision
	local pattern = '^+?((((((-?%d*)-%d*)-%d*)T%d*):%d*):%d*)Z$'
	local replacement = '%1' -- second
	if precision == 13 then replacement = '%2' -- minute
	elseif precision == 12 then replacement = '%3' -- hour
	elseif precision == 11 then replacement = '%4' -- day
	elseif precision == 10 then replacement = '%5' -- month
	elseif precision <= 9 then replacement = '%6' -- year
	end
	local date = mw.ustring.gsub( timestamp, pattern, replacement )

	return date, precision, calendar, timestamp
end

-- “main statement value” functions --

function p.string( ... )
	local fromModule, entityOrId, propertyId, somevalueReturn, novalueReturn = parseMainArgs( unpack( arg ) )
	
	local statement, hasOther = bestStatement( entityOrId, propertyId )
	local snak = mainSnakWithType( statement, 'string' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOther )
	end
	local wikitext, string = processStringValue( value )
	
	return returnOneOrMore( fromModule, wikitext, hasOther, string )
end

function p.url( ... )
	local fromModule, entityOrId, propertyId, somevalueReturn, novalueReturn = parseMainArgs( unpack( arg ) )
	
	local statement, hasOther = bestStatement( entityOrId, propertyId )
	local snak = mainSnakWithType( statement, 'string', 'url' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOther )
	end
	local url = processUrlValue( value )
	
	return returnOneOrMore( fromModule, url, hasOther )
end

function p.entityId( ... )
	local fromModule, entityOrId, propertyId, somevalueReturn, novalueReturn = parseMainArgs( unpack( arg ) )
	
	local statement, hasOther = bestStatement( entityOrId, propertyId )
	local snak = mainSnakWithType( statement, 'wikibase-entityid' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOther )
	end
	local entityId, entityType = processEntityIdValue( value )
	
	return returnOneOrMore( fromModule, entityId, hasOther, entityType )
end

function p.monolingualText( ... )
	local fromModule, entityOrId, propertyId, somevalueReturn, novalueReturn = parseMainArgs( unpack( arg ) )
	
	local statement, hasOther = bestStatement( entityOrId, propertyId )
	local snak = mainSnakWithType( statement, 'monolingualtext' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOther )
	end
	local wikitext, text, language = processMonolingualTextValue( value )
	
	return returnOneOrMore( fromModule, wikitext, hasOther, text, language )
end

function p.time( ... )
	local fromModule, entityOrId, propertyId, somevalueReturn, novalueReturn = parseMainArgs( unpack( arg ) )
	
	local statement, hasOther = bestStatement( entityOrId, propertyId )
	local snak = mainSnakWithType( statement, 'time' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOther )
	end
	local timestamp, precision, calendar = processTimeValue( value )
	
	return returnOneOrMore( fromModule, timestamp, hasOther, precision, calendar )
end

function p.date( ... )
	local fromModule, entityOrId, propertyId, somevalueReturn, novalueReturn = parseMainArgs( unpack( arg ) )
	
	local statement, hasOther = bestStatement( entityOrId, propertyId )
	local snak = mainSnakWithType( statement, 'time' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOther )
	end
	local date, precision, calendar, timestamp = processDateValue( value )
	
	return returnOneOrMore( fromModule, date, hasOther, precision, calendar, timestamp )
end

-- “qualifier” functions

function p.stringQualifier( ... )
	local fromModule, entityOrId, propertyId, qualifierId, somevalueReturn, novalueReturn = parseQualArgs( unpack( arg ) )
	
	local statement, hasOtherStatement = bestStatement( entityOrId, propertyId )
	local snak, hasOtherQualifier = firstQualifierWithType( statement, qualifierId, 'string' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOtherStatement, hasOtherQualifier )
	end
	local wikitext, string = processStringValue( value )
	
	return returnOneOrMore( fromModule, wikitext, hasOtherStatement, hasOtherQualifier, string )
end

function p.urlQualifier( ... )
	local fromModule, entityOrId, propertyId, qualifierId, somevalueReturn, novalueReturn = parseQualArgs( unpack( arg ) )
	
	local statement, hasOtherStatement = bestStatement( entityOrId, propertyId )
	local snak, hasOtherQualifier = firstQualifierWithType( statement, qualifierId, 'string', 'url' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOtherStatement, hasOtherQualifier )
	end
	local url = processUrlValue( value )
	
	return returnOneOrMore( fromModule, url, hasOtherStatement, hasOtherQualifier )
end

function p.entityIdQualifier( ... )
	local fromModule, entityOrId, propertyId, qualifierId, somevalueReturn, novalueReturn = parseQualArgs( unpack( arg ) )
	
	local statement, hasOtherStatement = bestStatement( entityOrId, propertyId )
	local snak, hasOtherQualifier = firstQualifierWithType( statement, qualifierId, 'wikibase-entityid' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOtherStatement, hasOtherQualifier )
	end
	local entityId, entityType = processEntityIdValue( value )
	
	return returnOneOrMore( fromModule, entityId, hasOtherStatement, hasOtherQualifier, entityType )
end

function p.monolingualTextQualifier( ... )
	local fromModule, entityOrId, propertyId, qualifierId, somevalueReturn, novalueReturn = parseQualArgs( unpack( arg ) )
	
	local statement, hasOtherStatement = bestStatement( entityOrId, propertyId )
	local snak, hasOtherQualifier = firstQualifierWithType( statement, qualifierId, 'monolingualtext' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOtherStatement, hasOtherQualifier )
	end
	local wikitext, text, language = processMonolingualTextValue( value )
	
	return returnOneOrMore( fromModule, wikitext, hasOtherStatement, hasOtherQualifier, text, language )
end

function p.timeQualifier( ... )
	local fromModule, entityOrId, propertyId, qualifierId, somevalueReturn, novalueReturn = parseQualArgs( unpack( arg ) )
	
	local statement, hasOtherStatement = bestStatement( entityOrId, propertyId )
	local snak, hasOtherQualifier = firstQualifierWithType( statement, qualifierId, 'time' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOtherStatement, hasOtherQualifier )
	end
	local timestamp, precision, calendar = processTimeValue( value )
	
	return returnOneOrMore( fromModule, timestamp, hasOtherStatement, hasOtherQualifier, precision, calendar )
end

function p.dateQualifier( ... )
	local fromModule, entityOrId, propertyId, qualifierId, somevalueReturn, novalueReturn = parseQualArgs( unpack( arg ) )
	
	local statement, hasOtherStatement = bestStatement( entityOrId, propertyId )
	local snak, hasOtherQualifier = firstQualifierWithType( statement, qualifierId, 'time' )
	local value, earlyReturn = snakValueOrEarlyReturn( snak, somevalueReturn, novalueReturn )
	if value == nil then
		return returnOneOrMore( fromModule, earlyReturn, hasOtherStatement, hasOtherQualifier )
	end
	local date, precision, calendar, timestamp = processDateValue( value )
	
	return returnOneOrMore( fromModule, date, hasOtherStatement, hasOtherQualifier, precision, calendar, timestamp )
end

return p