Test Failed
Push — travis/4010 ( cd7197 )
by Ravinder
12:19
created

Give_Stripe_Webhooks::process()   C

Complexity

Conditions 12
Paths 43

Size

Total Lines 88

Duplication

Lines 25
Ratio 28.41 %

Importance

Changes 0
Metric Value
cc 12
nc 43
nop 1
dl 25
loc 88
rs 5.8351
c 0
b 0
f 0

How to fix   Long Method    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
 * Give - Stripe Core | Process Webhooks
4
 *
5
 * @since 2.5.0
6
 *
7
 * @package    Give
8
 * @subpackage Stripe Core
9
 * @copyright  Copyright (c) 2019, GiveWP
10
 * @license    https://opensource.org/licenses/gpl-license GNU Public License
11
 */
12
13
// Exit if accessed directly.
14
if ( ! defined( 'ABSPATH' ) ) {
15
	exit;
16
}
17
18
if ( ! class_exists( 'Give_Stripe_Webhooks' ) ) {
19
20
	/**
21
	 * Class Give_Stripe_Webhooks
22
	 *
23
	 * @since 2.5.0
24
	 */
25
	class Give_Stripe_Webhooks {
26
27
		/**
28
		 * Stripe Gateway
29
		 *
30
		 * @since  2.5.0
31
		 * @access public
32
		 *
33
		 * @var $stripe_gateway
34
		 */
35
		public $stripe_gateway;
36
37
		/**
38
		 * Give_Stripe_Webhooks constructor.
39
		 *
40
		 * @since 2.5.0
41
		 */
42
		public function __construct() {
43
44
			$this->stripe_gateway = new Give_Stripe_Gateway();
45
46
			add_action( 'init', array( $this, 'listen' ) );
47
		}
48
49
		/**
50
		 * Listen for Stripe events.
51
		 *
52
		 * @access public
53
		 * @since  2.5.0
54
		 *
55
		 * @return void
56
		 */
57
		public function listen() {
58
59
			$give_listener = give_clean( filter_input( INPUT_GET, 'give-listener' ) );
60
61
			// Must be a stripe listener to proceed.
62
			if ( ! isset( $give_listener ) || 'stripe' !== $give_listener ) {
63
				return;
64
			}
65
66
			// Get the Stripe SDK autoloader.
67
			require_once GIVE_PLUGIN_DIR . 'vendor/autoload.php';
68
69
			$this->stripe_gateway->set_api_key();
70
			$this->stripe_gateway->set_api_version();
71
72
			// Retrieve the request's body and parse it as JSON.
73
			$body  = @file_get_contents( 'php://input' );
0 ignored issues
show
Coding Style introduced by
Silencing errors is discouraged
Loading history...
introduced by
file_get_contents is highly discouraged, please use wpcom_vip_file_get_contents() instead.
Loading history...
74
			$event = json_decode( $body );
75
76
			$processed_event = $this->process( $event );
77
78
			if ( false === $processed_event ) {
79
				$message = __( 'Something went wrong with processing the payment gateway event.', 'give' );
80
			} else {
81
				$message = sprintf(
82
					/* translators: 1. Processing result. */
83
					__( 'Processed event: %s', 'give' ),
84
					$result
85
				);
86
			}
87
88
			give_stripe_record_log(
89
				__( 'Stripe - Webhook Received', 'give' ),
90
				sprintf(
91
					/* translators: 1. Event ID 2. Event Type 3. Message */
92
					__( 'Webhook received with ID %1$s and TYPE %2$s which processed and returned a message %3$s.', 'give' ),
93
					$event_json->id,
94
					$event_json->type,
95
					$message
96
				)
97
			);
98
99
			status_header( 200 );
100
			exit( $message );
101
		}
102
103
		/**
104
		 * Process Stripe Webhooks.
105
		 *
106
		 * @since  2.5.0
107
		 * @access public
108
		 *
109
		 * @param \Stripe\Event $event_json Stripe Event.
110
		 */
111
		public function process( $event_json ) {
112
113
			// Next, proceed with additional webhooks.
114
			if ( isset( $event_json->id ) ) {
115
116
				status_header( 200 );
117
118
				try {
119
120
					$event = \Stripe\Event::retrieve( $event_json->id );
121
122
					// Update time of webhook received whenever the event is retrieved.
123
					give_update_option( 'give_stripe_last_webhook_received_timestamp', current_time( 'timestamp', 1 ) );
124
125
				} catch ( \Stripe\Error\Authentication $e ) {
126
127
					if ( strpos( $e->getMessage(), 'Platform access may have been revoked' ) !== false ) {
0 ignored issues
show
introduced by
Found "!== false". Use Yoda Condition checks, you must
Loading history...
128
						give_stripe_connect_delete_options();
129
					}
130
				} catch ( Exception $e ) {
131
					die( 'Invalid event ID' );
132
				}
133
134
				// Bailout, if event type doesn't exists.
135
				if ( empty( $event->type ) ) {
136
					return false;
137
				}
138
139
				switch ( $event->type ) {
140
141 View Code Duplication
					case 'payment_intent.succeeded':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
142
						$intent = $event->data->object;
143
144
						if ( 'succeeded' === $intent->status ) {
145
							$donation_id = give_stripe_get_donation_id_by( $intent->id, 'intent_id' );
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $donation_id is correct as give_stripe_get_donation...ntent->id, 'intent_id') (which targets give_stripe_get_donation_id_by()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

Loading history...
146
147
							// Update payment status to donation.
148
							give_update_payment_status( $donation_id, 'publish' );
149
150
							// Insert donation note to inform admin that charge succeeded.
151
							give_insert_payment_note( $donation_id, __( 'Charge succeeded in Stripe.', 'give' ) );
152
						}
153
154
						break;
155
156 View Code Duplication
					case 'payment_intent.payment_failed':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
157
							$intent      = $event->data->object;
158
							$donation_id = give_stripe_get_donation_id_by( $intent->id, 'intent_id' );
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $donation_id is correct as give_stripe_get_donation...ntent->id, 'intent_id') (which targets give_stripe_get_donation_id_by()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

Loading history...
159
160
							// Update payment status to donation.
161
							give_update_payment_status( $donation_id, 'failed' );
162
163
							// Insert donation note to inform admin that charge succeeded.
164
							give_insert_payment_note( $donation_id, __( 'Charge failed in Stripe.', 'give' ) );
165
166
						break;
167
168
					case 'charge.refunded':
169
						global $wpdb;
170
171
						$charge = $event->data->object;
172
173
						if ( $charge->refunded ) {
174
175
							$payment_id = $wpdb->get_var( $wpdb->prepare( "SELECT donation_id FROM {$wpdb->donationmeta} WHERE meta_key = '_give_payment_transaction_id' AND meta_value = %s LIMIT 1", $charge->id ) );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
176
177
							if ( $payment_id ) {
178
179
								give_update_payment_status( $payment_id, 'refunded' );
180
								give_insert_payment_note( $payment_id, __( 'Charge refunded in Stripe.', 'give' ) );
181
182
							}
183
						}
184
185
						break;
186
				}
187
188
				do_action( 'give_stripe_event_' . $event->type, $event );
189
190
				return $event->type;
191
192
			} else {
193
				status_header( 500 );
194
				// Something went wrong outside of Stripe.
195
				give_record_gateway_error( __( 'Stripe Error', 'give' ), sprintf( __( 'An error occurred while processing a webhook.', 'give' ) ) );
196
				die( '-1' ); // Failed.
197
			} // End if().
198
		}
199
	}
200
}
201
202
new Give_Stripe_Webhooks();
203