PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.0.10
Tutor LMS – eLearning and online course solution v2.0.10
3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 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.5.9 1.6.0 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.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 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.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 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.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / classes / WooCommerce.php
tutor / classes Last commit date
Addons.php 4 years ago Admin.php 4 years ago Ajax.php 3 years ago Announcements.php 4 years ago Assets.php 3 years ago Backend_Page_Trait.php 4 years ago Course.php 3 years ago Course_Embed.php 3 years ago Course_Filter.php 4 years ago Course_List.php 3 years ago Course_Settings_Tabs.php 4 years ago Course_Widget.php 4 years ago Custom_Validation.php 4 years ago Dashboard.php 3 years ago FormHandler.php 4 years ago Frontend.php 3 years ago Gutenberg.php 4 years ago Input.php 3 years ago Instructor.php 4 years ago Instructors_List.php 3 years ago Lesson.php 3 years ago Options_V2.php 3 years ago Post_types.php 4 years ago Private_Course_Access.php 4 years ago Q_and_A.php 3 years ago Question_Answers_List.php 4 years ago Quiz.php 3 years ago Quiz_Attempts_List.php 3 years ago RestAPI.php 4 years ago Reviews.php 4 years ago Rewrite_Rules.php 4 years ago Shortcode.php 4 years ago Student.php 4 years ago Students_List.php 4 years ago Taxonomies.php 4 years ago Template.php 3 years ago Theme_Compatibility.php 5 years ago Tools.php 3 years ago Tools_V2.php 4 years ago Tutor.php 3 years ago TutorEDD.php 4 years ago Tutor_Base.php 5 years ago Tutor_List_Table.php 4 years ago Tutor_Setup.php 3 years ago Upgrader.php 4 years ago User.php 4 years ago Utils.php 3 years ago Video_Stream.php 4 years ago Withdraw.php 3 years ago Withdraw_Requests_List.php 4 years ago WooCommerce.php 3 years ago
WooCommerce.php
716 lines
1 <?php
2
3 /**
4 * Manage WooCommerce integration
5 *
6 * @package Tutor\WooCommerce
7 */
8
9 namespace TUTOR;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * Handle woocommerce hooks
17 */
18 class WooCommerce extends Tutor_Base {
19
20 /**
21 * Register hooks
22 */
23 public function __construct() {
24 parent::__construct();
25
26 // Add option settings.
27 add_filter( 'tutor_monetization_options', array( $this, 'tutor_monetization_options' ) );
28
29 $monetize_by = tutor_utils()->get_option( 'monetize_by' );
30 if ( $monetize_by !== 'wc' ) {
31 return;
32 }
33
34 add_filter( 'tutor/options/attr', array( $this, 'add_options' ) );
35
36 /**
37 * Is Course Purchasable
38 */
39 add_filter( 'is_course_purchasable', array( $this, 'is_course_purchasable' ), 10, 2 );
40 add_filter( 'get_tutor_course_price', array( $this, 'get_tutor_course_price' ), 10, 2 );
41 add_filter( 'tutor_course_sell_by', array( $this, 'tutor_course_sell_by' ) );
42
43 add_filter( 'product_type_options', array( $this, 'add_tutor_type_in_wc_product' ) );
44
45 add_action( 'add_meta_boxes', array( $this, 'register_meta_box' ) );
46 add_action( 'save_post_' . $this->course_post_type, array( $this, 'save_course_meta' ), 10, 2 );
47 add_action( 'save_post_product', array( $this, 'save_wc_product_meta' ) );
48
49 add_action( 'tutor_course/single/before/enroll', 'wc_print_notices' );
50
51 /**
52 * After place new order
53 */
54 add_action( 'woocommerce_new_order', array( $this, 'course_placing_order_from_admin' ), 10, 3 );
55 add_action( 'woocommerce_new_order_item', array( $this, 'course_placing_order_from_customer' ), 10, 3 );
56
57 /**
58 * Order Status Hook
59 *
60 * Remove course from active courses if an order is cancelled or refunded
61 */
62 add_action( 'woocommerce_order_status_changed', array( $this, 'enrolled_courses_status_change' ), 10, 3 );
63
64 /**
65 * Add Earning Data
66 */
67 add_action( 'woocommerce_new_order_item', array( $this, 'add_earning_data' ), 10, 3 );
68 add_action( 'woocommerce_order_status_changed', array( $this, 'add_earning_data_status_change' ), 10, 3 );
69
70 /**
71 * WC Print Notices After Enroll
72 *
73 * @since v.1.3.5
74 */
75 if ( tutor_utils()->has_wc() ) {
76 add_action( 'tutor_course/single/before/inner-wrap', 'wc_print_notices', 10 );
77 add_action( 'tutor_course/single/enrolled/before/inner-wrap', 'wc_print_notices', 10 );
78 }
79
80 /**
81 * Manage WooCommerce plugin dependency
82 *
83 * @since v.1.7.8
84 */
85 $woocommerce_path = dirname( dirname( __DIR__ ) ) . DIRECTORY_SEPARATOR . 'woocommerce' . DIRECTORY_SEPARATOR . 'woocommerce.php';
86 register_deactivation_hook( $woocommerce_path, array( $this, 'disable_tutor_monetization' ) );
87 /**
88 * Redirect student on enrolled courses after course
89 * enrolment complete
90 *
91 * @since 1.9.0
92 */
93 add_action( 'woocommerce_thankyou', array( $this, 'redirect_to_enrolled_courses' ) );
94
95 /**
96 * Change woo commerce cart product link if it is tutor product
97 */
98 add_filter( 'woocommerce_cart_item_permalink', array( $this, 'tutor_update_product_url' ), 10, 2 );
99 add_filter( 'woocommerce_order_item_permalink', array( $this, 'filter_order_item_permalink_callback' ), 10, 3 );
100
101 /**
102 * on WC product delete clear course linked product
103 *
104 * @since 2.0.7
105 */
106 add_action( 'delete_post', array( $this, 'clear_course_linked_product' ) );
107 }
108
109 /**
110 * On WC product delete, clear course linked product
111 *
112 * @param int $post_id
113 * @return void
114 *
115 * @since 2.0.7
116 */
117 public function clear_course_linked_product( $post_id ) {
118 if ( get_post_type( $post_id ) === 'product' ) {
119 global $wpdb;
120 $wpdb->query(
121 $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE meta_key=%s AND meta_value=%d", '_tutor_course_product_id', $post_id )
122 );
123 }
124 }
125
126 function filter_order_item_permalink_callback( $product_permalink, $item, $order ) {
127
128 // For product variations
129 if ( $item->get_variation_id() > 0 ) {
130 $product = $item->get_product();
131
132 $is_visible = $product && $product->is_visible();
133
134 // Get the instance of the parent variable product Object
135 $parent_product = wc_get_product( $item->get_product_id() );
136
137 // Return the parent product permalink (if product is visible)
138 return $is_visible ? $parent_product->get_permalink() : '';
139 }
140
141 $course_id = $this->get_post_id_by_meta_key_and_value( '_tutor_course_product_id', $item->get_product_id() );
142
143 return get_permalink( $course_id );
144 }
145
146 public function get_post_id_by_meta_key_and_value( $key, $value ) {
147 global $wpdb;
148 $meta = $wpdb->get_results( 'SELECT * FROM `' . $wpdb->postmeta . "` WHERE meta_key='" . esc_sql( $key ) . "' AND meta_value='" . esc_sql( $value ) . "'" );
149 if ( is_array( $meta ) && ! empty( $meta ) && isset( $meta[0] ) ) {
150 $meta = $meta[0];
151 }
152 if ( is_object( $meta ) ) {
153 return $meta->post_id;
154 } else {
155 return false;
156 }
157 }
158
159 public function is_course_purchasable( $bool, $course_id ) {
160 if ( ! tutor_utils()->has_wc() ) {
161 return false;
162 }
163
164 $course_id = tutor_utils()->get_post_id( $course_id );
165 $has_product_id = get_post_meta( $course_id, '_tutor_course_product_id', true );
166 if ( $has_product_id ) {
167 return true;
168 }
169 return false;
170 }
171
172 public function get_tutor_course_price( $price, $course_id ) {
173 $price = null;
174
175 if ( tutor_utils()->is_course_purchasable( $course_id ) ) {
176 if ( tutor_utils()->has_wc() ) {
177 $product_id = tutor_utils()->get_course_product_id( $course_id );
178 $product = wc_get_product( $product_id );
179
180 if ( $product ) {
181 ob_start();
182 ?>
183 <div class="price">
184 <?php echo $product->get_price_html(); ?>
185 </div>
186 <?php
187 return ob_get_clean();
188 }
189 }
190 }
191
192 return $price;
193 }
194
195 public function tutor_course_sell_by() {
196 return 'woocommerce';
197 }
198
199 public function add_tutor_type_in_wc_product( $types ) {
200 $types['tutor_product'] = array(
201 'id' => '_tutor_product',
202 'wrapper_class' => 'show_if_simple',
203 'label' => __( 'For Tutor', 'tutor' ),
204 'description' => __( 'This checkmark ensure that you will sell a specif course via this product.', 'tutor' ),
205 'default' => 'no',
206 );
207
208 return $types;
209 }
210
211 /**
212 * Save course meta for attaching WC product
213 *
214 * @param int $post_ID this is course ID
215 * @param mixed $post course details
216 *
217 * @return void
218 */
219 public function save_course_meta( $post_ID, $post ) {
220 do_action( 'save_tutor_course', $post_ID, $post );
221 }
222
223 public function register_meta_box() {
224 tutor_meta_box_wrapper( 'tutor-attach-product', __( 'Add Product', 'tutor' ), array( $this, 'course_add_product_metabox' ), $this->course_post_type, 'advanced', 'high', 'tutor-admin-post-meta' );
225 }
226
227 public function course_add_product_metabox() {
228 include tutor()->path . 'views/metabox/course-add-product-metabox.php';
229 }
230
231 public function save_wc_product_meta( $post_ID ) {
232 $is_tutor_product = sanitize_text_field( tutor_utils()->avalue_dot( '_tutor_product', $_POST ) );
233 if ( $is_tutor_product === 'on' ) {
234 update_post_meta( $post_ID, '_tutor_product', 'yes' );
235 } else {
236 delete_post_meta( $post_ID, '_tutor_product' );
237 }
238 }
239
240 /**
241 * Take enrolled course action based on order status change
242 *
243 * Order auto complete
244 *
245 * @param int $order_id wc order id.
246 * @param string $status_from from status.
247 * @param string $status_to to status.
248 *
249 * @return void
250 */
251 public function enrolled_courses_status_change( $order_id, $status_from, $status_to ) {
252 if ( ! tutor_utils()->is_tutor_order( $order_id ) ) {
253 return;
254 }
255
256 $enrolled_ids_with_course = $this->get_course_enrolled_ids_by_order_id( $order_id );
257
258 if ( $enrolled_ids_with_course ) {
259 $enrolled_ids = wp_list_pluck( $enrolled_ids_with_course, 'enrolled_id' );
260
261 if ( is_array( $enrolled_ids ) && count( $enrolled_ids ) ) {
262 foreach ( $enrolled_ids as $enrolled_id ) {
263 /**
264 * If order status is processing and payment is not cash on
265 * delivery then mark enrollment as completed.
266 *
267 * Note: Order status processing simply mean customer have done
268 * payment.
269 *
270 * @since v2.0.5
271 */
272 if ( self::should_order_auto_complete( $order_id ) ) {
273 tutor_utils()->course_enrol_status_change( $enrolled_id, 'completed' );
274 // Mark complete only from client side.
275 $mark_completed = self::mark_order_complete( $order_id );
276 if ( $mark_completed ) {
277 $user_id = get_post_field( 'post_author', $enrolled_id );
278 $course_id = get_post_field( 'post_parent', $enrolled_id );
279 do_action( 'tutor_after_enrolled', $course_id, $user_id, $enrolled_id );
280 }
281 } else {
282 tutor_utils()->course_enrol_status_change( $enrolled_id, $status_to );
283 }
284 // Invoke enrolled hook.
285 if ( 'completed' === $status_to ) {
286 $user_id = get_post_field( 'post_author', $enrolled_id );
287 $course_id = get_post_field( 'post_parent', $enrolled_id );
288 do_action( 'tutor_after_enrolled', $course_id, $user_id, $enrolled_id );
289 }
290 }
291 }
292 }
293 }
294
295 /**
296 * @param $order_id
297 *
298 * @return array|bool
299 */
300 public function get_course_enrolled_ids_by_order_id( $order_id ) {
301 global $wpdb;
302 // Getting all of courses ids within this order
303
304 $courses_ids = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key LIKE '_tutor_order_for_course_id_%' ", $order_id ) );
305
306 if ( is_array( $courses_ids ) && count( $courses_ids ) ) {
307 $course_enrolled_by_order = array();
308 foreach ( $courses_ids as $courses_id ) {
309 $course_id = str_replace( '_tutor_order_for_course_id_', '', $courses_id->meta_key );
310 // array(order_id => array('course_id' => $course_id, 'enrolled_id' => enrolled_id, 'order_id' => $courses_id->post_id))
311 $course_enrolled_by_order[] = array(
312 'course_id' => $course_id,
313 'enrolled_id' => $courses_id->meta_value,
314 'order_id' => $courses_id->post_id,
315 );
316 }
317 return $course_enrolled_by_order;
318 }
319 return false;
320 }
321
322 /**
323 * Remove course
324 *
325 * TODO: right now it's unused
326 */
327 public function remove_active_course( $order_id ) {
328 global $wpdb;
329 // Getting all of courses ids within this order
330
331 $courses_ids = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->postmeta} WHERE post_id = %d meta_key LIKE '_tutor_order_for_course_id_%' ", $order_id ) );
332 }
333
334
335 /**
336 * @param $attr
337 *
338 * @return mixed
339 *
340 * Add option for WooCommerce settings
341 */
342 public function add_options( $attr ) {
343 $attr['monetization']['blocks']['block_options']['fields'][] = array(
344 'key' => 'enable_guest_course_cart',
345 'type' => 'toggle_switch',
346 'label' => __( 'Enable Guest Mode', 'tutor' ),
347 'label_title' => __( '', 'tutor' ),
348 'default' => 'off',
349 'desc' => __( 'Allow customers to place orders without an account.', 'tutor' ),
350 );
351
352 return $attr;
353 }
354
355 /**
356 * @param $arr
357 *
358 * @return mixed
359 *
360 * Returning monetization options
361 *
362 * @since v.1.3.5
363 */
364 public function tutor_monetization_options( $arr ) {
365 $has_wc = tutor_utils()->has_wc();
366 if ( $has_wc ) {
367 $arr['wc'] = __( 'WooCommerce', 'tutor' );
368 }
369 return $arr;
370 }
371
372 /**
373 * Adding Earning Data processing WooCommerce
374 *
375 * @param $item_id
376 * @param $item
377 * @param $order_id
378 * @since v.1.1.2
379 */
380 public function add_earning_data( $item_id, $item, $order_id ) {
381
382 if ( tutor_utils()->get_option( 'monetize_by' ) != 'wc' ) {
383 return;
384 }
385
386 global $wpdb;
387 $item = new \WC_Order_Item_Product( $item );
388
389 $product_id = $item->get_product_id();
390 $if_has_course = tutor_utils()->product_belongs_with_course( $product_id );
391
392 if ( $if_has_course ) {
393 $course_id = $if_has_course->post_id;
394 $user_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_author FROM {$wpdb->posts} WHERE ID = %d ", $course_id ) );
395 $order_status = $wpdb->get_var( $wpdb->prepare( "SELECT post_status from {$wpdb->posts} where ID = %d ", $order_id ) );
396
397 /**
398 * Return here if already added this product from this order
399 *
400 * @since v1.9.7
401 */
402 $exist_count = (int) $wpdb->get_var(
403 $wpdb->prepare(
404 "SELECT COUNT(earning_id)
405 FROM {$wpdb->prefix}tutor_earnings
406 WHERE course_id=%d
407 AND order_id=%d
408 AND user_id=%d",
409 $course_id,
410 $order_id,
411 $user_id
412 )
413 );
414
415 if ( $exist_count > 0 ) {
416 return;
417 }
418
419 $total_price = $item->get_total();
420
421 $fees_deduct_data = array();
422 $tutor_earning_fees = tutor_utils()->get_option( 'fee_amount_type' );
423 $enable_fees_deducting = tutor_utils()->get_option( 'enable_fees_deducting' );
424
425 $course_price_grand_total = $total_price;
426
427 // Deduct predefined amount (percent or fixed)
428 if ( $enable_fees_deducting ) {
429 $fees_name = tutor_utils()->get_option( 'fees_name', '' );
430 $fees_amount = (int) tutor_utils()->avalue_dot( 'fees_amount', $tutor_earning_fees );
431 $fees_type = tutor_utils()->avalue_dot( 'fees_type', $tutor_earning_fees );
432
433 if ( $fees_amount > 0 ) {
434 if ( $fees_type === 'percent' ) {
435 $fees_amount = ( $total_price * $fees_amount ) / 100;
436 }
437
438 $course_price_grand_total = $total_price - $fees_amount;
439 }
440
441 $fees_deduct_data = array(
442 'deduct_fees_amount' => $fees_amount,
443 'deduct_fees_name' => $fees_name,
444 'deduct_fees_type' => $fees_type,
445 );
446 }
447
448 // Distribute amount between admin and instructor
449 $sharing_enabled = tutor_utils()->get_option( 'enable_revenue_sharing' );
450 $instructor_rate = $sharing_enabled ? tutor_utils()->get_option( 'earning_instructor_commission' ) : 0;
451 $admin_rate = $sharing_enabled ? tutor_utils()->get_option( 'earning_admin_commission' ) : 100;
452 $commission_type = 'percent';
453 $instructor_amount = $instructor_rate > 0 ? ( ( $course_price_grand_total * $instructor_rate ) / 100 ) : 0;
454 $admin_amount = $admin_rate > 0 ? ( ( $course_price_grand_total * $admin_rate ) / 100 ) : 0;
455
456 // (Use Pro Filter - Start)
457 // The response must be same array structure.
458 // Do not change used variable names here, or change in both of here and pro plugin
459 $pro_arg = array(
460 'user_id' => $user_id,
461 'instructor_rate' => $instructor_rate,
462 'admin_rate' => $admin_rate,
463 'instructor_amount' => $instructor_amount,
464 'admin_amount' => $admin_amount,
465 'course_price_grand_total' => $course_price_grand_total,
466 'commission_type' => $commission_type,
467 );
468 $pro_calculation = apply_filters( 'tutor_pro_earning_calculator', $pro_arg );
469 extract( $pro_calculation );
470 // (Use Pro Filter - End)
471
472 // Prepare insertable earning data
473 $earning_data = array(
474 'user_id' => $user_id,
475 'course_id' => $course_id,
476 'order_id' => $order_id,
477 'order_status' => $order_status,
478 'course_price_total' => $total_price,
479 'course_price_grand_total' => $course_price_grand_total,
480
481 'instructor_amount' => $instructor_amount,
482 'instructor_rate' => $instructor_rate,
483 'admin_amount' => $admin_amount,
484 'admin_rate' => $admin_rate,
485
486 'commission_type' => $commission_type,
487 'process_by' => 'woocommerce',
488 'created_at' => date( 'Y-m-d H:i:s', tutor_time() ),
489 );
490 $earning_data = apply_filters( 'tutor_new_earning_data', array_merge( $earning_data, $fees_deduct_data ) );
491
492 $wpdb->insert( $wpdb->prefix . 'tutor_earnings', $earning_data );
493 }
494 }
495
496 /**
497 * @param $order_id
498 * @param $status_from
499 * @param $status_to
500 *
501 * Change Earning data status
502 *
503 * @since v.1.1.2
504 */
505 public function add_earning_data_status_change( $order_id, $status_from, $status_to ) {
506 if ( ! tutor_utils()->is_tutor_order( $order_id ) ) {
507 tutor_log( 'not tutor order' );
508 return;
509 }
510 global $wpdb;
511
512 /**
513 * If it is auto complete order then make earning status complete
514 * to reflect earning for admin & instructor
515 *
516 * @since v2.0.9
517 */
518 if ( self::should_order_auto_complete( $order_id ) ) {
519 $status_to = 'completed';
520 }
521
522 $is_earning_data = (int) $wpdb->get_var(
523 $wpdb->prepare(
524 "SELECT COUNT(earning_id)
525 FROM {$wpdb->prefix}tutor_earnings
526 WHERE order_id = %d ",
527 $order_id
528 )
529 );
530
531 if ( $is_earning_data ) {
532 $update_earning_status = $wpdb->update(
533 $wpdb->prefix . 'tutor_earnings',
534 array( 'order_status' => $status_to ),
535 array( 'order_id' => $order_id )
536 );
537 tutor_log( $update_earning_status . $status_to );
538 do_action( 'tutor_after_earning_status_change', $update_earning_status );
539 }
540 }
541
542 /**
543 * Course placing order from admin
544 *
545 * @param $order_id
546 * @since v.1.6.7
547 */
548 public function course_placing_order_from_admin( $order_id ) {
549 if ( ! is_admin() ) {
550 return;
551 }
552
553 $order = wc_get_order( $order_id );
554 foreach ( $order->get_items() as $item ) {
555 $product_id = $item->get_product_id();
556 $if_has_course = tutor_utils()->product_belongs_with_course( $product_id );
557 if ( $if_has_course ) {
558 $course_id = $if_has_course->post_id;
559 $customer_id = $order->get_customer_id();
560 tutor_utils()->do_enroll( $course_id, $order_id, $customer_id );
561 }
562 }
563 }
564
565 /**
566 * Course placing order from customer
567 *
568 * @param $order_id
569 * @since v.1.6.7
570 */
571 public function course_placing_order_from_customer( $item_id, $item, $order_id ) {
572 if ( is_admin() ) {
573 return;
574 }
575
576 $item = new \WC_Order_Item_Product( $item );
577 $product_id = $item->get_product_id();
578 $if_has_course = tutor_utils()->product_belongs_with_course( $product_id );
579
580 if ( $if_has_course ) {
581 $course_id = $if_has_course->post_id;
582 tutor_utils()->do_enroll( $course_id, $order_id );
583 }
584 }
585
586 /**
587 * Disable course monetization on woocommerce deactivation
588 *
589 * @since v.1.7.8
590 */
591 public function disable_tutor_monetization() {
592 tutor_utils()->update_option( 'monetize_by', 'free' );
593 update_option( 'tutor_show_woocommerce_notice', true );
594 }
595
596 /**
597 * Redirect student on enrolled courses after course
598 * enrolment complete if course is purchasable
599 *
600 * @param $order_id | int
601 * @since 1.9.0
602 */
603 public function redirect_to_enrolled_courses( $order_id ) {
604 if ( ! tutor_utils()->get_option( 'wc_automatic_order_complete_redirect_to_courses' ) ) {
605 // Since 1.9.1
606 return;
607 }
608
609 // get woo order details
610 $order = wc_get_order( $order_id );
611 $tutor_product = false;
612 $url = tutor_utils()->tutor_dashboard_url() . 'enrolled-courses/';
613
614 foreach ( $order->get_items() as $item ) {
615 $product_id = $item->get_product_id();
616 // check if product associated with tutor course
617 $if_has_course = tutor_utils()->product_belongs_with_course( $product_id );
618 if ( $if_has_course ) {
619 $tutor_product = true;
620 }
621 }
622
623 // if tutor product & order status completed
624 if ( $order->has_status( 'completed' ) && $tutor_product ) {
625 wp_safe_redirect( $url );
626 exit;
627 }
628 }
629
630 /**
631 * Change product url on cart page if product is tutor course
632 *
633 * @since 1.9.8
634 */
635 function tutor_update_product_url( $permalink, $cart_item ) {
636
637 $woo_product_id = $cart_item['product_id'];
638 $product_meta = get_post_meta( $woo_product_id );
639
640 if ( isset( $product_meta['_tutor_product'] ) && $product_meta['_tutor_product'][0] ) {
641
642 global $wpdb;
643 $table = $wpdb->base_prefix . 'postmeta';
644 $post_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM {$table} WHERE meta_key = '_tutor_course_product_id' AND meta_value = %d ", $woo_product_id ) );
645
646 if ( $post_id ) {
647 $data = get_post_permalink( $post_id );
648 return $data;
649 }
650 }
651 }
652
653 /**
654 * Mark woocommerce order as complete only from the
655 * client side.
656 *
657 * @since v2.0.5
658 *
659 * @param integer $order_id
660 *
661 * @return boolean
662 */
663 public static function mark_order_complete( int $order_id ): bool {
664 if ( is_admin() ) {
665 return false;
666 }
667 global $wpdb;
668 $update = $wpdb->update(
669 $wpdb->posts,
670 array( 'post_status' => 'wc-completed' ),
671 array( 'ID' => $order_id )
672 );
673 return (bool) $update;
674 }
675
676 /**
677 * Check if order should auto complete
678 *
679 * @since v2.0.9
680 *
681 * @param int $order_id wc order id.
682 *
683 * @return boolean return true if it should auto complete, otherwise false
684 */
685 public static function should_order_auto_complete( int $order_id ): bool {
686 $auto_complete = false;
687 $order = wc_get_order( $order_id );
688 $order_data = is_object( $order ) && method_exists( $order, 'get_data' ) ? $order->get_data() : array();
689
690 $payment_method = isset( $order_data['payment_method'] ) ? $order_data['payment_method'] : '';
691 $monetize_by = tutor_utils()->get_option( 'monetize_by' );
692
693 $should_auto_complete = tutor_utils()->get_option( 'tutor_woocommerce_order_auto_complete' );
694 $is_enabled_auto_complete = 'wc' === $monetize_by && $should_auto_complete ? true : false;
695
696 if ( ! is_admin() && $is_enabled_auto_complete && 'cod' !== $payment_method ) {
697 $auto_complete = true;
698 }
699 return $auto_complete;
700 }
701 }
702
703
704 add_action(
705 'admin_notices',
706 function() {
707
708 $show = get_option( 'tutor_show_woocommerce_notice' ) && tutor_utils()->get_option( 'monetize_by', 'free' ) == 'free';
709
710 if ( $show ) {
711 $message = __( 'Since WooCommerce is disabled, your monetized courses have been set to free. Please make sure to enable Tutor LMS monetization if you decide to re-enable WooCommerce.', 'tutor' );
712 echo '<div class="notice notice-error"><p>' . $message . '</p></div>';
713 }
714 }
715 );
716