Skip to content

Commit 49a0c9d

Browse files
authored
Merge pull request #137 from woocommerce/fix/131/coherent-users
Makes the data generated by the Customers generator more "coherent" and contextual to a locale, plus a few other enhancements to make it more useful for testing. * Adds an optional country parameter to the generator, which is used to localize the Faker library that produces the random data. If a country isn't specified, falls back on randomly selecting any country that the store is configured to sell to. * Ensures that first, last, and/or company name that is generated is then used when generating username and email address. * Adds an optional type parameter to the generator, to specify if the customer should be a person or a company. Company customers do not have the first and last name fields filled in. * Sets the password of every created customer account to password so that it's easy to log in as that customer and see the store from that perspective. * Misc tweaks. Fixes #131 Fixes #108 Fixes #66
2 parents 5b764d7 + 6d68985 commit 49a0c9d

File tree

4 files changed

+402
-113
lines changed

4 files changed

+402
-113
lines changed

includes/CLI.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ function () use ( $progress ) {
149149
while ( $remaining_amount > 0 ) {
150150
$batch = min( $remaining_amount, Generator\Customer::MAX_BATCH_SIZE );
151151

152-
$result = Generator\Customer::batch( $batch );
152+
$result = Generator\Customer::batch( $batch, $assoc_args );
153153

154154
if ( is_wp_error( $result ) ) {
155155
WP_CLI::error( $result );
@@ -337,8 +337,22 @@ function () use ( $progress ) {
337337
'optional' => true,
338338
'default' => 10,
339339
),
340+
array(
341+
'name' => 'country',
342+
'type' => 'assoc',
343+
'description' => 'The ISO 3166-1 alpha-2 country code to use for localizing the customer data. If none is specified, any country in the "Selling location(s)" setting may be used.',
344+
'optional' => true,
345+
'default' => '',
346+
),
347+
array(
348+
'name' => 'type',
349+
'type' => 'assoc',
350+
'description' => 'The type of customer to generate data for. If none is specified, it will be a 70% person, 30% company mix.',
351+
'optional' => true,
352+
'options' => array( 'company', 'person' ),
353+
),
340354
),
341-
'longdesc' => "## EXAMPLES\n\nwc generate customers 10",
355+
'longdesc' => "## EXAMPLES\n\nwc generate customers 10\n\nwc generate customers --country=ES --type=company",
342356
) );
343357

344358
WP_CLI::add_command( 'wc generate coupons', array( 'WC\SmoothGenerator\CLI', 'coupons' ), array(

includes/Generator/Customer.php

Lines changed: 90 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -11,130 +11,105 @@
1111
* Customer data generator.
1212
*/
1313
class Customer extends Generator {
14-
1514
/**
1615
* Return a new customer.
1716
*
18-
* @param bool $save Save the object before returning or not.
19-
* @return \WC_Customer Customer object with data populated.
17+
* @param bool $save Save the object before returning or not.
18+
* @param array $assoc_args Arguments passed via the CLI for additional customization.
19+
*
20+
* @return \WC_Customer|\WP_Error Customer object with data populated.
2021
*/
21-
public static function generate( $save = true ) {
22+
public static function generate( $save = true, array $assoc_args = array() ) {
2223
self::init_faker();
2324

24-
// Make sure a unique username and e-mail are used.
25-
do {
26-
$username = self::$faker->userName();
27-
} while ( username_exists( $username ) );
28-
29-
do {
30-
$email = self::$faker->safeEmail();
31-
} while ( email_exists( $email ) );
32-
33-
/*PERSON*/
34-
$person['billing']['firstname'] = self::$faker->firstName( self::$faker->randomElement( array( 'male', 'female' ) ) );
35-
$person['billing']['lastname'] = self::$faker->lastName();
36-
37-
// 50% chance
38-
if ( (bool) wp_rand( 0, 1 ) ) {
39-
$person['shipping']['firstname'] = self::$faker->firstName( self::$faker->randomElement( array( 'male', 'female' ) ) );
40-
$person['shipping']['lastname'] = self::$faker->lastName();
41-
} else {
42-
$person['shipping']['firstname'] = $person['billing']['firstname'];
43-
$person['shipping']['lastname'] = $person['billing']['lastname'];
25+
$args = filter_var_array(
26+
$assoc_args,
27+
array(
28+
'country' => array(
29+
'filter' => FILTER_VALIDATE_REGEXP,
30+
'options' => array(
31+
'regexp' => '/^[A-Za-z]{2}$/',
32+
'default' => '',
33+
),
34+
),
35+
'type' => array(
36+
'filter' => FILTER_VALIDATE_REGEXP,
37+
'options' => array(
38+
'regexp' => '/^(company|person)$/',
39+
),
40+
),
41+
)
42+
);
43+
44+
list( 'country' => $country, 'type' => $type ) = $args;
45+
46+
$country = CustomerInfo::get_valid_country_code( $country );
47+
if ( is_wp_error( $country ) ) {
48+
return $country;
4449
}
4550

46-
/*COMPANY*/
47-
$company_variations = array( 'B2B', 'C2C', 'C2B', 'B2C' );
48-
$relationType = self::$faker->randomElements( $company_variations, $count = 1 );
51+
if ( ! $type ) {
52+
$type = self::$faker->randomDigit() < 7 ? 'person' : 'company'; // 70% person, 30% company.
53+
}
4954

50-
switch ( $relationType[0] ) {
51-
case 'B2B':
52-
$company['billing']['company_name'] = self::$faker->company();
53-
if ( self::$faker->randomFloat( 0, 0, 1 ) == 1 ) {
54-
$company['shipping']['company_name'] = self::$faker->company();
55-
} else {
56-
$company['shipping']['company_name'] = $company['billing']['company_name'];
57-
}
55+
$keys_for_address = array( 'email' );
5856

59-
break;
60-
case 'C2C':
61-
$company['billing']['company_name'] = '';
62-
$company['shipping']['company_name'] = '';
63-
break;
64-
case 'B2C':
65-
$company['billing']['company_name'] = self::$faker->company();
66-
$company['shipping']['company_name'] = '';
67-
break;
68-
case 'C2B':
69-
$company['billing']['company_name'] = '';
70-
$company['shipping']['company_name'] = self::$faker->company();
71-
break;
57+
$customer_data = array(
58+
'role' => 'customer',
59+
);
60+
switch ( $type ) {
61+
case 'person':
7262
default:
63+
$customer_data = array_merge( $customer_data, CustomerInfo::generate_person( $country ) );
64+
$other_customer_data = CustomerInfo::generate_person( $country );
65+
$keys_for_address[] = 'first_name';
66+
$keys_for_address[] = 'last_name';
67+
break;
68+
69+
case 'company':
70+
$customer_data = array_merge( $customer_data, CustomerInfo::generate_company( $country ) );
71+
$other_customer_data = CustomerInfo::generate_company( $country );
72+
$keys_for_address[] = 'company';
7373
break;
7474
}
75-
/*ADDRESS*/
76-
$address['billing']['address0'] = self::$faker->buildingNumber() . ' ' . self::$faker->streetName();
77-
$address['billing']['address1'] = self::$faker->streetAddress();
78-
$address['billing']['city'] = self::$faker->city();
79-
$address['billing']['state'] = self::$faker->stateAbbr();
80-
$address['billing']['postcode'] = self::$faker->postcode();
81-
$address['billing']['country'] = self::$faker->countryCode();
82-
$address['billing']['phone'] = self::$faker->e164PhoneNumber();
83-
$address['billing']['email'] = $email;
84-
85-
// 50% chance
86-
if ( (bool) wp_rand( 0, 1 ) ) {
87-
$address['shipping']['address0'] = self::$faker->buildingNumber() . ' ' . self::$faker->streetName();
88-
$address['shipping']['address1'] = self::$faker->streetAddress();
89-
$address['shipping']['city'] = self::$faker->city();
90-
$address['shipping']['state'] = self::$faker->stateAbbr();
91-
$address['shipping']['postcode'] = self::$faker->postcode();
92-
$address['shipping']['country'] = self::$faker->countryCode();
93-
} else {
94-
$address['shipping']['address0'] = $address['billing']['address0'];
95-
$address['shipping']['address1'] = $address['billing']['address1'];
96-
$address['shipping']['city'] = $address['billing']['city'];
97-
$address['shipping']['state'] = $address['billing']['state'];
98-
$address['shipping']['postcode'] = $address['billing']['postcode'];
99-
$address['shipping']['country'] = $address['billing']['country'];
75+
76+
$customer_data['billing'] = array_merge(
77+
CustomerInfo::generate_address( $country ),
78+
array_intersect_key( $customer_data, array_fill_keys( $keys_for_address, '' ) )
79+
);
80+
81+
$has_shipping = self::$faker->randomDigit() < 5;
82+
if ( $has_shipping ) {
83+
$same_shipping = self::$faker->randomDigit() < 5;
84+
if ( $same_shipping ) {
85+
$customer_data['shipping'] = $customer_data['billing'];
86+
} else {
87+
$customer_data['shipping'] = array_merge(
88+
CustomerInfo::generate_address( $country ),
89+
array_intersect_key( $other_customer_data, array_fill_keys( $keys_for_address, '' ) )
90+
);
91+
}
92+
}
93+
94+
unset( $customer_data['company'], $customer_data['shipping']['email'] );
95+
96+
foreach ( array( 'billing', 'shipping' ) as $address_type ) {
97+
if ( isset( $customer_data[ $address_type ] ) ) {
98+
$address_data = array_combine(
99+
array_map(
100+
fn( $line ) => $address_type . '_' . $line,
101+
array_keys( $customer_data[ $address_type ] )
102+
),
103+
array_values( $customer_data[ $address_type ] )
104+
);
105+
106+
$customer_data = array_merge( $customer_data, $address_data );
107+
unset( $customer_data[ $address_type ] );
108+
}
100109
}
101110

102111
$customer = new \WC_Customer();
103-
104-
$customer->set_props(
105-
array(
106-
'date_created' => null,
107-
'date_modified' => null,
108-
'email' => $email,
109-
'first_name' => $person['billing']['firstname'],
110-
'last_name' => $person['billing']['lastname'],
111-
'display_name' => $person['billing']['firstname'],
112-
'role' => 'customer',
113-
'username' => $username,
114-
'password' => self::$faker->password(),
115-
'billing_first_name' => $person['billing']['firstname'],
116-
'billing_last_name' => $person['billing']['lastname'],
117-
'billing_company' => $company['billing']['company_name'],
118-
'billing_address_0' => $address['billing']['address0'],
119-
'billing_address_1' => $address['billing']['address1'],
120-
'billing_city' => $address['billing']['city'],
121-
'billing_state' => $address['billing']['state'],
122-
'billing_postcode' => $address['billing']['postcode'],
123-
'billing_country' => $address['billing']['country'],
124-
'billing_email' => $address['billing']['email'],
125-
'billing_phone' => $address['billing']['phone'],
126-
'shipping_first_name' => $person['shipping']['firstname'],
127-
'shipping_last_name' => $person['shipping']['lastname'],
128-
'shipping_company' => $company['shipping']['company_name'],
129-
'shipping_address_0' => $address['shipping']['address0'],
130-
'shipping_address_1' => $address['shipping']['address1'],
131-
'shipping_city' => $address['shipping']['city'],
132-
'shipping_state' => $address['shipping']['state'],
133-
'shipping_postcode' => $address['shipping']['postcode'],
134-
'shipping_country' => $address['shipping']['country'],
135-
'is_paying_customer' => false,
136-
)
137-
);
112+
$customer->set_props( $customer_data );
138113

139114
if ( $save ) {
140115
$customer->save();
@@ -155,11 +130,12 @@ public static function generate( $save = true ) {
155130
/**
156131
* Create multiple customers.
157132
*
158-
* @param int $amount The number of customers to create.
133+
* @param int $amount The number of customers to create.
134+
* @param array $args Additional args for customer creation.
159135
*
160136
* @return int[]|\WP_Error
161137
*/
162-
public static function batch( $amount ) {
138+
public static function batch( $amount, array $args = array() ) {
163139
$amount = self::validate_batch_amount( $amount );
164140
if ( is_wp_error( $amount ) ) {
165141
return $amount;
@@ -168,7 +144,10 @@ public static function batch( $amount ) {
168144
$customer_ids = array();
169145

170146
for ( $i = 1; $i <= $amount; $i++ ) {
171-
$customer = self::generate( true );
147+
$customer = self::generate( true, $args );
148+
if ( is_wp_error( $customer ) ) {
149+
return $customer;
150+
}
172151
$customer_ids[] = $customer->get_id();
173152
}
174153

0 commit comments

Comments
 (0)