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
|
|
|
// Start output buffer since the html may need discarding for BW compatibility |
51
|
|
|
ob_start(); |
52
|
|
|
|
53
|
|
|
// Collect notices before output |
54
|
|
|
$notices = wc_get_notices(); |
55
|
|
|
|
56
|
|
|
// Output the new account page |
57
|
|
|
self::my_account( $atts ); |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Deprecated my-account.php template handling. This code should be |
61
|
|
|
* removed in a future release. |
62
|
|
|
* |
63
|
|
|
* If woocommerce_account_content did not run, this is an old template |
64
|
|
|
* so we need to render the endpoint content again. |
65
|
|
|
*/ |
66
|
|
|
if ( ! did_action( 'woocommerce_account_content' ) ) { |
67
|
|
|
foreach ( $wp->query_vars as $key => $value ) { |
68
|
|
|
if ( 'pagename' === $key ) { |
69
|
|
|
continue; |
70
|
|
|
} |
71
|
|
|
if ( has_action( 'woocommerce_account_' . $key . '_endpoint' ) ) { |
72
|
|
|
ob_clean(); // Clear previous buffer |
73
|
|
|
wc_set_notices( $notices ); |
74
|
|
|
wc_print_notices(); |
75
|
|
|
do_action( 'woocommerce_account_' . $key . '_endpoint', $value ); |
76
|
|
|
break; |
77
|
|
|
} |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
_deprecated_function( 'Your theme version of my-account.php template', '2.6', 'the latest version, which supports multiple account pages and navigation, from WC 2.6.0' ); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
// Send output buffer |
84
|
|
|
ob_end_flush(); |
85
|
|
|
} |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* My account page. |
90
|
|
|
* |
91
|
|
|
* @param array $atts |
92
|
|
|
*/ |
93
|
|
|
private static function my_account( $atts ) { |
94
|
|
|
extract( shortcode_atts( array( |
95
|
|
|
'order_count' => 15 // @deprecated 2.6.0. Keep for backward compatibility. |
96
|
|
|
), $atts ) ); |
97
|
|
|
|
98
|
|
|
wc_get_template( 'myaccount/my-account.php', array( |
99
|
|
|
'current_user' => get_user_by( 'id', get_current_user_id() ), |
100
|
|
|
'order_count' => 'all' == $order_count ? -1 : $order_count, |
101
|
|
|
) ); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* View order page. |
106
|
|
|
* |
107
|
|
|
* @param int $order_id |
108
|
|
|
*/ |
109
|
|
|
public static function view_order( $order_id ) { |
110
|
|
|
$order = wc_get_order( $order_id ); |
111
|
|
|
|
112
|
|
View Code Duplication |
if ( ! current_user_can( 'view_order', $order_id ) ) { |
|
|
|
|
113
|
|
|
echo '<div class="woocommerce-error">' . __( 'Invalid order.', 'woocommerce' ) . ' <a href="' . wc_get_page_permalink( 'myaccount' ).'" class="wc-forward">'. __( 'My Account', 'woocommerce' ) .'</a>' . '</div>'; |
114
|
|
|
return; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
// Backwards compatibility |
118
|
|
|
$status = new stdClass(); |
119
|
|
|
$status->name = wc_get_order_status_name( $order->get_status() ); |
120
|
|
|
|
121
|
|
|
wc_get_template( 'myaccount/view-order.php', array( |
122
|
|
|
'status' => $status, // @deprecated 2.2 |
123
|
|
|
'order' => wc_get_order( $order_id ), |
124
|
|
|
'order_id' => $order_id |
125
|
|
|
) ); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Edit account details page. |
130
|
|
|
*/ |
131
|
|
|
public static function edit_account() { |
132
|
|
|
wc_get_template( 'myaccount/form-edit-account.php', array( 'user' => get_user_by( 'id', get_current_user_id() ) ) ); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Edit address page. |
137
|
|
|
* |
138
|
|
|
* @param string $load_address |
139
|
|
|
*/ |
140
|
|
|
public static function edit_address( $load_address = 'billing' ) { |
141
|
|
|
$current_user = wp_get_current_user(); |
142
|
|
|
$load_address = sanitize_key( $load_address ); |
143
|
|
|
|
144
|
|
|
$address = WC()->countries->get_address_fields( get_user_meta( get_current_user_id(), $load_address . '_country', true ), $load_address . '_' ); |
145
|
|
|
|
146
|
|
|
// Enqueue scripts |
147
|
|
|
wp_enqueue_script( 'wc-country-select' ); |
148
|
|
|
wp_enqueue_script( 'wc-address-i18n' ); |
149
|
|
|
|
150
|
|
|
// Prepare values |
151
|
|
|
foreach ( $address as $key => $field ) { |
152
|
|
|
|
153
|
|
|
$value = get_user_meta( get_current_user_id(), $key, true ); |
154
|
|
|
|
155
|
|
|
if ( ! $value ) { |
156
|
|
|
switch( $key ) { |
157
|
|
|
case 'billing_email' : |
158
|
|
|
case 'shipping_email' : |
159
|
|
|
$value = $current_user->user_email; |
160
|
|
|
break; |
161
|
|
|
case 'billing_country' : |
162
|
|
|
case 'shipping_country' : |
163
|
|
|
$value = WC()->countries->get_base_country(); |
164
|
|
|
break; |
165
|
|
|
case 'billing_state' : |
166
|
|
|
case 'shipping_state' : |
167
|
|
|
$value = WC()->countries->get_base_state(); |
168
|
|
|
break; |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
$address[ $key ]['value'] = apply_filters( 'woocommerce_my_account_edit_address_field_value', $value, $key, $load_address ); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
wc_get_template( 'myaccount/form-edit-address.php', array( |
176
|
|
|
'load_address' => $load_address, |
177
|
|
|
'address' => apply_filters( 'woocommerce_address_to_edit', $address ) |
178
|
|
|
) ); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* Lost password page handling. |
183
|
|
|
*/ |
184
|
|
|
public static function lost_password() { |
185
|
|
|
/** |
186
|
|
|
* After sending the reset link, don't show the form again. |
187
|
|
|
*/ |
188
|
|
|
if ( ! empty( $_GET['reset-link-sent'] ) ) { |
189
|
|
|
return wc_get_template( 'myaccount/lost-password-confirmation.php' ); |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* After reset, show confirmation message. |
193
|
|
|
*/ |
194
|
|
|
} elseif ( ! empty( $_GET['reset'] ) ) { |
195
|
|
|
wc_add_notice( __( 'Your password has been reset.', 'woocommerce' ) . ' <a class="button" href="' . esc_url( wc_get_page_permalink( 'myaccount' ) ) . '">' . __( 'Log in', 'woocommerce' ) . '</a>' ); |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Process reset key / login from email confirmation link |
199
|
|
|
*/ |
200
|
|
|
} elseif ( ! empty( $_GET['show-reset-form'] ) ) { |
201
|
|
|
if ( isset( $_COOKIE[ 'wp-resetpass-' . COOKIEHASH ] ) && 0 < strpos( $_COOKIE[ 'wp-resetpass-' . COOKIEHASH ], ':' ) ) { |
202
|
|
|
list( $rp_login, $rp_key ) = array_map( 'wc_clean', explode( ':', wp_unslash( $_COOKIE[ 'wp-resetpass-' . COOKIEHASH ] ), 2 ) ); |
203
|
|
|
$user = self::check_password_reset_key( $rp_key, $rp_login ); |
204
|
|
|
|
205
|
|
|
// reset key / login is correct, display reset password form with hidden key / login values |
206
|
|
|
if ( is_object( $user ) ) { |
207
|
|
|
return wc_get_template( 'myaccount/form-reset-password.php', array( |
208
|
|
|
'key' => $rp_key, |
209
|
|
|
'login' => $rp_login, |
210
|
|
|
) ); |
211
|
|
|
} else { |
212
|
|
|
self::set_reset_password_cookie(); |
213
|
|
|
} |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
// Show lost password form by default |
218
|
|
|
wc_get_template( 'myaccount/form-lost-password.php', array( |
219
|
|
|
'form' => 'lost_password', |
220
|
|
|
) ); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Handles sending password retrieval email to customer. |
225
|
|
|
* |
226
|
|
|
* Based on retrieve_password() in core wp-login.php. |
227
|
|
|
* |
228
|
|
|
* @uses $wpdb WordPress Database object |
229
|
|
|
* @return bool True: when finish. False: on error |
230
|
|
|
*/ |
231
|
|
|
public static function retrieve_password() { |
232
|
|
|
global $wpdb, $wp_hasher; |
233
|
|
|
|
234
|
|
|
$login = trim( $_POST['user_login'] ); |
235
|
|
|
|
236
|
|
|
if ( empty( $login ) ) { |
237
|
|
|
|
238
|
|
|
wc_add_notice( __( 'Enter a username or e-mail address.', 'woocommerce' ), 'error' ); |
239
|
|
|
return false; |
240
|
|
|
|
241
|
|
|
} else { |
242
|
|
|
// Check on username first, as customers can use emails as usernames. |
243
|
|
|
$user_data = get_user_by( 'login', $login ); |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
// If no user found, check if it login is email and lookup user based on email. |
247
|
|
|
if ( ! $user_data && is_email( $login ) && apply_filters( 'woocommerce_get_username_from_email', true ) ) { |
248
|
|
|
$user_data = get_user_by( 'email', $login ); |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
do_action( 'lostpassword_post' ); |
252
|
|
|
|
253
|
|
|
if ( ! $user_data ) { |
254
|
|
|
wc_add_notice( __( 'Invalid username or e-mail.', 'woocommerce' ), 'error' ); |
255
|
|
|
return false; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
if ( is_multisite() && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) { |
259
|
|
|
wc_add_notice( __( 'Invalid username or e-mail.', 'woocommerce' ), 'error' ); |
260
|
|
|
return false; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
// redefining user_login ensures we return the right case in the email |
264
|
|
|
$user_login = $user_data->user_login; |
265
|
|
|
|
266
|
|
|
do_action( 'retrieve_password', $user_login ); |
267
|
|
|
|
268
|
|
|
$allow = apply_filters( 'allow_password_reset', true, $user_data->ID ); |
269
|
|
|
|
270
|
|
|
if ( ! $allow ) { |
271
|
|
|
|
272
|
|
|
wc_add_notice( __( 'Password reset is not allowed for this user', 'woocommerce' ), 'error' ); |
273
|
|
|
return false; |
274
|
|
|
|
275
|
|
|
} elseif ( is_wp_error( $allow ) ) { |
276
|
|
|
|
277
|
|
|
wc_add_notice( $allow->get_error_message(), 'error' ); |
278
|
|
|
return false; |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
$key = wp_generate_password( 20, false ); |
282
|
|
|
|
283
|
|
|
do_action( 'retrieve_password_key', $user_login, $key ); |
284
|
|
|
|
285
|
|
|
// Now insert the key, hashed, into the DB. |
286
|
|
|
if ( empty( $wp_hasher ) ) { |
287
|
|
|
require_once ABSPATH . 'wp-includes/class-phpass.php'; |
288
|
|
|
$wp_hasher = new PasswordHash( 8, true ); |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
$hashed = $wp_hasher->HashPassword( $key ); |
292
|
|
|
|
293
|
|
|
$wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user_login ) ); |
294
|
|
|
|
295
|
|
|
// Send email notification |
296
|
|
|
WC()->mailer(); // load email classes |
297
|
|
|
do_action( 'woocommerce_reset_password_notification', $user_login, $key ); |
298
|
|
|
|
299
|
|
|
return true; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Retrieves a user row based on password reset key and login. |
304
|
|
|
* |
305
|
|
|
* @uses $wpdb WordPress Database object |
306
|
|
|
* |
307
|
|
|
* @param string $key Hash to validate sending user's password |
308
|
|
|
* @param string $login The user login |
309
|
|
|
* @return WP_USER|bool User's database row on success, false for invalid keys |
310
|
|
|
*/ |
311
|
|
|
public static function check_password_reset_key( $key, $login ) { |
312
|
|
|
global $wpdb, $wp_hasher; |
313
|
|
|
|
314
|
|
|
$key = preg_replace( '/[^a-z0-9]/i', '', $key ); |
315
|
|
|
|
316
|
|
View Code Duplication |
if ( empty( $key ) || ! is_string( $key ) ) { |
|
|
|
|
317
|
|
|
wc_add_notice( __( 'Invalid key', 'woocommerce' ), 'error' ); |
318
|
|
|
return false; |
319
|
|
|
} |
320
|
|
|
|
321
|
|
View Code Duplication |
if ( empty( $login ) || ! is_string( $login ) ) { |
|
|
|
|
322
|
|
|
wc_add_notice( __( 'Invalid key', 'woocommerce' ), 'error' ); |
323
|
|
|
return false; |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
$user = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->users WHERE user_login = %s", $login ) ); |
327
|
|
|
|
328
|
|
|
if ( ! empty( $user ) ) { |
329
|
|
|
if ( empty( $wp_hasher ) ) { |
330
|
|
|
require_once ABSPATH . 'wp-includes/class-phpass.php'; |
331
|
|
|
$wp_hasher = new PasswordHash( 8, true ); |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
$valid = $wp_hasher->CheckPassword( $key, $user->user_activation_key ); |
335
|
|
|
} |
336
|
|
|
|
337
|
|
View Code Duplication |
if ( empty( $user ) || empty( $valid ) ) { |
|
|
|
|
338
|
|
|
wc_add_notice( __( 'Invalid key', 'woocommerce' ), 'error' ); |
339
|
|
|
return false; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
return get_userdata( $user->ID ); |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
/** |
346
|
|
|
* Handles resetting the user's password. |
347
|
|
|
* |
348
|
|
|
* @param object $user The user |
349
|
|
|
* @param string $new_pass New password for the user in plaintext |
350
|
|
|
*/ |
351
|
|
|
public static function reset_password( $user, $new_pass ) { |
352
|
|
|
do_action( 'password_reset', $user, $new_pass ); |
353
|
|
|
|
354
|
|
|
wp_set_password( $new_pass, $user->ID ); |
355
|
|
|
self::set_reset_password_cookie(); |
356
|
|
|
|
357
|
|
|
wp_password_change_notification( $user ); |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* Set or unset the cookie. |
362
|
|
|
*/ |
363
|
|
|
public static function set_reset_password_cookie( $value = '' ) { |
364
|
|
|
$rp_cookie = 'wp-resetpass-' . COOKIEHASH; |
365
|
|
|
$rp_path = current( explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); |
366
|
|
|
|
367
|
|
|
if ( $value ) { |
368
|
|
|
setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true ); |
369
|
|
|
} else { |
370
|
|
|
setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true ); |
371
|
|
|
} |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
/** |
375
|
|
|
* Show the add payment method page. |
376
|
|
|
*/ |
377
|
|
|
public static function add_payment_method() { |
378
|
|
|
|
379
|
|
|
if ( ! is_user_logged_in() ) { |
380
|
|
|
|
381
|
|
|
wp_safe_redirect( wc_get_page_permalink( 'myaccount' ) ); |
382
|
|
|
exit(); |
383
|
|
|
|
384
|
|
|
} else { |
385
|
|
|
|
386
|
|
|
do_action( 'before_woocommerce_add_payment_method' ); |
387
|
|
|
|
388
|
|
|
wc_print_notices(); |
389
|
|
|
|
390
|
|
|
wc_get_template( 'myaccount/form-add-payment-method.php' ); |
391
|
|
|
|
392
|
|
|
do_action( 'after_woocommerce_add_payment_method' ); |
393
|
|
|
|
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
} |
399
|
|
|
|
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.