PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.2.1
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.2.1
4.4.10 4.4.9.1 4.4.9 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 All 142 releases
learnpress / inc / cart / class-lp-cart.php

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

490 lines 11.2 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 $instance = null;
22
23 /**
24 * Hold the content of the cart
25 *
26 * @var array
27 */
28 protected $_cart_content = [];
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::register( 'add-course-to-cart', array( $this, 'add_to_cart' ), 20 );
62 LP_Request::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 // Only load on checkout page
76 $page_checkout_option = untrailingslashit( get_the_permalink( learn_press_get_page_id( 'checkout' ) ) );
77 $page_checkout_option = str_replace( '/', '\/', $page_checkout_option );
78 $pattern = '/' . $page_checkout_option . '/';
79 if ( ! preg_match( $pattern, LP_Helper::getUrlCurrent() ) ) {
80 return;
81 }
82
83 //$this->get_cart_from_session();
84 }
85
86 /**
87 * @deprecated 4.1.7.2
88 */
89 public function maybe_set_cart_cookies() {
90
91 if ( ! headers_sent()/* && did_action( 'wp_loaded' )*/ ) {
92 // $this->set_cart_cookies( ! $this->is_empty() );
93 }
94 }
95
96 /**
97 * @deprecated 4.2.1
98 */
99 private function set_cart_cookies( $set = true ) {
100 _deprecated_function( __METHOD__, '4.2.1' );
101 /*if ( $set ) {
102 learn_press_setcookie( 'wordpress_lp_cart', 1 );
103 } elseif ( isset( $_COOKIE['wordpress_lp_cart'] ) ) {
104 learn_press_setcookie( 'wordpress_lp_cart', 0, time() - HOUR_IN_SECONDS );
105 }
106
107 do_action( 'learn_press_set_cart_cookies', $set );*/
108 }
109
110 /**
111 * Get data from session
112 *
113 * @return array
114 * @deprecated 4.1.7.3
115 */
116 public function get_cart_for_session() {
117 _deprecated_function( __FUNCTION__, '4.1.7.3', 'get_cart' );
118 $cart_session = array();
119
120 if ( $this->get_cart() ) {
121 foreach ( $this->get_cart() as $key => $values ) {
122 $cart_session[ $key ] = $values;
123 unset( $cart_session[ $key ]['data'] );
124 }
125 }
126
127 return $cart_session;
128 }
129
130 /**
131 * Get cart content.
132 *
133 * @return array
134 */
135 public function get_cart(): array {
136 /*if ( ! did_action( 'wp_loaded' ) ) {
137 _doing_it_wrong( __FUNCTION__, __( 'Get cart should not be called before the wp_loaded action.', 'learnpress' ), '2.3' );
138 }*/
139
140 /*if ( ! did_action( 'learn_press_cart_loaded_from_session' ) ) {
141 return $this->get_cart_from_session();
142 }*/
143
144 return array_filter( (array) $this->_cart_content );
145 }
146
147 /**
148 * Add course to cart.
149 *
150 * @param int $item_id
151 * @param int $quantity
152 * @param array $item_data
153 *
154 * @return string|false
155 */
156 public function add_to_cart( int $item_id = 0, int $quantity = 1, array $item_data = array() ) {
157 try {
158 $item_type = get_post_type( $item_id );
159
160 if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
161 throw new Exception( 'Item type is invalid!', 'learnpress' );
162 }
163
164 switch ( $item_type ) {
165 case LP_COURSE_CPT:
166 $course = learn_press_get_course( $item_id );
167
168 if ( ! $course->is_purchasable() ) {
169 throw new Exception( __( 'Sorry! This course is not purchasable.', 'learnpress' ) );
170 }
171
172 if ( ! $course->is_in_stock() ) {
173 throw new Exception( __( 'Sorry! The number of enrolled students has reached its limit', 'learnpress' ) );
174 }
175
176 //$item_data['data'] = $course;
177 break;
178 default:
179 $item_data = apply_filters( 'learnpress/cart/add-item/item_type_' . $item_type, $item_data, $item_id, $quantity );
180 break;
181 }
182
183 // $item_data = apply_filters( 'learnpress/cart/item-data', $item_data, $item_id );
184
185 $cart_id = $this->generate_cart_id( $item_id, $item_data );
186
187 $this->_cart_content[ $cart_id ] = apply_filters(
188 'learn_press_add_cart_item',
189 array_merge(
190 array(
191 'item_id' => $item_id,
192 'quantity' => $quantity,
193 //'data' => array(),
194 ),
195 $item_data
196 )
197 );
198
199 // Update cart to session DB.
200 $this->update_session();
201
202 //$this->set_cart_cookies( true );
203
204 do_action( 'learn-press/add-to-cart', $item_id, $quantity, $item_data, $cart_id );
205 return $cart_id;
206 } catch ( Exception $e ) {
207 if ( $e->getMessage() ) {
208 learn_press_add_message( $e->getMessage(), 'error' );
209 }
210
211 return false;
212 }
213 }
214
215 /**
216 * Remove an item from cart
217 *
218 * @param $item_id
219 *
220 * @return bool
221 */
222 public function remove_item( $item_id ) {
223 if ( isset( $this->_cart_content['items'][ $item_id ] ) ) {
224
225 do_action( 'learn_press_remove_cart_item', $item_id, $this );
226
227 unset( $this->_cart_content['items'][ $item_id ] );
228
229 do_action( 'learn_press_cart_item_removed', $item_id, $this );
230
231 $this->update_session();
232
233 return true;
234 }
235
236 return false;
237 }
238
239 /**
240 * Re-calculate cart totals and update data to session
241 *
242 * @since 3.0.0
243 * @version 4.0.1
244 */
245 public function calculate_totals() {
246 $data = new stdClass();
247 $total = 0;
248 $data->subtotal = $total;
249 $data->total = $total;
250 $subtotal = $total;
251 $this->total = $total;
252 $this->subtotal = $total;
253 $items = $this->get_cart();
254
255 if ( $items ) {
256 foreach ( $items as $cart_id => $item ) {
257 $item_type = get_post_type( $item['item_id'] );
258 if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
259 continue;
260 }
261
262 switch ( $item_type ) {
263 case LP_COURSE_CPT:
264 $course = learn_press_get_course( $item['item_id'] );
265 $subtotal = $course->get_price() * absint( $item['quantity'] );
266 break;
267 default:
268 $subtotal = apply_filters( 'learnpress/cart/calculate_sub_total/item_type_' . $item_type, $subtotal, $item );
269 break;
270 }
271
272 $total = $subtotal;
273
274 $data->subtotal += $subtotal;
275 $data->total += $total;
276
277 // For template old use.
278 LearnPress::instance()->cart->subtotal += $subtotal;
279 LearnPress::instance()->cart->total += $total;
280 }
281 }
282
283 return apply_filters( 'lp/cart/calculate_total', $data );
284
285 //$this->update_session();
286 }
287
288 /**
289 * Update cart content to session
290 *
291 * @since 3.0.0
292 * @version 1.0.1
293 */
294 public function update_session() {
295 //learn_press_session_set( $this->_cart_session_key, $this->get_cart_for_session() );
296 $cart = $this->get_cart();
297
298 // Only save data item_id and quantity.
299 /**
300 * Current certificate is not compatible with type $data_cart_save,
301 * because certificate override hook 'learn-press/review-order/cart-item-product' to set course.
302 * Need rewrite certificate to compatible with new cart.
303 */
304 $data_cart_save = array_map(
305 function ( $item ) {
306 return array(
307 'item_id' => $item['item_id'],
308 'quantity' => $item['quantity'],
309 );
310 },
311 $cart
312 );
313
314 LearnPress::instance()->session->set( $this->_cart_session_key, $cart, true );
315 }
316
317 /**
318 * Get cart id
319 *
320 * @return mixed
321 * @deprecated 4.2.0
322 */
323 public function get_cart_id() {
324 _deprecated_function( __METHOD__, '4.2.0' );
325 return ! empty( $_SESSION['learn_press_cart']['cart_id'] ) ? $_SESSION['learn_press_cart']['cart_id'] : 0;
326 }
327
328 /**
329 * Get all items from cart.
330 *
331 * @return array
332 */
333 public function get_items(): array {
334 return $this->get_cart();
335 }
336
337 /**
338 * Load cart content data from session
339 *
340 * @since 3.0.0
341 * @version 3.0.2
342 * @modify 4.2.0 - tungnx
343 */
344 public function get_cart_from_session() {
345 $session_data = LearnPress::instance()->session->get_session_data();
346 $cart = maybe_unserialize( $session_data['cart'] ?? '' );
347 $this->_cart_content = $cart;
348 return $this->_cart_content;
349 }
350
351 /**
352 * Get cart sub-total
353 *
354 * @return mixed
355 */
356 public function get_subtotal() {
357 $subtotal = apply_filters( 'learn_press_get_cart_subtotal', learn_press_format_price( $this->subtotal, true ) );
358
359 return apply_filters( 'learn-press/cart-subtotal', $subtotal );
360 }
361
362 /**
363 * Get cart total
364 *
365 * @return mixed
366 */
367 public function get_total() {
368 $total = apply_filters( 'learn_press_get_cart_total', learn_press_format_price( $this->total, true ) );
369
370 return apply_filters( 'learn-press/cart-total', $total );
371 }
372
373 /**
374 * Generate unique cart id from course id and data.
375 *
376 * @param int $course_id
377 * @param mixed $data
378 *
379 * @return string
380 */
381 public function generate_cart_id( $course_id, $data = '' ) {
382 $cart_id = array( $course_id );
383
384 if ( is_array( $data ) ) {
385 foreach ( $data as $key => $value ) {
386 $cart_id[1] = '';
387
388 if ( is_array( $value ) || is_object( $value ) ) {
389 $value = http_build_query( $value );
390 }
391
392 $cart_id[1] .= trim( $key ) . trim( $value );
393 }
394 }
395
396 return apply_filters( 'learn-press/cart-id', md5( join( '_', $cart_id ) ), $cart_id, $data );
397 }
398
399 /**
400 * Return subtotal of cart content
401 *
402 * @param LP_Course|LP_Certificate $item
403 * @param int $quantity
404 *
405 * @return mixed
406 */
407 public function get_item_subtotal( $item, int $quantity = 1 ) {
408 $price = $item->get_price();
409 $row_price = $price * $quantity;
410 $course_subtotal = learn_press_format_price( $row_price, true );
411
412 return apply_filters( 'learn-press/cart/item-subtotal', $course_subtotal, $item, $quantity, $this );
413 }
414
415 /**
416 * Clean all items from cart
417 *
418 * @return $this
419 */
420 public function empty_cart(): LP_Cart {
421
422 do_action( 'learn-press/cart/before-empty' );
423
424 $this->_cart_content = array();
425 $lp_session = LearnPress::instance()->session;
426 $lp_session->remove( 'order_awaiting_payment' );
427 $lp_session->remove( 'cart', true );
428 //unset( LearnPress::instance()->session->order_awaiting_payment );
429 //unset( LearnPress::instance()->session->cart );
430
431 do_action( 'learn-press/cart/emptied' );
432
433 return $this;
434 }
435
436 /**
437 * Check if cart is empty or not
438 *
439 * @return bool
440 */
441 public function is_empty(): bool {
442 $this->get_cart_from_session();
443 return sizeof( $this->get_cart() ) === 0;
444 }
445
446 /**
447 * Get checkout url for checkout page
448 * Return default url of checkout page
449 *
450 * @return mixed
451 */
452 public function get_checkout_url() {
453 $checkout_url = learn_press_get_page_link( 'checkout' );
454
455 return apply_filters( 'learn_press_get_checkout_url', $checkout_url );
456 }
457
458 /**
459 * Checks if need to payment
460 * Return true if cart total greater than 0
461 *
462 * @return mixed
463 */
464 public function needs_payment() {
465 $cart_data = $this->calculate_totals();
466 return apply_filters( 'learn_press_cart_needs_payment', $cart_data->total > 0, $this );
467 }
468
469 /**
470 * Destroy cart instance
471 */
472 public function destroy() {
473
474 }
475
476
477 /**
478 * Get unique instance of LP_Cart object
479 *
480 * @return LP_Cart
481 */
482 public static function instance() {
483 if ( is_null( self::$instance ) ) {
484 self::$instance = new self();
485 }
486
487 return self::$instance;
488 }
489 }
490