PluginProbe ʕ •ᴥ•ʔ
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress / 4.0.3
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress v4.0.3
4.17.2 4.17.1 4.17.0 4.16.19 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 4 years ago CheckoutController.php 4 years ago CheckoutResponse.php 4 years ago CheckoutSessionData.php 4 years ago CheckoutTrait.php 4 years ago FrontendController.php 4 years ago SubscriptionPlanController.php 4 years ago index.php 4 years ago
CheckoutTrait.php
467 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
26 trait CheckoutTrait
27 {
28 public function cleanup_posted_data($POST)
29 {
30 // cleanup $_POST
31 unset($POST['_wp_http_referer']);
32 unset($POST['action']);
33 unset($POST['ppress_checkout_nonce']);
34 // remove checkout login form fields
35 unset($POST['ppmb_user_login']);
36 unset($POST['ppmb_user_pass']);
37 //remove hidden required fields
38 unset($POST['required-fields']);
39
40 return ppress_clean($POST, 'trim');
41 }
42
43 public function alert_message($messages, $type = 'error')
44 {
45 if (empty($messages)) return '';
46
47 $alert = sprintf('<div class="ppress-checkout-alert ppress-%s">', $type);
48
49 if (is_array($messages) && count($messages) > 1) {
50 $alert .= '<ul>';
51 foreach ($messages as $message) {
52 $alert .= sprintf('<li>%s</li>', $message);
53 }
54 $alert .= '</ul>';
55 }
56
57 if (is_array($messages) && 1 == count($messages)) {
58 $alert .= sprintf('<p>%s</p>', $messages[0]);
59 }
60
61 if (is_string($messages)) {
62 $alert .= sprintf('<p>%s</p>', $messages);
63 }
64
65 $alert .= '</div>';
66
67 return $alert;
68 }
69
70 public function should_skip_validation($field_key, $field_settings)
71 {
72 if (is_user_logged_in() && ((ppress_var($field_settings, 'logged_in_hide') == 'true') || in_array($field_key, CF::logged_in_hidden_fields()))) {
73 return true;
74 }
75
76 return false;
77 }
78
79 public function validate_required_field($field_key, $field_type)
80 {
81 if ('file' == $field_type && ! empty($_FILES[$field_key]['name'])) {
82 return true;
83 }
84
85 if (ppress_is_boolean($_POST[$field_key]) || ! empty($_POST[$field_key])) {
86 return true;
87 }
88
89 return false;
90 }
91
92 /**
93 * @param int $customer_id
94 * @param CartEntity $cart_vars
95 *
96 * @return int|\WP_Error
97 */
98 public function create_subscription($customer_id, $cart_vars)
99 {
100 $plan_obj = ppress_get_plan((int)$_POST['plan_id']);
101 $plan_id = $plan_obj->id;
102
103 // delete all pending subs of plan_id by customer
104 SubscriptionRepository::init()->delete_pending_subs($customer_id, $plan_id);
105
106 $subscription = new SubscriptionEntity();
107
108 $subscription->plan_id = $plan_id;
109
110 $subscription->customer_id = $customer_id;
111 $subscription->billing_frequency = $plan_obj->billing_frequency;
112 $subscription->initial_amount = $cart_vars->initial_amount;
113 $subscription->initial_tax_rate = $cart_vars->initial_tax_rate;
114 $subscription->initial_tax = $cart_vars->initial_tax;
115
116 $subscription->recurring_amount = $cart_vars->recurring_amount;
117 $subscription->recurring_tax = $cart_vars->recurring_tax;
118 $subscription->recurring_tax_rate = $cart_vars->recurring_tax_rate;
119
120 $subscription->total_payments = $plan_obj->total_payments;
121 $subscription->trial_period = $plan_obj->has_free_trial() ? $plan_obj->free_trial : SubscriptionTrialPeriod::DISABLED;
122
123 $subscription->status = SubscriptionStatus::PENDING;
124
125 $subscription->expiration_date = SubscriptionService::init()->get_plan_expiration_datetime($plan_id);
126
127 if (Calculator::init($subscription->recurring_amount)->isNegativeOrZero()) {
128 $subscription->expiration_date = '';
129 }
130
131 $subscription_id = $subscription->save();
132
133 if ( ! $subscription_id || ! is_int($subscription_id)) {
134 return new \WP_Error('subscription_creation_failed', esc_html__('Unable to create subscription. Please try again', 'wp-user-avatar'));
135 }
136
137 return $subscription_id;
138 }
139
140 /**
141 * @param $customer_id
142 * @param CartEntity $cart_vars
143 *
144 * @return int|\WP_Error
145 */
146 public function create_order($customer_id, $cart_vars)
147 {
148 $plan_id = (int)$_POST['plan_id'];
149
150 $payment_method = sanitize_text_field(ppressPOST_var('ppress_payment_method', StoreGateway::get_instance()->get_id(), true));
151
152 // delete all pending orders of plan_id by customer
153 OrderRepository::init()->delete_pending_orders($customer_id, $plan_id);
154
155 $billing_fields = CheckoutFields::standard_billing_fields();
156
157 $order = new OrderEntity();
158
159 if (is_array($billing_fields) && ! empty($billing_fields)) {
160 foreach ($billing_fields as $field_key => $field) {
161 $posted_field = $payment_method . '_' . $field_key;
162 if ((isset($_POST[$posted_field]) && ppress_is_boolean($_POST[$posted_field])) || ! empty($_POST[$posted_field])) {
163
164 $key = str_replace('ppress_', '', $field_key);
165
166 $order->$key = ppress_clean($_POST[$posted_field]);
167 }
168 }
169 }
170
171 $order->order_key = OrderService::init()->generate_order_key();
172 $order->plan_id = $plan_id;
173 $order->customer_id = $customer_id;
174 $order->order_type = OrderType::NEW_ORDER;
175 $order->mode = ppress_get_payment_mode();
176 $order->payment_method = sanitize_text_field($payment_method);
177 $order->status = OrderStatus::PENDING;
178 $order->coupon_code = $cart_vars->coupon_code;
179 $order->discount = $cart_vars->discount_amount;
180 $order->subtotal = $cart_vars->sub_total;
181 $order->tax = $cart_vars->tax_amount;
182 $order->tax_rate = $cart_vars->tax_rate;
183 $order->total = $cart_vars->total;
184 $order->currency = ppress_get_currency();
185 $order->ip_address = ppress_get_ip_address();
186 $order_id = $order->save();
187
188 if ( ! $order_id || ! is_int($order_id)) {
189 return new \WP_Error('order_creation_failed', esc_html__('Unable to create order. Please try again', 'wp-user-avatar'));
190 }
191
192 return $order_id;
193 }
194
195 /**
196 * @param $user_id
197 *
198 * @return int|\WP_Error
199 */
200 public function create_customer($user_id)
201 {
202 $customer = CustomerFactory::fromUserId($user_id);
203
204 $customer_id = $customer->get_id();
205
206 if ( ! $customer->exists()) {
207 $customer->user_id = $user_id;
208 $customer_id = $customer->save();
209 if ( ! $customer_id) {
210 return new \WP_Error('customer_creation_failure', esc_html__('Unable to create customer. Please try again', 'wp-user-avatar'));
211 }
212 }
213
214 return $customer_id;
215 }
216
217 public function register_update_user()
218 {
219 $error_bucket = new \WP_Error();
220
221 $is_user_update = false;
222
223 $billing_fields = CF::billing_fields();
224 $account_info_fields = CF::account_info_fields();
225
226 $should_validate_fields = [];
227
228 // --------START --------- validation for required fields ----------------------//
229 foreach ($account_info_fields as $field_key => $field_settings) {
230
231 if ($this->should_skip_validation($field_key, $field_settings)) continue;
232
233 $should_validate_fields[] = $field_key;
234
235 if (ppress_var($field_settings, 'required') == 'true') {
236
237 if ( ! $this->validate_required_field($field_key, $field_settings['field_type'])) {
238 $error_bucket->add('required_field_empty', sprintf(__('%s field is required', 'wp-user-avatar'), $field_settings['label']));
239 }
240 }
241 }
242
243 $payment_method = ppressPOST_var('ppress_payment_method', '');
244
245 if (apply_filters('ppress_checkout_billing_validation', true, $billing_fields)) {
246 foreach ($billing_fields as $field_key => $field_settings) {
247
248 if ($this->should_skip_validation($field_key, $field_settings)) continue;
249
250 $should_validate_fields[] = $field_key;
251
252 if (ppress_var($field_settings, 'required') == 'true') {
253 // add payment method id from billing field IDs so validation will work.
254 if ( ! empty($payment_method)) $field_key = $payment_method . '_' . $field_key;
255
256 if ( ! $this->validate_required_field($field_key, $field_settings['field_type'])) {
257 $error_bucket->add('required_field_empty', sprintf(__('%s field is required', 'wp-user-avatar'), $field_settings['label']));
258 }
259 }
260 }
261 }
262
263 if ($error_bucket->has_errors()) {
264 return $error_bucket;
265 }
266
267 // --------END --------- validation for required fields ----------------------//
268
269
270 // --------START --------- validation ----------------------//
271 $email = ppressPOST_var(CF::ACCOUNT_EMAIL_ADDRESS, '');
272 $email2 = ppressPOST_var(CF::ACCOUNT_CONFIRM_EMAIL_ADDRESS, '');
273
274 if (in_array(CF::ACCOUNT_EMAIL_ADDRESS, $should_validate_fields)) {
275
276 if (isset($_POST[CF::ACCOUNT_CONFIRM_EMAIL_ADDRESS]) && ($email != $email2)) {
277 $error_bucket->add('email_mismatch', esc_html__('Email addresses do not match', 'wp-user-avatar'));
278 } elseif ( ! is_email($email)) {
279 $error_bucket->add('invalid_email', esc_html__('Email address is not valid', 'wp-user-avatar'));
280 } elseif (email_exists($email)) {
281 $error_bucket->add('email_used', esc_html__('Email already used. Login or use a different email to complete your order', 'wp-user-avatar'));
282 }
283 }
284
285 if (in_array(CF::ACCOUNT_USERNAME, $should_validate_fields)) {
286
287 $username = ppressPOST_var(CF::ACCOUNT_USERNAME, '');
288
289 if (empty($username)) {
290 $username = sanitize_user(current(explode('@', $email)), true);
291 // Ensure username is unique.
292 $append = 1;
293 $o_username = $username;
294 while (username_exists($username)) {
295 $username = $o_username . $append;
296 $append++;
297 }
298 }
299
300 if ( ! validate_username($username)) {
301 $error_bucket->add('invalid_username', esc_html__('Username is invalid because it uses illegal characters', 'wp-user-avatar'));
302 }
303 }
304
305 if (in_array(CF::ACCOUNT_PASSWORD, $should_validate_fields)) {
306
307 $password = ppressPOST_var(CF::ACCOUNT_PASSWORD, '');
308 $password2 = ppressPOST_var(CF::ACCOUNT_CONFIRM_PASSWORD, '');
309
310 if (isset($_POST[CF::ACCOUNT_CONFIRM_PASSWORD]) && ($password != $password2)) {
311 $error_bucket->add('password_mismatch', esc_html__('Passwords do not match', 'wp-user-avatar'));
312 }
313
314 $flag_to_send_password_reset = false;
315
316 if (empty($password) && (ppressPOST_var('ppmb_password_present') != 'true')) {
317 $password = wp_generate_password(24);
318 $flag_to_send_password_reset = apply_filters('ppress_enable_auto_send_password_reset_flag', true);
319 }
320 }
321
322 // --------END --------- validation ----------------------//
323
324 // --------START --------- validation for file upload ----------------------//
325 $uploads = FileUploader::init();
326 if ( ! empty($uploads)) {
327 foreach ($uploads as $field_key => $uploaded_filename_or_wp_error) {
328 if (is_wp_error($uploads[$field_key])) {
329 $error_bucket->add('file_upload_error', $uploads[$field_key]->get_error_message());
330 }
331 }
332 }
333 // --------END --------- validation for file upload ----------------------//
334
335 if ($error_bucket->has_errors()) {
336 return $error_bucket;
337 }
338
339 $valid_userdata_fields = array_keys(CF::standard_account_info_fields()) + ['ppmb_password_present'];
340
341 $real_userdata = array_filter(apply_filters('ppress_checkout_registration_user_data', [
342 'user_login' => isset($username) ? $username : '',
343 'user_pass' => isset($password) ? $password : '',
344 'user_email' => $email,
345 'user_url' => ppressPOST_var(CF::ACCOUNT_WEBSITE, ''),
346 'nickname' => ppressPOST_var(CF::ACCOUNT_NICKNAME, ''),
347 'display_name' => ppressPOST_var(CF::ACCOUNT_DISPLAY_NAME, ''),
348 'first_name' => ppressPOST_var(CF::ACCOUNT_FIRST_NAME, ''),
349 'last_name' => ppressPOST_var(CF::ACCOUNT_LAST_NAME, ''),
350 'description' => ppressPOST_var(CF::ACCOUNT_BIO, ''),
351 ]));
352
353 // get the data for use by update_meta
354 $custom_usermeta = [];
355
356 // loop over the $_POST data and create an array of the invalid userdata/ custom usermeta
357 foreach ($_POST as $key => $value) {
358
359 // remove payment method prefix from key
360 $key = str_replace($payment_method . '_', '', $key);
361
362 if (in_array($key, $valid_userdata_fields) || in_array($key, ppress_reserved_field_keys())) continue;
363
364 if ( ! in_array($key, array_keys(ppress_custom_fields_key_value_pair(true)))) continue;
365
366 $custom_usermeta[$key] = is_array($value) ? array_map('sanitize_textarea_field', $value) : sanitize_textarea_field($value);
367 }
368
369 // merge real data(for use by wp_insert_user()) and custom fields data
370 // $real_userdata comes second so custom user meta won't override it.
371 $user_data = array_merge($custom_usermeta, $real_userdata);
372
373 $reg_form_errors = apply_filters('ppress_checkout_registration_validation', $error_bucket, $user_data);
374
375 if (is_wp_error($reg_form_errors) && $reg_form_errors->get_error_code() != '') {
376 return $reg_form_errors->get_error_message();
377 }
378
379 do_action('ppress_before_checkout_registration', $user_data);
380
381 if (is_user_logged_in()) {
382 $user_id = get_current_user_id();
383 $is_user_update = true;
384 $real_userdata['ID'] = $user_id;
385 $user_id = wp_update_user($real_userdata);
386 } else {
387 $user_id = wp_insert_user($real_userdata);
388 }
389
390 if (is_wp_error($user_id)) {
391 return $user_id->get_error_message();
392 }
393
394 $customer_id = $this->create_customer($user_id);
395
396 // --------START --------- register custom field ----------------------//
397
398 // if we get to this point, it means the files pass validation defined above.
399 // array of files uploaded. Array key is the "custom field key" and the filename as the array value.
400 $custom_usermeta['pp_uploaded_files'] = $uploads;
401
402 if (is_array($custom_usermeta)) {
403
404 foreach ($custom_usermeta as $key => $value) {
405 if ( ! empty($value)) {
406 update_user_meta($user_id, $key, $value);
407 do_action('ppress_after_custom_field_update', $key, $value, $user_id, 'checkout');
408 }
409 }
410 }
411
412 // --------END --------- register custom field ----------------------//
413
414 if (isset($flag_to_send_password_reset, $username) && $flag_to_send_password_reset === true) {
415 PasswordReset::retrieve_password_func($username);
416 }
417
418 if ( ! $is_user_update && isset($user_id, $password)) {
419 // record signup via
420 add_user_meta($user_id, '_pp_signup_via', 'checkout');
421
422 RegistrationAuth::send_welcome_email($user_id, $password);
423
424 ppress_wp_new_user_notification($user_id, null, 'admin');
425 }
426
427 return $customer_id;
428 }
429
430 public function save_eu_vat_details($payment_method_id, $order_id)
431 {
432 $key = sprintf('%s_ppress_vat_number', $payment_method_id);
433
434 if ( ! empty($_POST[$key])) {
435
436 $order = OrderFactory::fromId($order_id);
437 $vat_number = sanitize_text_field($_POST[$key]);
438
439 $vat_data = CheckoutSessionData::get_eu_vat_number_details($order->plan_id, $vat_number);
440
441 $order->update_meta(OrderEntity::EU_VAT_NUMBER, sanitize_text_field($_POST[$key]));
442
443 $order->update_meta(
444 OrderEntity::EU_VAT_COUNTRY_CODE,
445 ppress_var($vat_data, 'country_code', '')
446 );
447
448 $order->update_meta(
449 OrderEntity::EU_VAT_NUMBER_IS_VALID,
450 ppress_var($vat_data, 'is_valid') === true ? 'true' : 'false'
451 );
452
453 $order->update_meta(
454 OrderEntity::EU_VAT_IS_REVERSE_CHARGED,
455 ppress_var($vat_data, 'reverse_charged') === true ? 'true' : 'false'
456 );
457
458 if ( ! empty($vat_data['company_name'])) {
459 $order->update_meta(OrderEntity::EU_VAT_COMPANY_NAME, sanitize_text_field($vat_data['company_name']));
460 }
461
462 if ( ! empty($vat_data['company_address'])) {
463 $order->update_meta(OrderEntity::EU_VAT_COMPANY_ADDRESS, sanitize_text_field($vat_data['company_address']));
464 }
465 }
466 }
467 }