1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Manage Customers. |
5
|
|
|
* |
6
|
|
|
* @since 2.5.0 |
7
|
|
|
* @package WooCommerce/CLI |
8
|
|
|
* @category CLI |
9
|
|
|
* @author WooThemes |
10
|
|
|
*/ |
11
|
|
|
class WC_CLI_Customer extends WC_CLI_Command { |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Create a customer. |
15
|
|
|
* |
16
|
|
|
* ## OPTIONS |
17
|
|
|
* |
18
|
|
|
* <email> |
19
|
|
|
* : The email address of the customer to create. |
20
|
|
|
* |
21
|
|
|
* [--<field>=<value>] |
22
|
|
|
* : Associative args for the new customer. |
23
|
|
|
* |
24
|
|
|
* [--porcelain] |
25
|
|
|
* : Outputs just the new customer id. |
26
|
|
|
* |
27
|
|
|
* ## AVAILABLE FIELDS |
28
|
|
|
* |
29
|
|
|
* These fields are optionally available for create command: |
30
|
|
|
* |
31
|
|
|
* * username |
32
|
|
|
* * password |
33
|
|
|
* * first_name |
34
|
|
|
* * last_name |
35
|
|
|
* |
36
|
|
|
* Billing address fields: |
37
|
|
|
* |
38
|
|
|
* * billing_address.first_name |
39
|
|
|
* * billing_address.last_name |
40
|
|
|
* * billing_address.company |
41
|
|
|
* * billing_address.address_1 |
42
|
|
|
* * billing_address.address_2 |
43
|
|
|
* * billing_address.city |
44
|
|
|
* * billing_address.state |
45
|
|
|
* * billing_address.postcode |
46
|
|
|
* * billing_address.country |
47
|
|
|
* * billing_address.email |
48
|
|
|
* * billing_address.phone |
49
|
|
|
* |
50
|
|
|
* Shipping address fields: |
51
|
|
|
* |
52
|
|
|
* * shipping_address.first_name |
53
|
|
|
* * shipping_address.last_name |
54
|
|
|
* * shipping_address.company |
55
|
|
|
* * shipping_address.address_1 |
56
|
|
|
* * shipping_address.address_2 |
57
|
|
|
* * shipping_address.city |
58
|
|
|
* * shipping_address.state |
59
|
|
|
* * shipping_address.postcode |
60
|
|
|
* * shipping_address.country |
61
|
|
|
* |
62
|
|
|
* ## EXAMPLES |
63
|
|
|
* |
64
|
|
|
* wp wc customer create [email protected] --first_name=Akeda |
65
|
|
|
* |
66
|
|
|
* @since 2.5.0 |
67
|
|
|
*/ |
68
|
|
|
public function create( $args, $assoc_args ) { |
69
|
|
|
global $wpdb; |
70
|
|
|
|
71
|
|
|
try { |
72
|
|
|
$porcelain = isset( $assoc_args['porcelain'] ); |
73
|
|
|
unset( $assoc_args['porcelain'] ); |
74
|
|
|
|
75
|
|
|
$assoc_args['email'] = $args[0]; |
76
|
|
|
$data = apply_filters( 'woocommerce_cli_create_customer_data', $this->unflatten_array( $assoc_args ) ); |
77
|
|
|
|
78
|
|
|
// Sets the username. |
79
|
|
|
$data['username'] = ! empty( $data['username'] ) ? $data['username'] : ''; |
80
|
|
|
|
81
|
|
|
// Sets the password. |
82
|
|
|
$data['password'] = ! empty( $data['password'] ) ? $data['password'] : ''; |
83
|
|
|
|
84
|
|
|
// Attempts to create the new customer. |
85
|
|
|
$id = wc_create_new_customer( $data['email'], $data['username'], $data['password'] ); |
86
|
|
|
|
87
|
|
|
// Checks for an error in the customer creation. |
88
|
|
|
if ( is_wp_error( $id ) ) { |
89
|
|
|
throw new WC_CLI_Exception( $id->get_error_code(), $id->get_error_message() ); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
// Added customer data. |
93
|
|
|
$this->update_customer_data( $id, $data ); |
94
|
|
|
|
95
|
|
|
do_action( 'woocommerce_cli_create_customer', $id, $data ); |
96
|
|
|
|
97
|
|
|
if ( $porcelain ) { |
98
|
|
|
WP_CLI::line( $id ); |
99
|
|
|
} else { |
100
|
|
|
WP_CLI::success( "Created customer $id." ); |
101
|
|
|
} |
102
|
|
|
} catch ( WC_CLI_Exception $e ) { |
103
|
|
|
WP_CLI::error( $e->getMessage() ); |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Delete one or more customers. |
109
|
|
|
* |
110
|
|
|
* ## OPTIONS |
111
|
|
|
* |
112
|
|
|
* <customer>... |
113
|
|
|
* : The customer ID, email, or username to delete. |
114
|
|
|
* |
115
|
|
|
* ## EXAMPLES |
116
|
|
|
* |
117
|
|
|
* wp wc customer delete 123 |
118
|
|
|
* |
119
|
|
|
* wp wc customer delete $(wp wc customer list --format=ids) |
120
|
|
|
* |
121
|
|
|
* @since 2.5.0 |
122
|
|
|
*/ |
123
|
|
|
public function delete( $args, $assoc_args ) { |
124
|
|
|
$exit_code = 0; |
125
|
|
|
foreach ( $args as $arg ) { |
126
|
|
|
try { |
127
|
|
|
$customer = $this->get_user( $arg ); |
128
|
|
|
do_action( 'woocommerce_cli_delete_customer', $customer['id'] ); |
129
|
|
|
$r = wp_delete_user( $customer['id'] ); |
130
|
|
|
|
131
|
|
|
if ( $r ) { |
132
|
|
|
WP_CLI::success( "Deleted customer {$customer['id']}." ); |
133
|
|
|
} else { |
134
|
|
|
$exit_code += 1; |
135
|
|
|
WP_CLI::warning( "Failed deleting customer {$customer['id']}." ); |
136
|
|
|
} |
137
|
|
|
} catch ( WC_CLI_Exception $e ) { |
138
|
|
|
WP_CLI::warning( $e->getMessage() ); |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
exit( $exit_code ? 1 : 0 ); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* View customer downloads. |
146
|
|
|
* |
147
|
|
|
* ## OPTIONS |
148
|
|
|
* |
149
|
|
|
* <customer> |
150
|
|
|
* : The customer ID, email or username. |
151
|
|
|
* |
152
|
|
|
* [--field=<field>] |
153
|
|
|
* : Instead of returning the whole customer fields, returns the value of a single fields. |
154
|
|
|
* |
155
|
|
|
* [--fields=<fields>] |
156
|
|
|
* : Get a specific subset of the customer's fields. |
157
|
|
|
* |
158
|
|
|
* [--format=<format>] |
159
|
|
|
* : Accepted values: table, json, csv. Default: table. |
160
|
|
|
* |
161
|
|
|
* ## AVAILABLE FIELDS |
162
|
|
|
* |
163
|
|
|
* * download_id |
164
|
|
|
* * download_name |
165
|
|
|
* * access_expires |
166
|
|
|
* |
167
|
|
|
* ## EXAMPLES |
168
|
|
|
* |
169
|
|
|
* wp wc customer downloads 123 |
170
|
|
|
* |
171
|
|
|
* @since 2.5.0 |
172
|
|
|
*/ |
173
|
|
|
public function downloads( $args, $assoc_args ) { |
174
|
|
|
try { |
175
|
|
|
$user = $this->get_user( $args[0] ); |
176
|
|
|
$downloads = array(); |
177
|
|
|
foreach ( wc_get_customer_available_downloads( $user['id'] ) as $key => $download ) { |
178
|
|
|
$downloads[ $key ] = $download; |
179
|
|
|
$downloads[ $key ]['access_expires'] = $this->format_datetime( $download['access_expires'] ); |
180
|
|
|
} |
181
|
|
|
$downloads = apply_filters( 'woocommerce_cli_customer_downloads', $downloads, $user, $assoc_args ); |
182
|
|
|
|
183
|
|
|
if ( empty( $assoc_args['fields'] ) ) { |
184
|
|
|
$assoc_args['fields'] = $this->get_customer_download_fields(); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
$formatter = $this->get_formatter( $assoc_args ); |
188
|
|
|
$formatter->display_items( $downloads ); |
189
|
|
|
|
190
|
|
|
} catch ( WC_CLI_Exception $e ) { |
191
|
|
|
WP_CLI::error( $e->getMessage() ); |
192
|
|
|
} |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* Get a customer. |
197
|
|
|
* |
198
|
|
|
* ## OPTIONS |
199
|
|
|
* |
200
|
|
|
* <customer> |
201
|
|
|
* : Customer ID, email, or username. |
202
|
|
|
* |
203
|
|
|
* [--field=<field>] |
204
|
|
|
* : Instead of returning the whole customer fields, returns the value of a single fields. |
205
|
|
|
* |
206
|
|
|
* [--fields=<fields>] |
207
|
|
|
* : Get a specific subset of the customer's fields. |
208
|
|
|
* |
209
|
|
|
* [--format=<format>] |
210
|
|
|
* : Accepted values: table, json, csv. Default: table. |
211
|
|
|
* |
212
|
|
|
* ## AVAILABLE FIELDS |
213
|
|
|
* |
214
|
|
|
* * id |
215
|
|
|
* * email |
216
|
|
|
* * first_name |
217
|
|
|
* * last_name |
218
|
|
|
* * created_at |
219
|
|
|
* * username |
220
|
|
|
* * last_order_id |
221
|
|
|
* * last_order_date |
222
|
|
|
* * orders_count |
223
|
|
|
* * total_spent |
224
|
|
|
* * avatar_url |
225
|
|
|
* |
226
|
|
|
* Billing address fields: |
227
|
|
|
* |
228
|
|
|
* * billing_address.first_name |
229
|
|
|
* * billing_address.last_name |
230
|
|
|
* * billing_address.company |
231
|
|
|
* * billing_address.address_1 |
232
|
|
|
* * billing_address.address_2 |
233
|
|
|
* * billing_address.city |
234
|
|
|
* * billing_address.state |
235
|
|
|
* * billing_address.postcode |
236
|
|
|
* * billing_address.country |
237
|
|
|
* * billing_address.email |
238
|
|
|
* * billing_address.phone |
239
|
|
|
* |
240
|
|
|
* Shipping address fields: |
241
|
|
|
* |
242
|
|
|
* * shipping_address.first_name |
243
|
|
|
* * shipping_address.last_name |
244
|
|
|
* * shipping_address.company |
245
|
|
|
* * shipping_address.address_1 |
246
|
|
|
* * shipping_address.address_2 |
247
|
|
|
* * shipping_address.city |
248
|
|
|
* * shipping_address.state |
249
|
|
|
* * shipping_address.postcode |
250
|
|
|
* * shipping_address.country |
251
|
|
|
* |
252
|
|
|
* Fields for filtering query result also available: |
253
|
|
|
* |
254
|
|
|
* * role Filter customers associated with certain role. |
255
|
|
|
* * q Filter customers with search query. |
256
|
|
|
* * created_at_min Filter customers whose registered after this date. |
257
|
|
|
* * created_at_max Filter customers whose registered before this date. |
258
|
|
|
* * limit The maximum returned number of results. |
259
|
|
|
* * offset Offset the returned results. |
260
|
|
|
* * order Accepted values: ASC and DESC. Default: DESC. |
261
|
|
|
* * orderby Sort retrieved customers by parameter. One or more options can be passed. |
262
|
|
|
* |
263
|
|
|
* ## EXAMPLES |
264
|
|
|
* |
265
|
|
|
* wp wc customer get 123 --field=email |
266
|
|
|
* |
267
|
|
|
* wp wc customer get customer-login --format=json |
268
|
|
|
* |
269
|
|
|
* @since 2.5.0 |
270
|
|
|
*/ |
271
|
|
|
public function get( $args, $assoc_args ) { |
272
|
|
|
try { |
273
|
|
|
$user = $this->get_user( $args[0] ); |
274
|
|
|
|
275
|
|
|
if ( empty( $assoc_args['fields'] ) ) { |
276
|
|
|
$assoc_args['fields'] = array_keys( $user ); |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
$formatter = $this->get_formatter( $assoc_args ); |
280
|
|
|
$formatter->display_item( $user ); |
281
|
|
|
} catch ( WC_CLI_Exception $e ) { |
282
|
|
|
WP_CLI::error( $e->getMessage() ); |
283
|
|
|
} |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* List customers. |
288
|
|
|
* |
289
|
|
|
* ## OPTIONS |
290
|
|
|
* |
291
|
|
|
* [--<field>=<value>] |
292
|
|
|
* : Filter customer based on customer property. |
293
|
|
|
* |
294
|
|
|
* [--field=<field>] |
295
|
|
|
* : Prints the value of a single field for each customer. |
296
|
|
|
* |
297
|
|
|
* [--fields=<fields>] |
298
|
|
|
* : Limit the output to specific customer fields. |
299
|
|
|
* |
300
|
|
|
* [--format=<format>] |
301
|
|
|
* : Acceptec values: table, csv, json, count, ids. Default: table. |
302
|
|
|
* |
303
|
|
|
* ## AVAILABLE FIELDS |
304
|
|
|
* |
305
|
|
|
* These fields will be displayed by default for each customer: |
306
|
|
|
* |
307
|
|
|
* * id |
308
|
|
|
* * email |
309
|
|
|
* * first_name |
310
|
|
|
* * last_name |
311
|
|
|
* * created_at |
312
|
|
|
* |
313
|
|
|
* These fields are optionally available: |
314
|
|
|
* |
315
|
|
|
* * username |
316
|
|
|
* * last_order_id |
317
|
|
|
* * last_order_date |
318
|
|
|
* * orders_count |
319
|
|
|
* * total_spent |
320
|
|
|
* * avatar_url |
321
|
|
|
* |
322
|
|
|
* Billing address fields: |
323
|
|
|
* |
324
|
|
|
* * billing_address.first_name |
325
|
|
|
* * billing_address.last_name |
326
|
|
|
* * billing_address.company |
327
|
|
|
* * billing_address.address_1 |
328
|
|
|
* * billing_address.address_2 |
329
|
|
|
* * billing_address.city |
330
|
|
|
* * billing_address.state |
331
|
|
|
* * billing_address.postcode |
332
|
|
|
* * billing_address.country |
333
|
|
|
* * billing_address.email |
334
|
|
|
* * billing_address.phone |
335
|
|
|
* |
336
|
|
|
* Shipping address fields: |
337
|
|
|
* |
338
|
|
|
* * shipping_address.first_name |
339
|
|
|
* * shipping_address.last_name |
340
|
|
|
* * shipping_address.company |
341
|
|
|
* * shipping_address.address_1 |
342
|
|
|
* * shipping_address.address_2 |
343
|
|
|
* * shipping_address.city |
344
|
|
|
* * shipping_address.state |
345
|
|
|
* * shipping_address.postcode |
346
|
|
|
* * shipping_address.country |
347
|
|
|
* |
348
|
|
|
* Fields for filtering query result also available: |
349
|
|
|
* |
350
|
|
|
* * role Filter customers associated with certain role. |
351
|
|
|
* * q Filter customers with search query. |
352
|
|
|
* * created_at_min Filter customers whose registered after this date. |
353
|
|
|
* * created_at_max Filter customers whose registered before this date. |
354
|
|
|
* * limit The maximum returned number of results. |
355
|
|
|
* * offset Offset the returned results. |
356
|
|
|
* * order Accepted values: ASC and DESC. Default: DESC. |
357
|
|
|
* * orderby Sort retrieved customers by parameter. One or more options can be passed. |
358
|
|
|
* |
359
|
|
|
* ## EXAMPLES |
360
|
|
|
* |
361
|
|
|
* wp wc customer list |
362
|
|
|
* |
363
|
|
|
* wp wc customer list --field=id |
364
|
|
|
* |
365
|
|
|
* wp wc customer list --fields=id,email,first_name --format=json |
366
|
|
|
* |
367
|
|
|
* @subcommand list |
368
|
|
|
* @since 2.5.0 |
369
|
|
|
*/ |
370
|
|
View Code Duplication |
public function list_( $__, $assoc_args ) { |
|
|
|
|
371
|
|
|
$query_args = $this->merge_wp_user_query_args( $this->get_list_query_args(), $assoc_args ); |
372
|
|
|
$formatter = $this->get_formatter( $assoc_args ); |
373
|
|
|
|
374
|
|
|
if ( 'ids' === $formatter->format ) { |
375
|
|
|
$query_args['fields'] = 'ids'; |
376
|
|
|
$query = new WP_User_Query( $query_args ); |
377
|
|
|
echo implode( ' ', $query->results ); |
378
|
|
|
} else { |
379
|
|
|
$query = new WP_User_Query( $query_args ); |
380
|
|
|
$items = $this->format_users_to_items( $query->results ); |
381
|
|
|
$formatter->display_items( $items ); |
382
|
|
|
} |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* View customer orders. |
387
|
|
|
* |
388
|
|
|
* ## OPTIONS |
389
|
|
|
* |
390
|
|
|
* <customer> |
391
|
|
|
* : The customer ID, email or username. |
392
|
|
|
* |
393
|
|
|
* [--field=<field>] |
394
|
|
|
* : Instead of returning the whole customer fields, returns the value of a single fields. |
395
|
|
|
* |
396
|
|
|
* [--fields=<fields>] |
397
|
|
|
* : Get a specific subset of the customer's fields. |
398
|
|
|
* |
399
|
|
|
* [--format=<format>] |
400
|
|
|
* : Accepted values: table, json, csv. Default: table. |
401
|
|
|
* |
402
|
|
|
* ## AVAILABLE FIELDS |
403
|
|
|
* |
404
|
|
|
* For more fields, see: wp wc order list --help |
405
|
|
|
* |
406
|
|
|
* ## EXAMPLES |
407
|
|
|
* |
408
|
|
|
* wp wc customer orders 123 |
409
|
|
|
* |
410
|
|
|
* @since 2.5.0 |
411
|
|
|
*/ |
412
|
|
|
public function orders( $args, $assoc_args ) { |
413
|
|
|
try { |
414
|
|
|
WP_CLI::run_command( array( 'wc', 'order', 'list' ), array( 'customer_id' => $args[0] ) ); |
415
|
|
|
} catch ( WC_CLI_Exception $e ) { |
416
|
|
|
WP_CLI::error( $e->getMessage() ); |
417
|
|
|
} |
418
|
|
|
} |
419
|
|
|
|
420
|
|
|
/** |
421
|
|
|
* Update one or more customers. |
422
|
|
|
* |
423
|
|
|
* ## OPTIONS |
424
|
|
|
* |
425
|
|
|
* <customer> |
426
|
|
|
* : Customer ID, email, or username. |
427
|
|
|
* |
428
|
|
|
* [--<field>=<value>] |
429
|
|
|
* : One or more fields to update. |
430
|
|
|
* |
431
|
|
|
* ## AVAILABLE FIELDS |
432
|
|
|
* |
433
|
|
|
* These fields are available for update command: |
434
|
|
|
* |
435
|
|
|
* * email |
436
|
|
|
* * password |
437
|
|
|
* * first_name |
438
|
|
|
* * last_name |
439
|
|
|
* |
440
|
|
|
* Billing address fields: |
441
|
|
|
* |
442
|
|
|
* * billing_address.first_name |
443
|
|
|
* * billing_address.last_name |
444
|
|
|
* * billing_address.company |
445
|
|
|
* * billing_address.address_1 |
446
|
|
|
* * billing_address.address_2 |
447
|
|
|
* * billing_address.city |
448
|
|
|
* * billing_address.state |
449
|
|
|
* * billing_address.postcode |
450
|
|
|
* * billing_address.country |
451
|
|
|
* * billing_address.email |
452
|
|
|
* * billing_address.phone |
453
|
|
|
* |
454
|
|
|
* Shipping address fields: |
455
|
|
|
* |
456
|
|
|
* * shipping_address.first_name |
457
|
|
|
* * shipping_address.last_name |
458
|
|
|
* * shipping_address.company |
459
|
|
|
* * shipping_address.address_1 |
460
|
|
|
* * shipping_address.address_2 |
461
|
|
|
* * shipping_address.city |
462
|
|
|
* * shipping_address.state |
463
|
|
|
* * shipping_address.postcode |
464
|
|
|
* * shipping_address.country |
465
|
|
|
* |
466
|
|
|
* ## EXAMPLES |
467
|
|
|
* |
468
|
|
|
* wp wc customer update customer-login --first_name=akeda --last_name=bagus |
469
|
|
|
* |
470
|
|
|
* wp wc customer update [email protected] --password=new-password |
471
|
|
|
* |
472
|
|
|
* @since 2.5.0 |
473
|
|
|
*/ |
474
|
|
|
public function update( $args, $assoc_args ) { |
475
|
|
|
try { |
476
|
|
|
$user = $this->get_user( $args[0] ); |
477
|
|
|
$data = $this->unflatten_array( $assoc_args ); |
478
|
|
|
$data = apply_filters( 'woocommerce_cli_update_customer_data', $data ); |
479
|
|
|
|
480
|
|
|
// Customer email. |
481
|
|
View Code Duplication |
if ( isset( $data['email'] ) ) { |
|
|
|
|
482
|
|
|
wp_update_user( array( 'ID' => $user['id'], 'user_email' => sanitize_email( $data['email'] ) ) ); |
483
|
|
|
} |
484
|
|
|
|
485
|
|
|
// Customer password. |
486
|
|
View Code Duplication |
if ( isset( $data['password'] ) ) { |
|
|
|
|
487
|
|
|
wp_update_user( array( 'ID' => $user['id'], 'user_pass' => wc_clean( $data['password'] ) ) ); |
488
|
|
|
} |
489
|
|
|
|
490
|
|
|
// Update customer data. |
491
|
|
|
$this->update_customer_data( $user['id'], $data ); |
492
|
|
|
|
493
|
|
|
do_action( 'woocommerce_cli_update_customer', $user['id'], $data ); |
494
|
|
|
|
495
|
|
|
WP_CLI::success( "Updated customer {$user['id']}." ); |
496
|
|
|
} catch ( WC_CLI_Exception $e ) { |
497
|
|
|
WP_CLI::error( $e->getMessage() ); |
498
|
|
|
} |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
/** |
502
|
|
|
* Get query args for list subcommand. |
503
|
|
|
* |
504
|
|
|
* @since 2.5.0 |
505
|
|
|
* @return array |
506
|
|
|
*/ |
507
|
|
|
protected function get_list_query_args() { |
508
|
|
|
return array( |
509
|
|
|
'role' => 'customer', |
510
|
|
|
'orderby' => 'registered', |
511
|
|
|
); |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
/** |
515
|
|
|
* Get default format fields that will be used in `list` and `get` subcommands. |
516
|
|
|
* |
517
|
|
|
* @since 2.5.0 |
518
|
|
|
* @return string |
519
|
|
|
*/ |
520
|
|
|
protected function get_default_format_fields() { |
521
|
|
|
return 'id,email,first_name,last_name,created_at'; |
522
|
|
|
} |
523
|
|
|
|
524
|
|
|
/** |
525
|
|
|
* Format users from WP_User_Query result to items in which each item contain |
526
|
|
|
* common properties of item. |
527
|
|
|
* |
528
|
|
|
* @since 2.5.0 |
529
|
|
|
* @param array $users Array of user |
530
|
|
|
* @return array Items |
531
|
|
|
*/ |
532
|
|
|
protected function format_users_to_items( $users ) { |
533
|
|
|
$items = array(); |
534
|
|
|
foreach ( $users as $user ) { |
535
|
|
|
try { |
536
|
|
|
$items[] = $this->get_user( $user->ID ); |
537
|
|
|
} catch ( WC_CLI_Exception $e ) { |
538
|
|
|
WP_CLI::warning( $e->getMessage() ); |
539
|
|
|
} |
540
|
|
|
} |
541
|
|
|
|
542
|
|
|
return $items; |
543
|
|
|
} |
544
|
|
|
|
545
|
|
|
/** |
546
|
|
|
* Get user from given user ID, email, or login |
547
|
|
|
* |
548
|
|
|
* @throws WC_CLI_Exception |
549
|
|
|
* |
550
|
|
|
* @since 2.5.0 |
551
|
|
|
* @param mixed $id_email_or_login |
552
|
|
|
* @return array|WP_Error |
553
|
|
|
*/ |
554
|
|
|
protected function get_user( $id_email_or_login ) { |
555
|
|
|
global $wpdb; |
556
|
|
|
|
557
|
|
|
if ( is_numeric( $id_email_or_login ) ) { |
558
|
|
|
$user = get_user_by( 'id', $id_email_or_login ); |
559
|
|
|
} else if ( is_email( $id_email_or_login ) ) { |
560
|
|
|
$user = get_user_by( 'email', $id_email_or_login ); |
561
|
|
|
} else { |
562
|
|
|
$user = get_user_by( 'login', $id_email_or_login ); |
563
|
|
|
} |
564
|
|
|
|
565
|
|
|
if ( ! $user ) { |
566
|
|
|
throw new WC_CLI_Exception( 'woocommerce_cli_invalid_customer', sprintf( __( 'Invalid customer "%s"', 'woocommerce' ), $id_email_or_login ) ); |
567
|
|
|
} |
568
|
|
|
|
569
|
|
|
// Get info about user's last order |
570
|
|
|
$last_order = $wpdb->get_row( "SELECT id, post_date_gmt |
571
|
|
|
FROM $wpdb->posts AS posts |
572
|
|
|
LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id |
573
|
|
|
WHERE meta.meta_key = '_customer_user' |
574
|
|
|
AND meta.meta_value = {$user->ID} |
575
|
|
|
AND posts.post_type = 'shop_order' |
576
|
|
|
AND posts.post_status IN ( '" . implode( "','", array_keys( wc_get_order_statuses() ) ) . "' ) |
577
|
|
|
ORDER BY posts.ID DESC |
578
|
|
|
" ); |
579
|
|
|
|
580
|
|
|
$customer = array( |
581
|
|
|
'id' => $user->ID, |
582
|
|
|
'created_at' => $this->format_datetime( $user->user_registered ), |
583
|
|
|
'email' => $user->user_email, |
584
|
|
|
'first_name' => $user->first_name, |
585
|
|
|
'last_name' => $user->last_name, |
586
|
|
|
'username' => $user->user_login, |
587
|
|
|
'role' => $user->roles[0], |
588
|
|
|
'last_order_id' => is_object( $last_order ) ? $last_order->id : null, |
589
|
|
|
'last_order_date' => is_object( $last_order ) ? $this->format_datetime( $last_order->post_date_gmt ) : null, |
590
|
|
|
'orders_count' => wc_get_customer_order_count( $user->ID ), |
591
|
|
|
'total_spent' => wc_format_decimal( wc_get_customer_total_spent( $user->ID ), 2 ), |
592
|
|
|
'avatar_url' => $this->get_avatar_url( $user->customer_email ), |
593
|
|
|
'billing_address' => array( |
594
|
|
|
'first_name' => $user->billing_first_name, |
595
|
|
|
'last_name' => $user->billing_last_name, |
596
|
|
|
'company' => $user->billing_company, |
597
|
|
|
'address_1' => $user->billing_address_1, |
598
|
|
|
'address_2' => $user->billing_address_2, |
599
|
|
|
'city' => $user->billing_city, |
600
|
|
|
'state' => $user->billing_state, |
601
|
|
|
'postcode' => $user->billing_postcode, |
602
|
|
|
'country' => $user->billing_country, |
603
|
|
|
'email' => $user->billing_email, |
604
|
|
|
'phone' => $user->billing_phone, |
605
|
|
|
), |
606
|
|
|
'shipping_address' => array( |
607
|
|
|
'first_name' => $user->shipping_first_name, |
608
|
|
|
'last_name' => $user->shipping_last_name, |
609
|
|
|
'company' => $user->shipping_company, |
610
|
|
|
'address_1' => $user->shipping_address_1, |
611
|
|
|
'address_2' => $user->shipping_address_2, |
612
|
|
|
'city' => $user->shipping_city, |
613
|
|
|
'state' => $user->shipping_state, |
614
|
|
|
'postcode' => $user->shipping_postcode, |
615
|
|
|
'country' => $user->shipping_country, |
616
|
|
|
), |
617
|
|
|
); |
618
|
|
|
|
619
|
|
|
|
620
|
|
|
// Allow dot notation for nested array so that user can specifies field |
621
|
|
|
// like 'billing_address.first_name'. |
622
|
|
|
return $this->flatten_array( $customer ); |
623
|
|
|
} |
624
|
|
|
|
625
|
|
|
/** |
626
|
|
|
* Wrapper for @see get_avatar() which doesn't simply return |
627
|
|
|
* the URL so we need to pluck it from the HTML img tag |
628
|
|
|
* |
629
|
|
|
* Kudos to https://github.com/WP-API/WP-API for offering a better solution |
630
|
|
|
* |
631
|
|
|
* @since 2.5.0 |
632
|
|
|
* @param string $email the customer's email |
633
|
|
|
* @return string the URL to the customer's avatar |
634
|
|
|
*/ |
635
|
|
View Code Duplication |
protected function get_avatar_url( $email ) { |
|
|
|
|
636
|
|
|
$avatar_html = get_avatar( $email ); |
637
|
|
|
|
638
|
|
|
// Get the URL of the avatar from the provided HTML |
639
|
|
|
preg_match( '/src=["|\'](.+)[\&|"|\']/U', $avatar_html, $matches ); |
640
|
|
|
|
641
|
|
|
if ( isset( $matches[1] ) && ! empty( $matches[1] ) ) { |
642
|
|
|
return esc_url_raw( $matches[1] ); |
643
|
|
|
} |
644
|
|
|
|
645
|
|
|
return null; |
646
|
|
|
} |
647
|
|
|
|
648
|
|
|
/** |
649
|
|
|
* Add/Update customer data. |
650
|
|
|
* |
651
|
|
|
* @since 2.5.0 |
652
|
|
|
* @param int $id The customer ID |
653
|
|
|
* @param array $data |
654
|
|
|
*/ |
655
|
|
|
protected function update_customer_data( $id, $data ) { |
656
|
|
|
// Customer first name. |
657
|
|
|
if ( isset( $data['first_name'] ) ) { |
658
|
|
|
update_user_meta( $id, 'first_name', wc_clean( $data['first_name'] ) ); |
659
|
|
|
} |
660
|
|
|
|
661
|
|
|
// Customer last name. |
662
|
|
|
if ( isset( $data['last_name'] ) ) { |
663
|
|
|
update_user_meta( $id, 'last_name', wc_clean( $data['last_name'] ) ); |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
// Customer billing address. |
667
|
|
|
if ( isset( $data['billing_address'] ) ) { |
668
|
|
|
foreach ( $this->get_customer_billing_address_fields() as $address ) { |
669
|
|
|
if ( isset( $data['billing_address'][ $address ] ) ) { |
670
|
|
|
update_user_meta( $id, 'billing_' . $address, wc_clean( $data['billing_address'][ $address ] ) ); |
671
|
|
|
} |
672
|
|
|
} |
673
|
|
|
} |
674
|
|
|
|
675
|
|
|
// Customer shipping address. |
676
|
|
|
if ( isset( $data['shipping_address'] ) ) { |
677
|
|
|
foreach ( $this->get_customer_shipping_address_fields() as $address ) { |
678
|
|
|
if ( isset( $data['shipping_address'][ $address ] ) ) { |
679
|
|
|
update_user_meta( $id, 'shipping_' . $address, wc_clean( $data['shipping_address'][ $address ] ) ); |
680
|
|
|
} |
681
|
|
|
} |
682
|
|
|
} |
683
|
|
|
|
684
|
|
|
do_action( 'woocommerce_cli_update_customer_data', $id, $data ); |
685
|
|
|
} |
686
|
|
|
|
687
|
|
|
/** |
688
|
|
|
* Get customer billing address fields. |
689
|
|
|
* |
690
|
|
|
* @since 2.5.0 |
691
|
|
|
* @return array |
692
|
|
|
*/ |
693
|
|
View Code Duplication |
protected function get_customer_billing_address_fields() { |
|
|
|
|
694
|
|
|
return apply_filters( 'woocommerce_cli_customer_billing_address_fields', array( |
695
|
|
|
'first_name', |
696
|
|
|
'last_name', |
697
|
|
|
'company', |
698
|
|
|
'address_1', |
699
|
|
|
'address_2', |
700
|
|
|
'city', |
701
|
|
|
'state', |
702
|
|
|
'postcode', |
703
|
|
|
'country', |
704
|
|
|
'email', |
705
|
|
|
'phone', |
706
|
|
|
) ); |
707
|
|
|
} |
708
|
|
|
|
709
|
|
|
/** |
710
|
|
|
* Get customer shipping address fields. |
711
|
|
|
* |
712
|
|
|
* @since 2.5.0 |
713
|
|
|
* @return array |
714
|
|
|
*/ |
715
|
|
View Code Duplication |
protected function get_customer_shipping_address_fields() { |
|
|
|
|
716
|
|
|
return apply_filters( 'woocommerce_cli_customer_shipping_address_fields', array( |
717
|
|
|
'first_name', |
718
|
|
|
'last_name', |
719
|
|
|
'company', |
720
|
|
|
'address_1', |
721
|
|
|
'address_2', |
722
|
|
|
'city', |
723
|
|
|
'state', |
724
|
|
|
'postcode', |
725
|
|
|
'country', |
726
|
|
|
) ); |
727
|
|
|
} |
728
|
|
|
|
729
|
|
|
/** |
730
|
|
|
* Get customer download fields. |
731
|
|
|
* |
732
|
|
|
* @since 2.5.0 |
733
|
|
|
* @return array |
734
|
|
|
*/ |
735
|
|
|
protected function get_customer_download_fields() { |
736
|
|
|
return apply_filters( 'woocommerce_cli_customer_download_fields', array( |
737
|
|
|
'download_id', |
738
|
|
|
'download_name', |
739
|
|
|
'access_expires', |
740
|
|
|
) ); |
741
|
|
|
} |
742
|
|
|
} |
743
|
|
|
|
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.