Skip to content

Commit

Permalink
Feat: add unit converter class to actually convert values from/to units
Browse files Browse the repository at this point in the history
  • Loading branch information
jordanbrauer committed Oct 9, 2017
1 parent 4e241a1 commit 3a84d07
Show file tree
Hide file tree
Showing 3 changed files with 261 additions and 0 deletions.
129 changes: 129 additions & 0 deletions src/UnitConverter/UnitConverter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php

/**
* This file is part of the jordanbrauer/unit-converter PHP package.
*
* @copyright 2017 Jordan Brauer <[email protected]>
* @license MIT
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types = 1);

namespace UnitConverter;

use UnitConverter\Measure;
use UnitConverter\Unit\UnitInterface;
use UnitConverter\Registry\UnitRegistryInterface;

/**
* The actual unit converter object.
*
* @version 1.0.0
* @since 1.0.0
* @author Jordan Brauer <[email protected]>
*/
class UnitConverter implements UnitConverterInterface
{
/**
* @var UnitRegistryInterface The registry that the unit converter accesses available units from.
*/
protected $registry;

/**
* @var float $convert The value being converted.
*/
protected $convert;

/**
* @var string $from The unit of measure being converted **from**.
*/
protected $from;

/**
* @var string $to The unit of measure being converted **to**.
*/
protected $to;

/**
* Public constructor function for the UnitConverter class.
*
* @param UnitInterface[] A two-dimensional array of UnitInterface objects.
* @return self
*/
public function __construct (UnitRegistryInterface $registry = null)
{
$this->setRegistry($registry);
}

/**
* Determine whether or not the converter has an active registry.
*
* @internal
* @return bool
*/
protected function registryExists () : bool
{
if ($this->registry instanceof UnitRegistryInterface)
return true;

return false;
}

/**
* Load a unit from the unit converter registry.
*
* @internal
* @uses UnitConverter\UnitRegistry::loadUnit
* @throws ErrorException An error exceptino will be thrown if no registry exits
* @return UnitInterface
*/
protected function loadUnit(string $symbol) : UnitInterface
{
if ($this->registryExists() === false)
throw new \ErrorException("No unit registry was found to load units from.");

return $this->registry->loadUnit($symbol);
}

/**
* Calculate the conversion from one unit to another.
*
* @internal
* @param float $value The initial value being converted.
* @param UnitInterface $from The unit of measure being converted **from**.
* @param UnitInterface $to The unit of measure being converted **to**.
* @return float
*/
protected function calculate (float $value, UnitInterface $from, UnitInterface $to): float
{
return ($value * $from->getUnits()) / $to->getUnits();
}


public function setRegistry ($registry) : UnitConverterInterface
{
$this->registry = $registry;
return $this;
}

public function convert (float $value)
{
$this->convert = $value;
return $this;
}

public function from (string $unit)
{
$this->from = $this->loadUnit($unit);
return $this;
}

public function to (string $unit)
{
$this->to = $this->loadUnit($unit);
return $this->calculate($this->convert, $this->from, $this->to);
}
}
67 changes: 67 additions & 0 deletions src/UnitConverter/UnitConverterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

/**
* This file is part of the jordanbrauer/unit-converter PHP package.
*
* @copyright 2017 Jordan Brauer <[email protected]>
* @license MIT
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types = 1);

namespace UnitConverter;

use UnitConverter\Unit\UnitInterface;

/**
* The interface for any and all unit converter classes. If you want
* a custom converter, implement this interface and you are good to
* go!
*
* @version 1.0.0
* @since 1.0.0
* @author Jordan Brauer <[email protected]>
*/
interface UnitConverterInterface
{
/**
* Set the unit converter registry for storing units of measure to convert values with.
*
* @api
* @param UnitRegistryInterface $registry An instance of UnitRegistry.
*/
public function setRegistry ($registry) : UnitConverterInterface;

/**
* Set the unit converters' value to be converted. This method is the first
* method to be called in the chain of conversion methods.
*
* @api
* @example $converter->convert(1)->from("in")->to("cm");
* @param float $value The numerical value being converted.
*/
public function convert (float $value);

/**
* Set the unit converters' unit to be converted **from**. This method is the
* second to be called in the chain of conversion methods.
*
* @api
* @example $converter->convert(1)->from("in")->to("cm");
* @param string $unit The unit being conerted **from**. The unit must first be registered to the UnitRegistry.
*/
public function from (string $unit);

/**
* Set the unit converters' unit to be converted **to**. This method is the
* third to be called in the chain of conversion methods.
*
* @api
* @example $converter->convert(1)->from("in")->to("cm");
* @param string $unit The unit being converted **to**. The unit must first be registered to the UnitRegistry.
*/
public function to (string $unit);
}
65 changes: 65 additions & 0 deletions tests/unit/UnitConverter/UnitConverter.spec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

/**
* This file is part of the jordanbrauer/unit-converter PHP package.
*
* @copyright 2017 Jordan Brauer <[email protected]>
* @license MIT
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types = 1);

namespace UnitConverter\Tests\Unit;

use PHPUnit\Framework\TestCase;
use UnitConverter\UnitConverter;
use UnitConverter\Registry\UnitRegistry;
use UnitConverter\Unit\Length\{
Centimeter,
Inch
};

/**
* @coversDefaultClass UnitConverter\UnitConverter
* @author Jordan Brauer <[email protected]>
*/
class UnitConverterSpec extends TestCase
{
protected function setUp ()
{
$this->converter = new UnitConverter(
new UnitRegistry(array(
new Centimeter,
new Inch,
))
);
}

protected function tearDown ()
{
unset($this->converter);
}

/**
* @test
* @covers ::convert
* @covers ::from
* @covers ::to
* @covers ::calculate
*/
public function assertCalculateMethodReturnsCorrectCalculation ()
{
$expected = 2.54; # = (1 * 0.0254) / 0.01
$actual = $this->converter
->convert(1)
->from("in")
->to("cm")
;

$this->assertEquals($expected, $actual);
$this->assertInternalType("float", $actual);
}
}

0 comments on commit 3a84d07

Please sign in to comment.