|
1
|
|
|
<?php |
|
2
|
|
|
// MUST have WordPress. |
|
3
|
|
|
if ( !defined( 'WPINC' ) ) { |
|
4
|
|
|
exit( 'Do NOT access this file directly: ' . basename( __FILE__ ) ); |
|
5
|
|
|
} |
|
6
|
|
|
|
|
7
|
|
|
/** |
|
8
|
|
|
* Retrieves the tax class. |
|
9
|
|
|
* |
|
10
|
|
|
* @return WPInv_EUVat |
|
11
|
|
|
*/ |
|
12
|
|
|
function getpaid_tax() { |
|
13
|
|
|
return new WPInv_EUVat(); |
|
14
|
|
|
} |
|
15
|
|
|
|
|
16
|
|
|
/** |
|
17
|
|
|
* Checks if a given country is an EU state. |
|
18
|
|
|
* |
|
19
|
|
|
* @return bool |
|
20
|
|
|
*/ |
|
21
|
|
|
function getpaid_is_eu_state( $country ) { |
|
22
|
|
|
return WPInv_EUVat::is_eu_state( $country ); |
|
23
|
|
|
} |
|
24
|
|
|
|
|
25
|
|
|
/** |
|
26
|
|
|
* Checks if a given country is GST country. |
|
27
|
|
|
* |
|
28
|
|
|
* @return bool |
|
29
|
|
|
*/ |
|
30
|
|
|
function getpaid_is_gst_country( $country ) { |
|
31
|
|
|
return WPInv_EUVat::is_gst_country( $country ); |
|
32
|
|
|
} |
|
33
|
|
|
|
|
34
|
|
|
/** |
|
35
|
|
|
* Returns the vat name. |
|
36
|
|
|
* |
|
37
|
|
|
* @return string |
|
38
|
|
|
*/ |
|
39
|
|
|
function getpaid_vat_name() { |
|
40
|
|
|
return getpaid_tax()->get_vat_name(); |
|
41
|
|
|
} |
|
42
|
|
|
|
|
43
|
|
|
|
|
44
|
|
|
function wpinv_use_taxes() { |
|
45
|
|
|
$ret = wpinv_get_option( 'enable_taxes', false ); |
|
46
|
|
|
|
|
47
|
|
|
return (bool) apply_filters( 'wpinv_use_taxes', $ret ); |
|
48
|
|
|
} |
|
49
|
|
|
|
|
50
|
|
|
function wpinv_get_tax_rates() { |
|
51
|
|
|
$rates = get_option( 'wpinv_tax_rates', array() ); |
|
52
|
|
|
|
|
53
|
|
|
return apply_filters( 'wpinv_get_tax_rates', $rates ); |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
function wpinv_get_tax_rate( $country = false, $state = false, $item_id = 0 ) { |
|
57
|
|
|
global $wpinv_euvat, $wpi_tax_rates, $wpi_userID; |
|
58
|
|
|
$wpi_tax_rates = !empty( $wpi_tax_rates ) ? $wpi_tax_rates : array(); |
|
59
|
|
|
|
|
60
|
|
|
if ( !empty( $wpi_tax_rates ) && !empty( $item_id ) && isset( $wpi_tax_rates[$item_id] ) ) { |
|
61
|
|
|
return $wpi_tax_rates[$item_id]; |
|
62
|
|
|
} |
|
63
|
|
|
|
|
64
|
|
|
if ( !$wpinv_euvat->item_is_taxable( $item_id, $country, $state ) ) { |
|
65
|
|
|
$wpi_tax_rates[$item_id] = 0; |
|
66
|
|
|
return 0; |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
$is_global = false; |
|
70
|
|
|
if ( $item_id == 'global' ) { |
|
71
|
|
|
$is_global = true; |
|
72
|
|
|
$item_id = 0; |
|
73
|
|
|
} |
|
74
|
|
|
|
|
75
|
|
|
$rate = (float)wpinv_get_option( 'tax_rate', 0 ); |
|
76
|
|
|
$user_address = wpinv_get_user_address( $wpi_userID ); |
|
77
|
|
|
|
|
78
|
|
|
if( empty( $country ) ) { |
|
79
|
|
|
if( !empty( $_POST['wpinv_country'] ) ) { |
|
80
|
|
|
$country = $_POST['wpinv_country']; |
|
81
|
|
|
} elseif( !empty( $_POST['wpinv_country'] ) ) { |
|
82
|
|
|
$country = $_POST['wpinv_country']; |
|
83
|
|
|
} elseif( !empty( $_POST['country'] ) ) { |
|
84
|
|
|
$country = $_POST['country']; |
|
85
|
|
|
} elseif( is_user_logged_in() && !empty( $user_address ) ) { |
|
86
|
|
|
$country = $user_address['country']; |
|
87
|
|
|
} |
|
88
|
|
|
$country = !empty( $country ) ? $country : wpinv_get_default_country(); |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
|
|
if( empty( $state ) ) { |
|
92
|
|
|
if( !empty( $_POST['wpinv_state'] ) ) { |
|
93
|
|
|
$state = $_POST['wpinv_state']; |
|
94
|
|
|
} elseif( !empty( $_POST['wpinv_state'] ) ) { |
|
95
|
|
|
$state = $_POST['wpinv_state']; |
|
96
|
|
|
} elseif( !empty( $_POST['state'] ) ) { |
|
97
|
|
|
$state = $_POST['state']; |
|
98
|
|
|
} elseif( is_user_logged_in() && !empty( $user_address ) ) { |
|
99
|
|
|
$state = $user_address['state']; |
|
100
|
|
|
} |
|
101
|
|
|
$state = !empty( $state ) ? $state : wpinv_get_default_state(); |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
|
|
if( !empty( $country ) ) { |
|
105
|
|
|
$tax_rates = wpinv_get_tax_rates(); |
|
106
|
|
|
|
|
107
|
|
|
if( !empty( $tax_rates ) ) { |
|
108
|
|
|
// Locate the tax rate for this country / state, if it exists |
|
109
|
|
|
foreach( $tax_rates as $key => $tax_rate ) { |
|
110
|
|
|
if( $country != $tax_rate['country'] ) |
|
111
|
|
|
continue; |
|
112
|
|
|
|
|
113
|
|
|
if( !empty( $tax_rate['global'] ) ) { |
|
114
|
|
|
if( !empty( $tax_rate['rate'] ) ) { |
|
115
|
|
|
$rate = number_format( $tax_rate['rate'], 4 ); |
|
116
|
|
|
} |
|
117
|
|
|
} else { |
|
118
|
|
|
|
|
119
|
|
|
if( empty( $tax_rate['state'] ) || strtolower( $state ) != strtolower( $tax_rate['state'] ) ) |
|
120
|
|
|
continue; |
|
121
|
|
|
|
|
122
|
|
|
$state_rate = $tax_rate['rate']; |
|
123
|
|
|
if( 0 !== $state_rate || !empty( $state_rate ) ) { |
|
124
|
|
|
$rate = number_format( $state_rate, 4 ); |
|
125
|
|
|
} |
|
126
|
|
|
} |
|
127
|
|
|
} |
|
128
|
|
|
} |
|
129
|
|
|
} |
|
130
|
|
|
|
|
131
|
|
|
$rate = apply_filters( 'wpinv_tax_rate', $rate, $country, $state, $item_id ); |
|
132
|
|
|
|
|
133
|
|
|
if ( !empty( $item_id ) ) { |
|
134
|
|
|
$wpi_tax_rates[$item_id] = $rate; |
|
135
|
|
|
} else if ( $is_global ) { |
|
136
|
|
|
$wpi_tax_rates['global'] = $rate; |
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
|
|
return $rate; |
|
140
|
|
|
} |
|
141
|
|
|
|
|
142
|
|
|
function wpinv_get_formatted_tax_rate( $country = false, $state = false, $item_id ) { |
|
143
|
|
|
$rate = wpinv_get_tax_rate( $country, $state, $item_id ); |
|
144
|
|
|
$rate = round( $rate, 4 ); |
|
145
|
|
|
$formatted = $rate .= '%'; |
|
146
|
|
|
return apply_filters( 'wpinv_formatted_tax_rate', $formatted, $rate, $country, $state, $item_id ); |
|
147
|
|
|
} |
|
148
|
|
|
|
|
149
|
|
|
function wpinv_calculate_tax( $amount = 0, $country = false, $state = false, $item_id = 0 ) { |
|
150
|
|
|
$rate = wpinv_get_tax_rate( $country, $state, $item_id ); |
|
151
|
|
|
$tax = 0.00; |
|
152
|
|
|
|
|
153
|
|
|
if ( wpinv_use_taxes() ) { |
|
154
|
|
|
if ( wpinv_prices_include_tax() ) { |
|
155
|
|
|
$pre_tax = ( $amount / ( ( 1 + $rate ) * 0.01 ) ); |
|
156
|
|
|
$tax = $amount - $pre_tax; |
|
157
|
|
|
} else { |
|
158
|
|
|
$tax = $amount * $rate * 0.01; |
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
} |
|
162
|
|
|
|
|
163
|
|
|
return apply_filters( 'wpinv_taxed_amount', $tax, $rate, $country, $state, $item_id ); |
|
164
|
|
|
} |
|
165
|
|
|
|
|
166
|
|
|
function wpinv_prices_include_tax() { |
|
167
|
|
|
return false; // TODO |
|
168
|
|
|
$ret = ( wpinv_get_option( 'prices_include_tax', false ) == 'yes' && wpinv_use_taxes() ); |
|
|
|
|
|
|
169
|
|
|
|
|
170
|
|
|
return apply_filters( 'wpinv_prices_include_tax', $ret ); |
|
171
|
|
|
} |
|
172
|
|
|
|
|
173
|
|
|
function wpinv_sales_tax_for_year( $year = null ) { |
|
174
|
|
|
return wpinv_price( wpinv_format_amount( wpinv_get_sales_tax_for_year( $year ) ) ); |
|
175
|
|
|
} |
|
176
|
|
|
|
|
177
|
|
|
function wpinv_get_sales_tax_for_year( $year = null ) { |
|
178
|
|
|
global $wpdb; |
|
179
|
|
|
|
|
180
|
|
|
// Start at zero |
|
181
|
|
|
$tax = 0; |
|
182
|
|
|
|
|
183
|
|
|
if ( ! empty( $year ) ) { |
|
184
|
|
|
$args = array( |
|
185
|
|
|
'post_type' => 'wpi_invoice', |
|
186
|
|
|
'post_status' => array( 'publish' ), |
|
187
|
|
|
'posts_per_page' => -1, |
|
188
|
|
|
'year' => $year, |
|
189
|
|
|
'fields' => 'ids' |
|
190
|
|
|
); |
|
191
|
|
|
|
|
192
|
|
|
$payments = get_posts( $args ); |
|
193
|
|
|
$payment_ids = implode( ',', $payments ); |
|
194
|
|
|
|
|
195
|
|
|
if ( count( $payments ) > 0 ) { |
|
196
|
|
|
$sql = "SELECT SUM( meta_value ) FROM $wpdb->postmeta WHERE meta_key = '_wpinv_tax' AND post_id IN( $payment_ids )"; |
|
197
|
|
|
$tax = $wpdb->get_var( $sql ); |
|
198
|
|
|
} |
|
199
|
|
|
|
|
200
|
|
|
} |
|
201
|
|
|
|
|
202
|
|
|
return apply_filters( 'wpinv_get_sales_tax_for_year', $tax, $year ); |
|
203
|
|
|
} |
|
204
|
|
|
|
|
205
|
|
|
function wpinv_is_cart_taxed() { |
|
206
|
|
|
return wpinv_use_taxes(); |
|
207
|
|
|
} |
|
208
|
|
|
|
|
209
|
|
|
function wpinv_prices_show_tax_on_checkout() { |
|
210
|
|
|
return false; // TODO |
|
211
|
|
|
$ret = ( wpinv_get_option( 'checkout_include_tax', false ) == 'yes' && wpinv_use_taxes() ); |
|
|
|
|
|
|
212
|
|
|
|
|
213
|
|
|
return apply_filters( 'wpinv_taxes_on_prices_on_checkout', $ret ); |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
function wpinv_display_tax_rate() { |
|
217
|
|
|
$ret = wpinv_use_taxes() && wpinv_get_option( 'display_tax_rate', false ); |
|
218
|
|
|
|
|
219
|
|
|
return apply_filters( 'wpinv_display_tax_rate', $ret ); |
|
220
|
|
|
} |
|
221
|
|
|
|
|
222
|
|
|
function wpinv_cart_needs_tax_address_fields() { |
|
223
|
|
|
if( !wpinv_is_cart_taxed() ) |
|
224
|
|
|
return false; |
|
225
|
|
|
|
|
226
|
|
|
return ! did_action( 'wpinv_after_cc_fields', 'wpinv_default_cc_address_fields' ); |
|
|
|
|
|
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
function wpinv_item_is_tax_exclusive( $item_id = 0 ) { |
|
230
|
|
|
$ret = (bool)get_post_meta( $item_id, '_wpinv_tax_exclusive', false ); |
|
231
|
|
|
return apply_filters( 'wpinv_is_tax_exclusive', $ret, $item_id ); |
|
232
|
|
|
} |
|
233
|
|
|
|
|
234
|
|
|
function wpinv_currency_decimal_filter( $decimals = 2 ) { |
|
235
|
|
|
$currency = wpinv_get_currency(); |
|
236
|
|
|
|
|
237
|
|
|
switch ( $currency ) { |
|
238
|
|
|
case 'RIAL' : |
|
239
|
|
|
case 'JPY' : |
|
240
|
|
|
case 'TWD' : |
|
241
|
|
|
case 'HUF' : |
|
242
|
|
|
$decimals = 0; |
|
243
|
|
|
break; |
|
244
|
|
|
} |
|
245
|
|
|
|
|
246
|
|
|
return apply_filters( 'wpinv_currency_decimal_count', $decimals, $currency ); |
|
247
|
|
|
} |
|
248
|
|
|
|
|
249
|
|
|
function wpinv_tax_amount() { |
|
250
|
|
|
$output = 0.00; |
|
251
|
|
|
|
|
252
|
|
|
return apply_filters( 'wpinv_tax_amount', $output ); |
|
253
|
|
|
} |
|
254
|
|
|
|
|
255
|
|
|
function wpinv_recalculated_tax() { |
|
256
|
|
|
define( 'WPINV_RECALCTAX', true ); |
|
257
|
|
|
} |
|
258
|
|
|
add_action( 'wp_ajax_wpinv_recalculate_tax', 'wpinv_recalculated_tax', 1 ); |
|
259
|
|
|
|
|
260
|
|
|
function wpinv_recalculate_tax( $return = false ) { |
|
261
|
|
|
$invoice_id = (int)wpinv_get_invoice_cart_id(); |
|
|
|
|
|
|
262
|
|
|
if ( empty( $invoice_id ) ) { |
|
263
|
|
|
return false; |
|
264
|
|
|
} |
|
265
|
|
|
|
|
266
|
|
|
$invoice = wpinv_get_invoice_cart( $invoice_id ); |
|
|
|
|
|
|
267
|
|
|
|
|
268
|
|
|
if ( empty( $invoice ) ) { |
|
269
|
|
|
return false; |
|
270
|
|
|
} |
|
271
|
|
|
|
|
272
|
|
|
if ( empty( $_POST['country'] ) ) { |
|
273
|
|
|
$_POST['country'] = !empty($invoice->country) ? $invoice->country : wpinv_get_default_country(); |
|
|
|
|
|
|
274
|
|
|
} |
|
275
|
|
|
|
|
276
|
|
|
$invoice->country = sanitize_text_field($_POST['country']); |
|
|
|
|
|
|
277
|
|
|
$invoice->set( 'country', sanitize_text_field( $_POST['country'] ) ); |
|
278
|
|
|
if (isset($_POST['state'])) { |
|
279
|
|
|
$invoice->state = sanitize_text_field($_POST['state']); |
|
|
|
|
|
|
280
|
|
|
$invoice->set( 'state', sanitize_text_field( $_POST['state'] ) ); |
|
281
|
|
|
} |
|
282
|
|
|
|
|
283
|
|
|
$invoice->cart_details = wpinv_get_cart_content_details(); |
|
|
|
|
|
|
284
|
|
|
|
|
285
|
|
|
$subtotal = wpinv_get_cart_subtotal( $invoice->cart_details ); |
|
|
|
|
|
|
286
|
|
|
$tax = wpinv_get_cart_tax( $invoice->cart_details ); |
|
|
|
|
|
|
287
|
|
|
$total = wpinv_get_cart_total( $invoice->cart_details ); |
|
|
|
|
|
|
288
|
|
|
|
|
289
|
|
|
$invoice->tax = $tax; |
|
|
|
|
|
|
290
|
|
|
$invoice->subtotal = $subtotal; |
|
|
|
|
|
|
291
|
|
|
$invoice->total = $total; |
|
|
|
|
|
|
292
|
|
|
|
|
293
|
|
|
$invoice->save(); |
|
294
|
|
|
|
|
295
|
|
|
if ( $invoice->is_free_trial() ) { |
|
|
|
|
|
|
296
|
|
|
$total = 0; |
|
297
|
|
|
} |
|
298
|
|
|
|
|
299
|
|
|
$response = array( |
|
300
|
|
|
'total' => html_entity_decode( wpinv_price( wpinv_format_amount( $total ) ), ENT_COMPAT, 'UTF-8' ), |
|
301
|
|
|
'total_raw' => $total, |
|
302
|
|
|
'free' => !( (float)$total > 0 ) && $invoice->is_free() ? true : false, |
|
303
|
|
|
'html' => wpinv_checkout_cart( $invoice->cart_details, false ), |
|
304
|
|
|
); |
|
305
|
|
|
|
|
306
|
|
|
if ( $return ) { |
|
307
|
|
|
return $response; |
|
308
|
|
|
} |
|
309
|
|
|
|
|
310
|
|
|
wp_send_json( $response ); |
|
311
|
|
|
} |
|
312
|
|
|
add_action( 'wp_ajax_wpinv_recalculate_tax', 'wpinv_recalculate_tax' ); |
|
313
|
|
|
add_action( 'wp_ajax_nopriv_wpinv_recalculate_tax', 'wpinv_recalculate_tax' ); |
|
314
|
|
|
|
|
315
|
|
|
// VAT Settings |
|
316
|
|
|
function wpinv_vat_rate_add_callback( $args ) { |
|
|
|
|
|
|
317
|
|
|
?> |
|
318
|
|
|
<p class="wpi-vat-rate-actions"><input id="wpi_vat_rate_add" type="button" value="<?php esc_attr_e( 'Add', 'invoicing' );?>" class="button button-primary" /> <i style="display:none;" class="fa fa-refresh fa-spin"></i></p> |
|
319
|
|
|
<?php |
|
320
|
|
|
} |
|
321
|
|
|
|
|
322
|
|
|
function wpinv_vat_rate_delete_callback( $args ) { |
|
|
|
|
|
|
323
|
|
|
global $wpinv_euvat; |
|
324
|
|
|
|
|
325
|
|
|
$vat_classes = $wpinv_euvat->get_rate_classes(); |
|
326
|
|
|
$vat_class = isset( $_REQUEST['wpi_sub'] ) && $_REQUEST['wpi_sub'] !== '' && isset( $vat_classes[$_REQUEST['wpi_sub']] )? sanitize_text_field( $_REQUEST['wpi_sub'] ) : ''; |
|
327
|
|
|
if ( isset( $vat_classes[$vat_class] ) ) { |
|
328
|
|
|
?> |
|
329
|
|
|
<p class="wpi-vat-rate-actions"><input id="wpi_vat_rate_delete" type="button" value="<?php echo wp_sprintf( esc_attr__( 'Delete class "%s"', 'invoicing' ), $vat_classes[$vat_class] );?>" class="button button-primary" /> <i style="display:none;" class="fa fa-refresh fa-spin"></i></p> |
|
330
|
|
|
<?php |
|
331
|
|
|
} |
|
332
|
|
|
} |
|
333
|
|
|
|
|
334
|
|
|
function wpinv_vat_rates_callback( $args ) { |
|
335
|
|
|
global $wpinv_euvat; |
|
336
|
|
|
|
|
337
|
|
|
$vat_classes = $wpinv_euvat->get_rate_classes(); |
|
338
|
|
|
$vat_class = isset( $_REQUEST['wpi_sub'] ) && $_REQUEST['wpi_sub'] !== '' && isset( $vat_classes[$_REQUEST['wpi_sub']] )? sanitize_text_field( $_REQUEST['wpi_sub'] ) : '_standard'; |
|
339
|
|
|
|
|
340
|
|
|
$eu_states = $wpinv_euvat->get_eu_states(); |
|
341
|
|
|
$countries = wpinv_get_country_list(); |
|
342
|
|
|
$vat_groups = $wpinv_euvat->get_vat_groups(); |
|
343
|
|
|
$rates = $wpinv_euvat->get_vat_rates( $vat_class ); |
|
344
|
|
|
ob_start(); |
|
345
|
|
|
?> |
|
346
|
|
|
</td><tr> |
|
347
|
|
|
<td colspan="2" class="wpinv_vat_tdbox"> |
|
348
|
|
|
<input type="hidden" name="wpi_vat_class" value="<?php echo $vat_class;?>" /> |
|
349
|
|
|
<p><?php echo ( isset( $args['desc'] ) ? $args['desc'] : '' ); ?></p> |
|
350
|
|
|
<table id="wpinv_vat_rates" class="wp-list-table widefat fixed posts"> |
|
351
|
|
|
<colgroup> |
|
352
|
|
|
<col width="50px" /> |
|
353
|
|
|
<col width="auto" /> |
|
354
|
|
|
<col width="auto" /> |
|
355
|
|
|
<col width="auto" /> |
|
356
|
|
|
<col width="auto" /> |
|
357
|
|
|
<col width="auto" /> |
|
358
|
|
|
</colgroup> |
|
359
|
|
|
<thead> |
|
360
|
|
|
<tr> |
|
361
|
|
|
<th scope="col" colspan="2" class="wpinv_vat_country_name"><?php _e( 'Country', 'invoicing' ); ?></th> |
|
362
|
|
|
<th scope="col" class="wpinv_vat_global" title="<?php esc_attr_e( 'Apply rate to whole country', 'invoicing' ); ?>"><?php _e( 'Country Wide', 'invoicing' ); ?></th> |
|
363
|
|
|
<th scope="col" class="wpinv_vat_rate"><?php _e( 'Rate %', 'invoicing' ); ?></th> |
|
364
|
|
|
<th scope="col" class="wpinv_vat_name"><?php _e( 'VAT Name', 'invoicing' ); ?></th> |
|
365
|
|
|
<th scope="col" class="wpinv_vat_group"><?php _e( 'Tax Group', 'invoicing' ); ?></th> |
|
366
|
|
|
</tr> |
|
367
|
|
|
</thead> |
|
368
|
|
|
<tbody> |
|
369
|
|
|
<?php if( !empty( $eu_states ) ) { ?> |
|
370
|
|
|
<?php |
|
371
|
|
|
foreach ( $eu_states as $state ) { |
|
372
|
|
|
$country_name = isset( $countries[$state] ) ? $countries[$state] : ''; |
|
373
|
|
|
|
|
374
|
|
|
// Filter the rate for each country |
|
375
|
|
|
$country_rate = array_filter( $rates, function( $rate ) use( $state ) { return $rate['country'] === $state; } ); |
|
376
|
|
|
|
|
377
|
|
|
// If one does not exist create a default |
|
378
|
|
|
$country_rate = is_array( $country_rate ) && count( $country_rate ) > 0 ? reset( $country_rate ) : array(); |
|
379
|
|
|
|
|
380
|
|
|
$vat_global = isset( $country_rate['global'] ) ? !empty( $country_rate['global'] ) : true; |
|
381
|
|
|
$vat_rate = isset( $country_rate['rate'] ) ? $country_rate['rate'] : ''; |
|
382
|
|
|
$vat_name = !empty( $country_rate['name'] ) ? esc_attr( stripslashes( $country_rate['name'] ) ) : ''; |
|
383
|
|
|
$vat_group = !empty( $country_rate['group'] ) ? $country_rate['group'] : ( $vat_class === '_standard' ? 'standard' : 'reduced' ); |
|
384
|
|
|
?> |
|
385
|
|
|
<tr> |
|
386
|
|
|
<td class="wpinv_vat_country"><?php echo $state; ?><input type="hidden" name="vat_rates[<?php echo $state; ?>][country]" value="<?php echo $state; ?>" /><input type="hidden" name="vat_rates[<?php echo $state; ?>][state]" value="" /></td> |
|
387
|
|
|
<td class="wpinv_vat_country_name"><?php echo $country_name; ?></td> |
|
388
|
|
|
<td class="wpinv_vat_global"> |
|
389
|
|
|
<input type="checkbox" name="vat_rates[<?php echo $state;?>][global]" id="vat_rates[<?php echo $state;?>][global]" value="1" <?php checked( true, $vat_global );?> disabled="disabled" /> |
|
390
|
|
|
<label for="tax_rates[<?php echo $state;?>][global]"><?php _e( 'Apply to whole country', 'invoicing' ); ?></label> |
|
391
|
|
|
<input type="hidden" name="vat_rates[<?php echo $state;?>][global]" value="1" checked="checked" /> |
|
392
|
|
|
</td> |
|
393
|
|
|
<td class="wpinv_vat_rate"><input type="number" class="small-text" step="any" min="0" max="99" name="vat_rates[<?php echo $state;?>][rate]" value="<?php echo $vat_rate; ?>" /></td> |
|
394
|
|
|
<td class="wpinv_vat_name"><input type="text" class="regular-text" name="vat_rates[<?php echo $state;?>][name]" value="<?php echo $vat_name; ?>" /></td> |
|
395
|
|
|
<td class="wpinv_vat_group"> |
|
396
|
|
|
<?php |
|
397
|
|
|
echo wpinv_html_select( array( |
|
398
|
|
|
'name' => 'vat_rates[' . $state . '][group]', |
|
399
|
|
|
'selected' => $vat_group, |
|
400
|
|
|
'id' => 'vat_rates[' . $state . '][group]', |
|
401
|
|
|
'class' => 'wpi_select2', |
|
402
|
|
|
'options' => $vat_groups, |
|
403
|
|
|
'multiple' => false, |
|
404
|
|
|
'show_option_all' => false, |
|
405
|
|
|
'show_option_none' => false |
|
406
|
|
|
) ); |
|
407
|
|
|
?> |
|
408
|
|
|
</td> |
|
409
|
|
|
</tr> |
|
410
|
|
|
<?php } ?> |
|
411
|
|
|
<tr> |
|
412
|
|
|
<td colspan="6" style="background-color:#fafafa;"> |
|
413
|
|
|
<span><input id="wpi_vat_get_rates_group" type="button" class="button-secondary" value="<?php esc_attr_e( 'Update EU VAT Rates', 'invoicing' ); ?>" /> <i style="display:none" class="fa fa-refresh fa-spin"></i></span><span id="wpinv-rates-error-wrap" class="wpinv_errors" style="display:none;"></span> |
|
414
|
|
|
</td> |
|
415
|
|
|
</tr> |
|
416
|
|
|
<?php } ?> |
|
417
|
|
|
</tbody> |
|
418
|
|
|
</table> |
|
419
|
|
|
<?php |
|
420
|
|
|
$content = ob_get_clean(); |
|
421
|
|
|
|
|
422
|
|
|
echo $content; |
|
423
|
|
|
} |
|
424
|
|
|
|
|
425
|
|
|
function wpinv_vat_number_callback( $args ) { |
|
426
|
|
|
global $wpinv_euvat; |
|
427
|
|
|
|
|
428
|
|
|
$vat_number = $wpinv_euvat->get_vat_number(); |
|
429
|
|
|
$vat_valid = $wpinv_euvat->is_vat_validated(); |
|
430
|
|
|
|
|
431
|
|
|
$size = ( isset( $args['size'] ) && !is_null( $args['size'] ) ) ? $args['size'] : 'regular'; |
|
432
|
|
|
$validated_text = $vat_valid ? __( 'VAT number validated', 'invoicing' ) : __( 'VAT number not validated', 'invoicing' ); |
|
433
|
|
|
$disabled = $vat_valid ? 'disabled="disabled"' : " "; |
|
434
|
|
|
|
|
435
|
|
|
$html = '<input type="text" class="' . $size . '-text" id="wpinv_settings[' . $args['id'] . ']" name="wpinv_settings[' . $args['id'] . ']" placeholder="GB123456789" value="' . esc_attr( stripslashes( $vat_number ) ) . '"/>'; |
|
436
|
|
|
$html .= '<span> <input type="button" id="wpinv_vat_validate" class="wpinv_validate_vat_button button-secondary" ' . $disabled . ' value="' . esc_attr__( 'Validate VAT Number', 'invoicing' ) . '" /></span>'; |
|
437
|
|
|
$html .= '<span class="wpinv-vat-stat wpinv-vat-stat-' . (int)$vat_valid . '"><i class="fa"></i> <font>' . $validated_text . '</font></span>'; |
|
438
|
|
|
$html .= '<label for="wpinv_settings[' . $args['id'] . ']">' . '<p>' . __( 'Enter your VAT number including country identifier, eg: GB123456789 (Settings must be saved after validation)', 'invoicing' ).'</p>' . '</label>'; |
|
439
|
|
|
$html .= '<input type="hidden" name="_wpi_nonce" value="' . wp_create_nonce( 'vat_validation' ) . '">'; |
|
440
|
|
|
|
|
441
|
|
|
echo $html; |
|
442
|
|
|
} |
|
443
|
|
|
|
|
444
|
|
|
function wpinv_eu_fallback_rate_callback( $args ) { |
|
445
|
|
|
global $wpinv_options; |
|
446
|
|
|
|
|
447
|
|
|
$value = isset( $wpinv_options[$args['id']] ) ? $wpinv_options[ $args['id'] ] : ( isset( $args['std'] ) ? $args['std'] : '' ); |
|
448
|
|
|
$size = ( isset( $args['size'] ) && !is_null( $args['size'] ) ) ? $args['size'] : 'small'; |
|
449
|
|
|
|
|
450
|
|
|
$html = '<input type="number" min="0" max="99" step="any" class="' . $size . '-text" id="wpinv_settings_' . $args['section'] . '_' . $args['id'] . '" name="wpinv_settings[' . $args['id'] . ']" value="' . esc_attr( stripslashes( $value ) ) . '" />'; |
|
451
|
|
|
$html .= '<span> <input id="wpi_add_eu_states" type="button" class="button-secondary" value="' . esc_attr__( 'Add EU Member States', 'invoicing' ) . '" /></span>'; |
|
452
|
|
|
$html .= '<span> <input id="wpi_remove_eu_states" type="button" class="button-secondary" value="' . esc_attr__( 'Remove EU Member States', 'invoicing' ) . '" /></span>'; |
|
453
|
|
|
$html .= '<span> <input id="wpi_vat_get_rates" type="button" class="button-secondary" value="' . esc_attr__( 'Update EU VAT Rates', 'invoicing' ) . '" /> <i style="display:none" class="fa fa-refresh fa-spin"></i></span>'; |
|
454
|
|
|
$html .= '<p><label for="wpinv_settings_' . $args['section'] . '_' . $args['id'] . '">' . $args['desc'] . '</label></p>'; |
|
455
|
|
|
echo $html; |
|
456
|
|
|
?> |
|
457
|
|
|
<span id="wpinv-rates-error-wrap" class="wpinv_errors" style="display:none;"></span> |
|
458
|
|
|
<?php |
|
459
|
|
|
} |
|
460
|
|
|
|
|
461
|
|
|
function wpinv_vat_ip_lookup_callback( $args ) { |
|
462
|
|
|
global $wpinv_options, $wpinv_euvat; |
|
463
|
|
|
|
|
464
|
|
|
$value = isset( $wpinv_options[ $args['id'] ] ) ? $wpinv_options[ $args['id'] ] : ( isset( $args['std'] ) ? $args['std'] : 'default' ); |
|
465
|
|
|
|
|
466
|
|
|
$options = array(); |
|
467
|
|
|
if ( function_exists( 'geoip_country_code_by_name' ) ) { |
|
468
|
|
|
$options['geoip'] = __( 'PHP GeoIP extension', 'invoicing' ); |
|
469
|
|
|
} |
|
470
|
|
|
|
|
471
|
|
|
$geoip2_database = $wpinv_euvat->geoip2_country_dbfile(); |
|
472
|
|
|
|
|
473
|
|
|
if ( !function_exists( 'bcadd' ) ) { |
|
474
|
|
|
$geoip2_message = __( 'GeoIP2 service requires the BC Math PHP extension, it is not loaded in your version of PHP!', 'invoicing' ); |
|
475
|
|
|
} else { |
|
476
|
|
|
$geoip2_message = ini_get('safe_mode') ? __( 'GeoIP2 is not supported with PHP safe mode enabled!', 'invoicing' ) : ''; |
|
477
|
|
|
} |
|
478
|
|
|
|
|
479
|
|
|
if ( $geoip2_database !== false && empty( $geoip2_message ) ) { |
|
480
|
|
|
$options['geoip2'] = __( 'GeoIP2 Database', 'invoicing' ); |
|
481
|
|
|
} |
|
482
|
|
|
|
|
483
|
|
|
if ( function_exists( 'simplexml_load_file' ) ) { |
|
484
|
|
|
$options['geoplugin'] = __( 'geoPlugin Web Service', 'invoicing' ); |
|
485
|
|
|
} |
|
486
|
|
|
|
|
487
|
|
|
$options['site'] = __( 'Use default country', 'invoicing' ); |
|
488
|
|
|
$options['default'] = __( 'Auto', 'invoicing' ); |
|
489
|
|
|
|
|
490
|
|
|
$html = wpinv_html_select( array( |
|
491
|
|
|
'name' => "wpinv_settings[{$args['id']}]", |
|
492
|
|
|
'selected' => $value, |
|
493
|
|
|
'id' => "wpinv_settings[{$args['id']}]", |
|
494
|
|
|
'class' => isset($args['class']) ? $args['class'] : "", |
|
495
|
|
|
'options' => $options, |
|
496
|
|
|
'multiple' => false, |
|
497
|
|
|
'show_option_all' => false, |
|
498
|
|
|
'show_option_none' => false |
|
499
|
|
|
)); |
|
500
|
|
|
|
|
501
|
|
|
$desc = '<label for="wpinv_settings[' . $args['id'] . ']">'; |
|
502
|
|
|
$desc .= __( 'Select the option Invoicing should use to determine the country from the IP address of the user.', 'invoicing' ); |
|
503
|
|
|
$desc .= '<p>'; |
|
504
|
|
|
if ( empty( $geoip2_message ) ) { |
|
505
|
|
|
if ( $geoip2_database ) { |
|
506
|
|
|
$last_updated = ''; |
|
507
|
|
|
if ( $time_updated = wpinv_get_option( 'wpinv_geoip2_date_updated' ) ) { |
|
508
|
|
|
$date_updated = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $time_updated ); |
|
|
|
|
|
|
509
|
|
|
$last_updated = '<br>' . sprintf( __( 'The GeoIP2 database was last updated on: <b>%s</b>', 'invoicing' ), $date_updated ); |
|
510
|
|
|
} |
|
511
|
|
|
$desc .= __( 'GeoIP2 database exists:', 'invoicing' ) . $last_updated . ' <input type="button" id="wpi_geoip2" action="update" class="wpinv-refresh-geoip2-btn button-secondary" value="' . __( 'Update GeoIP2 database now (~30MB)', 'invoicing' ) . '"></input>'; |
|
512
|
|
|
} else { |
|
513
|
|
|
$desc .= __( 'GeoIP2 database does not exist:', 'invoicing' ) . ' <input type="button" id="wpi_geoip2" action="download" class="wpinv-download-geoip2-btn button-secondary" value="' . __( 'Download GeoIP2 database now', 'invoicing' ) . ' (~30MB)"></input><br>' . __( 'After downloading the GeoIP2 database the GeoIP2 lookup option will show.', 'invoicing' ); |
|
514
|
|
|
} |
|
515
|
|
|
} else { |
|
516
|
|
|
$desc .= $geoip2_message; |
|
517
|
|
|
} |
|
518
|
|
|
$desc .= '</p><p>'. __( 'geoPlugin is a great free service please consider supporting them: ', 'invoicing' ) . ' <a href="http://www.geoplugin.com/" target="_blank">GeoPlugin.com</a></p>'; |
|
519
|
|
|
$desc .= '</label>'; |
|
520
|
|
|
|
|
521
|
|
|
$html .= $desc; |
|
522
|
|
|
|
|
523
|
|
|
echo $html; |
|
524
|
|
|
?> |
|
525
|
|
|
<span id="wpinv-geoip2-errors" class="wpinv_errors" style="display:none;padding:4px;"></span> |
|
526
|
|
|
<?php |
|
527
|
|
|
} |
|
528
|
|
|
|
|
529
|
|
|
/** |
|
530
|
|
|
* Filters the VAT rules to ensure that each item has a VAT rule. |
|
531
|
|
|
* |
|
532
|
|
|
* @param string|bool|null $vat_rule |
|
533
|
|
|
*/ |
|
534
|
|
|
function getpaid_filter_vat_rule( $vat_rule ) { |
|
535
|
|
|
global $wpinv_euvat; |
|
536
|
|
|
|
|
537
|
|
|
if ( empty( $vat_rule ) ) { |
|
538
|
|
|
return $wpinv_euvat->allow_vat_rules() ? 'digital' : 'physical'; |
|
539
|
|
|
} |
|
540
|
|
|
|
|
541
|
|
|
return $vat_rule; |
|
542
|
|
|
} |
|
543
|
|
|
add_filter( 'wpinv_get_item_vat_rule', 'getpaid_filter_vat_rule' ); |
|
544
|
|
|
|
|
545
|
|
|
/** |
|
546
|
|
|
* Filters the VAT class to ensure that each item has a VAT class. |
|
547
|
|
|
* |
|
548
|
|
|
* @param string|bool|null $vat_rule |
|
549
|
|
|
*/ |
|
550
|
|
|
function getpaid_filter_vat_class( $vat_class ) { |
|
551
|
|
|
return empty( $vat_class ) ? '_standard' : $vat_class; |
|
552
|
|
|
} |
|
553
|
|
|
add_filter( 'wpinv_get_item_vat_class', 'getpaid_filter_vat_class' ); |
|
554
|
|
|
|
|
555
|
|
|
/** |
|
556
|
|
|
* Returns the ip address location url. |
|
557
|
|
|
* |
|
558
|
|
|
*/ |
|
559
|
|
|
function getpaid_ip_location_url( $ip_address ) { |
|
560
|
|
|
|
|
561
|
|
|
return add_query_arg( |
|
562
|
|
|
array( |
|
563
|
|
|
'action' => 'wpinv_ip_geolocation', |
|
564
|
|
|
'ip' => $ip_address, |
|
565
|
|
|
'_wpnonce' => wp_create_nonce( 'getpaid-ip-location' ) |
|
566
|
|
|
), |
|
567
|
|
|
admin_url( 'admin-ajax.php' ) |
|
568
|
|
|
); |
|
569
|
|
|
|
|
570
|
|
|
} |
|
571
|
|
|
|
|
572
|
|
|
/** |
|
573
|
|
|
* GeoLocates an ip address. |
|
574
|
|
|
* |
|
575
|
|
|
* @return array|bool |
|
576
|
|
|
*/ |
|
577
|
|
|
function getpaid_geolocate_ip_address( $ip_address ) { |
|
578
|
|
|
|
|
579
|
|
|
// Do we have an ip address? |
|
580
|
|
|
if ( empty( $ip_address ) ) { |
|
581
|
|
|
return false; |
|
582
|
|
|
} |
|
583
|
|
|
|
|
584
|
|
|
/** |
|
585
|
|
|
* Retrieve ip address using max mind. |
|
586
|
|
|
*/ |
|
587
|
|
|
if ( wpinv_get_option( 'vat_ip_lookup' ) == 'geoip2' && $geoip2_city = getpaid_tax()->geoip2_city_record( $ip_address ) ) { |
|
588
|
|
|
|
|
589
|
|
|
try { |
|
590
|
|
|
$iso = $geoip2_city->country->isoCode; |
|
591
|
|
|
$country = $geoip2_city->country->name; |
|
592
|
|
|
$region = ! empty( $geoip2_city->subdivisions ) && ! empty( $geoip2_city->subdivisions[0]->name ) ? $geoip2_city->subdivisions[0]->name : ''; |
|
593
|
|
|
$city = $geoip2_city->city->name; |
|
594
|
|
|
$longitude = $geoip2_city->location->longitude; |
|
595
|
|
|
$latitude = $geoip2_city->location->latitude; |
|
596
|
|
|
$credit = __( 'Geolocated using the information by MaxMind, available from <a href="http://www.maxmind.com" target="_blank">www.maxmind.com</a>', 'invoicing' ); |
|
597
|
|
|
} catch( Exception $e ) { } |
|
|
|
|
|
|
598
|
|
|
|
|
599
|
|
|
} |
|
600
|
|
|
|
|
601
|
|
|
// If that fails, GeoLocate using GeoPlugin. |
|
602
|
|
|
if ( ( empty( $iso ) || empty( $longitude ) || empty( $latitude ) ) && function_exists( 'simplexml_load_file' ) ) { |
|
603
|
|
|
|
|
604
|
|
|
try { |
|
605
|
|
|
$load_xml = simplexml_load_file( 'http://www.geoplugin.net/xml.gp?ip=' . $ip_address ); |
|
|
|
|
|
|
606
|
|
|
|
|
607
|
|
|
if ( ! empty( $load_xml ) && isset( $load_xml->geoplugin_countryCode ) && ! empty( $load_xml->geoplugin_latitude ) && ! empty( $load_xml->geoplugin_longitude ) ) { |
|
608
|
|
|
$iso = $load_xml->geoplugin_countryCode; |
|
609
|
|
|
$country = $load_xml->geoplugin_countryName; |
|
610
|
|
|
$region = ! empty( $load_xml->geoplugin_regionName ) ? $load_xml->geoplugin_regionName : ''; |
|
611
|
|
|
$city = ! empty( $load_xml->geoplugin_city ) ? $load_xml->geoplugin_city : ''; |
|
612
|
|
|
$longitude = $load_xml->geoplugin_longitude; |
|
613
|
|
|
$latitude = $load_xml->geoplugin_latitude; |
|
614
|
|
|
$credit = $load_xml->geoplugin_credit; |
|
|
|
|
|
|
615
|
|
|
$credit = __( 'Geolocated using the information by geoPlugin, available from <a href="http://www.geoplugin.com" target="_blank">www.geoplugin.com</a>', 'invoicing' ) . '<br>' . $load_xml->geoplugin_credit; |
|
616
|
|
|
} |
|
617
|
|
|
} catch( Exception $e ) { } |
|
|
|
|
|
|
618
|
|
|
|
|
619
|
|
|
} |
|
620
|
|
|
|
|
621
|
|
|
if ( empty( $iso ) ) { |
|
622
|
|
|
return false; |
|
623
|
|
|
} |
|
624
|
|
|
|
|
625
|
|
|
return compact( 'iso', 'country', 'region', 'city', 'longitude', 'latitude', 'credit' ); |
|
626
|
|
|
|
|
627
|
|
|
} |
|
628
|
|
|
|
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return,dieorexitstatements that have been added for debug purposes.In the above example, the last
return falsewill never be executed, because a return statement has already been met in every possible execution path.