Completed
Pull Request — master (#2165)
by Justin
06:18
created

WPSC_Checkout_Form_Data::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
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 ) {
34
		$this->log_id = absint( $log_id );
35
		$this->fetch();
36
	}
37
38
	/**
39
	 * Fetches the actual $data array.
40
	 *
41
	 * @access protected
42
	 * @since 4.0
43
	 *
44
	 * @return void
45
	 */
46
	protected function fetch() {
47
		if ( $this->fetched ) {
48
			return;
49
		}
50
51
		global $wpdb;
52
53
		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 boolean 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...
54
			$sql = "
55
				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
56
				FROM " . WPSC_TABLE_SUBMITTED_FORM_DATA . " AS s
57
				INNER JOIN " . WPSC_TABLE_CHECKOUT_FORMS . " AS c
58
					ON c.id = s.form_id
59
				WHERE s.log_id = %d AND active = '1'
60
			";
61
62
			$sql = $wpdb->prepare( $sql, $this->log_id );
63
			$this->raw_data = $wpdb->get_results( $sql );
64
			$this->exists   = ! empty( $this->raw_data );
0 ignored issues
show
Documentation Bug introduced by
The property $exists was declared of type string, but !empty($this->raw_data) is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
65
66
			// Set the cache for raw checkout for data
67
			$this->cache_set( $this->log_id, $this->raw_data, 'raw_data' );
68
		}
69
70
		$this->segmented_data = array(
71
			'shipping' => array(),
72
			'billing'  => array(),
73
		);
74
75
		// At the moment, only core fields have unique_name. In the future,
76
		// all fields will have a unique name rather than just IDs.
77
		foreach ( $this->raw_data as $index => $field ) {
78
			if ( ! empty( $field->unique_name ) ) {
79
80
				$is_shipping = false !== strpos( $field->unique_name, 'shipping' );
81
82
				if ( $is_shipping ) {
83
					$this->segmented_data['shipping'][ str_replace( 'shipping', '', $field->unique_name ) ] = $index;
84
				} else {
85
					$this->segmented_data['billing'][ str_replace( 'billing', '', $field->unique_name ) ] = $index;
86
				}
87
88
				$this->data[ $field->unique_name ] = $field->value;
89
			}
90
		}
91
92
		do_action( 'wpsc_checkout_form_data_fetched', $this );
93
94
		$this->fetched = true;
0 ignored issues
show
Documentation Bug introduced by
The property $fetched was declared of type string, but true is of type boolean. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
95
	}
96
97
	/**
98
	 * Get the raw data indexed by the 'id' column.
99
	 *
100
	 * @since  4.0
101
	 *
102
	 * @return array
103
	 */
104
	public function get_indexed_raw_data() {
105
		$data = array();
106
		foreach ( $this->raw_data as $field ) {
107
			$data[ $field->id ] = $field;
108
		}
109
110
		return $data;
111
	}
112
113
	/**
114
	 * Determines if values in shipping fields matches values in billing fields.
115
	 *
116
	 * @since  4.0
117
	 *
118
	 * @return bool  Whether shipping values match billing values.
119
	 */
120
	public function shipping_matches_billing() {
121
		foreach ( $this->segmented_data['shipping'] as $id => $index ) {
122
			// If we're missing data from any of these arrays, something's wrong (and they don't match).
123
			if ( ! isset(
124
				$this->raw_data[ $index ],
125
				$this->segmented_data['billing'][ $id ],
126
				$this->raw_data[ $this->segmented_data['billing'][ $id ] ]
127
			) ) {
128
				return false;
129
			}
130
131
			// Now we can get the values for the fields.
132
			$ship_val    = $this->raw_data[ $index ]->value;
133
			$billing_val = $this->raw_data[ $this->segmented_data['billing'][ $id ] ]->value;
134
135
			// Do they match?
136
			if ( $ship_val !== $billing_val ) {
137
				return false;
138
			}
139
		}
140
141
		return true;
142
	}
143
144
	/**
145
	 * Get the segmented billing info.
146
	 *
147
	 * @since  4.0
148
	 *
149
	 * @return array
150
	 */
151
	public function get_billing_data() {
152
		return $this->segmented_data['billing'];
153
	}
154
155
	/**
156
	 * Get the segmented shipping info.
157
	 *
158
	 * @since  4.0
159
	 *
160
	 * @return array
161
	 */
162
	public function get_shipping_data() {
163
		return $this->segmented_data['shipping'];
164
	}
165
166
	/**
167
	 * Gets the raw data array.
168
	 *
169
	 * @since  4.0
170
	 *
171
	 * @return array
172
	 */
173
	public function get_raw_data() {
174
		return $this->raw_data;
175
	}
176
177
	/**
178
	 * Prepares the return value for get() (apply_filters, etc).
179
	 *
180
	 * @access protected
181
	 * @since  4.0
182
	 *
183
	 * @param  mixed  $value Value fetched
184
	 * @param  string $key   Key for $data.
185
	 *
186
	 * @return mixed
187
	 */
188
	protected function prepare_get( $value, $key ) {
189
		return apply_filters( 'wpsc_checkout_form_data_get_property', $value, $key, $this );
190
	}
191
192
	/**
193
	 * Prepares the return value for get_data() (apply_filters, etc).
194
	 *
195
	 * @access protected
196
	 * @since  4.0
197
	 *
198
	 * @return mixed
199
	 */
200
	protected function prepare_get_data() {
201
		return apply_filters( 'wpsc_checkout_form_get_data', $this->data, $this->log_id, $this );
202
	}
203
204
	public function get_gateway_data() {
205
		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 boolean 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...
206
			$map = array(
207
				'firstname' => 'first_name',
208
				'lastname'  => 'last_name',
209
				'address'   => 'street',
210
				'city'      => 'city',
211
				'state'     => 'state',
212
				'country'   => 'country',
213
				'postcode'  => 'zip',
214
				'phone'     => 'phone',
215
			);
216
217
			foreach ( array( 'shipping', 'billing' ) as $type ) {
218
219
				$data_key = "{$type}_address";
220
				$this->gateway_data[ $data_key ] = array();
221
222
				foreach ( $map as $key => $new_key ) {
223
					$key = $type . $key;
224
225
					if ( isset( $this->data[ $key ] ) ) {
226
						$value = $this->data [$key ];
227
228
						if ( $new_key == 'state' && is_numeric( $value ) ) {
229
							$value = wpsc_get_state_by_id( $value, 'code' );
230
						}
231
232
						$this->gateway_data[ $data_key ][ $new_key ] = $value;
233
					}
234
				}
235
236
				$name  = isset( $this->gateway_data[ $data_key ]['first_name'] ) ? $this->gateway_data[ $data_key ]['first_name'] . ' ' : '';
237
				$name .= isset( $this->gateway_data[ $data_key ]['last_name']  ) ? $this->gateway_data[ $data_key ]['last_name']        : '';
238
239
				$this->gateway_data[ $data_key ]['name'] = trim( $name );
240
			}
241
242
			// Sets the cache for checkout form gateway data
243
			$this->cache_set( $this->log_id, $this->gateway_data, 'gateway_data' );
244
		}
245
246
		return apply_filters( 'wpsc_checkout_form_gateway_data', $this->gateway_data, $this->log_id );
247
	}
248
249
	/**
250
	 * Set specific database fields.
251
	 *
252
	 * @param string|int $key   Expects either form ID or unique name.
253
	 * @param string     $value Value to be set for field.
254
	 *
255
	 * @since  4.0
256
	 * @return WPSC_Checkout_Form_Data Current instance of form data.
257
	 */
258
	public function set( $key, $value = '' ) {
259
260
		if ( ! is_numeric( $key ) ) {
261
			$checkout_form = WPSC_Checkout_Form::get();
262
			$key = $checkout_form->get_field_id_by_unique_name( $key );
263
		}
264
265
		$this->submitted_data[ $key ] = $value;
266
267
		return $this;
268
	}
269
270
	/**
271
	 * Used in conjunction with set() method, saves individual checkout form fields to database.
272
	 *
273
	 * @since  4.0
274
	 * @return void
275
	 */
276
	public function save() {
277
278
		$log    = new WPSC_Purchase_Log( $this->log_id );
279
		$form   = WPSC_Checkout_Form::get();
280
		$fields = $form->get_fields();
281
282
		$original_data = wp_list_pluck( $this->get_raw_data(), 'value', 'id' );
283
284
		$this->submitted_data = array_replace( $original_data, $this->submitted_data );
285
286
		return self::save_form( $log, $fields, $this->submitted_data );
287
	}
288
289
	/**
290
	 * Save Submitted Form Fields to the wpsc_submited_form_data table.
291
	 *
292
	 * @param WPSC_Purchase_Log $purchase_log
293
	 * @param array $fields
294
	 * @return void
295
	 */
296
	public static function save_form( $purchase_log, $fields, $data = array() ) {
297
		global $wpdb;
298
299
		$log_id = $purchase_log->get( 'id' );
300
301
		// delete previous field values
302
		$sql = $wpdb->prepare( "DELETE FROM " . WPSC_TABLE_SUBMITTED_FORM_DATA . " WHERE log_id = %d", $log_id );
303
		$wpdb->query( $sql );
304
305
		if ( empty( $data ) && isset( $_POST['wpsc_checkout_details'] ) ) {
306
			$data = $_POST['wpsc_checkout_details'];
307
		}
308
309
		$customer_details = array();
310
311
		foreach ( $fields as $field ) {
312
313
			if ( $field->type == 'heading' ) {
314
				continue;
315
			}
316
317
			$value = '';
318
319
			if ( isset( $data[ $field->id ] ) ) {
320
				$value = wp_unslash( $data[ $field->id ] );
321
			}
322
323
			$customer_details[ $field->id ] = $value;
324
325
			$wpdb->insert(
326
				WPSC_TABLE_SUBMITTED_FORM_DATA,
327
				array(
328
					'log_id'  => $log_id,
329
					'form_id' => $field->id,
330
					'value'   => $value,
331
				),
332
				array(
333
					'%d',
334
					'%d',
335
					'%s',
336
				)
337
			);
338
		}
339
340
		wpsc_save_customer_details( $customer_details );
341
	}
342
343
	/**
344
	 * Returns the log id property.
345
	 *
346
	 * @since  4.0
347
	 *
348
	 * @return int  The log id.
349
	 */
350
	public function get_log_id() {
351
		return $this->log_id;
352
	}
353
354
}
355