Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a StatementRank class #562

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions src/Statement/Statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,19 @@
class Statement implements Hashable, Comparable, PropertyIdProvider {

/**
* Rank enum. Higher values are more preferred.
*
* @since 2.0
* @deprecated since 4.4, use StatementRank::PREFERRED instead.
*/
const RANK_PREFERRED = StatementRank::PREFERRED;

/**
* @deprecated since 4.4, use StatementRank::NORMAL instead.
*/
const RANK_PREFERRED = 2;
const RANK_NORMAL = 1;
const RANK_DEPRECATED = 0;
const RANK_NORMAL = StatementRank::NORMAL;

/**
* @deprecated since 4.4, use StatementRank::DEPRECATED instead.
*/
const RANK_DEPRECATED = StatementRank::DEPRECATED;

/**
* @var string|null
Expand All @@ -56,9 +62,9 @@ class Statement implements Hashable, Comparable, PropertyIdProvider {
private $references;

/**
* @var integer, element of the Statement::RANK_ enum
* @var int One of the StatementRank::... constants.
*/
private $rank = self::RANK_NORMAL;
private $rank = StatementRank::NORMAL;

/**
* @since 2.0
Expand Down Expand Up @@ -190,19 +196,15 @@ public function addNewReference( $snaks = [] /*...*/ ) {

/**
* Sets the rank of the statement.
* The rank is an element of the Statement::RANK_ enum.
*
* @since 0.1
*
* @param integer $rank
* @param int $rank One of the StatementRank::... constants.
*
* @throws InvalidArgumentException
*/
public function setRank( $rank ) {
$ranks = [ self::RANK_DEPRECATED, self::RANK_NORMAL, self::RANK_PREFERRED ];

if ( !in_array( $rank, $ranks, true ) ) {
throw new InvalidArgumentException( 'Invalid rank specified for statement: ' . var_export( $rank, true ) );
}
StatementRank::assertIsValid( $rank );

$this->rank = $rank;
}
Expand Down
165 changes: 165 additions & 0 deletions src/Statement/StatementRank.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<?php

namespace Wikibase\DataModel\Statement;

use InvalidArgumentException;

/**
* Everything we know about statement's ranks and what they are supposed to mean.
*
* @see https://www.mediawiki.org/wiki/Wikibase/DataModel#Ranks_of_Statements
* @see https://meta.wikimedia.org/wiki/Wikidata/Data_model_update#Ranks_and_order
*
* @since 4.4
*
* @license GNU GPL v2+
* @author Thiemo Kreuz
*/
class StatementRank {

/**
* Higher values are more preferred.
* TODO: Link to discussion/documentation that guarantees increasing order.
*/
const DEPRECATED = 0;
const NORMAL = 1;
const PREFERRED = 2;

private static $names = [
self::DEPRECATED => 'deprecated',
self::NORMAL => 'normal',
self::PREFERRED => 'preferred',
];

/**
* @return string[] Array mapping all known self::... constants (integers) to string names.
*/
public static function getNames() {
return self::$names;
}

/**
* @return int[] Array mapping string names to all known self::... constants (integers).
*/
public static function getAllRanks() {
return array_flip( self::$names );
}

/**
* @param int $rank
*
* @throws InvalidArgumentException
*/
public static function assertIsValid( $rank ) {
if ( !self::isValid( $rank ) ) {
throw new InvalidArgumentException( 'Invalid rank' );
}
}

/**
* @param int $rank
*
* @return bool
*/
public static function isValid( $rank ) {
return is_int( $rank ) && array_key_exists( $rank, self::$names );
}

/**
* @param int $rank
*
* @throws InvalidArgumentException
* @return bool Statements with a deprecated (or lower) rank are known to be false. But don't be
* fooled, this does not mean higher ranks are known to be true!
*/
public static function isFalse( $rank ) {
self::assertIsValid( $rank );

return $rank === self::DEPRECATED;
}

/**
* @param int|null $rank1
* @param int|null $rank2
*
* @throws InvalidArgumentException
* @return bool True if the given ranks are equal.
*/
public static function isEqual( $rank1, $rank2 ) {
return self::compare( $rank1, $rank2 ) === 0;
}

/**
* @param int|null $rank1
* @param int|null $rank2
*
* @throws InvalidArgumentException
* @return bool True if the first rank is less preferred than the second.
*/
public static function isLower( $rank1, $rank2 ) {
return self::compare( $rank1, $rank2 ) === -1;
}

/**
* @param int|null $rank1
* @param int|null $rank2
*
* @throws InvalidArgumentException
* @return bool True if the first rank is more preferred than the second.
*/
public static function isHigher( $rank1, $rank2 ) {
return self::compare( $rank1, $rank2 ) === 1;
}

/**
* @param int|null $rank1
* @param int|null $rank2
*
* @throws InvalidArgumentException
* @return int 0 if the ranks are equal, -1 if the first rank is less preferred than the second,
* or +1 if the first rank is more preferred than the second.
*/
public static function compare( $rank1, $rank2 ) {
if ( $rank1 !== null ) {
self::assertIsValid( $rank1 );
}
if ( $rank2 !== null ) {
self::assertIsValid( $rank2 );
}

if ( $rank1 === $rank2 ) {
return 0;
} elseif ( $rank1 === null || $rank1 < $rank2 ) {
return -1;
} else {
return 1;
}
}

/**
* @param int[]|int $ranks
* @param int [$rank2,...]
*
* @return int|null Best rank in the array or list of arguments, or null if none given.
*/
public static function findBestRank( $ranks = [] /*...*/ ) {
if ( !is_array( $ranks ) ) {
$ranks = func_get_args();
}

$best = null;

foreach ( $ranks as $rank ) {
if ( self::isHigher( $rank, $best ) ) {
$best = $rank;

if ( $best === self::PREFERRED ) {
break;
}
}
}

return $best;
}

}
Loading