Issues (850)

Security Analysis    4 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection (1)
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (2)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (1)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/class-wpinv-subscriptions.php (6 issues)

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( 'wpinv_invoice_metabox_saved', array( $this, 'maybe_update_invoice_subscription' ), 5 );
33
        add_action( 'getpaid_checkout_invoice_updated', array( $this, 'maybe_update_invoice_subscription' ), 5 );
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->exists() ? $subscription : wpinv_get_invoice_subscription( $invoice );
63
    }
64
65
    /**
66
     * Deactivates the invoice subscription(s) whenever an invoice status changes.
67
     *
68
     * @param WPInv_Invoice $invoice
69
     */
70
    public function maybe_deactivate_invoice_subscription( $invoice ) {
71
72
        $subscriptions = getpaid_get_invoice_subscriptions( $invoice );
73
74
        if ( empty( $subscriptions ) ) {
75
            return;
76
        }
77
78
        if ( ! is_array( $subscriptions ) ) {
0 ignored issues
show
The condition is_array($subscriptions) is always false.
Loading history...
79
            $subscriptions = array( $subscriptions );
80
        }
81
82
        foreach ( $subscriptions as $subscription ) {
83
            if ( $subscription->is_active() ) {
84
                $subscription->set_status( 'pending' );
85
                $subscription->save();
86
            }
87
        }
88
89
    }
90
91
    /**
92
	 * Processes subscription status changes.
93
     *
94
     * @param WPInv_Subscription $subscription
95
     * @param string $from
96
     * @param string $to
97
	 */
98
    public function process_subscription_status_change( $subscription, $from, $to ) {
99
100
        $gateway = $subscription->get_gateway();
101
102
        if ( ! empty( $gateway ) ) {
103
            $gateway = sanitize_key( $gateway );
104
            $from    = sanitize_key( $from );
105
            $to      = sanitize_key( $to );
106
            do_action( "getpaid_{$gateway}_subscription_$to", $subscription, $from );
107
        }
108
109
    }
110
111
    /**
112
     * Get pretty subscription frequency
113
     *
114
     * @param $period
115
     * @param int $frequency_count The frequency of the period.
116
     * @deprecated
117
     * @return mixed|string|void
118
     */
119
    public static function wpinv_get_pretty_subscription_frequency( $period, $frequency_count = 1 ) {
120
        return getpaid_get_subscription_period_label( $period, $frequency_count );
121
    }
122
123
    /**
124
     * Handles cancellation requests for a subscription
125
     *
126
     * @access      public
127
     * @since       1.0.0
128
     * @return      void
129
     */
130
    public function user_cancel_single_subscription( $data ) {
131
132
        // Ensure there is a subscription to cancel.
133
        if ( empty( $data['subscription'] ) ) {
134
            return;
135
        }
136
137
        $subscription = new WPInv_Subscription( (int) $data['subscription'] );
138
139
        // Ensure that it exists and that it belongs to the current user.
140
        if ( ! $subscription->exists() || $subscription->get_customer_id() != get_current_user_id() ) {
141
            $notice = 'perm_cancel_subscription';
142
143
        // Can it be cancelled.
144
        } elseif ( ! $subscription->can_cancel() ) {
145
            $notice = 'cannot_cancel_subscription';
146
147
        // Cancel it.
148
        } else {
149
150
            $subscription->cancel();
151
            $notice = 'cancelled_subscription';
152
        }
153
154
        $redirect = array(
155
            'getpaid-action' => false,
156
            'getpaid-nonce'  => false,
157
            'wpinv-notice'   => $notice,
158
        );
159
160
        wp_safe_redirect( add_query_arg( $redirect ) );
161
        exit;
0 ignored issues
show
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...
162
163
    }
164
165
    /**
166
     * Creates a subscription(s) for an invoice.
167
     *
168
     * @access      public
169
     * @param       WPInv_Invoice $invoice
170
     * @since       1.0.0
171
     */
172
    public function maybe_create_invoice_subscription( $invoice ) {
173
        global $getpaid_subscriptions_skip_invoice_update;
174
175
        // Abort if it is not recurring.
176
        if ( ! $invoice->is_type( 'invoice' ) || $invoice->is_free() || ! $invoice->is_recurring() || $invoice->is_renewal() ) {
177
            return;
178
        }
179
180
        // Either group the subscriptions or only process a single suscription.
181
        if ( getpaid_should_group_subscriptions( $invoice ) ) {
182
183
            $subscription_groups = array();
184
            $is_first            = true;
185
186
            foreach ( getpaid_calculate_subscription_totals( $invoice ) as $group_key => $totals ) {
187
                $subscription_groups[ $group_key ] = $this->create_invoice_subscription_group( $totals, $invoice, 0, $is_first );
188
189
                if ( $is_first ) {
190
                    $getpaid_subscriptions_skip_invoice_update = true;
191
                    $invoice->set_subscription_id( $subscription_groups[ $group_key ]['subscription_id'] );
192
                    $invoice->save();
193
                    $getpaid_subscriptions_skip_invoice_update = false;
194
                }
195
196
                $is_first                          = false;
197
            }
198
199
            // Cache subscription groups.
200
            update_post_meta( $invoice->get_id(), 'getpaid_subscription_groups', $subscription_groups );
201
            return true;
202
203
        }
204
205
        $subscription = new WPInv_Subscription();
206
        return $this->update_invoice_subscription( $subscription, $invoice );
207
208
    }
209
210
    /**
211
     * Saves a new invoice subscription group.
212
     *
213
     * @access      public
214
     * @param       array $totals
215
     * @param       WPInv_Invoice $invoice
216
     * @param       int $subscription_id Current subscription id of the group.
217
     * @param       bool $is_first Whether or not this is the first subscription group for the invoice. In which case we'll add totals of non-recurring items.
218
     *
219
     * @since       2.3.0
220
     */
221
    public function create_invoice_subscription_group( $totals, $invoice, $subscription_id = 0, $is_first = false ) {
222
223
        $subscription  = new WPInv_Subscription( (int) $subscription_id );
224
        $initial_amt   = $totals['initial_total'];
225
        $recurring_amt = $totals['recurring_total'];
226
        $fees          = array();
227
228
        // Maybe add recurring fees.
229
        if ( $is_first ) {
230
231
            foreach ( $invoice->get_fees() as $i => $fee ) {
232
                if ( ! empty( $fee['recurring_fee'] ) ) {
233
                    $initial_amt   += wpinv_sanitize_amount( $fee['initial_fee'] );
234
                    $recurring_amt += wpinv_sanitize_amount( $fee['recurring_fee'] );
235
                    $fees[ $i ]       = $fee;
236
                }
237
            }
238
        }
239
240
        $subscription->set_customer_id( $invoice->get_user_id() );
241
        $subscription->set_parent_invoice_id( $invoice->get_id() );
242
        $subscription->set_initial_amount( $initial_amt );
243
        $subscription->set_recurring_amount( $recurring_amt );
244
        $subscription->set_date_created( current_time( 'mysql' ) );
245
        $subscription->set_status( $invoice->is_paid() ? 'active' : 'pending' );
246
        $subscription->set_product_id( $totals['item_id'] );
247
        $subscription->set_period( $totals['period'] );
248
        $subscription->set_frequency( $totals['interval'] );
249
        $subscription->set_bill_times( $totals['recurring_limit'] );
250
        $subscription->set_next_renewal_date( $totals['renews_on'] );
251
252
        // Trial periods.
253
        if ( ! empty( $totals['trialling'] ) ) {
254
            $subscription->set_trial_period( $totals['trialling'] );
255
            $subscription->set_status( 'trialling' );
256
257
        // If initial amount is free, treat it as a free trial even if the subscription item does not have a free trial.
258
        } elseif ( empty( $initial_amt ) ) {
259
            $subscription->set_trial_period( $totals['interval'] . ' ' . $totals['period'] );
260
            $subscription->set_status( 'trialling' );
261
        }
262
263
        $subscription->save();
264
265
        $totals['subscription_id'] = $subscription->get_id();
266
        $totals['fees']            = $fees;
267
268
        return $totals;
269
    }
270
271
    /**
272
     * (Maybe) Updates a subscription for an invoice.
273
     *
274
     * @access      public
275
     * @param       WPInv_Invoice $invoice
276
     * @since       1.0.19
277
     */
278
    public function maybe_update_invoice_subscription( $invoice ) {
279
        global $getpaid_subscriptions_skip_invoice_update;
280
281
        // Avoid infinite loops.
282
        if ( ! empty( $getpaid_subscriptions_skip_invoice_update ) ) {
283
            return;
284
        }
285
286
        // Do not process renewals.
287
        if ( $invoice->is_renewal() ) {
288
            return;
289
        }
290
291
        // Delete existing subscriptions if available and the invoice is not recurring.
292
        if ( ! $invoice->is_recurring() ) {
293
            $this->delete_invoice_subscriptions( $invoice );
294
            return;
295
        }
296
297
        // Fetch existing subscriptions.
298
        $subscriptions = getpaid_get_invoice_subscriptions( $invoice );
299
300
        // Create new ones if no existing subscriptions.
301
        if ( empty( $subscriptions ) ) {
302
            return $this->maybe_create_invoice_subscription( $invoice );
303
        }
304
305
        // Abort if an invoice is paid and already has a subscription.
306
        if ( $invoice->is_paid() || $invoice->is_refunded() ) {
307
            return;
308
        }
309
310
        $is_grouped   = is_array( $subscriptions );
311
        $should_group = getpaid_should_group_subscriptions( $invoice );
312
313
        // Ensure that the subscriptions are only grouped if there are more than 1 recurring items.
314
        if ( $is_grouped != $should_group ) {
315
            $this->delete_invoice_subscriptions( $invoice );
316
            delete_post_meta( $invoice->get_id(), 'getpaid_subscription_groups' );
317
            return $this->maybe_create_invoice_subscription( $invoice );
318
        }
319
320
        // If there is only one recurring item...
321
        if ( ! $is_grouped ) {
322
            return $this->update_invoice_subscription( $subscriptions, $invoice );
323
        }
324
325
        // Process subscription groups.
326
        $current_groups      = getpaid_get_invoice_subscription_groups( $invoice->get_id() );
327
        $subscription_groups = array();
328
        $is_first            = true;
329
330
        // Create new subscription groups.
331
        foreach ( getpaid_calculate_subscription_totals( $invoice ) as $group_key => $totals ) {
332
            $subscription_id                   = isset( $current_groups[ $group_key ] ) ? $current_groups[ $group_key ]['subscription_id'] : 0;
333
            $subscription_groups[ $group_key ] = $this->create_invoice_subscription_group( $totals, $invoice, $subscription_id, $is_first );
334
335
            if ( $is_first && $invoice->get_subscription_id() !== $subscription_groups[ $group_key ]['subscription_id'] ) {
336
                $getpaid_subscriptions_skip_invoice_update = true;
337
                $invoice->set_subscription_id( $subscription_groups[ $group_key ]['subscription_id'] );
338
                $invoice->save();
339
                $getpaid_subscriptions_skip_invoice_update = false;
340
            }
341
342
            $is_first                          = false;
343
        }
344
345
        // Delete non-existent subscription groups.
346
        foreach ( $current_groups as $group_key => $data ) {
347
            if ( ! isset( $subscription_groups[ $group_key ] ) ) {
348
                $subscription = new WPInv_Subscription( (int) $data['subscription_id'] );
349
350
                if ( $subscription->exists() ) {
351
                    $subscription->delete( true );
352
                }
353
}
354
        }
355
356
        // Cache subscription groups.
357
        update_post_meta( $invoice->get_id(), 'getpaid_subscription_groups', $subscription_groups );
358
        return true;
359
360
    }
361
362
    /**
363
     * Deletes invoice subscription(s).
364
     *
365
     * @param WPInv_Invoice $invoice
366
     */
367
    public function delete_invoice_subscriptions( $invoice ) {
368
369
        $subscriptions = getpaid_get_invoice_subscriptions( $invoice );
370
371
        if ( empty( $subscriptions ) ) {
372
            return;
373
        }
374
375
        if ( ! is_array( $subscriptions ) ) {
0 ignored issues
show
The condition is_array($subscriptions) is always false.
Loading history...
376
            $subscriptions = array( $subscriptions );
377
        }
378
379
        foreach ( $subscriptions as $subscription ) {
380
            $subscription->delete( true );
381
        }
382
383
    }
384
385
    /**
386
     * Updates a subscription for an invoice.
387
     *
388
     * @access      public
389
     * @param       WPInv_Subscription $subscription
390
     * @param       WPInv_Invoice $invoice
391
     * @since       1.0.19
392
     */
393
    public function update_invoice_subscription( $subscription, $invoice ) {
394
395
        // Delete the subscription if an invoice is free or nolonger recurring.
396
        if ( ! $invoice->is_type( 'invoice' ) || $invoice->is_free() || ! $invoice->is_recurring() ) {
397
            return $subscription->delete();
398
        }
399
400
        $subscription->set_customer_id( $invoice->get_user_id() );
401
        $subscription->set_parent_invoice_id( $invoice->get_id() );
402
        $subscription->set_initial_amount( $invoice->get_initial_total() );
403
        $subscription->set_recurring_amount( $invoice->get_recurring_total() );
404
        $subscription->set_date_created( current_time( 'mysql' ) );
405
        $subscription->set_status( $invoice->is_paid() ? 'active' : 'pending' );
406
407
        // Get the recurring item and abort if it does not exist.
408
        $subscription_item = $invoice->get_recurring( true );
409
        if ( ! $subscription_item->get_id() ) {
410
            $invoice->set_subscription_id( 0 );
411
            $invoice->save();
412
            return $subscription->delete();
413
        }
414
415
        $subscription->set_product_id( $subscription_item->get_id() );
416
        $subscription->set_period( $subscription_item->get_recurring_period( true ) );
417
        $subscription->set_frequency( $subscription_item->get_recurring_interval() );
418
        $subscription->set_bill_times( $subscription_item->get_recurring_limit() );
419
420
        // Calculate the next renewal date.
421
        $period       = $subscription_item->get_recurring_period( true );
422
        $interval     = $subscription_item->get_recurring_interval();
423
424
        // If the subscription item has a trial period...
425
        if ( $subscription_item->has_free_trial() ) {
426
            $period   = $subscription_item->get_trial_period( true );
427
            $interval = $subscription_item->get_trial_interval();
428
            $subscription->set_trial_period( $interval . ' ' . $period );
429
            $subscription->set_status( 'trialling' );
430
        }
431
432
        // If initial amount is free, treat it as a free trial even if the subscription item does not have a free trial.
433
        if ( $invoice->has_free_trial() ) {
434
            $subscription->set_trial_period( $interval . ' ' . $period );
435
            $subscription->set_status( 'trialling' );
436
        }
437
438
        // Calculate the next renewal date.
439
        $expiration = date( 'Y-m-d H:i:s', strtotime( "+$interval $period", strtotime( $subscription->get_date_created() ) ) );
440
441
        $subscription->set_next_renewal_date( $expiration );
442
        $subscription->save();
443
        $invoice->set_subscription_id( $subscription->get_id() );
444
        return $subscription->get_id();
445
446
    }
447
448
    /**
449
     * Fired when an admin updates a subscription via the single subscription single page.
450
     *
451
     * @param       array $data
452
     * @since       1.0.19
453
     */
454
    public function admin_update_single_subscription( $args ) {
455
456
        // Ensure the subscription exists and that a status has been given.
457
        if ( empty( $args['subscription_id'] ) ) {
458
            return;
459
        }
460
461
        // Retrieve the subscriptions.
462
        $subscription = new WPInv_Subscription( $args['subscription_id'] );
463
464
        if ( $subscription->get_id() ) {
465
466
            $subscription->set_props(
467
                array(
468
                    'status'       => isset( $args['subscription_status'] ) ? $args['subscription_status'] : null,
469
                    'profile_id'   => isset( $args['wpinv_subscription_profile_id'] ) ? $args['wpinv_subscription_profile_id'] : null,
470
                    'date_created' => ! empty( $args['wpinv_subscription_date_created'] ) ? $args['wpinv_subscription_date_created'] : null,
471
                    'expiration'   => ! empty( $args['wpinv_subscription_expiration'] ) ? $args['wpinv_subscription_expiration'] : null,
472
                    'bill_times'   => ! empty( $args['wpinv_subscription_max_bill_times'] ) ? $args['wpinv_subscription_max_bill_times'] : null,
473
                )
474
            );
475
476
            $changes = $subscription->get_changes();
477
478
            $subscription->save();
479
            getpaid_admin()->show_info( __( 'Subscription updated', 'invoicing' ) );
480
481
            do_action( 'getpaid_admin_updated_subscription', $subscription, $args, $changes );
482
        }
483
484
    }
485
486
    /**
487
     * Fired when an admin manually renews a subscription.
488
     *
489
     * @param       array $data
490
     * @since       1.0.19
491
     */
492
    public function admin_renew_single_subscription( $args ) {
493
494
        // Ensure the subscription exists and that a status has been given.
495
        if ( empty( $args['id'] ) ) {
496
            return;
497
        }
498
499
        // Retrieve the subscriptions.
500
        $subscription = new WPInv_Subscription( $args['id'] );
501
502
        if ( $subscription->get_id() ) {
503
504
            do_action( 'getpaid_admin_renew_subscription', $subscription );
505
506
            $args = array( 'transaction_id', $subscription->get_parent_invoice()->generate_key( 'renewal_' ) );
507
508
            if ( ! $subscription->add_payment( $args ) ) {
509
                getpaid_admin()->show_error( __( 'We are unable to renew this subscription as the parent invoice does not exist.', 'invoicing' ) );
510
            } else {
511
                $subscription->renew();
512
                getpaid_admin()->show_info( __( 'This subscription has been renewed and extended.', 'invoicing' ) );
513
            }
514
515
            wp_safe_redirect(
516
                add_query_arg(
517
                    array(
518
                        'getpaid-admin-action' => false,
519
                        'getpaid-nonce'        => false,
520
                    )
521
                )
522
            );
523
            exit;
0 ignored issues
show
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...
524
525
        }
526
527
    }
528
529
    /**
530
     * Fired when an admin manually deletes a subscription.
531
     *
532
     * @param       array $data
533
     * @since       1.0.19
534
     */
535
    public function admin_delete_single_subscription( $args ) {
536
537
        // Ensure the subscription exists and that a status has been given.
538
        if ( empty( $args['id'] ) ) {
539
            return;
540
        }
541
542
        // Retrieve the subscriptions.
543
        $subscription = new WPInv_Subscription( $args['id'] );
544
545
        if ( $subscription->delete() ) {
546
            getpaid_admin()->show_info( __( 'This subscription has been deleted.', 'invoicing' ) );
547
        } else {
548
            getpaid_admin()->show_error( __( 'We are unable to delete this subscription. Please try again.', 'invoicing' ) );
549
        }
550
551
        $redirected = wp_safe_redirect(
552
            add_query_arg(
553
                array(
554
                    'getpaid-admin-action' => false,
555
                    'getpaid-nonce'        => false,
556
                    'id'                   => false,
557
                )
558
            )
559
        );
560
561
        if ( $redirected ) {
562
            exit;
0 ignored issues
show
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...
563
        }
564
565
    }
566
567
    /**
568
     * Filters the invoice line items actions.
569
     *
570
     * @param array actions
0 ignored issues
show
The type actions was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
571
     * @param WPInv_Item $item
572
     * @param WPInv_Invoice $invoice
573
     */
574
    public function filter_invoice_line_item_actions( $actions, $item, $invoice ) {
575
576
        // Abort if this invoice uses subscription groups.
577
        $subscriptions = getpaid_get_invoice_subscriptions( $invoice );
578
        if ( ! $invoice->is_recurring() || ! is_object( $subscriptions ) ) {
579
            return $actions;
580
        }
581
582
        // Fetch item subscription.
583
        $args  = array(
584
            'invoice_in'  => $invoice->is_parent() ? $invoice->get_id() : $invoice->get_parent_id(),
585
            'product_in'  => $item->get_id(),
586
            'number'      => 1,
587
            'count_total' => false,
588
            'fields'      => 'id',
589
        );
590
591
        $subscription = new GetPaid_Subscriptions_Query( $args );
592
        $subscription = $subscription->get_results();
593
594
        // In case we found a match...
595
        if ( ! empty( $subscription ) ) {
596
            $url                     = esc_url( add_query_arg( 'subscription', (int) $subscription[0], get_permalink( (int) wpinv_get_option( 'invoice_subscription_page' ) ) ) );
597
            $actions['subscription'] = "<a href='$url' class='text-decoration-none'>" . __( 'Manage Subscription', 'invoicing' ) . '</a>';
598
        }
599
600
        return $actions;
601
602
    }
603
604
}
605