172 lines
5.2 KiB
PHP
172 lines
5.2 KiB
PHP
<?php
|
|
namespace PhpUnitsOfMeasure;
|
|
|
|
class UnitOfMeasure implements UnitOfMeasureInterface
|
|
{
|
|
/**
|
|
* For the special case of units that have a linear conversion factor, this factory
|
|
* method simplifies the construction of the unit of measure.
|
|
*
|
|
* For example the relationship between meters and feet is a simple multiplicative factor of
|
|
* 0.3048 meters in a foot. Converting back and forth between these two units is a matter of
|
|
* multiplication or division by this scaling factor.
|
|
*
|
|
* In contrast, converting Celsius to Fahrenheit involves an offset calculation, and cannot
|
|
* be represented by a simple conversion factor. In such cases this class's constructor should be
|
|
* invoked directly.
|
|
*
|
|
* To help in getting the multiplication and division right, think of the toNativeUnitFactor
|
|
* as the number you'd multiply this unit by to get to the native unit of measure. In
|
|
* other words:
|
|
* 'Value in the native unit of measure' = 'Value in this unit of measure' * toNativeUnitFactor
|
|
*
|
|
* @param string $name This unit of measure's canonical name
|
|
* @param float $toNativeUnitFactor The factor to scale the unit by where factor * base unit = this unit
|
|
*
|
|
* @return self
|
|
*/
|
|
public static function linearUnitFactory($name, $toNativeUnitFactor)
|
|
{
|
|
return new static(
|
|
$name,
|
|
function ($valueInNativeUnit) use ($toNativeUnitFactor) {
|
|
return $valueInNativeUnit / $toNativeUnitFactor;
|
|
},
|
|
function ($valueInThisUnit) use ($toNativeUnitFactor) {
|
|
return $valueInThisUnit * $toNativeUnitFactor;
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* This is a special case of the linear unit factory above, for use in generating the native unit of measure
|
|
* for a given physical quantity. By definition, the conversion factor is 1.
|
|
*
|
|
* @param string $name This unit of measure's canonical name
|
|
*
|
|
* @return self
|
|
*/
|
|
public static function nativeUnitFactory($name)
|
|
{
|
|
return static::linearUnitFactory($name, 1);
|
|
}
|
|
|
|
/**
|
|
* The canonical name for this unit of measure.
|
|
*
|
|
* Typically this is the official way the unit is abbreviated.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $name;
|
|
|
|
/**
|
|
* A collection of alias names that map to this unit of measure
|
|
*
|
|
* @var string[]
|
|
*/
|
|
protected $aliases = [];
|
|
|
|
/**
|
|
* A callable that can convert a value in this quantity's
|
|
* native unit to this unit of measure.
|
|
*
|
|
* @var callable
|
|
*/
|
|
protected $fromNativeUnit;
|
|
|
|
/**
|
|
* A callable that can convert a value in this unit of measure
|
|
* to a value in the native unit of the physical quantity.
|
|
*
|
|
* @var callable
|
|
*/
|
|
protected $toNativeUnit;
|
|
|
|
/**
|
|
* Configure this object's mandatory properties.
|
|
*
|
|
* @param string $name This unit of measure's canonical name
|
|
* @param callable $fromNativeUnit The callable that can cast values into this unit of measure from the native unit of measure
|
|
* @param callable $toNativeUnit The callable that can cast values into the native unit from this unit of measure
|
|
*
|
|
* @throws Exception\NonStringUnitName
|
|
*/
|
|
public function __construct($name, callable $fromNativeUnit, callable $toNativeUnit)
|
|
{
|
|
if (!is_string($name)) {
|
|
throw new Exception\NonStringUnitName([':name' => $name]);
|
|
}
|
|
|
|
$this->name = $name;
|
|
$this->fromNativeUnit = $fromNativeUnit;
|
|
$this->toNativeUnit = $toNativeUnit;
|
|
}
|
|
|
|
/**
|
|
* @see \PhpUnitsOfMeasure\UnitOfMeasureInterface::getName
|
|
*/
|
|
public function getName()
|
|
{
|
|
return $this->name;
|
|
}
|
|
|
|
/**
|
|
* @see \PhpUnitsOfMeasure\UnitOfMeasureInterface::addAlias
|
|
*/
|
|
public function addAlias($alias)
|
|
{
|
|
if (!is_string($alias)) {
|
|
throw new Exception\NonStringUnitName([':name' => $alias]);
|
|
}
|
|
|
|
$this->aliases[] = $alias;
|
|
}
|
|
|
|
/**
|
|
* @see \PhpUnitsOfMeasure\UnitOfMeasureInterface::getAliases
|
|
*/
|
|
public function getAliases()
|
|
{
|
|
return $this->aliases;
|
|
}
|
|
|
|
/**
|
|
* @see \PhpUnitsOfMeasure\UnitOfMeasureInterface::isAliasOf
|
|
*/
|
|
public function isAliasOf($unit)
|
|
{
|
|
if (!is_string($unit)) {
|
|
throw new Exception\NonStringUnitName([':name' => $unit]);
|
|
}
|
|
|
|
return in_array($unit, $this->aliases);
|
|
}
|
|
|
|
/**
|
|
* @see \PhpUnitsOfMeasure\UnitOfMeasureInterface::convertValueFromNativeUnitOfMeasure
|
|
*/
|
|
public function convertValueFromNativeUnitOfMeasure($value)
|
|
{
|
|
if (!is_numeric($value)) {
|
|
throw new Exception\NonNumericValue([':value' => $value]);
|
|
}
|
|
|
|
$callable = $this->fromNativeUnit;
|
|
return $callable($value);
|
|
}
|
|
|
|
/**
|
|
* @see \PhpUnitsOfMeasure\UnitOfMeasureInterface::convertValueToNativeUnitOfMeasure
|
|
*/
|
|
public function convertValueToNativeUnitOfMeasure($value)
|
|
{
|
|
if (!is_numeric($value)) {
|
|
throw new Exception\NonNumericValue([':value' => $value]);
|
|
}
|
|
|
|
$callable = $this->toNativeUnit;
|
|
return $callable($value);
|
|
}
|
|
}
|