PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 1.5.9
Tutor LMS – eLearning and online course solution v1.5.9
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
1023 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 }
240
241 if ( ! empty($_POST['course_requirements'])){
242 $requirements = wp_kses_post($_POST['course_requirements']);
243 update_post_meta($post_ID, '_tutor_course_requirements', $requirements);
244 }
245
246 if ( ! empty($_POST['course_target_audience'])){
247 $target_audience = wp_kses_post($_POST['course_target_audience']);
248 update_post_meta($post_ID, '_tutor_course_target_audience', $target_audience);
249 }
250
251 if ( ! empty($_POST['course_material_includes'])){
252 $material_includes = wp_kses_post($_POST['course_material_includes']);
253 update_post_meta($post_ID, '_tutor_course_material_includes', $material_includes);
254 }
255 /**
256 * Sorting Topics and lesson
257 */
258 if ( ! empty($_POST['tutor_topics_lessons_sorting'])){
259 $new_order = sanitize_text_field(stripslashes($_POST['tutor_topics_lessons_sorting']));
260 $order = json_decode($new_order, true);
261
262 if (is_array($order) && count($order)){
263 $i = 0;
264 foreach ($order as $topic ){
265 $i++;
266 $wpdb->update(
267 $wpdb->posts,
268 array('menu_order' => $i),
269 array('ID' => $topic['topic_id'])
270 );
271
272 /**
273 * Removing All lesson with topic
274 */
275
276 $wpdb->update(
277 $wpdb->posts,
278 array('post_parent' => 0),
279 array('post_parent' => $topic['topic_id'])
280 );
281
282 /**
283 * Lesson Attaching with topic ID
284 * sorting lesson
285 */
286 if (isset($topic['lesson_ids'])){
287 $lesson_ids = $topic['lesson_ids'];
288 }else{
289 $lesson_ids = array();
290 }
291 if (count($lesson_ids)){
292 foreach ($lesson_ids as $lesson_key => $lesson_id ){
293 $wpdb->update(
294 $wpdb->posts,
295 array('post_parent' => $topic['topic_id'], 'menu_order' => $lesson_key),
296 array('ID' => $lesson_id)
297 );
298 }
299 }
300 }
301 }
302 }
303
304 //Video
305 if ( ! empty($_POST['video']['source'])){
306 //$video = tutor_utils()->sanitize_array($_POST['video']);
307 $video = tutor_utils()->array_get('video', $_POST);
308 update_post_meta($post_ID, '_video', $video);
309 }else{
310 delete_post_meta($post_ID, '_video');
311 }
312
313 /**
314 * Adding author to instructor automatically
315 */
316
317 $author_id = $post->post_author;
318 $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} ");
319 if ( ! $attached){
320 add_user_meta($author_id, '_tutor_instructor_course_id', $post_ID);
321 }
322
323 //Announcements
324 if ( ! wp_doing_ajax()) {
325 $announcement_title = tutor_utils()->avalue_dot( 'announcements.title', $_POST );
326 if ( ! empty( $announcement_title ) ) {
327 $title = sanitize_text_field( tutor_utils()->avalue_dot( 'announcements.title', $_POST ) );
328 $content = wp_kses_post( tutor_utils()->avalue_dot( 'announcements.content', $_POST ) );
329
330 $post_arr = array(
331 'post_type' => 'tutor_announcements',
332 'post_title' => $title,
333 'post_content' => $content,
334 'post_status' => 'publish',
335 'post_author' => get_current_user_id(),
336 'post_parent' => $post_ID,
337 );
338 wp_insert_post( $post_arr );
339 }
340 }
341
342 do_action( "tutor_save_course_after", $post_ID, $post);
343 }
344
345 /**
346 * Tutor add course topic
347 */
348 public function tutor_add_course_topic(){
349 if (empty($_POST['topic_title']) ) {
350 wp_send_json_error();
351 }
352 $course_id = (int) tutor_utils()->avalue_dot('tutor_topic_course_ID', $_POST);
353 $next_topic_order_id = tutor_utils()->get_next_topic_order_id($course_id);
354
355 $topic_title = sanitize_text_field( $_POST['topic_title'] );
356 $topic_summery = wp_kses_post( $_POST['topic_summery'] );
357
358 $post_arr = array(
359 'post_type' => 'topics',
360 'post_title' => $topic_title,
361 'post_content' => $topic_summery,
362 'post_status' => 'publish',
363 'post_author' => get_current_user_id(),
364 'post_parent' => $course_id,
365 'menu_order' => $next_topic_order_id,
366 );
367 $current_topic_id = wp_insert_post( $post_arr );
368
369 ob_start();
370 include tutor()->path.'views/metabox/course-contents.php';
371 $course_contents = ob_get_clean();
372
373 wp_send_json_success(array('course_contents' => $course_contents));
374 }
375
376 /**
377 * Update the topic
378 */
379 public function tutor_update_topic(){
380 $topic_id = (int) sanitize_text_field($_POST['topic_id']);
381 $topic_title = sanitize_text_field($_POST['topic_title']);
382 $topic_summery = wp_kses_post($_POST['topic_summery']);
383
384 $topic_attr = array(
385 'ID' => $topic_id,
386 'post_title' => $topic_title,
387 'post_content' => $topic_summery,
388 );
389 wp_update_post( $topic_attr );
390
391 wp_send_json_success(array('msg' => __('Topic has been updated', 'tutor') ));
392 }
393
394
395 /**
396 * @param $columns
397 *
398 * @return mixed
399 *
400 * Add Lesson column
401 */
402 public function add_column($columns){
403 $date_col = $columns['date'];
404 unset($columns['date']);
405 $columns['lessons'] = __('Lessons', 'tutor');
406 $columns['students'] = __('Students', 'tutor');
407 $columns['price'] = __('Price', 'tutor');
408 $columns['date'] = $date_col;
409
410 return $columns;
411 }
412
413 /**
414 * @param $column
415 * @param $post_id
416 *
417 */
418 public function custom_lesson_column($column, $post_id ){
419 if ($column === 'lessons'){
420 echo tutor_utils()->get_lesson_count_by_course($post_id);
421 }
422
423 if ($column === 'students'){
424 echo tutor_utils()->count_enrolled_users_by_course($post_id);
425 }
426
427 if ($column === 'price'){
428 $price = tutor_utils()->get_course_price($post_id);
429 if ($price){
430 $monetize_by = tutils()->get_option('monetize_by');
431 if (function_exists('wc_price') && $monetize_by === 'wc'){
432 echo '<span class="tutor-label-success">'.wc_price($price).'</span>';
433 }else{
434 echo '<span class="tutor-label-success">'.$price.'</span>';
435 }
436 }else{
437 echo 'free';
438 }
439 }
440 }
441
442
443 public function tutor_delete_topic(){
444 if (!isset($_GET[tutor()->nonce]) || !wp_verify_nonce($_GET[tutor()->nonce], tutor()->nonce_action)) {
445 exit();
446 }
447 if ( ! isset($_GET['topic_id'])){
448 exit();
449 }
450
451 global $wpdb;
452
453 $topic_id = (int) sanitize_text_field($_GET['topic_id']);
454 $wpdb->update(
455 $wpdb->posts,
456 array('post_parent' => 0),
457 array('post_parent' => $topic_id)
458 );
459
460 $wpdb->delete(
461 $wpdb->postmeta,
462 array('post_id' => $topic_id)
463 );
464
465 wp_delete_post($topic_id);
466 wp_safe_redirect(wp_get_referer());
467 }
468
469 public function tutor_delete_announcement(){
470 tutor_utils()->checking_nonce('get');
471
472 $announcement_id = (int) sanitize_text_field($_GET['topic_id']);
473
474 wp_delete_post($announcement_id);
475 wp_safe_redirect(wp_get_referer());
476 }
477
478 public function enroll_now(){
479
480 //Checking if action comes from Enroll form
481 if (tutor_utils()->array_get('tutor_course_action', $_POST) !== '_tutor_course_enroll_now' || ! isset($_POST['tutor_course_id']) ){
482 return;
483 }
484 //Checking Nonce
485 tutor_utils()->checking_nonce();
486
487 $user_id = get_current_user_id();
488 if ( ! $user_id){
489 exit(__('Please Sign In first', 'tutor'));
490 }
491
492 $course_id = (int) sanitize_text_field($_POST['tutor_course_id']);
493 $user_id = get_current_user_id();
494
495 /**
496 * TODO: need to check purchase information
497 */
498
499 $is_purchasable = tutor_utils()->is_course_purchasable($course_id);
500
501 /**
502 * If is is not purchasable, it's free, and enroll right now
503 *
504 * if purchasable, then process purchase.
505 *
506 * @since: v.1.0.0
507 */
508 if ($is_purchasable){
509 //process purchase
510
511 }else{
512 //Free enroll
513 tutor_utils()->do_enroll($course_id);
514 }
515
516 $referer_url = wp_get_referer();
517 wp_redirect($referer_url);
518 }
519
520 /**
521 *
522 * Mark complete completed
523 *
524 * @since v.1.0.0
525 */
526 public function mark_course_complete(){
527 if ( ! isset($_POST['tutor_action']) || $_POST['tutor_action'] !== 'tutor_complete_course' ){
528 return;
529 }
530 //Checking nonce
531 tutor_utils()->checking_nonce();
532
533 $user_id = get_current_user_id();
534
535 //TODO: need to show view if not signed_in
536 if ( ! $user_id){
537 die(__('Please Sign-In', 'tutor'));
538 }
539
540 $course_id = (int) sanitize_text_field($_POST['course_id']);
541
542 do_action('tutor_course_complete_before', $course_id);
543 /**
544 * Marking course completed at Comment
545 */
546
547 global $wpdb;
548
549 $date = date("Y-m-d H:i:s", tutor_time());
550
551 //Making sure that, hash is unique
552 do{
553 $hash = substr(md5(wp_generate_password(32).$date.$course_id.$user_id), 0, 16);
554 $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}' ");
555 }while($hasHash > 0);
556
557 $data = array(
558 'comment_post_ID' => $course_id,
559 'comment_author' => $user_id,
560 'comment_date' => $date,
561 'comment_date_gmt' => get_gmt_from_date($date),
562 'comment_content' => $hash, //Identification Hash
563 'comment_approved' => 'approved',
564 'comment_agent' => 'TutorLMSPlugin',
565 'comment_type' => 'course_completed',
566 'user_id' => $user_id,
567 );
568
569 $wpdb->insert($wpdb->comments, $data);
570
571 do_action('tutor_course_complete_after', $course_id);
572
573 wp_redirect(get_the_permalink($course_id));
574 }
575
576
577 public function tutor_load_instructors_modal(){
578 global $wpdb;
579
580 $course_id = (int) sanitize_text_field($_POST['course_id']);
581 $search_terms = sanitize_text_field(tutor_utils()->avalue_dot('search_terms', $_POST));
582
583 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
584
585 $instructors = array();
586
587
588 $not_in_sql = apply_filters('tutor_instructor_query_when_exists', " AND ID <1 ");
589
590 if ($saved_instructors){
591 $saved_instructors_ids = wp_list_pluck($saved_instructors, 'ID');
592 $instructor_not_in_ids = implode(',', $saved_instructors_ids);
593 $not_in_sql .= "AND ID NOT IN($instructor_not_in_ids) ";
594 }
595
596 $search_sql = '';
597 if ($search_terms){
598 $search_sql = "AND (user_login like '%{$search_terms}%' or user_nicename like '%{$search_terms}%' or display_name like '%{$search_terms}%') ";
599 }
600
601 $instructors = $wpdb->get_results("select ID, display_name from {$wpdb->users}
602 INNER JOIN {$wpdb->usermeta} ON ID = user_id AND meta_key = '_tutor_instructor_status' AND meta_value = 'approved'
603 WHERE 1=1 {$not_in_sql} {$search_sql} limit 10 ");
604
605 $output = '';
606 if (is_array($instructors) && count($instructors)){
607 $instructor_output = '';
608 foreach ($instructors as $instructor){
609 $instructor_output .= "<p><label><input type='radio' name='tutor_instructor_ids[]' value='{$instructor->ID}' > {$instructor->display_name} </label></p>";
610 }
611
612 $output .= apply_filters('tutor_course_instructors_html', $instructor_output, $instructors);
613
614 }else{
615 $output .= __('<p>No instructor available or you have already added maximum instructors</p>', 'tutor');
616 }
617
618
619 if ( ! defined('TUTOR_MT_VERSION')){
620 $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>';
621 }
622
623 wp_send_json_success(array('output' => $output));
624 }
625
626 public function tutor_add_instructors_to_course(){
627 $course_id = (int) sanitize_text_field($_POST['course_id']);
628 $instructor_ids = tutor_utils()->avalue_dot('tutor_instructor_ids', $_POST);
629
630 if (is_array($instructor_ids) && count($instructor_ids)){
631 foreach ($instructor_ids as $instructor_id){
632 add_user_meta($instructor_id, '_tutor_instructor_course_id', $course_id);
633 }
634 }
635
636 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
637 $output = '';
638
639 if ($saved_instructors){
640 foreach ($saved_instructors as $t){
641
642 $output .= '<div id="added-instructor-id-'.$t->ID.'" class="added-instructor-item added-instructor-item-'.$t->ID.'" data-instructor-id="'.$t->ID.'">
643 <span class="instructor-icon">'.get_avatar($t->ID, 30).'</span>
644 <span class="instructor-name"> '.$t->display_name.' </span>
645 <span class="instructor-control">
646 <a href="javascript:;" class="tutor-instructor-delete-btn"><i class="tutor-icon-line-cross"></i></a>
647 </span>
648 </div>';
649 }
650 }
651
652 wp_send_json_success(array('output' => $output));
653 }
654
655 public function detach_instructor_from_course(){
656 global $wpdb;
657
658 $instructor_id = (int) sanitize_text_field($_POST['instructor_id']);
659 $course_id = (int) sanitize_text_field($_POST['course_id']);
660
661 $wpdb->delete($wpdb->usermeta, array('user_id' => $instructor_id, 'meta_key' => '_tutor_instructor_course_id', 'meta_value' => $course_id) );
662 wp_send_json_success();
663 }
664
665 public function tutor_delete_dashboard_course(){
666 $course_id = intval(sanitize_text_field($_POST['course_id']));
667 wp_trash_post($course_id);
668 wp_send_json_success();
669 }
670
671
672 public function tutor_add_gutenberg_author($data , $postarr){
673 global $wpdb;
674
675 $courses_post_type = tutor()->course_post_type;
676 $post_type = tutils()->array_get('post_type', $postarr);
677
678 /*
679 $post_author = (int) tutor_utils()->avalue_dot('post_author', $data);
680
681 if ( ! $post_author){
682 $user_ID = (int) tutor_utils()->avalue_dot('user_ID', $postarr);
683 if ($user_ID){
684 $data['post_author'] = $user_ID;
685 }else{
686 $post_ID = (int) tutor_utils()->avalue_dot('ID', $postarr);
687 $post_author = (int) $wpdb->get_var("SELECT post_author FROM {$wpdb->posts} WHERE ID = {$post_ID} ");
688
689 $data['post_author'] = $post_author;
690 }
691 }*/
692
693 if ($courses_post_type === $post_type){
694 $post_ID = (int) tutor_utils()->avalue_dot('ID', $postarr);
695 $post_author = (int) $wpdb->get_var("SELECT post_author FROM {$wpdb->posts} WHERE ID = {$post_ID} ");
696
697 if ($post_author > 0){
698 $data['post_author'] = $post_author;
699 }else{
700 $data['post_author'] = get_current_user_id();
701 }
702 }
703
704 return $data;
705 }
706
707
708 /**
709 * @param $post_ID
710 * @param $postData
711 *
712 * Attach product during save course from the frontend course dashboard.
713 *
714 * @return string
715 *
716 * @since v.1.3.4
717 */
718 public function attach_product_with_course($post_ID, $postData){
719 $attached_product_id = tutor_utils()->get_course_product_id($post_ID);
720 $course_price = sanitize_text_field(tutor_utils()->array_get('course_price', $_POST));
721
722 if ( ! $course_price){
723 return;
724 }
725
726 $monetize_by = tutor_utils()->get_option('monetize_by');
727 $course = get_post($post_ID);
728
729 if ($monetize_by === 'wc'){
730
731 $is_update = false;
732 if ($attached_product_id){
733 $wc_product = get_post_meta($attached_product_id, '_product_version', true);
734 if ($wc_product){
735 $is_update = true;
736 }
737 }
738
739 if ($is_update){
740
741 $productObj = new \WC_Product($attached_product_id);
742 $productObj->set_price($course_price); // set product price
743 $productObj->set_regular_price($course_price); // set product regular price
744 $product_id = $productObj->save();
745
746 }else{
747
748 $productObj = new \WC_Product();
749 $productObj->set_name($course->post_title);
750 $productObj->set_status('publish');
751 $productObj->set_price($course_price); // set product price
752 $productObj->set_regular_price($course_price); // set product regular price
753
754 $product_id = $productObj->save();
755 if ($product_id) {
756 update_post_meta( $post_ID, '_tutor_course_product_id', $product_id );
757 //Mark product for woocommerce
758 update_post_meta( $product_id, '_virtual', 'yes' );
759 update_post_meta( $product_id, '_tutor_product', 'yes' );
760
761 $coursePostThumbnail = get_post_meta( $post_ID, '_thumbnail_id', true );
762 if ( $coursePostThumbnail ) {
763 set_post_thumbnail( $product_id, $coursePostThumbnail );
764 }
765 }
766 }
767
768 }elseif ($monetize_by === 'edd'){
769
770 $is_update = false;
771
772 if ($attached_product_id){
773 $edd_price = get_post_meta($attached_product_id, 'edd_price', true);
774 if ($edd_price){
775 $is_update = true;
776 }
777 }
778
779 if ($is_update){
780 //Update the product
781 update_post_meta( $attached_product_id, 'edd_price', $course_price );
782 }else{
783 //Create new product
784
785 $post_arr = array(
786 'post_type' => 'download',
787 'post_title' => $course->post_title,
788 'post_status' => 'publish',
789 'post_author' => get_current_user_id(),
790 );
791 $download_id = wp_insert_post( $post_arr );
792 if ($download_id ) {
793 //edd_price
794 update_post_meta( $download_id, 'edd_price', $course_price );
795
796 update_post_meta( $post_ID, '_tutor_course_product_id', $download_id );
797 //Mark product for EDD
798 update_post_meta( $download_id, '_tutor_product', 'yes' );
799
800 $coursePostThumbnail = get_post_meta( $post_ID, '_thumbnail_id', true );
801 if ( $coursePostThumbnail ) {
802 set_post_thumbnail( $download_id, $coursePostThumbnail );
803 }
804
805 }
806
807 }
808
809
810 }
811
812 }
813
814
815 /**
816 * Add Course level to course settings
817 * @since v.1.4.1
818 */
819 public function add_course_level_to_settings(){
820 include tutor()->path.'views/metabox/course-level-metabox.php';
821 }
822
823 /**
824 * Check if course starting
825 *
826 * @since v.1.4.8
827 */
828 public function tutor_lesson_load_before(){
829 $course_id = tutils()->get_course_id_by_content(get_the_ID());
830 $completed_lessons = tutor_utils()->get_completed_lesson_count_by_course($course_id);
831 if (is_user_logged_in()){
832 $is_course_started = get_post_meta($course_id, '_tutor_course_started', true);
833 if ( ! $completed_lessons && ! $is_course_started){
834 update_post_meta($course_id, '_tutor_course_started', tutor_time());
835 do_action('tutor/course/started', $course_id);
836 }
837 }
838 }
839
840 /**
841 * Add Course level to course settings
842 * @since v.1.4.8
843 */
844 public function course_elements_enable_disable(){
845 add_filter('tutor_course/single/completing-progress-bar', array($this, 'enable_disable_course_progress_bar') );
846 add_filter('tutor_course/single/material_includes', array($this, 'enable_disable_material_includes') );
847 add_filter('tutor_course/single/content', array($this, 'enable_disable_course_content') );
848 add_filter('tutor_course/single/benefits_html', array($this, 'enable_disable_course_benefits') );
849 add_filter('tutor_course/single/requirements_html', array($this, 'enable_disable_course_requirements') );
850 add_filter('tutor_course/single/audience_html', array($this, 'enable_disable_course_target_audience') );
851 add_filter('tutor_course/single/enrolled/nav_items', array($this, 'enable_disable_course_nav_items') );
852 }
853
854 /**
855 * Enable disable course progress bar
856 * @since v.1.4.8
857 */
858 public function enable_disable_course_progress_bar($html){
859 $disable_option = (bool) get_tutor_option('disable_course_progress_bar');
860 if($disable_option){
861 return '';
862 }
863 return $html;
864 }
865
866 /**
867 * Enable disable material includes
868 * @since v.1.4.8
869 */
870 public function enable_disable_material_includes($html){
871 $disable_option = (bool) get_tutor_option('disable_course_material');
872 if($disable_option){
873 return '';
874 }
875 return $html;
876 }
877
878 /**
879 * Enable disable course content
880 * @since v.1.4.8
881 */
882 public function enable_disable_course_content($html){
883 $disable_option = (bool) get_tutor_option('disable_course_description');
884 if($disable_option){
885 return '';
886 }
887 return $html;
888 }
889
890 /**
891 * Enable disable course benefits
892 * @since v.1.4.8
893 */
894 public function enable_disable_course_benefits($html){
895 $disable_option = (bool) get_tutor_option('disable_course_benefits');
896 if($disable_option){
897 return '';
898 }
899 return $html;
900 }
901
902 /**
903 * Enable disable course requirements
904 * @since v.1.4.8
905 */
906 public function enable_disable_course_requirements($html){
907 $disable_option = (bool) get_tutor_option('disable_course_requirements');
908 if($disable_option){
909 return '';
910 }
911 return $html;
912 }
913
914 /**
915 * Enable disable course target audience
916 * @since v.1.4.8
917 */
918 public function enable_disable_course_target_audience($html){
919 $disable_option = (bool) get_tutor_option('disable_course_target_audience');
920 if($disable_option){
921 return '';
922 }
923 return $html;
924 }
925
926 /**
927 * Enable disable course nav items
928 * @since v.1.4.8
929 */
930 public function enable_disable_course_nav_items($items){
931 $enable_q_and_a_on_course = (bool) get_tutor_option('enable_q_and_a_on_course');
932 $disable_course_announcements = (bool) get_tutor_option('disable_course_announcements');
933
934 if(! $enable_q_and_a_on_course){
935 if(tutils()->array_get('questions', $items)) {
936 unset($items['questions']);
937 }
938 }
939 if($disable_course_announcements){
940 if(tutils()->array_get('announcements', $items)) {
941 unset($items['announcements']);
942 }
943 }
944 return $items;
945 }
946
947 /**
948 * Filter product in shop page
949 * @since v.1.4.9
950 */
951 public function filter_product_in_shop_page(){
952 $hide_course_from_shop_page = (bool) get_tutor_option('hide_course_from_shop_page');
953 if(!$hide_course_from_shop_page){
954 return;
955 }
956 add_action('woocommerce_product_query', array($this, 'filter_woocommerce_product_query'));
957 add_filter('edd_downloads_query', array($this, 'filter_edd_downloads_query'), 10, 2);
958 add_action('pre_get_posts', array($this, 'filter_archive_meta_query'), 1);
959 }
960
961 /**
962 * Tutor product meta query
963 * @since v.1.4.9
964 */
965 public function tutor_product_meta_query(){
966 $meta_query = array(
967 'key' => '_tutor_product',
968 'compare' => 'NOT EXISTS'
969 );
970 return $meta_query;
971 }
972
973 /**
974 * Filter product in woocommerce shop page
975 * @since v.1.4.9
976 */
977 public function filter_woocommerce_product_query($wp_query){
978 $wp_query->set('meta_query', array($this->tutor_product_meta_query()));
979 return $wp_query;
980 }
981
982 /**
983 * Filter product in edd downloads shortcode page
984 * @since v.1.4.9
985 */
986 public function filter_edd_downloads_query($query){
987 $query['meta_query'][] = $this->tutor_product_meta_query();
988 return $query;
989 }
990
991 /**
992 * Filter product in edd downloads archive page
993 * @since v.1.4.9
994 */
995 public function filter_archive_meta_query($wp_query){
996 if(!is_admin() && $wp_query->is_archive && $wp_query->get('post_type') === 'download'){
997 $wp_query->set('meta_query', array($this->tutor_product_meta_query()));
998 }
999 return $wp_query;
1000 }
1001
1002 /**
1003 * @param $html
1004 * @return string
1005 *
1006 * Removed course price if already enrolled at single course
1007 *
1008 * @since v.1.5.8
1009 */
1010 public function remove_price_if_enrolled($html){
1011 $should_removed = apply_filters('should_remove_price_if_enrolled', true);
1012
1013 if ($should_removed){
1014 $course_id = get_the_ID();
1015 $enrolled = tutils()->is_enrolled($course_id);
1016 if ($enrolled){
1017 $html = '';
1018 }
1019 }
1020 return $html;
1021 }
1022
1023 }