Completed
Push — master ( a5b3f7...f4924c )
by Roy
02:22
created

WC_Stripe_Customer::get_cards()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 8.7624
c 0
b 0
f 0
cc 5
eloc 12
nc 4
nop 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
/**
7
 * WC_Stripe_Customer class.
8
 *
9
 * Represents a Stripe Customer.
10
 */
11
class WC_Stripe_Customer {
12
13
	/**
14
	 * Stripe customer ID
15
	 * @var string
16
	 */
17
	private $id = '';
18
19
	/**
20
	 * WP User ID
21
	 * @var integer
22
	 */
23
	private $user_id = 0;
24
25
	/**
26
	 * Data from API
27
	 * @var array
28
	 */
29
	private $customer_data = array();
30
31
	/**
32
	 * Constructor
33
	 * @param integer $user_id
34
	 */
35
	public function __construct( $user_id = 0 ) {
36
		if ( $user_id ) {
37
			$this->set_user_id( $user_id );
38
			$this->set_id( get_user_meta( $user_id, '_stripe_customer_id', true ) );
39
		}
40
	}
41
42
	/**
43
	 * Get Stripe customer ID.
44
	 * @return string
45
	 */
46
	public function get_id() {
47
		return $this->id;
48
	}
49
50
	/**
51
	 * Set Stripe customer ID.
52
	 * @param [type] $id [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
53
	 */
54
	public function set_id( $id ) {
55
		$this->id = wc_clean( $id );
56
	}
57
58
	/**
59
	 * User ID in WordPress.
60
	 * @return int
61
	 */
62
	public function get_user_id() {
63
		return absint( $this->user_id );
64
	}
65
66
	/**
67
	 * Set User ID used by WordPress.
68
	 * @param int $user_id
69
	 */
70
	public function set_user_id( $user_id ) {
71
		$this->user_id = absint( $user_id );
72
	}
73
74
	/**
75
	 * Get user object.
76
	 * @return WP_User
77
	 */
78
	protected function get_user() {
79
		return $this->get_user_id() ? get_user_by( 'id', $this->get_user_id() ) : false;
80
	}
81
82
	/**
83
	 * Store data from the Stripe API about this customer
84
	 */
85
	public function set_customer_data( $data ) {
86
		$this->customer_data = $data;
87
	}
88
89
	/**
90
	 * Get data from the Stripe API about this customer
91
	 */
92
	public function get_customer_data() {
93
		if ( empty( $this->customer_data ) && $this->get_id() && false === ( $this->customer_data = get_transient( 'stripe_customer_' . $this->get_id() ) ) ) {
94
			$response = WC_Stripe_API::request( array(), 'customers/' . $this->get_id() );
95
96
			if ( ! is_wp_error( $response ) ) {
97
				$this->set_customer_data( $response );
98
				set_transient( 'stripe_customer_' . $this->get_id(), $response, HOUR_IN_SECONDS * 48 );
99
			}
100
		}
101
		return $this->customer_data;
102
	}
103
104
	/**
105
	 * Get default card/source
106
	 * @return string
107
	 */
108
	public function get_default_card() {
109
		$data   = $this->get_customer_data();
110
		$source = '';
111
112
		if ( $data ) {
113
			$source = $data->default_source;
114
		}
115
116
		return $source;
117
	}
118
119
	/**
120
	 * Create a customer via API.
121
	 * @param array $args
122
	 * @return WP_Error|int
123
	 */
124
	public function create_customer( $args = array() ) {
125
		if ( $user = $this->get_user() ) {
126
			$billing_first_name = get_user_meta( $user->ID, 'billing_first_name', true );
127
			$billing_last_name  = get_user_meta( $user->ID, 'billing_last_name', true );
128
129
			$defaults = array(
130
				'email'       => $user->user_email,
131
				'description' => $billing_first_name . ' ' . $billing_last_name,
132
			);
133
		} else {
134
			$defaults = array(
135
				'email'       => '',
136
				'description' => '',
137
			);
138
		}
139
140
		$metadata = array();
141
142
		$defaults['metadata'] = apply_filters( 'wc_stripe_customer_metadata', $metadata, $user );
143
144
		$args     = wp_parse_args( $args, $defaults );
145
		$response = WC_Stripe_API::request( $args, 'customers' );
0 ignored issues
show
Bug Compatibility introduced by
The expression \WC_Stripe_API::request($args, 'customers'); of type array|WP_Error adds the type array to the return on line 148 which is incompatible with the return type documented by WC_Stripe_Customer::create_customer of type WP_Error|integer.
Loading history...
146
147
		if ( is_wp_error( $response ) ) {
148
			return $response;
149
		} elseif ( empty( $response->id ) ) {
150
			return new WP_Error( 'stripe_error', __( 'Could not create Stripe customer.', 'woocommerce-gateway-stripe' ) );
151
		}
152
153
		$this->set_id( $response->id );
154
		$this->clear_cache();
155
		$this->set_customer_data( $response );
156
157
		if ( $this->get_user_id() ) {
158
			update_user_meta( $this->get_user_id(), '_stripe_customer_id', $response->id );
159
		}
160
161
		do_action( 'woocommerce_stripe_add_customer', $args, $response );
162
163
		return $response->id;
164
	}
165
166
	/**
167
	 * Add a card for this stripe customer.
168
	 * @param string $token
169
	 * @param bool $retry
170
	 * @return WP_Error|int
171
	 */
172
	public function add_card( $token, $retry = true ) {
173
		if ( ! $this->get_id() ) {
174
			if ( ( $response = $this->create_customer() ) && is_wp_error( $response ) ) {
175
				return $response;
176
			}
177
		}
178
179
		$response = WC_Stripe_API::request( array(
0 ignored issues
show
Bug Compatibility introduced by
The expression \WC_Stripe_API::request(...get_id() . '/sources'); of type array|WP_Error adds the type array to the return on line 195 which is incompatible with the return type documented by WC_Stripe_Customer::add_card of type WP_Error|integer.
Loading history...
180
			'source' => $token,
181
		), 'customers/' . $this->get_id() . '/sources' );
182
183
		if ( is_wp_error( $response ) ) {
184
			// It is possible the WC user once was linked to a customer on Stripe
185
			// but no longer exists. Instead of failing, lets try to create a
186
			// new customer.
187
			if ( preg_match( '/No such customer:/', $response->get_error_message() ) ) {
188
				delete_user_meta( $this->get_user_id(), '_stripe_customer_id' );
189
				$this->create_customer();
190
				return $this->add_card( $token, false );
191
			} elseif ( 'customer' === $response->get_error_code() && $retry ) {
192
				$this->create_customer();
193
				return $this->add_card( $token, false );
194
			} else {
195
				return $response;
196
			}
197
		} elseif ( empty( $response->id ) ) {
198
			return new WP_Error( 'error', __( 'Unable to add card', 'woocommerce-gateway-stripe' ) );
199
		}
200
201
		// Add token to WooCommerce
202
		if ( $this->get_user_id() && class_exists( 'WC_Payment_Token_CC' ) ) {
203
			$token = new WC_Payment_Token_CC();
204
			$token->set_token( $response->id );
205
			$token->set_gateway_id( 'stripe' );
206
			$token->set_card_type( strtolower( $response->brand ) );
207
			$token->set_last4( $response->last4 );
208
			$token->set_expiry_month( $response->exp_month );
209
			$token->set_expiry_year( $response->exp_year );
210
			$token->set_user_id( $this->get_user_id() );
211
			$token->save();
212
		}
213
214
		$this->clear_cache();
215
216
		do_action( 'woocommerce_stripe_add_card', $this->get_id(), $token, $response );
217
218
		return $response->id;
219
	}
220
221
	/**
222
	 * Get a customers saved cards using their Stripe ID. Cached.
223
	 *
224
	 * @param  string $customer_id
0 ignored issues
show
Bug introduced by
There is no parameter named $customer_id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
225
	 * @return array
226
	 */
227
	public function get_cards() {
228
		$cards = array();
229
230
		if ( $this->get_id() && false === ( $cards = get_transient( 'stripe_cards_' . $this->get_id() ) ) ) {
231
			$response = WC_Stripe_API::request( array(
232
				'limit'       => 100,
233
			), 'customers/' . $this->get_id() . '/sources', 'GET' );
234
235
			if ( is_wp_error( $response ) ) {
236
				return array();
237
			}
238
239
			if ( is_array( $response->data ) ) {
240
				$cards = $response->data;
241
			}
242
243
			set_transient( 'stripe_cards_' . $this->get_id(), $cards, HOUR_IN_SECONDS * 48 );
244
		}
245
246
		return $cards;
247
	}
248
249
	/**
250
	 * Delete a card from stripe.
251
	 * @param string $card_id
252
	 */
253 View Code Duplication
	public function delete_card( $card_id ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
254
		$response = WC_Stripe_API::request( array(), 'customers/' . $this->get_id() . '/sources/' . sanitize_text_field( $card_id ), 'DELETE' );
255
256
		$this->clear_cache();
257
258
		if ( ! is_wp_error( $response ) ) {
259
			do_action( 'wc_stripe_delete_card', $this->get_id(), $response );
260
261
			return true;
262
		}
263
264
		return false;
265
	}
266
267
	/**
268
	 * Set default card in Stripe
269
	 * @param string $card_id
270
	 */
271 View Code Duplication
	public function set_default_card( $card_id ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
272
		$response = WC_Stripe_API::request( array(
273
			'default_source' => sanitize_text_field( $card_id ),
274
		), 'customers/' . $this->get_id(), 'POST' );
275
276
		$this->clear_cache();
277
278
		if ( ! is_wp_error( $response ) ) {
279
			do_action( 'wc_stripe_set_default_card', $this->get_id(), $response );
280
281
			return true;
282
		}
283
284
		return false;
285
	}
286
287
	/**
288
	 * Deletes caches for this users cards.
289
	 */
290
	public function clear_cache() {
291
		delete_transient( 'stripe_cards_' . $this->get_id() );
292
		delete_transient( 'stripe_customer_' . $this->get_id() );
293
		$this->customer_data = array();
294
	}
295
}
296