Passed
Pull Request — master (#116)
by
unknown
03:57
created

WPInv_Subscriptions::instance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 0
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
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();
51
        self::actions();
52
        self::filters();
0 ignored issues
show
Unused Code introduced by
The call to the method WPInv_Subscriptions::filters() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
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' ), 10 );
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( 'wpi-pending_wpi_invoice', array( $this, 'wpinv_add_update_subscription' ), 10, 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
            'manage_invoicing',
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
        $frequency = '';
187
        //Format period details
188
        switch ( $period ) {
189
            case 'day' :
190
                $frequency = sprintf( _n('%d Day', '%d Days', $frequency_count, 'invoicing'), $frequency_count);
191
                break;
192
            case 'week' :
193
                $frequency = sprintf( _n('%d Week', '%d Weeks', $frequency_count, 'invoicing'), $frequency_count);
194
                break;
195
            case 'month' :
196
                $frequency = sprintf( _n('%d Month', '%d Months', $frequency_count, 'invoicing'), $frequency_count);
197
                break;
198
            case 'year' :
199
                $frequency = sprintf( _n('%d Year', '%d Years', $frequency_count, 'invoicing'), $frequency_count);
200
                break;
201
            default :
202
                $frequency = apply_filters( 'wpinv_recurring_subscription_frequency', $frequency, $period, $frequency_count );
203
                break;
204
        }
205
206
        return $frequency;
207
208
    }
209
210
    /**
211
     * Handles cancellation requests for a subscription
212
     *
213
     * @access      public
214
     * @since       1.0.0
215
     * @return      void
216
     */
217
    public function wpinv_process_cancellation( $data ) {
218
219
220
        if( empty( $data['sub_id'] ) ) {
221
            return;
222
        }
223
224
        if( ! is_user_logged_in() ) {
225
            return;
226
        }
227
228
        if( ! wp_verify_nonce( $data['_wpnonce'], 'wpinv-recurring-cancel' ) ) {
229
            wp_die( __( 'Error', 'invoicing' ), __( 'Nonce verification failed', 'invoicing' ), array( 'response' => 403 ) );
230
        }
231
232
        $data['sub_id'] = absint( $data['sub_id'] );
233
        $subscription   = new WPInv_Subscription( $data['sub_id'] );
234
235
        if( ! $subscription->can_cancel() ) {
236
            wp_die( __( 'Error', 'invoicing' ), __( 'This subscription cannot be cancelled', 'invoicing' ), array( 'response' => 403 ) );
237
        }
238
239
        try {
240
241
            do_action( 'wpinv_recurring_cancel_' . $subscription->gateway . '_subscription', $subscription, true );
242
243
            $subscription->cancel();
244
245
            if( is_admin() ) {
246
247
                wp_redirect( admin_url( 'admin.php?page=wpinv-subscriptions&wpinv-message=cancelled&id=' . $subscription->id ) );
248
                exit;
249
250
            } else {
251
252
                $redirect = remove_query_arg( array( '_wpnonce', 'wpinv_action', 'sub_id' ), add_query_arg( array( 'wpinv-message' => 'cancelled' ) ) );
253
                $redirect = apply_filters( 'wpinv_recurring_cancellation_redirect', $redirect, $subscription );
254
                wp_safe_redirect( $redirect );
255
                exit;
256
257
            }
258
259
        } catch ( Exception $e ) {
260
            wp_die( __( 'Error', 'invoicing' ), $e->getMessage(), array( 'response' => 403 ) );
261
        }
262
263
    }
264
265
    /**
266
     * Create/Update subscription on invoice created/updated
267
     *
268
     * @access      public
269
     * @since       1.0.0
270
     * @return      void
271
     */
272
    public function wpinv_add_update_subscription( $invoice_id, $invoice ) {
0 ignored issues
show
Unused Code introduced by
The parameter $invoice is not used and could be removed.

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

Loading history...
273
274
        remove_action( 'save_post', __FUNCTION__ );
275
276
        if(empty($invoice_id) || 'wpi_invoice' != get_post_type($invoice_id)){
277
            return;
278
        }
279
280
        if ( defined( 'DOING_AUTOSAVE' ) ) {
281
            return;
282
        }
283
284
        if ( ( defined( 'DOING_AJAX') && DOING_AJAX ) || isset( $_REQUEST['bulk_edit'] ) ) {
285
            return;
286
        }
287
288
        $invoice_obj = new WPInv_Invoice($invoice_id);
289
290
        if ( !$invoice_obj->is_recurring() ) {
291
            return;
292
        }
293
294
        $item_id = $invoice_obj->get_recurring();
295
        $item = new WPInv_Item( $item_id );
296
297
        $period             = $item->get_recurring_period(true);
298
        $interval           = $item->get_recurring_interval();
299
        $bill_times         = (int)$item->get_recurring_limit();
300
        $initial_amount     = wpinv_sanitize_amount( $invoice_obj->get_total(), 2 );
301
        $recurring_amount   = wpinv_sanitize_amount( $invoice_obj->get_recurring_details( 'total' ), 2 );
302
        $status             = 'pending';
303
        $expiration         = date( 'Y-m-d H:i:s', strtotime( '+' . $interval . ' ' . $period  . ' 23:59:59', current_time( 'timestamp' ) ) );
304
305
306
        $trial_period = '';
307
        if ( $invoice_obj->is_free_trial() && $item->has_free_trial() ) {
308
            $trial_period       = $item->get_trial_period(true);
309
            $free_trial         = $item->get_free_trial();
310
            $trial_period       = ! empty( $invoice_obj->is_free_trial() ) ? $free_trial . ' ' . $trial_period : '';
311
            $expiration         = date( 'Y-m-d H:i:s', strtotime( '+' . $trial_period . ' 23:59:59', current_time( 'timestamp' ) ) );
312
            $status = 'trialling';
313
        }
314
315
        $args = array(
316
            'product_id'        => $item_id,
317
            'customer_id'       => $invoice_obj->user_id,
318
            'parent_payment_id' => $invoice_obj->ID,
319
            'status'            => $status,
320
            'frequency'         => $interval,
321
            'period'            => $period,
322
            'initial_amount'    => $initial_amount,
323
            'recurring_amount'  => $recurring_amount,
324
            'bill_times'        => $bill_times,
325
            'created'           => date( 'Y-m-d H:i:s' ),
326
            'expiration'        => $expiration,
327
            'trial_period'      => $trial_period,
328
            'profile_id'        => '',
329
            'transaction_id'    => '',
330
        );
331
332
        $subs_db      = new WPInv_Subscriptions_DB;
333
        $subs         = $subs_db->get_subscriptions( array( 'parent_payment_id' => $invoice_obj->ID, 'number' => 1 ) );
334
        $subscription = reset( $subs );
335
336
        if( !$subscription || $subscription->id <= 0 ) {
337
338
            $subscription = new WPInv_Subscription();
339
            $subscription->create( $args );
340
341
        }
342
343
    }
344
}