<?php
/**
* Class Distance
*/
class Distance
{
/**
* @var array
*/
public static $units = [
'meters' => [
'suffix' => 'm',
'unit' => 1.00
],
'kilometers' => [
'suffix' => 'km',
'unit' => 0.001
],
'miles' => [ //statute miles
'suffix' => 'mi.',
'unit' => 0.000621371
],
'nautical_miles' => [
'suffix' => 'nmi',
'unit' => 0.000539956
]
];
/**
* @var float
*/
private $value;
/**
* @var string
*/
private $unit;
/**
* Distance constructor.
*
* @param float $value
* @param string $unit
*
* @throws \InvalidArgumentException
*/
public function __construct(float $value, $unit = 'meters')
{
$this->value = $value;
$this->setUnit($unit);
}
/**
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* @param mixed $value
*/
public function setValue($value)
{
$this->value = $value;
}
/**
* @return string
*/
public function getUnit()
{
return $this->unit;
}
/**
* @param string $unit
*
* @throws \InvalidArgumentException
*/
public function setUnit(string $unit)
{
if (!array_key_exists($unit, self::$units)) {
throw new \InvalidArgumentException('The given Unit is not supported.');
}
$this->unit = $unit;
}
/**
* @return bool
*/
public function isMeters()
{
return $this->unit === 'meters';
}
/**
* @return bool
*/
public function isKilometers()
{
return $this->unit === 'kilometers';
}
/**
* @return bool
*/
public function isMiles()
{
return $this->unit === 'miles';
}
/**
* @return bool
*/
public function isNauticalMiles()
{
return $this->unit === 'nautical_miles';
}
/**
* @param $distance
*
* @return static
* @throws \InvalidArgumentException
*/
public static function fromMeters($distance)
{
return new static($distance, 'meters');
}
/**
* @param $distance
*
* @return static
* @throws \InvalidArgumentException
*/
public static function fromKilometers($distance)
{
return new static($distance, 'kilometers');
}
/**
* @param $distance
*
* @return static
* @throws \InvalidArgumentException
*/
public static function fromMiles($distance)
{
return new static($distance, 'miles');
}
/**
* @param $distance
*
* @return static
* @throws \InvalidArgumentException
*/
public static function fromNauticalMiles($distance)
{
return new static($distance, 'nautical_miles');
}
/**
* @param string $unit
*
* @return float
* @throws \InvalidArgumentException
*/
public function getMeasurement(string $unit = '')
{
$unit = $this->unit ?: $unit;
if (!array_key_exists($unit, self::$units)) {
throw new \InvalidArgumentException('The measurement '.$unit.' not found.');
}
return self::$units[$unit]['unit'];
}
/**
* @return string
*/
public function getSuffix()
{
return self::$units[$this->unit]['suffix'];
}
/**
* @param string $unit
*
* @return float
* @throws \InvalidArgumentException
*/
public function asUnit(string $unit)
{
$from = $this->getMeasurement($this->unit);
$to = $this->getMeasurement($unit);
return $this->value * $to * (1/$from);
}
/**
* @param string $unit
*
* @return static
* @throws \InvalidArgumentException
*/
public function convertTo(string $unit)
{
$distance = $this->asUnit($unit);
return new static($distance, $unit);
}
/**
* @return Distance
* @throws \InvalidArgumentException
*/
public function toMeters()
{
return $this->convertTo('meters');
}
/**
* @return Distance
* @throws \InvalidArgumentException
*/
public function toKilometers()
{
return $this->convertTo('kilometers');
}
/**
* @return Distance
* @throws \InvalidArgumentException
*/
public function toMiles()
{
return $this->convertTo('miles');
}
/**
* @return Distance
* @throws \InvalidArgumentException
*/
public function toNauticalMiles()
{
return $this->convertTo('nautical_miles');
}
/**
* @return string
*/
public function toString()
{
return (string)number_format($this->value, 2, ',', '.');
}
/**
* @return string
*/
public function toStringWithSuffix()
{
return sprintf('%s %s', $this->toString(), $this->getSuffix());
}
/**
* @inheritDoc
*/
public function __toString()
{
return $this->toString();
}
}