PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 1.4.9
Tutor LMS – eLearning and online course solution v1.4.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 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
982 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 global $wpdb;
677
678 $post_ID = (int) tutor_utils()->avalue_dot('ID', $postarr);
679 $post_author = (int) $wpdb->get_var("SELECT post_author FROM {$wpdb->posts} WHERE ID = {$post_ID} ");
680
681 $data['post_author'] = $post_author;
682 }
683 }
684
685 return $data;
686 }
687
688
689 /**
690 * @param $post_ID
691 * @param $postData
692 *
693 * Attach product during save course from the frontend course dashboard.
694 *
695 * @return string
696 *
697 * @since v.1.3.4
698 */
699 public function attach_product_with_course($post_ID, $postData){
700 $attached_product_id = tutor_utils()->get_course_product_id($post_ID);
701 $course_price = sanitize_text_field(tutor_utils()->array_get('course_price', $_POST));
702
703 if ( ! $course_price){
704 return;
705 }
706
707 $monetize_by = tutor_utils()->get_option('monetize_by');
708 $course = get_post($post_ID);
709
710 if ($monetize_by === 'wc'){
711
712 $is_update = false;
713 if ($attached_product_id){
714 $wc_product = get_post_meta($attached_product_id, '_product_version', true);
715 if ($wc_product){
716 $is_update = true;
717 }
718 }
719
720 if ($is_update){
721
722 $productObj = new \WC_Product($attached_product_id);
723 $productObj->set_price($course_price); // set product price
724 $productObj->set_regular_price($course_price); // set product regular price
725 $product_id = $productObj->save();
726
727 }else{
728
729 $productObj = new \WC_Product();
730 $productObj->set_name($course->post_title);
731 $productObj->set_status('publish');
732 $productObj->set_price($course_price); // set product price
733 $productObj->set_regular_price($course_price); // set product regular price
734
735 $product_id = $productObj->save();
736 if ($product_id) {
737 update_post_meta( $post_ID, '_tutor_course_product_id', $product_id );
738 //Mark product for woocommerce
739 update_post_meta( $product_id, '_virtual', 'yes' );
740 update_post_meta( $product_id, '_tutor_product', 'yes' );
741
742 $coursePostThumbnail = get_post_meta( $post_ID, '_thumbnail_id', true );
743 if ( $coursePostThumbnail ) {
744 set_post_thumbnail( $product_id, $coursePostThumbnail );
745 }
746 }
747 }
748
749 }elseif ($monetize_by === 'edd'){
750
751 $is_update = false;
752
753 if ($attached_product_id){
754 $edd_price = get_post_meta($attached_product_id, 'edd_price', true);
755 if ($edd_price){
756 $is_update = true;
757 }
758 }
759
760 if ($is_update){
761 //Update the product
762 update_post_meta( $attached_product_id, 'edd_price', $course_price );
763 }else{
764 //Create new product
765
766 $post_arr = array(
767 'post_type' => 'download',
768 'post_title' => $course->post_title,
769 'post_status' => 'publish',
770 'post_author' => get_current_user_id(),
771 );
772 $download_id = wp_insert_post( $post_arr );
773 if ($download_id ) {
774 //edd_price
775 update_post_meta( $download_id, 'edd_price', $course_price );
776
777 update_post_meta( $post_ID, '_tutor_course_product_id', $download_id );
778 //Mark product for EDD
779 update_post_meta( $download_id, '_tutor_product', 'yes' );
780
781 $coursePostThumbnail = get_post_meta( $post_ID, '_thumbnail_id', true );
782 if ( $coursePostThumbnail ) {
783 set_post_thumbnail( $download_id, $coursePostThumbnail );
784 }
785
786 }
787
788 }
789
790
791 }
792
793 }
794
795
796 /**
797 * Add Course level to course settings
798 * @since v.1.4.1
799 */
800 public function add_course_level_to_settings(){
801 include tutor()->path.'views/metabox/course-level-metabox.php';
802 }
803
804 /**
805 * Check if course starting
806 *
807 * @since v.1.4.8
808 */
809 public function tutor_lesson_load_before(){
810 $course_id = tutils()->get_course_id_by_content(get_the_ID());
811 $completed_lessons = tutor_utils()->get_completed_lesson_count_by_course($course_id);
812 if (is_user_logged_in()){
813 $is_course_started = get_post_meta($course_id, '_tutor_course_started', true);
814 if ( ! $completed_lessons && ! $is_course_started){
815 update_post_meta($course_id, '_tutor_course_started', tutor_time());
816 do_action('tutor/course/started', $course_id);
817 }
818 }
819 }
820
821 /**
822 * Add Course level to course settings
823 * @since v.1.4.8
824 */
825 public function course_elements_enable_disable(){
826 add_filter('tutor_course/single/completing-progress-bar', array($this, 'enable_disable_course_progress_bar') );
827 add_filter('tutor_course/single/material_includes', array($this, 'enable_disable_material_includes') );
828 add_filter('tutor_course/single/content', array($this, 'enable_disable_course_content') );
829 add_filter('tutor_course/single/benefits_html', array($this, 'enable_disable_course_benefits') );
830 add_filter('tutor_course/single/requirements_html', array($this, 'enable_disable_course_requirements') );
831 add_filter('tutor_course/single/audience_html', array($this, 'enable_disable_course_target_audience') );
832 add_filter('tutor_course/single/enrolled/nav_items', array($this, 'enable_disable_course_nav_items') );
833 }
834
835 /**
836 * Enable disable course progress bar
837 * @since v.1.4.8
838 */
839 public function enable_disable_course_progress_bar($html){
840 $disable_option = (bool) get_tutor_option('disable_course_progress_bar');
841 if($disable_option){
842 return '';
843 }
844 return $html;
845 }
846
847 /**
848 * Enable disable material includes
849 * @since v.1.4.8
850 */
851 public function enable_disable_material_includes($html){
852 $disable_option = (bool) get_tutor_option('disable_course_material');
853 if($disable_option){
854 return '';
855 }
856 return $html;
857 }
858
859 /**
860 * Enable disable course content
861 * @since v.1.4.8
862 */
863 public function enable_disable_course_content($html){
864 $disable_option = (bool) get_tutor_option('disable_course_description');
865 if($disable_option){
866 return '';
867 }
868 return $html;
869 }
870
871 /**
872 * Enable disable course benefits
873 * @since v.1.4.8
874 */
875 public function enable_disable_course_benefits($html){
876 $disable_option = (bool) get_tutor_option('disable_course_benefits');
877 if($disable_option){
878 return '';
879 }
880 return $html;
881 }
882
883 /**
884 * Enable disable course requirements
885 * @since v.1.4.8
886 */
887 public function enable_disable_course_requirements($html){
888 $disable_option = (bool) get_tutor_option('disable_course_requirements');
889 if($disable_option){
890 return '';
891 }
892 return $html;
893 }
894
895 /**
896 * Enable disable course target audience
897 * @since v.1.4.8
898 */
899 public function enable_disable_course_target_audience($html){
900 $disable_option = (bool) get_tutor_option('disable_course_target_audience');
901 if($disable_option){
902 return '';
903 }
904 return $html;
905 }
906
907 /**
908 * Enable disable course nav items
909 * @since v.1.4.8
910 */
911 public function enable_disable_course_nav_items($items){
912 $enable_q_and_a_on_course = (bool) get_tutor_option('enable_q_and_a_on_course');
913 $disable_course_announcements = (bool) get_tutor_option('disable_course_announcements');
914
915 if(! $enable_q_and_a_on_course){
916 if(tutils()->array_get('questions', $items)) {
917 unset($items['questions']);
918 }
919 }
920 if($disable_course_announcements){
921 if(tutils()->array_get('announcements', $items)) {
922 unset($items['announcements']);
923 }
924 }
925 return $items;
926 }
927
928 /**
929 * Filter product in shop page
930 * @since v.1.4.9
931 */
932 public function filter_product_in_shop_page(){
933 $hide_course_from_shop_page = (bool) get_tutor_option('hide_course_from_shop_page');
934 if(!$hide_course_from_shop_page){
935 return;
936 }
937 add_action('woocommerce_product_query', array($this, 'filter_woocommerce_product_query'));
938 add_filter('edd_downloads_query', array($this, 'filter_edd_downloads_query'), 10, 2);
939 add_action('pre_get_posts', array($this, 'filter_archive_meta_query'), 1);
940 }
941
942 /**
943 * Tutor product meta query
944 * @since v.1.4.9
945 */
946 public function tutor_product_meta_query(){
947 $meta_query = array(
948 'key' => '_tutor_product',
949 'compare' => 'NOT EXISTS'
950 );
951 return $meta_query;
952 }
953
954 /**
955 * Filter product in woocommerce shop page
956 * @since v.1.4.9
957 */
958 public function filter_woocommerce_product_query($wp_query){
959 $wp_query->set('meta_query', array($this->tutor_product_meta_query()));
960 return $wp_query;
961 }
962
963 /**
964 * Filter product in edd downloads shortcode page
965 * @since v.1.4.9
966 */
967 public function filter_edd_downloads_query($query){
968 $query['meta_query'][] = $this->tutor_product_meta_query();
969 return $query;
970 }
971
972 /**
973 * Filter product in edd downloads archive page
974 * @since v.1.4.9
975 */
976 public function filter_archive_meta_query($wp_query){
977 if(!is_admin() && $wp_query->is_archive && $wp_query->get('post_type') === 'download'){
978 $wp_query->set('meta_query', array($this->tutor_product_meta_query()));
979 }
980 return $wp_query;
981 }
982 }