PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | inc/class-lp-checkout.php +339 -538 4.1.7.24.4.8 View file →
@@ -6,45 +6,41 @@
6 6 * @package LearnPress/Classes
7 7 * @version 4.0.0
8 8 */
9 9
10 +use LearnPress\Helpers\Singleton;
11 +use LearnPress\Models\CourseModel;
12 +use LearnPress\Models\UserModel;
13 +
10 14 defined( 'ABSPATH' ) || exit;
11 15
12 16 class LP_Checkout {
17 + use Singleton;
13 18
14 19 /**
15 - * @var LP_Checkout object instance
16 - * @access protected
17 - */
18 - protected static $_instance = null;
19 -
20 - /**
21 20 * Payment method
22 21 *
23 - * @var string|LP_Gateway_Abstract
22 + * @var LP_Gateway_Abstract
24 23 */
25 24 public $payment_method = null;
26 -
27 25 /**
28 - * @var array|mixed|null|void
26 + * Payment method string when user choice
27 + *
28 + * @var string $payment_method_str
29 29 */
30 - protected $checkout_fields = array();
31 -
30 + public $payment_method_str = '';
32 31 /**
33 32 * @var null
34 33 */
35 34 public $user_login = null;
36 -
37 35 /**
38 36 * @var null
39 37 */
40 38 public $user_pass = null;
41 -
42 39 /**
43 40 * @var null
44 41 */
45 42 public $order_comment = null;
46 -
47 43 /**
48 44 * Handle the errors when checking out.
49 45 *
50 46 * @var array
@@ -49,32 +45,17 @@
49 45 *
50 46 * @var array
51 47 */
52 48 public $errors = array();
53 -
54 49 /**
55 50 * @var string
56 51 */
57 52 protected $_checkout_email = '';
58 -
59 53 /**
60 - * @var array
61 - * @since 4.0.0
62 - */
63 - protected $login_data = array();
64 -
65 - /**
66 - * @var array
67 - * @since 4.0.0
68 - */
69 - protected $register_data = array();
70 -
71 - /**
72 54 * @var string
73 55 * @since 4.0.0
74 56 */
75 57 protected $guest_email = '';
76 -
77 58 /**
78 59 * @var string
79 60 * @since 4.0.0
80 61 */
@@ -79,160 +60,141 @@
79 60 * @since 4.0.0
80 61 */
81 62 protected $checkout_action = '';
82 63
83 - /**
84 - * @var array
85 - * @since 4.0.0
86 - */
87 - protected $checkout_form_data = array();
88 -
89 - /**
90 - * Constructor
91 - */
92 - public function __construct() {
93 - add_filter( 'learn-press/validate-checkout-field', array( $this, 'validate_fields' ), 10, 3 );
94 - add_filter( 'learn-press/validate-checkout-fields', array( $this, 'check_validate_fields' ), 10, 3 );
95 - //add_filter( 'learn-press/payment-successful-result', array( $this, 'process_customer' ), 10, 2 );
96 -
64 + public function init(): void {
97 65 if ( ! is_null( LearnPress::instance()->session ) ) {
98 66 $this->_checkout_email = LearnPress::instance()->session->get( 'checkout-email' );
99 67 }
68 +
69 + add_action( 'set_logged_in_cookie', [ $this, 'set_logged_in_cookie' ] );
100 70 }
101 71
102 72 /**
103 - * Process customer when checking out.
73 + * Create account when checking out with user guest and tick create account.
104 74 *
105 - * @param array $result
106 - * @param int $order_id
107 - *
108 - * @return mixed
109 - * @editor tungnx
110 - * @modify 4.1.4 - merge to function create_order
75 + * @return int|WP_Error
111 76 */
112 - /*public function process_customer( $result, $order_id ) {
77 + protected function create_account(): int {
78 + $user_id = 0;
79 +
113 80 try {
114 - if ( ! $this->is_enable_guest_checkout() ) {
115 - throw new Exception( '' );
116 - }
81 + $email = $this->get_checkout_email();
82 + $password = wp_generate_password();
83 + $user_id = wp_create_user( $email, $password, $email );
84 + } catch ( Throwable $e ) {
85 + error_log( $e->getMessage() );
86 + }
117 87
118 - $order = learn_press_get_order( $order_id );
88 + return $user_id;
89 + }
119 90
120 - if ( ! $order ) {
121 - throw new Exception( '' );
122 - }
91 + /**
92 + * Check valid fields login/register/guest checkout.
93 + * Store session guest before login success.
94 + * When user login success, will update session data of guest for user.
95 + *
96 + * @throws Exception
97 + */
98 + public function check_validate_fields() {
99 + $session = LearnPress::instance()->session;
100 + $data_session_before_user_login = $session->get_session_data();
101 + $this->checkout_action = null;
123 102
124 - $user_id = 0;
125 - $checkout_option = LP_Request::get_string( 'checkout-email-option' );
126 -
127 - switch ( $checkout_option ) {
128 - case 'new-account':
129 - if ( $this->checkout_email_exists() ) {
130 - throw new Exception( 'NEW ACCOUNT EMAIL IS EXISTED', 0 );
131 - }
132 -
133 - $order->set_meta( '_create_account', 'yes' );
134 -
135 - $user_id = $this->_create_account();
136 -
137 - if ( ! is_wp_error( $user_id ) ) {
138 - wp_new_user_notification( $user_id, null, apply_filters( 'learn-press/email-create-new-user-when-checkout', 'user' ) );
139 - }
140 - break;
141 - }
142 -
143 - if ( $user_id ) {
144 - $order->set_user_id( $user_id );
145 - $order->save();
146 - }
147 - } catch ( Exception $ex ) {
148 - if ( $ex->getCode() && $ex->getMessage() ) {
149 - $result['message'] = $ex->getMessage();
150 - }
103 + if ( isset( $_POST['reg_email'] ) ) {
104 + $this->checkout_action = 'register';
105 + } elseif ( isset( $_POST['username'] ) ) {
106 + $this->checkout_action = 'login';
107 + } elseif ( isset( $_POST['guest_email'] ) ) {
108 + $this->checkout_action = 'guest';
151 109 }
152 110
153 - return $result;
154 - }*/
111 + switch ( $this->checkout_action ) {
112 + case 'login':
113 + $user = wp_signon(
114 + array(
115 + 'user_login' => LP_Request::get_param( 'username' ),
116 + 'user_password' => LP_Request::get_param( 'password' ),
117 + 'remember' => LP_Request::get_param( 'remember', false ),
118 + ),
119 + is_ssl()
120 + );
155 121
156 - /**
157 - * @return int|WP_Error
158 - */
159 - protected function _create_account() {
160 - $email = $this->get_checkout_email();
161 - $password = wp_generate_password( 12, true );
162 - $user_id = wp_create_user( $email, $password, $email );
122 + if ( is_wp_error( $user ) ) {
123 + throw new Exception( $user->get_error_message() );
124 + } else {
125 + wp_set_current_user( $user->ID );
126 + }
127 + break;
128 + case 'register':
129 + $default_fields = array(
130 + 'reg_email' => LP_Request::get_param( 'reg_email' ),
131 + 'reg_username' => LP_Request::get_param( 'reg_username' ),
132 + 'reg_password' => LP_Request::get_param( 'reg_password' ),
133 + 'reg_password2' => LP_Request::get_param( 'reg_password2' ),
134 + );
163 135
164 - return $user_id;
165 - }
136 + if ( isset( $_POST['reg_first_name'] ) ) {
137 + $default_fields['first_name'] = LP_Request::get_param( 'reg_first_name' );
138 + }
166 139
167 - /**
168 - * @param array $errors
169 - * @param array $fields
170 - * @param LP_Checkout $checkout
171 - *
172 - * @return array
173 - */
174 - public function check_validate_fields( $errors, $fields, $checkout ) {
175 - if ( empty( $errors ) ) {
176 - switch ( $this->checkout_action ) {
177 - case 'checkout-login':
178 - $this->checkout_form_data['remember'] = isset( $_POST['rememberme'] ) ? true : false;
140 + if ( isset( $_POST['reg_last_name'] ) ) {
141 + $default_fields['last_name'] = LP_Request::get_param( 'reg_last_name' );
142 + }
179 143
180 - $login_info = $this->checkout_form_data;
144 + if ( isset( $_POST['reg_display_name'] ) ) {
145 + $default_fields['display_name'] = LP_Request::get_param( 'reg_display_name' );
146 + }
181 147
182 - $user = wp_signon(
183 - array(
184 - 'user_login' => $login_info['username'],
185 - 'user_password' => $login_info['password'],
186 - 'remember' => $login_info['remember'],
187 - ),
188 - is_ssl()
189 - );
148 + $update_meta = isset( $_POST['_lp_custom_register_form'] ) ? LP_Helper::sanitize_params_submitted( $_POST['_lp_custom_register_form'] ) : array();
190 149
191 - if ( is_wp_error( $user ) ) {
192 - $errors['login_error'] = $user->get_error_message();
193 - } else {
194 - wp_set_current_user( $user->ID );
195 - }
196 - break;
197 - case 'checkout-register':
198 - $default_fields = array();
150 + $user_id = LP_Forms_Handler::learnpress_create_new_customer(
151 + $default_fields['reg_email'],
152 + $default_fields['reg_username'],
153 + $default_fields['reg_password'],
154 + $default_fields['reg_password2'],
155 + $default_fields,
156 + $update_meta
157 + );
199 158
200 - if ( isset( $_POST['reg_first_name'] ) ) {
201 - $default_fields['first_name'] = LP_Helper::sanitize_params_submitted( $_POST['reg_first_name'] );
202 - }
159 + if ( is_wp_error( $user_id ) ) {
160 + throw new Exception( $user_id->get_error_message() );
161 + } else {
162 + // Directly authenticate the newly created user to bypass captcha plugins
163 + // that hook into 'authenticate'. We already verified the password during registration.
164 + $user = get_user_by( 'id', $user_id );
203 165
204 - if ( isset( $_POST['reg_last_name'] ) ) {
205 - $default_fields['last_name'] = LP_Helper::sanitize_params_submitted( $_POST['reg_last_name'] );
166 + if ( ! $user instanceof WP_User ) {
167 + throw new Exception( __( 'User registration succeeded but the user cannot be loaded.', 'learnpress' ) );
206 168 }
207 169
208 - if ( isset( $_POST['reg_display_name'] ) ) {
209 - $default_fields['display_name'] = LP_Helper::sanitize_params_submitted( $_POST['reg_display_name'] );
210 - }
170 + /*if ( ! wp_check_password( $default_fields['reg_password'], $user->user_pass, $user->ID ) ) {
171 + throw new Exception( __( 'Incorrect password.', 'learnpress' ) );
172 + }*/
211 173
212 - $update_meta = isset( $_POST['_lp_custom_register_form'] ) ? LP_Helper::sanitize_params_submitted( $_POST['_lp_custom_register_form'] ) : array();
174 + wp_set_current_user( $user->ID );
175 + wp_set_auth_cookie( $user->ID, true, is_ssl() );
176 + do_action( 'wp_login', $user->user_login, $user );
177 + }
178 + break;
179 + case 'guest':
180 + $email_guest = LP_Request::get_param( 'guest_email' );
181 + if ( ! is_email( $email_guest ) ) {
182 + throw new Exception( __( 'Your email is not valid!', 'learnpress' ) );
183 + }
213 184
214 - $user_id = LP_Forms_Handler::learnpress_create_new_customer(
215 - $this->checkout_form_data['reg_email'],
216 - $this->checkout_form_data['reg_username'],
217 - $this->checkout_form_data['reg_password'],
218 - $this->checkout_form_data['reg_password2'],
219 - $default_fields,
220 - $update_meta
221 - );
185 + $this->guest_email = $email_guest;
186 + $this->_checkout_email = $email_guest;
187 + break;
188 + }
222 189
223 - if ( is_wp_error( $user_id ) ) {
224 - $errors['create_user_error'] = $user_id->get_error_message();
225 - } else {
226 - wp_set_current_user( $user_id );
227 - wp_set_auth_cookie( $user_id, true );
228 - }
229 - break;
230 - case 'guest-checkout':
190 + // Set session, cart for user have just login/register success.
191 + if ( in_array( $this->checkout_action, [ 'login', 'register' ] ) ) {
192 + foreach ( $data_session_before_user_login as $key => $item ) {
193 + $session->set( $key, maybe_unserialize( $item ) );
231 194 }
195 + $session->save_data();
232 196 }
233 -
234 - return $errors;
235 197 }
236 198
237 199 /**
238 200 * Get email of user is being checkout.
@@ -242,11 +204,12 @@
242 204 public function get_checkout_email() {
243 205 if ( $this->_checkout_email ) {
244 206 return $this->_checkout_email;
245 207 } elseif ( is_user_logged_in() ) {
246 - $user = learn_press_get_current_user( false );
247 -
248 - return $user->get_email();
208 + $userModel = UserModel::find( get_current_user_id(), true );
209 + if ( $userModel instanceof UserModel ) {
210 + return $userModel->get_email();
211 + }
249 212 }
250 213
251 214 return false;
252 215 }
@@ -261,9 +224,8 @@
261 224 return false;
262 225 }
263 226
264 227 $user = get_user_by( 'email', $email );
265 -
266 228 if ( ! $user ) {
267 229 return false;
268 230 }
269 231
@@ -269,203 +231,105 @@
269 231
270 232 return $user->ID;
271 233 }
272 234
273 - public function verify_nonce() {
274 - if ( empty( $_POST['learn-press-checkout-nonce'] ) ) {
275 - return false;
276 - }
277 -
278 - if ( ! is_user_logged_in() ) {
279 - $actions = array( 'guest-checkout', 'checkout-register', 'checkout-login' );
280 - } else {
281 - $actions = array( 'guest-checkout', 'checkout-register', 'user-logged' );
282 - }
283 -
284 - foreach ( $actions as $action ) {
285 - if ( wp_verify_nonce( $_REQUEST['learn-press-checkout-nonce'], "learn-press-{$action}" ) ) {
286 - $this->checkout_action = $action;
287 -
288 - return true;
289 - }
290 - }
291 -
292 - return false;
293 - }
294 -
295 235 /**
296 - * Checkout fields.
236 + * Create LP Order.
297 237 *
298 - * @return array
299 - */
300 - public function get_checkout_fields() {
301 - if ( ! $this->verify_nonce() ) {
302 - $this->checkout_fields['invalid_request'] = new WP_Error( 'invalid_request', __( 'Your session has expired.', 'learnpress' ) );
303 - } else {
304 - if ( $this->checkout_action === 'checkout-register' ) {
305 - $this->checkout_fields['reg_email'] = esc_html__( 'Email', 'learnpress' );
306 - $this->checkout_fields['reg_username'] = esc_html__( 'Username', 'learnpress' );
307 - $this->checkout_fields['reg_password'] = esc_html__( 'Password', 'learnpress' );
308 - $this->checkout_fields['reg_password2'] = esc_html__( 'Confirm Password', 'learnpress' );
309 - } elseif ( $this->checkout_action === 'checkout-login' ) {
310 - $this->checkout_fields['username'] = esc_html__( 'Username', 'learnpress' );
311 - $this->checkout_fields['password'] = esc_html__( 'Password', 'learnpress' );
312 - } elseif ( $this->checkout_action === 'guest-checkout' ) {
313 - $this->checkout_fields['guest_email'] = esc_html__( 'Email', 'learnpress' );
314 - }
315 - }
316 -
317 - $this->checkout_fields = apply_filters( 'learn_press_checkout_fields', $this->checkout_fields );
318 -
319 - return $this->checkout_fields;
320 - }
321 -
322 - /**
323 - * Check if an order is pending or failed.
324 - *
325 - * @param $order_id
326 - *
327 - * @return LP_Order|bool
328 - */
329 - protected function _is_resume_order( $order_id ) {
330 - $order = learn_press_get_order( $order_id );
331 -
332 - if ( $order_id > 0 && $order && $order->has_status( array( 'pending', 'failed' ) ) ) {
333 - return $order;
334 - }
335 -
336 - return false;
337 - }
338 -
339 - /**
340 - * Creates temp new order if needed
341 - *
342 - * @return mixed|WP_Error
238 + * @return mixed|string
343 239 * @throws Exception
240 + * @since 3.0.0
241 + * @version 4.0.3
344 242 */
345 243 public function create_order() {
346 - global $wpdb;
244 + $cart = LearnPress::instance()->cart;
245 + $cart_total = $cart->calculate_totals();
246 + $order = new LP_Order();
247 + $user_id = 0;
248 + $user_can_register = get_option( 'users_can_register' );
347 249
348 - $order_id = apply_filters( 'learn-press/checkout/create-order', null, $this );
250 + if ( is_user_logged_in() ) {
251 + $user_id = get_current_user_id();
252 + } elseif ( $user_can_register ) {
253 + $checkout_option = LP_Request::get_param( 'checkout-email-option' );
254 + // Set user id for Order if buy with Guest and email exists on the user
255 + $user_id = $this->checkout_email_exists();
349 256
350 - if ( $order_id ) {
351 - return $order_id;
352 - }
353 - $cart = LearnPress::instance()->cart;
354 -
355 - try {
356 - $wpdb->query( 'START TRANSACTION' );
357 -
358 - // Insert or update the post data
359 - $order_id = absint( LearnPress::instance()->session->get( 'order_awaiting_payment' ) );
360 -
361 - // Resume the unpaid order if its pending
362 - $order = $this->_is_resume_order( $order_id );
363 -
364 - if ( $order ) {
365 - if ( is_wp_error( $order ) ) {
366 - throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'learnpress' ), 401 ) );
257 + // Create new user if buy with Guest and tick "Create new Account"
258 + if ( $checkout_option === 'new-account' ) {
259 + if ( $user_id ) {
260 + throw new Exception( __( 'New account email is existed', 'learnpress' ), 0 );
367 261 }
368 262
369 - $order->remove_order_items();
370 - do_action( 'learn-press/checkout/resume-order', $order_id );
263 + //$order->set_meta( '_create_account', 'yes' );
371 264
372 - } else {
373 - $order = new LP_Order();
374 -
375 - if ( is_wp_error( $order ) ) {
376 - throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'learnpress' ), 400 ) );
265 + $user_id = $this->create_account();
266 + if ( $user_id ) {
267 + // Notify mail create user success
268 + wp_new_user_notification(
269 + $user_id,
270 + null,
271 + apply_filters( 'learn-press/email-create-new-user-when-checkout', 'user' )
272 + );
273 + } else {
274 + throw new Exception( __( 'Create account failed', 'learnpress' ), 0 );
377 275 }
378 -
379 - $order_id = $order->get_id();
380 - do_action( 'learn-press/checkout/new-order', $order_id );
381 276 }
382 277
383 - $user_id = 0;
384 - if ( is_user_logged_in() ) {
385 - $user_id = get_current_user_id();
386 - } else {
387 - $checkout_option = LP_Helper::sanitize_params_submitted( $_POST['checkout-email-option'] ?? '' );
388 -
389 - // Create new user if buy with Guest and tick "Create new Account"
390 - if ( $checkout_option === 'new-account' ) {
391 - if ( $this->checkout_email_exists() ) {
392 - throw new Exception( 'NEW ACCOUNT EMAIL IS EXISTED', 0 );
393 - }
394 -
395 - $order->set_meta( '_create_account', 'yes' );
396 -
397 - $user_id = $this->_create_account();
398 -
399 - if ( ! is_wp_error( $user_id ) ) {
400 - wp_new_user_notification( $user_id, null, apply_filters( 'learn-press/email-create-new-user-when-checkout', 'user' ) );
401 - }
402 - } else { // Set user id for Order if buy with Guest and email exists on the user
403 - $user = get_user_by( 'email', $this->get_checkout_email() );
404 -
405 - if ( $order->is_guest() && $user ) {
406 - $user_id = $user->ID;
407 - }
408 - }
409 -
410 - if ( $user_id ) {
411 - $order->set_user_id( $user_id );
412 - }
278 + // Get user_id Guest
279 + if ( ! $user_id ) {
280 + /**
281 + * @var LP_User_Guest $user_guest
282 + */
283 + $user_guest = learn_press_get_user();
284 + $user_id = $user_guest->get_id();
413 285 }
286 + }
414 287
415 - $order->set_customer_note( $this->order_comment );
416 - $order->set_status( learn_press_default_order_status( 'lp-' ) );
417 - $order->set_total( $cart->total );
418 - $order->set_subtotal( $cart->subtotal );
419 - $order->set_user_ip_address( learn_press_get_ip() );
420 - $order->set_user_agent( learn_press_get_user_agent() );
421 - $order->set_created_via( 'checkout' );
422 - $order->set_user_id( apply_filters( 'learn-press/checkout/default-user', $user_id ) );
423 -
424 - if ( $this->is_enable_guest_checkout() && $this->get_checkout_email() ) {
425 - $order->set_checkout_email( $this->get_checkout_email() );
288 + if ( $this->is_enable_guest_checkout() && $this->get_checkout_email() ) {
289 + $order->set_checkout_email( $this->get_checkout_email() );
290 + // Check email exists on the user will get user_id to set
291 + if ( ! $user_id ) {
292 + $user_id = $this->checkout_email_exists();
426 293 }
294 + }
427 295
428 - $order_id = $order->save();
296 + $order->set_customer_note( $this->order_comment );
297 + $order->set_status( LP_ORDER_PENDING );
298 + $order->set_total( $cart_total->total );
299 + $order->set_subtotal( $cart_total->subtotal );
300 + $order->set_user_ip_address( learn_press_get_ip() );
301 + $order->set_user_agent( learn_press_get_user_agent() );
302 + $order->set_created_via( 'checkout' );
303 + $order->set_user_id( apply_filters( 'learn-press/checkout/default-user', $user_id ) );
304 + if ( $this->payment_method instanceof LP_Gateway_Abstract ) {
305 + $order->set_data( 'payment_method', $this->payment_method->get_id() );
306 + $order->set_data( 'payment_method_title', $this->payment_method->get_title() );
307 + }
429 308
430 - // Store the line items to the new/resumed order
431 - foreach ( $cart->get_items() as $item ) {
432 - $item_type = get_post_type( $item['item_id'] );
309 + $order_id = $order->save();
433 310
434 - if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
435 - continue;
436 - }
437 -
438 - $item_id = $order->add_item( $item );
439 -
440 - if ( ! $item_id ) {
441 - throw new Exception( sprintf( __( 'Error %d: Unable to create order. Please try again.', 'learnpress' ), 402 ) );
442 - }
443 -
444 - do_action( 'learn-press/checkout/add-order-item-meta', $item_id, $item );
311 + // Store the line items to the order
312 + foreach ( $cart->get_items() as $item ) {
313 + $item_type = get_post_type( $item['item_id'] );
314 + if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
315 + continue;
445 316 }
446 317
447 - $order->set_payment_method( $this->payment_method );
448 -
449 - if ( ! empty( $this->user_id ) ) {
450 - do_action( 'learn-press/checkout/update-user-meta', $this->user_id );
318 + $item_id = $order->add_item( $item );
319 + if ( ! $item_id ) {
320 + throw new Exception( sprintf( __( 'Error %d: Unable to add item to order. Please try again.', 'learnpress' ), 402 ) );
451 321 }
452 322
453 - do_action( 'learn-press/checkout/update-order-meta', $order_id );
323 + do_action( 'learn-press/checkout/add-order-item-meta', $item_id, $item );
324 + }
454 325
455 - if ( ! $order_id || is_wp_error( $order_id ) ) {
456 - learn_press_add_message( __( 'Unable to checkout. Order creation failed.', 'learnpress' ) );
457 - }
326 + if ( ! empty( $this->user_id ) ) {
327 + do_action( 'learn-press/checkout/update-user-meta', $this->user_id );
328 + }
458 329
459 - $wpdb->query( 'COMMIT' );
330 + do_action( 'learn-press/checkout/update-order-meta', $order_id );
460 331
461 - } catch ( Exception $e ) {
462 - $wpdb->query( 'ROLLBACK' );
463 - learn_press_add_message( $e->getMessage() );
464 -
465 - return false;
466 - }
467 -
468 332 return $order_id;
469 333 }
470 334
471 335 /**
@@ -470,23 +334,29 @@
470 334
471 335 /**
472 336 * Guest checkout is enable?
473 337 *
474 - * @return mixed
338 + * @return bool
475 339 * @since 3.0.0
476 340 */
477 - public function is_enable_guest_checkout() {
478 - return apply_filters( 'learn-press/checkout/enable-guest', LP_Settings::instance()->get( 'guest_checkout', 'no' ) == 'yes' );
341 + public function is_enable_guest_checkout(): bool {
342 + return apply_filters(
343 + 'learn-press/checkout/enable-guest',
344 + LP_Settings::get_option( 'guest_checkout', 'no' ) === 'yes'
345 + );
479 346 }
480 347
481 348 /**
482 - * Enable user can login in checkout page?
349 + * Enable user can log in checkout page?
483 350 *
484 351 * @return bool
485 352 * @since 3.0.0
486 353 */
487 - public function is_enable_login() {
488 - return apply_filters( 'learn-press/checkout/enable-login', in_array( LP_Settings::instance()->get( 'enable_login_checkout' ), array( '', 'yes' ) ) );
354 + public function is_enable_login(): bool {
355 + return apply_filters(
356 + 'learn-press/checkout/enable-login',
357 + 'yes' === LP_Settings::get_option( 'enable_login_checkout', 'yes' )
358 + );
489 359 }
490 360
491 361 /**
492 362 * Enable user can register in checkout page?
@@ -493,175 +363,84 @@
493 363 *
494 364 * @return bool
495 365 * @since 3.0.0
496 366 */
497 - public function is_enable_register() {
498 - return apply_filters( 'learn-press/checkout/enable-register', in_array( LP_Settings::instance()->get( 'enable_registration_checkout' ), array( '', 'yes' ) ) && get_option( 'users_can_register' ) );
367 + public function is_enable_register(): bool {
368 + return apply_filters(
369 + 'learn-press/checkout/enable-register',
370 + 'yes' === LP_Settings::get_option( 'enable_registration_checkout', 'yes' )
371 + && get_option( 'users_can_register' )
372 + );
499 373 }
500 374
501 375 /**
502 - * Validate fields
503 - *
504 - * @param bool $validate
505 - * @param mixed $field
506 - * @param string $name
507 - *
508 - * @return bool|WP_Error
509 - */
510 - public function validate_fields( $validate, $field, $name ) {
511 - switch ( $this->checkout_action ) {
512 - case 'checkout-register':
513 - if ( $name === 'reg_username' ) {
514 - if ( empty( $_POST['reg_username'] ) ) {
515 - return new WP_Error( 'username_empty', sprintf( __( '%s is required field.', 'learnpress' ), $field ) );
516 - } elseif ( username_exists( $_POST['reg_username'] ) ) {
517 - return new WP_Error( 'username_exists', sprintf( __( '%s is exists.', 'learnpress' ), $_POST['reg_username'] ) );
518 - } elseif ( ! validate_username( $_POST['reg_username'] ) ) {
519 - return new WP_Error( 'username_invalid', sprintf( __( '%s is not a valid username.', 'learnpress' ), $_POST['reg_username'] ) );
520 - }
521 - } elseif ( $name === 'reg_email' ) {
522 - if ( empty( $_POST['reg_email'] ) ) {
523 - return new WP_Error( 'email_empty', sprintf( __( '%s is required field.', 'learnpress' ), $field ) );
524 - } elseif ( email_exists( $_POST['reg_email'] ) ) {
525 - return new WP_Error( 'email_exists', sprintf( __( '%s is exists.', 'learnpress' ), $_POST['reg_email'] ) );
526 - } elseif ( ! is_email( $_POST['reg_email'] ) ) {
527 - return new WP_Error( 'email_invalid', sprintf( __( '%s is not a valid email.', 'learnpress' ), $_POST['reg_email'] ) );
528 - }
529 - } elseif ( $name === 'reg_password' ) {
530 - if ( empty( $_POST['reg_password'] ) ) {
531 - return new WP_Error( 'password_empty', sprintf( __( '%s is required field.', 'learnpress' ), $field ) );
532 - }
533 - } elseif ( $name === 'reg_password2' ) {
534 - if ( empty( $_POST['reg_password2'] ) ) {
535 - return new WP_Error( 'password2_empty', sprintf( __( '%s is required field.', 'learnpress' ), $field ) );
536 - }
537 - }
538 -
539 - $this->checkout_form_data[ $name ] = LP_Helper::maybe_unserialize( $_POST[ $name ] );
540 -
541 - break;
542 - case 'checkout-login':
543 - if ( $name === 'username' ) {
544 - if ( empty( $_POST['username'] ) ) {
545 - return new WP_Error( 'email_empty', sprintf( __( '%s is required field.', 'learnpress' ), $field ) );
546 - }
547 -
548 - if ( ! username_exists( $_POST['username'] ) && ! email_exists( $_POST['username'] ) ) {
549 - return new WP_Error( 'username_exists', sprintf( __( '%s is not exists.', 'learnpress' ), $field ) );
550 - }
551 - } elseif ( $name === 'password' ) {
552 - if ( empty( $_POST['password'] ) ) {
553 - return new WP_Error( 'email_empty', sprintf( __( '%s is required field.', 'learnpress' ), $field ) );
554 - }
555 - }
556 -
557 - $this->checkout_form_data[ $name ] = LP_Helper::maybe_unserialize( $_POST[ $name ] );
558 - break;
559 - case 'guest-checkout':
560 - if ( empty( $_POST['guest_email'] ) ) {
561 - return new WP_Error( 'email_empty', sprintf( __( '%s is required field.', 'learnpress' ), $field ) );
562 - } elseif ( ! is_email( $_POST['guest_email'] ) ) {
563 - return new WP_Error( 'email_invalid', __( 'Your email is not a valid.', 'learnpress' ) );
564 - }
565 -
566 - $this->guest_email = LP_Helper::maybe_unserialize( $_POST[ $name ] );
567 - $this->_checkout_email = LP_Helper::maybe_unserialize( $_POST[ $name ] );
568 - }
569 -
570 - return $validate;
571 - }
572 -
573 - /**
574 376 * Process checkout from request.
575 377 *
576 - * @return mixed
378 + * @return void
577 379 * @throws Exception
578 380 */
579 381 public function process_checkout_handler() {
580 382 if ( strtolower( $_SERVER['REQUEST_METHOD'] ) != 'post' ) {
581 - return false;
383 + return;
582 384 }
583 385
584 386 /**
585 387 * Set default fields from request.
586 388 */
587 - $this->payment_method = LP_Request::get_string( 'payment_method' );
588 - $this->user_login = LP_Request::get_string( 'username' );
589 - $this->user_pass = LP_Request::get_string( 'password' );
590 - $this->order_comment = LP_Request::get_string( 'order_comments' );
591 - $this->_checkout_email = LP_Request::get_email( 'checkout-email' );
592 -
593 - if ( LP_Request::get_int( 'terms_conditions_field', 0 ) ) {
594 - $this->checkout_fields['terms_conditions'] = LP_Request::get_string( 'terms_conditions', '' );
595 - }
596 -
389 + $this->payment_method_str = LP_Request::get_param( 'payment_method' );
390 + $this->order_comment = LP_Request::get_param( 'order_comments' );
391 + $this->_checkout_email = LP_Request::get_param( 'checkout-email' );
597 392 if ( $this->_checkout_email ) {
598 393 LearnPress::instance()->session->set( 'checkout-email', $this->_checkout_email );
599 394 }
600 395
601 396 $this->process_checkout();
602 -
603 - return true;
604 397 }
605 398
606 399 /**
607 400 * Validate fields.
608 401 *
609 - * @return bool
402 + * Addon Upsell 4.0.1 use argument $errors
403 + * Must update to 4.0.2 to use throw Error instead.
404 + *
405 + * @throws Exception
610 406 */
611 407 public function validate_checkout_fields() {
612 408 $this->errors = array();
613 - $fields = $this->get_checkout_fields();
614 409
615 - if ( $fields ) {
616 - foreach ( $fields as $name => $field ) {
617 - if ( ! is_wp_error( $field ) ) {
618 - $error = apply_filters( 'learn-press/validate-checkout-field', true, $field, $name );
619 - } else {
620 - $error = $field;
621 - }
622 -
623 - if ( is_wp_error( $error ) ) {
624 - $this->errors[ $name ] = $error;
625 - } elseif ( ! $error ) {
626 - $this->errors[ $name ] = new WP_Error( 'invalid_field', __( 'Invalid field', 'learnpress' ) );
627 - }
628 - }
410 + // Check nonce
411 + $nonce = LP_Request::get_param( 'learn-press-checkout-nonce' );
412 + if ( ! wp_verify_nonce( $nonce, 'learn-press-checkout' ) ) {
413 + throw new Exception( __( 'Your session has expired.', 'learnpress' ) );
629 414 }
630 415
631 - $this->errors = apply_filters( 'learn-press/validate-checkout-fields', $this->errors, $fields, $this );
416 + $this->check_validate_fields();
632 417
633 - return ! sizeof( $this->errors );
418 + do_action( 'learn-press/validate-checkout-fields', $this );
634 419 }
635 420
636 421 /**
637 422 * Validate checkout payment.
638 423 *
639 - * @return bool
640 424 * @throws Exception
641 425 */
642 426 public function validate_payment() {
643 - $cart = LearnPress::instance()->cart;
644 - $validate = true;
427 + $cart = LearnPress::instance()->cart;
428 + //$validate = true;
645 429
646 430 if ( $cart->needs_payment() ) {
647 431 if ( ! $this->payment_method instanceof LP_Gateway_Abstract ) {
648 432 $available_gateways = LP_Gateways::instance()->get_available_payment_gateways();
649 433
650 - if ( ! isset( $available_gateways[ $this->payment_method ] ) ) {
651 - $this->payment_method = '';
434 + if ( ! isset( $available_gateways[ $this->payment_method_str ] ) ) {
652 435 throw new Exception( __( 'No payment method is selected', 'learnpress' ), LP_ERROR_NO_PAYMENT_METHOD_SELECTED );
653 436 } else {
654 - $this->payment_method = $available_gateways[ $this->payment_method ];
437 + $this->payment_method = $available_gateways[ $this->payment_method_str ];
655 438 }
656 - }
657 439
658 - if ( $this->payment_method ) {
659 - $validate = $this->payment_method->validate_fields();
440 + $this->payment_method->validate_fields();
660 441 }
661 442 }
662 -
663 - return $validate;
664 443 }
665 444
666 445 /**
667 446 * Process checkout.
@@ -668,27 +447,24 @@
668 447 *
669 448 * @throws Exception
670 449 */
671 450 public function process_checkout() {
672 - $has_error = false;
451 + ini_set( 'max_execution_time', HOUR_IN_SECONDS );
452 + $result = array(
453 + 'result' => 'fail',
454 + 'message' => '',
455 + );
673 456
674 457 try {
458 + $lp_session = LearnPress::instance()->session;
675 459
676 - if ( function_exists( 'set_time_limit' ) ) {
677 - @set_time_limit( 0 ); // @codingStandardsIgnoreLine
678 - }
679 -
680 460 do_action( 'learn-press/before-checkout' );
681 461
682 - $cart = LearnPress::instance()->cart;
683 - $result = false;
684 -
462 + $cart = LearnPress::instance()->cart;
685 463 if ( $cart->is_empty() ) {
686 464 throw new Exception( __( 'Your cart is currently empty.', 'learnpress' ) );
687 465 }
688 466
689 - $messages = array();
690 -
691 467 foreach ( $cart->get_items() as $item ) {
692 468 $item_type = get_post_type( $item['item_id'] );
693 469
694 470 if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
@@ -695,113 +471,138 @@
695 471 throw new Exception( __( 'Type item buy invalid!', 'learnpress' ) );
696 472 }
697 473 }
698 474
699 - if ( ! $this->validate_checkout_fields() ) {
700 - foreach ( $this->errors as $key => $error ) {
701 - if ( is_wp_error( $error ) ) {
702 - $error = $error->get_error_message();
475 + // Validate fields
476 + $this->validate_checkout_fields();
477 + // Validate payment method
478 + $this->validate_payment();
479 +
480 + $user_id = $this->checkout_email_exists();
481 + if ( ! $user_id ) {
482 + $user_id = 0;
483 + }
484 +
485 + // Check user can purchase, enrolled course
486 + foreach ( $cart->get_items() as $item ) {
487 + $item_type = get_post_type( $item['item_id'] );
488 + if ( LP_COURSE_CPT === $item_type ) {
489 + $courseModel = CourseModel::find( $item['item_id'], true );
490 + if ( ! $courseModel ) {
491 + throw new Exception( __( 'Course is invalid!', 'learnpress' ) );
703 492 }
704 - $messages[ $key ] = array( $error, 'error' );
493 +
494 + $userModel = UserModel::find( $user_id, true );
495 +
496 + // Check user can purchase course
497 + if ( ! $courseModel->is_free() ) {
498 + $can_purchase = $courseModel->can_purchase( $userModel );
499 + if ( is_wp_error( $can_purchase ) ) {
500 + //throw new Exception( $can_purchase->get_error_message() );
501 + learn_press_set_message(
502 + [
503 + 'status' => 'error',
504 + 'content' => $can_purchase->get_error_message(),
505 + ]
506 + );
507 + $result['redirect'] = LP_Page_Controller::get_link_page( 'checkout', [], true );
508 + $result['message'] = $can_purchase->get_error_message();
509 + learn_press_send_json( $result );
510 + }
511 + } else {
512 + // Check user can enroll course
513 + $can_enroll = $courseModel->can_enroll( $userModel );
514 + if ( is_wp_error( $can_enroll ) ) {
515 + learn_press_set_message(
516 + [
517 + 'status' => 'error',
518 + 'content' => $can_enroll->get_error_message(),
519 + ]
520 + );
521 + $result['redirect'] = LP_Page_Controller::get_link_page( 'checkout', [], true );
522 + $result['message'] = $can_enroll->get_error_message();
523 + learn_press_send_json( $result );
524 + }
525 + }
705 526 }
706 - } else {
707 - // maybe throw new exception
708 - $this->validate_payment();
527 + }
709 528
710 - // Create order.
529 + // Create order if not handle done.
530 + $order_id = $lp_session->get( 'order_awaiting_payment', 0 );
531 + if ( ! $order_id ) {
711 532 $order_id = $this->create_order();
712 -
713 533 if ( is_wp_error( $order_id ) ) {
714 534 throw new Exception( $order_id->get_error_message() );
715 535 }
716 536
717 - // allow Third-party hook: send email and more...
718 - do_action( 'learn-press/checkout-order-processed', $order_id, $this );
537 + $lp_session->set( 'order_awaiting_payment', $order_id, true );
538 + }
719 539
720 - if ( $this->payment_method ) {
721 - // Store the order is waiting f6or payment and each payment method should clear it
722 - LearnPress::instance()->session->order_awaiting_payment = $order_id;
723 - // Process Payment
724 - $result = $this->payment_method->process_payment( $order_id );
540 + // allow Third-party hook: send email and more...
541 + do_action( 'learn-press/checkout-order-processed', $order_id, $this );
725 542
726 - if ( isset( $result['result'] ) ) {
727 - if ( 'success' === $result['result'] ) {
728 - $result = apply_filters( 'learn-press/payment-successful-result', $result, $order_id );
729 - }
543 + if ( $this->payment_method instanceof LP_Gateway_Abstract ) {
544 + // Process Payment
545 + $result = $this->payment_method->process_payment( $order_id );
546 + if ( isset( $result['result'] ) ) {
547 + if ( 'success' === $result['result'] ) {
548 + // Clear cart.
549 + LearnPress::instance()->get_cart()->empty_cart();
550 + $result = apply_filters( 'learn-press/payment-successful-result', $result, $order_id );
551 + }
730 552
731 - if ( learn_press_is_ajax() ) {
732 - learn_press_send_json( $result );
733 - } else {
734 - wp_redirect( $result['redirect'] );
735 - exit;
736 - }
553 + if ( ! learn_press_is_ajax() ) {
554 + ini_set( 'max_execution_time', LearnPress::$time_limit_default_of_sever );
555 + wp_redirect( $result['redirect'] );
556 + exit;
737 557 }
738 - } else {
739 - // ensure that no order is waiting for payment
740 - $order = new LP_Order( $order_id );
558 + }
559 + } else {
560 + // For case enroll a course free.
561 + $order = new LP_Order( $order_id );
562 + if ( $order->payment_complete() ) {
563 + $redirect = $order->get_checkout_order_received_url();
741 564
742 - if ( $order && $order->payment_complete() ) {
565 + // Clear cart.
566 + LearnPress::instance()->get_cart()->empty_cart();
743 567
744 - $is_guest_checkout = $this->guest_email ? true : false;
745 - $redirect = $order->get_checkout_order_received_url();
568 + $result = array(
569 + 'result' => 'success',
570 + 'redirect' => $redirect,
571 + );
746 572
747 - if ( ! $is_guest_checkout ) {
748 - $course_id = get_transient( 'checkout_enroll_course_id' );
749 -
750 - if ( ! $course_id ) {
751 - if ( ! empty( $_REQUEST['enroll-course'] ) ) {
752 - $course_id = absint( $_REQUEST['enroll-course'] );
753 - }
754 - }
755 -
756 - if ( $course_id ) {
757 - delete_transient( 'checkout_enroll_course_id' );
758 - $redirect = get_the_permalink( $course_id );
759 - }
760 - }
761 -
762 - $result = array(
763 - 'result' => 'success',
764 - 'redirect' => $redirect,
765 - );
766 -
767 - if ( learn_press_is_ajax() ) {
768 - learn_press_send_json( $result );
769 - } else {
770 - wp_redirect( $result['redirect'] );
771 - exit;
772 - }
573 + if ( ! learn_press_is_ajax() ) {
574 + ini_set( 'max_execution_time', LearnPress::$time_limit_default_of_sever );
575 + wp_redirect( $result['redirect'] );
576 + exit;
773 577 }
774 578 }
775 579 }
776 - } catch ( Exception $e ) {
777 - $has_error = $e->getMessage();
778 - $messages[] = array( $has_error, 'error' );
580 + } catch ( Throwable $e ) {
581 + $result['message'] = $e->getMessage();
779 582 }
780 583
781 - $is_error = sizeof( $messages );
782 -
783 - $result = apply_filters(
784 - 'learn-press/checkout-error',
785 - array(
786 - 'result' => ! $is_error ? 'success' : 'fail',
787 - 'messages' => $messages,
788 - )
789 - );
790 -
791 - learn_press_maybe_send_json( $result, 'learn_press_remove_messages' );
584 + ini_set( 'max_execution_time', LearnPress::$time_limit_default_of_sever );
585 + learn_press_send_json( $result );
792 586 }
793 587
794 588 /**
795 - * Get unique instance for this object
589 + * Sync $_COOKIE[LOGGED_IN_COOKIE] within the current checkout request.
796 590 *
797 - * @return LP_Checkout
591 + * Checkout runs over AJAX. When login/register succeeds, wp_signon() only
592 + * sends a Set-Cookie header to the browser (effective on the next request)
593 + * and does not update $_COOKIE for the current request. Hooking into
594 + * 'set_logged_in_cookie' lets us grab the newly generated cookie value and
595 + * assign it to $_COOKIE manually, so subsequent code in the same request
596 + * (e.g. creating the order) correctly recognizes the logged-in user.
597 + * LPBackgroundAjax use $_COOKIE to send mails.
598 + *
599 + * @param string $logged_in_cookie The newly generated logged_in cookie value.
798 600 */
799 - public static function instance() {
800 - if ( empty( self::$_instance ) ) {
801 - self::$_instance = new LP_Checkout();
601 + public function set_logged_in_cookie( $logged_in_cookie ) {
602 + if ( ! isset( $_POST['learn-press-checkout-nonce'] ) ) {
603 + return;
802 604 }
803 605
804 - return self::$_instance;
606 + $_COOKIE[ LOGGED_IN_COOKIE ] = $logged_in_cookie;
805 607 }
806 608 }
807 -