PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 1.3.1
Tutor LMS – eLearning and online course solution v1.3.1
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 7 years ago Admin.php 7 years ago Ajax.php 7 years ago Assets.php 7 years ago Course.php 7 years ago Course_Widget.php 7 years ago Gutenberg.php 7 years ago Instructor.php 7 years ago Instructors_List.php 7 years ago Lesson.php 7 years ago Options.php 7 years ago Post_types.php 7 years ago Q_and_A.php 7 years ago Question.php 7 years ago Question_Answers_List.php 7 years ago Quiz.php 7 years ago Quiz_Attempts_List.php 7 years ago Rewrite_Rules.php 7 years ago Shortcode.php 7 years ago Student.php 7 years ago Students_List.php 7 years ago Taxonomies.php 7 years ago Template.php 7 years ago Theme_Compatibility.php 7 years ago Tools.php 7 years ago Tutor.php 7 years ago TutorEDD.php 7 years ago Tutor_Base.php 7 years ago Tutor_List_Table.php 7 years ago User.php 7 years ago Utils.php 7 years ago Video_Stream.php 7 years ago Withdraw.php 7 years ago Withdraw_Requests_List.php 7 years ago WooCommerce.php 7 years ago
Course.php
539 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 /**
39 * Registering metabox
40 */
41 public function register_meta_box(){
42 $coursePostType = tutor()->course_post_type;
43 $course_marketplace = tutor_utils()->get_option('enable_course_marketplace');
44
45 add_meta_box( 'tutor-course-topics', __( 'Course Builder', 'tutor' ), array($this, 'course_meta_box'), $coursePostType );
46 add_meta_box( 'tutor-course-additional-data', __( 'Additional Data', 'tutor' ), array($this, 'course_additional_data_meta_box'), $coursePostType );
47 add_meta_box( 'tutor-course-videos', __( 'Video', 'tutor' ), array($this, 'video_metabox'), $coursePostType );
48
49 if ($course_marketplace) {
50 add_meta_box( 'tutor-instructors', __( 'Instructors', 'tutor' ), array( $this, 'instructors_metabox' ), $coursePostType );
51 }
52 add_meta_box( 'tutor-announcements', __( 'Announcements', 'tutor' ), array($this, 'announcements_metabox'), $coursePostType );
53 }
54 public function course_meta_box(){
55 include tutor()->path.'views/metabox/course-topics.php';
56 }
57 public function course_additional_data_meta_box(){
58 include tutor()->path.'views/metabox/course-additional-data.php';
59 }
60 public function video_metabox(){
61 include tutor()->path.'views/metabox/video-metabox.php';
62 }
63
64 public function announcements_metabox(){
65 include tutor()->path.'views/metabox/announcements-metabox.php';
66 }
67
68 public function instructors_metabox(){
69 include tutor()->path . 'views/metabox/instructors-metabox.php';
70 }
71
72 /**
73 * @param $post_ID
74 *
75 * Insert Topic and attached it with Course
76 */
77 public function save_course_meta($post_ID, $post){
78 global $wpdb;
79 /**
80 * Insert Topic
81 */
82 if ( ! empty($_POST['topic_title'])) {
83 $topic_title = sanitize_text_field( $_POST['topic_title'] );
84 $topic_summery = wp_kses_post( $_POST['topic_summery'] );
85
86 $post_arr = array(
87 'post_type' => 'topics',
88 'post_title' => $topic_title,
89 'post_content' => $topic_summery,
90 'post_status' => 'publish',
91 'post_author' => get_current_user_id(),
92 'post_parent' => $post_ID,
93 );
94 wp_insert_post( $post_arr );
95 }
96
97 //Course Duration
98 if ( ! empty($_POST['course_duration'])){
99 $video = tutor_utils()->sanitize_array($_POST['course_duration']);
100 update_post_meta($post_ID, '_course_duration', $video);
101 }
102
103 if ( ! empty($_POST['course_level'])){
104 $course_level = sanitize_text_field($_POST['course_level']);
105 update_post_meta($post_ID, '_tutor_course_level', $course_level);
106 }
107
108 if ( ! empty($_POST['course_benefits'])){
109 $course_benefits = wp_kses_post($_POST['course_benefits']);
110 update_post_meta($post_ID, '_tutor_course_benefits', $course_benefits);
111 }
112
113 if ( ! empty($_POST['course_requirements'])){
114 $requirements = wp_kses_post($_POST['course_requirements']);
115 update_post_meta($post_ID, '_tutor_course_requirements', $requirements);
116 }
117
118 if ( ! empty($_POST['course_target_audience'])){
119 $target_audience = wp_kses_post($_POST['course_target_audience']);
120 update_post_meta($post_ID, '_tutor_course_target_audience', $target_audience);
121 }
122
123 if ( ! empty($_POST['course_material_includes'])){
124 $material_includes = wp_kses_post($_POST['course_material_includes']);
125 update_post_meta($post_ID, '_tutor_course_material_includes', $material_includes);
126 }
127 /**
128 * Sorting Topics and lesson
129 */
130 if ( ! empty($_POST['tutor_topics_lessons_sorting'])){
131 $new_order = sanitize_text_field(stripslashes($_POST['tutor_topics_lessons_sorting']));
132 $order = json_decode($new_order, true);
133
134 if (is_array($order) && count($order)){
135 $i = 0;
136 foreach ($order as $topic ){
137 $i++;
138 $wpdb->update(
139 $wpdb->posts,
140 array('menu_order' => $i),
141 array('ID' => $topic['topic_id'])
142 );
143
144 /**
145 * Removing All lesson with topic
146 */
147
148 $wpdb->update(
149 $wpdb->posts,
150 array('post_parent' => 0),
151 array('post_parent' => $topic['topic_id'])
152 );
153
154 /**
155 * Lesson Attaching with topic ID
156 * sorting lesson
157 */
158 if (isset($topic['lesson_ids'])){
159 $lesson_ids = $topic['lesson_ids'];
160 }else{
161 $lesson_ids = array();
162 }
163 if (count($lesson_ids)){
164 foreach ($lesson_ids as $lesson_key => $lesson_id ){
165 $wpdb->update(
166 $wpdb->posts,
167 array('post_parent' => $topic['topic_id'], 'menu_order' => $lesson_key),
168 array('ID' => $lesson_id)
169 );
170 }
171 }
172 }
173 }
174 }
175
176
177 //Video
178 if ( ! empty($_POST['video']['source'])){
179 $video = tutor_utils()->sanitize_array($_POST['video']);
180 update_post_meta($post_ID, '_video', $video);
181 }
182
183 /**
184 * Adding author to instructor automatically
185 */
186
187 $author_id = $post->post_author;
188 $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} ");
189 if ( ! $attached){
190 add_user_meta($author_id, '_tutor_instructor_course_id', $post_ID);
191 }
192
193 //Announcements
194 $announcement_title = tutor_utils()->avalue_dot('announcements.title', $_POST );
195 if ( ! empty($announcement_title)){
196 $title = sanitize_text_field(tutor_utils()->avalue_dot('announcements.title', $_POST ));
197 $content = wp_kses_post(tutor_utils()->avalue_dot('announcements.content', $_POST ));
198
199 $post_arr = array(
200 'post_type' => 'tutor_announcements',
201 'post_title' => $title,
202 'post_content' => $content,
203 'post_status' => 'publish',
204 'post_author' => get_current_user_id(),
205 'post_parent' => $post_ID,
206 );
207 wp_insert_post( $post_arr );
208 }
209 }
210
211 /**
212 * Tutor add course topic
213 */
214 public function tutor_add_course_topic(){
215 if (empty($_POST['topic_title'])) {
216 wp_send_json_error();
217 }
218 $course_id = (int) tutor_utils()->avalue_dot('tutor_topic_course_ID', $_POST);
219 $next_topic_order_id = tutor_utils()->get_next_topic_order_id($course_id);
220
221 $topic_title = sanitize_text_field( $_POST['topic_title'] );
222 $topic_summery = wp_kses_post( $_POST['topic_summery'] );
223
224 $post_arr = array(
225 'post_type' => 'topics',
226 'post_title' => $topic_title,
227 'post_content' => $topic_summery,
228 'post_status' => 'publish',
229 'post_author' => get_current_user_id(),
230 'post_parent' => $course_id,
231 'menu_order' => $next_topic_order_id,
232 );
233 $current_topic_id = wp_insert_post( $post_arr );
234
235 ob_start();
236 include tutor()->path.'views/metabox/course-contents.php';
237 $course_contents = ob_get_clean();
238
239 wp_send_json_success(array('course_contents' => $course_contents));
240 }
241
242 /**
243 * Update the topic
244 */
245 public function tutor_update_topic(){
246 $topic_id = (int) sanitize_text_field($_POST['topic_id']);
247 $topic_title = sanitize_text_field($_POST['topic_title']);
248 $topic_summery = wp_kses_post($_POST['topic_summery']);
249
250 $topic_attr = array(
251 'ID' => $topic_id,
252 'post_title' => $topic_title,
253 'post_content' => $topic_summery,
254 );
255 wp_update_post( $topic_attr );
256
257 wp_send_json_success(array('msg' => __('Topic has been updated', 'tutor') ));
258 }
259
260
261 /**
262 * @param $columns
263 *
264 * @return mixed
265 *
266 * Add Lesson column
267 */
268
269 public function add_column($columns){
270 $date_col = $columns['date'];
271 unset($columns['date']);
272 $columns['lessons'] = __('Lessons', 'tutor');
273 $columns['students'] = __('Students', 'tutor');
274 $columns['price'] = __('Price', 'tutor');
275 $columns['date'] = $date_col;
276
277 return $columns;
278 }
279
280 /**
281 * @param $column
282 * @param $post_id
283 *
284 */
285 public function custom_lesson_column($column, $post_id ){
286 if ($column === 'lessons'){
287 echo tutor_utils()->get_lesson_count_by_course($post_id);
288 }
289
290 if ($column === 'students'){
291 echo tutor_utils()->count_enrolled_users_by_course($post_id);
292 }
293
294 if ($column === 'price'){
295 $price = tutor_utils()->get_course_price($post_id);
296
297 if ($price){
298 if (function_exists('wc_price')){
299 echo '<span class="tutor-label-success">'.wc_price($price).'</span>';
300 }else{
301 echo '<span class="tutor-label-success">'.$price.'</span>';
302 }
303 }else{
304 echo 'free';
305 }
306 }
307 }
308
309
310 public function tutor_delete_topic(){
311 if (!isset($_GET[tutor()->nonce]) || !wp_verify_nonce($_GET[tutor()->nonce], tutor()->nonce_action)) {
312 exit();
313 }
314 if ( ! isset($_GET['topic_id'])){
315 exit();
316 }
317
318 global $wpdb;
319
320 $topic_id = (int) sanitize_text_field($_GET['topic_id']);
321 $wpdb->update(
322 $wpdb->posts,
323 array('post_parent' => 0),
324 array('post_parent' => $topic_id)
325 );
326
327 $wpdb->delete(
328 $wpdb->postmeta,
329 array('post_id' => $topic_id)
330 );
331
332 wp_delete_post($topic_id);
333 wp_safe_redirect(wp_get_referer());
334 }
335
336 public function tutor_delete_announcement(){
337 tutor_utils()->checking_nonce('get');
338
339 $announcement_id = (int) sanitize_text_field($_GET['topic_id']);
340
341 wp_delete_post($announcement_id);
342 wp_safe_redirect(wp_get_referer());
343 }
344
345 public function enroll_now(){
346 //Checking if action comes from Enroll form
347 if ( ! isset($_POST['tutor_course_action']) || $_POST['tutor_course_action'] !== '_tutor_course_enroll_now' || ! isset($_POST['tutor_course_id']) ){
348 return;
349 }
350 //Checking Nonce
351 tutor_utils()->checking_nonce();
352
353 $user_id = get_current_user_id();
354 if ( ! $user_id){
355 exit(__('Please Sign In first', 'tutor'));
356 }
357
358 $course_id = (int) sanitize_text_field($_POST['tutor_course_id']);
359 $user_id = get_current_user_id();
360
361 /**
362 * TODO: need to check purchase information
363 */
364
365 $is_purchasable = tutor_utils()->is_course_purchasable($course_id);
366
367 /**
368 * If is is not purchasable, it's free, and enroll right now
369 *
370 * if purchasable, then process purchase.
371 *
372 * @since: v.1.0.0
373 */
374 if ($is_purchasable){
375 //process purchase
376
377 }else{
378 //Free enroll
379 tutor_utils()->do_enroll($course_id);
380 }
381
382 $referer_url = wp_get_referer();
383 wp_redirect($referer_url);
384 }
385
386 /**
387 *
388 * Mark complete completed
389 *
390 * @since v.1.0.0
391 */
392 public function mark_course_complete(){
393 if ( ! isset($_POST['tutor_action']) || $_POST['tutor_action'] !== 'tutor_complete_course' ){
394 return;
395 }
396 //Checking nonce
397 tutor_utils()->checking_nonce();
398
399 $user_id = get_current_user_id();
400
401 //TODO: need to show view if not signed_in
402 if ( ! $user_id){
403 die(__('Please Sign-In', 'tutor'));
404 }
405
406 $course_id = (int) sanitize_text_field($_POST['course_id']);
407
408 do_action('tutor_course_complete_before', $course_id);
409 /**
410 * Marking course completed at Comment
411 */
412
413 global $wpdb;
414
415 $date = date("Y-m-d H:i:s");
416
417 //Making sure that, hash is unique
418 do{
419 $hash = substr(md5(wp_generate_password(32).$date.$course_id.$user_id), 0, 16);
420 $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}' ");
421 }while($hasHash > 0);
422
423 $data = array(
424 'comment_post_ID' => $course_id,
425 'comment_author' => $user_id,
426 'comment_date' => $date,
427 'comment_date_gmt' => get_gmt_from_date($date),
428 'comment_content' => $hash, //Identification Hash
429 'comment_approved' => 'approved',
430 'comment_agent' => 'TutorLMSPlugin',
431 'comment_type' => 'course_completed',
432 'user_id' => $user_id,
433 );
434
435 $wpdb->insert($wpdb->comments, $data);
436
437 do_action('tutor_course_complete_after', $course_id);
438
439 wp_redirect(get_the_permalink($course_id));
440 }
441
442
443 public function tutor_load_instructors_modal(){
444 global $wpdb;
445
446 $course_id = (int) sanitize_text_field($_POST['course_id']);
447 $search_terms = sanitize_text_field(tutor_utils()->avalue_dot('search_terms', $_POST));
448
449 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
450
451 $instructors = array();
452
453
454 $not_in_sql = apply_filters('tutor_instructor_query_when_exists', " AND ID <1 ");
455
456 if ($saved_instructors){
457 $saved_instructors_ids = wp_list_pluck($saved_instructors, 'ID');
458 $instructor_not_in_ids = implode(',', $saved_instructors_ids);
459 $not_in_sql .= "AND ID NOT IN($instructor_not_in_ids) ";
460 }
461
462 $search_sql = '';
463 if ($search_terms){
464 $search_sql = "AND (user_login like '%{$search_terms}%' or user_nicename like '%{$search_terms}%' or display_name like '%{$search_terms}%') ";
465 }
466
467 $instructors = $wpdb->get_results("select ID, display_name from {$wpdb->users}
468 INNER JOIN {$wpdb->usermeta} ON ID = user_id AND meta_key = '_tutor_instructor_status' AND meta_value = 'approved'
469 WHERE 1=1 {$not_in_sql} {$search_sql} limit 10 ");
470
471 $output = '';
472 if (is_array($instructors) && count($instructors)){
473 $instructor_output = '';
474 foreach ($instructors as $instructor){
475 $instructor_output .= "<p><label><input type='radio' name='tutor_instructor_ids[]' value='{$instructor->ID}' > {$instructor->display_name} </label></p>";
476 }
477
478 $output .= apply_filters('tutor_course_instructors_html', $instructor_output, $instructors);
479 $output .= '<p class="quiz-search-suggest-text">'.__('Search to get the specific instructors', 'tutor').'</p>';
480
481 }else{
482 $output .= __('No instructor available or you have already added maximum instructors', 'tutor');
483 }
484
485
486 if ( ! defined('TUTOR_MT_VERSION')){
487 $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>';
488 }
489
490 wp_send_json_success(array('output' => $output));
491 }
492
493 public function tutor_add_instructors_to_course(){
494 $course_id = (int) sanitize_text_field($_POST['course_id']);
495 $instructor_ids = tutor_utils()->avalue_dot('tutor_instructor_ids', $_POST);
496
497 if (is_array($instructor_ids) && count($instructor_ids)){
498 foreach ($instructor_ids as $instructor_id){
499 add_user_meta($instructor_id, '_tutor_instructor_course_id', $course_id);
500 }
501 }
502
503 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
504 $output = '';
505
506 if ($saved_instructors){
507 foreach ($saved_instructors as $t){
508
509 $output .= '<div id="added-instructor-id-'.$t->ID.'" class="added-instructor-item added-instructor-item-'.$t->ID.'" data-instructor-id="'.$t->ID.'">
510 <span class="instructor-icon">'.get_avatar($t->ID, 30).'</span>
511 <span class="instructor-name"> '.$t->display_name.' </span>
512 <span class="instructor-control">
513 <a href="javascript:;" class="tutor-instructor-delete-btn"><i class="tutor-icon-garbage"></i></a>
514 </span>
515 </div>';
516 }
517 }
518
519 wp_send_json_success(array('output' => $output));
520 }
521
522 public function detach_instructor_from_course(){
523 global $wpdb;
524
525 $instructor_id = (int) sanitize_text_field($_POST['instructor_id']);
526 $course_id = (int) sanitize_text_field($_POST['course_id']);
527
528 $wpdb->delete($wpdb->usermeta, array('user_id' => $instructor_id, 'meta_key' => '_tutor_instructor_course_id', 'meta_value' => $course_id) );
529 wp_send_json_success();
530 }
531
532 public function tutor_delete_dashboard_course(){
533 $course_id = intval(sanitize_text_field($_POST['course_id']));
534 wp_trash_post($course_id);
535 wp_send_json_success();
536 }
537
538
539 }