Passed
Pull Request — master (#153)
by Kiran
04:16
created

wpinv-helper-functions.php ➔ wpinv_get_invoice_statuses()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 16
nc 4
nop 3
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0
1
<?php
2
/**
3
 * Contains functions related to Invoicing plugin.
4
 *
5
 * @since 1.0.0
6
 * @package Invoicing
7
 */
8
9
// MUST have WordPress.
10
if ( !defined( 'WPINC' ) ) {
11
    exit( 'Do NOT access this file directly: ' . basename( __FILE__ ) );
12
}
13
14
function wpinv_item_quantities_enabled() {
15
    $ret = wpinv_get_option( 'item_quantities', true );
16
17
    return (bool) apply_filters( 'wpinv_item_quantities_enabled', $ret );
18
}
19
20
function wpinv_get_ip() {
21
    $ip = '127.0.0.1';
22
23
    if ( !empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
24
        $ip = sanitize_text_field( $_SERVER['HTTP_CLIENT_IP'] );
25
    } elseif ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
26
        $ip = sanitize_text_field( $_SERVER['HTTP_X_FORWARDED_FOR'] );
27
    } elseif( !empty( $_SERVER['REMOTE_ADDR'] ) ) {
28
        $ip = sanitize_text_field( $_SERVER['REMOTE_ADDR'] );
29
    }
30
31
    return apply_filters( 'wpinv_get_ip', $ip );
32
}
33
34
function wpinv_get_user_agent() {
35
    if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
36
        $user_agent = sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] );
37
    } else {
38
        $user_agent = '';
39
    }
40
41
    return apply_filters( 'wpinv_get_user_agent', $user_agent );
42
}
43
44
function wpinv_sanitize_amount( $amount, $decimals = NULL ) {
45
    $is_negative   = false;
46
    $thousands_sep = wpinv_thousands_separator();
47
    $decimal_sep   = wpinv_decimal_separator();
48
    if ( $decimals === NULL ) {
49
        $decimals = wpinv_decimals();
50
    }
51
52
    // Sanitize the amount
53
    if ( $decimal_sep == ',' && false !== ( $found = strpos( $amount, $decimal_sep ) ) ) {
54
        if ( ( $thousands_sep == '.' || $thousands_sep == ' ' ) && false !== ( $found = strpos( $amount, $thousands_sep ) ) ) {
55
            $amount = str_replace( $thousands_sep, '', $amount );
56 View Code Duplication
        } elseif( empty( $thousands_sep ) && false !== ( $found = strpos( $amount, '.' ) ) ) {
57
            $amount = str_replace( '.', '', $amount );
58
        }
59
60
        $amount = str_replace( $decimal_sep, '.', $amount );
61 View Code Duplication
    } elseif( $thousands_sep == ',' && false !== ( $found = strpos( $amount, $thousands_sep ) ) ) {
62
        $amount = str_replace( $thousands_sep, '', $amount );
63
    }
64
65
    if( $amount < 0 ) {
66
        $is_negative = true;
67
    }
68
69
    $amount   = preg_replace( '/[^0-9\.]/', '', $amount );
70
71
    $decimals = apply_filters( 'wpinv_sanitize_amount_decimals', absint( $decimals ), $amount );
72
    $amount   = number_format( (double) $amount, absint( $decimals ), '.', '' );
73
74
    if( $is_negative ) {
75
        $amount *= -1;
76
    }
77
78
    return apply_filters( 'wpinv_sanitize_amount', $amount, $decimals );
79
}
80
add_filter( 'wpinv_sanitize_amount_decimals', 'wpinv_currency_decimal_filter', 10, 1 );
81
82
function wpinv_round_amount( $amount, $decimals = NULL ) {
83
    if ( $decimals === NULL ) {
84
        $decimals = wpinv_decimals();
85
    }
86
    
87
    $amount = round( (double)$amount, wpinv_currency_decimal_filter( absint( $decimals ) ) );
88
89
    return apply_filters( 'wpinv_round_amount', $amount, $decimals );
90
}
91
92
function wpinv_get_invoice_statuses( $draft = false, $trashed = false, $invoice = false ) {
93
    global $post;
94
95
    $invoice_statuses = array(
96
        'wpi-pending' => __( 'Pending Payment', 'invoicing' ),
97
        'publish' => __( 'Paid', 'invoicing'),
98
        'wpi-processing' => __( 'Processing', 'invoicing' ),
99
        'wpi-onhold' => __( 'On Hold', 'invoicing' ),
100
        'wpi-refunded' => __( 'Refunded', 'invoicing' ),
101
        'wpi-cancelled' => __( 'Cancelled', 'invoicing' ),
102
        'wpi-failed' => __( 'Failed', 'invoicing' ),
103
        'wpi-renewal' => __( 'Renewal Payment', 'invoicing' )
104
    );
105
106
    if ( $draft ) {
107
        $invoice_statuses['draft'] = __( 'Draft', 'invoicing' );
108
    }
109
110
    if ( $trashed ) {
111
        $invoice_statuses['trash'] = __( 'Trash', 'invoicing' );
112
    }
113
114
    return apply_filters( 'wpinv_statuses', $invoice_statuses, $invoice );
115
}
116
117
function wpinv_status_nicename( $status ) {
118
    $statuses = wpinv_get_invoice_statuses( true, true );
119
    $status   = isset( $statuses[$status] ) ? $statuses[$status] : __( $status, 'invoicing' );
120
121
    return $status;
122
}
123
124
function wpinv_get_currency() {
125
    $currency = wpinv_get_option( 'currency', 'USD' );
0 ignored issues
show
Documentation introduced by
'USD' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
126
    
127
    return apply_filters( 'wpinv_currency', $currency );
128
}
129
130
function wpinv_currency_symbol( $currency = '' ) {
131
    if ( empty( $currency ) ) {
132
        $currency = wpinv_get_currency();
133
    }
134
    
135
    $symbols = apply_filters( 'wpinv_currency_symbols', array(
136
        'AED' => '&#x62f;.&#x625;',
137
        'AFN' => '&#x60b;',
138
        'ALL' => 'L',
139
        'AMD' => 'AMD',
140
        'ANG' => '&fnof;',
141
        'AOA' => 'Kz',
142
        'ARS' => '&#36;',
143
        'AUD' => '&#36;',
144
        'AWG' => '&fnof;',
145
        'AZN' => 'AZN',
146
        'BAM' => 'KM',
147
        'BBD' => '&#36;',
148
        'BDT' => '&#2547;',
149
        'BGN' => '&#1083;&#1074;.',
150
        'BHD' => '.&#x62f;.&#x628;',
151
        'BIF' => 'Fr',
152
        'BMD' => '&#36;',
153
        'BND' => '&#36;',
154
        'BOB' => 'Bs.',
155
        'BRL' => '&#82;&#36;',
156
        'BSD' => '&#36;',
157
        'BTC' => '&#3647;',
158
        'BTN' => 'Nu.',
159
        'BWP' => 'P',
160
        'BYN' => 'Br',
161
        'BZD' => '&#36;',
162
        'CAD' => '&#36;',
163
        'CDF' => 'Fr',
164
        'CHF' => '&#67;&#72;&#70;',
165
        'CLP' => '&#36;',
166
        'CNY' => '&yen;',
167
        'COP' => '&#36;',
168
        'CRC' => '&#x20a1;',
169
        'CUC' => '&#36;',
170
        'CUP' => '&#36;',
171
        'CVE' => '&#36;',
172
        'CZK' => '&#75;&#269;',
173
        'DJF' => 'Fr',
174
        'DKK' => 'DKK',
175
        'DOP' => 'RD&#36;',
176
        'DZD' => '&#x62f;.&#x62c;',
177
        'EGP' => 'EGP',
178
        'ERN' => 'Nfk',
179
        'ETB' => 'Br',
180
        'EUR' => '&euro;',
181
        'FJD' => '&#36;',
182
        'FKP' => '&pound;',
183
        'GBP' => '&pound;',
184
        'GEL' => '&#x10da;',
185
        'GGP' => '&pound;',
186
        'GHS' => '&#x20b5;',
187
        'GIP' => '&pound;',
188
        'GMD' => 'D',
189
        'GNF' => 'Fr',
190
        'GTQ' => 'Q',
191
        'GYD' => '&#36;',
192
        'HKD' => '&#36;',
193
        'HNL' => 'L',
194
        'HRK' => 'Kn',
195
        'HTG' => 'G',
196
        'HUF' => '&#70;&#116;',
197
        'IDR' => 'Rp',
198
        'ILS' => '&#8362;',
199
        'IMP' => '&pound;',
200
        'INR' => '&#8377;',
201
        'IQD' => '&#x639;.&#x62f;',
202
        'IRR' => '&#xfdfc;',
203
        'IRT' => '&#x062A;&#x0648;&#x0645;&#x0627;&#x0646;',
204
        'ISK' => 'kr.',
205
        'JEP' => '&pound;',
206
        'JMD' => '&#36;',
207
        'JOD' => '&#x62f;.&#x627;',
208
        'JPY' => '&yen;',
209
        'KES' => 'KSh',
210
        'KGS' => '&#x441;&#x43e;&#x43c;',
211
        'KHR' => '&#x17db;',
212
        'KMF' => 'Fr',
213
        'KPW' => '&#x20a9;',
214
        'KRW' => '&#8361;',
215
        'KWD' => '&#x62f;.&#x643;',
216
        'KYD' => '&#36;',
217
        'KZT' => 'KZT',
218
        'LAK' => '&#8365;',
219
        'LBP' => '&#x644;.&#x644;',
220
        'LKR' => '&#xdbb;&#xdd4;',
221
        'LRD' => '&#36;',
222
        'LSL' => 'L',
223
        'LYD' => '&#x644;.&#x62f;',
224
        'MAD' => '&#x62f;.&#x645;.',
225
        'MDL' => 'MDL',
226
        'MGA' => 'Ar',
227
        'MKD' => '&#x434;&#x435;&#x43d;',
228
        'MMK' => 'Ks',
229
        'MNT' => '&#x20ae;',
230
        'MOP' => 'P',
231
        'MRO' => 'UM',
232
        'MUR' => '&#x20a8;',
233
        'MVR' => '.&#x783;',
234
        'MWK' => 'MK',
235
        'MXN' => '&#36;',
236
        'MYR' => '&#82;&#77;',
237
        'MZN' => 'MT',
238
        'NAD' => '&#36;',
239
        'NGN' => '&#8358;',
240
        'NIO' => 'C&#36;',
241
        'NOK' => '&#107;&#114;',
242
        'NPR' => '&#8360;',
243
        'NZD' => '&#36;',
244
        'OMR' => '&#x631;.&#x639;.',
245
        'PAB' => 'B/.',
246
        'PEN' => 'S/.',
247
        'PGK' => 'K',
248
        'PHP' => '&#8369;',
249
        'PKR' => '&#8360;',
250
        'PLN' => '&#122;&#322;',
251
        'PRB' => '&#x440;.',
252
        'PYG' => '&#8370;',
253
        'QAR' => '&#x631;.&#x642;',
254
        'RMB' => '&yen;',
255
        'RON' => 'lei',
256
        'RSD' => '&#x434;&#x438;&#x43d;.',
257
        'RUB' => '&#8381;',
258
        'RWF' => 'Fr',
259
        'SAR' => '&#x631;.&#x633;',
260
        'SBD' => '&#36;',
261
        'SCR' => '&#x20a8;',
262
        'SDG' => '&#x62c;.&#x633;.',
263
        'SEK' => '&#107;&#114;',
264
        'SGD' => '&#36;',
265
        'SHP' => '&pound;',
266
        'SLL' => 'Le',
267
        'SOS' => 'Sh',
268
        'SRD' => '&#36;',
269
        'SSP' => '&pound;',
270
        'STD' => 'Db',
271
        'SYP' => '&#x644;.&#x633;',
272
        'SZL' => 'L',
273
        'THB' => '&#3647;',
274
        'TJS' => '&#x405;&#x41c;',
275
        'TMT' => 'm',
276
        'TND' => '&#x62f;.&#x62a;',
277
        'TOP' => 'T&#36;',
278
        'TRY' => '&#8378;',
279
        'TTD' => '&#36;',
280
        'TWD' => '&#78;&#84;&#36;',
281
        'TZS' => 'Sh',
282
        'UAH' => '&#8372;',
283
        'UGX' => 'UGX',
284
        'USD' => '&#36;',
285
        'UYU' => '&#36;',
286
        'UZS' => 'UZS',
287
        'VEF' => 'Bs.',
288
        'VND' => '&#8363;',
289
        'VUV' => 'Vt',
290
        'WST' => 'T',
291
        'XAF' => 'Fr',
292
        'XCD' => '&#36;',
293
        'XOF' => 'Fr',
294
        'XPF' => 'Fr',
295
        'YER' => '&#xfdfc;',
296
        'ZAR' => '&#82;',
297
        'ZMW' => 'ZK',
298
    ) );
299
300
    $currency_symbol = isset( $symbols[$currency] ) ? $symbols[$currency] : $currency;
301
302
    return apply_filters( 'wpinv_currency_symbol', $currency_symbol, $currency );
303
}
304
305
function wpinv_currency_position() {
306
    $position = wpinv_get_option( 'currency_position', 'left' );
0 ignored issues
show
Documentation introduced by
'left' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
307
    
308
    return apply_filters( 'wpinv_currency_position', $position );
309
}
310
311
function wpinv_thousands_separator() {
312
    $thousand_sep = wpinv_get_option( 'thousands_separator', ',' );
0 ignored issues
show
Documentation introduced by
',' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
313
    
314
    return apply_filters( 'wpinv_thousands_separator', $thousand_sep );
315
}
316
317
function wpinv_decimal_separator() {
318
    $decimal_sep = wpinv_get_option( 'decimal_separator', '.' );
0 ignored issues
show
Documentation introduced by
'.' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
319
    
320
    return apply_filters( 'wpinv_decimal_separator', $decimal_sep );
321
}
322
323
function wpinv_decimals() {
324
    $decimals = apply_filters( 'wpinv_decimals', wpinv_get_option( 'decimals', 2 ) );
0 ignored issues
show
Documentation introduced by
2 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
325
    
326
    return absint( $decimals );
327
}
328
329
function wpinv_get_currencies() {
330
    $currencies = array(
331
        'USD' => __( 'US Dollar', 'invoicing' ),
332
        'EUR' => __( 'Euro', 'invoicing' ),
333
        'GBP' => __( 'Pound Sterling', 'invoicing' ),
334
        'AFN' => __( 'Afghan Afghani', 'invoicing' ),
335
        'ALL' => __( 'Albanian Lek', 'invoicing' ),
336
        'AMD' => __( 'Armenian Dram', 'invoicing' ),
337
        'ANG' => __( 'Netherlands Antillean Guilder', 'invoicing' ),
338
        'AOA' => __( 'Angolan Kwanza', 'invoicing' ),
339
        'ARS' => __( 'Argentine Peso', 'invoicing' ),
340
        'AUD' => __( 'Australian Dollar', 'invoicing' ),
341
        'AWG' => __( 'Aruban Florin', 'invoicing' ),
342
        'AZN' => __( 'Azerbaijani Manat', 'invoicing' ),
343
        'BAM' => __( 'Bosnia and Herzegovina Convertible Marka', 'invoicing' ),
344
        'BBD' => __( 'Barbadian Dollar', 'invoicing' ),
345
        'BDT' => __( 'Bangladeshi Taka', 'invoicing' ),
346
        'BGN' => __( 'Bulgarian Lev', 'invoicing' ),
347
        'BHD' => __( 'Bahraini Dinar', 'invoicing' ),
348
        'BIF' => __( 'Burundian Franc', 'invoicing' ),
349
        'BMD' => __( 'Bermudian Dollar', 'invoicing' ),
350
        'BND' => __( 'Brunei Dollar', 'invoicing' ),
351
        'BOB' => __( 'Bolivian Boliviano', 'invoicing' ),
352
        'BRL' => __( 'Brazilian Real', 'invoicing' ),
353
        'BSD' => __( 'Bahamian Dollar', 'invoicing' ),
354
        'BTC' => __( 'Bitcoin', 'invoicing' ),
355
        'BTN' => __( 'Bhutanese Ngultrum', 'invoicing' ),
356
        'BWP' => __( 'Botswana Pula', 'invoicing' ),
357
        'BYN' => __( 'Belarusian Ruble', 'invoicing' ),
358
        'BZD' => __( 'Belize Dollar', 'invoicing' ),
359
        'CAD' => __( 'Canadian Dollar', 'invoicing' ),
360
        'CDF' => __( 'Congolese Franc', 'invoicing' ),
361
        'CHF' => __( 'Swiss Franc', 'invoicing' ),
362
        'CLP' => __( 'Chilean Peso', 'invoicing' ),
363
        'CNY' => __( 'Chinese Yuan', 'invoicing' ),
364
        'COP' => __( 'Colombian Peso', 'invoicing' ),
365
        'CRC' => __( 'Costa Rican Colon', 'invoicing' ),
366
        'CUC' => __( 'Cuban Convertible Peso', 'invoicing' ),
367
        'CUP' => __( 'Cuban Peso', 'invoicing' ),
368
        'CVE' => __( 'Cape Verdean escudo', 'invoicing' ),
369
        'CZK' => __( 'Czech Koruna', 'invoicing' ),
370
        'DJF' => __( 'Djiboutian Franc', 'invoicing' ),
371
        'DKK' => __( 'Danish Krone', 'invoicing' ),
372
        'DOP' => __( 'Dominican Peso', 'invoicing' ),
373
        'DZD' => __( 'Algerian Dinar', 'invoicing' ),
374
        'EGP' => __( 'Egyptian Pound', 'invoicing' ),
375
        'ERN' => __( 'Eritrean Nakfa', 'invoicing' ),
376
        'ETB' => __( 'Ethiopian irr', 'invoicing' ),
377
        'FJD' => __( 'Fijian Dollar', 'invoicing' ),
378
        'FKP' => __( 'Falkland Islands Pound', 'invoicing' ),
379
        'GEL' => __( 'Georgian lari', 'invoicing' ),
380
        'GGP' => __( 'Guernsey Pound', 'invoicing' ),
381
        'GHS' => __( 'Ghana cedi', 'invoicing' ),
382
        'GIP' => __( 'Gibraltar Pound', 'invoicing' ),
383
        'GMD' => __( 'Gambian Dalasi', 'invoicing' ),
384
        'GNF' => __( 'Guinean Franc', 'invoicing' ),
385
        'GTQ' => __( 'Guatemalan Quetzal', 'invoicing' ),
386
        'GYD' => __( 'Guyanese Dollar', 'invoicing' ),
387
        'HKD' => __( 'Hong Kong Dollar', 'invoicing' ),
388
        'HNL' => __( 'Honduran Lempira', 'invoicing' ),
389
        'HRK' => __( 'Croatian Kuna', 'invoicing' ),
390
        'HTG' => __( 'Haitian Gourde', 'invoicing' ),
391
        'HUF' => __( 'Hungarian Forint', 'invoicing' ),
392
        'IDR' => __( 'Indonesian Rupiah', 'invoicing' ),
393
        'ILS' => __( 'Israeli New Shekel', 'invoicing' ),
394
        'IMP' => __( 'Manx Pound', 'invoicing' ),
395
        'INR' => __( 'Indian Rupee', 'invoicing' ),
396
        'IQD' => __( 'Iraqi Dinar', 'invoicing' ),
397
        'IRR' => __( 'Iranian Rial', 'invoicing' ),
398
        'IRT' => __( 'Iranian Toman', 'invoicing' ),
399
        'ISK' => __( 'Icelandic Krona', 'invoicing' ),
400
        'JEP' => __( 'Jersey Pound', 'invoicing' ),
401
        'JMD' => __( 'Jamaican Dollar', 'invoicing' ),
402
        'JOD' => __( 'Jordanian Dinar', 'invoicing' ),
403
        'JPY' => __( 'Japanese Yen', 'invoicing' ),
404
        'KES' => __( 'Kenyan Shilling', 'invoicing' ),
405
        'KGS' => __( 'Kyrgyzstani Som', 'invoicing' ),
406
        'KHR' => __( 'Cambodian Riel', 'invoicing' ),
407
        'KMF' => __( 'Comorian Franc', 'invoicing' ),
408
        'KPW' => __( 'North Korean Won', 'invoicing' ),
409
        'KRW' => __( 'South Korean Won', 'invoicing' ),
410
        'KWD' => __( 'Kuwaiti Dinar', 'invoicing' ),
411
        'KYD' => __( 'Cayman Islands Dollar', 'invoicing' ),
412
        'KZT' => __( 'Kazakhstani Tenge', 'invoicing' ),
413
        'LAK' => __( 'Lao Kip', 'invoicing' ),
414
        'LBP' => __( 'Lebanese Pound', 'invoicing' ),
415
        'LKR' => __( 'Sri Lankan Rupee', 'invoicing' ),
416
        'LRD' => __( 'Liberian Dollar', 'invoicing' ),
417
        'LSL' => __( 'Lesotho Loti', 'invoicing' ),
418
        'LYD' => __( 'Libyan Dinar', 'invoicing' ),
419
        'MAD' => __( 'Moroccan Dirham', 'invoicing' ),
420
        'MDL' => __( 'Moldovan Leu', 'invoicing' ),
421
        'MGA' => __( 'Malagasy Ariary', 'invoicing' ),
422
        'MKD' => __( 'Macedonian Denar', 'invoicing' ),
423
        'MMK' => __( 'Burmese Kyat', 'invoicing' ),
424
        'MNT' => __( 'Mongolian Tughrik', 'invoicing' ),
425
        'MOP' => __( 'Macanese Pataca', 'invoicing' ),
426
        'MRO' => __( 'Mauritanian Ouguiya', 'invoicing' ),
427
        'MUR' => __( 'Mauritian Rupee', 'invoicing' ),
428
        'MVR' => __( 'Maldivian Rufiyaa', 'invoicing' ),
429
        'MWK' => __( 'Malawian Kwacha', 'invoicing' ),
430
        'MXN' => __( 'Mexican Peso', 'invoicing' ),
431
        'MYR' => __( 'Malaysian Ringgit', 'invoicing' ),
432
        'MZN' => __( 'Mozambican Metical', 'invoicing' ),
433
        'NAD' => __( 'Namibian Dollar', 'invoicing' ),
434
        'NGN' => __( 'Nigerian Naira', 'invoicing' ),
435
        'NIO' => __( 'Nicaraguan Cordoba', 'invoicing' ),
436
        'NOK' => __( 'Norwegian Krone', 'invoicing' ),
437
        'NPR' => __( 'Nepalese Rupee', 'invoicing' ),
438
        'NZD' => __( 'New Zealand Dollar', 'invoicing' ),
439
        'OMR' => __( 'Omani Rial', 'invoicing' ),
440
        'PAB' => __( 'Panamanian Balboa', 'invoicing' ),
441
        'PEN' => __( 'Peruvian Nuevo Sol', 'invoicing' ),
442
        'PGK' => __( 'Papua New Guinean Kina', 'invoicing' ),
443
        'PHP' => __( 'Philippine Peso', 'invoicing' ),
444
        'PKR' => __( 'Pakistani Rupee', 'invoicing' ),
445
        'PLN' => __( 'Polish Zloty', 'invoicing' ),
446
        'PRB' => __( 'Transnistrian Ruble', 'invoicing' ),
447
        'PYG' => __( 'Paraguayan Guarani', 'invoicing' ),
448
        'QAR' => __( 'Qatari Riyal', 'invoicing' ),
449
        'RON' => __( 'Romanian Leu', 'invoicing' ),
450
        'RSD' => __( 'Serbian Dinar', 'invoicing' ),
451
        'RUB' => __( 'Russian Ruble', 'invoicing' ),
452
        'RWF' => __( 'Rwandan Franc', 'invoicing' ),
453
        'SAR' => __( 'Saudi Riyal', 'invoicing' ),
454
        'SBD' => __( 'Solomon Islands Dollar', 'invoicing' ),
455
        'SCR' => __( 'Seychellois Rupee', 'invoicing' ),
456
        'SDG' => __( 'Sudanese Pound', 'invoicing' ),
457
        'SEK' => __( 'Swedish Krona', 'invoicing' ),
458
        'SGD' => __( 'Singapore Dollar', 'invoicing' ),
459
        'SHP' => __( 'Saint Helena Pound', 'invoicing' ),
460
        'SLL' => __( 'Sierra Leonean Leone', 'invoicing' ),
461
        'SOS' => __( 'Somali Shilling', 'invoicing' ),
462
        'SRD' => __( 'Surinamese Dollar', 'invoicing' ),
463
        'SSP' => __( 'South Sudanese Pound', 'invoicing' ),
464
        'STD' => __( 'Sao Tomean Dobra', 'invoicing' ),
465
        'SYP' => __( 'Syrian Pound', 'invoicing' ),
466
        'SZL' => __( 'Swazi Lilangeni', 'invoicing' ),
467
        'THB' => __( 'Thai Baht', 'invoicing' ),
468
        'TJS' => __( 'Tajikistani Somoni', 'invoicing' ),
469
        'TMT' => __( 'Turkmenistan Manat', 'invoicing' ),
470
        'TND' => __( 'Tunisian Dinar', 'invoicing' ),
471
        'TOP' => __( 'Tongan Pa&#x2bb;anga', 'invoicing' ),
472
        'TRY' => __( 'Turkish Lira', 'invoicing' ),
473
        'TTD' => __( 'Trinidad and Tobago Dollar', 'invoicing' ),
474
        'TWD' => __( 'New Taiwan Dollar', 'invoicing' ),
475
        'TZS' => __( 'Tanzanian Shilling', 'invoicing' ),
476
        'UAH' => __( 'Ukrainian Hryvnia', 'invoicing' ),
477
        'UGX' => __( 'Ugandan Shilling', 'invoicing' ),
478
        'UYU' => __( 'Uruguayan Peso', 'invoicing' ),
479
        'UZS' => __( 'Uzbekistani Som', 'invoicing' ),
480
        'VEF' => __( 'Venezuelan Bol&iacute;var', 'invoicing' ),
481
        'VND' => __( 'Vietnamese Dong', 'invoicing' ),
482
        'VUV' => __( 'Vanuatu Vatu', 'invoicing' ),
483
        'WST' => __( 'Samoan Tala', 'invoicing' ),
484
        'XAF' => __( 'Central African CFA Franc', 'invoicing' ),
485
        'XCD' => __( 'East Caribbean Dollar', 'invoicing' ),
486
        'XOF' => __( 'West African CFA Franc', 'invoicing' ),
487
        'XPF' => __( 'CFP Franc', 'invoicing' ),
488
        'YER' => __( 'Yemeni Rial', 'invoicing' ),
489
        'ZAR' => __( 'South African Rand', 'invoicing' ),
490
        'ZMW' => __( 'Zambian Kwacha', 'invoicing' ),
491
    );
492
    
493
    //asort( $currencies ); // this
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
494
495
    return apply_filters( 'wpinv_currencies', $currencies );
496
}
497
498
function wpinv_price( $amount = '', $currency = '' ) {
499
    if( empty( $currency ) ) {
500
        $currency = wpinv_get_currency();
501
    }
502
503
    $position = wpinv_currency_position();
504
505
    $negative = $amount < 0;
506
507
    if ( $negative ) {
508
        $amount = substr( $amount, 1 );
509
    }
510
511
    $symbol = wpinv_currency_symbol( $currency );
512
513
    if ( $position == 'left' || $position == 'left_space' ) {
514 View Code Duplication
        switch ( $currency ) {
515
            case "GBP" :
516
            case "BRL" :
517
            case "EUR" :
518
            case "USD" :
519
            case "AUD" :
520
            case "CAD" :
521
            case "HKD" :
522
            case "MXN" :
523
            case "NZD" :
524
            case "SGD" :
525
            case "JPY" :
526
                $price = $position == 'left_space' ? $symbol . ' ' .  $amount : $symbol . $amount;
527
                break;
528
            default :
529
                //$price = $currency . ' ' . $amount;
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
530
                $price = $position == 'left_space' ? $symbol . ' ' .  $amount : $symbol . $amount;
531
                break;
532
        }
533
    } else {
534 View Code Duplication
        switch ( $currency ) {
535
            case "GBP" :
536
            case "BRL" :
537
            case "EUR" :
538
            case "USD" :
539
            case "AUD" :
540
            case "CAD" :
541
            case "HKD" :
542
            case "MXN" :
543
            case "SGD" :
544
            case "JPY" :
545
                $price = $position == 'right_space' ? $amount . ' ' .  $symbol : $amount . $symbol;
546
                break;
547
            default :
548
                //$price = $amount . ' ' . $currency;
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
549
                $price = $position == 'right_space' ? $amount . ' ' .  $symbol : $amount . $symbol;
550
                break;
551
        }
552
    }
553
    
554
    if ( $negative ) {
555
        $price = '-' . $price;
556
    }
557
    
558
    $price = apply_filters( 'wpinv_' . strtolower( $currency ) . '_currency_filter_' . $position, $price, $currency, $amount );
559
560
    return $price;
561
}
562
563
function wpinv_format_amount( $amount, $decimals = NULL, $calculate = false ) {
564
    $thousands_sep = wpinv_thousands_separator();
565
    $decimal_sep   = wpinv_decimal_separator();
566
567
    if ( $decimals === NULL ) {
568
        $decimals = wpinv_decimals();
569
    }
570
571
    if ( $decimal_sep == ',' && false !== ( $sep_found = strpos( $amount, $decimal_sep ) ) ) {
572
        $whole = substr( $amount, 0, $sep_found );
573
        $part = substr( $amount, $sep_found + 1, ( strlen( $amount ) - 1 ) );
574
        $amount = $whole . '.' . $part;
575
    }
576
577 View Code Duplication
    if ( $thousands_sep == ',' && false !== ( $found = strpos( $amount, $thousands_sep ) ) ) {
578
        $amount = str_replace( ',', '', $amount );
579
    }
580
581 View Code Duplication
    if ( $thousands_sep == ' ' && false !== ( $found = strpos( $amount, $thousands_sep ) ) ) {
582
        $amount = str_replace( ' ', '', $amount );
583
    }
584
585
    if ( empty( $amount ) ) {
586
        $amount = 0;
587
    }
588
    
589
    $decimals  = apply_filters( 'wpinv_amount_format_decimals', $decimals ? $decimals : 0, $amount, $calculate );
590
    $formatted = number_format( (float)$amount, $decimals, $decimal_sep, $thousands_sep );
591
    
592
    if ( $calculate ) {
593
        if ( $thousands_sep === "," ) {
594
            $formatted = str_replace( ",", "", $formatted );
595
        }
596
        
597
        if ( $decimal_sep === "," ) {
598
            $formatted = str_replace( ",", ".", $formatted );
599
        }
600
    }
601
602
    return apply_filters( 'wpinv_amount_format', $formatted, $amount, $decimals, $decimal_sep, $thousands_sep, $calculate );
603
}
604
add_filter( 'wpinv_amount_format_decimals', 'wpinv_currency_decimal_filter', 10, 1 );
605
606
function wpinv_sanitize_key( $key ) {
607
    $raw_key = $key;
608
    $key = preg_replace( '/[^a-zA-Z0-9_\-\.\:\/]/', '', $key );
609
610
    return apply_filters( 'wpinv_sanitize_key', $key, $raw_key );
611
}
612
613
function wpinv_get_file_extension( $str ) {
614
    $parts = explode( '.', $str );
615
    return end( $parts );
616
}
617
618
function wpinv_string_is_image_url( $str ) {
619
    $ext = wpinv_get_file_extension( $str );
620
621
    switch ( strtolower( $ext ) ) {
622
        case 'jpeg';
623
        case 'jpg';
624
            $return = true;
625
            break;
626
        case 'png';
627
            $return = true;
628
            break;
629
        case 'gif';
630
            $return = true;
631
            break;
632
        default:
633
            $return = false;
634
            break;
635
    }
636
637
    return (bool)apply_filters( 'wpinv_string_is_image', $return, $str );
638
}
639
640
function wpinv_error_log( $log, $title = '', $file = '', $line = '', $exit = false ) {
641
    $should_log = apply_filters( 'wpinv_log_errors', WP_DEBUG );
642
    
643
    if ( true === $should_log ) {
644
        $label = '';
645
        if ( $file && $file !== '' ) {
646
            $label .= basename( $file ) . ( $line ? '(' . $line . ')' : '' );
647
        }
648
        
649
        if ( $title && $title !== '' ) {
650
            $label = $label !== '' ? $label . ' ' : '';
651
            $label .= $title . ' ';
652
        }
653
        
654
        $label = $label !== '' ? trim( $label ) . ' : ' : '';
655
        
656
        if ( is_array( $log ) || is_object( $log ) ) {
657
            error_log( $label . print_r( $log, true ) );
658
        } else {
659
            error_log( $label . $log );
660
        }
661
        
662
        if ( $exit ) {
663
            exit;
664
        }
665
    }
666
}
667
668
function wpinv_is_ajax_disabled() {
669
    $retval = false;
670
    return apply_filters( 'wpinv_is_ajax_disabled', $retval );
671
}
672
673
function wpinv_get_current_page_url( $nocache = false ) {
674
    global $wp;
675
676
    if ( get_option( 'permalink_structure' ) ) {
677
        $base = trailingslashit( home_url( $wp->request ) );
678
    } else {
679
        $base = add_query_arg( $wp->query_string, '', trailingslashit( home_url( $wp->request ) ) );
680
        $base = remove_query_arg( array( 'post_type', 'name' ), $base );
681
    }
682
683
    $scheme = is_ssl() ? 'https' : 'http';
684
    $uri    = set_url_scheme( $base, $scheme );
685
686
    if ( is_front_page() ) {
687
        $uri = home_url( '/' );
688
    } elseif ( wpinv_is_checkout( array(), false ) ) {
0 ignored issues
show
Unused Code introduced by
The call to wpinv_is_checkout() has too many arguments starting with array().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
689
        $uri = wpinv_get_checkout_uri();
690
    }
691
692
    $uri = apply_filters( 'wpinv_get_current_page_url', $uri );
693
694
    if ( $nocache ) {
695
        $uri = wpinv_add_cache_busting( $uri );
696
    }
697
698
    return $uri;
699
}
700
701
function wpinv_get_php_arg_separator_output() {
702
	return ini_get( 'arg_separator.output' );
703
}
704
705
function wpinv_rgb_from_hex( $color ) {
706
    $color = str_replace( '#', '', $color );
707
    // Convert shorthand colors to full format, e.g. "FFF" -> "FFFFFF"
708
    $color = preg_replace( '~^(.)(.)(.)$~', '$1$1$2$2$3$3', $color );
709
710
    $rgb      = array();
711
    $rgb['R'] = hexdec( $color{0}.$color{1} );
712
    $rgb['G'] = hexdec( $color{2}.$color{3} );
713
    $rgb['B'] = hexdec( $color{4}.$color{5} );
714
715
    return $rgb;
716
}
717
718 View Code Duplication
function wpinv_hex_darker( $color, $factor = 30 ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
719
    $base  = wpinv_rgb_from_hex( $color );
720
    $color = '#';
721
722
    foreach ( $base as $k => $v ) {
723
        $amount      = $v / 100;
724
        $amount      = round( $amount * $factor );
725
        $new_decimal = $v - $amount;
726
727
        $new_hex_component = dechex( $new_decimal );
728
        if ( strlen( $new_hex_component ) < 2 ) {
729
            $new_hex_component = "0" . $new_hex_component;
730
        }
731
        $color .= $new_hex_component;
732
    }
733
734
    return $color;
735
}
736
737 View Code Duplication
function wpinv_hex_lighter( $color, $factor = 30 ) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
738
    $base  = wpinv_rgb_from_hex( $color );
739
    $color = '#';
740
741
    foreach ( $base as $k => $v ) {
742
        $amount      = 255 - $v;
743
        $amount      = $amount / 100;
744
        $amount      = round( $amount * $factor );
745
        $new_decimal = $v + $amount;
746
747
        $new_hex_component = dechex( $new_decimal );
748
        if ( strlen( $new_hex_component ) < 2 ) {
749
            $new_hex_component = "0" . $new_hex_component;
750
        }
751
        $color .= $new_hex_component;
752
    }
753
754
    return $color;
755
}
756
757
function wpinv_light_or_dark( $color, $dark = '#000000', $light = '#FFFFFF' ) {
758
    $hex = str_replace( '#', '', $color );
759
760
    $c_r = hexdec( substr( $hex, 0, 2 ) );
761
    $c_g = hexdec( substr( $hex, 2, 2 ) );
762
    $c_b = hexdec( substr( $hex, 4, 2 ) );
763
764
    $brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000;
765
766
    return $brightness > 155 ? $dark : $light;
767
}
768
769
function wpinv_format_hex( $hex ) {
770
    $hex = trim( str_replace( '#', '', $hex ) );
771
772
    if ( strlen( $hex ) == 3 ) {
773
        $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
774
    }
775
776
    return $hex ? '#' . $hex : null;
777
}
778
779
/**
780
 * Get truncated string with specified width.
781
 *
782
 * @since 1.0.0
783
 *
784
 * @param string $str The string being decoded.
785
 * @param int $start The start position offset. Number of characters from the beginning of string.
786
 *                      For negative value, number of characters from the end of the string.
787
 * @param int $width The width of the desired trim. Negative widths count from the end of the string.
788
 * @param string $trimmaker A string that is added to the end of string when string is truncated. Ex: "...".
789
 * @param string $encoding The encoding parameter is the character encoding. Default "UTF-8".
790
 * @return string
791
 */
792
function wpinv_utf8_strimwidth( $str, $start, $width, $trimmaker = '', $encoding = 'UTF-8' ) {
793
    if ( function_exists( 'mb_strimwidth' ) ) {
794
        return mb_strimwidth( $str, $start, $width, $trimmaker, $encoding );
795
    }
796
    
797
    return wpinv_utf8_substr( $str, $start, $width, $encoding ) . $trimmaker;
798
}
799
800
/**
801
 * Get the string length.
802
 *
803
 * @since 1.0.0
804
 *
805
 * @param string $str The string being checked for length. 
806
 * @param string $encoding The encoding parameter is the character encoding. Default "UTF-8".
807
 * @return int Returns the number of characters in string.
808
 */
809
function wpinv_utf8_strlen( $str, $encoding = 'UTF-8' ) {
810
    if ( function_exists( 'mb_strlen' ) ) {
811
        return mb_strlen( $str, $encoding );
812
    }
813
        
814
    return strlen( $str );
815
}
816
817
function wpinv_utf8_strtolower( $str, $encoding = 'UTF-8' ) {
818
    if ( function_exists( 'mb_strtolower' ) ) {
819
        return mb_strtolower( $str, $encoding );
820
    }
821
    
822
    return strtolower( $str );
823
}
824
825
function wpinv_utf8_strtoupper( $str, $encoding = 'UTF-8' ) {
826
    if ( function_exists( 'mb_strtoupper' ) ) {
827
        return mb_strtoupper( $str, $encoding );
828
    }
829
    
830
    return strtoupper( $str );
831
}
832
833
/**
834
 * Find position of first occurrence of string in a string
835
 *
836
 * @since 1.0.0
837
 *
838
 * @param string $str The string being checked.
839
 * @param string $find The string to find in input string.
840
 * @param int $offset The search offset. Default "0". A negative offset counts from the end of the string.
841
 * @param string $encoding The encoding parameter is the character encoding. Default "UTF-8".
842
 * @return int Returns the position of the first occurrence of search in the string.
843
 */
844
function wpinv_utf8_strpos( $str, $find, $offset = 0, $encoding = 'UTF-8' ) {
845
    if ( function_exists( 'mb_strpos' ) ) {
846
        return mb_strpos( $str, $find, $offset, $encoding );
847
    }
848
        
849
    return strpos( $str, $find, $offset );
850
}
851
852
/**
853
 * Find position of last occurrence of a string in a string.
854
 *
855
 * @since 1.0.0
856
 *
857
 * @param string $str The string being checked, for the last occurrence of search.
858
 * @param string $find The string to find in input string.
859
 * @param int $offset Specifies begin searching an arbitrary number of characters into the string.
860
 * @param string $encoding The encoding parameter is the character encoding. Default "UTF-8".
861
 * @return int Returns the position of the last occurrence of search.
862
 */
863
function wpinv_utf8_strrpos( $str, $find, $offset = 0, $encoding = 'UTF-8' ) {
864
    if ( function_exists( 'mb_strrpos' ) ) {
865
        return mb_strrpos( $str, $find, $offset, $encoding );
866
    }
867
        
868
    return strrpos( $str, $find, $offset );
869
}
870
871
/**
872
 * Get the part of string.
873
 *
874
 * @since 1.0.0
875
 *
876
 * @param string $str The string to extract the substring from.
877
 * @param int $start If start is non-negative, the returned string will start at the entered position in string, counting from zero.
878
 *                      If start is negative, the returned string will start at the entered position from the end of string. 
879
 * @param int|null $length Maximum number of characters to use from string.
880
 * @param string $encoding The encoding parameter is the character encoding. Default "UTF-8".
881
 * @return string
882
 */
883
function wpinv_utf8_substr( $str, $start, $length = null, $encoding = 'UTF-8' ) {
884
    if ( function_exists( 'mb_substr' ) ) {
885
        if ( $length === null ) {
886
            return mb_substr( $str, $start, wpinv_utf8_strlen( $str, $encoding ), $encoding );
887
        } else {
888
            return mb_substr( $str, $start, $length, $encoding );
889
        }
890
    }
891
        
892
    return substr( $str, $start, $length );
893
}
894
895
/**
896
 * Get the width of string.
897
 *
898
 * @since 1.0.0
899
 *
900
 * @param string $str The string being decoded.
901
 * @param string $encoding The encoding parameter is the character encoding. Default "UTF-8".
902
 * @return string The width of string.
903
 */
904
function wpinv_utf8_strwidth( $str, $encoding = 'UTF-8' ) {
905
    if ( function_exists( 'mb_strwidth' ) ) {
906
        return mb_strwidth( $str, $encoding );
907
    }
908
    
909
    return wpinv_utf8_strlen( $str, $encoding );
910
}
911
912
function wpinv_utf8_ucfirst( $str, $lower_str_end = false, $encoding = 'UTF-8' ) {
913
    if ( function_exists( 'mb_strlen' ) ) {
914
        $first_letter = wpinv_utf8_strtoupper( wpinv_utf8_substr( $str, 0, 1, $encoding ), $encoding );
915
        $str_end = "";
0 ignored issues
show
Unused Code introduced by
$str_end is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
916
        
917
        if ( $lower_str_end ) {
918
            $str_end = wpinv_utf8_strtolower( wpinv_utf8_substr( $str, 1, wpinv_utf8_strlen( $str, $encoding ), $encoding ), $encoding );
919
        } else {
920
            $str_end = wpinv_utf8_substr( $str, 1, wpinv_utf8_strlen( $str, $encoding ), $encoding );
921
        }
922
923
        return $first_letter . $str_end;
924
    }
925
    
926
    return ucfirst( $str );
927
}
928
929
function wpinv_utf8_ucwords( $str, $encoding = 'UTF-8' ) {
930
    if ( function_exists( 'mb_convert_case' ) ) {
931
        return mb_convert_case( $str, MB_CASE_TITLE, $encoding );
932
    }
933
    
934
    return ucwords( $str );
935
}
936
937
function wpinv_period_in_days( $period, $unit ) {
938
    $period = absint( $period );
939
    
940
    if ( $period > 0 ) {
941
        if ( in_array( strtolower( $unit ), array( 'w', 'week', 'weeks' ) ) ) {
942
            $period = $period * 7;
943
        } else if ( in_array( strtolower( $unit ), array( 'm', 'month', 'months' ) ) ) {
944
            $period = $period * 30;
945
        } else if ( in_array( strtolower( $unit ), array( 'y', 'year', 'years' ) ) ) {
946
            $period = $period * 365;
947
        }
948
    }
949
    
950
    return $period;
951
}
952
953
function wpinv_cal_days_in_month( $calendar, $month, $year ) {
954
    if ( function_exists( 'cal_days_in_month' ) ) {
955
        return cal_days_in_month( $calendar, $month, $year );
956
    }
957
958
    // Fallback in case the calendar extension is not loaded in PHP
959
    // Only supports Gregorian calendar
960
    return date( 't', mktime( 0, 0, 0, $month, 1, $year ) );
961
}
962