PluginProbe
Tutor LMS – eLearning and online course solution / 1.9.4
Tutor LMS – eLearning and online course solution v1.9.4
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 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 All 191 releases
← All changes | classes/Course.php +881 -88 1.0.51.9.4 View file →
@@ -4,11 +4,17 @@
4 4 if ( ! defined( 'ABSPATH' ) )
5 5 exit;
6 6
7 7 class Course extends Tutor_Base {
8 +
9 + private $additional_meta=array(
10 + '_tutor_disable_qa',
11 + '_tutor_is_public_course'
12 + );
13 +
8 14 public function __construct() {
9 15 parent::__construct();
10 -
16 +
11 17 add_action( 'add_meta_boxes', array($this, 'register_meta_box') );
12 18 add_action('save_post_'.$this->course_post_type, array($this, 'save_course_meta'), 10, 2);
13 19 add_action('wp_ajax_tutor_add_course_topic', array($this, 'tutor_add_course_topic'));
14 20 add_action('wp_ajax_tutor_update_topic', array($this, 'tutor_update_topic'));
@@ -27,40 +33,219 @@
27 33 //Modal Perform
28 34 add_action('wp_ajax_tutor_load_instructors_modal', array($this, 'tutor_load_instructors_modal'));
29 35 add_action('wp_ajax_tutor_add_instructors_to_course', array($this, 'tutor_add_instructors_to_course'));
30 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'));
31 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 +
32 152 /**
33 153 * Registering metabox
34 154 */
35 155 public function register_meta_box(){
36 156 $coursePostType = tutor()->course_post_type;
37 -
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 );
38 159 add_meta_box( 'tutor-course-topics', __( 'Course Builder', 'tutor' ), array($this, 'course_meta_box'), $coursePostType );
39 160 add_meta_box( 'tutor-course-additional-data', __( 'Additional Data', 'tutor' ), array($this, 'course_additional_data_meta_box'), $coursePostType );
40 161 add_meta_box( 'tutor-course-videos', __( 'Video', 'tutor' ), array($this, 'video_metabox'), $coursePostType );
41 - add_meta_box( 'tutor-instructors', __( 'Instructors', 'tutor' ), array($this, 'instructors_metabox'), $coursePostType );
42 - add_meta_box( 'tutor-announcements', __( 'Announcements', 'tutor' ), array($this, 'announcements_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' );
43 171 }
44 - public function course_meta_box(){
172 +
173 + public function course_meta_box($echo = true){
174 + ob_start();
45 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 + }
46 183 }
47 - public function course_additional_data_meta_box(){
184 +
185 + public function course_additional_data_meta_box($echo = true){
186 +
187 + ob_start();
48 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 + }
49 196 }
50 - public function video_metabox(){
197 +
198 + public function video_metabox($echo = true){
199 + ob_start();
51 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 + }
52 208 }
53 209
54 - public function announcements_metabox(){
55 - include tutor()->path.'views/metabox/announcements-metabox.php';
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 + }
56 220 }
57 221
58 - public function instructors_metabox(){
59 - include tutor()->path.'views/metabox/instructors-metabox.php';
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 + }
60 232 }
61 233
62 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 + /**
63 248 * @param $post_ID
64 249 *
65 250 * Insert Topic and attached it with Course
66 251 */
@@ -65,29 +250,22 @@
65 250 * Insert Topic and attached it with Course
66 251 */
67 252 public function save_course_meta($post_ID, $post){
68 253 global $wpdb;
254 +
255 + do_action( "tutor_save_course", $post_ID, $post);
256 +
69 257 /**
70 - * Insert Topic
258 + * Save course price type
71 259 */
72 - if ( ! empty($_POST['topic_title'])) {
73 - $topic_title = sanitize_text_field( $_POST['topic_title'] );
74 - $topic_summery = wp_kses_post( $_POST['topic_summery'] );
75 -
76 - $post_arr = array(
77 - 'post_type' => 'topics',
78 - 'post_title' => $topic_title,
79 - 'post_content' => $topic_summery,
80 - 'post_status' => 'publish',
81 - 'post_author' => get_current_user_id(),
82 - 'post_parent' => $post_ID,
83 - );
84 - wp_insert_post( $post_arr );
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);
85 263 }
86 264
87 265 //Course Duration
88 266 if ( ! empty($_POST['course_duration'])){
89 - $video = tutor_utils()->sanitize_array($_POST['course_duration']);
267 + $video = tutils()->sanitize_array($_POST['course_duration']);
90 268 update_post_meta($post_ID, '_course_duration', $video);
91 269 }
92 270
93 271 if ( ! empty($_POST['course_level'])){
@@ -94,27 +272,40 @@
94 272 $course_level = sanitize_text_field($_POST['course_level']);
95 273 update_post_meta($post_ID, '_tutor_course_level', $course_level);
96 274 }
97 275
98 - if ( ! empty($_POST['course_benefits'])){
99 - $course_benefits = wp_kses_post($_POST['course_benefits']);
100 - update_post_meta($post_ID, '_tutor_course_benefits', $course_benefits);
101 - }
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 + }
102 284
103 - if ( ! empty($_POST['course_requirements'])){
104 - $requirements = wp_kses_post($_POST['course_requirements']);
105 - update_post_meta($post_ID, '_tutor_course_requirements', $requirements);
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 + }
106 305 }
107 306
108 - if ( ! empty($_POST['course_target_audience'])){
109 - $target_audience = wp_kses_post($_POST['course_target_audience']);
110 - update_post_meta($post_ID, '_tutor_course_target_audience', $target_audience);
111 - }
112 307
113 - if ( ! empty($_POST['course_material_includes'])){
114 - $material_includes = wp_kses_post($_POST['course_material_includes']);
115 - update_post_meta($post_ID, '_tutor_course_material_includes', $material_includes);
116 - }
117 308 /**
118 309 * Sorting Topics and lesson
119 310 */
120 311 if ( ! empty($_POST['tutor_topics_lessons_sorting'])){
@@ -161,14 +352,16 @@
161 352 }
162 353 }
163 354 }
164 355 }
165 -
166 -
167 - //Video
168 - if ( ! empty($_POST['video']['source'])){
169 - $video = tutor_utils()->sanitize_array($_POST['video']);
170 - update_post_meta($post_ID, '_video', $video);
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 + }
171 364 }
172 365
173 366 /**
174 367 * Adding author to instructor automatically
@@ -174,29 +367,27 @@
174 367 * Adding author to instructor automatically
175 368 */
176 369
177 370 $author_id = $post->post_author;
178 - $attached = (int) $wpdb->get_var(" SELECT COUNT(umeta_id) FROM {$wpdb->usermeta} WHERE user_id = {$author_id} AND meta_key = '_tutor_instructor_course_id' AND meta_value = {$post_ID} ");
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 +
179 375 if ( ! $attached){
180 376 add_user_meta($author_id, '_tutor_instructor_course_id', $post_ID);
181 377 }
182 378
183 - //Announcements
184 - $announcement_title = tutor_utils()->avalue_dot('announcements.title', $_POST );
185 - if ( ! empty($announcement_title)){
186 - $title = sanitize_text_field(tutor_utils()->avalue_dot('announcements.title', $_POST ));
187 - $content = wp_kses_post(tutor_utils()->avalue_dot('announcements.content', $_POST ));
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 + }
188 388
189 - $post_arr = array(
190 - 'post_type' => 'tutor_announcements',
191 - 'post_title' => $title,
192 - 'post_content' => $content,
193 - 'post_status' => 'publish',
194 - 'post_author' => get_current_user_id(),
195 - 'post_parent' => $post_ID,
196 - );
197 - wp_insert_post( $post_arr );
198 - }
389 + do_action( "tutor_save_course_after", $post_ID, $post);
199 390 }
200 391
201 392 /**
202 393 * Tutor add course topic
@@ -201,13 +392,19 @@
201 392 /**
202 393 * Tutor add course topic
203 394 */
204 395 public function tutor_add_course_topic(){
205 - if (empty($_POST['topic_title'])) {
396 + tutils()->checking_nonce();
397 +
398 + if (empty($_POST['topic_title']) ) {
206 399 wp_send_json_error();
207 400 }
208 401 $course_id = (int) tutor_utils()->avalue_dot('tutor_topic_course_ID', $_POST);
209 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 + }
210 407
211 408 $topic_title = sanitize_text_field( $_POST['topic_title'] );
212 409 $topic_summery = wp_kses_post( $_POST['topic_summery'] );
213 410
@@ -232,12 +429,18 @@
232 429 /**
233 430 * Update the topic
234 431 */
235 432 public function tutor_update_topic(){
433 + tutils()->checking_nonce();
434 +
236 435 $topic_id = (int) sanitize_text_field($_POST['topic_id']);
237 436 $topic_title = sanitize_text_field($_POST['topic_title']);
238 437 $topic_summery = wp_kses_post($_POST['topic_summery']);
239 438
439 + if(!tutils()->can_user_manage('topic', $topic_id)) {
440 + wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
441 + }
442 +
240 443 $topic_attr = array(
241 444 'ID' => $topic_id,
242 445 'post_title' => $topic_title,
243 446 'post_content' => $topic_summery,
@@ -254,9 +457,8 @@
254 457 * @return mixed
255 458 *
256 459 * Add Lesson column
257 460 */
258 -
259 461 public function add_column($columns){
260 462 $date_col = $columns['date'];
261 463 unset($columns['date']);
262 464 $columns['lessons'] = __('Lessons', 'tutor');
@@ -282,17 +484,17 @@
282 484 }
283 485
284 486 if ($column === 'price'){
285 487 $price = tutor_utils()->get_course_price($post_id);
286 -
287 488 if ($price){
288 - if (function_exists('wc_price')){
489 + $monetize_by = tutils()->get_option('monetize_by');
490 + if (function_exists('wc_price') && $monetize_by === 'wc'){
289 491 echo '<span class="tutor-label-success">'.wc_price($price).'</span>';
290 492 }else{
291 493 echo '<span class="tutor-label-success">'.$price.'</span>';
292 494 }
293 495 }else{
294 - echo 'free';
496 + echo apply_filters('tutor-loop-default-price', 'free');
295 497 }
296 498 }
297 499 }
298 500
@@ -297,15 +499,13 @@
297 499 }
298 500
299 501
300 502 public function tutor_delete_topic(){
301 - if (!isset($_GET[tutor()->nonce]) || !wp_verify_nonce($_GET[tutor()->nonce], tutor()->nonce_action)) {
302 - exit();
303 - }
304 - if ( ! isset($_GET['topic_id'])){
305 - exit();
306 - }
307 503
504 + tutils()->checking_nonce('get');
505 +
506 + !isset($_GET['topic_id']) ? exit() : 0;
507 +
308 508 global $wpdb;
309 509
310 510 $topic_id = (int) sanitize_text_field($_GET['topic_id']);
311 511 $wpdb->update(
@@ -332,10 +532,11 @@
332 532 wp_safe_redirect(wp_get_referer());
333 533 }
334 534
335 535 public function enroll_now(){
536 +
336 537 //Checking if action comes from Enroll form
337 - if ( ! isset($_POST['tutor_course_action']) || $_POST['tutor_course_action'] !== '_tutor_course_enroll_now' || ! isset($_POST['tutor_course_id']) ){
538 + if (tutor_utils()->array_get('tutor_course_action', $_POST) !== '_tutor_course_enroll_now' || ! isset($_POST['tutor_course_id']) ){
338 539 return;
339 540 }
340 541 //Checking Nonce
341 542 tutor_utils()->checking_nonce();
@@ -401,14 +602,17 @@
401 602 */
402 603
403 604 global $wpdb;
404 605
405 - $date = date("Y-m-d H:i:s");
606 + $date = date("Y-m-d H:i:s", tutor_time());
406 607
407 608 //Making sure that, hash is unique
408 609 do{
409 610 $hash = substr(md5(wp_generate_password(32).$date.$course_id.$user_id), 0, 16);
410 - $hasHash = (int) $wpdb->get_var("SELECT COUNT(comment_ID) from {$wpdb->comments} WHERE comment_agent = 'TutorLMSPlugin' AND comment_type = 'course_completed' AND comment_content = '{$hash}' ");
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 +
411 615 }while($hasHash > 0);
412 616
413 617 $data = array(
414 618 'comment_post_ID' => $course_id,
@@ -423,9 +627,9 @@
423 627 );
424 628
425 629 $wpdb->insert($wpdb->comments, $data);
426 630
427 - do_action('tutor_course_complete_after', $course_id);
631 + do_action('tutor_course_complete_after', $course_id, $user_id);
428 632
429 633 wp_redirect(get_the_permalink($course_id));
430 634 }
431 635
@@ -430,34 +634,38 @@
430 634 }
431 635
432 636
433 637 public function tutor_load_instructors_modal(){
638 + tutils()->checking_nonce();
639 +
434 640 global $wpdb;
435 641
436 642 $course_id = (int) sanitize_text_field($_POST['course_id']);
437 643 $search_terms = sanitize_text_field(tutor_utils()->avalue_dot('search_terms', $_POST));
438 644
645 + if(!tutils()->can_user_manage('course', $course_id)) {
646 + wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
647 + }
648 +
439 649 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
440 -
441 650 $instructors = array();
442 651
443 -
444 652 $not_in_sql = apply_filters('tutor_instructor_query_when_exists', " AND ID <1 ");
445 653
446 654 if ($saved_instructors){
447 655 $saved_instructors_ids = wp_list_pluck($saved_instructors, 'ID');
448 656 $instructor_not_in_ids = implode(',', $saved_instructors_ids);
449 - $not_in_sql .= "AND ID NOT IN($instructor_not_in_ids) ";
657 + $not_in_sql .= "AND user.ID NOT IN($instructor_not_in_ids) ";
450 658 }
451 659
452 660 $search_sql = '';
453 661 if ($search_terms){
454 - $search_sql = "AND user_login like '%{$search_terms}%' or user_nicename like '%{$search_terms}%' or display_name like '%{$search_terms}%' ";
662 + $search_sql = "AND (user.user_login like '%{$search_terms}%' or user.user_nicename like '%{$search_terms}%' or user.display_name like '%{$search_terms}%') ";
455 663 }
456 664
457 - $instructors = $wpdb->get_results("select ID, display_name from {$wpdb->users}
458 - INNER JOIN {$wpdb->usermeta} ON ID = user_id AND meta_key = '_tutor_instructor_status' AND meta_value = 'approved'
459 - WHERE ID > 0 {$not_in_sql} {$search_sql} limit 10 ");
665 + $instructors = $wpdb->get_results("SELECT user.ID, user.display_name from {$wpdb->users} user
666 + INNER JOIN {$wpdb->usermeta} meta ON user.ID = meta.user_id AND meta.meta_key = '_tutor_instructor_status' AND meta.meta_value = 'approved'
667 + WHERE 1=1 {$not_in_sql} {$search_sql} limit 10 ");
460 668
461 669 $output = '';
462 670 if (is_array($instructors) && count($instructors)){
463 671 $instructor_output = '';
@@ -465,12 +673,11 @@
465 673 $instructor_output .= "<p><label><input type='radio' name='tutor_instructor_ids[]' value='{$instructor->ID}' > {$instructor->display_name} </label></p>";
466 674 }
467 675
468 676 $output .= apply_filters('tutor_course_instructors_html', $instructor_output, $instructors);
469 - $output .= '<p class="quiz-search-suggest-text">'.__('Search to get the specific instructors', 'tutor').'</p>';
470 677
471 678 }else{
472 - $output .= __('No instructor available or you have already added maximum instructors', 'tutor');
679 + $output .= __('<p>No instructor available or you have already added maximum instructors</p>', 'tutor');
473 680 }
474 681
475 682
476 683 if ( ! defined('TUTOR_MT_VERSION')){
@@ -480,10 +687,16 @@
480 687 wp_send_json_success(array('output' => $output));
481 688 }
482 689
483 690 public function tutor_add_instructors_to_course(){
691 + tutils()->checking_nonce();
692 +
484 693 $course_id = (int) sanitize_text_field($_POST['course_id']);
485 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 + }
486 699
487 700 if (is_array($instructor_ids) && count($instructor_ids)){
488 701 foreach ($instructor_ids as $instructor_id){
489 702 add_user_meta($instructor_id, '_tutor_instructor_course_id', $course_id);
@@ -499,9 +712,9 @@
499 712 $output .= '<div id="added-instructor-id-'.$t->ID.'" class="added-instructor-item added-instructor-item-'.$t->ID.'" data-instructor-id="'.$t->ID.'">
500 713 <span class="instructor-icon">'.get_avatar($t->ID, 30).'</span>
501 714 <span class="instructor-name"> '.$t->display_name.' </span>
502 715 <span class="instructor-control">
503 - <a href="javascript:;" class="tutor-instructor-delete-btn"><i class="tutor-icon-garbage"></i></a>
716 + <a href="javascript:;" class="tutor-instructor-delete-btn"><i class="tutor-icon-line-cross"></i></a>
504 717 </span>
505 718 </div>';
506 719 }
507 720 }
@@ -509,15 +722,595 @@
509 722 wp_send_json_success(array('output' => $output));
510 723 }
511 724
512 725 public function detach_instructor_from_course(){
726 + tutils()->checking_nonce();
727 +
513 728 global $wpdb;
514 729
515 730 $instructor_id = (int) sanitize_text_field($_POST['instructor_id']);
516 731 $course_id = (int) sanitize_text_field($_POST['course_id']);
517 732
733 + if(!tutils()->can_user_manage('course', $course_id)) {
734 + wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
735 + }
736 +
518 737 $wpdb->delete($wpdb->usermeta, array('user_id' => $instructor_id, 'meta_key' => '_tutor_instructor_course_id', 'meta_value' => $course_id) );
519 738 wp_send_json_success();
520 739 }
521 740
741 + public function tutor_delete_dashboard_course(){
742 + tutils()->checking_nonce();
522 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 + }
523 1316 }