Skip to content

Commit 439e591

Browse files
committed
Initial commit
0 parents  commit 439e591

File tree

166 files changed

+2713
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

166 files changed

+2713
-0
lines changed

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.git
2+
composer.lock
3+
composer.phar
4+
build
5+
vendor
6+
node_modules

Gruntfile.js

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
module.exports = function(grunt) {
2+
grunt.initConfig({
3+
pkg: grunt.file.readJSON('package.json'),
4+
});
5+
6+
// Quickly generate all SI prefixed units
7+
grunt.registerTask('default', function() {
8+
var siPrefixes = 'src/Prefix/Metric/',
9+
unitFolder = 'src/Unit/',
10+
fileExt = '.php',
11+
baseUnits = {},
12+
units = { 'Mass' : '',
13+
'Length': '',
14+
'Area': 'Square',
15+
'Volume': 'Cubic',
16+
};
17+
phpTemplate = `<?php
18+
namespace PhpMeasurements\\Unit\\<%= unit %>;
19+
20+
use PhpMeasurements\\System\\Metric;
21+
use PhpMeasurements\\Prefix\\Metric\\<%= prefixSI %>;
22+
23+
class <%= baseUnitPrefix %><%= prefixSI %><%= baseUnit %> extends <%= baseUnitPrefix %><%= baseUnit %> implements Metric, <%= prefixSI %>
24+
{
25+
26+
}
27+
`;
28+
var baseRegex = /BASE_UNIT\s*=\s*([^:]+)::/,
29+
replaceExt = new RegExp(fileExt);
30+
31+
grunt.file.recurse(siPrefixes, function(abspath, rootdir, subdir, filename) {
32+
for(var unit in units) {
33+
var baseUnitPrefix = units[unit];
34+
35+
if(!baseUnits[unit]) {
36+
var baseContent = grunt.file.read(unitFolder + unit + fileExt),
37+
matches = baseRegex.exec(baseContent),
38+
baseUnit = matches[1].split('\\').pop();
39+
40+
baseUnit = baseUnit.replace(new RegExp(baseUnitPrefix), '');
41+
baseUnits[unit] = baseUnit;
42+
}else{
43+
baseUnit = baseUnits[unit];
44+
}
45+
46+
if(baseUnit) {
47+
var prefixSI = filename.replace(replaceExt, ''),
48+
phpFileName = unitFolder + unit + '/' + baseUnitPrefix + prefixSI + baseUnit + fileExt;
49+
50+
51+
if(!grunt.file.exists(phpFileName)) {
52+
grunt.file.write(phpFileName,
53+
grunt.template.process(phpTemplate, { data: { unit: unit, prefixSI: prefixSI, baseUnit: baseUnit, baseUnitPrefix: baseUnitPrefix }})
54+
);
55+
}
56+
}
57+
}
58+
});
59+
60+
61+
62+
63+
});
64+
};

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) pimle <[email protected]>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

+203
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
# Php Unit Conversion
2+
3+
The `php-unit-conversion/php-unit-conversion` package provides full PSR-4 compatible unit conversion. Most other packages that are available for unit conversion are using `string` types to indicate unit types. In this package all unit types are classes.
4+
5+
### Basic Usage
6+
```php
7+
use PhpUnitConversion\Unit\Mass;
8+
$milliGram = new Mass\MilliGram(12);
9+
$milliGram->getValue(); // 12
10+
$milliGram->getSymbol(); // 'mg'
11+
12+
/* A format method is available that accepts two parameters:
13+
* @integer precision
14+
* @boolean add_symbol
15+
*/
16+
$milliGram->format(3, false); // 12.000
17+
18+
/* Units are set relative to the BASE_UNIT of the unit type
19+
* e.g. for Mass the base unit is gram's
20+
*/
21+
echo Mass::BASE_UNIT;
22+
// PhpUnitConversion\Unit\Mass\Gram
23+
24+
/* Most units are linear related to the base unit by a fixed factor
25+
* For these units you can retrieve the factor by calling getFactor,
26+
* this can return false if no factor has been defined
27+
*/
28+
echo $milliGram->getFactor();
29+
// 0.001
30+
31+
/* The base unit has no factor defined, this is because we use class constants
32+
* to define factors for SI prefixes and you can't extend/overwrite constants
33+
*/
34+
var_dump((new Mass\Gram(2))->getFactor());
35+
// false
36+
```
37+
38+
### Unit Conversions
39+
```php
40+
use PhpUnitConversion\Unit;
41+
use PhpUnitConversion\Unit\Mass;
42+
43+
/* If you have an instantiated unit, you can convert to a new unit by calling the static `from` method on the unit you want to convert to
44+
*/
45+
$grams = new Mass\Gram(21);
46+
echo Mass\PennyWeight::from($grams)->format();
47+
// 13.503 dwt
48+
49+
/* You can also call the `to` method on the unit object and pass the class name of the unit you want to convert to
50+
*/
51+
$grams = new Mass\Gram(21);
52+
$milliGram = $massUnit->to(Mass\MilliGram::class);
53+
echo $milliGram->format(0);
54+
// 21000 mg
55+
56+
/* or use an instantiated object, this will overwrite any existing value
57+
* due to php passing objects by reference there is no need for a left assignment this way
58+
*/
59+
$grams = new Mass\Gram(21);
60+
$kiloGram = new Mass\KiloGram;
61+
$grams->to($kiloGram);
62+
echo $kiloGram->format();
63+
// 0.021 kg
64+
65+
/* but `to` also returns the object
66+
$massUnit = new Mass\Gram(21);
67+
$ounce = $massUnit->to(new Mass\Ounce);
68+
echo $ounce->format();
69+
// 0.741 oz
70+
71+
/* you can convert directly from a string which has a format of '<value><symbol>'
72+
* by calling the static `from` method on the unit class
73+
*/
74+
$milliGrams = Unit::from('21 mg');
75+
var_dump($milliGrams instanceof Mass\MilliGram::class)
76+
// true
77+
78+
/* but if you already know which type of unit to expect, you can also call
79+
* `from` directly on the unit type class. This could prevent errors when multiple units
80+
* exists with the same symbol
81+
*/
82+
$milliGrams = Mass::from('21 mg');
83+
var_dump($milliGrams instanceof Mass\MilliGram::class)
84+
// true
85+
```
86+
87+
### Arithmetic Operators
88+
```php
89+
/* You can add units of the same type by calling `add` method with one or more units as arguments
90+
* add always returns a new instance
91+
*/
92+
$grams = new Mass\Gram(580);
93+
$addGrams = $massUnit->add(new Mass\KiloGram(0.4), new Mass\Gram(11));
94+
echo $addGrams->format(0);
95+
// 991 g
96+
97+
/* You can also substract units of the same type by calling `substract` method with one or more units as arguments
98+
* substract always returns a new instance
99+
*/
100+
$grams = new Mass\Gram(580);
101+
$subGrams = $massUnit->substract(new Mass\KiloGram(0.4), new Mass\Gram(11));
102+
echo $subGrams->format(0);
103+
// 169 g
104+
105+
/* When you try to add/substract units of different types an exception is thrown
106+
*/
107+
$grams = new Mass\Gram(580);
108+
$addGrams = $massUnit->add(new Time\Second(60) );
109+
// throws a PhpUnitConversion\Exception\UnsupportedUnitException
110+
```
111+
112+
### Contributing
113+
As this package is still very much a work in progress, any help adding more unit's and unit tests is really appreciated!
114+
115+
A couple of things important when submitting a Pull Request:
116+
- ** Use the PSR-2 Coding Standard **
117+
- ** Add tests **
118+
- ** Use the method of implementation as described below **
119+
120+
#### Implementation
121+
##### Add a new unit type
122+
Please make sure to first define a `TYPE_XXX` const in `Unit.php`. Give it a unique number, prefereable the next in the sequence.
123+
124+
Next create a new unit type class in file `Unit/XXX.php`, this will hold the type description. All units belonging to this unit type
125+
should be extended from this class. Make sure you add `const TYPE = Unit::TYPE_XXX`. Also set the const BASE_UNIT to the class of your
126+
base unit. Please choose your base unit logically, units from the metric system have preference over the imperial / usc systems.
127+
128+
Now create a folder Unit/XXX/ in which we will place all the unit classes for this unit type, after this proceed with adding a base unit
129+
130+
##### Adding a base unit
131+
We prefer the base unit to be a unit from the metric system. This way we can easily add all SI prefixed units by extending them from the base
132+
unit and only implement a PhpUnitConversion\Prefix\Metric\<SI_Prefix> interface. E.g. the implementation of Mass\MilliGram is:
133+
```php
134+
class MilliGram extends Gram implements Metric, Milli
135+
{
136+
}
137+
```
138+
See the comment above in Basic Usage about the FACTOR constant. You should not set a FACTOR on the `BASE_UNIT`, otherwise the above implementation
139+
will fail because the interface `Prefix\Metric\Milli` cannot overwrite an already defined class constant.
140+
141+
See the `Gruntfile.js` file for a way to quickly add all prefixed classes to your unit.
142+
143+
##### Add an new unit to a unit type
144+
When adding a unit `YYY` to unit type `XXX` start by creating the file `Unit/XXX/YYY.php`.
145+
146+
If your unit has a linear correspondence to the base unit, just set class constant `FACTOR` to its correct value.
147+
If your unit has an offset to the base unit, you can add a class constant `ADDITION`.
148+
(Conversion to the BASE_UNIT value is done by first applying the `FACTOR`, then adding the `ADDITION`)
149+
150+
Please also set the class constant `SYMBOL` and `LABEL`. When your unit does not have a `SYMBOL`, omit it or set it to an empty string. `LABEL` is often equal to your lower case classname.
151+
152+
##### Relative factors
153+
It is possible to set factors on your unit which are not relative to the `BASE_UNIT` but to another unit. You should extend your new unit `ZZZ` from
154+
the existing unit `YYY` and include the `HasRelativeFactor` Trait in `ZZZ`. Due to class scopes in php you also have to add the `HasFactor` trait to
155+
`YYY` to make sure we use the correct (late binding) static class constant.
156+
157+
See `Unit\Mass\Pound` (=`YYY`) and `Unit\Mass\Ounce` (=`ZZZ`) for an example:
158+
```php
159+
class AvoirdupoisPound extends Mass
160+
{
161+
use HasFactor;
162+
163+
const FACTOR = 453.59237; // FACTOR is relative to Mass\Gram, 453.6 Gram in a Pound
164+
}
165+
166+
class Ounce extends Pound
167+
{
168+
use HasRelativeFactor;
169+
170+
const FACTOR = 16; // FACTOR is relative to Mass\Pound, 16 Ounce in a Pound
171+
}
172+
```
173+
174+
##### System of Measurement
175+
Please also implement the correct unit system interfaces for your unit:
176+
```php
177+
/* Metric units should implement the Metric interface
178+
* see https://en.wikipedia.org/wiki/Metric_system
179+
*/
180+
use PhpUnitConversion\System\Metric;
181+
182+
class YYY extends XXX implements Metric
183+
{
184+
185+
/* Imperial units should implement the Imperial interface
186+
* see https://en.wikipedia.org/wiki/Imperial_units
187+
*/
188+
use PhpUnitConversion\System\Imperial;
189+
190+
/* US customary units should implement the USC interface
191+
* see https://en.wikipedia.org/wiki/United_States_customary_units
192+
*/
193+
use PhpUnitConversion\System\USC;
194+
195+
/* Some units like `feet` are used in more then one system,
196+
* in that case implement both systems
197+
*/
198+
use PhpUnitConversion\System\Imperial;
199+
use PhpUnitConversion\System\USC;
200+
201+
class Yard extends InternationalYard implements Imperial, USC
202+
{
203+
```

composer.json

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "php-unit-conversion/php-unit-conversion",
3+
"description": "A fully PSR-4 compatible PHP library for converting between standard units of measure.",
4+
"keywords": [
5+
"measurements", "data", "conversion"
6+
],
7+
"homepage": "https://github.com/pimlie/php-unit-conversion",
8+
"license": "MIT",
9+
"type": "library",
10+
"authors": [
11+
{
12+
"name": "pimlie",
13+
"email": "[email protected]",
14+
"homepage": "https://github.com/pimlie/",
15+
"role": "Developer"
16+
}
17+
],
18+
"support": {
19+
"email": "[email protected]",
20+
"issues": "https://github.com/pimlie/php-unit-conversion/issues",
21+
"source": "https://github.com/pimlie/php-unit-conversion"
22+
},
23+
"require": {
24+
"php": ">=5.4.0"
25+
},
26+
"require-dev": {
27+
"phpunit/phpunit": "^6.0.7"
28+
},
29+
"autoload": {
30+
"psr-4": {
31+
"PhpUnitConversion\\": "src/"
32+
}
33+
},
34+
"autoload-dev": {
35+
"psr-4": {
36+
"PhpUnitConversionTests\\": "tests/"
37+
}
38+
}
39+
}

package.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "php-unit-conversion",
3+
"version": "0.0.1",
4+
"description": "Full PSR-4 compatible unit conversions",
5+
"main": "Gruntfile.js",
6+
"directories": {
7+
"test": "tests"
8+
},
9+
"dependencies": {},
10+
"devDependencies": {
11+
"grunt": "^1.0.1"
12+
},
13+
"scripts": {
14+
"test": "echo \"Error: no test specified\" && exit 1"
15+
},
16+
"author": "",
17+
"license": "MIT"
18+
}

src/Exception.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace PhpUnitConversion;
4+
5+
class Exception extends \Exception
6+
{
7+
protected $error;
8+
9+
public function __construct(array $variables = [])
10+
{
11+
parent::__construct(strtr($this->error, $variables));
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
namespace PhpUnitConversion\Exception;
3+
4+
use PhpUnitConversion\Exception;
5+
6+
class UnsupportedConversionException extends Exception
7+
{
8+
protected $error = 'Conversion from (:0) to (:1) is not supported';
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
namespace PhpUnitConversion\Exception;
3+
4+
use PhpUnitConversion\Exception;
5+
6+
class UnsupportedUnitException extends Exception
7+
{
8+
protected $error = 'Unit :0 is not supported in this method';
9+
}

0 commit comments

Comments
 (0)