Completed
Pull Request — master (#2165)
by Justin
05:44
created

WPSC_Checkout_Form_Data   B

Complexity

Total Complexity 39

Size/Duplication

Total Lines 364
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 0
loc 364
rs 8.2857
c 0
b 0
f 0
wmc 39
lcom 1
cbo 3

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
B fetch() 0 52 6
A get_indexed_raw_data() 0 10 2
B shipping_matches_billing() 0 25 4
A get_billing_data() 0 5 1
A get_shipping_data() 0 5 1
A get_raw_data() 0 5 1
A prepare_get() 0 3 1
A prepare_get_data() 0 3 1
D get_gateway_data() 0 44 9
A set() 0 11 2
A save() 0 12 1
C save_form() 0 48 7
A get_log_id() 0 3 1
1
<?php
2
/**
3
 * The WP eCommerce Checkout form data Class
4
 *
5
 * @package wp-e-commerce
6
 * @since 3.8
7
 */
8
9
class WPSC_Checkout_Form_Data extends WPSC_Query_Base {
10
	protected $raw_data       = array();
11
	protected $segmented_data = array();
12
	protected $gateway_data   = array();
13
	protected $submitted_data = array();
14
	protected $log_id = 0;
15
16
	/**
17
	 * An array of arrays of cache keys. Allows versioning the cached values,
18
	 * and busting cache for a group if needed (by incrementing the version).
19
	 *
20
	 * @var array
21
	 */
22
	protected $group_ids = array(
23
		'raw_data' => array(
24
			'group'     => 'wpsc_checkout_form_raw_data',
25
			'version' => 1,
26
		),
27
		'gateway_data' => array(
28
			'group'     => 'wpsc_checkout_form_gateway_data',
29
			'version' => 0,
30
		),
31
	);
32
33
	public function __construct( $log_id, $pre_fetch = true ) {
34
		$this->log_id = absint( $log_id );
35
		if ( $pre_fetch ) {
36
			$this->fetch();
37
		}
38
	}
39
40
	/**
41
	 * Fetches the actual $data array.
42
	 *
43
	 * @access protected
44
	 * @since 4.0
45
	 *
46
	 * @return WPSC_Checkout_Form_Data
47
	 */
48
	protected function fetch() {
49
		if ( $this->fetched ) {
50
			return;
51
		}
52
53
		global $wpdb;
54
55
		if ( ! $this->raw_data = $this->cache_get( $this->log_id, 'raw_data' ) ) {
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->cache_get($this->log_id, 'raw_data') of type * is incompatible with the declared type array of property $raw_data.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
56
			$sql = "
57
				SELECT c.id, c.name, c.type, c.mandatory, c.unique_name, c.checkout_set as form_group, s.id as data_id, s.value
58
				FROM " . WPSC_TABLE_SUBMITTED_FORM_DATA . " AS s
59
				INNER JOIN " . WPSC_TABLE_CHECKOUT_FORMS . " AS c
60
					ON c.id = s.form_id
61
				WHERE s.log_id = %d AND active = '1'
62
			";
63
64
			$sql = $wpdb->prepare( $sql, $this->log_id );
65
			$this->raw_data = $wpdb->get_results( $sql );
66
67
			// Set the cache for raw checkout for data
68
			$this->cache_set( $this->log_id, $this->raw_data, 'raw_data' );
69
		}
70
71
		$this->exists = ! empty( $this->raw_data );
72
		$this->segmented_data = array(
73
			'shipping' => array(),
74
			'billing'  => array(),
75
		);
76
77
		// At the moment, only core fields have unique_name. In the future,
78
		// all fields will have a unique name rather than just IDs.
79
		foreach ( $this->raw_data as $index => $field ) {
80
			if ( ! empty( $field->unique_name ) ) {
81
82
				$is_shipping = false !== strpos( $field->unique_name, 'shipping' );
83
84
				if ( $is_shipping ) {
85
					$this->segmented_data['shipping'][ str_replace( 'shipping', '', $field->unique_name ) ] = $index;
86
				} else {
87
					$this->segmented_data['billing'][ str_replace( 'billing', '', $field->unique_name ) ] = $index;
88
				}
89
90
				$this->data[ $field->unique_name ] = $field->value;
91
			}
92
		}
93
94
		do_action( 'wpsc_checkout_form_data_fetched', $this );
95
96
		$this->fetched = true;
97
98
		return $this;
99
	}
100
101
	/**
102
	 * Get the raw data indexed by the 'id' column.
103
	 *
104
	 * @since  4.0
105
	 *
106
	 * @return array
107
	 */
108
	public function get_indexed_raw_data() {
109
		$this->fetch();
110
111
		$data = array();
112
		foreach ( $this->raw_data as $field ) {
113
			$data[ $field->id ] = $field;
114
		}
115
116
		return $data;
117
	}
118
119
	/**
120
	 * Determines if values in shipping fields matches values in billing fields.
121
	 *
122
	 * @since  4.0
123
	 *
124
	 * @return bool  Whether shipping values match billing values.
125
	 */
126
	public function shipping_matches_billing() {
127
		$this->fetch();
128
129
		foreach ( $this->segmented_data['shipping'] as $id => $index ) {
130
			// If we're missing data from any of these arrays, something's wrong (and they don't match).
131
			if ( ! isset(
132
				$this->raw_data[ $index ],
133
				$this->segmented_data['billing'][ $id ],
134
				$this->raw_data[ $this->segmented_data['billing'][ $id ] ]
135
			) ) {
136
				return false;
137
			}
138
139
			// Now we can get the values for the fields.
140
			$ship_val    = $this->raw_data[ $index ]->value;
141
			$billing_val = $this->raw_data[ $this->segmented_data['billing'][ $id ] ]->value;
142
143
			// Do they match?
144
			if ( $ship_val !== $billing_val ) {
145
				return false;
146
			}
147
		}
148
149
		return true;
150
	}
151
152
	/**
153
	 * Get the segmented billing info.
154
	 *
155
	 * @since  4.0
156
	 *
157
	 * @return array
158
	 */
159
	public function get_billing_data() {
160
		$this->fetch();
161
162
		return $this->segmented_data['billing'];
163
	}
164
165
	/**
166
	 * Get the segmented shipping info.
167
	 *
168
	 * @since  4.0
169
	 *
170
	 * @return array
171
	 */
172
	public function get_shipping_data() {
173
		$this->fetch();
174
175
		return $this->segmented_data['shipping'];
176
	}
177
178
	/**
179
	 * Gets the raw data array.
180
	 *
181
	 * @since  4.0
182
	 *
183
	 * @return array
184
	 */
185
	public function get_raw_data() {
186
		$this->fetch();
187
188
		return $this->raw_data;
189
	}
190
191
	/**
192
	 * Prepares the return value for get() (apply_filters, etc).
193
	 *
194
	 * @access protected
195
	 * @since  4.0
196
	 *
197
	 * @param  mixed  $value Value fetched
198
	 * @param  string $key   Key for $data.
199
	 *
200
	 * @return mixed
201
	 */
202
	protected function prepare_get( $value, $key ) {
203
		return apply_filters( 'wpsc_checkout_form_data_get_property', $value, $key, $this );
204
	}
205
206
	/**
207
	 * Prepares the return value for get_data() (apply_filters, etc).
208
	 *
209
	 * @access protected
210
	 * @since  4.0
211
	 *
212
	 * @return mixed
213
	 */
214
	protected function prepare_get_data() {
215
		return apply_filters( 'wpsc_checkout_form_get_data', $this->data, $this->log_id, $this );
216
	}
217
218
	public function get_gateway_data() {
219
		if ( ! $this->gateway_data = $this->cache_get( $this->log_id, 'gateway_data' ) ) {
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->cache_get($this->log_id, 'gateway_data') of type * is incompatible with the declared type array of property $gateway_data.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
220
			$map = array(
221
				'firstname' => 'first_name',
222
				'lastname'  => 'last_name',
223
				'address'   => 'street',
224
				'city'      => 'city',
225
				'state'     => 'state',
226
				'country'   => 'country',
227
				'postcode'  => 'zip',
228
				'phone'     => 'phone',
229
			);
230
231
			foreach ( array( 'shipping', 'billing' ) as $type ) {
232
233
				$data_key = "{$type}_address";
234
				$this->gateway_data[ $data_key ] = array();
235
236
				foreach ( $map as $key => $new_key ) {
237
					$key = $type . $key;
238
239
					if ( isset( $this->data[ $key ] ) ) {
240
						$value = $this->data [$key ];
241
242
						if ( $new_key == 'state' && is_numeric( $value ) ) {
243
							$value = wpsc_get_state_by_id( $value, 'code' );
244
						}
245
246
						$this->gateway_data[ $data_key ][ $new_key ] = $value;
247
					}
248
				}
249
250
				$name  = isset( $this->gateway_data[ $data_key ]['first_name'] ) ? $this->gateway_data[ $data_key ]['first_name'] . ' ' : '';
251
				$name .= isset( $this->gateway_data[ $data_key ]['last_name']  ) ? $this->gateway_data[ $data_key ]['last_name']        : '';
252
253
				$this->gateway_data[ $data_key ]['name'] = trim( $name );
254
			}
255
256
			// Sets the cache for checkout form gateway data
257
			$this->cache_set( $this->log_id, $this->gateway_data, 'gateway_data' );
258
		}
259
260
		return apply_filters( 'wpsc_checkout_form_gateway_data', $this->gateway_data, $this->log_id );
261
	}
262
263
	/**
264
	 * Set specific database fields.
265
	 *
266
	 * @param string|int $key   Expects either form ID or unique name.
267
	 * @param string     $value Value to be set for field.
268
	 *
269
	 * @since  4.0
270
	 * @return WPSC_Checkout_Form_Data Current instance of form data.
271
	 */
272
	public function set( $key, $value = '' ) {
273
274
		if ( ! is_numeric( $key ) ) {
275
			$checkout_form = WPSC_Checkout_Form::get();
276
			$key = $checkout_form->get_field_id_by_unique_name( $key );
277
		}
278
279
		$this->submitted_data[ $key ] = $value;
280
281
		return $this;
282
	}
283
284
	/**
285
	 * Used in conjunction with set() method, saves individual checkout form fields to database.
286
	 *
287
	 * @since  4.0
288
	 * @return void
289
	 */
290
	public function save() {
291
292
		$log    = new WPSC_Purchase_Log( $this->log_id );
293
		$form   = WPSC_Checkout_Form::get();
294
		$fields = $form->get_fields();
295
296
		$original_data = wp_list_pluck( $this->get_raw_data(), 'value', 'id' );
297
298
		$this->submitted_data = array_replace( $original_data, $this->submitted_data );
299
300
		return self::save_form( $log, $fields, $this->submitted_data );
301
	}
302
303
	/**
304
	 * Save Submitted Form Fields to the wpsc_submited_form_data table.
305
	 *
306
	 * @param WPSC_Purchase_Log $purchase_log
307
	 * @param array $fields
308
	 * @param array $data
309
	 * @param bool  $update_customer
310
	 * @return void
311
	 */
312
	public static function save_form( $purchase_log, $fields, $data = array(), $update_customer = true ) {
313
		global $wpdb;
314
315
		$log_id = $purchase_log->get( 'id' );
316
317
		// delete previous field values
318
		$sql = $wpdb->prepare( "DELETE FROM " . WPSC_TABLE_SUBMITTED_FORM_DATA . " WHERE log_id = %d", $log_id );
319
		$wpdb->query( $sql );
320
321
		if ( empty( $data ) && isset( $_POST['wpsc_checkout_details'] ) ) {
322
			$data = wp_unslash( $_POST['wpsc_checkout_details'] );
323
		}
324
325
		$customer_details = array();
326
327
		foreach ( $fields as $field ) {
328
329
			if ( $field->type == 'heading' ) {
330
				continue;
331
			}
332
333
			$value = '';
334
335
			if ( isset( $data[ $field->id ] ) ) {
336
				$value = $data[ $field->id ];
337
			}
338
339
			$customer_details[ $field->id ] = $value;
340
341
			$wpdb->insert(
342
				WPSC_TABLE_SUBMITTED_FORM_DATA,
343
				array(
344
					'log_id'  => $log_id,
345
					'form_id' => $field->id,
346
					'value'   => $value,
347
				),
348
				array(
349
					'%d',
350
					'%d',
351
					'%s',
352
				)
353
			);
354
		}
355
356
		if ( $update_customer ) {
357
			wpsc_save_customer_details( $customer_details );
358
		}
359
	}
360
361
	/**
362
	 * Returns the log id property.
363
	 *
364
	 * @since  4.0
365
	 *
366
	 * @return int  The log id.
367
	 */
368
	public function get_log_id() {
369
		return $this->log_id;
370
	}
371
372
}
373