Skip to content

Commit

Permalink
Merge branch 'release/1.0.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
remcotolsma committed Sep 30, 2021
2 parents fb21aef + 6a61d40 commit ff5c55c
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 3 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.0.1] - 2021-09-30
- Added number parser.

## [1.0.0] - 2021-07-02
### Added
- First release.

[Unreleased]: https://github.com/pronamic/wp-number/compare/1.0.0...HEAD
[Unreleased]: https://github.com/pronamic/wp-number/compare/1.0.1...HEAD
[1.0.1]: https://github.com/pronamic/wp-number/compare/1.0.0...1.0.1
[1.0.0]: https://github.com/pronamic/wp-number/releases/tag/1.0.0
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,7 @@ _Source:_ https://www.php.net/manual/en/language.types.integer.php
> `$y = "0123" + 0 // 123`
_Source:_ https://www.php.net/manual/en/language.types.integer.php#111523

## Links

- https://0.30000000000000004.com/
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
"phpmd/phpmd": "^2.9",
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0",
"pronamic/wp-coding-standards": "^1.0",
"roots/wordpress": "^5.7",
"wp-phpunit/wp-phpunit": "^5.6"
"roots/wordpress": "^5.8",
"wp-phpunit/wp-phpunit": "^5.8"
},
"scripts": {
"ci": [
Expand Down
111 changes: 111 additions & 0 deletions src/Parser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php
/**
* Parser
*
* @author Pronamic <info@pronamic.eu>
* @copyright 2005-2021 Pronamic
* @license GPL-3.0-or-later
* @package Pronamic\WordPress\Number
*/

namespace Pronamic\WordPress\Number;

/**
* Parser
*
* @author Remco Tolsma
* @version 2.0.0
* @since 1.1.0
*/
class Parser {
/**
* Parse.
*
* @link https://github.com/wp-pay/core/blob/2.0.2/src/Core/Util.php#L128-L176
* @param string $string String to parse as money.
* @return Number
* @throws \Exception Throws exception when parsing string fails.
*/
public function parse( $string ) {
global $wp_locale;

$decimal_sep = $wp_locale->number_format['decimal_point'];

// Separators.
$separators = array( $decimal_sep, '.', ',' );
$separators = array_unique( array_filter( $separators ) );

// Check.
foreach ( array( - 3, - 2 ) as $i ) {
$test = substr( $string, $i, 1 );

if ( in_array( $test, $separators, true ) ) {
$decimal_sep = $test;

break;
}
}

// Split.
$position = false;

if ( is_string( $decimal_sep ) ) {
$position = strrpos( $string, $decimal_sep );
}

// Check decimal position on -4th position at end of string of negative amount (e.g. `2.500,75-`).
if ( false === $position && '-' === \substr( $string, -1, 1 ) ) {
$test = substr( $string, -4, 1 );

if ( is_string( $test ) && in_array( $test, $separators, true ) ) {
$position = strrpos( $string, $test );
}
}

if ( false !== $position ) {
$full = substr( $string, 0, $position );
$half = substr( $string, $position + 1 );

/*
* Consider `-` after decimal separator as alternative notation for 'no minor units' (e.g. `€ 5,-`).
*
* @link https://taaladvies.net/taal/advies/vraag/275/euro_komma_en_streepje_in_de_notatie_van_hele_bedragen/
*/
if ( \in_array( $half, array( '-', '', '' ), true ) ) {
$half = '';
}

$end_minus = ( '-' === \substr( $half, -1, 1 ) );

$full = filter_var( $full, FILTER_SANITIZE_NUMBER_INT );
$half = filter_var( $half, FILTER_SANITIZE_NUMBER_INT );

// Make amount negative if half string ends with minus sign.
if ( $end_minus ) {
// Make full negative.
$full = sprintf( '-%s', $full );

// Remove minus from end of half.
$half = \substr( (string) $half, 0, -1 );
}

$string = $full . '.' . $half;
} else {
// Make amount negative if full string ends with minus sign.
if ( '-' === \substr( $string, -1, 1 ) ) {
$string = sprintf( '-%s', \substr( $string, 0, -1 ) );
}

$string = filter_var( $string, FILTER_SANITIZE_NUMBER_INT );
}

// Filter.
$value = filter_var( $string, FILTER_VALIDATE_FLOAT );

if ( false === $value ) {
throw new \Exception( 'Could not parse value to number object.' );
}

return Number::from_mixed( $value );
}
}
143 changes: 143 additions & 0 deletions tests/src/ParserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php
/**
* Parser
*
* @author Pronamic <info@pronamic.eu>
* @copyright 2005-2021 Pronamic
* @license GPL-3.0-or-later
* @package Pronamic\WordPress\Number
*/

namespace Pronamic\WordPress\Number;

use WP_UnitTestCase;

/**
* Parser
*
* @author Remco Tolsma
* @version 1.2.5
* @since 1.1.0
*/
class ParserTest extends WP_UnitTestCase {
/**
* Parser.
*
* @var Parser
*/
private $parser;

/**
* Setup.
*/
public function setUp() {
parent::setUp();

$this->parser = new Parser();
}

/**
* Test string to amount.
*
* @link https://github.com/pronamic/wp-pronamic-ideal/blob/3.7.3/classes/Pronamic/WP/Pay/Settings.php#L71-L91
* @link https://github.com/WordPress/WordPress/blob/4.9.6/wp-includes/class-wp-locale.php
* @link https://github.com/WordPress/WordPress/blob/4.9.6/wp-includes/functions.php#L206-L237
*
* @dataProvider string_to_amount_provider
*
* @param string $thousands_sep Thousands seperator.
* @param string $decimal_sep Decimal seperator.
* @param string $string String value to convert.
* @param float $expected Expected float value.
*/
public function test_string_to_amount( $thousands_sep, $decimal_sep, $string, $expected ) {
global $wp_locale;

$wp_locale->number_format['thousands_sep'] = $thousands_sep;
$wp_locale->number_format['decimal_point'] = $decimal_sep;

$number = $this->parser->parse( $string );

$value = $number->get_value();

$this->assertSame( $expected, $value );
}

/**
* String to amount provider.
*
* @return array
*/
public function string_to_amount_provider() {
return array(
// Thousands separator is '' and decimal separator is '.'.
array( '', '.', '1', '1' ),
array( '', '.', '2,5', '2.5' ),
array( '', '.', '2,50', '2.5' ),
array( '', '.', '1250,00', '1250' ),
array( '', '.', '1250,75', '1250.75' ),
array( '', '.', '1250.75', '1250.75' ),
array( '', '.', '1.250,00', '1250' ),
array( '', '.', '2.500,75', '2500.75' ),
array( '', '.', '2500,75-', '-2500.75' ),
array( '', '.', '-2500,75', '-2500.75' ),
array( '', '.', '2500-', '-2500' ),
array( '', '.', '-2500', '-2500' ),
array( '', '.', '1-', '-1' ),
// Thousands separator is '.' and decimal separator is ','.
array( '.', ',', '1', '1' ),
array( '.', ',', '2,5', '2.5' ),
array( '.', ',', '2,50', '2.5' ),
array( '.', ',', '1250,00', '1250' ),
array( '.', ',', '2500,75', '2500.75' ),
array( '.', ',', '1.250,00', '1250' ),
array( '.', ',', '2.500,75', '2500.75' ),
array( '.', ',', '2.500,750', '2500.75' ),
array( '.', ',', '1.234.567.890', '1234567890' ),
array( '.', ',', '2.500,75-', '-2500.75' ),
array( '.', ',', '-2.500,75', '-2500.75' ),
array( '.', ',', '2.500-', '-2500' ),
array( '.', ',', '-2.500', '-2500' ),
array( '.', ',', '1-', '-1' ),
// Thousands separator is ',' and decimal separator is '.'.
array( ',', '.', '1', '1' ),
array( ',', '.', '2.5', '2.5' ),
array( ',', '.', '2.50', '2.5' ),
array( ',', '.', '1250.00', '1250' ),
array( ',', '.', '1250.75', '1250.75' ),
array( ',', '.', '1,250.00', '1250' ),
array( ',', '.', '2,500.75', '2500.75' ),
array( ',', '.', '2,500.', '2500' ),
array( ',', '.', '2,500.75-', '-2500.75' ),
array( ',', '.', '-2,500.75', '-2500.75' ),
array( ',', '.', '2,500-', '-2500' ),
array( ',', '.', '-2,500', '-2500' ),
array( ',', '.', '1-', '-1' ),
// Thousands separator is ' ' and decimal separator is '.'.
array( ' ', '.', '2 500.75', '2500.75' ),
// Thousands separator is 't' and decimal separator is '.'.
array( 't', '.', '2t500.75', '2500.75' ),
array( 't', '.', '2t500.7', '2500.7' ),
// Thousands separator is 't' and decimal separator is '-'.
array( 't', '-', '2t500-75', '2500.75' ),
array( 't', '-', '2t500-7', '2500.7' ),
// Thousands separator is 't' and decimal separator is ' '.
array( 't', ' ', '2t500 75', '2500.75' ),
array( 't', ' ', '2t500 7', '2500.7' ),
// Thousands separator is ' ' and decimal separator is 'd'.
array( ' ', 'd', '2 500d75', '2500.75' ),
array( ' ', 'd', '2 500d7', '2500.7' ),
array( ' ', 'd', '-2 500d75', '-2500.75' ),
array( ' ', 'd', '-2 500d7', '-2500.7' ),
// Other.
array( '.', ',', 'EUR 1.250', '1250' ),
array( '.', ',', 'EUR 1.250,75', '1250.75' ),
array( '.', ',', 'EUR -1.250', '-1250' ),
array( '.', ',', 'EUR -1.250,75', '-1250.75' ),
array( '.', ',', '1.250,-', '1250' ),
array( '.', ',', '-1.250,-', '-1250' ),
array( '', '', '123456789', '123456789' ),
array( false, false, '123 456 789', '123456789' ),
);
}
}

0 comments on commit ff5c55c

Please sign in to comment.