PluginProbe
Tiered Pricing Table for WooCommerce / 8.0.2
Tiered Pricing Table for WooCommerce v8.0.2
8.0.2 7.1.7 7.1.5 7.1.4 7.1.1 6.5.0 6.4.0 6.1.0 trunk 1.0 1.1 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 2.3.1 2.3.2 2.3.3 All 91 releases
tier-pricing-table / src / Addons / NonLoggedInUsers / Wholesale / Services / ApplicationService.php

ApplicationService.php in Tiered Pricing Table for WooCommerce 8.0.2, at src/Addons/NonLoggedInUsers/Wholesale/Services/ApplicationService.php

231 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php namespace TierPricingTable\Addons\NonLoggedInUsers\Wholesale\Services;
2
3 use TierPricingTable\Addons\NonLoggedInUsers\Wholesale\Models\WholesaleApplication;
4 use TierPricingTable\Addons\NonLoggedInUsers\Wholesale\Settings\FormFields;
5 use TierPricingTable\Addons\NonLoggedInUsers\Wholesale\Settings\Settings;
6 use WC_Customer;
7 use WP_Error;
8 use WP_User;
9
10 /**
11 * Submits, approves and rejects wholesale applications.
12 */
13 class ApplicationService {
14
15 /**
16 * Whether the registration form has to ask for a password (WooCommerce can generate one instead).
17 */
18 public static function needsPassword(): bool {
19 return 'yes' !== get_option( 'woocommerce_registration_generate_password', 'yes' );
20 }
21
22 /**
23 * Handles a form submission: validates, creates the customer account for guests, stores the
24 * application, and approves it right away when the store approves automatically.
25 *
26 * @param array $input raw form values
27 * @param WP_User|null $currentUser the logged-in customer, or null for a guest
28 *
29 * @return WholesaleApplication|WP_Error
30 */
31 public function submit( array $input, ?WP_User $currentUser ) {
32 $isGuest = null === $currentUser;
33
34 $fields = Settings::getFormFields();
35
36 $validated = ApplicationValidator::validate( $input, array(
37 'fields' => $fields,
38 'isGuest' => $isGuest,
39 'needsPassword' => $isGuest && self::needsPassword(),
40 'needsTerms' => Settings::getTermsPageId() > 0,
41 'emailExists' => function ( string $email ): bool {
42 return false !== email_exists( $email );
43 },
44 ) );
45
46 if ( ! empty( $validated['errors'] ) ) {
47 $error = new WP_Error();
48
49 foreach ( $validated['errors'] as $field => $message ) {
50 $error->add( $field, $message );
51 }
52
53 return $error;
54 }
55
56 $data = $validated['data'];
57
58 if ( $isGuest ) {
59 $userId = $this->createCustomer( $data );
60
61 if ( is_wp_error( $userId ) ) {
62 return $userId;
63 }
64
65 $user = get_user_by( 'id', $userId );
66 } else {
67 $user = $currentUser;
68
69 $existing = WholesaleApplication::findForUser( $user->ID );
70
71 if ( $existing && $existing->isPending() ) {
72 return new WP_Error( 'pending', __( 'You already have a pending application.', 'tier-pricing-table' ) );
73 }
74
75 $data['first_name'] = $user->first_name;
76 $data['last_name'] = $user->last_name;
77 $data['email'] = $user->user_email;
78 }
79
80 $this->saveBusinessDetails( $user, $data );
81
82 // the recognised keys have their own meta; everything else the store owner added is kept as custom fields
83 $data['custom_fields'] = array();
84
85 foreach ( $fields as $field ) {
86 $key = (string) $field['key'];
87
88 if ( FormFields::isKnownKey( $key ) || ! array_key_exists( $key, $data ) ) {
89 continue;
90 }
91
92 $data['custom_fields'][ $key ] = array(
93 'label' => (string) $field['label'],
94 'type' => (string) $field['type'],
95 'value' => (string) $data[ $key ],
96 );
97
98 unset( $data[ $key ] );
99 }
100
101 $data['user_id'] = $user->ID;
102 $data['requested_role'] = Settings::getRole();
103 unset( $data['password'] );
104
105 $application = WholesaleApplication::create( $data );
106
107 if ( ! $application ) {
108 return new WP_Error( 'save', __( 'The application could not be saved. Please try again.', 'tier-pricing-table' ) );
109 }
110
111 do_action( 'tiered_pricing_table/wholesale/application_submitted', $application->getId(), $application );
112
113 if ( Settings::isAutoApproval() ) {
114 $this->approve( $application, 0 );
115 }
116
117 return $application;
118 }
119
120 /**
121 * @return int|WP_Error the new user id
122 */
123 protected function createCustomer( array $data ) {
124 $password = $data['password'] ?? '';
125
126 $userId = wc_create_new_customer( $data['email'], '', $password, array(
127 'first_name' => $data['first_name'],
128 'last_name' => $data['last_name'],
129 ) );
130
131 if ( is_wp_error( $userId ) ) {
132 return $userId;
133 }
134
135 return (int) $userId;
136 }
137
138 protected function saveBusinessDetails( WP_User $user, array $data ) {
139 try {
140 $customer = new WC_Customer( $user->ID );
141
142 if ( ! empty( $data['first_name'] ) && ! $customer->get_first_name() ) {
143 $customer->set_first_name( $data['first_name'] );
144 }
145
146 if ( ! empty( $data['last_name'] ) && ! $customer->get_last_name() ) {
147 $customer->set_last_name( $data['last_name'] );
148 }
149
150 if ( ! empty( $data['company'] ) ) {
151 $customer->set_billing_company( $data['company'] );
152 }
153
154 if ( ! empty( $data['phone'] ) ) {
155 $customer->set_billing_phone( $data['phone'] );
156 }
157
158 if ( ! empty( $data['website'] ) ) {
159 wp_update_user( array( 'ID' => $user->ID, 'user_url' => $data['website'] ) );
160 }
161
162 $customer->save();
163 } catch ( \Exception $e ) {
164 // the application still holds the details; the customer record is a convenience
165 unset( $e );
166 }
167 }
168
169 /**
170 * Gives the applicant the wholesale role and marks the application approved.
171 *
172 * @param int $decidedBy admin user id, 0 for automatic approval
173 */
174 public function approve( WholesaleApplication $application, int $decidedBy ): bool {
175 if ( $application->isApproved() ) {
176 return true;
177 }
178
179 $user = $application->getUser();
180 $role = $application->getRequestedRole() ?: Settings::getRole();
181
182 if ( ! $user || ! $role || ! wp_roles()->is_role( $role ) ) {
183 return false;
184 }
185
186 $user->set_role( $role );
187
188 if ( ! $application->setStatus( WholesaleApplication::STATUS_APPROVED, $decidedBy ) ) {
189 return false;
190 }
191
192 do_action( 'tiered_pricing_table/wholesale/application_approved', $application->getId(), $application, $decidedBy );
193
194 return true;
195 }
196
197 /**
198 * Marks the application rejected; the user keeps the role they have.
199 */
200 public function reject( WholesaleApplication $application, int $decidedBy, string $reason = '' ): bool {
201 if ( $application->isRejected() ) {
202 return true;
203 }
204
205 $role = $application->getRequestedRole() ?: Settings::getRole();
206 $user = $application->getUser();
207
208 // an approved application that is rejected later takes the role away again
209 if ( $application->isApproved() && $user && $role && in_array( $role, (array) $user->roles, true ) ) {
210 $user->set_role( 'customer' );
211 }
212
213 if ( ! $application->setStatus( WholesaleApplication::STATUS_REJECTED, $decidedBy, $reason ) ) {
214 return false;
215 }
216
217 do_action( 'tiered_pricing_table/wholesale/application_rejected', $application->getId(), $application, $decidedBy );
218
219 return true;
220 }
221
222 /**
223 * Whether the user already has the wholesale role.
224 */
225 public static function isWholesaleUser( ?WP_User $user ): bool {
226 $role = Settings::getRole();
227
228 return $user && $role && in_array( $role, (array) $user->roles, true );
229 }
230 }
231