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