PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.1.7
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.1.7
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
learnpress / inc / cart / class-lp-cart.php

class-lp-cart.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.1.7, at inc/cart/class-lp-cart.php

538 lines 12.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class LP_Cart
4 *
5 * Simple Cart object for now. Maybe need to expand later
6 *
7 * @author ThimPress
8 * @package LearnPress/Classes
9 * @version 1.0
10 */
11
12 defined( 'ABSPATH' ) || exit();
13
14 class LP_Cart {
15
16 /**
17 * Unique instance of LP_Cart
18 *
19 * @var LP_Cart object
20 */
21 private static $instances = array();
22
23 /**
24 * Hold the content of the cart
25 *
26 * @var array
27 */
28 protected $_cart_content = array();
29
30 /**
31 * Key of cart content stored in session
32 *
33 * @var string
34 */
35 protected $_cart_session_key = 'cart';
36
37 /**
38 * Cart total
39 *
40 * @var int
41 */
42 public $total = 0;
43
44 /**
45 * Cart subtotal
46 *
47 * @var int
48 */
49 public $subtotal = 0;
50
51 /**
52 * Constructor
53 *
54 * @param string $key . Added since 3.3.0
55 */
56 public function __construct( $key = '' ) {
57 if ( $key ) {
58 $this->_cart_session_key = $key;
59 }
60
61 LP_Request_Handler::register( 'add-course-to-cart', array( $this, 'add_to_cart' ), 20 );
62 LP_Request_Handler::register( 'remove-cart-item', array( $this, 'remove_item' ), 20 );
63
64 add_action( 'learn-press/add-to-cart', array( $this, 'calculate_totals' ), 10 );
65 add_action( 'wp', array( $this, 'maybe_set_cart_cookies' ), 99 );
66 add_action( 'shutdown', array( $this, 'maybe_set_cart_cookies' ), 0 );
67 add_action( 'wp_loaded', array( $this, 'init' ) );
68 }
69
70 /**
71 * Init cart.
72 * Get data from session and put to cart content.
73 */
74 function init() {
75 $this->get_cart_from_session();
76 }
77
78 public function maybe_set_cart_cookies() {
79
80 if ( ! headers_sent()/* && did_action( 'wp_loaded' )*/ ) {
81 // $this->set_cart_cookies( ! $this->is_empty() );
82 }
83 }
84
85 private function set_cart_cookies( $set = true ) {
86 if ( $set ) {
87 learn_press_setcookie( 'wordpress_lp_cart', 1 );
88 } elseif ( isset( $_COOKIE['wordpress_lp_cart'] ) ) {
89 learn_press_setcookie( 'wordpress_lp_cart', 0, time() - HOUR_IN_SECONDS );
90 }
91
92 do_action( 'learn_press_set_cart_cookies', $set );
93 }
94
95 /**
96 * Get data from session
97 *
98 * @return array
99 */
100 public function get_cart_for_session() {
101 $cart_session = array();
102
103 if ( $this->get_cart() ) {
104 foreach ( $this->get_cart() as $key => $values ) {
105 $cart_session[ $key ] = $values;
106 unset( $cart_session[ $key ]['data'] );
107 }
108 }
109
110 return $cart_session;
111 }
112
113 /**
114 * Get cart content.
115 *
116 * @return array
117 */
118 public function get_cart() {
119 if ( ! did_action( 'wp_loaded' ) ) {
120 _doing_it_wrong( __FUNCTION__, __( 'Get cart should not be called before the wp_loaded action.', 'learnpress' ), '2.3' );
121 }
122
123 if ( ! did_action( 'learn_press_cart_loaded_from_session' ) ) {
124 $this->get_cart_from_session();
125 }
126
127 return array_filter( (array) $this->_cart_content );
128 }
129
130 /**
131 * Add course to cart.
132 *
133 * @param int $item_id
134 * @param int $quantity
135 * @param array $item_data
136 *
137 * @return mixed
138 */
139 public function add_to_cart( int $item_id = 0, int $quantity = 1, array $item_data = array() ) {
140 try {
141 $item_type = get_post_type( $item_id );
142
143 if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
144 throw new Exception( 'Item type is invalid!', 'learnpress' );
145 }
146
147 switch ( $item_type ) {
148 case LP_COURSE_CPT:
149 $course = learn_press_get_course( $item_id );
150
151 if ( ! $course->is_purchasable() ) {
152 throw new Exception( __( 'Sorry! This course is not purchasable.', 'learnpress' ) );
153 }
154
155 if ( ! $course->is_in_stock() ) {
156 throw new Exception( __( 'Sorry! The number of enrolled students has reached limit', 'learnpress' ) );
157 }
158
159 $item_data['data'] = $course;
160 break;
161 default:
162 $item_data = apply_filters( 'learnpress/cart/add-item/item_type_' . $item_type, $item_data, $item_id, $quantity );
163 break;
164 }
165
166 // $item_data = apply_filters( 'learnpress/cart/item-data', $item_data, $item_id );
167
168 $cart_id = $this->generate_cart_id( $item_id, $item_data );
169
170 $this->_cart_content[ $cart_id ] = apply_filters(
171 'learn_press_add_cart_item',
172 array_merge(
173 array(
174 'item_id' => $item_id,
175 'quantity' => $quantity,
176 'data' => array(),
177 ),
178 $item_data
179 )
180 );
181
182 $this->set_cart_cookies( true );
183
184 /**
185 * @see LP_Cart::calculate_totals()
186 */
187 do_action( 'learn-press/add-to-cart', $item_id, $quantity, $item_data, $cart_id );
188
189 return $cart_id;
190 } catch ( Exception $e ) {
191 if ( $e->getMessage() ) {
192 learn_press_add_message( $e->getMessage(), 'error' );
193 }
194
195 return false;
196 }
197 }
198
199 /**
200 * Remove an item from cart
201 *
202 * @param $item_id
203 *
204 * @return bool
205 */
206 public function remove_item( $item_id ) {
207 if ( isset( $this->_cart_content['items'][ $item_id ] ) ) {
208
209 do_action( 'learn_press_remove_cart_item', $item_id, $this );
210
211 unset( $this->_cart_content['items'][ $item_id ] );
212
213 do_action( 'learn_press_cart_item_removed', $item_id, $this );
214
215 $this->calculate_totals();
216
217 return true;
218 }
219
220 return false;
221 }
222
223 /**
224 * Re-calculate cart totals and update data to session
225 */
226 public function calculate_totals() {
227 $total = $subtotal = 0;
228 $this->total = $this->subtotal = 0;
229 $items = $this->get_cart();
230
231 if ( $items ) {
232 foreach ( $items as $cart_id => $item ) {
233
234 $item_type = get_post_type( $item['item_id'] );
235
236 if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
237 continue;
238 }
239
240 switch ( $item_type ) {
241 case LP_COURSE_CPT:
242 $course = learn_press_get_course( $item['item_id'] );
243 $subtotal = $course->get_price() * absint( $item['quantity'] );
244 break;
245 default:
246 $subtotal = apply_filters( 'learnpress/cart/calculate_sub_total/item_type_' . $item_type, $subtotal, $item );
247 break;
248 }
249
250 $total = $subtotal;
251
252 $this->_cart_content[ $cart_id ]['subtotal'] = $subtotal;
253 $this->_cart_content[ $cart_id ]['total'] = $total;
254
255 $this->subtotal += $subtotal;
256 $this->total += $total;
257 }
258 }
259
260 $this->update_session();
261 }
262
263 /**
264 * Update cart content to session
265 */
266 public function update_session() {
267 learn_press_session_set( $this->_cart_session_key, $this->get_cart_for_session() );
268 }
269
270 /**
271 * Get cart id
272 *
273 * @return mixed
274 */
275 public function get_cart_id() {
276 return ! empty( $_SESSION['learn_press_cart']['cart_id'] ) ? $_SESSION['learn_press_cart']['cart_id'] : 0;
277 }
278
279 /**
280 * Get all items from cart.
281 *
282 * @return array
283 */
284 public function get_items() {
285 $items = $this->get_cart();
286
287 return $items;
288 }
289
290 /**
291 * Load cart content data from session
292 */
293 public function get_cart_from_session() {
294 if ( ! did_action( 'learn_press_get_cart_from_session' ) ) {
295 $cart = learn_press_session_get( $this->_cart_session_key );
296 $data = array();
297 if ( $cart ) {
298 foreach ( $cart as $cart_id => $values ) {
299 if ( ! empty( $values['item_id'] ) ) {
300
301 $item_type = get_post_type( $values['item_id'] );
302 if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
303 return false;
304 }
305 switch ( $item_type ) {
306 case LP_COURSE_CPT:
307 $course = learn_press_get_course( $values['item_id'] );
308 if ( $course && $course->exists() && $values['quantity'] > 0 ) {
309 if ( ! $course->is_purchasable() ) {
310 learn_press_add_message( sprintf( __( '%s has been removed from your cart because it can no longer be purchased.', 'learnpress' ), $course->get_title() ), 'error' );
311 do_action( 'learn-press/remove-cart-item-from-session', $cart, $values );
312 } else {
313 $data = array_merge( $values, array( 'data' => $course ) );
314 $this->_cart_content[ $cart_id ] = $data;
315 }
316 }
317 break;
318 default:
319 $this->_cart_content[ $cart_id ] = apply_filters( 'learn-press/get-cart-item-from-session/item_type_' . $item_type, $data, $values, $cart_id );
320 break;
321 }
322 }
323 }
324 }
325
326 do_action( 'learn_press_cart_loaded_from_session' );
327 LP()->session->set( $this->_cart_session_key, $this->get_cart_for_session() );
328 do_action( 'learn_press_get_cart_from_session' );
329
330 $this->calculate_totals();
331 }
332 }
333
334 /**
335 * Get cart sub-total
336 *
337 * @return mixed
338 */
339 public function get_subtotal() {
340 $subtotal = apply_filters( 'learn_press_get_cart_subtotal', learn_press_format_price( $this->subtotal, true ) );
341
342 return apply_filters( 'learn-press/cart-subtotal', $subtotal );
343 }
344
345 /**
346 * Get cart total
347 *
348 * @return mixed
349 */
350 public function get_total() {
351 $total = apply_filters( 'learn_press_get_cart_total', learn_press_format_price( $this->total, true ) );
352
353 return apply_filters( 'learn-press/cart-total', $total );
354 }
355
356 /**
357 * Generate unique cart id from course id and data.
358 *
359 * @param int $course_id
360 * @param mixed $data
361 *
362 * @return string
363 */
364 public function generate_cart_id( $course_id, $data = '' ) {
365 $cart_id = array( $course_id );
366
367 if ( is_array( $data ) ) {
368 foreach ( $data as $key => $value ) {
369 $cart_id[1] = '';
370
371 if ( is_array( $value ) || is_object( $value ) ) {
372 $value = http_build_query( $value );
373 }
374
375 $cart_id[1] .= trim( $key ) . trim( $value );
376 }
377 }
378
379 return apply_filters( 'learn-press/cart-id', md5( join( '_', $cart_id ) ), $cart_id, $data );
380 }
381
382 /**
383 * Return sub-total of cart content
384 *
385 * @param LP_Course $course
386 * @param int $quantity
387 *
388 * @return mixed
389 */
390 public function get_item_subtotal( $course, $quantity = 1 ) {
391 $price = $course->get_price();
392 $row_price = $price * $quantity;
393 $course_subtotal = learn_press_format_price( $row_price, true );
394
395 return apply_filters( 'learn-press/cart/item-subtotal', $course_subtotal, $course, $quantity, $this );
396 }
397
398 /**
399 * Clean all items from cart
400 *
401 * @return $this
402 */
403 public function empty_cart() {
404
405 do_action( 'learn-press/cart/before-empty' );
406
407 $this->_cart_content = array();
408
409 unset( LP()->session->order_awaiting_payment );
410 unset( LP()->session->cart );
411
412 do_action( 'learn-press/cart/emptied' );
413
414 return $this;
415 }
416
417 /**
418 * Check if cart is empty or not
419 *
420 * @return bool
421 */
422 public function is_empty() {
423 return sizeof( $this->get_cart() ) === 0;
424 }
425
426 /**
427 * Get checkout url for checkout page
428 * Return default url of checkout page
429 *
430 * @return mixed
431 */
432 public function get_checkout_url() {
433 $checkout_url = learn_press_get_page_link( 'checkout' );
434
435 return apply_filters( 'learn_press_get_checkout_url', $checkout_url );
436 }
437
438 /**
439 * Checks if need to payment
440 * Return true if cart total greater than 0
441 *
442 * @return mixed
443 */
444 public function needs_payment() {
445 return apply_filters( 'learn_press_cart_needs_payment', $this->total > 0, $this );
446 }
447
448 /**
449 * Process action for purchase course button
450 *
451 * @param $course_id
452 * @depecated 4.1.6.8
453 */
454 public function purchase_course_handler( $course_id ) {
455 _deprecated_function( __FUNCTION__, '4.1.6.8' );
456 do_action( 'learn_press_before_purchase_course_handler', $course_id, $this );
457
458 if ( apply_filters( 'learn_press_purchase_single_course', true ) ) {
459 $this->empty_cart();
460 }
461
462 $this->add_to_cart( $course_id, 1, $_POST );
463 $redirect = learn_press_get_checkout_url();
464 $has_checkout = $redirect ? true : false;
465 $need_checkout = $this->needs_payment();
466
467 // In case the course is FREE and "No checkout free course" is turn off
468 if ( ! $need_checkout ) {
469 $user = learn_press_get_current_user();
470 if ( ! $user->has_purchased_course( $course_id )/* || $user->has_finished_course( $course_id ) */ ) {
471 require_once LP_PLUGIN_PATH . '/inc/gateways/class-lp-gateway-none.php';
472 $checkout = learn_press_get_checkout( array( 'payment_method' => new LP_Gateway_None() ) );
473
474 /**
475 * + Auto enroll
476 */
477 // add_filter( 'learn_press_checkout_success_result', '_learn_press_checkout_success_result', 10, 2 );
478 $checkout->process_checkout();
479 // remove_filter( 'learn_press_checkout_success_result', '_learn_press_checkout_success_result', 10 );
480 }/*
481 else {
482 if ( $user->has_finished_course( $course_id ) ) {
483 learn_press_add_message( __( 'You have already finished course', 'learnpress' ) );
484 } else {
485 learn_press_add_message( __( 'You have already enrolled course', 'learnpress' ) );
486 }
487 }*/
488 } else {
489
490 // Checkout page is not setting up
491 if ( ! $has_checkout ) {
492 learn_press_add_message( __( 'Checkout page hasn\'t been setup', 'learnpress' ), 'error' );
493 } else {
494 wp_redirect( apply_filters( 'learn_press_checkout_redirect', $redirect ) );
495 exit();
496 }
497 }
498
499 return;
500 }
501
502 /**
503 * Destroy cart instance
504 */
505 public function destroy() {
506
507 }
508
509
510 /**
511 * Get unique instance of LP_Cart object
512 *
513 * @return LP_Cart|mixed
514 */
515 public static function instance() {
516 $class = __CLASS__;
517 if ( function_exists( 'get_called_class' ) ) {
518 $class = get_called_class();
519 }
520
521 $backtrace = debug_backtrace();
522
523 if ( isset( $backtrace[2]['function'] ) ) {
524 if ( 'call_user_func' === $backtrace[2]['function'] ) {
525 $class = $backtrace[2]['args'][0][0];
526 }
527 } elseif ( isset( $backtrace[2]['class'] ) ) {
528 $class = $backtrace[2]['class'];
529 }
530
531 if ( empty( self::$instances[ $class ] ) ) {
532 self::$instances[ $class ] = new $class();
533 }
534
535 return self::$instances[ $class ];
536 }
537 }
538