PluginProbe ʕ •ᴥ•ʔ
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress / trunk
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress vtrunk
4.16.18 4.16.17 4.16.16 trunk 1.0 1.0.1 1.0.2 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5a 1.1.6 1.1.7 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.4 1.4.1 1.4.2 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.7 1.7.1 1.7.2 1.8 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.1.9 2.2.10 2.2.11 2.2.12 2.2.13 2.2.14 2.2.15 2.2.16 2.2.2 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 3.0 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.13.3 4.13.4 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.15.0 4.15.1 4.15.10 4.15.11 4.15.12 4.15.13 4.15.14 4.15.15 4.15.16 4.15.17 4.15.18 4.15.19 4.15.2 4.15.20 4.15.20.1 4.15.21 4.15.22 4.15.23 4.15.24 4.15.25 4.15.3 4.15.4 4.15.5 4.15.6 4.15.7 4.15.8 4.15.9 4.16.0 4.16.1 4.16.10 4.16.11 4.16.12 4.16.13 4.16.14 4.16.15 4.16.2 4.16.3 4.16.4 4.16.5 4.16.6 4.16.7 4.16.8 4.16.9 4.2.0 4.3.0 4.3.1 4.3.2 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.7.0 4.8.0 4.9.0
wp-user-avatar / src / Membership / Controllers / CheckoutTrait.php
wp-user-avatar / src / Membership / Controllers Last commit date
BaseController.php 3 years ago CheckoutController.php 2 months ago CheckoutResponse.php 3 years ago CheckoutSessionData.php 3 years ago CheckoutTrait.php 2 months ago FrontendController.php 1 week ago SubscriptionPlanController.php 2 months ago index.php 3 years ago
CheckoutTrait.php
519 lines
1 <?php
2
3 namespace ProfilePress\Core\Membership\Controllers;
4
5 use ProfilePress\Core\Classes\FileUploader;
6 use ProfilePress\Core\Classes\PasswordReset;
7 use ProfilePress\Core\Classes\RegistrationAuth;
8 use ProfilePress\Core\Membership\CheckoutFields;
9 use ProfilePress\Core\Membership\CheckoutFields as CF;
10 use ProfilePress\Core\Membership\Models\Customer\CustomerFactory;
11 use ProfilePress\Core\Membership\Models\Order\CartEntity;
12 use ProfilePress\Core\Membership\Models\Order\OrderEntity;
13 use ProfilePress\Core\Membership\Models\Order\OrderFactory;
14 use ProfilePress\Core\Membership\Models\Order\OrderStatus;
15 use ProfilePress\Core\Membership\Models\Order\OrderType;
16 use ProfilePress\Core\Membership\Models\Subscription\SubscriptionEntity;
17 use ProfilePress\Core\Membership\Models\Subscription\SubscriptionStatus;
18 use ProfilePress\Core\Membership\Models\Subscription\SubscriptionTrialPeriod;
19 use ProfilePress\Core\Membership\PaymentMethods\StoreGateway;
20 use ProfilePress\Core\Membership\Repositories\OrderRepository;
21 use ProfilePress\Core\Membership\Repositories\SubscriptionRepository;
22 use ProfilePress\Core\Membership\Services\Calculator;
23 use ProfilePress\Core\Membership\Services\OrderService;
24 use ProfilePress\Core\Membership\Services\SubscriptionService;
25 use ProfilePress\Libsodium\UserModeration\UserModeration;
26 use ProfilePress\Libsodium\UserModeration\UserModerationNotification;
27
28 trait CheckoutTrait
29 {
30 public function cleanup_posted_data($POST)
31 {
32 // cleanup $_POST
33 unset($POST['_wp_http_referer']);
34 unset($POST['action']);
35 unset($POST['ppress_checkout_nonce']);
36 // remove checkout login form fields
37 unset($POST['ppmb_user_login']);
38 unset($POST['ppmb_user_pass']);
39 //remove hidden required fields
40 unset($POST['required-fields']);
41
42 return ppress_clean($POST, 'trim');
43 }
44
45 public function alert_message($messages, $type = 'error')
46 {
47 if (empty($messages)) return '';
48
49 $alert = sprintf('<div class="ppress-checkout-alert ppress-%s">', $type);
50
51 if (is_array($messages) && count($messages) > 1) {
52 $alert .= '<ul>';
53 foreach ($messages as $message) {
54 $alert .= sprintf('<li>%s</li>', $message);
55 }
56 $alert .= '</ul>';
57 }
58
59 if (is_array($messages) && 1 == count($messages)) {
60 $alert .= sprintf('<p>%s</p>', $messages[0]);
61 }
62
63 if (is_string($messages)) {
64 $alert .= sprintf('<p>%s</p>', $messages);
65 }
66
67 $alert .= '</div>';
68
69 return $alert;
70 }
71
72 public function should_skip_validation($field_key, $field_settings)
73 {
74 if (is_user_logged_in() && ((ppress_var($field_settings, 'logged_in_hide') == 'true') || in_array($field_key, CF::logged_in_hidden_fields()))) {
75 return true;
76 }
77
78 return false;
79 }
80
81 public function validate_required_field($field_key, $field_type)
82 {
83 if ('file' == $field_type && ! empty($_FILES[$field_key]['name'])) {
84 return true;
85 }
86
87 if (ppress_is_boolean($_POST[$field_key]) || ! empty($_POST[$field_key])) {
88 return true;
89 }
90
91 return false;
92 }
93
94 /**
95 * @param int $customer_id
96 * @param CartEntity $cart_vars
97 *
98 * @return int|\WP_Error
99 */
100 public function create_subscription($customer_id, $cart_vars)
101 {
102 $plan_obj = ppress_get_plan((int)$_POST['plan_id']);
103 $plan_id = $plan_obj->id;
104
105 // delete all pending subs of plan_id by customer
106 SubscriptionRepository::init()->delete_pending_subs($customer_id, $plan_id);
107
108 $subscription = new SubscriptionEntity();
109
110 $subscription->plan_id = $plan_id;
111
112 $subscription->customer_id = $customer_id;
113 $subscription->billing_frequency = $plan_obj->billing_frequency;
114 $subscription->initial_amount = $cart_vars->initial_amount;
115 $subscription->initial_tax_rate = $cart_vars->initial_tax_rate;
116 $subscription->initial_tax = $cart_vars->initial_tax;
117
118 $subscription->recurring_amount = $cart_vars->recurring_amount;
119 $subscription->recurring_tax = $cart_vars->recurring_tax;
120 $subscription->recurring_tax_rate = $cart_vars->recurring_tax_rate;
121
122 $subscription->total_payments = $plan_obj->total_payments;
123 $subscription->trial_period = $plan_obj->has_free_trial() ? $plan_obj->free_trial : SubscriptionTrialPeriod::DISABLED;
124
125 $subscription->status = SubscriptionStatus::PENDING;
126
127 $subscription->expiration_date = SubscriptionService::init()->get_plan_expiration_datetime($plan_id);
128
129 if ($subscription->is_recurring() && Calculator::init($subscription->recurring_amount)->isNegativeOrZero()) {
130 $subscription->expiration_date = '';
131 }
132
133 $subscription_id = $subscription->save();
134
135 if ( ! $subscription_id || ! is_int($subscription_id)) {
136 return new \WP_Error('subscription_creation_failed', esc_html__('Unable to create subscription. Please try again', 'wp-user-avatar'));
137 }
138
139 return $subscription_id;
140 }
141
142 /**
143 * @param $customer_id
144 * @param CartEntity $cart_vars
145 *
146 * @return int|\WP_Error
147 */
148 public function create_order($customer_id, $cart_vars)
149 {
150 $plan_id = (int)$_POST['plan_id'];
151
152 $payment_method = sanitize_text_field(ppressPOST_var('ppress_payment_method', StoreGateway::get_instance()->get_id(), true));
153
154 // delete all pending orders of plan_id by customer
155 OrderRepository::init()->delete_pending_orders($customer_id, $plan_id);
156
157 $billing_fields = CheckoutFields::standard_billing_fields();
158
159 $order = new OrderEntity();
160
161 if (is_array($billing_fields) && ! empty($billing_fields)) {
162 foreach ($billing_fields as $field_key => $field) {
163 $posted_field = $payment_method . '_' . $field_key;
164 if ((isset($_POST[$posted_field]) && ppress_is_boolean($_POST[$posted_field])) || ! empty($_POST[$posted_field])) {
165
166 $key = str_replace('ppress_', '', $field_key);
167
168 $order->$key = ppress_strip_shortcodes_clean($_POST[$posted_field]);
169 }
170 }
171 }
172
173 $order_type = CheckoutSessionData::get_order_type($plan_id);
174
175 if ( ! $order_type) $order_type = OrderType::NEW_ORDER;
176
177 $order->order_key = OrderService::init()->generate_order_key();
178 $order->plan_id = $plan_id;
179 $order->customer_id = $customer_id;
180 $order->order_type = $order_type;
181 $order->mode = ppress_get_payment_mode();
182 $order->payment_method = sanitize_text_field($payment_method);
183 $order->status = OrderStatus::PENDING;
184 $order->coupon_code = $cart_vars->coupon_code;
185 $order->discount = $cart_vars->discount_amount;
186 $order->subtotal = $cart_vars->sub_total;
187 $order->tax = $cart_vars->tax_amount;
188 $order->tax_rate = $cart_vars->tax_rate;
189 $order->total = $cart_vars->total;
190 $order->currency = ppress_get_currency();
191 $order->ip_address = ppress_get_ip_address();
192 $order_id = $order->save();
193
194 if ( ! $order_id || ! is_int($order_id)) {
195 return new \WP_Error('order_creation_failed', esc_html__('Unable to create order. Please try again', 'wp-user-avatar'));
196 }
197
198 return $order_id;
199 }
200
201 /**
202 * @return int|\WP_Error
203 */
204 public function register_update_user()
205 {
206 $error_bucket = new \WP_Error();
207
208 $is_user_update = false;
209
210 $billing_fields = CF::billing_fields();
211 $account_info_fields = CF::account_info_fields();
212
213 $should_validate_fields = [];
214
215 if ( ! is_user_logged_in() && apply_filters('ppress_checkout_is_registration_checked_enabled', true) && ! get_option('users_can_register')) {
216 $error_bucket->add('registration_disabled', esc_html__('Registration is disabled', 'wp-user-avatar'));
217 }
218
219 // --------START --------- validation for required fields ----------------------//
220 foreach ($account_info_fields as $field_key => $field_settings) {
221
222 if ($this->should_skip_validation($field_key, $field_settings)) continue;
223
224 if (apply_filters('ppress_checkout_disable_validate_field_' . $field_key, false)) continue;
225
226 $should_validate_fields[] = $field_key;
227
228 if (ppress_var($field_settings, 'required') == 'true') {
229
230 if ( ! $this->validate_required_field($field_key, $field_settings['field_type'])) {
231 $error_bucket->add('required_field_empty', sprintf(__('%s field is required', 'wp-user-avatar'), $field_settings['label']));
232 }
233 }
234 }
235
236 $payment_method = ppressPOST_var('ppress_payment_method', '');
237
238 if (apply_filters('ppress_checkout_billing_validation', true, $billing_fields)) {
239 foreach ($billing_fields as $field_key => $field_settings) {
240
241 if ($this->should_skip_validation($field_key, $field_settings)) continue;
242
243 $should_validate_fields[] = $field_key;
244
245 if (ppress_var($field_settings, 'required') == 'true') {
246 // add payment method id from billing field IDs so validation will work.
247 if ( ! empty($payment_method)) $field_key = $payment_method . '_' . $field_key;
248
249 if ( ! $this->validate_required_field($field_key, $field_settings['field_type'])) {
250 $error_bucket->add('required_field_empty', sprintf(__('%s field is required', 'wp-user-avatar'), $field_settings['label']));
251 }
252 }
253 }
254 }
255
256 if ($error_bucket->has_errors()) {
257 return $error_bucket;
258 }
259
260 // --------END --------- validation for required fields ----------------------//
261
262
263 // --------START --------- validation ----------------------//
264 $email = ppressPOST_var(CF::ACCOUNT_EMAIL_ADDRESS, '');
265 $email2 = ppressPOST_var(CF::ACCOUNT_CONFIRM_EMAIL_ADDRESS, '');
266
267 if (in_array(CF::ACCOUNT_EMAIL_ADDRESS, $should_validate_fields)) {
268
269 if (isset($_POST[CF::ACCOUNT_CONFIRM_EMAIL_ADDRESS]) && ($email != $email2)) {
270 $error_bucket->add('email_mismatch', esc_html__('Email addresses do not match', 'wp-user-avatar'));
271 } elseif ( ! is_email($email)) {
272 $error_bucket->add('invalid_email', esc_html__('Email address is not valid', 'wp-user-avatar'));
273 } elseif (email_exists($email)) {
274 $error_bucket->add('email_used', esc_html__('Email already used. Login or use a different email to complete your order', 'wp-user-avatar'));
275 }
276 }
277
278 if (in_array(CF::ACCOUNT_USERNAME, $should_validate_fields)) {
279
280 $username = ppressPOST_var(CF::ACCOUNT_USERNAME, '');
281
282 if (empty($username)) {
283 $username = apply_filters('ppress_checkout_username', sanitize_user(current(explode('@', $email)), true), $email);
284 // Ensure username is unique.
285 $append = 1;
286 $o_username = $username;
287 while (username_exists($username)) {
288 $username = $o_username . $append;
289 $append++;
290 }
291 }
292
293 if ( ! validate_username($username)) {
294 $error_bucket->add('invalid_username', esc_html__('Username is invalid because it uses illegal characters', 'wp-user-avatar'));
295 }
296 }
297
298 if (in_array(CF::ACCOUNT_PASSWORD, $should_validate_fields)) {
299
300 $password = ppressPOST_var(CF::ACCOUNT_PASSWORD, '');
301 $password2 = ppressPOST_var(CF::ACCOUNT_CONFIRM_PASSWORD, '');
302
303 if (isset($_POST[CF::ACCOUNT_CONFIRM_PASSWORD]) && ($password != $password2)) {
304 $error_bucket->add('password_mismatch', esc_html__('Passwords do not match', 'wp-user-avatar'));
305 }
306
307 $flag_to_send_password_reset = false;
308
309 if (empty($password) && (ppressPOST_var('ppmb_password_present') != 'true')) {
310 $password = wp_generate_password(24);
311 $flag_to_send_password_reset = apply_filters('ppress_enable_auto_send_password_reset_flag', true);
312 }
313 }
314
315 // --------END --------- validation ----------------------//
316
317 // --------START --------- validation for file upload ----------------------//
318 $uploads = FileUploader::init();
319 if ( ! empty($uploads)) {
320 foreach ($uploads as $field_key => $uploaded_filename_or_wp_error) {
321 if (is_wp_error($uploaded_filename_or_wp_error)) {
322 $error_bucket->add('file_upload_error', $uploaded_filename_or_wp_error->get_error_message());
323 }
324 }
325 }
326 // --------END --------- validation for file upload ----------------------//
327
328 if ($error_bucket->has_errors()) {
329 return $error_bucket;
330 }
331
332 $valid_userdata_fields = array_keys(CF::standard_account_info_fields()) + ['ppmb_password_present'];
333
334 $real_userdata = array_filter(apply_filters('ppress_checkout_registration_user_data', [
335 'user_login' => ! empty($username) ? $username : (is_user_logged_in() ? wp_get_current_user()->user_login : $email),
336 'user_pass' => $password ?? '',
337 'user_email' => $email,
338 'user_url' => ppressPOST_var(CF::ACCOUNT_WEBSITE, ''),
339 'nickname' => ppressPOST_var(CF::ACCOUNT_NICKNAME, ''),
340 'display_name' => ppressPOST_var(CF::ACCOUNT_DISPLAY_NAME, ''),
341 'first_name' => ppressPOST_var(CF::ACCOUNT_FIRST_NAME, ''),
342 'last_name' => ppressPOST_var(CF::ACCOUNT_LAST_NAME, ''),
343 'description' => ppressPOST_var(CF::ACCOUNT_BIO, ''),
344 ]));
345
346 // get the data for use by update_meta
347 $custom_usermeta = [];
348
349 // loop over the $_POST data and create an array of the invalid userdata/ custom usermeta
350 foreach ($_POST as $key => $value) {
351
352 if ( ! empty($payment_method)) {
353 // remove payment method prefix from key
354 $key = str_replace($payment_method . '_', '', $key);
355 }
356
357 if (in_array($key, $valid_userdata_fields) || in_array($key, ppress_reserved_field_keys())) continue;
358
359 if ( ! in_array($key, array_keys(ppress_custom_fields_key_value_pair(true)))) continue;
360
361 $custom_usermeta[$key] = ppress_strip_shortcodes_clean($value);
362 }
363
364 // merge real data(for use by wp_insert_user()) and custom fields data
365 // $real_userdata comes second so custom user meta won't override it.
366 $user_data = array_merge($custom_usermeta, $real_userdata);
367
368 $reg_form_errors = apply_filters('ppress_checkout_registration_validation', $error_bucket, $user_data);
369
370 if (is_wp_error($reg_form_errors) && $reg_form_errors->get_error_code() != '') {
371 return $reg_form_errors;
372 }
373
374 do_action('ppress_before_checkout_registration', $user_data);
375
376 if (is_user_logged_in()) {
377 $user_id = get_current_user_id();
378 $is_user_update = true;
379 $real_userdata['ID'] = $user_id;
380 $user_id = wp_update_user($real_userdata);
381
382 if (is_wp_error($user_id)) {
383 // because we sometimes save username the same as email, we dont want this error "Sorry, that username is not available" breaking checkout.
384 if ($user_id->get_error_code() == 'existing_user_email_as_login') {
385 $user_id = get_current_user_id();
386 } else {
387 return $user_id;
388 }
389 }
390
391 } else {
392 $user_id = wp_insert_user($real_userdata);
393
394 if (is_wp_error($user_id)) return $user_id;
395 }
396
397 $customer_id = ppress_create_customer($user_id);
398
399 // --------START --------- register custom field ----------------------//
400
401 if (is_user_logged_in()) {
402
403 $current_user_id = get_current_user_id();
404
405 // we get the old array of stored file for the user
406 $old = get_user_meta($current_user_id, 'pp_uploaded_files', true);
407 $old = ! empty($old) ? $old : [];
408 // we loop through the array of newly uploaded files and remove any file (un-setting the file array key)
409 // that isn't be updated i.e if the field is left empty, un-setting it prevent update_user_meta
410 // fom overriding it.
411 // we then merge the old and new uploads before saving the data to user meta table.
412 foreach ($uploads as $key => $value) {
413 if (empty($value)) {
414 unset($uploads[$key]);
415 }
416 }
417
418 $merged_data = array_merge($old, $uploads);
419
420 update_user_meta($current_user_id, 'pp_uploaded_files', $merged_data);
421 do_action('ppress_after_custom_field_update', 'pp_uploaded_files', $merged_data, $user_id, 'checkout');
422
423 } else {
424 // if we get to this point, it means the files pass validation defined above.
425 // array of files uploaded. Array key is the "custom field key" and the filename as the array value.
426 $custom_usermeta['pp_uploaded_files'] = $uploads;
427 }
428
429 if (is_array($custom_usermeta)) {
430
431 foreach ($custom_usermeta as $key => $value) {
432 if ( ! empty($value)) {
433 update_user_meta($user_id, $key, $value);
434 do_action('ppress_after_custom_field_update', $key, $value, $user_id, 'checkout');
435 }
436 }
437 }
438
439 // --------END --------- register custom field ----------------------//
440
441 if (isset($flag_to_send_password_reset, $username) && $flag_to_send_password_reset === true) {
442 PasswordReset::retrieve_password_func($username);
443 }
444
445 if ( ! $is_user_update && isset($user_id, $password)) {
446 // record signup via
447 add_user_meta($user_id, '_pp_signup_via', 'checkout');
448
449 $should_send_welcome_email = true;
450
451 // if moderation is active, set new registered users as pending
452 if (
453 class_exists('ProfilePress\Libsodium\UserModeration\UserModeration') &&
454 UserModeration::moderation_is_active() &&
455 apply_filters('ppress_checkout_registration_user_moderation_support', false, $user_id)
456 ) {
457
458 if (apply_filters('ppress_user_moderation_make_pending', true, 'checkout', $user_data)) {
459
460 $should_send_welcome_email = false;
461
462 UserModeration::make_pending($user_id);
463 UserModerationNotification::pending($user_id);
464 UserModerationNotification::pending_admin_notification($user_id);
465 }
466 }
467
468 if (apply_filters('ppress_registration_should_send_welcome_email', $should_send_welcome_email, $user_id, $user_data)) {
469 RegistrationAuth::send_welcome_email($user_id, $password, 'checkout');
470 }
471
472 ppress_wp_new_user_notification($user_id, null, 'admin');
473
474 /** Fires after a user registration is completed. */
475 do_action('ppress_after_registration', 0, $user_data, $user_id, false);
476 }
477
478 return $customer_id;
479 }
480
481 public function save_eu_vat_details($payment_method_id, $order_id)
482 {
483 $key = sprintf('%s_ppress_vat_number', $payment_method_id);
484
485 if ( ! empty($_POST[$key])) {
486
487 $order = OrderFactory::fromId($order_id);
488 $vat_number = sanitize_text_field($_POST[$key]);
489
490 $vat_data = CheckoutSessionData::get_eu_vat_number_details($order->plan_id, $vat_number);
491
492 $order->update_meta(OrderEntity::EU_VAT_NUMBER, sanitize_text_field($_POST[$key]));
493
494 $order->update_meta(
495 OrderEntity::EU_VAT_COUNTRY_CODE,
496 ppress_var($vat_data, 'country_code', '')
497 );
498
499 $order->update_meta(
500 OrderEntity::EU_VAT_NUMBER_IS_VALID,
501 ppress_var($vat_data, 'is_valid') === true ? 'true' : 'false'
502 );
503
504 $order->update_meta(
505 OrderEntity::EU_VAT_IS_REVERSE_CHARGED,
506 ppress_var($vat_data, 'reverse_charged') === true ? 'true' : 'false'
507 );
508
509 if ( ! empty($vat_data['company_name'])) {
510 $order->update_meta(OrderEntity::EU_VAT_COMPANY_NAME, sanitize_text_field($vat_data['company_name']));
511 }
512
513 if ( ! empty($vat_data['company_address'])) {
514 $order->update_meta(OrderEntity::EU_VAT_COMPANY_ADDRESS, sanitize_text_field($vat_data['company_address']));
515 }
516 }
517 }
518 }
519