PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 1.6.0
Tutor LMS – eLearning and online course solution v1.6.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 6 years ago Admin.php 6 years ago Ajax.php 6 years ago Assets.php 6 years ago Course.php 6 years ago Course_Settings_Tabs.php 6 years ago Course_Widget.php 6 years ago Dashboard.php 6 years ago Email.php 6 years ago FormHandler.php 6 years ago Frontend.php 6 years ago Gutenberg.php 6 years ago Instructor.php 6 years ago Instructors_List.php 6 years ago Lesson.php 6 years ago Options.php 6 years ago Post_types.php 6 years ago Q_and_A.php 6 years ago Question_Answers_List.php 6 years ago Quiz.php 6 years ago Quiz_Attempts_List.php 6 years ago RestAPI.php 6 years ago Rewrite_Rules.php 6 years ago Shortcode.php 6 years ago Student.php 6 years ago Students_List.php 6 years ago Taxonomies.php 6 years ago Template.php 6 years ago Theme_Compatibility.php 6 years ago Tools.php 6 years ago Tutor.php 6 years ago TutorEDD.php 6 years ago Tutor_Base.php 6 years ago Tutor_List_Table.php 6 years ago Tutor_Setup.php 6 years ago Upgrader.php 6 years ago User.php 6 years ago Utils.php 6 years ago Video_Stream.php 6 years ago Withdraw.php 6 years ago Withdraw_Requests_List.php 6 years ago WooCommerce.php 6 years ago
Course.php
1033 lines
1 <?php
2 namespace TUTOR;
3
4 if ( ! defined( 'ABSPATH' ) )
5 exit;
6
7 class Course extends Tutor_Base {
8 public function __construct() {
9 parent::__construct();
10
11 add_action( 'add_meta_boxes', array($this, 'register_meta_box') );
12 add_action('save_post_'.$this->course_post_type, array($this, 'save_course_meta'), 10, 2);
13 add_action('wp_ajax_tutor_add_course_topic', array($this, 'tutor_add_course_topic'));
14 add_action('wp_ajax_tutor_update_topic', array($this, 'tutor_update_topic'));
15
16 //Add Column
17 add_filter( "manage_{$this->course_post_type}_posts_columns", array($this, 'add_column'), 10,1 );
18 add_action( "manage_{$this->course_post_type}_posts_custom_column" , array($this, 'custom_lesson_column'), 10, 2 );
19
20 add_action('admin_action_tutor_delete_topic', array($this, 'tutor_delete_topic'));
21 add_action('admin_action_tutor_delete_announcement', array($this, 'tutor_delete_announcement'));
22
23 //Frontend Action
24 add_action('template_redirect', array($this, 'enroll_now'));
25 add_action('template_redirect', array($this, 'mark_course_complete'));
26
27 //Modal Perform
28 add_action('wp_ajax_tutor_load_instructors_modal', array($this, 'tutor_load_instructors_modal'));
29 add_action('wp_ajax_tutor_add_instructors_to_course', array($this, 'tutor_add_instructors_to_course'));
30 add_action('wp_ajax_detach_instructor_from_course', array($this, 'detach_instructor_from_course'));
31
32 /**
33 * Frontend Dashboard
34 */
35 add_action('wp_ajax_tutor_delete_dashboard_course', array($this, 'tutor_delete_dashboard_course'));
36
37 /**
38 * Gutenberg author support
39 */
40 add_filter('wp_insert_post_data', array($this, 'tutor_add_gutenberg_author'), '99', 2);
41
42 /**
43 * Frontend metabox supports for course builder
44 * @since v.1.3.4
45 */
46 add_action('tutor/dashboard_course_builder_form_field_after', array($this, 'register_meta_box_in_frontend'));
47
48
49 /**
50 * Do Stuff for the course save from frontend
51 */
52 add_action('save_tutor_course', array($this, 'attach_product_with_course'), 10, 2);
53
54 /**
55 * Add course level to course settings
56 * @since v.1.4.1
57 */
58 add_action('tutor_course/settings_tab_content/after/general', array($this, 'add_course_level_to_settings'));
59
60 /**
61 * Enable Disable Course Details Page Feature
62 * @since v.1.4.8
63 */
64 $this->course_elements_enable_disable();
65
66 /**
67 * @since v.1.4.8
68 * Check if course starting, set meta if starting
69 */
70 add_action('tutor_lesson_load_before', array($this, 'tutor_lesson_load_before'));
71
72 /**
73 * @since v.1.4.9
74 * Filter product in shop page
75 */
76 $this->filter_product_in_shop_page();
77
78 /**
79 * Remove the course price if enrolled
80 * @since 1.5.8
81 */
82 add_filter('tutor_course_price', array($this, 'remove_price_if_enrolled'));
83 }
84
85 /**
86 * Registering metabox
87 */
88 public function register_meta_box(){
89 $coursePostType = tutor()->course_post_type;
90 $course_marketplace = tutor_utils()->get_option('enable_course_marketplace');
91 //add_meta_box( 'tutor-course-levels', __( 'Course Level', 'tutor' ), array($this, 'course_level_metabox'), $coursePostType );
92 add_meta_box( 'tutor-course-topics', __( 'Course Builder', 'tutor' ), array($this, 'course_meta_box'), $coursePostType );
93 add_meta_box( 'tutor-course-additional-data', __( 'Additional Data', 'tutor' ), array($this, 'course_additional_data_meta_box'), $coursePostType );
94 add_meta_box( 'tutor-course-videos', __( 'Video', 'tutor' ), array($this, 'video_metabox'), $coursePostType );
95 if ($course_marketplace) {
96 add_meta_box( 'tutor-instructors', __( 'Instructors', 'tutor' ), array( $this, 'instructors_metabox' ), $coursePostType );
97 }
98 add_meta_box( 'tutor-announcements', __( 'Announcements', 'tutor' ), array($this, 'announcements_metabox'), $coursePostType );
99 }
100
101 public function course_meta_box($echo = true){
102 ob_start();
103 include tutor()->path.'views/metabox/course-topics.php';
104 $content = ob_get_clean();
105
106 if ($echo){
107 echo $content;
108 }else{
109 return $content;
110 }
111 }
112
113 public function course_additional_data_meta_box($echo = true){
114
115 ob_start();
116 include tutor()->path.'views/metabox/course-additional-data.php';
117 $content = ob_get_clean();
118
119 if ($echo){
120 echo $content;
121 }else{
122 return $content;
123 }
124 }
125
126 public function video_metabox($echo = true){
127 ob_start();
128 include tutor()->path.'views/metabox/video-metabox.php';
129 $content = ob_get_clean();
130
131 if ($echo){
132 echo $content;
133 }else{
134 return $content;
135 }
136 }
137
138 public function course_level_metabox($echo = true){
139 ob_start();
140 include tutor()->path.'views/metabox/course-level-metabox.php';
141 $content = ob_get_clean();
142
143 if ($echo){
144 echo $content;
145 }else{
146 return $content;
147 }
148 }
149
150 public function announcements_metabox($echo = true){
151 ob_start();
152 include tutor()->path.'views/metabox/announcements-metabox.php';
153 $content = ob_get_clean();
154
155 if ($echo){
156 echo $content;
157 }else{
158 return $content;
159 }
160 }
161
162 public function instructors_metabox($echo = true){
163 ob_start();
164 include tutor()->path . 'views/metabox/instructors-metabox.php';
165 $content = ob_get_clean();
166
167 if ($echo){
168 echo $content;
169 }else{
170 return $content;
171 }
172 }
173
174 /**
175 * Register metabox in course builder tutor
176 * @since v.1.3.4
177 */
178 public function register_meta_box_in_frontend(){
179 do_action('tutor_course_builder_metabox_before', get_the_ID());
180 course_builder_section_wrap($this->video_metabox($echo = false), 'Video');
181 course_builder_section_wrap($this->course_meta_box($echo = false), 'Course Builder');
182 course_builder_section_wrap($this->instructors_metabox($echo = false), 'Instructors');
183 course_builder_section_wrap($this->course_additional_data_meta_box($echo = false), 'Additional Data');
184 course_builder_section_wrap($this->announcements_metabox($echo = false), 'Announcements');
185 do_action('tutor_course_builder_metabox_after', get_the_ID());
186 }
187
188 /**
189 * @param $post_ID
190 *
191 * Insert Topic and attached it with Course
192 */
193 public function save_course_meta($post_ID, $post){
194 global $wpdb;
195
196 do_action( "tutor_save_course", $post_ID, $post);
197
198 /**
199 * Insert Topic
200 */
201 /*
202 if ( ! empty($_POST['topic_title'])) {
203 $topic_title = sanitize_text_field( $_POST['topic_title'] );
204 $topic_summery = wp_kses_post( $_POST['topic_summery'] );
205
206 $post_arr = array(
207 'post_type' => 'topics',
208 'post_title' => $topic_title,
209 'post_content' => $topic_summery,
210 'post_status' => 'publish',
211 'post_author' => get_current_user_id(),
212 'post_parent' => $post_ID,
213 );
214 wp_insert_post( $post_arr );
215 }*/
216
217 /**
218 * Save course price type
219 */
220 $price_type = tutils()->array_get('tutor_course_price_type', $_POST);
221 if ($price_type){
222 update_post_meta($post_ID, '_tutor_course_price_type', $price_type);
223 }
224
225 //Course Duration
226 if ( ! empty($_POST['course_duration'])){
227 $video = tutor_utils()->sanitize_array($_POST['course_duration']);
228 update_post_meta($post_ID, '_course_duration', $video);
229 }
230
231 if ( ! empty($_POST['course_level'])){
232 $course_level = sanitize_text_field($_POST['course_level']);
233 update_post_meta($post_ID, '_tutor_course_level', $course_level);
234 }
235
236 if ( ! empty($_POST['course_benefits'])){
237 $course_benefits = wp_kses_post($_POST['course_benefits']);
238 update_post_meta($post_ID, '_tutor_course_benefits', $course_benefits);
239 }else{
240 delete_post_meta($post_ID, '_tutor_course_benefits');
241 }
242
243 if ( ! empty($_POST['course_requirements'])){
244 $requirements = wp_kses_post($_POST['course_requirements']);
245 update_post_meta($post_ID, '_tutor_course_requirements', $requirements);
246 }else{
247 delete_post_meta($post_ID, '_tutor_course_requirements');
248 }
249
250 if ( ! empty($_POST['course_target_audience'])){
251 $target_audience = wp_kses_post($_POST['course_target_audience']);
252 update_post_meta($post_ID, '_tutor_course_target_audience', $target_audience);
253 }else{
254 delete_post_meta($post_ID, '_tutor_course_target_audience');
255 }
256
257 if ( ! empty($_POST['course_material_includes'])){
258 $material_includes = wp_kses_post($_POST['course_material_includes']);
259 update_post_meta($post_ID, '_tutor_course_material_includes', $material_includes);
260 }else{
261 delete_post_meta($post_ID, '_tutor_course_material_includes');
262 }
263
264
265 /**
266 * Sorting Topics and lesson
267 */
268 if ( ! empty($_POST['tutor_topics_lessons_sorting'])){
269 $new_order = sanitize_text_field(stripslashes($_POST['tutor_topics_lessons_sorting']));
270 $order = json_decode($new_order, true);
271
272 if (is_array($order) && count($order)){
273 $i = 0;
274 foreach ($order as $topic ){
275 $i++;
276 $wpdb->update(
277 $wpdb->posts,
278 array('menu_order' => $i),
279 array('ID' => $topic['topic_id'])
280 );
281
282 /**
283 * Removing All lesson with topic
284 */
285
286 $wpdb->update(
287 $wpdb->posts,
288 array('post_parent' => 0),
289 array('post_parent' => $topic['topic_id'])
290 );
291
292 /**
293 * Lesson Attaching with topic ID
294 * sorting lesson
295 */
296 if (isset($topic['lesson_ids'])){
297 $lesson_ids = $topic['lesson_ids'];
298 }else{
299 $lesson_ids = array();
300 }
301 if (count($lesson_ids)){
302 foreach ($lesson_ids as $lesson_key => $lesson_id ){
303 $wpdb->update(
304 $wpdb->posts,
305 array('post_parent' => $topic['topic_id'], 'menu_order' => $lesson_key),
306 array('ID' => $lesson_id)
307 );
308 }
309 }
310 }
311 }
312 }
313
314 //Video
315 if ( ! empty($_POST['video']['source'])){
316 //$video = tutor_utils()->sanitize_array($_POST['video']);
317 $video = tutor_utils()->array_get('video', $_POST);
318 update_post_meta($post_ID, '_video', $video);
319 }else{
320 delete_post_meta($post_ID, '_video');
321 }
322
323 /**
324 * Adding author to instructor automatically
325 */
326
327 $author_id = $post->post_author;
328 $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} ");
329 if ( ! $attached){
330 add_user_meta($author_id, '_tutor_instructor_course_id', $post_ID);
331 }
332
333 //Announcements
334 if ( ! wp_doing_ajax()) {
335 $announcement_title = tutor_utils()->avalue_dot( 'announcements.title', $_POST );
336 if ( ! empty( $announcement_title ) ) {
337 $title = sanitize_text_field( tutor_utils()->avalue_dot( 'announcements.title', $_POST ) );
338 $content = wp_kses_post( tutor_utils()->avalue_dot( 'announcements.content', $_POST ) );
339
340 $post_arr = array(
341 'post_type' => 'tutor_announcements',
342 'post_title' => $title,
343 'post_content' => $content,
344 'post_status' => 'publish',
345 'post_author' => get_current_user_id(),
346 'post_parent' => $post_ID,
347 );
348 wp_insert_post( $post_arr );
349 }
350 }
351
352 do_action( "tutor_save_course_after", $post_ID, $post);
353 }
354
355 /**
356 * Tutor add course topic
357 */
358 public function tutor_add_course_topic(){
359 if (empty($_POST['topic_title']) ) {
360 wp_send_json_error();
361 }
362 $course_id = (int) tutor_utils()->avalue_dot('tutor_topic_course_ID', $_POST);
363 $next_topic_order_id = tutor_utils()->get_next_topic_order_id($course_id);
364
365 $topic_title = sanitize_text_field( $_POST['topic_title'] );
366 $topic_summery = wp_kses_post( $_POST['topic_summery'] );
367
368 $post_arr = array(
369 'post_type' => 'topics',
370 'post_title' => $topic_title,
371 'post_content' => $topic_summery,
372 'post_status' => 'publish',
373 'post_author' => get_current_user_id(),
374 'post_parent' => $course_id,
375 'menu_order' => $next_topic_order_id,
376 );
377 $current_topic_id = wp_insert_post( $post_arr );
378
379 ob_start();
380 include tutor()->path.'views/metabox/course-contents.php';
381 $course_contents = ob_get_clean();
382
383 wp_send_json_success(array('course_contents' => $course_contents));
384 }
385
386 /**
387 * Update the topic
388 */
389 public function tutor_update_topic(){
390 $topic_id = (int) sanitize_text_field($_POST['topic_id']);
391 $topic_title = sanitize_text_field($_POST['topic_title']);
392 $topic_summery = wp_kses_post($_POST['topic_summery']);
393
394 $topic_attr = array(
395 'ID' => $topic_id,
396 'post_title' => $topic_title,
397 'post_content' => $topic_summery,
398 );
399 wp_update_post( $topic_attr );
400
401 wp_send_json_success(array('msg' => __('Topic has been updated', 'tutor') ));
402 }
403
404
405 /**
406 * @param $columns
407 *
408 * @return mixed
409 *
410 * Add Lesson column
411 */
412 public function add_column($columns){
413 $date_col = $columns['date'];
414 unset($columns['date']);
415 $columns['lessons'] = __('Lessons', 'tutor');
416 $columns['students'] = __('Students', 'tutor');
417 $columns['price'] = __('Price', 'tutor');
418 $columns['date'] = $date_col;
419
420 return $columns;
421 }
422
423 /**
424 * @param $column
425 * @param $post_id
426 *
427 */
428 public function custom_lesson_column($column, $post_id ){
429 if ($column === 'lessons'){
430 echo tutor_utils()->get_lesson_count_by_course($post_id);
431 }
432
433 if ($column === 'students'){
434 echo tutor_utils()->count_enrolled_users_by_course($post_id);
435 }
436
437 if ($column === 'price'){
438 $price = tutor_utils()->get_course_price($post_id);
439 if ($price){
440 $monetize_by = tutils()->get_option('monetize_by');
441 if (function_exists('wc_price') && $monetize_by === 'wc'){
442 echo '<span class="tutor-label-success">'.wc_price($price).'</span>';
443 }else{
444 echo '<span class="tutor-label-success">'.$price.'</span>';
445 }
446 }else{
447 echo 'free';
448 }
449 }
450 }
451
452
453 public function tutor_delete_topic(){
454 if (!isset($_GET[tutor()->nonce]) || !wp_verify_nonce($_GET[tutor()->nonce], tutor()->nonce_action)) {
455 exit();
456 }
457 if ( ! isset($_GET['topic_id'])){
458 exit();
459 }
460
461 global $wpdb;
462
463 $topic_id = (int) sanitize_text_field($_GET['topic_id']);
464 $wpdb->update(
465 $wpdb->posts,
466 array('post_parent' => 0),
467 array('post_parent' => $topic_id)
468 );
469
470 $wpdb->delete(
471 $wpdb->postmeta,
472 array('post_id' => $topic_id)
473 );
474
475 wp_delete_post($topic_id);
476 wp_safe_redirect(wp_get_referer());
477 }
478
479 public function tutor_delete_announcement(){
480 tutor_utils()->checking_nonce('get');
481
482 $announcement_id = (int) sanitize_text_field($_GET['topic_id']);
483
484 wp_delete_post($announcement_id);
485 wp_safe_redirect(wp_get_referer());
486 }
487
488 public function enroll_now(){
489
490 //Checking if action comes from Enroll form
491 if (tutor_utils()->array_get('tutor_course_action', $_POST) !== '_tutor_course_enroll_now' || ! isset($_POST['tutor_course_id']) ){
492 return;
493 }
494 //Checking Nonce
495 tutor_utils()->checking_nonce();
496
497 $user_id = get_current_user_id();
498 if ( ! $user_id){
499 exit(__('Please Sign In first', 'tutor'));
500 }
501
502 $course_id = (int) sanitize_text_field($_POST['tutor_course_id']);
503 $user_id = get_current_user_id();
504
505 /**
506 * TODO: need to check purchase information
507 */
508
509 $is_purchasable = tutor_utils()->is_course_purchasable($course_id);
510
511 /**
512 * If is is not purchasable, it's free, and enroll right now
513 *
514 * if purchasable, then process purchase.
515 *
516 * @since: v.1.0.0
517 */
518 if ($is_purchasable){
519 //process purchase
520
521 }else{
522 //Free enroll
523 tutor_utils()->do_enroll($course_id);
524 }
525
526 $referer_url = wp_get_referer();
527 wp_redirect($referer_url);
528 }
529
530 /**
531 *
532 * Mark complete completed
533 *
534 * @since v.1.0.0
535 */
536 public function mark_course_complete(){
537 if ( ! isset($_POST['tutor_action']) || $_POST['tutor_action'] !== 'tutor_complete_course' ){
538 return;
539 }
540 //Checking nonce
541 tutor_utils()->checking_nonce();
542
543 $user_id = get_current_user_id();
544
545 //TODO: need to show view if not signed_in
546 if ( ! $user_id){
547 die(__('Please Sign-In', 'tutor'));
548 }
549
550 $course_id = (int) sanitize_text_field($_POST['course_id']);
551
552 do_action('tutor_course_complete_before', $course_id);
553 /**
554 * Marking course completed at Comment
555 */
556
557 global $wpdb;
558
559 $date = date("Y-m-d H:i:s", tutor_time());
560
561 //Making sure that, hash is unique
562 do{
563 $hash = substr(md5(wp_generate_password(32).$date.$course_id.$user_id), 0, 16);
564 $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}' ");
565 }while($hasHash > 0);
566
567 $data = array(
568 'comment_post_ID' => $course_id,
569 'comment_author' => $user_id,
570 'comment_date' => $date,
571 'comment_date_gmt' => get_gmt_from_date($date),
572 'comment_content' => $hash, //Identification Hash
573 'comment_approved' => 'approved',
574 'comment_agent' => 'TutorLMSPlugin',
575 'comment_type' => 'course_completed',
576 'user_id' => $user_id,
577 );
578
579 $wpdb->insert($wpdb->comments, $data);
580
581 do_action('tutor_course_complete_after', $course_id);
582
583 wp_redirect(get_the_permalink($course_id));
584 }
585
586
587 public function tutor_load_instructors_modal(){
588 global $wpdb;
589
590 $course_id = (int) sanitize_text_field($_POST['course_id']);
591 $search_terms = sanitize_text_field(tutor_utils()->avalue_dot('search_terms', $_POST));
592
593 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
594
595 $instructors = array();
596
597
598 $not_in_sql = apply_filters('tutor_instructor_query_when_exists', " AND ID <1 ");
599
600 if ($saved_instructors){
601 $saved_instructors_ids = wp_list_pluck($saved_instructors, 'ID');
602 $instructor_not_in_ids = implode(',', $saved_instructors_ids);
603 $not_in_sql .= "AND ID NOT IN($instructor_not_in_ids) ";
604 }
605
606 $search_sql = '';
607 if ($search_terms){
608 $search_sql = "AND (user_login like '%{$search_terms}%' or user_nicename like '%{$search_terms}%' or display_name like '%{$search_terms}%') ";
609 }
610
611 $instructors = $wpdb->get_results("select ID, display_name from {$wpdb->users}
612 INNER JOIN {$wpdb->usermeta} ON ID = user_id AND meta_key = '_tutor_instructor_status' AND meta_value = 'approved'
613 WHERE 1=1 {$not_in_sql} {$search_sql} limit 10 ");
614
615 $output = '';
616 if (is_array($instructors) && count($instructors)){
617 $instructor_output = '';
618 foreach ($instructors as $instructor){
619 $instructor_output .= "<p><label><input type='radio' name='tutor_instructor_ids[]' value='{$instructor->ID}' > {$instructor->display_name} </label></p>";
620 }
621
622 $output .= apply_filters('tutor_course_instructors_html', $instructor_output, $instructors);
623
624 }else{
625 $output .= __('<p>No instructor available or you have already added maximum instructors</p>', 'tutor');
626 }
627
628
629 if ( ! defined('TUTOR_MT_VERSION')){
630 $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>';
631 }
632
633 wp_send_json_success(array('output' => $output));
634 }
635
636 public function tutor_add_instructors_to_course(){
637 $course_id = (int) sanitize_text_field($_POST['course_id']);
638 $instructor_ids = tutor_utils()->avalue_dot('tutor_instructor_ids', $_POST);
639
640 if (is_array($instructor_ids) && count($instructor_ids)){
641 foreach ($instructor_ids as $instructor_id){
642 add_user_meta($instructor_id, '_tutor_instructor_course_id', $course_id);
643 }
644 }
645
646 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
647 $output = '';
648
649 if ($saved_instructors){
650 foreach ($saved_instructors as $t){
651
652 $output .= '<div id="added-instructor-id-'.$t->ID.'" class="added-instructor-item added-instructor-item-'.$t->ID.'" data-instructor-id="'.$t->ID.'">
653 <span class="instructor-icon">'.get_avatar($t->ID, 30).'</span>
654 <span class="instructor-name"> '.$t->display_name.' </span>
655 <span class="instructor-control">
656 <a href="javascript:;" class="tutor-instructor-delete-btn"><i class="tutor-icon-line-cross"></i></a>
657 </span>
658 </div>';
659 }
660 }
661
662 wp_send_json_success(array('output' => $output));
663 }
664
665 public function detach_instructor_from_course(){
666 global $wpdb;
667
668 $instructor_id = (int) sanitize_text_field($_POST['instructor_id']);
669 $course_id = (int) sanitize_text_field($_POST['course_id']);
670
671 $wpdb->delete($wpdb->usermeta, array('user_id' => $instructor_id, 'meta_key' => '_tutor_instructor_course_id', 'meta_value' => $course_id) );
672 wp_send_json_success();
673 }
674
675 public function tutor_delete_dashboard_course(){
676 $course_id = intval(sanitize_text_field($_POST['course_id']));
677 wp_trash_post($course_id);
678 wp_send_json_success();
679 }
680
681
682 public function tutor_add_gutenberg_author($data , $postarr){
683 global $wpdb;
684
685 $courses_post_type = tutor()->course_post_type;
686 $post_type = tutils()->array_get('post_type', $postarr);
687
688 /*
689 $post_author = (int) tutor_utils()->avalue_dot('post_author', $data);
690
691 if ( ! $post_author){
692 $user_ID = (int) tutor_utils()->avalue_dot('user_ID', $postarr);
693 if ($user_ID){
694 $data['post_author'] = $user_ID;
695 }else{
696 $post_ID = (int) tutor_utils()->avalue_dot('ID', $postarr);
697 $post_author = (int) $wpdb->get_var("SELECT post_author FROM {$wpdb->posts} WHERE ID = {$post_ID} ");
698
699 $data['post_author'] = $post_author;
700 }
701 }*/
702
703 if ($courses_post_type === $post_type){
704 $post_ID = (int) tutor_utils()->avalue_dot('ID', $postarr);
705 $post_author = (int) $wpdb->get_var("SELECT post_author FROM {$wpdb->posts} WHERE ID = {$post_ID} ");
706
707 if ($post_author > 0){
708 $data['post_author'] = $post_author;
709 }else{
710 $data['post_author'] = get_current_user_id();
711 }
712 }
713
714 return $data;
715 }
716
717
718 /**
719 * @param $post_ID
720 * @param $postData
721 *
722 * Attach product during save course from the frontend course dashboard.
723 *
724 * @return string
725 *
726 * @since v.1.3.4
727 */
728 public function attach_product_with_course($post_ID, $postData){
729 $attached_product_id = tutor_utils()->get_course_product_id($post_ID);
730 $course_price = sanitize_text_field(tutor_utils()->array_get('course_price', $_POST));
731
732 if ( ! $course_price){
733 return;
734 }
735
736 $monetize_by = tutor_utils()->get_option('monetize_by');
737 $course = get_post($post_ID);
738
739 if ($monetize_by === 'wc'){
740
741 $is_update = false;
742 if ($attached_product_id){
743 $wc_product = get_post_meta($attached_product_id, '_product_version', true);
744 if ($wc_product){
745 $is_update = true;
746 }
747 }
748
749 if ($is_update){
750
751 $productObj = new \WC_Product($attached_product_id);
752 $productObj->set_price($course_price); // set product price
753 $productObj->set_regular_price($course_price); // set product regular price
754 $product_id = $productObj->save();
755
756 }else{
757
758 $productObj = new \WC_Product();
759 $productObj->set_name($course->post_title);
760 $productObj->set_status('publish');
761 $productObj->set_price($course_price); // set product price
762 $productObj->set_regular_price($course_price); // set product regular price
763
764 $product_id = $productObj->save();
765 if ($product_id) {
766 update_post_meta( $post_ID, '_tutor_course_product_id', $product_id );
767 //Mark product for woocommerce
768 update_post_meta( $product_id, '_virtual', 'yes' );
769 update_post_meta( $product_id, '_tutor_product', 'yes' );
770
771 $coursePostThumbnail = get_post_meta( $post_ID, '_thumbnail_id', true );
772 if ( $coursePostThumbnail ) {
773 set_post_thumbnail( $product_id, $coursePostThumbnail );
774 }
775 }
776 }
777
778 }elseif ($monetize_by === 'edd'){
779
780 $is_update = false;
781
782 if ($attached_product_id){
783 $edd_price = get_post_meta($attached_product_id, 'edd_price', true);
784 if ($edd_price){
785 $is_update = true;
786 }
787 }
788
789 if ($is_update){
790 //Update the product
791 update_post_meta( $attached_product_id, 'edd_price', $course_price );
792 }else{
793 //Create new product
794
795 $post_arr = array(
796 'post_type' => 'download',
797 'post_title' => $course->post_title,
798 'post_status' => 'publish',
799 'post_author' => get_current_user_id(),
800 );
801 $download_id = wp_insert_post( $post_arr );
802 if ($download_id ) {
803 //edd_price
804 update_post_meta( $download_id, 'edd_price', $course_price );
805
806 update_post_meta( $post_ID, '_tutor_course_product_id', $download_id );
807 //Mark product for EDD
808 update_post_meta( $download_id, '_tutor_product', 'yes' );
809
810 $coursePostThumbnail = get_post_meta( $post_ID, '_thumbnail_id', true );
811 if ( $coursePostThumbnail ) {
812 set_post_thumbnail( $download_id, $coursePostThumbnail );
813 }
814
815 }
816
817 }
818
819
820 }
821
822 }
823
824
825 /**
826 * Add Course level to course settings
827 * @since v.1.4.1
828 */
829 public function add_course_level_to_settings(){
830 include tutor()->path.'views/metabox/course-level-metabox.php';
831 }
832
833 /**
834 * Check if course starting
835 *
836 * @since v.1.4.8
837 */
838 public function tutor_lesson_load_before(){
839 $course_id = tutils()->get_course_id_by_content(get_the_ID());
840 $completed_lessons = tutor_utils()->get_completed_lesson_count_by_course($course_id);
841 if (is_user_logged_in()){
842 $is_course_started = get_post_meta($course_id, '_tutor_course_started', true);
843 if ( ! $completed_lessons && ! $is_course_started){
844 update_post_meta($course_id, '_tutor_course_started', tutor_time());
845 do_action('tutor/course/started', $course_id);
846 }
847 }
848 }
849
850 /**
851 * Add Course level to course settings
852 * @since v.1.4.8
853 */
854 public function course_elements_enable_disable(){
855 add_filter('tutor_course/single/completing-progress-bar', array($this, 'enable_disable_course_progress_bar') );
856 add_filter('tutor_course/single/material_includes', array($this, 'enable_disable_material_includes') );
857 add_filter('tutor_course/single/content', array($this, 'enable_disable_course_content') );
858 add_filter('tutor_course/single/benefits_html', array($this, 'enable_disable_course_benefits') );
859 add_filter('tutor_course/single/requirements_html', array($this, 'enable_disable_course_requirements') );
860 add_filter('tutor_course/single/audience_html', array($this, 'enable_disable_course_target_audience') );
861 add_filter('tutor_course/single/enrolled/nav_items', array($this, 'enable_disable_course_nav_items') );
862 }
863
864 /**
865 * Enable disable course progress bar
866 * @since v.1.4.8
867 */
868 public function enable_disable_course_progress_bar($html){
869 $disable_option = (bool) get_tutor_option('disable_course_progress_bar');
870 if($disable_option){
871 return '';
872 }
873 return $html;
874 }
875
876 /**
877 * Enable disable material includes
878 * @since v.1.4.8
879 */
880 public function enable_disable_material_includes($html){
881 $disable_option = (bool) get_tutor_option('disable_course_material');
882 if($disable_option){
883 return '';
884 }
885 return $html;
886 }
887
888 /**
889 * Enable disable course content
890 * @since v.1.4.8
891 */
892 public function enable_disable_course_content($html){
893 $disable_option = (bool) get_tutor_option('disable_course_description');
894 if($disable_option){
895 return '';
896 }
897 return $html;
898 }
899
900 /**
901 * Enable disable course benefits
902 * @since v.1.4.8
903 */
904 public function enable_disable_course_benefits($html){
905 $disable_option = (bool) get_tutor_option('disable_course_benefits');
906 if($disable_option){
907 return '';
908 }
909 return $html;
910 }
911
912 /**
913 * Enable disable course requirements
914 * @since v.1.4.8
915 */
916 public function enable_disable_course_requirements($html){
917 $disable_option = (bool) get_tutor_option('disable_course_requirements');
918 if($disable_option){
919 return '';
920 }
921 return $html;
922 }
923
924 /**
925 * Enable disable course target audience
926 * @since v.1.4.8
927 */
928 public function enable_disable_course_target_audience($html){
929 $disable_option = (bool) get_tutor_option('disable_course_target_audience');
930 if($disable_option){
931 return '';
932 }
933 return $html;
934 }
935
936 /**
937 * Enable disable course nav items
938 * @since v.1.4.8
939 */
940 public function enable_disable_course_nav_items($items){
941 $enable_q_and_a_on_course = (bool) get_tutor_option('enable_q_and_a_on_course');
942 $disable_course_announcements = (bool) get_tutor_option('disable_course_announcements');
943
944 if(! $enable_q_and_a_on_course){
945 if(tutils()->array_get('questions', $items)) {
946 unset($items['questions']);
947 }
948 }
949 if($disable_course_announcements){
950 if(tutils()->array_get('announcements', $items)) {
951 unset($items['announcements']);
952 }
953 }
954 return $items;
955 }
956
957 /**
958 * Filter product in shop page
959 * @since v.1.4.9
960 */
961 public function filter_product_in_shop_page(){
962 $hide_course_from_shop_page = (bool) get_tutor_option('hide_course_from_shop_page');
963 if(!$hide_course_from_shop_page){
964 return;
965 }
966 add_action('woocommerce_product_query', array($this, 'filter_woocommerce_product_query'));
967 add_filter('edd_downloads_query', array($this, 'filter_edd_downloads_query'), 10, 2);
968 add_action('pre_get_posts', array($this, 'filter_archive_meta_query'), 1);
969 }
970
971 /**
972 * Tutor product meta query
973 * @since v.1.4.9
974 */
975 public function tutor_product_meta_query(){
976 $meta_query = array(
977 'key' => '_tutor_product',
978 'compare' => 'NOT EXISTS'
979 );
980 return $meta_query;
981 }
982
983 /**
984 * Filter product in woocommerce shop page
985 * @since v.1.4.9
986 */
987 public function filter_woocommerce_product_query($wp_query){
988 $wp_query->set('meta_query', array($this->tutor_product_meta_query()));
989 return $wp_query;
990 }
991
992 /**
993 * Filter product in edd downloads shortcode page
994 * @since v.1.4.9
995 */
996 public function filter_edd_downloads_query($query){
997 $query['meta_query'][] = $this->tutor_product_meta_query();
998 return $query;
999 }
1000
1001 /**
1002 * Filter product in edd downloads archive page
1003 * @since v.1.4.9
1004 */
1005 public function filter_archive_meta_query($wp_query){
1006 if(!is_admin() && $wp_query->is_archive && $wp_query->get('post_type') === 'download'){
1007 $wp_query->set('meta_query', array($this->tutor_product_meta_query()));
1008 }
1009 return $wp_query;
1010 }
1011
1012 /**
1013 * @param $html
1014 * @return string
1015 *
1016 * Removed course price if already enrolled at single course
1017 *
1018 * @since v.1.5.8
1019 */
1020 public function remove_price_if_enrolled($html){
1021 $should_removed = apply_filters('should_remove_price_if_enrolled', true);
1022
1023 if ($should_removed){
1024 $course_id = get_the_ID();
1025 $enrolled = tutils()->is_enrolled($course_id);
1026 if ($enrolled){
1027 $html = '';
1028 }
1029 }
1030 return $html;
1031 }
1032
1033 }