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