initial commit; version 22.5.12042
This commit is contained in:
276
libs/PhpUnitsOfMeasure/AbstractPhysicalQuantity.php
Normal file
276
libs/PhpUnitsOfMeasure/AbstractPhysicalQuantity.php
Normal file
@ -0,0 +1,276 @@
|
||||
<?php
|
||||
namespace PhpUnitsOfMeasure;
|
||||
|
||||
abstract class AbstractPhysicalQuantity implements PhysicalQuantityInterface
|
||||
{
|
||||
/**
|
||||
* The collection of units in which this quantity can be represented.
|
||||
*
|
||||
* Commented out to ensure that each child class defines its own instance of this static.
|
||||
*
|
||||
* @var UnitOfMeasureInterface[]
|
||||
*/
|
||||
// protected static $unitDefinitions;
|
||||
|
||||
/**
|
||||
* Static cache for unit lookups.
|
||||
*
|
||||
* @var UnitOfMeasureInterface[]
|
||||
*/
|
||||
private static $unitCache = [];
|
||||
|
||||
/**
|
||||
* Create a cache key for the unit lookup cache.
|
||||
*
|
||||
* @var UnitOfMeasureInterface[]
|
||||
*/
|
||||
private static function buildUnitCacheKey($unit)
|
||||
{
|
||||
return get_called_class() . '#' . $unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new unit of measure for all instances of this this physical quantity.
|
||||
*
|
||||
* @throws Exception\DuplicateUnitNameOrAlias If the unit name or any alias already exists
|
||||
*
|
||||
* @param UnitOfMeasureInterface $unit The new unit of measure
|
||||
*/
|
||||
public static function addUnit(UnitOfMeasureInterface $unit)
|
||||
{
|
||||
if (static::unitNameOrAliasesAlreadyRegistered($unit)) {
|
||||
throw new Exception\DuplicateUnitNameOrAlias([
|
||||
':labels' => implode(', ', array_merge([$unit->getName()], $unit->getAliases()))
|
||||
]);
|
||||
}
|
||||
|
||||
static::$unitDefinitions[] = $unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unit of measure that matches the given name by either name or alias.
|
||||
*
|
||||
* @param string $unit A name or alias by which the unit is known.
|
||||
*
|
||||
* @throws Exception\UnknownUnitOfMeasure when an unknown unit of measure is given
|
||||
*
|
||||
* @return UnitOfMeasureInterface
|
||||
*/
|
||||
public static function getUnit($unit)
|
||||
{
|
||||
// If this class hasn't been initialized yet, do so now
|
||||
if (!is_array(static::$unitDefinitions)) {
|
||||
static::$unitDefinitions = [];
|
||||
static::initialize();
|
||||
}
|
||||
|
||||
$key = static::buildUnitCacheKey($unit);
|
||||
if (isset(self::$unitCache[$key])) {
|
||||
return self::$unitCache[$key];
|
||||
}
|
||||
|
||||
foreach (static::$unitDefinitions as $unitOfMeasure) {
|
||||
if ($unit === $unitOfMeasure->getName() || $unitOfMeasure->isAliasOf($unit)) {
|
||||
return self::$unitCache[$key] = $unitOfMeasure;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception\UnknownUnitOfMeasure([':unit' => $unit]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a unit of measure, determine if its name or any of its aliases conflict
|
||||
* with the set of already-known unit names and aliases.
|
||||
*
|
||||
* @param UnitOfMeasureInterface $unit The unit in question
|
||||
*
|
||||
* @return boolean true if there is a conflict, false if there is not
|
||||
*/
|
||||
protected static function unitNameOrAliasesAlreadyRegistered(UnitOfMeasureInterface $unit)
|
||||
{
|
||||
// If this class hasn't been initialized yet, do so now
|
||||
if (!is_array(static::$unitDefinitions)) {
|
||||
static::$unitDefinitions = [];
|
||||
static::initialize();
|
||||
}
|
||||
|
||||
$currentUnitNamesAndAliases = [];
|
||||
foreach (static::$unitDefinitions as $unitOfMeasure) {
|
||||
$currentUnitNamesAndAliases[] = $unitOfMeasure->getName();
|
||||
$currentUnitNamesAndAliases = array_merge($currentUnitNamesAndAliases, $unitOfMeasure->getAliases());
|
||||
}
|
||||
|
||||
$newUnitNamesAndAliases = array_merge([$unit->getName()], $unit->getAliases());
|
||||
|
||||
return count(array_intersect($currentUnitNamesAndAliases, $newUnitNamesAndAliases)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the static properties of this quantity class, such as the set of
|
||||
* default units of measure.
|
||||
*/
|
||||
protected static function initialize()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The scalar value, in the original unit of measure.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
protected $originalValue;
|
||||
|
||||
/**
|
||||
* The original unit of measure's string representation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $originalUnit;
|
||||
|
||||
/**
|
||||
* Store the value and its original unit.
|
||||
*
|
||||
* @param float $value The scalar value of the measurement
|
||||
* @param string $unit The unit of measure in which this value is provided
|
||||
*
|
||||
* @throws Exception\NonNumericValue If the value is not numeric
|
||||
* @throws Exception\NonStringUnitName If the unit is not a string
|
||||
*/
|
||||
public function __construct($value, $unit)
|
||||
{
|
||||
if (!is_numeric($value)) {
|
||||
throw new Exception\NonNumericValue([':value' => $value]);
|
||||
}
|
||||
|
||||
if (!is_string($unit)) {
|
||||
throw new Exception\NonStringUnitName([':name' => $unit]);
|
||||
}
|
||||
|
||||
$this->originalValue = $value;
|
||||
$this->originalUnit = $unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \PhpUnitsOfMeasure\PhysicalQuantityInterface::toUnit
|
||||
*/
|
||||
public function toUnit($toUnit)
|
||||
{
|
||||
return $this->toUnitOfMeasure(static::getUnit($toUnit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this quantity to the given unit of measure.
|
||||
*
|
||||
* @param UnitOfMeasureInterface $unit The object representing the target unit of measure.
|
||||
*
|
||||
* @return float This quantity's value in the given unit of measure.
|
||||
*/
|
||||
private function toUnitOfMeasure(UnitOfMeasureInterface $unit)
|
||||
{
|
||||
$thisValueInNativeUnit = $this->toNativeUnit();
|
||||
return $unit->convertValueFromNativeUnitOfMeasure($thisValueInNativeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \PhpUnitsOfMeasure\PhysicalQuantityInterface::toNativeUnit
|
||||
*/
|
||||
public function toNativeUnit()
|
||||
{
|
||||
return static::getUnit($this->originalUnit)
|
||||
->convertValueToNativeUnitOfMeasure($this->originalValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \PhpUnitsOfMeasure\PhysicalQuantityInterface::__toString
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return trim($this->originalValue . ' ' . static::getUnit($this->originalUnit)->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \PhpUnitsOfMeasure\PhysicalQuantityInterface::add
|
||||
*/
|
||||
public function add(PhysicalQuantityInterface $quantity)
|
||||
{
|
||||
if (!$this->isEquivalentQuantity($quantity)) {
|
||||
throw new Exception\PhysicalQuantityMismatch([
|
||||
':lhs' => (string) $this,
|
||||
':rhs' => (string) $quantity
|
||||
]);
|
||||
}
|
||||
|
||||
$quantityValueInThisOriginalUnit = $quantity->toUnitOfMeasure(static::getUnit($this->originalUnit));
|
||||
$newValue = $this->originalValue + $quantityValueInThisOriginalUnit;
|
||||
|
||||
return new static($newValue, static::getUnit($this->originalUnit)->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \PhpUnitsOfMeasure\PhysicalQuantityInterface::subtract
|
||||
*/
|
||||
public function subtract(PhysicalQuantityInterface $quantity)
|
||||
{
|
||||
if (!$this->isEquivalentQuantity($quantity)) {
|
||||
throw new Exception\PhysicalQuantityMismatch([
|
||||
':lhs' => (string) $this,
|
||||
':rhs' => (string) $quantity
|
||||
]);
|
||||
}
|
||||
|
||||
$quantityValueInThisOriginalUnit = $quantity->toUnitOfMeasure(static::getUnit($this->originalUnit));
|
||||
$newValue = $this->originalValue - $quantityValueInThisOriginalUnit;
|
||||
|
||||
return new static($newValue, static::getUnit($this->originalUnit)->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \PhpUnitsOfMeasure\PhysicalQuantityInterface::isEquivalentQuantity
|
||||
*/
|
||||
public function isEquivalentQuantity(PhysicalQuantityInterface $testQuantity)
|
||||
{
|
||||
return get_class($this) === get_class($testQuantity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \PhpUnitsOfMeasure\PhysicalQuantityInterface::isUnitDefined
|
||||
*/
|
||||
public static function isUnitDefined($name)
|
||||
{
|
||||
$units = static::getUnitDefinitions();
|
||||
foreach ($units as $unit) {
|
||||
if ($name === $unit->getName() || $unit->isAliasOf($name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \PhpUnitsOfMeasure\PhysicalQuantityInterface::listAllUnits
|
||||
*/
|
||||
public static function listAllUnits()
|
||||
{
|
||||
$return = [];
|
||||
$units = static::getUnitDefinitions();
|
||||
foreach ($units as $unit) {
|
||||
$return[$unit->getName()] = $unit->getAliases();
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unit definition array
|
||||
* @return Array $unitDefinitions
|
||||
*/
|
||||
public static function getUnitDefinitions()
|
||||
{
|
||||
if (!is_array(static::$unitDefinitions)) {
|
||||
static::$unitDefinitions = [];
|
||||
static::initialize();
|
||||
}
|
||||
|
||||
return static::$unitDefinitions;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user