PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 1.0.0
Tutor LMS – eLearning and online course solution v1.0.0
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
508 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'));
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){
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 //Announcements
174 $announcement_title = tutor_utils()->avalue_dot('announcements.title', $_POST );
175 if ( ! empty($announcement_title)){
176 $title = sanitize_text_field(tutor_utils()->avalue_dot('announcements.title', $_POST ));
177 $content = wp_kses_post(tutor_utils()->avalue_dot('announcements.content', $_POST ));
178
179 $post_arr = array(
180 'post_type' => 'tutor_announcements',
181 'post_title' => $title,
182 'post_content' => $content,
183 'post_status' => 'publish',
184 'post_author' => get_current_user_id(),
185 'post_parent' => $post_ID,
186 );
187 wp_insert_post( $post_arr );
188 }
189 }
190
191 /**
192 * Tutor add course topic
193 */
194 public function tutor_add_course_topic(){
195 if (empty($_POST['topic_title'])) {
196 wp_send_json_error();
197 }
198 $course_id = (int) tutor_utils()->avalue_dot('tutor_topic_course_ID', $_POST);
199 $next_topic_order_id = tutor_utils()->get_next_topic_order_id($course_id);
200
201 $topic_title = sanitize_text_field( $_POST['topic_title'] );
202 $topic_summery = wp_kses_post( $_POST['topic_summery'] );
203
204 $post_arr = array(
205 'post_type' => 'topics',
206 'post_title' => $topic_title,
207 'post_content' => $topic_summery,
208 'post_status' => 'publish',
209 'post_author' => get_current_user_id(),
210 'post_parent' => $course_id,
211 'menu_order' => $next_topic_order_id,
212 );
213 $current_topic_id = wp_insert_post( $post_arr );
214
215 ob_start();
216 include tutor()->path.'views/metabox/course-contents.php';
217 $course_contents = ob_get_clean();
218
219 wp_send_json_success(array('course_contents' => $course_contents));
220 }
221
222 /**
223 * Update the topic
224 */
225 public function tutor_update_topic(){
226 $topic_id = (int) sanitize_text_field($_POST['topic_id']);
227 $topic_title = sanitize_text_field($_POST['topic_title']);
228 $topic_summery = wp_kses_post($_POST['topic_summery']);
229
230 $topic_attr = array(
231 'ID' => $topic_id,
232 'post_title' => $topic_title,
233 'post_content' => $topic_summery,
234 );
235 wp_update_post( $topic_attr );
236
237 wp_send_json_success(array('msg' => __('Topic has been updated', 'tutor') ));
238 }
239
240
241 /**
242 * @param $columns
243 *
244 * @return mixed
245 *
246 * Add Lesson column
247 */
248
249 public function add_column($columns){
250 $date_col = $columns['date'];
251 unset($columns['date']);
252 $columns['lessons'] = __('Lessons', 'tutor');
253 $columns['students'] = __('Students', 'tutor');
254 $columns['price'] = __('Price', 'tutor');
255 $columns['date'] = $date_col;
256
257 return $columns;
258 }
259
260 /**
261 * @param $column
262 * @param $post_id
263 *
264 */
265 public function custom_lesson_column($column, $post_id ){
266 if ($column === 'lessons'){
267 echo tutor_utils()->get_lesson_count_by_course($post_id);
268 }
269
270 if ($column === 'students'){
271 echo tutor_utils()->count_enrolled_users_by_course($post_id);
272 }
273
274 if ($column === 'price'){
275 $price = tutor_utils()->get_course_price($post_id);
276
277 if ($price){
278 if (function_exists('wc_price')){
279 echo '<span class="tutor-label-success">'.wc_price($price).'</span>';
280 }else{
281 echo '<span class="tutor-label-success">'.$price.'</span>';
282 }
283 }else{
284 echo 'free';
285 }
286 }
287 }
288
289
290 public function tutor_delete_topic(){
291 if (!isset($_GET[tutor()->nonce]) || !wp_verify_nonce($_GET[tutor()->nonce], tutor()->nonce_action)) {
292 exit();
293 }
294 if ( ! isset($_GET['topic_id'])){
295 exit();
296 }
297
298 global $wpdb;
299
300 $topic_id = (int) sanitize_text_field($_GET['topic_id']);
301 $wpdb->update(
302 $wpdb->posts,
303 array('post_parent' => 0),
304 array('post_parent' => $topic_id)
305 );
306
307 $wpdb->delete(
308 $wpdb->postmeta,
309 array('post_id' => $topic_id)
310 );
311
312 wp_delete_post($topic_id);
313 wp_safe_redirect(wp_get_referer());
314 }
315
316 public function tutor_delete_announcement(){
317 tutor_utils()->checking_nonce('get');
318
319 $announcement_id = (int) sanitize_text_field($_GET['topic_id']);
320
321 wp_delete_post($announcement_id);
322 wp_safe_redirect(wp_get_referer());
323 }
324
325 public function enroll_now(){
326 //Checking if action comes from Enroll form
327 if ( ! isset($_POST['tutor_course_action']) || $_POST['tutor_course_action'] !== '_tutor_course_enroll_now' || ! isset($_POST['tutor_course_id']) ){
328 return;
329 }
330 //Checking Nonce
331 tutor_utils()->checking_nonce();
332
333 $user_id = get_current_user_id();
334 if ( ! $user_id){
335 exit(__('Please Sign In first', 'tutor'));
336 }
337
338 $course_id = (int) sanitize_text_field($_POST['tutor_course_id']);
339 $user_id = get_current_user_id();
340
341 /**
342 * TODO: need to check purchase information
343 */
344
345 $is_purchasable = tutor_utils()->is_course_purchasable($course_id);
346
347 /**
348 * If is is not purchasable, it's free, and enroll right now
349 *
350 * if purchasable, then process purchase.
351 *
352 * @since: v.1.0.0
353 */
354 if ($is_purchasable){
355 //process purchase
356
357 }else{
358 //Free enroll
359 tutor_utils()->do_enroll($course_id);
360 }
361
362 $referer_url = wp_get_referer();
363 wp_redirect($referer_url);
364 }
365
366 /**
367 *
368 * Mark complete completed
369 *
370 * @since v.1.0.0
371 */
372 public function mark_course_complete(){
373 if ( ! isset($_POST['tutor_action']) || $_POST['tutor_action'] !== 'tutor_complete_course' ){
374 return;
375 }
376 //Checking nonce
377 tutor_utils()->checking_nonce();
378
379 $user_id = get_current_user_id();
380
381 //TODO: need to show view if not signed_in
382 if ( ! $user_id){
383 die(__('Please Sign-In', 'tutor'));
384 }
385
386 $course_id = (int) sanitize_text_field($_POST['course_id']);
387
388 do_action('tutor_course_complete_before', $course_id);
389 /**
390 * Marking course completed at Comment
391 */
392
393 global $wpdb;
394
395 $date = date("Y-m-d H:i:s");
396
397 //Making sure that, hash is unique
398 do{
399 $hash = substr(md5(wp_generate_password(32).$date.$course_id.$user_id), 0, 16);
400 $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}' ");
401 }while($hasHash > 0);
402
403 $data = array(
404 'comment_post_ID' => $course_id,
405 'comment_author' => $user_id,
406 'comment_date' => $date,
407 'comment_date_gmt' => get_gmt_from_date($date),
408 'comment_content' => $hash, //Identification Hash
409 'comment_approved' => 'approved',
410 'comment_agent' => 'TutorLMSPlugin',
411 'comment_type' => 'course_completed',
412 'user_id' => $user_id,
413 );
414
415 $wpdb->insert($wpdb->comments, $data);
416
417 do_action('tutor_course_complete_after', $course_id);
418
419 wp_redirect(get_the_permalink($course_id));
420 }
421
422
423 public function tutor_load_instructors_modal(){
424 global $wpdb;
425
426 $course_id = (int) sanitize_text_field($_POST['course_id']);
427 $search_terms = sanitize_text_field(tutor_utils()->avalue_dot('search_terms', $_POST));
428
429 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
430
431 $instructors = array();
432
433
434 $not_in_sql = '';
435 if ($saved_instructors){
436 $saved_instructors_ids = wp_list_pluck($saved_instructors, 'ID');
437 $instructor_not_in_ids = implode(',', $saved_instructors_ids);
438 $activated = apply_filters('tutor_instructor_query_when_exists', " AND ID <1 ");
439 $not_in_sql = $activated."AND ID NOT IN($instructor_not_in_ids) ";
440 }
441
442 $search_sql = '';
443 if ($search_terms){
444 $search_sql = "AND user_login like '%{$search_terms}%' or user_nicename like '%{$search_terms}%' or display_name like '%{$search_terms}%' ";
445 }
446
447 $instructors = $wpdb->get_results("select ID, display_name from {$wpdb->users}
448 INNER JOIN {$wpdb->usermeta} ON ID = user_id AND meta_key = '_tutor_instructor_status' AND meta_value = 'approved'
449 WHERE ID > 0 {$not_in_sql} {$search_sql} limit 10 ");
450
451 $output = '';
452 if (is_array($instructors) && count($instructors)){
453 $instructor_output = '';
454 foreach ($instructors as $instructor){
455 $instructor_output .= "<p><label><input type='radio' name='tutor_instructor_ids[]' value='{$instructor->ID}' > {$instructor->display_name} </label></p>";
456 }
457
458 $output .= apply_filters('tutor_course_instructors_html', $instructor_output, $instructors);
459 $output .= '<p class="quiz-search-suggest-text">'.__('Search to get the specific instructors', 'tutor').'</p>';
460
461 }else{
462 $output .= __('No instructor available or you have already added maximum instructors', 'tutor');
463 }
464
465 wp_send_json_success(array('output' => $output));
466 }
467
468 public function tutor_add_instructors_to_course(){
469 $course_id = (int) sanitize_text_field($_POST['course_id']);
470 $instructor_ids = tutor_utils()->avalue_dot('tutor_instructor_ids', $_POST);
471
472 if (is_array($instructor_ids) && count($instructor_ids)){
473 foreach ($instructor_ids as $instructor_id){
474 add_user_meta($instructor_id, '_tutor_instructor_course_id', $course_id);
475 }
476 }
477
478 $saved_instructors = tutor_utils()->get_instructors_by_course($course_id);
479 $output = '';
480
481 if ($saved_instructors){
482 foreach ($saved_instructors as $t){
483
484 $output .= '<div id="added-instructor-id-'.$t->ID.'" class="added-instructor-item added-instructor-item-'.$t->ID.'" data-instructor-id="'.$t->ID.'">
485 <span class="instructor-icon">'.get_avatar($t->ID, 30).'</span>
486 <span class="instructor-name"> '.$t->display_name.' </span>
487 <span class="instructor-control">
488 <a href="javascript:;" class="tutor-instructor-delete-btn"><i class="tutor-icon-garbage"></i></a>
489 </span>
490 </div>';
491 }
492 }
493
494 wp_send_json_success(array('output' => $output));
495 }
496
497 public function detach_instructor_from_course(){
498 global $wpdb;
499
500 $instructor_id = (int) sanitize_text_field($_POST['instructor_id']);
501 $course_id = (int) sanitize_text_field($_POST['course_id']);
502
503 $wpdb->delete($wpdb->usermeta, array('user_id' => $instructor_id, 'meta_key' => '_tutor_instructor_course_id', 'meta_value' => $course_id) );
504 wp_send_json_success();
505 }
506
507
508 }