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