Completed
Pull Request — master (#10110)
by Claudio
13:32
created

WC_Shortcode_My_Account::output()   D

Complexity

Conditions 9
Paths 9

Size

Total Lines 36
Code Lines 21

Duplication

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