PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.1.0
Tutor LMS – eLearning and online course solution v2.1.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 / Lesson.php
tutor / classes Last commit date
Addons.php 3 years ago Admin.php 3 years ago Ajax.php 3 years ago Announcements.php 3 years ago Assets.php 3 years ago Backend_Page_Trait.php 3 years ago Course.php 3 years ago Course_Embed.php 3 years ago Course_Filter.php 3 years ago Course_List.php 3 years ago Course_Settings_Tabs.php 3 years ago Course_Widget.php 4 years ago Custom_Validation.php 4 years ago Dashboard.php 3 years ago FormHandler.php 4 years ago Frontend.php 3 years ago Gutenberg.php 3 years ago Input.php 3 years ago Instructor.php 4 years ago Instructors_List.php 3 years ago Lesson.php 3 years ago Options_V2.php 3 years ago Post_types.php 3 years ago Private_Course_Access.php 4 years ago Q_and_A.php 3 years ago Question_Answers_List.php 4 years ago Quiz.php 3 years ago Quiz_Attempts_List.php 3 years ago RestAPI.php 4 years ago Reviews.php 3 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 3 years ago Theme_Compatibility.php 5 years ago Tools.php 3 years ago Tools_V2.php 4 years ago Tutor.php 3 years ago TutorEDD.php 4 years ago Tutor_Base.php 5 years ago Tutor_List_Table.php 3 years ago Tutor_Setup.php 3 years ago Upgrader.php 4 years ago User.php 4 years ago Utils.php 3 years ago Video_Stream.php 4 years ago Withdraw.php 3 years ago Withdraw_Requests_List.php 3 years ago WooCommerce.php 3 years ago
Lesson.php
514 lines
1 <?php
2 namespace TUTOR;
3
4 use Tutor\Models\LessonModel;
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 if ( 'tutor_create_lesson_comment' === Input::post( 'action' ) ) {
71 $comment_data = array(
72 'comment_content' => Input::post( 'comment', '', Input::TYPE_KSES_POST ),
73 'comment_post_ID' => Input::post( 'comment_post_ID', 0, Input::TYPE_INT ),
74 'comment_parent' => Input::post( 'comment_parent', 0, Input::TYPE_INT ),
75 );
76 self::create_comment( $comment_data );
77 }
78 ob_start();
79 tutor_load_template( 'single.lesson.comment' );
80 $html = ob_get_clean();
81
82 wp_send_json_success( array( 'html' => $html ) );
83 }
84
85 /**
86 * Registering metabox
87 */
88 public function register_meta_box() {
89 $lesson_post_type = $this->lesson_post_type;
90
91 tutor_meta_box_wrapper( 'tutor-course-select', __( 'Select Course', 'tutor' ), array( $this, 'lesson_metabox' ), $lesson_post_type, 'advanced', 'default', 'tutor-admin-post-meta' );
92
93 tutor_meta_box_wrapper( 'tutor-lesson-videos', __( 'Lesson Video', 'tutor' ), array( $this, 'lesson_video_metabox' ), $lesson_post_type, 'advanced', 'default', 'tutor-admin-post-meta' );
94
95 tutor_meta_box_wrapper( 'tutor-lesson-attachments', __( 'Attachments', 'tutor' ), array( $this, 'lesson_attachments_metabox' ), $lesson_post_type, 'advanced', 'default', 'tutor-admin-post-meta' );
96 }
97
98 public function lesson_metabox() {
99 include tutor()->path . 'views/metabox/lesson-metabox.php';
100 }
101
102 public function lesson_video_metabox() {
103 include tutor()->path . 'views/metabox/video-metabox.php';
104 }
105
106 public function lesson_attachments_metabox() {
107 include tutor()->path . 'views/metabox/lesson-attachments-metabox.php';
108 }
109
110 /**
111 * @param $post_ID
112 *
113 * Saving lesson meta and assets
114 */
115 public function save_lesson_meta( $post_ID ) {
116 // Video
117 $video_source = sanitize_text_field( tutor_utils()->array_get( 'video.source', $_POST ) );
118 if ( $video_source === '-1' ) {
119 delete_post_meta( $post_ID, '_video' );
120 } elseif ( $video_source ) {
121 $video = (array) tutor_utils()->array_get( 'video', $_POST, array() );
122 update_post_meta( $post_ID, '_video', $video );
123 }
124
125 // Attachments
126 $attachments = array();
127 if ( ! empty( $_POST['tutor_attachments'] ) ) {
128 $attachments = tutor_utils()->sanitize_array( $_POST['tutor_attachments'] );
129 $attachments = array_unique( $attachments );
130 }
131
132 /**
133 * it !empty attachment then update meta else
134 * delete meta key to prevetn empty data in db
135 *
136 * @since 1.8.9
137 */
138 if ( ! empty( $attachments ) ) {
139 update_post_meta( $post_ID, '_tutor_attachments', $attachments );
140 } else {
141 delete_post_meta( $post_ID, '_tutor_attachments' );
142 }
143
144 }
145
146 public function tutor_load_edit_lesson_modal() {
147 tutor_utils()->checking_nonce();
148
149 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
150 $topic_id = Input::post( 'topic_id', 0, Input::TYPE_INT );
151
152 if ( ! tutor_utils()->can_user_manage( 'topic', $topic_id ) ) {
153 wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor' ) ) );
154 }
155
156 /**
157 * If Lesson Not Exists, provide dummy
158 */
159 $post_arr = array(
160 'ID' => 0,
161 'post_content' => '',
162 'post_type' => $this->lesson_post_type,
163 'post_title' => __( 'Draft Lesson', 'tutor' ),
164 'post_status' => 'publish',
165 'post_author' => get_current_user_id(),
166 'post_parent' => $topic_id,
167 );
168
169 $post = $lesson_id ? get_post( $lesson_id ) : (object) $post_arr;
170
171 ob_start();
172 include tutor()->path . 'views/modal/edit-lesson.php';
173 $output = ob_get_clean();
174
175 wp_send_json_success( array( 'output' => $output ) );
176 }
177
178 /**
179 * @since v.1.0.0
180 * @updated v.1.5.1
181 */
182 public function tutor_modal_create_or_update_lesson() {
183 tutor_utils()->checking_nonce();
184
185 global $wpdb;
186
187 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
188 $topic_id = Input::post( 'current_topic_id', 0, Input::TYPE_INT );
189 $current_topic_id = $topic_id;
190 $course_id = tutor_utils()->get_course_id_by( 'topic', $topic_id );
191
192 $_lesson_thumbnail_id = Input::post( '_lesson_thumbnail_id', 0, Input::TYPE_INT );
193 $is_html_active = Input::post( 'is_html_active' ) === 'true' ? true : false;
194 $raw_html_content = Input::post( 'tutor_lesson_modal_editor', '', Input::TYPE_KSES_POST );
195 $tmce_content = Input::post( 'lesson_content', '', Input::TYPE_KSES_POST );
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 = Input::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 = Input::post( 'lesson_id', 0, Input::TYPE_INT );
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 ( 'tutor_complete_lesson' !== Input::post( 'tutor_action' ) ) {
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 = Input::post( 'lesson_id', 0, Input::TYPE_INT );
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 LessonModel::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 = Input::post( 'lesson_id', 0, Input::TYPE_INT );
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 = Input::post( 'post_id', 0, Input::TYPE_INT );
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' => Input::post( 'comment', '', Input::TYPE_KSES_POST ),
435 'comment_post_ID' => Input::post( 'comment_post_ID', 0, Input::TYPE_INT ),
436 'comment_parent' => Input::post( 'comment_parent', 0, Input::TYPE_INT ),
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 esc_url( 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 esc_html( $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