Completed
Push — master ( e14dde...fdddbf )
by Mike
07:41
created

WC_Shortcode_My_Account::output()   C

Complexity

Conditions 8
Paths 9

Size

Total Lines 37
Code Lines 20

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 37
rs 5.3846
cc 8
eloc 20
nc 9
nop 1
1
<?php
2
/**
3
 * My Account Shortcodes
4
 *
5
 * Shows the 'my account' section where the customer can view past orders and update their information.
6
 *
7
 * @author 		WooThemes
8
 * @category 	Shortcodes
9
 * @package 	WooCommerce/Shortcodes/My_Account
10
 * @version     2.0.0
11
 */
12
class WC_Shortcode_My_Account {
13
14
	/**
15
	 * Get the shortcode content.
16
	 *
17
	 * @param array $atts
18
	 * @return string
19
	 */
20
	public static function get( $atts ) {
21
		return WC_Shortcodes::shortcode_wrapper( array( __CLASS__, 'output' ), $atts );
22
	}
23
24
	/**
25
	 * Output the shortcode.
26
	 *
27
	 * @param array $atts
28
	 */
29
	public static function output( $atts ) {
30
		global $wp;
31
32
		// Check cart class is loaded or abort
33
		if ( is_null( WC()->cart ) ) {
34
			return;
35
		}
36
37
		if ( ! is_user_logged_in() ) {
38
			$message = apply_filters( 'woocommerce_my_account_message', '' );
39
40
			if ( ! empty( $message ) ) {
41
				wc_add_notice( $message );
42
			}
43
44
			if ( isset( $wp->query_vars['lost-password'] ) ) {
45
				self::lost_password();
46
			} else {
47
				wc_get_template( 'myaccount/form-login.php' );
48
			}
49
	 	} else {
50
			// See if showing an account endpoint
51
			foreach ( $wp->query_vars as $key => $value ) {
52
				// Ignore pagename param.
53
				if ( 'pagename' === $key ) {
54
					continue;
55
				}
56
				if ( has_action( 'woocommerce_account_' . $key . '_endpoint' ) ) {
57
					do_action( 'woocommerce_account_' . $key . '_endpoint', $value );
58
					return;
59
				}
60
			}
61
62
			// No endpoint? Show main account page.
63
			self::my_account( $atts );
64
		}
65
	}
66
67
	/**
68
	 * My account page.
69
	 *
70
	 * @param array $atts
71
	 */
72
	private static function my_account( $atts ) {
73
		extract( shortcode_atts( array(
74
	    	'order_count' => 15 // @deprecated 2.6.0. Keep for backward compatibility.
75
		), $atts ) );
76
77
		wc_get_template( 'myaccount/my-account.php', array(
78
			'current_user' => get_user_by( 'id', get_current_user_id() ),
79
			'order_count'  => 'all' == $order_count ? -1 : $order_count
80
		) );
81
	}
82
83
	/**
84
	 * View order page.
85
	 *
86
	 * @param int $order_id
87
	 */
88
	public static function view_order( $order_id ) {
89
90
		$user_id = get_current_user_id();
0 ignored issues
show
Unused Code introduced by
$user_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
91
		$order   = wc_get_order( $order_id );
92
93 View Code Duplication
		if ( ! current_user_can( 'view_order', $order_id ) ) {
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...
94
			echo '<div class="woocommerce-error">' . __( 'Invalid order.', 'woocommerce' ) . ' <a href="' . wc_get_page_permalink( 'myaccount' ).'" class="wc-forward">'. __( 'My Account', 'woocommerce' ) .'</a>' . '</div>';
95
			return;
96
		}
97
98
		// Backwards compatibility
99
		$status       = new stdClass();
100
		$status->name = wc_get_order_status_name( $order->get_status() );
101
102
		wc_get_template( 'myaccount/view-order.php', array(
103
	        'status'    => $status, // @deprecated 2.2
104
	        'order'     => wc_get_order( $order_id ),
105
	        'order_id'  => $order_id
106
	    ) );
107
	}
108
109
	/**
110
	 * Edit account details page.
111
	 */
112
	public static function edit_account() {
113
		wc_get_template( 'myaccount/form-edit-account.php', array( 'user' => get_user_by( 'id', get_current_user_id() ) ) );
114
	}
115
116
	/**
117
	 * Edit address page.
118
	 *
119
	 * @param string $load_address
120
	 */
121
	public static function edit_address( $load_address = 'billing' ) {
122
		$current_user = wp_get_current_user();
123
		$load_address = sanitize_key( $load_address );
124
125
		$address = WC()->countries->get_address_fields( get_user_meta( get_current_user_id(), $load_address . '_country', true ), $load_address . '_' );
126
127
		// Enqueue scripts
128
		wp_enqueue_script( 'wc-country-select' );
129
		wp_enqueue_script( 'wc-address-i18n' );
130
131
		// Prepare values
132
		foreach ( $address as $key => $field ) {
133
134
			$value = get_user_meta( get_current_user_id(), $key, true );
135
136
			if ( ! $value ) {
137
				switch( $key ) {
138
					case 'billing_email' :
139
					case 'shipping_email' :
140
						$value = $current_user->user_email;
141
					break;
142
					case 'billing_country' :
143
					case 'shipping_country' :
144
						$value = WC()->countries->get_base_country();
145
					break;
146
					case 'billing_state' :
147
					case 'shipping_state' :
148
						$value = WC()->countries->get_base_state();
149
					break;
150
				}
151
			}
152
153
			$address[ $key ]['value'] = apply_filters( 'woocommerce_my_account_edit_address_field_value', $value, $key, $load_address );
154
		}
155
156
		wc_get_template( 'myaccount/form-edit-address.php', array(
157
			'load_address' 	=> $load_address,
158
			'address'		=> apply_filters( 'woocommerce_address_to_edit', $address )
159
		) );
160
	}
161
162
	/**
163
	 * Lost password page.
164
	 */
165
	public static function lost_password() {
166
		// arguments to pass to template
167
		$args = array( 'form' => 'lost_password' );
168
169
		// process reset key / login from email confirmation link
170
		if ( isset( $_GET['key'] ) && isset( $_GET['login'] ) ) {
171
172
			$user = self::check_password_reset_key( $_GET['key'], $_GET['login'] );
173
174
			// reset key / login is correct, display reset password form with hidden key / login values
175
			if ( is_object( $user ) ) {
176
				$args['form']  = 'reset_password';
177
				$args['key']   = esc_attr( $_GET['key'] );
178
				$args['login'] = esc_attr( $_GET['login'] );
179
			}
180
		} elseif ( isset( $_GET['reset'] ) ) {
181
			wc_add_notice( __( 'Your password has been reset.', 'woocommerce' ) . ' <a href="' . wc_get_page_permalink( 'myaccount' ) . '">' . __( 'Log in', 'woocommerce' ) . '</a>' );
182
		}
183
184
		wc_get_template( 'myaccount/form-lost-password.php', $args );
185
	}
186
187
	/**
188
	 * Handles sending password retrieval email to customer.
189
	 *
190
	 * Based on retrieve_password() in core wp-login.php.
191
	 *
192
	 * @uses $wpdb WordPress Database object
193
	 * @return bool True: when finish. False: on error
194
	 */
195
	public static function retrieve_password() {
196
		global $wpdb, $wp_hasher;
197
198
		$login = trim( $_POST['user_login'] );
199
200
		if ( empty( $login ) ) {
201
202
			wc_add_notice( __( 'Enter a username or e-mail address.', 'woocommerce' ), 'error' );
203
			return false;
204
205
		} else {
206
			// Check on username first, as customers can use emails as usernames.
207
			$user_data = get_user_by( 'login', $login );
208
		}
209
210
		// If no user found, check if it login is email and lookup user based on email.
211
		if ( ! $user_data && is_email( $login ) && apply_filters( 'woocommerce_get_username_from_email', true ) ) {
212
			$user_data = get_user_by( 'email', $login );
213
		}
214
215
		do_action( 'lostpassword_post' );
216
217
		if ( ! $user_data ) {
218
			wc_add_notice( __( 'Invalid username or e-mail.', 'woocommerce' ), 'error' );
219
			return false;
220
		}
221
222
		if ( is_multisite() && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) {
223
			wc_add_notice( __( 'Invalid username or e-mail.', 'woocommerce' ), 'error' );
224
			return false;
225
		}
226
227
		// redefining user_login ensures we return the right case in the email
228
		$user_login = $user_data->user_login;
229
230
		do_action( 'retrieve_password', $user_login );
231
232
		$allow = apply_filters( 'allow_password_reset', true, $user_data->ID );
233
234
		if ( ! $allow ) {
235
236
			wc_add_notice( __( 'Password reset is not allowed for this user', 'woocommerce' ), 'error' );
237
			return false;
238
239
		} elseif ( is_wp_error( $allow ) ) {
240
241
			wc_add_notice( $allow->get_error_message(), 'error' );
242
			return false;
243
		}
244
245
		$key = wp_generate_password( 20, false );
246
247
		do_action( 'retrieve_password_key', $user_login, $key );
248
249
		// Now insert the key, hashed, into the DB.
250
		if ( empty( $wp_hasher ) ) {
251
			require_once ABSPATH . 'wp-includes/class-phpass.php';
252
			$wp_hasher = new PasswordHash( 8, true );
253
		}
254
255
		$hashed = $wp_hasher->HashPassword( $key );
256
257
		$wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user_login ) );
258
259
		// Send email notification
260
		WC()->mailer(); // load email classes
261
		do_action( 'woocommerce_reset_password_notification', $user_login, $key );
262
263
		wc_add_notice( __( 'Check your e-mail for the confirmation link.', 'woocommerce' ) );
264
		return true;
265
	}
266
267
	/**
268
	 * Retrieves a user row based on password reset key and login.
269
	 *
270
	 * @uses $wpdb WordPress Database object
271
	 *
272
	 * @param string $key Hash to validate sending user's password
273
	 * @param string $login The user login
274
	 * @return WP_USER|bool User's database row on success, false for invalid keys
275
	 */
276
	public static function check_password_reset_key( $key, $login ) {
277
		global $wpdb, $wp_hasher;
278
279
		$key = preg_replace( '/[^a-z0-9]/i', '', $key );
280
281 View Code Duplication
		if ( empty( $key ) || ! is_string( $key ) ) {
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...
282
			wc_add_notice( __( 'Invalid key', 'woocommerce' ), 'error' );
283
			return false;
284
		}
285
286 View Code Duplication
		if ( empty( $login ) || ! is_string( $login ) ) {
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...
287
			wc_add_notice( __( 'Invalid key', 'woocommerce' ), 'error' );
288
			return false;
289
		}
290
291
		$user = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->users WHERE user_login = %s", $login ) );
292
293
		if ( ! empty( $user ) ) {
294
			if ( empty( $wp_hasher ) ) {
295
				require_once ABSPATH . 'wp-includes/class-phpass.php';
296
				$wp_hasher = new PasswordHash( 8, true );
297
			}
298
299
			$valid = $wp_hasher->CheckPassword( $key, $user->user_activation_key );
300
		}
301
302 View Code Duplication
		if ( empty( $user ) || empty( $valid ) ) {
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...
303
			wc_add_notice( __( 'Invalid key', 'woocommerce' ), 'error' );
304
			return false;
305
		}
306
307
		return get_userdata( $user->ID );
308
	}
309
310
	/**
311
	 * Handles resetting the user's password.
312
	 *
313
	 * @param object $user The user
314
	 * @param string $new_pass New password for the user in plaintext
315
	 */
316
	public static function reset_password( $user, $new_pass ) {
317
		do_action( 'password_reset', $user, $new_pass );
318
319
		wp_set_password( $new_pass, $user->ID );
320
321
		wp_password_change_notification( $user );
322
	}
323
324
	/**
325
	 * Show the add payment method page.
326
	 */
327
	public static function add_payment_method() {
328
329
		if ( ! is_user_logged_in() ) {
330
331
			wp_safe_redirect( wc_get_page_permalink( 'myaccount' ) );
332
			exit();
333
334
		} else {
335
336
			do_action( 'before_woocommerce_add_payment_method' );
337
338
			wc_print_notices();
339
340
			wc_get_template( 'myaccount/form-add-payment-method.php' );
341
342
			do_action( 'after_woocommerce_add_payment_method' );
343
344
		}
345
346
	}
347
}
348