Passed
Push — master ( 568391...260ce8 )
by Brian
05:13
created

wpinv_get_pretty_subscription_frequency()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 2
rs 10
cc 1
nc 1
nop 2
1
<?php
2
/**
3
 * Main Subscriptions class.
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
/**
9
 * Main Subscriptions class.
10
 *
11
 */
12
class WPInv_Subscriptions {
13
14
    /**
15
	 * Class constructor.
16
	 */
17
    public function __construct(){
18
19
        // Fire gateway specific hooks when a subscription changes.
20
        add_action( 'getpaid_subscription_status_changed', array( $this, 'process_subscription_status_change' ), 10, 3 );
21
22
        // De-activate a subscription whenever the invoice changes payment statuses.
23
        add_action( 'getpaid_invoice_status_wpi-refunded', array( $this, 'maybe_deactivate_invoice_subscription' ), 20 );
24
        add_action( 'getpaid_invoice_status_wpi-failed', array( $this, 'maybe_deactivate_invoice_subscription' ), 20 );
25
        add_action( 'getpaid_invoice_status_wpi-cancelled', array( $this, 'maybe_deactivate_invoice_subscription' ), 20 );
26
        add_action( 'getpaid_invoice_status_wpi-pending', array( $this, 'maybe_deactivate_invoice_subscription' ), 20 );
27
28
        // Handles subscription cancelations.
29
        add_action( 'getpaid_authenticated_action_subscription_cancel', array( $this, 'user_cancel_single_subscription' ) );
30
31
        // Create a subscription whenever an invoice is created, (and update it when it is updated).
32
        add_action( 'getpaid_new_invoice', array( $this, 'maybe_create_invoice_subscription' ) );
33
        add_action( 'getpaid_update_invoice', array( $this, 'maybe_update_invoice_subscription' ) );
34
35
        // Handles admin subscription update actions.
36
        add_action( 'getpaid_authenticated_admin_action_update_single_subscription', array( $this, 'admin_update_single_subscription' ) );
37
        add_action( 'getpaid_authenticated_admin_action_subscription_manual_renew', array( $this, 'admin_renew_single_subscription' ) );
38
        add_action( 'getpaid_authenticated_admin_action_subscription_manual_delete', array( $this, 'admin_delete_single_subscription' ) );
39
40
        // Filter invoice item row actions.
41
        add_action( 'getpaid-invoice-page-line-item-actions', array( $this, 'filter_invoice_line_item_actions' ), 10, 3 );
42
    }
43
44
    /**
45
     * Returns an invoice's subscription.
46
     *
47
     * @param WPInv_Invoice $invoice
48
     * @return WPInv_Subscription|bool
49
     */
50
    public function get_invoice_subscription( $invoice ) {
51
        $subscription_id = $invoice->get_subscription_id();
52
53
        // Fallback to the parent invoice if the child invoice has no subscription id.
54
        if ( empty( $subscription_id && $invoice->is_renewal() ) ) {
55
            $subscription_id = $invoice->get_parent_payment()->get_subscription_id();
56
        }
57
58
        // Fetch the subscription.
59
        $subscription = new WPInv_Subscription( $subscription_id );
60
61
        // Return subscription or use a fallback for backwards compatibility.
62
        return $subscription->get_id() ? $subscription : wpinv_get_subscription( $invoice );
63
    }
64
65
    /**
66
     * Deactivates the invoice subscription whenever an invoice status changes.
67
     * 
68
     * @param WPInv_Invoice $invoice
69
     */
70
    public function maybe_deactivate_invoice_subscription( $invoice ) {
71
72
        $subscription = $this->get_invoice_subscription( $invoice );
73
74
        // Abort if the subscription is missing or not active.
75
        if ( empty( $subscription ) || ! $subscription->is_active() ) {
76
            return;
77
        }
78
79
        $subscription->set_status( 'pending' );
80
        $subscription->save();
81
82
    }
83
84
    /**
85
	 * Processes subscription status changes.
86
     * 
87
     * @param WPInv_Subscription $subscription
88
     * @param string $from
89
     * @param string $to
90
	 */
91
    public function process_subscription_status_change( $subscription, $from, $to ) {
92
93
        $gateway = $subscription->get_gateway();
94
95
        if ( ! empty( $gateway ) ) {
96
            $gateway = sanitize_key( $gateway );
97
            $from    = sanitize_key( $from );
98
            $to      = sanitize_key( $to );
99
            do_action( "getpaid_{$gateway}subscription_$to", $subscription, $from );
100
        }
101
102
    }
103
104
    /**
105
     * Get pretty subscription frequency
106
     *
107
     * @param $period
108
     * @param int $frequency_count The frequency of the period.
109
     * @deprecated
110
     * @return mixed|string|void
111
     */
112
    public static function wpinv_get_pretty_subscription_frequency( $period, $frequency_count = 1 ) {
113
        return getpaid_get_subscription_period_label( $period, $frequency_count );
114
    }
115
116
    /**
117
     * Handles cancellation requests for a subscription
118
     *
119
     * @access      public
120
     * @since       1.0.0
121
     * @return      void
122
     */
123
    public function user_cancel_single_subscription( $data ) {
124
125
        // Ensure there is a subscription to cancel.
126
        if ( empty( $data['subscription'] ) ) {
127
            return;
128
        }
129
130
        $subscription = new WPInv_Subscription( (int) $data['subscription'] );
131
132
        // Ensure that it exists and that it belongs to the current user.
133
        if ( ! $subscription->get_id() || $subscription->get_customer_id() != get_current_user_id() ) {
134
            wpinv_set_error( 'invalid_subscription', __( 'You do not have permission to cancel this subscription', 'invoicing' ) );
135
136
        // Can it be cancelled.
137
        } else if ( ! $subscription->can_cancel() ) {
138
            wpinv_set_error( 'cannot_cancel', __( 'This subscription cannot be cancelled as it is not active.', 'invoicing' ) );
139
            
140
141
        // Cancel it.
142
        } else {
143
144
            $subscription->cancel();
145
            wpinv_set_error( 'cancelled', __( 'This subscription has been cancelled.', 'invoicing' ), 'info' );
146
        }
147
148
        $redirect = add_query_arg(
149
            array(
150
                'getpaid-action' => false,
151
                'getpaid-nonce'  => false,
152
            )
153
        );
154
155
        wp_safe_redirect( esc_url( $redirect ) );
156
        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...
157
158
    }
159
160
    /**
161
     * Creates a subscription for an invoice.
162
     *
163
     * @access      public
164
     * @param       WPInv_Invoice $invoice
165
     * @since       1.0.0
166
     */
167
    public function maybe_create_invoice_subscription( $invoice ) {
168
169
        // Abort if it is not recurring.
170
        if ( $invoice->is_free() || ! $invoice->is_recurring() || $invoice->is_renewal() ) {
171
            return;
172
        }
173
174
        $subscription = new WPInv_Subscription();
175
        return $this->update_invoice_subscription( $subscription, $invoice );
176
177
    }
178
179
    /**
180
     * (Maybe) Updates a subscription for an invoice.
181
     *
182
     * @access      public
183
     * @param       WPInv_Invoice $invoice
184
     * @since       1.0.19
185
     */
186
    public function maybe_update_invoice_subscription( $invoice ) {
187
188
        // Do not process renewals.
189
        if ( $invoice->is_renewal() ) {
190
            return;
191
        }
192
193
        // (Maybe) create a new subscription.
194
        if ( ! $invoice->get_subscription_id() ) {
195
            return $this->maybe_create_invoice_subscription( $invoice );
196
        }
197
198
        $subscription = new WPInv_Subscription( $invoice->get_subscription_id() );
199
200
        // In case the subscription was deleted...
201
        if ( ! $subscription->get_id() ) {
202
            return $this->maybe_create_invoice_subscription( $invoice );
203
        }
204
205
        // Abort if an invoice is paid and already has a subscription.
206
        if ( $invoice->is_paid() || $invoice->is_refunded() ) {
207
            return;
208
        }
209
210
        return $this->update_invoice_subscription( $subscription, $invoice );
211
212
    }
213
214
    /**
215
     * Updates a subscription for an invoice.
216
     *
217
     * @access      public
218
     * @param       WPInv_Subscription $subscription
219
     * @param       WPInv_Invoice $invoice
220
     * @since       1.0.19
221
     */
222
    public function update_invoice_subscription( $subscription, $invoice ) {
223
224
        // Delete the subscription if an invoice is free or nolonger recurring.
225
        if ( $invoice->is_free() || ! $invoice->is_recurring() ) {
226
            return $subscription->delete();
227
        }
228
229
        $subscription->set_customer_id( $invoice->get_customer_id() );
230
        $subscription->set_parent_invoice_id( $invoice->get_id() );
231
        $subscription->set_initial_amount( $invoice->get_initial_total() );
232
        $subscription->set_recurring_amount( $invoice->get_recurring_total() );
233
        $subscription->set_date_created( current_time( 'mysql' ) );
234
        $subscription->set_status( $invoice->is_paid() ? 'active' : 'pending' );
235
236
        // Get the recurring item and abort if it does not exist.
237
        $subscription_item = $invoice->get_recurring( true );
238
        if ( ! $subscription_item->get_id() ) {
239
            $invoice->set_subscription_id(0);
240
            $invoice->save();
241
            return $subscription->delete();
242
        }
243
244
        $subscription->set_product_id( $subscription_item->get_id() );
245
        $subscription->set_period( $subscription_item->get_recurring_period( true ) );
246
        $subscription->set_frequency( $subscription_item->get_recurring_interval() );
247
        $subscription->set_bill_times( $subscription_item->get_recurring_limit() );
248
249
        // Calculate the next renewal date.
250
        $period       = $subscription_item->get_recurring_period( true );
251
        $interval     = $subscription_item->get_recurring_interval();
252
253
        // If the subscription item has a trial period...
254
        if ( $subscription_item->has_free_trial() ) {
255
            $period   = $subscription_item->get_trial_period( true );
256
            $interval = $subscription_item->get_trial_interval();
257
            $subscription->set_trial_period( $interval . ' ' . $period );
258
            $subscription->set_status( 'trialling' );
259
        }
260
261
        // If initial amount is free, treat it as a free trial even if the subscription item does not have a free trial.
262
        if ( $invoice->has_free_trial() ) {
263
            $subscription->set_trial_period( $interval . ' ' . $period );
264
            $subscription->set_status( 'trialling' );
265
        }
266
267
        // Calculate the next renewal date.
268
        $expiration = date( 'Y-m-d H:i:s', strtotime( "+$interval $period", strtotime( $subscription->get_date_created() ) ) );
269
270
        $subscription->set_next_renewal_date( $expiration );
271
        return $subscription->save();
272
273
    }
274
275
    /**
276
     * Fired when an admin updates a subscription via the single subscription single page.
277
     *
278
     * @param       array $data
279
     * @since       1.0.19
280
     */
281
    public function admin_update_single_subscription( $args ) {
282
283
        // Ensure the subscription exists and that a status has been given.
284
        if ( empty( $args['subscription_id'] ) || empty( $args['subscription_status'] ) ) {
285
            return;
286
        }
287
288
        // Retrieve the subscriptions.
289
        $subscription = new WPInv_Subscription( $args['subscription_id'] );
290
291
        if ( $subscription->get_id() ) {
292
293
            $subscription->set_status( $args['subscription_status'] );
294
            $subscription->save();
295
            getpaid_admin()->show_info( __( 'Your changes have been saved', 'invoicing' ) );
296
297
        }
298
299
    }
300
301
    /**
302
     * Fired when an admin manually renews a subscription.
303
     *
304
     * @param       array $data
305
     * @since       1.0.19
306
     */
307
    public function admin_renew_single_subscription( $args ) {
308
309
        // Ensure the subscription exists and that a status has been given.
310
        if ( empty( $args['id'] ) ) {
311
            return;
312
        }
313
314
        // Retrieve the subscriptions.
315
        $subscription = new WPInv_Subscription( $args['id'] );
316
317
        if ( $subscription->get_id() ) {
318
319
            $args = array( 'transaction_id', $subscription->get_parent_invoice()->generate_key( 'renewal_' ) );
320
321
            if ( $subscription->add_payment( $args ) ) {
322
                $subscription->renew();
323
                getpaid_admin()->show_info( __( 'This subscription has been renewed and extended.', 'invoicing' ) );
324
            } else {
325
                getpaid_admin()->show_error( __( 'We are unable to renew this subscription as the parent invoice does not exist.', 'invoicing' ) );
326
            }
327
    
328
            wp_safe_redirect(
329
                add_query_arg(
330
                    array(
331
                        'getpaid-admin-action' => false,
332
                        'getpaid-nonce'        => false,
333
                    )
334
                )
335
            );
336
            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...
337
338
        }
339
340
    }
341
342
    /**
343
     * Fired when an admin manually deletes a subscription.
344
     *
345
     * @param       array $data
346
     * @since       1.0.19
347
     */
348
    public function admin_delete_single_subscription( $args ) {
349
350
        // Ensure the subscription exists and that a status has been given.
351
        if ( empty( $args['id'] ) ) {
352
            return;
353
        }
354
355
        // Retrieve the subscriptions.
356
        $subscription = new WPInv_Subscription( $args['id'] );
357
358
        if ( $subscription->delete() ) {
359
            getpaid_admin()->show_info( __( 'This subscription has been deleted.', 'invoicing' ) );
360
        } else {
361
            getpaid_admin()->show_error( __( 'We are unable to delete this subscription. Please try again.', 'invoicing' ) );
362
        }
363
    
364
        $redirected = wp_safe_redirect(
365
            add_query_arg(
366
                array(
367
                    'getpaid-admin-action' => false,
368
                    'getpaid-nonce'        => false,
369
                    'id'                   => false,
370
                )
371
            )
372
        );
373
374
        if ( $redirected ) {
375
            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...
376
        }
377
378
    }
379
380
    /**
381
     * Filters the invoice line items actions.
382
     *
383
     * @param array actions
384
     * @param WPInv_Item $item
385
     * @param WPInv_Invoice $invoice
386
     */
387
    public function filter_invoice_line_item_actions( $actions, $item, $invoice ) {
388
389
        // Fetch item subscription.
390
        $args  = array(
391
            'invoice_in'  => $invoice->is_parent() ? $invoice->get_id() : $invoice->get_parent_id(),
392
            'item_in'     => $item->get_id(),
393
            'number'      => 1,
394
            'count_total' => false,
395
            'fields'      => 'id',
396
        );
397
398
        $subscription = new GetPaid_Subscriptions_Query( $args );
399
        $subscription = $subscription->get_results();
400
401
        // In case we found a match...
402
        if ( ! empty( $subscription ) ) {
403
            $url                     = esc_url( add_query_arg( 'subscription', (int) $subscription[0], get_permalink( (int) wpinv_get_option( 'invoice_subscription_page' ) ) ) );
404
            $actions['subscription'] = "<a href='$url' class='text-decoration-none'>" . __( 'Manage Subscription', 'getpaid-license-manager' ) . '</a>';
405
        }
406
407
        return $actions;
408
409
    }
410
411
}
412