Passed
Push — master ( eba4be...60f62d )
by Brian
09:36 queued 04:47
created

WPInv_Subscriptions   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 332
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 43
eloc 135
c 1
b 0
f 0
dl 0
loc 332
rs 8.96

13 Methods

Rating   Name   Duplication   Size   Complexity  
A setup_constants() 0 5 2
A notices() 0 33 6
A wpinv_subscriptions_list() 0 8 1
A __construct() 0 1 1
A instance() 0 8 2
A init() 0 5 1
A wpinv_post_actions() 0 3 2
A filters() 0 1 1
A wpinv_get_actions() 0 3 2
A actions() 0 9 1
B wpinv_checkout_add_subscription() 0 69 8
B wpinv_process_cancellation() 0 44 7
B wpinv_get_pretty_subscription_frequency() 0 27 9

How to fix   Complexity   

Complex Class

Complex classes like WPInv_Subscriptions often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use WPInv_Subscriptions, and based on these observations, apply Extract Interface, too.

1
<?php
2
// Exit if accessed directly.
3
if (!defined( 'ABSPATH' ) ) exit;
4
5
function wpinv_subscription_init() {
6
    return WPInv_Subscriptions::instance();
7
}
8
add_action( 'plugins_loaded', 'wpinv_subscription_init', 100 );
9
10
/**
11
 * WPInv_Subscriptions Class.
12
 *
13
 * @since 1.0.0
14
 */
15
class WPInv_Subscriptions {
16
17
    private static $instance;
18
19
    /**
20
     * Main WPInv_Subscriptions Instance
21
     */
22
    public static function instance() {
23
        if ( ! isset( self::$instance ) ) {
24
            self::$instance = new WPInv_Subscriptions;
25
26
            self::$instance->init();
27
        }
28
29
        return self::$instance;
30
    }
31
32
    /**
33
     * Constructor -- prevent new instances
34
     *
35
     * @since 1.0.0
36
     */
37
    private function __construct(){
38
39
    }
40
41
    /**
42
     * Get things started
43
     *
44
     * Sets up inits actions and filters
45
     *
46
     * @since 1.0.0
47
     */
48
    function init() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
49
50
        self::setup_constants();
0 ignored issues
show
Bug Best Practice introduced by
The method WPInv_Subscriptions::setup_constants() is not static, but was called statically. ( Ignorable by Annotation )

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

50
        self::/** @scrutinizer ignore-call */ 
51
              setup_constants();
Loading history...
51
        self::actions();
0 ignored issues
show
Bug Best Practice introduced by
The method WPInv_Subscriptions::actions() is not static, but was called statically. ( Ignorable by Annotation )

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

51
        self::/** @scrutinizer ignore-call */ 
52
              actions();
Loading history...
52
        self::filters();
0 ignored issues
show
Bug Best Practice introduced by
The method WPInv_Subscriptions::filters() is not static, but was called statically. ( Ignorable by Annotation )

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

52
        self::/** @scrutinizer ignore-call */ 
53
              filters();
Loading history...
53
54
    }
55
56
    /**
57
     * Setup plugin constants.
58
     *
59
     * @access private
60
     * @since 1.0.0
61
     * @return void
62
     */
63
    private function setup_constants() {
64
65
        // Make sure CAL_GREGORIAN is defined.
66
        if ( ! defined( 'CAL_GREGORIAN' ) ) {
67
            define( 'CAL_GREGORIAN', 1 );
68
        }
69
    }
70
71
    /**
72
     * Add our actions
73
     *
74
     * @since  1.0.0
75
     * @return void
76
     */
77
    private function actions() {
78
79
        add_action( 'admin_menu', array( $this, 'wpinv_subscriptions_list' ), 40 );
80
        add_action( 'admin_notices', array( $this, 'notices' ) );
81
        add_action( 'init', array( $this, 'wpinv_post_actions' ) );
82
        add_action( 'init', array( $this, 'wpinv_get_actions' ) );
83
        add_action( 'wpinv_cancel_subscription', array( $this, 'wpinv_process_cancellation' ) );
84
        add_action( 'wpinv_checkout_before_send_to_gateway', array( $this, 'wpinv_checkout_add_subscription' ), -999, 2 );
85
        add_action( 'wpinv_subscriptions_front_notices', array( $this, 'notices' ) );
86
    }
87
88
    /**
89
     * Add our filters
90
     *
91
     * @since  1.0
92
     * @return void
93
     */
94
    private function filters() {
95
96
    }
97
98
    /**
99
     * Register our Subscriptions submenu
100
     *
101
     * @since  2.4
102
     * @return void
103
     */
104
    public function wpinv_subscriptions_list() {
105
        add_submenu_page(
106
            'wpinv',
107
            __( 'Subscriptions', 'invoicing' ),
108
            __( 'Subscriptions', 'invoicing' ),
109
            wpinv_get_capability(),
110
            'wpinv-subscriptions',
111
            'wpinv_subscriptions_page'
112
        );
113
    }
114
115
    public function notices() {
116
117
        if( empty( $_GET['wpinv-message'] ) ) {
118
            return;
119
        }
120
121
        $type    = 'updated';
122
        $message = '';
123
124
        switch( strtolower( $_GET['wpinv-message'] ) ) {
125
126
            case 'updated' :
127
128
                $message = __( 'Subscription updated successfully.', 'invoicing' );
129
130
                break;
131
132
            case 'deleted' :
133
134
                $message = __( 'Subscription deleted successfully.', 'invoicing' );
135
136
                break;
137
138
            case 'cancelled' :
139
140
                $message = __( 'Subscription cancelled successfully.', 'invoicing' );
141
142
                break;
143
144
        }
145
146
        if ( ! empty( $message ) ) {
147
            echo '<div class="' . esc_attr( $type ) . '"><p>' . $message . '</p></div>';
148
        }
149
150
    }
151
152
    /**
153
     * Every wpinv_action present in $_GET is called using WordPress's do_action function.
154
     * These functions are called on init.
155
     *
156
     * @since 1.0.0
157
     * @return void
158
     */
159
    function wpinv_get_actions() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
160
        if ( isset( $_GET['wpinv_action'] ) ) {
161
            do_action( 'wpinv_' . $_GET['wpinv_action'], $_GET );
162
        }
163
    }
164
165
    /**
166
     * Every wpinv_action present in $_POST is called using WordPress's do_action function.
167
     * These functions are called on init.
168
     *
169
     * @since 1.0.0
170
     * @return void
171
     */
172
    function wpinv_post_actions() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
173
        if ( isset( $_POST['wpinv_action'] ) ) {
174
            do_action( 'wpinv_' . $_POST['wpinv_action'], $_POST );
175
        }
176
    }
177
178
    /**
179
     * Get pretty subscription frequency
180
     *
181
     * @param $period
182
     * @param int $frequency_count The frequency of the period.
183
     * @return mixed|string|void
184
     */
185
    public static function wpinv_get_pretty_subscription_frequency( $period, $frequency_count = 1) {
186
187
        $frequency = '';
188
        //Format period details
189
        switch ( strtolower( $period ) ) {
190
            case 'day' :
191
            case 'd' :
192
                $frequency = sprintf( _n('Day', '%d Days', $frequency_count, 'invoicing'), $frequency_count);
193
                break;
194
            case 'week' :
195
            case 'w' :
196
                $frequency = sprintf( _n('Week', '%d Weeks', $frequency_count, 'invoicing'), $frequency_count);
197
                break;
198
            case 'month' :
199
            case 'm' :
200
                $frequency = sprintf( _n('Month', '%d Months', $frequency_count, 'invoicing'), $frequency_count);
201
                break;
202
            case 'year' :
203
            case 'y' :
204
                $frequency = sprintf( _n('Year', '%d Years', $frequency_count, 'invoicing'), $frequency_count);
205
                break;
206
            default :
207
                $frequency = apply_filters( 'wpinv_recurring_subscription_frequency', $frequency, $period, $frequency_count );
208
                break;
209
        }
210
211
        return $frequency;
212
213
    }
214
215
    /**
216
     * Handles cancellation requests for a subscription
217
     *
218
     * @access      public
219
     * @since       1.0.0
220
     * @return      void
221
     */
222
    public function wpinv_process_cancellation( $data ) {
223
224
225
        if( empty( $data['sub_id'] ) ) {
226
            return;
227
        }
228
229
        if( ! is_user_logged_in() ) {
230
            return;
231
        }
232
233
        if( ! wp_verify_nonce( $data['_wpnonce'], 'wpinv-recurring-cancel' ) ) {
234
            wp_die( __( 'Error', 'invoicing' ), __( 'Nonce verification failed', 'invoicing' ), array( 'response' => 403 ) );
235
        }
236
237
        $data['sub_id'] = absint( $data['sub_id'] );
238
        $subscription   = new WPInv_Subscription( $data['sub_id'] );
239
240
        if( ! $subscription->can_cancel() ) {
241
            wp_die( __( 'Error', 'invoicing' ), __( 'This subscription cannot be cancelled', 'invoicing' ), array( 'response' => 403 ) );
242
        }
243
244
        try {
245
246
            do_action( 'wpinv_recurring_cancel_' . $subscription->gateway . '_subscription', $subscription, true );
247
248
            $subscription->cancel();
249
250
            if( is_admin() ) {
251
252
                wp_redirect( admin_url( 'admin.php?page=wpinv-subscriptions&wpinv-message=cancelled&id=' . $subscription->id ) );
253
                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...
254
255
            } else {
256
257
                $redirect = remove_query_arg( array( '_wpnonce', 'wpinv_action', 'sub_id' ), add_query_arg( array( 'wpinv-message' => 'cancelled' ) ) );
258
                $redirect = apply_filters( 'wpinv_recurring_cancellation_redirect', $redirect, $subscription );
259
                wp_safe_redirect( $redirect );
260
                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...
261
262
            }
263
264
        } catch ( Exception $e ) {
265
            wp_die( __( 'Error', 'invoicing' ), $e->getMessage(), array( 'response' => 403 ) );
266
        }
267
268
    }
269
270
    /**
271
     * Create subscription on checkout
272
     *
273
     * @access      public
274
     * @param       WPInv_Invoice $invoice
275
     * @since       1.0.0
276
     * @return      void
277
     */
278
    public function wpinv_checkout_add_subscription( $invoice, $invoice_data ) {
0 ignored issues
show
Unused Code introduced by
The parameter $invoice_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

278
    public function wpinv_checkout_add_subscription( $invoice, /** @scrutinizer ignore-unused */ $invoice_data ) {

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...
279
        if ( ! ( ! empty( $invoice->ID ) && $invoice->is_recurring() ) ) {
280
            return;
281
        }
282
283
        // Should we create a subscription for the invoice?
284
        if ( apply_filters( 'wpinv_skip_invoice_subscription_creation', false, $invoice ) ) {
285
            return;
286
        }
287
288
        $item               = $invoice->get_recurring( true );
289
        if ( empty( $item ) ) {
290
            return;
291
        }
292
293
        $invoice_date       = $invoice->get_invoice_date( false );
0 ignored issues
show
Deprecated Code introduced by
The function WPInv_Invoice::get_invoice_date() has been deprecated. ( Ignorable by Annotation )

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

293
        $invoice_date       = /** @scrutinizer ignore-deprecated */ $invoice->get_invoice_date( false );
Loading history...
294
        $status             = 'pending';
295
296
        $period             = $item->get_recurring_period( true );
297
        $interval           = $item->get_recurring_interval();
298
        $bill_times         = (int)$item->get_recurring_limit();
299
        $add_period         = $interval . ' ' . $period;
300
        $trial_period       = '';
301
302
        if ( $invoice->is_free_trial() ) {
0 ignored issues
show
Deprecated Code introduced by
The function WPInv_Invoice::is_free_trial() has been deprecated. ( Ignorable by Annotation )

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

302
        if ( /** @scrutinizer ignore-deprecated */ $invoice->is_free_trial() ) {
Loading history...
Bug introduced by
Are you sure the usage of $invoice->is_free_trial() targeting WPInv_Invoice::is_free_trial() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
303
            $status         = 'trialling';
304
305
            if ( $invoice->is_free_trial_from_discount() ) {
306
307
                $trial_period   = $item->get_recurring_period( true );
308
                $free_interval  = $item->get_recurring_interval();
309
310
            } else {
311
                $trial_period   = $item->get_trial_period( true );
312
                $free_interval  = $item->get_trial_interval();
313
            }
314
315
            $trial_period   = $free_interval . ' ' . $trial_period;
316
317
            $add_period     = $trial_period;
318
        }
319
320
        $expiration         = date_i18n( 'Y-m-d H:i:s', strtotime( '+' . $add_period  . ' 23:59:59', strtotime( $invoice_date ) ) );
321
322
        $args = array(
323
            'product_id'        => $item->ID,
324
            'customer_id'       => $invoice->user_id,
0 ignored issues
show
Bug Best Practice introduced by
The property user_id does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
325
            'parent_payment_id' => $invoice->ID,
326
            'status'            => $status,
327
            'frequency'         => $interval,
328
            'period'            => $period,
329
            'initial_amount'    => $invoice->get_total(),
330
            'recurring_amount'  => $invoice->get_recurring_details( 'total' ),
331
            'bill_times'        => $bill_times,
332
            'created'           => $invoice_date,
333
            'expiration'        => $expiration,
334
            'trial_period'      => $trial_period,
335
            'profile_id'        => '',
336
            'transaction_id'    => '',
337
        );
338
339
        $subscription = wpinv_get_subscription( $invoice );
340
341
        if ( empty( $subscription ) ) {
342
            $subscription = new WPInv_Subscription();
343
            $subscription->create( $args );
344
        }
345
        
346
        return $subscription;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $subscription returns the type WPInv_Subscription|boolean which is incompatible with the documented return type void.
Loading history...
347
    }
348
}
349