PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.0.6
Tutor LMS – eLearning and online course solution v2.0.6
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 / Lesson.php
tutor / classes Last commit date
Addons.php 4 years ago Admin.php 4 years ago Ajax.php 4 years ago Announcements.php 4 years ago Assets.php 4 years ago Backend_Page_Trait.php 4 years ago Course.php 4 years ago Course_Filter.php 4 years ago Course_List.php 4 years ago Course_Settings_Tabs.php 4 years ago Course_Widget.php 4 years ago Custom_Validation.php 4 years ago Dashboard.php 4 years ago FormHandler.php 4 years ago Frontend.php 4 years ago Gutenberg.php 4 years ago Input.php 4 years ago Instructor.php 4 years ago Instructors_List.php 4 years ago Lesson.php 4 years ago Options_V2.php 4 years ago Post_types.php 4 years ago Private_Course_Access.php 4 years ago Q_and_A.php 4 years ago Question_Answers_List.php 4 years ago Quiz.php 4 years ago Quiz_Attempts_List.php 4 years ago RestAPI.php 4 years ago Reviews.php 4 years ago Rewrite_Rules.php 4 years ago Shortcode.php 4 years ago Student.php 4 years ago Students_List.php 4 years ago Taxonomies.php 4 years ago Template.php 4 years ago Theme_Compatibility.php 5 years ago Tools.php 4 years ago Tools_V2.php 4 years ago Tutor.php 4 years ago TutorEDD.php 4 years ago Tutor_Base.php 5 years ago Tutor_List_Table.php 4 years ago Tutor_Setup.php 4 years ago Upgrader.php 4 years ago User.php 4 years ago Utils.php 4 years ago Video_Stream.php 4 years ago Withdraw.php 4 years ago Withdraw_Requests_List.php 4 years ago WooCommerce.php 4 years ago
Lesson.php
514 lines
1 <?php
2 namespace TUTOR;
3
4 use SebastianBergmann\Environment\Console;
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit;
8 }
9
10 class Lesson extends Tutor_Base {
11 public function __construct() {
12 parent::__construct();
13
14 add_action( 'add_meta_boxes', array( $this, 'register_meta_box' ) );
15 add_action( 'save_post_' . $this->lesson_post_type, array( $this, 'save_lesson_meta' ) );
16
17 add_action( 'wp_ajax_tutor_load_edit_lesson_modal', array( $this, 'tutor_load_edit_lesson_modal' ) );
18 add_action( 'wp_ajax_tutor_modal_create_or_update_lesson', array( $this, 'tutor_modal_create_or_update_lesson' ) );
19 add_action( 'wp_ajax_tutor_delete_lesson_by_id', array( $this, 'tutor_delete_lesson_by_id' ) );
20
21 add_filter( 'get_sample_permalink', array( $this, 'change_lesson_permalink' ), 10, 2 );
22 add_action( 'admin_init', array( $this, 'flush_rewrite_rules' ) );
23
24 /**
25 * Add Column
26 */
27
28 add_filter( "manage_{$this->lesson_post_type}_posts_columns", array( $this, 'add_column' ), 10, 1 );
29 add_action( "manage_{$this->lesson_post_type}_posts_custom_column", array( $this, 'custom_lesson_column' ), 10, 2 );
30
31 // Frontend Action
32 add_action( 'template_redirect', array( $this, 'mark_lesson_complete' ) );
33
34 add_action( 'wp_ajax_tutor_render_lesson_content', array( $this, 'tutor_render_lesson_content' ) );
35 add_action( 'wp_ajax_nopriv_tutor_render_lesson_content', array( $this, 'tutor_render_lesson_content' ) ); // For public course access
36
37 /**
38 * Autoplay next video
39 *
40 * @since v.1.4.9
41 */
42 add_action( 'wp_ajax_autoload_next_course_content', array( $this, 'autoload_next_course_content' ) );
43
44 /**
45 * Load next course item after click complete button
46 *
47 * @since v.1.5.3
48 */
49 add_action( 'tutor_lesson_completed_after', array( $this, 'tutor_lesson_completed_after' ), 999 );
50
51 /**
52 * Lesson comment & reply ajax handler
53 *
54 * @since v2.0.0
55 */
56 add_action( 'wp_ajax_tutor_single_course_lesson_load_more', array( $this, 'tutor_single_course_lesson_load_more' ) );
57 add_action( 'wp_ajax_tutor_create_lesson_comment', array( $this, 'tutor_single_course_lesson_load_more' ) );
58 add_action( 'wp_ajax_tutor_reply_lesson_comment', array( $this, 'reply_lesson_comment' ) );
59 }
60
61 /**
62 * Manage load more & comment create
63 *
64 * @since v2.0.6
65 *
66 * @return void send wp json data
67 */
68 public function tutor_single_course_lesson_load_more() {
69 tutor_utils()->checking_nonce();
70 $action = $_POST['action'] ?? '';
71 if ( 'tutor_create_lesson_comment' === $action ) {
72 $comment_data = array(
73 'comment_content' => $_POST['comment'],
74 'comment_post_ID' => $_POST['comment_post_ID'],
75 'comment_parent' => $_POST['comment_parent'],
76 );
77 self::create_comment( $comment_data);
78 }
79 ob_start();
80 tutor_load_template('single.lesson.comment');
81 $html = ob_get_clean();
82
83 wp_send_json_success( array('html' => $html) );
84 }
85
86 /**
87 * Registering metabox
88 */
89 public function register_meta_box() {
90 $lesson_post_type = $this->lesson_post_type;
91
92 tutor_meta_box_wrapper( 'tutor-course-select', __( 'Select Course', 'tutor' ), array( $this, 'lesson_metabox' ), $lesson_post_type, 'advanced', 'default', 'tutor-admin-post-meta' );
93
94 tutor_meta_box_wrapper( 'tutor-lesson-videos', __( 'Lesson Video', 'tutor' ), array( $this, 'lesson_video_metabox' ), $lesson_post_type, 'advanced', 'default', 'tutor-admin-post-meta' );
95
96 tutor_meta_box_wrapper( 'tutor-lesson-attachments', __( 'Attachments', 'tutor' ), array( $this, 'lesson_attachments_metabox' ), $lesson_post_type, 'advanced', 'default', 'tutor-admin-post-meta' );
97 }
98
99 public function lesson_metabox() {
100 include tutor()->path . 'views/metabox/lesson-metabox.php';
101 }
102
103 public function lesson_video_metabox() {
104 include tutor()->path . 'views/metabox/video-metabox.php';
105 }
106
107 public function lesson_attachments_metabox() {
108 include tutor()->path . 'views/metabox/lesson-attachments-metabox.php';
109 }
110
111 /**
112 * @param $post_ID
113 *
114 * Saving lesson meta and assets
115 */
116 public function save_lesson_meta( $post_ID ) {
117 //Video
118 $video_source = sanitize_text_field( tutor_utils()->array_get('video.source', $_POST) );
119 if ( $video_source === '-1'){
120 delete_post_meta($post_ID, '_video');
121 }elseif($video_source) {
122 $video = (array)tutor_utils()->array_get('video', $_POST, array());
123 update_post_meta($post_ID, '_video', $video);
124 }
125
126 // Attachments
127 $attachments = array();
128 if ( ! empty($_POST['tutor_attachments'])){
129 $attachments = tutor_utils()->sanitize_array($_POST['tutor_attachments']);
130 $attachments = array_unique($attachments);
131 }
132
133 /**
134 * it !empty attachment then update meta else
135 * delete meta key to prevetn empty data in db
136 *
137 * @since 1.8.9
138 */
139 if ( ! empty( $attachments ) ) {
140 update_post_meta( $post_ID, '_tutor_attachments', $attachments );
141 } else {
142 delete_post_meta( $post_ID, '_tutor_attachments' );
143 }
144
145 }
146
147 public function tutor_load_edit_lesson_modal(){
148 tutor_utils()->checking_nonce();
149
150 $lesson_id = (int) tutor_utils()->avalue_dot( 'lesson_id', tutor_sanitize_data($_POST) );
151 $topic_id = (int) $_POST['topic_id'];
152
153 if(!tutor_utils()->can_user_manage('topic', $topic_id)) {
154 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
155 }
156
157 /**
158 * If Lesson Not Exists, provide dummy
159 */
160 $post_arr = array(
161 'ID' => 0,
162 'post_content' => '',
163 'post_type' => $this->lesson_post_type,
164 'post_title' => __( 'Draft Lesson', 'tutor' ),
165 'post_status' => 'publish',
166 'post_author' => get_current_user_id(),
167 'post_parent' => $topic_id,
168 );
169
170 $post = $lesson_id ? get_post($lesson_id) : (object)$post_arr;
171
172 ob_start();
173 include tutor()->path . 'views/modal/edit-lesson.php';
174 $output = ob_get_clean();
175
176 wp_send_json_success( array( 'output' => $output ) );
177 }
178
179 /**
180 * @since v.1.0.0
181 * @updated v.1.5.1
182 */
183 public function tutor_modal_create_or_update_lesson(){
184 tutor_utils()->checking_nonce();
185
186 global $wpdb;
187
188 $lesson_id = (int) sanitize_text_field(tutor_utils()->avalue_dot('lesson_id', $_POST));
189 $topic_id = (int) sanitize_text_field(tutor_utils()->avalue_dot('current_topic_id', $_POST));
190 $current_topic_id = $topic_id;
191 $course_id = tutor_utils()->get_course_id_by('topic', $topic_id);
192 $_lesson_thumbnail_id = (int) sanitize_text_field(tutor_utils()->avalue_dot('_lesson_thumbnail_id', $_POST));
193 $is_html_active = Input::post('is_html_active') === 'true' ? true : false;
194 $raw_html_content = wp_kses_post( $_POST['tutor_lesson_modal_editor'] );
195 $tmce_content = wp_kses_post( $_POST['lesson_content'] );
196
197 if(!tutor_utils()->can_user_manage('topic', $topic_id)) {
198 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
199 }
200
201 $title = sanitize_text_field( $_POST['lesson_title'] );
202 $lesson_content = $is_html_active ? $raw_html_content : $tmce_content;
203
204 $lesson_data = array(
205 'post_type' => $this->lesson_post_type,
206 'post_title' => $title,
207 'post_name' => sanitize_title($title),
208 'post_content' => $lesson_content,
209 'post_status' => 'publish',
210 'comment_status' => 'open',
211 'post_author' => get_current_user_id(),
212 'post_parent' => $topic_id
213 );
214
215 if ( $lesson_id == 0 ) {
216
217 $lesson_data['menu_order'] = tutor_utils()->get_next_course_content_order_id( $topic_id );
218 $lesson_id = wp_insert_post( $lesson_data );
219
220 if ( $lesson_id ) {
221 do_action( 'tutor/lesson/created', $lesson_id );
222 } else {
223 wp_send_json_error( array( 'message' => __( 'Couldn\'t create lesson.', 'tutor' ) ) );
224 }
225 } else {
226 $lesson_data['ID'] = $lesson_id;
227
228 do_action( 'tutor/lesson_update/before', $lesson_id );
229 wp_update_post( $lesson_data );
230 if ( $_lesson_thumbnail_id ) {
231 update_post_meta( $lesson_id, '_thumbnail_id', $_lesson_thumbnail_id );
232 } else {
233 delete_post_meta( $lesson_id, '_thumbnail_id' );
234 }
235
236 do_action( 'tutor/lesson_update/after', $lesson_id );
237 }
238
239 ob_start();
240 include tutor()->path . 'views/metabox/course-contents.php';
241 $course_contents = ob_get_clean();
242
243 wp_send_json_success( array( 'course_contents' => $course_contents ) );
244 }
245
246 /**
247 * Delete Lesson from course builder
248 */
249 public function tutor_delete_lesson_by_id(){
250 tutor_utils()->checking_nonce();
251
252 $lesson_id = (int) tutor_utils()->avalue_dot( 'lesson_id', $_POST );
253
254 if(!tutor_utils()->can_user_manage('lesson', $lesson_id)) {
255 wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) );
256 }
257
258 wp_delete_post( $lesson_id, true );
259 wp_send_json_success();
260 }
261
262
263 /**
264 * @param $uri
265 * @param $lesson_id
266 *
267 * @return mixed
268 *
269 * Changed the URI based
270 */
271
272 public function change_lesson_permalink( $uri, $lesson_id ) {
273 $post = get_post( $lesson_id );
274
275 if ( $post && $post->post_type === $this->lesson_post_type ) {
276 $uri_base = trailingslashit( site_url() );
277
278 $sample_course = 'sample-course';
279 $is_course = tutor_utils()->get_course_id_by( 'lesson', get_the_ID() );
280 if ( $is_course ) {
281 $course = get_post( $is_course );
282 if ( $course ) {
283 $sample_course = $course->post_name;
284 }
285 }
286
287 $new_course_base = $uri_base . "course/{$sample_course}/lesson/%pagename%/";
288 $uri[0] = $new_course_base;
289 }
290
291 return $uri;
292 }
293
294
295 public function flush_rewrite_rules() {
296 $is_required_flush = get_option( 'required_rewrite_flush' );
297 if ( $is_required_flush ) {
298 flush_rewrite_rules();
299 delete_option( 'required_rewrite_flush' );
300 }
301 }
302
303
304 public function add_column( $columns ) {
305 $date_col = $columns['date'];
306 unset( $columns['date'] );
307 $columns['course'] = __( 'Course', 'tutor' );
308 $columns['date'] = $date_col;
309
310 return $columns;
311 }
312
313 /**
314 * @param $column
315 * @param $post_id
316 */
317 public function custom_lesson_column( $column, $post_id ) {
318 if ( $column === 'course' ) {
319
320 $course_id = tutor_utils()->get_course_id_by( 'lesson', $post_id );
321 if ( $course_id ) {
322 echo '<a href="' . admin_url( 'post.php?post=' . $course_id . '&action=edit' ) . '">' . get_the_title( $course_id ) . '</a>';
323 }
324 }
325 }
326
327 /**
328 *
329 * Mark lesson completed
330 *
331 * @since v.1.0.0
332 */
333 public function mark_lesson_complete() {
334 if ( ! isset( $_POST['tutor_action'] ) || $_POST['tutor_action'] !== 'tutor_complete_lesson' ) {
335 return;
336 }
337 // Checking nonce
338 tutor_utils()->checking_nonce();
339
340 $user_id = get_current_user_id();
341
342 // TODO: need to show view if not signed_in
343 if ( ! $user_id ) {
344 die( __( 'Please Sign-In', 'tutor' ) );
345 }
346
347 $lesson_id = (int) $_POST['lesson_id'];
348
349 do_action( 'tutor_lesson_completed_before', $lesson_id );
350 /**
351 * Marking lesson at user meta, meta format, _tutor_completed_lesson_id_{id} and value = tutor_time();
352 */
353 tutor_utils()->mark_lesson_complete( $lesson_id );
354
355 do_action( 'tutor_lesson_completed_email_after', $lesson_id, $user_id );
356 do_action( 'tutor_lesson_completed_after', $lesson_id, $user_id );
357 }
358
359 /**
360 * Render the lesson content
361 */
362 public function tutor_render_lesson_content(){
363 tutor_utils()->checking_nonce();
364
365 $lesson_id = (int) tutor_utils()->avalue_dot( 'lesson_id', $_POST );
366
367 $ancestors = get_post_ancestors($lesson_id);
368 $course_id = !empty($ancestors) ? array_pop($ancestors): $lesson_id;
369
370 // Course must be public or current user must be enrolled to access this lesson
371 if(get_post_meta($course_id, '_tutor_is_public_course', true)!=='yes' && !tutor_utils()->is_enrolled($course_id)){
372
373 $is_admin = tutor_utils()->has_user_role('administrator');
374 $allowed = $is_admin ? true : tutor_utils()->is_instructor_of_this_course(get_current_user_id(), $course_id);
375
376 if ( ! $allowed ) {
377 http_response_code( 400 );
378 exit;
379 }
380 }
381
382 ob_start();
383 global $post;
384
385 $post = get_post( $lesson_id );
386 setup_postdata( $post );
387 tutor_lesson_content();
388 wp_reset_postdata();
389
390 $html = ob_get_clean();
391
392 wp_send_json_success(array('html' => $html));
393 }
394
395 /**
396 * Load next course item automatically
397 *
398 * @since v.1.4.9
399 */
400 public function autoload_next_course_content() {
401 tutor_utils()->checking_nonce();
402
403 $post_id = sanitize_text_field($_POST['post_id']);
404 $content_id = tutor_utils()->get_post_id($post_id);
405 $contents = tutor_utils()->get_course_prev_next_contents_by_id($content_id);
406
407 $autoload_course_content = (bool) get_tutor_option( 'autoload_next_course_content' );
408 $next_url = false;
409 if ( $autoload_course_content ) {
410 $next_url = get_the_permalink( $contents->next_id );
411 }
412 wp_send_json_success( array( 'next_url' => $next_url ) );
413 }
414
415 /**
416 * Load next course item after click complete button
417 *
418 * @since v.1.5.3
419 */
420 public function tutor_lesson_completed_after( $content_id ) {
421 $contents = tutor_utils()->get_course_prev_next_contents_by_id( $content_id );
422 $autoload_course_content = (bool) get_tutor_option( 'autoload_next_course_content' );
423 if ( $autoload_course_content ) {
424 wp_redirect( get_the_permalink( $contents->next_id ) );
425 } else {
426 wp_redirect( get_the_permalink( $content_id ) );
427 }
428 die();
429 }
430
431 public function reply_lesson_comment() {
432 tutor_utils()->checking_nonce();
433 $comment_data = array(
434 'comment_content' => $_POST['comment'],
435 'comment_post_ID' => $_POST['comment_post_ID'],
436 'comment_parent' => $_POST['comment_parent'],
437 );
438 $comment_id = self::create_comment( $comment_data);
439 if ( false === $comment_id ) {
440 wp_send_json_error();
441 return;
442 }
443 $reply = get_comment( $comment_id );
444 ob_start();
445 ?>
446 <div class="tutor-comments-list tutor-child-comment tutor-mt-32" id="lesson-comment-<?php echo esc_attr($reply->comment_ID) ?>">
447 <div class="comment-avatar">
448 <img src="<?php echo get_avatar_url($reply->user_id); ?>" alt="">
449 </div>
450 <div class="tutor-single-comment">
451 <div class="tutor-actual-comment tutor-mb-12">
452 <div class="tutor-comment-author">
453 <span class="tutor-fs-6 tutor-fw-bold">
454 <?php echo $reply->comment_author; ?>
455 </span>
456 <span class="tutor-fs-7 tutor-ml-0 tutor-ml-sm-10">
457 <?php echo human_time_diff(strtotime($reply->comment_date), tutor_time()) . __(' ago', 'tutor'); ?>
458 </span>
459 </div>
460 <div class="tutor-comment-text tutor-fs-6 tutor-mt-4">
461 <?php echo $reply->comment_content; ?>
462 </div>
463 </div>
464 </div>
465 </div>
466 <?php
467 $html = ob_get_clean();
468 wp_send_json_success( array('html' => $html) );
469 }
470
471 /**
472 * Get comments
473 *
474 * @since v2.0.6
475 *
476 * @param array $args
477 *
478 * ?Checkout arguments details:
479 * ?https://developer.wordpress.org/reference/classes/wp_comment_query/__construct/
480 *
481 * @return mixed based on arguments
482 */
483 public static function get_comments( array $args ) {
484 $comments = get_comments( $args );
485 return $comments;
486 }
487
488 /**
489 * Create comment
490 *
491 * @param array $post
492 *
493 * @return mixed comment id on success, false on failure
494 */
495 public static function create_comment( array $request ) {
496 $current_user = wp_get_current_user();
497 $default_data = array(
498 'comment_content' => '',
499 'comment_post_ID' => '',
500 'comment_parent' => '',
501 'user_id' => $current_user->ID,
502 'comment_author' => $current_user->user_login,
503 'comment_author_email' => $current_user->user_email,
504 'comment_author_url' => $current_user->user_url,
505 'comment_agent' => 'Tutor',
506 );
507 $comment_data = wp_parse_args( $request, $default_data );
508 return wp_insert_comment( $comment_data );
509 }
510
511 }
512
513
514