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