Passed
Pull Request — master (#377)
by Brian
11:41
created

wpinv_user_can_view_invoice()   B

Complexity

Conditions 10
Paths 6

Size

Total Lines 29
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 12
c 0
b 0
f 0
dl 0
loc 29
rs 7.6666
cc 10
nc 6
nop 1

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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_is_checkout() {
15
    global $wp_query;
16
17
    $is_object_set    = isset( $wp_query->queried_object );
18
    $is_object_id_set = isset( $wp_query->queried_object_id );
19
    $is_checkout      = is_page( wpinv_get_option( 'checkout_page' ) );
20
21
    if ( !$is_object_set ) {
22
        unset( $wp_query->queried_object );
23
    }
24
25
    if ( !$is_object_id_set ) {
26
        unset( $wp_query->queried_object_id );
27
    }
28
29
    return apply_filters( 'wpinv_is_checkout', $is_checkout );
30
}
31
32
function wpinv_can_checkout() {
33
	$can_checkout = true; // Always true for now
34
35
	return (bool) apply_filters( 'wpinv_can_checkout', $can_checkout );
36
}
37
38
function wpinv_get_success_page_uri() {
39
	$page_id = wpinv_get_option( 'success_page', 0 );
40
	$page_id = absint( $page_id );
41
42
	return apply_filters( 'wpinv_get_success_page_uri', get_permalink( $page_id ) );
43
}
44
45
function wpinv_get_history_page_uri() {
46
	$page_id = wpinv_get_option( 'invoice_history_page', 0 );
47
	$page_id = absint( $page_id );
48
49
	return apply_filters( 'wpinv_get_history_page_uri', get_permalink( $page_id ) );
50
}
51
52
function wpinv_is_success_page() {
53
	$is_success_page = wpinv_get_option( 'success_page', false );
54
	$is_success_page = isset( $is_success_page ) ? is_page( $is_success_page ) : false;
55
56
	return apply_filters( 'wpinv_is_success_page', $is_success_page );
57
}
58
59
function wpinv_is_invoice_history_page() {
60
	$ret = wpinv_get_option( 'invoice_history_page', false );
61
	$ret = $ret ? is_page( $ret ) : false;
62
	return apply_filters( 'wpinv_is_invoice_history_page', $ret );
63
}
64
65
function wpinv_is_subscriptions_history_page() {
66
    $ret = wpinv_get_option( 'invoice_subscription_page', false );
67
    $ret = $ret ? is_page( $ret ) : false;
68
    return apply_filters( 'wpinv_is_subscriptions_history_page', $ret );
69
}
70
71
function wpinv_send_to_success_page( $args = null ) {
72
	$redirect = wpinv_get_success_page_uri();
73
    
74
    if ( !empty( $args ) ) {
75
        // Check for backward compatibility
76
        if ( is_string( $args ) )
77
            $args = str_replace( '?', '', $args );
78
79
        $args = wp_parse_args( $args );
80
81
        $redirect = add_query_arg( $args, $redirect );
82
    }
83
84
    $gateway = isset( $_REQUEST['wpi-gateway'] ) ? $_REQUEST['wpi-gateway'] : '';
85
    
86
    $redirect = apply_filters( 'wpinv_success_page_redirect', $redirect, $gateway, $args );
87
    wp_redirect( $redirect );
88
    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
89
}
90
91
function wpinv_send_to_failed_page( $args = null ) {
92
	$redirect = wpinv_get_failed_transaction_uri();
93
    
94
    if ( !empty( $args ) ) {
95
        // Check for backward compatibility
96
        if ( is_string( $args ) )
97
            $args = str_replace( '?', '', $args );
98
99
        $args = wp_parse_args( $args );
100
101
        $redirect = add_query_arg( $args, $redirect );
102
    }
103
104
    $gateway = isset( $_REQUEST['wpi-gateway'] ) ? $_REQUEST['wpi-gateway'] : '';
105
    
106
    $redirect = apply_filters( 'wpinv_failed_page_redirect', $redirect, $gateway, $args );
107
    wp_redirect( $redirect );
108
    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
109
}
110
111
function wpinv_get_checkout_uri( $args = array() ) {
112
	$uri = wpinv_get_option( 'checkout_page', false );
113
	$uri = isset( $uri ) ? get_permalink( $uri ) : NULL;
114
115
	if ( !empty( $args ) ) {
116
		// Check for backward compatibility
117
		if ( is_string( $args ) )
118
			$args = str_replace( '?', '', $args );
119
120
		$args = wp_parse_args( $args );
121
122
		$uri = add_query_arg( $args, $uri );
123
	}
124
125
	$scheme = defined( 'FORCE_SSL_ADMIN' ) && FORCE_SSL_ADMIN ? 'https' : 'admin';
126
127
	$ajax_url = admin_url( 'admin-ajax.php', $scheme );
128
129
	if ( ( ! preg_match( '/^https/', $uri ) && preg_match( '/^https/', $ajax_url ) ) || wpinv_is_ssl_enforced() ) {
0 ignored issues
show
Bug introduced by
It seems like $uri can also be of type false; however, parameter $subject of preg_match() does only seem to accept 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

129
	if ( ( ! preg_match( '/^https/', /** @scrutinizer ignore-type */ $uri ) && preg_match( '/^https/', $ajax_url ) ) || wpinv_is_ssl_enforced() ) {
Loading history...
130
		$uri = preg_replace( '/^http:/', 'https:', $uri );
131
	}
132
133
	return apply_filters( 'wpinv_get_checkout_uri', $uri );
134
}
135
136
function wpinv_send_back_to_checkout( $args = array() ) {
137
	$redirect = wpinv_get_checkout_uri();
138
139
	if ( ! empty( $args ) ) {
140
		// Check for backward compatibility
141
		if ( is_string( $args ) )
142
			$args = str_replace( '?', '', $args );
143
144
		$args = wp_parse_args( $args );
145
146
		$redirect = add_query_arg( $args, $redirect );
147
	}
148
149
    do_action( 'wpinv_pre_send_back_to_checkout', $args );
150
	wp_redirect( apply_filters( 'wpinv_send_back_to_checkout', $redirect, $args ) );
151
	exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
152
}
153
154
function wpinv_get_success_page_url( $query_string = null ) {
155
	$success_page = wpinv_get_option( 'success_page', 0 );
156
	$success_page = get_permalink( $success_page );
157
158
	if ( $query_string )
159
		$success_page .= $query_string;
160
161
	return apply_filters( 'wpinv_success_page_url', $success_page );
162
}
163
164
function wpinv_get_failed_transaction_uri( $extras = false ) {
165
	$uri = wpinv_get_option( 'failure_page', '' );
166
	$uri = ! empty( $uri ) ? trailingslashit( get_permalink( $uri ) ) : home_url();
0 ignored issues
show
Bug introduced by
It seems like $uri can also be of type string; however, parameter $post of get_permalink() does only seem to accept WP_Post|integer, 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

166
	$uri = ! empty( $uri ) ? trailingslashit( get_permalink( /** @scrutinizer ignore-type */ $uri ) ) : home_url();
Loading history...
Bug introduced by
It seems like get_permalink($uri) can also be of type false; however, parameter $string of trailingslashit() does only seem to accept 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

166
	$uri = ! empty( $uri ) ? trailingslashit( /** @scrutinizer ignore-type */ get_permalink( $uri ) ) : home_url();
Loading history...
167
168
	if ( $extras )
169
		$uri .= $extras;
170
171
	return apply_filters( 'wpinv_get_failed_transaction_uri', $uri );
172
}
173
174
function wpinv_is_failed_transaction_page() {
175
	$ret = wpinv_get_option( 'failure_page', false );
176
	$ret = isset( $ret ) ? is_page( $ret ) : false;
177
178
	return apply_filters( 'wpinv_is_failure_page', $ret );
179
}
180
181
function wpinv_transaction_query( $type = 'start' ) {
182
    global $wpdb;
183
184
    $wpdb->hide_errors();
185
186
    if ( ! defined( 'WPINV_USE_TRANSACTIONS' ) ) {
187
        define( 'WPINV_USE_TRANSACTIONS', true );
188
    }
189
190
    if ( WPINV_USE_TRANSACTIONS ) {
191
        switch ( $type ) {
192
            case 'commit' :
193
                $wpdb->query( 'COMMIT' );
194
                break;
195
            case 'rollback' :
196
                $wpdb->query( 'ROLLBACK' );
197
                break;
198
            default :
199
                $wpdb->query( 'START TRANSACTION' );
200
            break;
201
        }
202
    }
203
}
204
205
function wpinv_create_invoice( $args = array(), $data = array(), $wp_error = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $data is not used and could be removed. ( Ignorable by Annotation )

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

205
function wpinv_create_invoice( $args = array(), /** @scrutinizer ignore-unused */ $data = array(), $wp_error = false ) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
206
    $default_args = array(
207
        'status'        => '',
208
        'user_id'       => null,
209
        'user_note'     => null,
210
        'invoice_id'    => 0,
211
        'created_via'   => '',
212
        'parent'        => 0,
213
        'post_type'     => 'wpi_invoice'
214
    );
215
216
    $args           = wp_parse_args( $args, $default_args );
217
    $invoice_data   = array();
218
219
    if ( $args['invoice_id'] > 0 ) {
220
        $updating           = true;
221
        $invoice_data['post_type']  = $args['post_type'];
222
        $invoice_data['ID']         = $args['invoice_id'];
223
    } else {
224
        $updating                       = false;
225
        $invoice_data['post_type']      = $args['post_type'];
226
        $invoice_data['post_status']    = apply_filters( 'wpinv_default_invoice_status', 'wpi-pending' );
227
        $invoice_data['ping_status']    = 'closed';
228
        $invoice_data['post_author']    = !empty( $args['user_id'] ) ? $args['user_id'] : get_current_user_id();
229
        $invoice_data['post_title']     = wpinv_format_invoice_number( '0' );
230
        $invoice_data['post_parent']    = absint( $args['parent'] );
231
        if ( !empty( $args['created_date'] ) ) {
232
            $invoice_data['post_date']      = $args['created_date'];
233
            $invoice_data['post_date_gmt']  = get_gmt_from_date( $args['created_date'] );
234
        }
235
    }
236
237
    if ( $args['status'] ) {
238
        if ( ! in_array( $args['status'], array_keys( wpinv_get_invoice_statuses() ) ) && 'wpi_invoice' === $invoice_data['post_type'] ) {
239
            return new WP_Error( 'wpinv_invalid_invoice_status', wp_sprintf( __( 'Invalid invoice status: %s', 'invoicing' ), $args['status'] ) );
240
        }
241
        $invoice_data['post_status']    = $args['status'];
242
    }
243
244
    if ( ! is_null( $args['user_note'] ) ) {
245
        $invoice_data['post_excerpt']   = $args['user_note'];
246
    }
247
248
    if ( $updating ) {
249
        $invoice_id = wp_update_post( $invoice_data, true );
250
    } else {
251
        $invoice_id = wp_insert_post( apply_filters( 'wpinv_new_invoice_data', $invoice_data ), true );
252
    }
253
254
    if ( is_wp_error( $invoice_id ) ) {
255
        return $wp_error ? $invoice_id : 0;
256
    }
257
    
258
    $invoice = wpinv_get_invoice( $invoice_id );
259
260
    if ( !$updating ) {
261
        update_post_meta( $invoice_id, '_wpinv_key', apply_filters( 'wpinv_generate_invoice_key', uniqid( 'wpinv_' ) ) );
0 ignored issues
show
Bug introduced by
It seems like $invoice_id can also be of type WP_Error; however, parameter $post_id of update_post_meta() does only seem to accept integer, 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

261
        update_post_meta( /** @scrutinizer ignore-type */ $invoice_id, '_wpinv_key', apply_filters( 'wpinv_generate_invoice_key', uniqid( 'wpinv_' ) ) );
Loading history...
262
        update_post_meta( $invoice_id, '_wpinv_currency', wpinv_get_currency() );
263
        update_post_meta( $invoice_id, '_wpinv_include_tax', get_option( 'wpinv_prices_include_tax' ) );
264
        update_post_meta( $invoice_id, '_wpinv_user_ip', wpinv_get_ip() );
265
        update_post_meta( $invoice_id, '_wpinv_user_agent', wpinv_get_user_agent() );
266
        update_post_meta( $invoice_id, '_wpinv_created_via', sanitize_text_field( $args['created_via'] ) );
267
        
268
        // Add invoice note
269
        if ( ! $invoice->is_quote() ) {
270
            $invoice->add_note( wp_sprintf( __( 'Invoice is created with status %s.', 'invoicing' ), wpinv_status_nicename( $invoice->status ) ) );
0 ignored issues
show
Bug Best Practice introduced by
The property status does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
271
        }
272
        
273
    }
274
275
    update_post_meta( $invoice_id, '_wpinv_version', WPINV_VERSION );
276
277
    return $invoice;
278
}
279
280
function wpinv_get_prefix() {
281
    $invoice_prefix = 'INV-';
282
    
283
    return apply_filters( 'wpinv_get_prefix', $invoice_prefix );
284
}
285
286
function wpinv_get_business_logo() {
287
    $business_logo = wpinv_get_option( 'logo' );
288
    return apply_filters( 'wpinv_get_business_logo', $business_logo );
289
}
290
291
function wpinv_get_business_name() {
292
    $business_name = wpinv_get_option('store_name');
293
    return apply_filters( 'wpinv_get_business_name', $business_name );
294
}
295
296
function wpinv_get_blogname() {
297
    return wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
0 ignored issues
show
Bug introduced by
It seems like get_option('blogname') can also be of type false; however, parameter $string of wp_specialchars_decode() does only seem to accept 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

297
    return wp_specialchars_decode( /** @scrutinizer ignore-type */ get_option( 'blogname' ), ENT_QUOTES );
Loading history...
298
}
299
300
function wpinv_get_admin_email() {
301
    $admin_email = wpinv_get_option( 'admin_email', get_option( 'admin_email' ) );
302
    return apply_filters( 'wpinv_admin_email', $admin_email );
303
}
304
305
function wpinv_get_business_website() {
306
    $business_website = home_url( '/' );
307
    return apply_filters( 'wpinv_get_business_website', $business_website );
308
}
309
310
function wpinv_get_terms_text( $invoice_id = 0 ) {
311
    $terms_text = '';
312
    return apply_filters( 'wpinv_get_terms_text', $terms_text, $invoice_id );
313
}
314
315
function wpinv_get_business_footer() {
316
    $site_link = '<a target="_blank" href="' . esc_url( wpinv_get_business_website() ) . '">' . esc_html( wpinv_get_business_name() ) . '</a>';
0 ignored issues
show
Bug introduced by
It seems like wpinv_get_business_name() can also be of type false; however, parameter $text of esc_html() does only seem to accept 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

316
    $site_link = '<a target="_blank" href="' . esc_url( wpinv_get_business_website() ) . '">' . esc_html( /** @scrutinizer ignore-type */ wpinv_get_business_name() ) . '</a>';
Loading history...
317
    $business_footer = wp_sprintf( __( 'Thanks for using %s', 'invoicing' ), $site_link );
318
    return apply_filters( 'wpinv_get_business_footer', $business_footer );
319
}
320
321
function wpinv_checkout_required_fields() {
322
    $required_fields = array();
323
    
324
    // Let payment gateways and other extensions determine if address fields should be required
325
    $require_billing_details = apply_filters( 'wpinv_checkout_required_billing_details', wpinv_use_taxes() );
326
    
327
    if ( $require_billing_details ) {
328
		if ( (bool)wpinv_get_option( 'fname_mandatory' ) ) {
329
			$required_fields['first_name'] = array(
330
				'error_id' => 'invalid_first_name',
331
				'error_message' => __( 'Please enter your first name', 'invoicing' )
332
			);
333
		}
334
		if ( (bool)wpinv_get_option( 'address_mandatory' ) ) {
335
			$required_fields['address'] = array(
336
				'error_id' => 'invalid_address',
337
				'error_message' => __( 'Please enter your address', 'invoicing' )
338
			);
339
		}
340
		if ( (bool)wpinv_get_option( 'city_mandatory' ) ) {
341
			$required_fields['city'] = array(
342
				'error_id' => 'invalid_city',
343
				'error_message' => __( 'Please enter your billing city', 'invoicing' )
344
			);
345
		}
346
		if ( (bool)wpinv_get_option( 'state_mandatory' ) ) {
347
			$required_fields['state'] = array(
348
				'error_id' => 'invalid_state',
349
				'error_message' => __( 'Please enter billing state / province', 'invoicing' )
350
			);
351
		}
352
		if ( (bool)wpinv_get_option( 'country_mandatory' ) ) {
353
			$required_fields['country'] = array(
354
				'error_id' => 'invalid_country',
355
				'error_message' => __( 'Please select your billing country', 'invoicing' )
356
			);
357
		}
358
    }
359
360
    return apply_filters( 'wpinv_checkout_required_fields', $required_fields );
361
}
362
363
function wpinv_is_ssl_enforced() {
364
    $ssl_enforced = wpinv_get_option( 'enforce_ssl', false );
365
    return (bool) apply_filters( 'wpinv_is_ssl_enforced', $ssl_enforced );
366
}
367
368
/**
369
 * Checks if the current user cna view an invoice.
370
 */
371
function wpinv_user_can_view_invoice( $invoice ) {
372
    $invoice = new WPInv_Invoice( $invoice );
373
374
    // Abort if the invoice does not exist.
375
    if ( 0 == $invoice->get_id() ) {
376
        return false;
377
    }
378
379
    // Don't allow trash, draft status
380
    if ( $invoice->is_draft() ) {
381
        return false;
382
    }
383
384
    // If users are not required to login to check out, compare the invoice keys.
385
    if ( ! wpinv_require_login_to_checkout() && isset( $_GET['invoice_key'] ) && trim( $_GET['invoice_key'] ) == $invoice->get_key() ) {
386
        return true;
387
    }
388
389
    // Always enable for admins..
390
    if ( wpinv_current_user_can_manage_invoicing() || current_user_can( 'view_invoices', $invoice->ID ) ) { // Admin user
391
        return true;
392
    }
393
394
    // Else, ensure that this is their invoice.
395
    if ( is_user_logged_in() && $invoice->get_user_id() == get_current_user_id() ) {
396
        return true;
397
    }
398
399
    return apply_filters( 'wpinv_current_user_can_view_invoice', false, $invoice );
400
}
401
402
function wpinv_schedule_events() {
403
404
    // Get the timestamp for the next event.
405
    $timestamp = wp_next_scheduled( 'wpinv_register_schedule_event_twicedaily' );
406
407
    if ( $timestamp ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $timestamp of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
408
        wp_unschedule_event( $timestamp, 'wpinv_register_schedule_event_twicedaily' );
409
    }
410
411
    if ( ! wp_next_scheduled( 'wpinv_register_schedule_event_daily' ) ) {
412
        wp_schedule_event( current_time( 'timestamp' ), 'daily', 'wpinv_register_schedule_event_daily' );
413
    }
414
}
415
add_action( 'wp', 'wpinv_schedule_events' );
416
417
function wpinv_schedule_event_twicedaily() {
418
    wpinv_email_payment_reminders();
419
    wpinv_email_renewal_reminders();
420
}
421
add_action( 'wpinv_register_schedule_event_daily', 'wpinv_schedule_event_twicedaily' );
422
423
function wpinv_require_login_to_checkout() {
424
    $return = wpinv_get_option( 'login_to_checkout', false );
425
    return (bool) apply_filters( 'wpinv_require_login_to_checkout', $return );
426
}
427
428
function wpinv_sequential_number_active( $type = '' ) {
429
    $check = apply_filters( 'wpinv_pre_check_sequential_number_active', null, $type );
430
    if ( null !== $check ) {
431
        return $check;
432
    }
433
    
434
    return wpinv_get_option( 'sequential_invoice_number' );
435
}
436
437
function wpinv_switch_to_locale( $locale = NULL ) {
438
    global $invoicing, $wpi_switch_locale;
439
440
    if ( ! empty( $invoicing ) && function_exists( 'switch_to_locale' ) ) {
441
        $locale = empty( $locale ) ? get_locale() : $locale;
442
443
        switch_to_locale( $locale );
444
445
        $wpi_switch_locale = $locale;
446
447
        add_filter( 'plugin_locale', 'get_locale' );
448
449
        $invoicing->load_textdomain();
450
451
        do_action( 'wpinv_switch_to_locale', $locale );
452
    }
453
}
454
455
function wpinv_restore_locale() {
456
    global $invoicing, $wpi_switch_locale;
457
    
458
    if ( ! empty( $invoicing ) && function_exists( 'restore_previous_locale' ) && $wpi_switch_locale ) {
459
        restore_previous_locale();
460
461
        $wpi_switch_locale = NULL;
462
463
        remove_filter( 'plugin_locale', 'get_locale' );
464
465
        $invoicing->load_textdomain();
466
467
        do_action( 'wpinv_restore_locale' );
468
    }
469
}
470
471
/**
472
 * Returns the default form's id.
473
 */
474
function wpinv_get_default_payment_form() {
475
    $form = get_option( 'wpinv_default_payment_form' );
476
477
    if ( empty( $form ) || 'publish' != get_post_status( $form ) ) {
478
        $form = wp_insert_post(
479
            array(
480
                'post_type'   => 'wpi_payment_form',
481
                'post_title'  => __( 'Checkout (default)', 'invoicing' ),
482
                'post_status' => 'publish',
483
                'meta_input'  => array(
484
                    'wpinv_form_elements' => wpinv_get_data( 'default-payment-form' ),
485
                    'wpinv_form_items'    => array(),
486
                )
487
            )
488
        );
489
490
        update_option( 'wpinv_default_payment_form', $form );
491
    }
492
493
    return $form;
494
}