PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
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 4.1.7.3.1 4.1.7.3.2 All 140 releases
← All changes | inc/cart/class-lp-cart.php +391 -391 4.3.8 → 4.4.9 View file →
@@ -1,391 +1,391 @@
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.1
10 - */
11 -
12 -use LearnPress\Models\CourseModel;
13 -
14 -defined( 'ABSPATH' ) || exit();
15 -
16 -class LP_Cart {
17 -
18 - /**
19 - * Unique instance of LP_Cart
20 - *
21 - * @var LP_Cart object
22 - */
23 - private static $instance = null;
24 -
25 - /**
26 - * Hold the content of the cart
27 - *
28 - * @var array
29 - */
30 - protected $_cart_content = [];
31 -
32 - /**
33 - * Key of cart content stored in session
34 - *
35 - * @var string
36 - */
37 - protected $_cart_session_key = 'cart';
38 -
39 - /**
40 - * Cart total
41 - *
42 - * @var int
43 - */
44 - public $total = 0;
45 -
46 - /**
47 - * Cart subtotal
48 - *
49 - * @var int
50 - */
51 - public $subtotal = 0;
52 -
53 - /**
54 - * Constructor
55 - *
56 - * @param string $key . Added since 3.3.0
57 - */
58 - public function __construct( $key = '' ) {
59 - if ( $key ) {
60 - $this->_cart_session_key = $key;
61 - }
62 -
63 - LP_Request::register( 'add-course-to-cart', array( $this, 'add_to_cart' ), 20 );
64 - LP_Request::register( 'remove-cart-item', array( $this, 'remove_item' ), 20 );
65 -
66 - //add_action( 'learn-press/add-to-cart', array( $this, 'calculate_totals' ), 10 );
67 - //add_action( 'wp', array( $this, 'maybe_set_cart_cookies' ), 99 );
68 - //add_action( 'shutdown', array( $this, 'maybe_set_cart_cookies' ), 0 );
69 - //add_action( 'wp_loaded', array( $this, 'init' ) );
70 - }
71 -
72 - /**
73 - * Add course to cart.
74 - *
75 - * @param int $item_id
76 - * @param int $quantity
77 - * @param array $item_data
78 - *
79 - * @return string|false
80 - */
81 - public function add_to_cart( int $item_id = 0, int $quantity = 1, array $item_data = array() ) {
82 - try {
83 - /**
84 - * Todo: check it to change, not use get_post_type
85 - * Ex: addon membership has plan need payment, but not use custom post type
86 - * Or addon certificate, currently use custom post type, but feature after upgrade, not save on posts table
87 - */
88 - $item_type = get_post_type( $item_id );
89 -
90 - if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
91 - throw new Exception( 'Item type is invalid!', 'learnpress' );
92 - }
93 -
94 - switch ( $item_type ) {
95 - case LP_COURSE_CPT:
96 - $course = CourseModel::find( $item_id, true );
97 - if ( ! $course ) {
98 - throw new Exception( __( 'Course is not exists!', 'learnpress' ) );
99 - }
100 - break;
101 - default:
102 - $item_data = apply_filters( 'learnpress/cart/add-item/item_type_' . $item_type, $item_data, $item_id, $quantity );
103 - break;
104 - }
105 -
106 - $cart_id = $this->generate_cart_id( $item_id, $item_data );
107 - $this->_cart_content = $this->get_cart_from_session();
108 - $this->_cart_content[ $cart_id ] = apply_filters(
109 - 'learn_press_add_cart_item',
110 - array_merge(
111 - array(
112 - 'item_id' => $item_id,
113 - 'quantity' => $quantity,
114 - //'data' => array(),
115 - ),
116 - $item_data
117 - )
118 - );
119 -
120 - // Fixed security, quantity must be > 0
121 - if ( (int) $this->_cart_content[ $cart_id ]['quantity'] <= 0 ) {
122 - $this->_cart_content[ $cart_id ]['quantity'] = 1;
123 - }
124 -
125 - // Update cart to session DB.
126 - $this->update_session( $this->_cart_content );
127 -
128 - do_action( 'learn-press/add-to-cart', $item_id, $quantity, $item_data, $cart_id );
129 -
130 - return $cart_id;
131 - } catch ( Exception $e ) {
132 - if ( $e->getMessage() ) {
133 -
134 - }
135 -
136 - return false;
137 - }
138 - }
139 -
140 - /**
141 - * Remove an item from cart
142 - *
143 - * @param $item_id
144 - *
145 - * @return bool
146 - */
147 - public function remove_item( $item_id ) {
148 - if ( isset( $this->_cart_content['items'][ $item_id ] ) ) {
149 -
150 - do_action( 'learn_press_remove_cart_item', $item_id, $this );
151 -
152 - unset( $this->_cart_content['items'][ $item_id ] );
153 -
154 - do_action( 'learn_press_cart_item_removed', $item_id, $this );
155 -
156 - $this->update_session( $this->_cart_content );
157 -
158 - return true;
159 - }
160 -
161 - return false;
162 - }
163 -
164 - /**
165 - * Re-calculate cart totals and update data to session
166 - *
167 - * @since 3.0.0
168 - * @version 4.0.2
169 - */
170 - public function calculate_totals() {
171 - $data = new stdClass();
172 - $total = 0;
173 - $data->subtotal = $total;
174 - $data->total = $total;
175 - $subtotal = $total;
176 - $this->total = $total;
177 - $this->subtotal = $total;
178 - $items = $this->get_items();
179 -
180 - if ( $items ) {
181 - foreach ( $items as $cart_id => $item ) {
182 - $item_type = get_post_type( $item['item_id'] );
183 - if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
184 - continue;
185 - }
186 -
187 - switch ( $item_type ) {
188 - case LP_COURSE_CPT:
189 - $course = learn_press_get_course( $item['item_id'] );
190 - $subtotal = $course->get_price() * absint( $item['quantity'] );
191 - break;
192 - default:
193 - $subtotal = apply_filters( 'learnpress/cart/calculate_sub_total/item_type_' . $item_type, $subtotal, $item );
194 - break;
195 - }
196 -
197 - $total = $subtotal;
198 -
199 - $data->subtotal += $subtotal;
200 - $data->total += $total;
201 -
202 - // For template old use.
203 - LearnPress::instance()->cart->subtotal += $subtotal;
204 - LearnPress::instance()->cart->total += $total;
205 - }
206 - }
207 -
208 - return apply_filters( 'lp/cart/calculate_total', $data, $items );
209 -
210 - //$this->update_session();
211 - }
212 -
213 - /**
214 - * Update cart content to session
215 - *
216 - * @since 3.0.0
217 - * @version 1.0.1
218 - */
219 - public function update_session( array $cart_content = [] ) {
220 - //learn_press_session_set( $this->_cart_session_key, $this->get_cart_for_session() );
221 - //$cart = $this->get_cart();
222 -
223 - // Only save data item_id and quantity.
224 - /**
225 - * Current certificate is not compatible with type $data_cart_save,
226 - * because certificate override hook 'learn-press/review-order/cart-item-product' to set course.
227 - * Need rewrite certificate to compatible with new cart.
228 - */
229 - /*$data_cart_save = array_map(
230 - function ( $item ) {
231 - return array(
232 - 'item_id' => $item['item_id'],
233 - 'quantity' => $item['quantity'],
234 - );
235 - },
236 - $cart
237 - );*/
238 -
239 - LearnPress::instance()->session->set( $this->_cart_session_key, $cart_content, true );
240 - }
241 -
242 - /**
243 - * Get all items from cart.
244 - *
245 - * @return array
246 - */
247 - public function get_items(): array {
248 - return $this->get_cart_from_session();
249 - }
250 -
251 - /**
252 - * Load cart content data from session
253 - *
254 - * @since 3.0.0
255 - * @version 3.0.2
256 - * @modify 4.2.0 - tungnx
257 - */
258 - public function get_cart_from_session() {
259 - $session_data = LearnPress::instance()->session->get_session_data();
260 - $cart = maybe_unserialize( $session_data['cart'] ?? '' );
261 - if ( ! is_array( $cart ) ) {
262 - $cart = [];
263 - }
264 -
265 - $this->_cart_content = $cart;
266 -
267 - return $this->_cart_content;
268 - }
269 -
270 - /**
271 - * Get cart sub-total
272 - *
273 - * @return mixed
274 - */
275 - public function get_subtotal() {
276 - $subtotal = learn_press_format_price( $this->subtotal, true );
277 -
278 - return apply_filters( 'learn-press/cart-subtotal', $subtotal, $this );
279 - }
280 -
281 - /**
282 - * Get cart total
283 - *
284 - * @return mixed
285 - */
286 - public function get_total() {
287 - $total = learn_press_format_price( $this->total, true );
288 -
289 - return apply_filters( 'learn-press/cart-total', $total, $this );
290 - }
291 -
292 - /**
293 - * Generate unique cart id from course id and data.
294 - *
295 - * @param int $course_id
296 - * @param mixed $data
297 - *
298 - * @return string
299 - */
300 - public function generate_cart_id( $course_id, $data = '' ) {
301 - $cart_id = array( $course_id );
302 -
303 - if ( is_array( $data ) ) {
304 - foreach ( $data as $key => $value ) {
305 - $cart_id[1] = '';
306 -
307 - if ( is_array( $value ) || is_object( $value ) ) {
308 - $value = http_build_query( $value );
309 - }
310 -
311 - $cart_id[1] .= trim( $key ) . trim( $value );
312 - }
313 - }
314 -
315 - return apply_filters( 'learn-press/cart-id', md5( join( '_', $cart_id ) ), $cart_id, $data );
316 - }
317 -
318 - /**
319 - * Return subtotal of cart content
320 - *
321 - * @param LP_Course|LP_Certificate|CourseModel $item
322 - * @param int $quantity
323 - *
324 - * @return mixed
325 - */
326 - public function get_item_subtotal( $item, int $quantity = 1 ) {
327 - $price = $item->get_price();
328 - $row_price = $price * $quantity;
329 - $course_subtotal = learn_press_format_price( $row_price, true );
330 -
331 - return apply_filters( 'learn-press/cart/item-subtotal', $course_subtotal, $item, $quantity, $this );
332 - }
333 -
334 - /**
335 - * Clean all items from cart
336 - *
337 - * @return $this
338 - */
339 - public function empty_cart(): LP_Cart {
340 -
341 - do_action( 'learn-press/cart/before-empty' );
342 -
343 - $this->_cart_content = array();
344 - $lp_session = LearnPress::instance()->session;
345 - $lp_session->remove( 'order_awaiting_payment', true );
346 - $lp_session->remove( 'cart', true );
347 - //unset( LearnPress::instance()->session->order_awaiting_payment );
348 - //unset( LearnPress::instance()->session->cart );
349 -
350 - do_action( 'learn-press/cart/emptied' );
351 -
352 - return $this;
353 - }
354 -
355 - /**
356 - * Check if cart is empty or not
357 - *
358 - * @return bool
359 - */
360 - public function is_empty(): bool {
361 - $cart_content = $this->get_cart_from_session();
362 -
363 - return sizeof( $cart_content ) === 0;
364 - }
365 -
366 - /**
367 - * Checks if need to payment
368 - * Return true if cart total greater than 0
369 - *
370 - * @return mixed
371 - */
372 - public function needs_payment() {
373 - $cart_data = $this->calculate_totals();
374 -
375 - return apply_filters( 'learn_press_cart_needs_payment', $cart_data->total > 0, $this );
376 - }
377 -
378 -
379 - /**
380 - * Get unique instance of LP_Cart object
381 - *
382 - * @return LP_Cart
383 - */
384 - public static function instance() {
385 - if ( is_null( self::$instance ) ) {
386 - self::$instance = new self();
387 - }
388 -
389 - return self::$instance;
390 - }
391 -}
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.1
10 + */
11 +
12 +use LearnPress\Models\CourseModel;
13 +
14 +defined( 'ABSPATH' ) || exit();
15 +
16 +class LP_Cart {
17 +
18 + /**
19 + * Unique instance of LP_Cart
20 + *
21 + * @var LP_Cart object
22 + */
23 + private static $instance = null;
24 +
25 + /**
26 + * Hold the content of the cart
27 + *
28 + * @var array
29 + */
30 + protected $_cart_content = [];
31 +
32 + /**
33 + * Key of cart content stored in session
34 + *
35 + * @var string
36 + */
37 + protected $_cart_session_key = 'cart';
38 +
39 + /**
40 + * Cart total
41 + *
42 + * @var int
43 + */
44 + public $total = 0;
45 +
46 + /**
47 + * Cart subtotal
48 + *
49 + * @var int
50 + */
51 + public $subtotal = 0;
52 +
53 + /**
54 + * Constructor
55 + *
56 + * @param string $key . Added since 3.3.0
57 + */
58 + public function __construct( $key = '' ) {
59 + if ( $key ) {
60 + $this->_cart_session_key = $key;
61 + }
62 +
63 + LP_Request::register( 'add-course-to-cart', array( $this, 'add_to_cart' ), 20 );
64 + LP_Request::register( 'remove-cart-item', array( $this, 'remove_item' ), 20 );
65 +
66 + //add_action( 'learn-press/add-to-cart', array( $this, 'calculate_totals' ), 10 );
67 + //add_action( 'wp', array( $this, 'maybe_set_cart_cookies' ), 99 );
68 + //add_action( 'shutdown', array( $this, 'maybe_set_cart_cookies' ), 0 );
69 + //add_action( 'wp_loaded', array( $this, 'init' ) );
70 + }
71 +
72 + /**
73 + * Add course to cart.
74 + *
75 + * @param int $item_id
76 + * @param int $quantity
77 + * @param array $item_data
78 + *
79 + * @return string|false
80 + */
81 + public function add_to_cart( int $item_id = 0, int $quantity = 1, array $item_data = array() ) {
82 + try {
83 + /**
84 + * Todo: check it to change, not use get_post_type
85 + * Ex: addon membership has plan need payment, but not use custom post type
86 + * Or addon certificate, currently use custom post type, but feature after upgrade, not save on posts table
87 + */
88 + $item_type = get_post_type( $item_id );
89 +
90 + if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
91 + throw new Exception( __( 'Item type is invalid!', 'learnpress' ) );
92 + }
93 +
94 + switch ( $item_type ) {
95 + case LP_COURSE_CPT:
96 + $course = CourseModel::find( $item_id, true );
97 + if ( ! $course ) {
98 + throw new Exception( __( 'Course is not exists!', 'learnpress' ) );
99 + }
100 + break;
101 + default:
102 + $item_data = apply_filters( 'learnpress/cart/add-item/item_type_' . $item_type, $item_data, $item_id, $quantity );
103 + break;
104 + }
105 +
106 + $cart_id = $this->generate_cart_id( $item_id, $item_data );
107 + $this->_cart_content = $this->get_cart_from_session();
108 + $this->_cart_content[ $cart_id ] = apply_filters(
109 + 'learn_press_add_cart_item',
110 + array_merge(
111 + array(
112 + 'item_id' => $item_id,
113 + 'quantity' => $quantity,
114 + //'data' => array(),
115 + ),
116 + $item_data
117 + )
118 + );
119 +
120 + // Fixed security, quantity must be > 0
121 + if ( (int) $this->_cart_content[ $cart_id ]['quantity'] <= 0 ) {
122 + $this->_cart_content[ $cart_id ]['quantity'] = 1;
123 + }
124 +
125 + // Update cart to session DB.
126 + $this->update_session( $this->_cart_content );
127 +
128 + do_action( 'learn-press/add-to-cart', $item_id, $quantity, $item_data, $cart_id );
129 +
130 + return $cart_id;
131 + } catch ( Exception $e ) {
132 + if ( $e->getMessage() ) {
133 +
134 + }
135 +
136 + return false;
137 + }
138 + }
139 +
140 + /**
141 + * Remove an item from cart
142 + *
143 + * @param $item_id
144 + *
145 + * @return bool
146 + */
147 + public function remove_item( $item_id ) {
148 + if ( isset( $this->_cart_content['items'][ $item_id ] ) ) {
149 +
150 + do_action( 'learn_press_remove_cart_item', $item_id, $this );
151 +
152 + unset( $this->_cart_content['items'][ $item_id ] );
153 +
154 + do_action( 'learn_press_cart_item_removed', $item_id, $this );
155 +
156 + $this->update_session( $this->_cart_content );
157 +
158 + return true;
159 + }
160 +
161 + return false;
162 + }
163 +
164 + /**
165 + * Re-calculate cart totals and update data to session
166 + *
167 + * @since 3.0.0
168 + * @version 4.0.2
169 + */
170 + public function calculate_totals() {
171 + $data = new stdClass();
172 + $total = 0;
173 + $data->subtotal = $total;
174 + $data->total = $total;
175 + $subtotal = $total;
176 + $this->total = $total;
177 + $this->subtotal = $total;
178 + $items = $this->get_items();
179 +
180 + if ( $items ) {
181 + foreach ( $items as $cart_id => $item ) {
182 + $item_type = get_post_type( $item['item_id'] );
183 + if ( ! in_array( $item_type, learn_press_get_item_types_can_purchase() ) ) {
184 + continue;
185 + }
186 +
187 + switch ( $item_type ) {
188 + case LP_COURSE_CPT:
189 + $course = learn_press_get_course( $item['item_id'] );
190 + $subtotal = $course->get_price() * absint( $item['quantity'] );
191 + break;
192 + default:
193 + $subtotal = apply_filters( 'learnpress/cart/calculate_sub_total/item_type_' . $item_type, $subtotal, $item );
194 + break;
195 + }
196 +
197 + $total = $subtotal;
198 +
199 + $data->subtotal += $subtotal;
200 + $data->total += $total;
201 +
202 + // For template old use.
203 + LearnPress::instance()->cart->subtotal += $subtotal;
204 + LearnPress::instance()->cart->total += $total;
205 + }
206 + }
207 +
208 + return apply_filters( 'lp/cart/calculate_total', $data, $items );
209 +
210 + //$this->update_session();
211 + }
212 +
213 + /**
214 + * Update cart content to session
215 + *
216 + * @since 3.0.0
217 + * @version 1.0.1
218 + */
219 + public function update_session( array $cart_content = [] ) {
220 + //learn_press_session_set( $this->_cart_session_key, $this->get_cart_for_session() );
221 + //$cart = $this->get_cart();
222 +
223 + // Only save data item_id and quantity.
224 + /**
225 + * Current certificate is not compatible with type $data_cart_save,
226 + * because certificate override hook 'learn-press/review-order/cart-item-product' to set course.
227 + * Need rewrite certificate to compatible with new cart.
228 + */
229 + /*$data_cart_save = array_map(
230 + function ( $item ) {
231 + return array(
232 + 'item_id' => $item['item_id'],
233 + 'quantity' => $item['quantity'],
234 + );
235 + },
236 + $cart
237 + );*/
238 +
239 + LearnPress::instance()->session->set( $this->_cart_session_key, $cart_content, true );
240 + }
241 +
242 + /**
243 + * Get all items from cart.
244 + *
245 + * @return array
246 + */
247 + public function get_items(): array {
248 + return $this->get_cart_from_session();
249 + }
250 +
251 + /**
252 + * Load cart content data from session
253 + *
254 + * @since 3.0.0
255 + * @version 3.0.2
256 + * @modify 4.2.0 - tungnx
257 + */
258 + public function get_cart_from_session() {
259 + $session_data = LearnPress::instance()->session->get_session_data();
260 + $cart = maybe_unserialize( $session_data['cart'] ?? '' );
261 + if ( ! is_array( $cart ) ) {
262 + $cart = [];
263 + }
264 +
265 + $this->_cart_content = $cart;
266 +
267 + return $this->_cart_content;
268 + }
269 +
270 + /**
271 + * Get cart sub-total
272 + *
273 + * @return mixed
274 + */
275 + public function get_subtotal() {
276 + $subtotal = learn_press_format_price( $this->subtotal, true );
277 +
278 + return apply_filters( 'learn-press/cart-subtotal', $subtotal, $this );
279 + }
280 +
281 + /**
282 + * Get cart total
283 + *
284 + * @return mixed
285 + */
286 + public function get_total() {
287 + $total = learn_press_format_price( $this->total, true );
288 +
289 + return apply_filters( 'learn-press/cart-total', $total, $this );
290 + }
291 +
292 + /**
293 + * Generate unique cart id from course id and data.
294 + *
295 + * @param int $course_id
296 + * @param mixed $data
297 + *
298 + * @return string
299 + */
300 + public function generate_cart_id( $course_id, $data = '' ) {
301 + $cart_id = array( $course_id );
302 +
303 + if ( is_array( $data ) ) {
304 + foreach ( $data as $key => $value ) {
305 + $cart_id[1] = '';
306 +
307 + if ( is_array( $value ) || is_object( $value ) ) {
308 + $value = http_build_query( $value );
309 + }
310 +
311 + $cart_id[1] .= trim( $key ) . trim( $value );
312 + }
313 + }
314 +
315 + return apply_filters( 'learn-press/cart-id', md5( join( '_', $cart_id ) ), $cart_id, $data );
316 + }
317 +
318 + /**
319 + * Return subtotal of cart content
320 + *
321 + * @param LP_Course|LP_Certificate|CourseModel $item
322 + * @param int $quantity
323 + *
324 + * @return mixed
325 + */
326 + public function get_item_subtotal( $item, int $quantity = 1 ) {
327 + $price = $item->get_price();
328 + $row_price = $price * $quantity;
329 + $course_subtotal = learn_press_format_price( $row_price, true );
330 +
331 + return apply_filters( 'learn-press/cart/item-subtotal', $course_subtotal, $item, $quantity, $this );
332 + }
333 +
334 + /**
335 + * Clean all items from cart
336 + *
337 + * @return $this
338 + */
339 + public function empty_cart(): LP_Cart {
340 +
341 + do_action( 'learn-press/cart/before-empty' );
342 +
343 + $this->_cart_content = array();
344 + $lp_session = LearnPress::instance()->session;
345 + $lp_session->remove( 'order_awaiting_payment', true );
346 + $lp_session->remove( 'cart', true );
347 + //unset( LearnPress::instance()->session->order_awaiting_payment );
348 + //unset( LearnPress::instance()->session->cart );
349 +
350 + do_action( 'learn-press/cart/emptied' );
351 +
352 + return $this;
353 + }
354 +
355 + /**
356 + * Check if cart is empty or not
357 + *
358 + * @return bool
359 + */
360 + public function is_empty(): bool {
361 + $cart_content = $this->get_cart_from_session();
362 +
363 + return sizeof( $cart_content ) === 0;
364 + }
365 +
366 + /**
367 + * Checks if need to payment
368 + * Return true if cart total greater than 0
369 + *
370 + * @return mixed
371 + */
372 + public function needs_payment() {
373 + $cart_data = $this->calculate_totals();
374 +
375 + return apply_filters( 'learn_press_cart_needs_payment', $cart_data->total > 0, $this );
376 + }
377 +
378 +
379 + /**
380 + * Get unique instance of LP_Cart object
381 + *
382 + * @return LP_Cart
383 + */
384 + public static function instance() {
385 + if ( is_null( self::$instance ) ) {
386 + self::$instance = new self();
387 + }
388 +
389 + return self::$instance;
390 + }
391 +}