GetPaid_Tax::get_all_tax_rules()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 16
nc 1
nop 0
dl 0
loc 23
rs 9.7333
c 0
b 0
f 0
1
<?php
2
/**
3
 * Contains the main tax class.
4
 *
5
 *
6
 */
7
8
defined( 'ABSPATH' ) || exit;
9
10
/**
11
 * Class GetPaid_Tax
12
 *
13
 */
14
class GetPaid_Tax {
15
16
	/**
17
	 * Calculates tax for a line item.
18
	 *
19
	 * @param  float   $price              The price to calc tax on.
20
	 * @param  array   $rates              The rates to apply.
21
	 * @param  boolean $price_includes_tax Whether the passed price has taxes included.
22
	 * @return array                       Array of tax name => tax amount.
23
	 */
24
	public static function calc_tax( $price, $rates, $price_includes_tax = false ) {
25
26
		if ( $price_includes_tax ) {
27
			$taxes = self::calc_inclusive_tax( $price, $rates );
28
		} else {
29
			$taxes = self::calc_exclusive_tax( $price, $rates );
30
		}
31
32
		return apply_filters( 'getpaid_calc_tax', $taxes, $price, $rates, $price_includes_tax );
33
34
	}
35
36
	/**
37
	 * Calc tax from inclusive price.
38
	 *
39
	 * @param  float $price Price to calculate tax for.
40
	 * @param  array $rates Array of tax rates.
41
	 * @return array
42
	 */
43
	public static function calc_inclusive_tax( $price, $rates ) {
44
		$taxes     = array();
45
		$tax_rates = wp_list_pluck( $rates, 'rate', 'name' );
46
47
		// Add tax rates.
48
		$tax_rate  = 1 + ( array_sum( $tax_rates ) / 100 );
49
50
		foreach ( $tax_rates as $name => $rate ) {
51
			$the_rate       = ( $rate / 100 ) / $tax_rate;
52
			$net_price      = $price - ( $the_rate * $price );
53
			$tax_amount     = apply_filters( 'getpaid_price_inc_tax_amount', $price - $net_price, $name, $rate, $price );
54
			$taxes[ $name ] = $tax_amount;
55
		}
56
57
		// Round all taxes to precision (4DP) before passing them back.
58
		$taxes = array_map( array( __CLASS__, 'round' ), $taxes );
59
60
		return $taxes;
61
	}
62
63
	/**
64
	 * Calc tax from exclusive price.
65
	 *
66
	 * @param  float $price Price to calculate tax for.
67
	 * @param  array $rates Array of tax rates.
68
	 * @return array
69
	 */
70
	public static function calc_exclusive_tax( $price, $rates ) {
71
		$taxes     = array();
72
		$tax_rates = wp_list_pluck( $rates, 'rate', 'name' );
73
74
		foreach ( $tax_rates as $name => $rate ) {
75
76
			$tax_amount     = $price * ( $rate / 100 );
77
			$taxes[ $name ] = apply_filters( 'getpaid_price_ex_tax_amount', $tax_amount, $name, $rate, $price );
78
79
		}
80
81
		// Round all taxes to precision (4DP) before passing them back.
82
		$taxes = array_map( array( __CLASS__, 'round' ), $taxes );
83
84
		return $taxes;
85
	}
86
87
	/**
88
	 * Get's an array of all tax rates.
89
	 *
90
	 * @return array
91
	 */
92
	public static function get_all_tax_rates() {
93
94
		$rates = get_option( 'wpinv_tax_rates', array() );
95
96
		return apply_filters(
97
			'getpaid_get_all_tax_rates',
98
			array_filter( wpinv_parse_list( $rates ) )
0 ignored issues
show
Bug introduced by
It seems like $rates can also be of type false; however, parameter $list of wpinv_parse_list() does only seem to accept array|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

98
			array_filter( wpinv_parse_list( /** @scrutinizer ignore-type */ $rates ) )
Loading history...
99
		);
100
101
	}
102
103
	/**
104
	 * Get's an array of default tax rates.
105
	 *
106
	 * @return array
107
	 */
108
	public static function get_default_tax_rates() {
109
110
		return apply_filters(
111
			'getpaid_get_default_tax_rates',
112
			array(
113
				array(
114
					'country' => wpinv_get_default_country(),
115
					'state'   => wpinv_get_default_state(),
116
					'global'  => true,
117
					'rate'    => wpinv_get_default_tax_rate(),
118
					'name'    => __( 'Tax', 'invoicing' ),
119
				),
120
			)
121
		);
122
123
	}
124
125
	/**
126
	 * Get's an array of all tax rules.
127
	 *
128
	 * @return array
129
	 */
130
	public static function get_all_tax_rules() {
131
132
		$rules = get_option(
133
			'wpinv_tax_rules',
134
			array(
135
				array(
136
					'key'               => 'physical',
137
					'label'             => __( 'Physical Item', 'invoicing' ),
138
					'tax_base'          => wpinv_get_option( 'tax_base', 'billing' ),
139
					'same_country_rule' => wpinv_get_option( 'vat_same_country_rule', 'vat_too' ),
140
				),
141
				array(
142
					'key'               => 'digital',
143
					'label'             => __( 'Digital Item', 'invoicing' ),
144
					'tax_base'          => wpinv_get_option( 'tax_base', 'billing' ),
145
					'same_country_rule' => wpinv_get_option( 'vat_same_country_rule', 'vat_too' ),
146
				),
147
        	)
148
		);
149
150
		return apply_filters(
151
			'getpaid_tax_rules',
152
			array_filter( array_values( wpinv_parse_list( $rules ) ) )
0 ignored issues
show
Bug introduced by
It seems like $rules can also be of type false; however, parameter $list of wpinv_parse_list() does only seem to accept array|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

152
			array_filter( array_values( wpinv_parse_list( /** @scrutinizer ignore-type */ $rules ) ) )
Loading history...
153
		);
154
155
	}
156
157
	/**
158
	 * Get's an array of tax rates for a given address.
159
	 *
160
	 * @param string $country
161
	 * @param string $state
162
	 * @return array
163
	 */
164
	public static function get_address_tax_rates( $country, $state ) {
165
166
		$all_tax_rates  = self::get_all_tax_rates();
167
		$matching_rates = array_merge(
168
			wp_list_filter( $all_tax_rates, array( 'country' => $country ) ),
169
			wp_list_filter( $all_tax_rates, array( 'country' => '' ) )
170
		);
171
172
		foreach ( $matching_rates as $i => $rate ) {
173
174
			$states = array_filter( wpinv_clean( explode( ',', strtolower( $rate['state'] ) ) ) );
175
			if ( empty( $rate['global'] ) && ! in_array( strtolower( $state ), $states ) ) {
176
				unset( $matching_rates[ $i ] );
177
			}
178
}
179
180
		return apply_filters( 'getpaid_get_address_tax_rates', $matching_rates, $country, $state );
181
182
	}
183
184
	/**
185
	 * Sums a set of taxes to form a single total. Result is rounded to precision.
186
	 *
187
	 * @param  array $taxes Array of taxes.
188
	 * @return float
189
	 */
190
	public static function get_tax_total( $taxes ) {
191
		return self::round( array_sum( $taxes ) );
192
	}
193
194
	/**
195
	 * Round to precision.
196
	 *
197
	 * Filter example: to return rounding to .5 cents you'd use:
198
	 *
199
	 * function euro_5cent_rounding( $in ) {
200
	 *      return round( $in / 5, 2 ) * 5;
201
	 * }
202
	 * add_filter( 'getpaid_tax_round', 'euro_5cent_rounding' );
203
	 *
204
	 * @param float|int $in Value to round.
205
	 * @return float
206
	 */
207
	public static function round( $in ) {
208
		return apply_filters( 'getpaid_tax_round', round( $in, 4 ), $in );
209
	}
210
211
}
212