PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 1.9.0
Tutor LMS – eLearning and online course solution v1.9.0
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 / Course.php
tutor / classes Last commit date
Addons.php 5 years ago Admin.php 5 years ago Ajax.php 5 years ago Assets.php 5 years ago Course.php 5 years ago Course_Filter.php 5 years ago Course_Settings_Tabs.php 5 years ago Course_Widget.php 5 years ago Custom_Validation.php 5 years ago Dashboard.php 5 years ago Email.php 5 years ago FormHandler.php 5 years ago Frontend.php 5 years ago Gutenberg.php 5 years ago Instructor.php 5 years ago Instructors_List.php 5 years ago Lesson.php 5 years ago Options.php 5 years ago Post_types.php 5 years ago Private_Course_Access.php 5 years ago Q_and_A.php 5 years ago Question_Answers_List.php 5 years ago Quiz.php 5 years ago Quiz_Attempts_List.php 5 years ago RestAPI.php 5 years ago Rewrite_Rules.php 5 years ago Shortcode.php 5 years ago Student.php 5 years ago Students_List.php 5 years ago Taxonomies.php 5 years ago Template.php 5 years ago Theme_Compatibility.php 5 years ago Tools.php 5 years ago Tutor.php 5 years ago TutorEDD.php 5 years ago Tutor_Base.php 5 years ago Tutor_List_Table.php 5 years ago Tutor_Setup.php 5 years ago Upgrader.php 5 years ago User.php 5 years ago Utils.php 5 years ago Video_Stream.php 5 years ago Withdraw.php 5 years ago Withdraw_Requests_List.php 5 years ago WooCommerce.php 5 years ago
Course.php
1316 lines
1 <?php
2 namespace TUTOR;
3
4 if ( ! defined( 'ABSPATH' ) )
5 exit;
6
7 class Course extends Tutor_Base {
8
9 private $additional_meta=array(
10 '_tutor_disable_qa',
11 '_tutor_is_public_course'
12 );
13
14 public function __construct() {
15 parent::__construct();
16
17 add_action( 'add_meta_boxes', array($this, 'register_meta_box') );
18 add_action('save_post_'.$this->course_post_type, array($this, 'save_course_meta'), 10, 2);
19 add_action('wp_ajax_tutor_add_course_topic', array($this, 'tutor_add_course_topic'));
20 add_action('wp_ajax_tutor_update_topic', array($this, 'tutor_update_topic'));
21
22 //Add Column
23 add_filter( "manage_{$this->course_post_type}_posts_columns", array($this, 'add_column'), 10,1 );
24 add_action( "manage_{$this->course_post_type}_posts_custom_column" , array($this, 'custom_lesson_column'), 10, 2 );
25
26 add_action('admin_action_tutor_delete_topic', array($this, 'tutor_delete_topic'));
27 add_action('admin_action_tutor_delete_announcement', array($this, 'tutor_delete_announcement'));
28
29 //Frontend Action
30 add_action('template_redirect', array($this, 'enroll_now'));
31 add_action('template_redirect', array($this, 'mark_course_complete'));
32
33 //Modal Perform
34 add_action('wp_ajax_tutor_load_instructors_modal', array($this, 'tutor_load_instructors_modal'));
35 add_action('wp_ajax_tutor_add_instructors_to_course', array($this, 'tutor_add_instructors_to_course'));
36 add_action('wp_ajax_detach_instructor_from_course', array($this, 'detach_instructor_from_course'));
37
38 /**
39 * Frontend Dashboard
40 */
41 add_action('wp_ajax_tutor_delete_dashboard_course', array($this, 'tutor_delete_dashboard_course'));
42
43 /**
44 * Gutenberg author support
45 */
46 add_filter('wp_insert_post_data', array($this, 'tutor_add_gutenberg_author'), '99', 2);
47
48 /**
49 * Frontend metabox supports for course builder
50 * @since v.1.3.4
51 */
52 add_action('tutor/dashboard_course_builder_form_field_after', array($this, 'register_meta_box_in_frontend'));
53
54 /**
55 * Do Stuff for the course save from frontend
56 */
57 add_action('save_tutor_course', array($this, 'attach_product_with_course'), 10, 2);
58
59 /**
60 * Add course level to course settings
61 * @since v.1.4.1
62 */
63 add_action('tutor_course/settings_tab_content/after/general', array($this, 'add_course_level_to_settings'));
64
65 /**
66 * Enable Disable Course Details Page Feature
67 * @since v.1.4.8
68 */
69 $this->course_elements_enable_disable();
70
71 /**
72 * @since v.1.4.8
73 * Check if course starting, set meta if starting
74 */
75 add_action('tutor_lesson_load_before', array($this, 'tutor_lesson_load_before'));
76
77 /**
78 * @since v.1.4.9
79 * Filter product in shop page
80 */
81 $this->filter_product_in_shop_page();
82
83 /**
84 * Remove the course price if enrolled
85 * @since 1.5.8
86 */
87 add_filter('tutor_course_price', array($this, 'remove_price_if_enrolled'));
88
89 /**
90 * Remove course complete button if course completion is strict mode
91 * @since v.1.6.1
92 */
93 add_filter('tutor_course/single/complete_form', array($this, 'tutor_lms_hide_course_complete_btn'));
94 add_filter('get_gradebook_generate_form_html', array($this, 'get_generate_greadbook'));
95
96 /**
97 * Add social share content in header
98 * @since v.1.6.3
99 */
100 add_action('wp_head', array($this, 'social_share_content'));
101
102 /**
103 * Delete course data after deleted course
104 * @since v.1.6.6
105 */
106 add_action('deleted_post', array($this, 'delete_tutor_course_data'));
107 add_action('tutor/dashboard_course_builder_form_field_after', array($this, 'tutor_course_setting_metabox_frontend'));
108
109 /**
110 * Delete course data after deleted course
111 * @since v.1.8.2
112 */
113 add_action('before_delete_post', array($this, 'delete_associated_enrollment'));
114
115 /**
116 * Show only own uploads in media library if user is instructor
117 * @since v1.8.9
118 */
119 add_filter('posts_where', array($this, 'restrict_media' ) );
120
121 /**
122 * Restrict new enrol/purchase button if course member limit reached
123 * @since v1.9.0
124 */
125 add_filter('tutor_course_restrict_new_entry', array($this, 'restrict_new_student_entry'));
126 }
127
128 public function restrict_new_student_entry($content) {
129
130 if(!tutils()->is_course_fully_booked()) {
131 // No restriction if not fully booked
132 return $content;
133 }
134
135 return '<span class="tutor-course-booked-fully">
136 <img src="' . tutor()->url . '/assets/images/icon-warning-info.svg"/>
137 <span>' . __('Fully booked', 'tutor') . '</span>
138 </span>';
139 }
140
141 function restrict_media( $where ){
142
143 if( isset( $_POST['action'] ) && $_POST['action'] == 'query-attachments' && tutor_utils()->is_instructor()){
144 if(!tutor_utils()->has_user_role(array('administrator', 'editor'))) {
145 $where .= ' AND post_author=' . get_current_user_id();
146 }
147 }
148
149 return $where;
150 }
151
152 /**
153 * Registering metabox
154 */
155 public function register_meta_box(){
156 $coursePostType = tutor()->course_post_type;
157 $course_marketplace = tutor_utils()->get_option('enable_course_marketplace');
158 //add_meta_box( 'tutor-course-levels', __( 'Course Level', 'tutor' ), array($this, 'course_level_metabox'), $coursePostType );
159 add_meta_box( 'tutor-course-topics', __( 'Course Builder', 'tutor' ), array($this, 'course_meta_box'), $coursePostType );
160 add_meta_box( 'tutor-course-additional-data', __( 'Additional Data', 'tutor' ), array($this, 'course_additional_data_meta_box'), $coursePostType );
161 add_meta_box( 'tutor-course-videos', __( 'Video', 'tutor' ), array($this, 'video_metabox'), $coursePostType );
162 if ($course_marketplace) {
163 add_meta_box( 'tutor-instructors', __( 'Instructors', 'tutor' ), array( $this, 'instructors_metabox' ), $coursePostType );
164 }
165
166 /**
167 * Tutor course sidebar settings metabox
168 * @since v.1.7.0
169 */
170 add_meta_box( 'tutor-course-sidebar-settings', __( 'Tutor Settings', 'tutor' ), array($this, 'tutor_course_setting_metabox'), $coursePostType, 'side' );
171 }
172
173 public function course_meta_box($echo = true){
174 ob_start();
175 include tutor()->path.'views/metabox/course-topics.php';
176 $content = ob_get_clean();
177
178 if ($echo){
179 echo $content;
180 }else{
181 return $content;
182 }
183 }
184
185 public function course_additional_data_meta_box($echo = true){
186
187 ob_start();
188 include tutor()->path.'views/metabox/course-additional-data.php';
189 $content = ob_get_clean();
190
191 if ($echo){
192 echo $content;
193 }else{
194 return $content;
195 }
196 }
197
198 public function video_metabox($echo = true){
199 ob_start();
200 include tutor()->path.'views/metabox/video-metabox.php';
201 $content = ob_get_clean();
202
203 if ($echo){
204 echo $content;
205 }else{
206 return $content;
207 }
208 }
209
210 public function course_level_metabox($echo = true){
211 ob_start();
212 include tutor()->path.'views/metabox/course-level-metabox.php';
213 $content = ob_get_clean();
214
215 if ($echo){
216 echo $content;
217 }else{
218 return $content;
219 }
220 }
221
222 public function instructors_metabox($echo = true){
223 ob_start();
224 include tutor()->path . 'views/metabox/instructors-metabox.php';
225 $content = ob_get_clean();
226
227 if ($echo){
228 echo $content;
229 }else{
230 return $content;
231 }
232 }
233
234 /**
235 * Register metabox in course builder tutor
236 * @since v.1.3.4
237 */
238 public function register_meta_box_in_frontend(){
239 do_action('tutor_course_builder_metabox_before', get_the_ID());
240 course_builder_section_wrap($this->video_metabox($echo = false), __( 'Video', 'tutor' ) );
241 course_builder_section_wrap($this->course_meta_box($echo = false), __( 'Course Builder', 'tutor' ) );
242 course_builder_section_wrap($this->instructors_metabox($echo = false), __( 'Instructors', 'tutor' ) );
243 course_builder_section_wrap($this->course_additional_data_meta_box($echo = false), __( 'Additional Data', 'tutor' ) );
244 do_action('tutor_course_builder_metabox_after', get_the_ID());
245 }
246
247 /**
248 * @param $post_ID
249 *
250 * Insert Topic and attached it with Course
251 */
252 public function save_course_meta($post_ID, $post){
253 global $wpdb;
254
255 do_action( "tutor_save_course", $post_ID, $post);
256
257 /**
258 * Save course price type
259 */
260 $price_type = tutils()->array_get('tutor_course_price_type', $_POST);
261 if ($price_type){
262 update_post_meta($post_ID, '_tutor_course_price_type', $price_type);
263 }
264
265 //Course Duration
266 if ( ! empty($_POST['course_duration'])){
267 $video = tutils()->sanitize_array($_POST['course_duration']);
268 update_post_meta($post_ID, '_course_duration', $video);
269 }
270
271 if ( ! empty($_POST['course_level'])){
272 $course_level = sanitize_text_field($_POST['course_level']);
273 update_post_meta($post_ID, '_tutor_course_level', $course_level);
274 }
275
276 $additional_data_edit = tutils()->avalue_dot('_tutor_course_additional_data_edit', $_POST);
277 if ($additional_data_edit) {
278 if (!empty($_POST['course_benefits'])) {
279 $course_benefits = wp_kses_post($_POST['course_benefits']);
280 update_post_meta($post_ID, '_tutor_course_benefits', $course_benefits);
281 } else {
282 delete_post_meta($post_ID, '_tutor_course_benefits');
283 }
284
285 if (!empty($_POST['course_requirements'])) {
286 $requirements = wp_kses_post($_POST['course_requirements']);
287 update_post_meta($post_ID, '_tutor_course_requirements', $requirements);
288 } else {
289 delete_post_meta($post_ID, '_tutor_course_requirements');
290 }
291
292 if (!empty($_POST['course_target_audience'])) {
293 $target_audience = wp_kses_post($_POST['course_target_audience']);
294 update_post_meta($post_ID, '_tutor_course_target_audience', $target_audience);
295 } else {
296 delete_post_meta($post_ID, '_tutor_course_target_audience');
297 }
298
299 if (!empty($_POST['course_material_includes'])) {
300 $material_includes = wp_kses_post($_POST['course_material_includes']);
301 update_post_meta($post_ID, '_tutor_course_material_includes', $material_includes);
302 } else {
303 delete_post_meta($post_ID, '_tutor_course_material_includes');
304 }
305 }
306
307
308 /**
309 * Sorting Topics and lesson
310 */
311 if ( ! empty($_POST['tutor_topics_lessons_sorting'])){
312 $new_order = sanitize_text_field(stripslashes($_POST['tutor_topics_lessons_sorting']));
313 $order = json_decode($new_order, true);
314
315 if (is_array($order) && count($order)){
316 $i = 0;
317 foreach ($order as $topic ){
318 $i++;
319 $wpdb->update(
320 $wpdb->posts,
321 array('menu_order' => $i),
322 array('ID' => $topic['topic_id'])
323 );
324
325 /**
326 * Removing All lesson with topic
327 */
328
329 $wpdb->update(
330 $wpdb->posts,
331 array('post_parent' => 0),
332 array('post_parent' => $topic['topic_id'])
333 );
334
335 /**
336 * Lesson Attaching with topic ID
337 * sorting lesson
338 */
339 if (isset($topic['lesson_ids'])){
340 $lesson_ids = $topic['lesson_ids'];
341 }else{
342 $lesson_ids = array();
343 }
344 if (count($lesson_ids)){
345 foreach ($lesson_ids as $lesson_key => $lesson_id ){
346 $wpdb->update(
347 $wpdb->posts,
348 array('post_parent' => $topic['topic_id'], 'menu_order' => $lesson_key),
349 array('ID' => $lesson_id)
350 );
351 }
352 }
353 }
354 }
355 }
356
357 if ($additional_data_edit) {
358 if ( ! empty($_POST['video']['source'])) { //Video
359 $video = tutor_utils()->array_get('video', $_POST);
360 update_post_meta($post_ID, '_video', $video);
361 }else{
362 delete_post_meta($post_ID, '_video');
363 }
364 }
365
366 /**
367 * Adding author to instructor automatically
368 */
369
370 $author_id = $post->post_author;
371 $attached = (int) $wpdb->get_var($wpdb->prepare(
372 "SELECT COUNT(umeta_id) FROM {$wpdb->usermeta}
373 WHERE user_id = %d AND meta_key = '_tutor_instructor_course_id' AND meta_value = %d ", $author_id, $post_ID));
374
375 if ( ! $attached){
376 add_user_meta($author_id, '_tutor_instructor_course_id', $post_ID);
377 }
378
379 /**
380 * Disable question and answer for this course
381 * @since 1.7.0
382 */
383 if ($additional_data_edit) {
384 foreach($this->additional_meta as $key){
385 update_post_meta($post_ID, $key, (isset($_POST[$key]) ? 'yes' : 'no'));
386 }
387 }
388
389 do_action( "tutor_save_course_after", $post_ID, $post);
390 }
391
392 /**
393 * Tutor add course topic
394 */
395 public function tutor_add_course_topic(){
396 tutils()->checking_nonce();
397
398 if (empty($_POST['topic_title']) ) {
399 wp_send_json_error();
400 }
401 $course_id = (int) tutor_utils()->avalue_dot('tutor_topic_course_ID', $_POST);
402 $next_topic_order_id = tutor_utils()->get_next_topic_order_id($course_id);
403
404 if(!tutils()->can_user_manage('course', $course_id)) {
405 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
406 }
407
408 $topic_title = sanitize_text_field( $_POST['topic_title'] );
409 $topic_summery = wp_kses_post( $_POST['topic_summery'] );
410
411 $post_arr = array(
412 'post_type' => 'topics',
413 'post_title' => $topic_title,
414 'post_content' => $topic_summery,
415 'post_status' => 'publish',
416 'post_author' => get_current_user_id(),
417 'post_parent' => $course_id,
418 'menu_order' => $next_topic_order_id,
419 );
420 $current_topic_id = wp_insert_post( $post_arr );
421
422 ob_start();
423 include tutor()->path.'views/metabox/course-contents.php';
424 $course_contents = ob_get_clean();
425
426 wp_send_json_success(array('course_contents' => $course_contents));
427 }
428
429 /**
430 * Update the topic
431 */
432 public function tutor_update_topic(){
433 tutils()->checking_nonce();
434
435 $topic_id = (int) sanitize_text_field($_POST['topic_id']);
436 $topic_title = sanitize_text_field($_POST['topic_title']);
437 $topic_summery = wp_kses_post($_POST['topic_summery']);
438
439 if(!tutils()->can_user_manage('topic', $topic_id)) {
440 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
441 }
442
443 $topic_attr = array(
444 'ID' => $topic_id,
445 'post_title' => $topic_title,
446 'post_content' => $topic_summery,
447 );
448 wp_update_post( $topic_attr );
449
450 wp_send_json_success(array('msg' => __('Topic has been updated', 'tutor') ));
451 }
452
453
454 /**
455 * @param $columns
456 *
457 * @return mixed
458 *
459 * Add Lesson column
460 */
461 public function add_column($columns){
462 $date_col = $columns['date'];
463 unset($columns['date']);
464 $columns['lessons'] = __('Lessons', 'tutor');
465 $columns['students'] = __('Students', 'tutor');
466 $columns['price'] = __('Price', 'tutor');
467 $columns['date'] = $date_col;
468
469 return $columns;
470 }
471
472 /**
473 * @param $column
474 * @param $post_id
475 *
476 */
477 public function custom_lesson_column($column, $post_id ){
478 if ($column === 'lessons'){
479 echo tutor_utils()->get_lesson_count_by_course($post_id);
480 }
481
482 if ($column === 'students'){
483 echo tutor_utils()->count_enrolled_users_by_course($post_id);
484 }
485
486 if ($column === 'price'){
487 $price = tutor_utils()->get_course_price($post_id);
488 if ($price){
489 $monetize_by = tutils()->get_option('monetize_by');
490 if (function_exists('wc_price') && $monetize_by === 'wc'){
491 echo '<span class="tutor-label-success">'.wc_price($price).'</span>';
492 }else{
493 echo '<span class="tutor-label-success">'.$price.'</span>';
494 }
495 }else{
496 echo apply_filters('tutor-loop-default-price', 'free');
497 }
498 }
499 }
500
501
502 public function tutor_delete_topic(){
503
504 tutils()->checking_nonce('get');
505
506 !isset($_GET['topic_id']) ? exit() : 0;
507
508 global $wpdb;
509
510 $topic_id = (int) sanitize_text_field($_GET['topic_id']);
511 $wpdb->update(
512 $wpdb->posts,
513 array('post_parent' => 0),
514 array('post_parent' => $topic_id)
515 );
516
517 $wpdb->delete(
518 $wpdb->postmeta,
519 array('post_id' => $topic_id)
520 );
521
522 wp_delete_post($topic_id);
523 wp_safe_redirect(wp_get_referer());
524 }
525
526 public function tutor_delete_announcement(){
527 tutor_utils()->checking_nonce('get');
528
529 $announcement_id = (int) sanitize_text_field($_GET['topic_id']);
530
531 wp_delete_post($announcement_id);
532 wp_safe_redirect(wp_get_referer());
533 }
534
535 public function enroll_now(){
536
537 //Checking if action comes from Enroll form
538 if (tutor_utils()->array_get('tutor_course_action', $_POST) !== '_tutor_course_enroll_now' || ! isset($_POST['tutor_course_id']) ){
539 return;
540 }
541 //Checking Nonce
542 tutor_utils()->checking_nonce();
543
544 $user_id = get_current_user_id();
545 if ( ! $user_id){
546 exit(__('Please Sign In first', 'tutor'));
547 }
548
549 $course_id = (int) sanitize_text_field($_POST['tutor_course_id']);
550 $user_id = get_current_user_id();
551
552 /**
553 * TODO: need to check purchase information
554 */
555
556 $is_purchasable = tutor_utils()->is_course_purchasable($course_id);
557
558 /**
559 * If is is not purchasable, it's free, and enroll right now
560 *
561 * if purchasable, then process purchase.
562 *
563 * @since: v.1.0.0
564 */
565 if ($is_purchasable){
566 //process purchase
567
568 }else{
569 //Free enroll
570 tutor_utils()->do_enroll($course_id);
571 }
572
573 $referer_url = wp_get_referer();
574 wp_redirect($referer_url);
575 }
576
577 /**
578 *
579 * Mark complete completed
580 *
581 * @since v.1.0.0
582 */
583 public function mark_course_complete(){
584 if ( ! isset($_POST['tutor_action']) || $_POST['tutor_action'] !== 'tutor_complete_course' ){
585 return;
586 }
587 //Checking nonce
588 tutor_utils()->checking_nonce();
589
590 $user_id = get_current_user_id();
591
592 //TODO: need to show view if not signed_in
593 if ( ! $user_id){
594 die(__('Please Sign-In', 'tutor'));
595 }
596
597 $course_id = (int) sanitize_text_field($_POST['course_id']);
598
599 do_action('tutor_course_complete_before', $course_id);
600 /**
601 * Marking course completed at Comment
602 */
603
604 global $wpdb;
605
606 $date = date("Y-m-d H:i:s", tutor_time());
607
608 //Making sure that, hash is unique
609 do{
610 $hash = substr(md5(wp_generate_password(32).$date.$course_id.$user_id), 0, 16);
611 $hasHash = (int) $wpdb->get_var($wpdb->prepare(
612 "SELECT COUNT(comment_ID) from {$wpdb->comments}
613 WHERE comment_agent = 'TutorLMSPlugin' AND comment_type = 'course_completed' AND comment_content = %s ", $hash));
614
615 }while($hasHash > 0);
616
617 $data = array(
618 'comment_post_ID' => $course_id,
619 'comment_author' => $user_id,
620 'comment_date' => $date,
621 'comment_date_gmt' => get_gmt_from_date($date),
622 'comment_content' => $hash, //Identification Hash
623 'comment_approved' => 'approved',
624 'comment_agent' => 'TutorLMSPlugin',
625 'comment_type' => 'course_completed',
626 'user_id' => $user_id,
627 );
628
629 $wpdb->insert($wpdb->comments, $data);
630
631 do_action('tutor_course_complete_after', $course_id, $user_id);
632
633 wp_redirect(get_the_permalink($course_id));
634 }
635
636
637 public function tutor_load_instructors_modal(){
638 tutils()->checking_nonce();
639
640 global $wpdb;
641
642 $course_id = (int) sanitize_text_field($_POST['course_id']);
643 $search_terms = sanitize_text_field(tutor_utils()->avalue_dot('search_terms', $_POST));
644
645 if(!tutils()->can_user_manage('course', $course_id)) {
646 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
647 }
648
649 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
650 $instructors = array();
651
652 $not_in_sql = apply_filters('tutor_instructor_query_when_exists', " AND ID <1 ");
653
654 if ($saved_instructors){
655 $saved_instructors_ids = wp_list_pluck($saved_instructors, 'ID');
656 $instructor_not_in_ids = implode(',', $saved_instructors_ids);
657 $not_in_sql .= "AND ID NOT IN($instructor_not_in_ids) ";
658 }
659
660 $search_sql = '';
661 if ($search_terms){
662 $search_sql = "AND (user_login like '%{$search_terms}%' or user_nicename like '%{$search_terms}%' or display_name like '%{$search_terms}%') ";
663 }
664
665 $instructors = $wpdb->get_results("select ID, display_name from {$wpdb->users}
666 INNER JOIN {$wpdb->usermeta} ON ID = user_id AND meta_key = '_tutor_instructor_status' AND meta_value = 'approved'
667 WHERE 1=1 {$not_in_sql} {$search_sql} limit 10 ");
668
669 $output = '';
670 if (is_array($instructors) && count($instructors)){
671 $instructor_output = '';
672 foreach ($instructors as $instructor){
673 $instructor_output .= "<p><label><input type='radio' name='tutor_instructor_ids[]' value='{$instructor->ID}' > {$instructor->display_name} </label></p>";
674 }
675
676 $output .= apply_filters('tutor_course_instructors_html', $instructor_output, $instructors);
677
678 }else{
679 $output .= __('<p>No instructor available or you have already added maximum instructors</p>', 'tutor');
680 }
681
682
683 if ( ! defined('TUTOR_MT_VERSION')){
684 $output .= '<p class="tutor-notice-warning" style="margin-top: 50px; font-size: 14px;">'. sprintf( __('To add unlimited multiple instructors in your course, get %sTutor LMS Pro%s', 'tutor'), '<a href="https://www.themeum.com/product/tutor-lms" target="_blank">', "</a>" ) .'</p>';
685 }
686
687 wp_send_json_success(array('output' => $output));
688 }
689
690 public function tutor_add_instructors_to_course(){
691 tutils()->checking_nonce();
692
693 $course_id = (int) sanitize_text_field($_POST['course_id']);
694 $instructor_ids = tutor_utils()->avalue_dot('tutor_instructor_ids', $_POST);
695
696 if(!tutils()->can_user_manage('course', $course_id)) {
697 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
698 }
699
700 if (is_array($instructor_ids) && count($instructor_ids)){
701 foreach ($instructor_ids as $instructor_id){
702 add_user_meta($instructor_id, '_tutor_instructor_course_id', $course_id);
703 }
704 }
705
706 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
707 $output = '';
708
709 if ($saved_instructors){
710 foreach ($saved_instructors as $t){
711
712 $output .= '<div id="added-instructor-id-'.$t->ID.'" class="added-instructor-item added-instructor-item-'.$t->ID.'" data-instructor-id="'.$t->ID.'">
713 <span class="instructor-icon">'.get_avatar($t->ID, 30).'</span>
714 <span class="instructor-name"> '.$t->display_name.' </span>
715 <span class="instructor-control">
716 <a href="javascript:;" class="tutor-instructor-delete-btn"><i class="tutor-icon-line-cross"></i></a>
717 </span>
718 </div>';
719 }
720 }
721
722 wp_send_json_success(array('output' => $output));
723 }
724
725 public function detach_instructor_from_course(){
726 tutils()->checking_nonce();
727
728 global $wpdb;
729
730 $instructor_id = (int) sanitize_text_field($_POST['instructor_id']);
731 $course_id = (int) sanitize_text_field($_POST['course_id']);
732
733 if(!tutils()->can_user_manage('course', $course_id)) {
734 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
735 }
736
737 $wpdb->delete($wpdb->usermeta, array('user_id' => $instructor_id, 'meta_key' => '_tutor_instructor_course_id', 'meta_value' => $course_id) );
738 wp_send_json_success();
739 }
740
741 public function tutor_delete_dashboard_course(){
742 tutils()->checking_nonce();
743
744 $course_id = intval(sanitize_text_field($_POST['course_id']));
745
746 if(!tutils()->can_user_manage('course', $course_id)) {
747 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
748 }
749
750 wp_trash_post($course_id);
751 wp_send_json_success(['element'=>'course']);
752 }
753
754
755 public function tutor_add_gutenberg_author($data , $postarr){
756 global $wpdb;
757
758 $courses_post_type = tutor()->course_post_type;
759 $post_type = tutils()->array_get('post_type', $postarr);
760
761 if ($courses_post_type === $post_type){
762 $post_ID = (int) tutor_utils()->avalue_dot('ID', $postarr);
763 $post_author = (int) $wpdb->get_var($wpdb->prepare("SELECT post_author FROM {$wpdb->posts} WHERE ID = %d ", $post_ID));
764
765 if ($post_author > 0){
766 $data['post_author'] = $post_author;
767 }else{
768 $data['post_author'] = get_current_user_id();
769 }
770 }
771
772 return $data;
773 }
774
775
776 /**
777 * @param $post_ID
778 * @param $postData
779 *
780 * Attach product during save course from the frontend course dashboard.
781 *
782 * @return string
783 *
784 * @since v.1.3.4
785 */
786 public function attach_product_with_course($post_ID, $postData){
787 $attached_product_id = tutor_utils()->get_course_product_id($post_ID);
788 $course_price = sanitize_text_field(tutor_utils()->array_get('course_price', $_POST));
789
790 if ( ! $course_price){
791 return;
792 }
793
794 $monetize_by = tutor_utils()->get_option('monetize_by');
795 $course = get_post($post_ID);
796
797 if ($monetize_by === 'wc'){
798
799 $is_update = false;
800 if ($attached_product_id){
801 $wc_product = get_post_meta($attached_product_id, '_product_version', true);
802 if ($wc_product){
803 $is_update = true;
804 }
805 }
806
807 if ($is_update) {
808 $productObj = wc_get_product($attached_product_id);
809 $productObj->set_price($course_price); // set product price
810 $productObj->set_regular_price($course_price); // set product regular price
811 $product_id = $productObj->save();
812 if($productObj->is_type('subscription')) {
813 update_post_meta( $attached_product_id, '_subscription_price', $course_price );
814 }
815 } else {
816 $productObj = new \WC_Product();
817 $productObj->set_name($course->post_title);
818 $productObj->set_status('publish');
819 $productObj->set_price($course_price); // set product price
820 $productObj->set_regular_price($course_price); // set product regular price
821
822 $product_id = $productObj->save();
823 if ($product_id) {
824 update_post_meta( $post_ID, '_tutor_course_product_id', $product_id );
825 //Mark product for woocommerce
826 update_post_meta( $product_id, '_virtual', 'yes' );
827 update_post_meta( $product_id, '_tutor_product', 'yes' );
828
829 $coursePostThumbnail = get_post_meta( $post_ID, '_thumbnail_id', true );
830 if ( $coursePostThumbnail ) {
831 set_post_thumbnail( $product_id, $coursePostThumbnail );
832 }
833 }
834 }
835
836 }elseif ($monetize_by === 'edd'){
837
838 $is_update = false;
839
840 if ($attached_product_id){
841 $edd_price = get_post_meta($attached_product_id, 'edd_price', true);
842 if ($edd_price){
843 $is_update = true;
844 }
845 }
846
847 if ($is_update){
848 //Update the product
849 update_post_meta( $attached_product_id, 'edd_price', $course_price );
850 }else{
851 //Create new product
852
853 $post_arr = array(
854 'post_type' => 'download',
855 'post_title' => $course->post_title,
856 'post_status' => 'publish',
857 'post_author' => get_current_user_id(),
858 );
859 $download_id = wp_insert_post( $post_arr );
860 if ($download_id ) {
861 //edd_price
862 update_post_meta( $download_id, 'edd_price', $course_price );
863
864 update_post_meta( $post_ID, '_tutor_course_product_id', $download_id );
865 //Mark product for EDD
866 update_post_meta( $download_id, '_tutor_product', 'yes' );
867
868 $coursePostThumbnail = get_post_meta( $post_ID, '_thumbnail_id', true );
869 if ( $coursePostThumbnail ) {
870 set_post_thumbnail( $download_id, $coursePostThumbnail );
871 }
872
873 }
874
875 }
876
877
878 }
879
880 }
881
882
883 /**
884 * Add Course level to course settings
885 * @since v.1.4.1
886 */
887 public function add_course_level_to_settings(){
888 include tutor()->path.'views/metabox/course-level-metabox.php';
889 }
890
891 /**
892 * Check if course starting
893 *
894 * @since v.1.4.8
895 */
896 public function tutor_lesson_load_before(){
897 $course_id = tutils()->get_course_id_by_content(get_the_ID());
898 $completed_lessons = tutor_utils()->get_completed_lesson_count_by_course($course_id);
899 if (is_user_logged_in()){
900 $is_course_started = get_post_meta($course_id, '_tutor_course_started', true);
901 if ( ! $completed_lessons && ! $is_course_started){
902 update_post_meta($course_id, '_tutor_course_started', tutor_time());
903 do_action('tutor/course/started', $course_id);
904 }
905 }
906 }
907
908 /**
909 * Add Course level to course settings
910 * @since v.1.4.8
911 */
912 public function course_elements_enable_disable(){
913 add_filter('tutor_course/single/completing-progress-bar', array($this, 'enable_disable_course_progress_bar') );
914 add_filter('tutor_course/single/material_includes', array($this, 'enable_disable_material_includes') );
915 add_filter('tutor_course/single/content', array($this, 'enable_disable_course_content') );
916 add_filter('tutor_course/single/benefits_html', array($this, 'enable_disable_course_benefits') );
917 add_filter('tutor_course/single/requirements_html', array($this, 'enable_disable_course_requirements') );
918 add_filter('tutor_course/single/audience_html', array($this, 'enable_disable_course_target_audience') );
919 add_filter('tutor_course/single/enrolled/nav_items', array($this, 'enable_disable_course_nav_items') );
920 }
921
922 /**
923 * Enable disable course progress bar
924 * @since v.1.4.8
925 */
926 public function enable_disable_course_progress_bar($html){
927 $disable_option = (bool) get_tutor_option('disable_course_progress_bar');
928 if($disable_option){
929 return '';
930 }
931 return $html;
932 }
933
934 /**
935 * Enable disable material includes
936 * @since v.1.4.8
937 */
938 public function enable_disable_material_includes($html){
939 $disable_option = (bool) get_tutor_option('disable_course_material');
940 if($disable_option){
941 return '';
942 }
943 return $html;
944 }
945
946 /**
947 * Enable disable course content
948 * @since v.1.4.8
949 */
950 public function enable_disable_course_content($html){
951 $disable_option = (bool) get_tutor_option('disable_course_description');
952 if($disable_option){
953 return '';
954 }
955 return $html;
956 }
957
958 /**
959 * Enable disable course benefits
960 * @since v.1.4.8
961 */
962 public function enable_disable_course_benefits($html){
963 $disable_option = (bool) get_tutor_option('disable_course_benefits');
964 if($disable_option){
965 return '';
966 }
967 return $html;
968 }
969
970 /**
971 * Enable disable course requirements
972 * @since v.1.4.8
973 */
974 public function enable_disable_course_requirements($html){
975 $disable_option = (bool) get_tutor_option('disable_course_requirements');
976 if($disable_option){
977 return '';
978 }
979 return $html;
980 }
981
982 /**
983 * Enable disable course target audience
984 * @since v.1.4.8
985 */
986 public function enable_disable_course_target_audience($html){
987 $disable_option = (bool) get_tutor_option('disable_course_target_audience');
988 if($disable_option){
989 return '';
990 }
991 return $html;
992 }
993
994 /**
995 * Enable disable course nav items
996 * @since v.1.4.8
997 */
998 public function enable_disable_course_nav_items($items){
999 global $wp_query, $post;
1000 $enable_q_and_a_on_course = (bool) get_tutor_option('enable_q_and_a_on_course');
1001 $disable_course_announcements = (bool) get_tutor_option('disable_course_announcements');
1002
1003 $disable_qa_for_this_course = ($wp_query->is_single && !empty($post)) ? get_post_meta($post->ID, '_tutor_disable_qa', true) : '';
1004
1005 if(!$enable_q_and_a_on_course || $disable_qa_for_this_course == 'yes') {
1006 if(tutils()->array_get('questions', $items)) {
1007 unset($items['questions']);
1008 }
1009 }
1010 if($disable_course_announcements){
1011 if(tutils()->array_get('announcements', $items)) {
1012 unset($items['announcements']);
1013 }
1014 }
1015 return $items;
1016 }
1017
1018 /**
1019 * Filter product in shop page
1020 * @since v.1.4.9
1021 */
1022 public function filter_product_in_shop_page(){
1023 $hide_course_from_shop_page = (bool) get_tutor_option('hide_course_from_shop_page');
1024 if(!$hide_course_from_shop_page){
1025 return;
1026 }
1027 add_action('woocommerce_product_query', array($this, 'filter_woocommerce_product_query'));
1028 add_filter('edd_downloads_query', array($this, 'filter_edd_downloads_query'), 10, 2);
1029 add_action('pre_get_posts', array($this, 'filter_archive_meta_query'), 1);
1030 }
1031
1032 /**
1033 * Tutor product meta query
1034 * @since v.1.4.9
1035 */
1036 public function tutor_product_meta_query(){
1037 $meta_query = array(
1038 'key' => '_tutor_product',
1039 'compare' => 'NOT EXISTS'
1040 );
1041 return $meta_query;
1042 }
1043
1044 /**
1045 * Filter product in woocommerce shop page
1046 * @since v.1.4.9
1047 */
1048 public function filter_woocommerce_product_query($wp_query){
1049 $wp_query->set('meta_query', array($this->tutor_product_meta_query()));
1050 return $wp_query;
1051 }
1052
1053 /**
1054 * Filter product in edd downloads shortcode page
1055 * @since v.1.4.9
1056 */
1057 public function filter_edd_downloads_query($query){
1058 $query['meta_query'][] = $this->tutor_product_meta_query();
1059 return $query;
1060 }
1061
1062 /**
1063 * Filter product in edd downloads archive page
1064 * @since v.1.4.9
1065 */
1066 public function filter_archive_meta_query($wp_query){
1067 if(!is_admin() && $wp_query->is_archive && $wp_query->get('post_type') === 'download'){
1068 $wp_query->set('meta_query', array($this->tutor_product_meta_query()));
1069 }
1070 return $wp_query;
1071 }
1072
1073 /**
1074 * @param $html
1075 * @return string
1076 *
1077 * Removed course price if already enrolled at single course
1078 *
1079 * @since v.1.5.8
1080 */
1081 public function remove_price_if_enrolled($html){
1082 $should_removed = apply_filters('should_remove_price_if_enrolled', true);
1083
1084 if ($should_removed){
1085 $course_id = get_the_ID();
1086 $enrolled = tutils()->is_enrolled($course_id);
1087 if ($enrolled){
1088 $html = '';
1089 }
1090 }
1091 return $html;
1092 }
1093
1094 /**
1095 * @param $html
1096 * @return string
1097 *
1098 * Check if all lessons and quizzes done before mark course complete.
1099 */
1100 function tutor_lms_hide_course_complete_btn($html){
1101
1102 $completion_mode = tutils()->get_option('course_completion_process');
1103 if ($completion_mode !== 'strict'){
1104 return $html;
1105 }
1106
1107 $completed_lesson = tutils()->get_completed_lesson_count_by_course();
1108 $lesson_count = tutils()->get_lesson_count_by_course();
1109
1110 if ($completed_lesson < $lesson_count){
1111 return '<p class="suggestion-before-course-complete">'.__('complete all lessons to mark this course as complete', 'tutor').'</p>';
1112 }
1113
1114 $quizzes = array();
1115
1116 $course_contents = tutils()->get_course_contents_by_id();
1117 if (tutils()->count($course_contents)){
1118 foreach ($course_contents as $content){
1119 if ($content->post_type === 'tutor_quiz'){
1120 $quizzes[] = $content;
1121 }
1122 }
1123 }
1124
1125 $is_pass = true;
1126 $required_quiz_pass = 0;
1127
1128 if (tutils()->count($quizzes)){
1129 foreach ($quizzes as $quiz){
1130
1131 $attempt = tutils()->get_quiz_attempt($quiz->ID);
1132 if ($attempt) {
1133 $passing_grade = tutor_utils()->get_quiz_option($quiz->ID, 'passing_grade', 0);
1134 $earned_percentage = $attempt->earned_marks > 0 ? (number_format(($attempt->earned_marks * 100) / $attempt->total_marks)) : 0;
1135
1136 if ($earned_percentage < $passing_grade) {
1137 $required_quiz_pass++;
1138 $is_pass = false;
1139 }
1140 }else{
1141 $required_quiz_pass++;
1142 $is_pass = false;
1143 }
1144 }
1145 }
1146
1147 if ( ! $is_pass){
1148 return '<p class="suggestion-before-course-complete">'.sprintf(__('You have to pass %s quizzes to complete this course.', 'tutor'), $required_quiz_pass).'</p>';
1149 }
1150
1151 return $html;
1152 }
1153
1154 public function get_generate_greadbook($html){
1155 if ( ! tutils()->is_completed_course()){
1156 return '';
1157 }
1158 return $html;
1159 }
1160
1161 /**
1162 * Add social share content in header
1163 * @since v.1.6.3
1164 */
1165 public function social_share_content(){
1166 global $wp_query, $post;
1167 if ($wp_query->is_single && ! empty($wp_query->query_vars['post_type']) && $wp_query->query_vars['post_type'] === $this->course_post_type) { ?>
1168 <!--Facebook-->
1169 <meta property="og:type" content="website"/>
1170 <meta property="og:image" content="<?php echo get_tutor_course_thumbnail_src(); ?>" />
1171 <meta property="og:description" content="<?php echo esc_html($post->post_content); ?>" />
1172 <!--Twitter-->
1173 <meta name="twitter:image" content="<?php echo get_tutor_course_thumbnail_src(); ?>">
1174 <meta name="twitter:description" content="<?php echo esc_html($post->post_content); ?>">
1175 <!--Google+-->
1176 <meta itemprop="image" content="<?php echo get_tutor_course_thumbnail_src(); ?>">
1177 <meta itemprop="description" content="<?php echo esc_html($post->post_content); ?>"> <?php
1178 }
1179 }
1180
1181 /**
1182 * Get posts by type and parent
1183 * @since v.1.6.6
1184 */
1185 public function tutor_get_post_ids($post_type, $post_parent) {
1186 $args = array(
1187 'fields' => 'ids',
1188 'post_type' => $post_type,
1189 'post_parent' => $post_parent,
1190 'post_status' => 'any',
1191 'posts_per_page' => -1,
1192 );
1193 return get_posts($args);
1194 }
1195
1196 /**
1197 * Delete course data when permanently deleting a course.
1198 * @since v.1.6.6
1199 */
1200 function delete_tutor_course_data( $post_id ) {
1201 $course_post_type = tutor()->course_post_type;
1202 $lesson_post_type = tutor()->lesson_post_type;
1203
1204 if (get_post_type($post_id) == $course_post_type) {
1205 global $wpdb;
1206 $topic_ids = $this->tutor_get_post_ids('topics', $post_id);
1207 if ( !empty($topic_ids) ) {
1208 foreach ($topic_ids as $topic_id) {
1209 $content_post_type = apply_filters('tutor_course_contents_post_types', array($lesson_post_type, 'tutor_quiz'));
1210 $topic_content_ids = $this->tutor_get_post_ids($content_post_type, $topic_id);
1211
1212 foreach ($topic_content_ids as $content_id) {
1213 if( get_post_type($content_id) == 'tutor_quiz') {
1214 $wpdb->delete($wpdb->prefix.'tutor_quiz_attempts', array('quiz_id' => $content_id));
1215 $wpdb->delete($wpdb->prefix.'tutor_quiz_attempt_answers', array('quiz_id' => $content_id));
1216
1217 $questions_ids = $wpdb->get_col($wpdb->prepare("SELECT question_id FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = %d ", $content_id));
1218 if (is_array($questions_ids) && count($questions_ids)){
1219 $in_question_ids = "'".implode("','", $questions_ids)."'";
1220 $wpdb->query("DELETE FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id IN({$in_question_ids}) ");
1221 }
1222 $wpdb->delete($wpdb->prefix.'tutor_quiz_questions', array('quiz_id' => $content_id));
1223 }
1224 wp_delete_post($content_id, true);
1225 }
1226 wp_delete_post($topic_id, true);
1227 }
1228 }
1229 $child_post_ids = $this->tutor_get_post_ids(array('tutor_announcements', 'tutor_enrolled'), $post_id);
1230 if ( !empty($child_post_ids) ) {
1231 foreach ($child_post_ids as $child_post_id) {
1232 wp_delete_post($child_post_id, true);
1233 }
1234 }
1235 }
1236 }
1237
1238 /**
1239 * tutor course setting metabox
1240 * @since v.1.7.0
1241 */
1242 function tutor_course_setting_metabox( $post ) {
1243
1244 $disable_qa = $this->additional_meta[0];
1245 $is_public = $this->additional_meta[1];
1246
1247 $disable_qa_checked = get_post_meta($post->ID, $disable_qa, true)=='yes' ? 'checked="checked"' : '';
1248 $is_public_checked = get_post_meta($post->ID, $is_public, true)=='yes' ? 'checked="checked"' : '';
1249
1250 do_action('tutor_before_course_sidebar_settings_metabox', $post);
1251 ?>
1252 <div class="tutor-course-sidebar-settings-item" id="_tutor_is_course_public_meta_checkbox" style="display:none">
1253 <label for="<?php echo $is_public; ?>">
1254 <input id="<?php echo $is_public; ?>" type="checkbox" name="<?php echo $is_public; ?>" value="yes" <?php echo $is_public_checked; ?> />
1255 <?php _e('Make This Course Public', 'tutor'); ?>
1256 <small style="display:block;padding-left:24px">
1257 <?php _e('No enrollment required.', 'tutor'); ?>
1258 </small>
1259 </label>
1260 </div>
1261 <div class="tutor-course-sidebar-settings-item">
1262 <label for="<?php echo $disable_qa; ?>">
1263 <input type="hidden" name="_tutor_course_additional_data_edit" value="true" />
1264 <input id="<?php echo $disable_qa; ?>" type="checkbox" name="<?php echo $disable_qa; ?>" value="yes" <?php echo $disable_qa_checked; ?> />
1265 <?php _e('Disable Q&A', 'tutor'); ?>
1266 </label>
1267 </div>
1268 <?php
1269 do_action('tutor_after_course_sidebar_settings_metabox', $post);
1270 }
1271
1272 function tutor_course_setting_metabox_frontend( $post ){
1273 ?>
1274 <div class="tutor-course-builder-section tutor-course-builder-info">
1275 <div class="tutor-course-builder-section-title">
1276 <h3><i class="tutor-icon-down"></i><span><?php esc_html_e('Tutor Settings', 'tutor'); ?></span></h3>
1277 </div>
1278 <div class="tutor-course-builder-section-content">
1279 <div class="tutor-frontend-builder-item-scope">
1280 <div class="tutor-form-group">
1281 <?php $this->tutor_course_setting_metabox($post); ?>
1282 </div>
1283 </div>
1284 </div>
1285 </div>
1286 <?php
1287 }
1288
1289 /**
1290 * Delete associated enrollment
1291 * @since v.1.8.2
1292 */
1293 public function delete_associated_enrollment($post_id) {
1294 global $wpdb;
1295
1296 $enroll_id = $wpdb->get_var( $wpdb->prepare(
1297 "SELECT
1298 post_id
1299 FROM
1300 {$wpdb->postmeta}
1301 WHERE
1302 meta_key='_tutor_enrolled_by_order_id'
1303 AND meta_value = %d
1304 ",
1305 $post_id
1306 ) );
1307
1308 if(is_numeric($enroll_id) && $enroll_id>0) {
1309
1310 $course_id = get_post_field('post_parent', $enroll_id);
1311 $user_id = get_post_field('post_author', $enroll_id);
1312
1313 tutils()->cancel_course_enrol($course_id, $user_id);
1314 }
1315 }
1316 }