gplx/mediawiki/extensions/SemanticMediaWiki/includes/dataitems/SMW_DataItem.php

284 lines
7.4 KiB
PHP

<?php
use MediaWiki\Json\JsonUnserializable;
use MediaWiki\Json\JsonUnserializer;
use SMW\DIConcept;
use SMW\DIProperty;
use SMW\DIWikiPage;
use SMW\Options;
use SMW\SemanticData;
/**
* This group contains all parts of SMW that relate to the processing of dataitems
* of various types.
*
* @defgroup SMWDataItems SMWDataItems
* @ingroup SMW
*/
/**
* Objects of this type represent all that is known about a certain piece of
* data that could act as the value of some property. Data items only represent
* the stored data, and are thus at the core of SMW's data model. Data items
* are always immutable, i.e. they must not be changed after creation (and this
* is mostly enforced by the API with some minor exceptions).
*
* The set of available data items is fixed and cannot be extended. These are
* the kinds of information that SMW can process. Their concrete use and
* handling might depend on the context in which they are used. In particular,
* property values may be influences by settings made for their property. This
* aspect, however, is not part of the data item API.
*
* @since 1.6
*
* @ingroup SMWDataItems
*/
abstract class SMWDataItem implements JsonUnserializable {
/// Data item ID that can be used to indicate that no data item class is appropriate
const TYPE_NOTYPE = 0;
/// Data item ID for SMWDINumber
const TYPE_NUMBER = 1;
/// Data item ID for SMWDIBlob
const TYPE_BLOB = 2;
/// Data item ID for SMWDIBoolean
const TYPE_BOOLEAN = 4;
/// Data item ID for SMWDIUri
const TYPE_URI = 5;
/// Data item ID for SMWDITimePoint
const TYPE_TIME = 6;
/// Data item ID for SMWDIGeoCoord
const TYPE_GEO = 7;
/// Data item ID for SMWDIContainer
const TYPE_CONTAINER = 8;
/// Data item ID for DIWikiPage
const TYPE_WIKIPAGE = 9;
/// Data item ID for DIConcept
const TYPE_CONCEPT = 10;
/// Data item ID for DIProperty
const TYPE_PROPERTY = 11;
/// Data item ID for SMWDIError
const TYPE_ERROR = 12;
/**
* @var Options
*/
private $options = null;
/**
* Convenience method that returns a constant that defines the concrete
* class that implements this data item. Used to switch when processing
* data items.
* @return int that specifies the basic type of data item
*/
abstract public function getDIType();
/**
* Return a value that can be used for sorting data of this type.
* If the data is of a numerical type, the sorting must be done in
* numerical order. If the data is a string, the data must be sorted
* alphabetically.
*
* @note Every data item returns a sort key, even if there is no
* natural linear order for the type. SMW must order listed data
* in some way in any case. If there is a natural order (e.g. for
* Booleans where false < true), then the sortkey must agree with
* this order (e.g. for Booleans where false maps to 0, and true
* maps to 1).
*
* @note Wiki pages are a special case in SMW. They are ordered by a
* sortkey that is assigned to them as a property value. When pages are
* sorted, this data should be used if possible.
*
* @return float|string
*/
abstract public function getSortKey();
/**
* Method to compare two SMWDataItems
* This should result true only if they are of the same DI type
* and have the same internal value
*
* @since 1.8
*
* @param SMWDataItem $di
* @return bool
*/
abstract public function equals( SMWDataItem $di );
/**
* Create a data item that represents the sortkey, i.e. either an
* SMWDIBlob or an SMWDINumber. For efficiency, these subclasses
* overwrite this method to return themselves.
*
* @return SMWDataItem
*/
public function getSortKeyDataItem() {
$sortKey = $this->getSortKey();
if ( is_numeric( $sortKey ) ) {
return new SMWDINumber( $sortKey );
}
return new SMWDIBlob( $sortKey );
}
/**
* Get a UTF-8 encoded string serialization of this data item.
* The serialisation should be concise and need not be pretty, but it
* must allow unserialization. Each subclass of SMWDataItem implements
* a static method doUnserialize() for this purpose.
* @return string
*/
abstract public function getSerialization();
/**
* @since 3.1
*
* @return string
*/
public function getSha1() {
return sha1( $this->getSerialization() );
}
/**
* Get a hash string for this data item. Might be overwritten in
* subclasses to obtain shorter or more efficient hashes.
*
* @return string
*/
public function getHash() {
return $this->getSerialization();
}
/**
* @since 2.1
*
* @return string
*/
public function __toString() {
return $this->getSerialization();
}
/**
* Create a data item of the given dataitem ID based on the the
* provided serialization string and (optional) typeid.
*
* @param int $diType dataitem ID
* @param string $serialization
*
* @return SMWDataItem
*/
public static function newFromSerialization( $diType, $serialization ) {
$diClass = self::getDataItemClassNameForId( $diType );
return call_user_func( [ $diClass, 'doUnserialize' ], $serialization );
}
/**
* Gets the class name of the data item that has the provided type id.
*
* @param int $diType Element of the SMWDataItem::TYPE_ enum
*
* @throws InvalidArgumentException
*
* @return string
*/
public static function getDataItemClassNameForId( $diType ) {
switch ( $diType ) {
case self::TYPE_NUMBER:
return SMWDINumber::class;
case self::TYPE_BLOB:
return SMWDIBlob::class;
case self::TYPE_BOOLEAN:
return SMWDIBoolean::class;
case self::TYPE_URI:
return SMWDIUri::class;
case self::TYPE_TIME:
return SMWDITime::class;
case self::TYPE_GEO:
return SMWDIGeoCoord::class;
case self::TYPE_CONTAINER:
return SMWDIContainer::class;
case self::TYPE_WIKIPAGE:
return DIWikiPage::class;
case self::TYPE_CONCEPT:
return DIConcept::class;
case self::TYPE_PROPERTY:
return DIProperty::class;
case self::TYPE_ERROR:
return SMWDIError::class;
case self::TYPE_NOTYPE:
default:
throw new InvalidArgumentException( "The value \"$diType\" is not a valid dataitem ID." );
}
}
/**
* @since 2.5
*
* @param string $key
* @param string $value
*/
public function setOption( $key, $value ) {
if ( !$this->options instanceof Options ) {
$this->options = new Options();
}
$this->options->set( $key, $value );
}
/**
* @since 2.5
*
* @param string $key
* @param string|null $default
*
* @return mixed
*/
public function getOption( $key, $default = null ) {
if ( !$this->options instanceof Options ) {
$this->options = new Options();
}
if ( $this->options->has( $key ) ) {
return $this->options->get( $key );
}
return $default;
}
/**
* Implements \JsonSerializable.
*
* @since 4.0.0
*
* @return array
*/
public function jsonSerialize(): array {
# T312589 explicitly calling jsonSerialize() will be unnecessary
# in the future.
return [
'options' => $this->options ? $this->options->jsonSerialize() : null,
'value' => $this->getSerialization(),
'_type_' => get_class( $this ),
];
}
/**
* Implements JsonUnserializable.
*
* @since 4.0.0
*
* @param JsonUnserializer $unserializer Unserializer
* @param array $json JSON to be unserialized
*
* @return self
*/
public static function newFromJsonArray( JsonUnserializer $unserializer, array $json ) {
$obj = static::doUnserialize( $json['value'] );
$obj->options = $json['options'] ? SemanticData::maybeUnserialize( $unserializer, $json['options'] ) : null;
return $obj;
}
}