Parser   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Test Coverage

Coverage 97.22%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 37
c 2
b 0
f 0
dl 0
loc 93
ccs 35
cts 36
cp 0.9722
rs 10
wmc 13

1 Method

Rating   Name   Duplication   Size   Complexity  
C parse() 0 81 13
1
<?php
2
/**
3
 * Parser
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2023 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Money
9
 */
10
11
namespace Pronamic\WordPress\Money;
12
13
use Exception;
14
15
/**
16
 * Parser
17
 *
18
 * @author  Remco Tolsma
19
 * @version 2.0.0
20
 * @since   1.1.0
21
 */
22
class Parser {
23
	/**
24
	 * Parse.
25
	 *
26
	 * @link https://github.com/wp-pay/core/blob/2.0.2/src/Core/Util.php#L128-L176
27
	 *
28
	 * @param string $string String to parse as money.
29
	 *
30
	 * @return Money
31
	 *
32
	 * @throws Exception Throws exception when parsing string fails.
33
	 */
34 59
	public function parse( $string ) {
35 59
		global $wp_locale;
36
37 59
		$decimal_sep = $wp_locale->number_format['decimal_point'];
38
39
		// Separators.
40 59
		$separators = [ $decimal_sep, '.', ',' ];
41 59
		$separators = array_unique( array_filter( $separators ) );
42
43
		// Check.
44 59
		foreach ( [ - 3, - 2 ] as $i ) {
45 59
			$test = substr( $string, $i, 1 );
46
47 59
			if ( in_array( $test, $separators, true ) ) {
48 37
				$decimal_sep = $test;
49
50 59
				break;
51
			}
52
		}
53
54
		// Split.
55 59
		$position = false;
56
57 59
		if ( is_string( $decimal_sep ) ) {
58 58
			$position = strrpos( $string, $decimal_sep );
59
		}
60
61
		// Check decimal position on -4th position at end of string of negative amount (e.g. `2.500,75-`).
62 59
		if ( false === $position && '-' === \substr( $string, -1, 1 ) ) {
63 7
			$test = substr( $string, -4, 1 );
64
65 7
			if ( is_string( $test ) && in_array( $test, $separators, true ) ) {
66 1
				$position = strrpos( $string, $test );
67
			}
68
		}
69
70 59
		if ( false !== $position ) {
71 42
			$full = substr( $string, 0, $position );
72 42
			$half = substr( $string, $position + 1 );
73
74
			/*
75
			 * Consider `-` after decimal separator as alternative notation for 'no minor units' (e.g. `€ 5,-`).
76
			 *
77
			 * @link https://taaladvies.net/taal/advies/vraag/275/euro_komma_en_streepje_in_de_notatie_van_hele_bedragen/
78
			 */
79 42
			if ( \in_array( $half, [ '-', '–', '—' ], true ) ) {
80 2
				$half = '';
81
			}
82
83 42
			$end_minus = ( '-' === \substr( $half, -1, 1 ) );
84
85 42
			$full = filter_var( $full, FILTER_SANITIZE_NUMBER_INT );
86 42
			$half = filter_var( $half, FILTER_SANITIZE_NUMBER_INT );
87
88
			// Make amount negative if half string ends with minus sign.
89 42
			if ( $end_minus ) {
90
				// Make full negative.
91 3
				$full = sprintf( '-%s', $full );
92
93
				// Remove minus from end of half.
94 3
				$half = \substr( (string) $half, 0, -1 );
95
			}
96
97 42
			$string = $full . '.' . $half;
98
		} else {
99
			// Make amount negative if full string ends with minus sign.
100 17
			if ( '-' === \substr( $string, -1, 1 ) ) {
101 6
				$string = sprintf( '-%s', \substr( $string, 0, -1 ) );
102
			}
103
104 17
			$string = filter_var( $string, FILTER_SANITIZE_NUMBER_INT );
105
		}
106
107
		// Filter.
108 59
		$value = filter_var( $string, FILTER_VALIDATE_FLOAT );
109
110 59
		if ( false === $value ) {
111
			throw new Exception( 'Could not parse value to money object.' );
112
		}
113
114 59
		return new Money( $value );
115
	}
116
}
117