PluginProbe
Tutor LMS – eLearning and online course solution / 3.9.15
Tutor LMS – eLearning and online course solution v3.9.15
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 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 All 191 releases
← All changes | classes/Lesson.php +112 -591 trunk3.9.15 View file →
@@ -9,17 +9,16 @@
9 9 */
10 10
11 11 namespace TUTOR;
12 12
13 -defined( 'ABSPATH' ) || exit;
13 +if ( ! defined( 'ABSPATH' ) ) {
14 + exit;
15 +}
14 16
15 17 use Tutor\Helpers\HttpHelper;
16 -use Tutor\Helpers\QueryHelper;
17 18 use Tutor\Helpers\ValidationHelper;
18 -use Tutor\Models\EnrollmentModel;
19 19 use Tutor\Models\LessonModel;
20 20 use Tutor\Traits\JsonResponse;
21 -use WP_Post;
22 21
23 22 /**
24 23 * Lesson class
25 24 *
@@ -28,34 +27,8 @@
28 27 class Lesson extends Tutor_Base {
29 28 use JsonResponse;
30 29
31 30 /**
32 - * Preview meta key
33 - *
34 - * @since 4.0.0
35 - * @var string
36 - */
37 - const PREVIEW_META_KEY = '_is_preview';
38 -
39 - /**
40 - * Lesson post type
41 - *
42 - * @since 4.0.0
43 - *
44 - * @var string
45 - */
46 - private $post_type;
47 -
48 - /**
49 - * Determine if legacy mode is enabled or not
50 - *
51 - * @since 4.0.0
52 - *
53 - * @var bool
54 - */
55 - private $is_legacy_learning_mode = false;
56 -
57 - /**
58 31 * Register hooks
59 32 *
60 33 * @since 1.0.0
61 34 * @since 3.7.0 param register hook added.
@@ -66,12 +39,8 @@
66 39 */
67 40 public function __construct( $register_hooks = true ) {
68 41 parent::__construct();
69 42
70 - $this->post_type = tutor()->lesson_post_type;
71 -
72 - $this->is_legacy_learning_mode = Options_V2::LEARNING_MODE_LEGACY === tutor_utils()->get_option( 'learning_mode' );
73 -
74 43 if ( ! $register_hooks ) {
75 44 return;
76 45 }
77 46
@@ -113,19 +82,11 @@
113 82 * Lesson comment & reply ajax handler
114 83 *
115 84 * @since 2.0.0
116 85 */
117 - add_action( 'wp_ajax_tutor_single_course_lesson_load_more', array( $this, 'ajax_single_course_lesson_load_more' ) );
118 - add_action( 'wp_ajax_tutor_create_lesson_comment', array( $this, 'ajax_single_course_lesson_load_more' ) );
119 - add_action( 'wp_ajax_tutor_delete_lesson_comment', array( $this, 'ajax_delete_lesson_comment' ) );
120 - add_action( 'wp_ajax_tutor_update_lesson_comment', array( $this, 'ajax_update_lesson_comment' ) );
121 - add_action( 'wp_ajax_tutor_reply_lesson_comment', array( $this, 'ajax_reply_lesson_comment' ) );
122 - add_action( 'wp_ajax_tutor_load_lesson_comments', array( $this, 'ajax_load_lesson_comments' ) );
123 - add_action( 'wp_ajax_tutor_load_comment_replies', array( $this, 'ajax_load_comment_replies' ) );
124 -
125 - // Add lesson title as nav item & render single content on the learning area.
126 - add_action( "tutor_learning_area_nav_item_{$this->post_type}", array( $this, 'render_nav_item' ), 10, 2 );
127 - add_action( "tutor_single_content_{$this->post_type}", array( $this, 'render_single_content' ) );
86 + add_action( 'wp_ajax_tutor_single_course_lesson_load_more', array( $this, 'tutor_single_course_lesson_load_more' ) );
87 + add_action( 'wp_ajax_tutor_create_lesson_comment', array( $this, 'tutor_single_course_lesson_load_more' ) );
88 + add_action( 'wp_ajax_tutor_reply_lesson_comment', array( $this, 'reply_lesson_comment' ) );
128 89 }
129 90
130 91 /**
131 92 * Manage load more & comment create
@@ -130,28 +91,20 @@
130 91 /**
131 92 * Manage load more & comment create
132 93 *
133 94 * @since 2.0.6
134 - *
135 - * @since 4.0.0 different template returned
136 - *
137 95 * @return void send wp json data
138 96 */
139 - public function ajax_single_course_lesson_load_more() {
97 + public function tutor_single_course_lesson_load_more() {
140 98 tutor_utils()->checking_nonce();
141 99
142 - $comment_id = 0;
143 100 $comment = Input::post( 'comment', '', Input::TYPE_TEXTAREA );
144 101 $lesson_id = Input::post( 'comment_post_ID', 0, Input::TYPE_INT );
145 102
146 - if ( ! self::is_comment_enabled_for_lesson( $lesson_id ) ) {
147 - $this->response_bad_request( tutor_utils()->error_message( 'invalid_req' ) );
148 - }
149 -
150 103 if ( 'tutor_create_lesson_comment' === Input::post( 'action' ) && strlen( $comment ) > 0 ) {
151 - if ( ! self::can_post_lesson_comment( $lesson_id ) ) {
152 - wp_send_json_error( tutor_utils()->error_message() );
153 - return;
104 + $course_id = tutor_utils()->get_course_id_by( 'lesson', $lesson_id );
105 + if ( ! tutor_utils()->is_enrolled( $course_id ) ) {
106 + wp_send_json_error( __( 'You must be enrolled to comment', 'tutor' ) );
154 107 }
155 108
156 109 $comment_data = array(
157 110 'comment_content' => $comment,
@@ -157,43 +110,11 @@
157 110 'comment_content' => $comment,
158 111 'comment_post_ID' => $lesson_id,
159 112 'comment_parent' => Input::post( 'comment_parent', 0, Input::TYPE_INT ),
160 113 );
161 - $comment_id = self::create_comment( $comment_data );
114 + self::create_comment( $comment_data );
162 115 do_action( 'tutor_new_comment_added', $comment_data );
163 116 }
164 -
165 - if ( ! $this->is_legacy_learning_mode ) {
166 - $html = '';
167 - if ( $comment_id ) {
168 - ob_start();
169 - tutor_load_template(
170 - 'learning-area.lesson.comment-card',
171 - array(
172 - 'comment_item' => get_comment( $comment_id ),
173 - 'lesson_id' => $lesson_id,
174 - 'user_id' => get_current_user_id(),
175 - )
176 - );
177 - $html = ob_get_clean();
178 - }
179 -
180 - $count = self::get_comments(
181 - array(
182 - 'post_id' => $lesson_id,
183 - 'parent' => 0,
184 - 'count' => true,
185 - )
186 - );
187 -
188 - wp_send_json_success(
189 - array(
190 - 'html' => $html,
191 - 'count' => $count,
192 - )
193 - );
194 - }
195 -
196 117 ob_start();
197 118 tutor_load_template( 'single.lesson.comment' );
198 119 $html = ob_get_clean();
199 120 wp_send_json_success( array( 'html' => $html ) );
@@ -199,124 +120,8 @@
199 120 wp_send_json_success( array( 'html' => $html ) );
200 121 }
201 122
202 123 /**
203 - * Delete lesson comment by AJAX
204 - *
205 - * @since 4.0.0
206 - *
207 - * @return void
208 - */
209 - public function ajax_delete_lesson_comment() {
210 - tutor_utils()->check_nonce();
211 - $comment_id = Input::post( 'comment_id', 0, Input::TYPE_INT );
212 - if ( ! $comment_id ) {
213 - $this->response_bad_request( __( 'Invalid comment ID', 'tutor' ) );
214 - }
215 -
216 - $comment = get_comment( $comment_id );
217 - if ( ! $comment ) {
218 - $this->response_bad_request( __( 'Invalid comment ID', 'tutor' ) );
219 - }
220 -
221 - $lesson_id = $comment->comment_post_ID;
222 - $parent_id = $comment->comment_parent;
223 - $is_reply = $parent_id > 0;
224 -
225 - if ( ! self::is_comment_enabled_for_lesson( $lesson_id ) ) {
226 - $this->response_bad_request( tutor_utils()->error_message( 'invalid_req' ) );
227 - }
228 -
229 - if ( get_current_user_id() === (int) $comment->user_id || tutor_utils()->can_user_manage( 'lesson', $lesson_id ) ) {
230 - wp_delete_comment( $comment_id, true );
231 -
232 - $total_comments = self::get_comments(
233 - array(
234 - 'post_id' => $lesson_id,
235 - 'parent' => 0,
236 - 'count' => true,
237 - )
238 - );
239 -
240 - wp_send_json_success(
241 - array(
242 - 'message' => __( 'Comment deleted successfully', 'tutor' ),
243 - 'count' => $total_comments,
244 - 'is_reply' => $is_reply,
245 - 'parent_id' => $parent_id,
246 - 'comment_id' => $comment_id,
247 - )
248 - );
249 - } else {
250 - $this->response_bad_request( __( 'You are not allowed to delete this comment', 'tutor' ) );
251 - }
252 - }
253 -
254 - /**
255 - * Update lesson comment by AJAX
256 - *
257 - * @since 4.0.0
258 - *
259 - * @return void
260 - */
261 - public function ajax_update_lesson_comment() {
262 - tutor_utils()->check_nonce();
263 -
264 - $comment_id = Input::post( 'comment_id', 0, Input::TYPE_INT );
265 - if ( ! $comment_id ) {
266 - $this->response_bad_request( __( 'Invalid comment ID', 'tutor' ) );
267 - }
268 -
269 - $comment = get_comment( $comment_id );
270 - if ( ! $comment ) {
271 - $this->response_bad_request( __( 'Invalid comment ID', 'tutor' ) );
272 - }
273 -
274 - $comment_content = Input::post( 'comment', '', Input::TYPE_KSES_POST );
275 - $user_id = get_current_user_id();
276 - $lesson_id = $comment->comment_post_ID;
277 -
278 - if ( ! self::is_comment_enabled_for_lesson( $lesson_id ) ) {
279 - $this->response_bad_request( tutor_utils()->error_message( 'invalid_req' ) );
280 - }
281 -
282 - if ( $user_id === (int) $comment->user_id ) {
283 - wp_update_comment(
284 - array(
285 - 'comment_ID' => $comment_id,
286 - 'comment_content' => $comment_content,
287 - )
288 - );
289 -
290 - $comment->comment_content = $comment_content;
291 - $is_reply = $comment->comment_parent > 0;
292 -
293 - ob_start();
294 - tutor_load_template(
295 - 'learning-area.lesson.comment-card',
296 - array(
297 - 'comment_item' => $comment,
298 - 'lesson_id' => $lesson_id,
299 - 'user_id' => $user_id,
300 - 'is_reply' => $is_reply,
301 - )
302 - );
303 - $html = ob_get_clean();
304 -
305 - wp_send_json_success(
306 - array(
307 - 'html' => $html,
308 - 'is_reply' => $is_reply,
309 - 'parent_id' => $is_reply ? $comment->comment_parent : 0,
310 - 'comment_id' => $comment_id,
311 - )
312 - );
313 - } else {
314 - $this->response_bad_request( tutor_utils()->error_message() );
315 - }
316 - }
317 -
318 - /**
319 124 * Saving lesson meta and assets
320 125 *
321 126 * @since 1.0.0
322 127 *
@@ -345,9 +150,9 @@
345 150 'source_embedded' => 'wp_kses_post',
346 151 ),
347 152 true
348 153 );
349 - update_post_meta( $post_ID, '_video', tutor_utils()->filter_video_meta( $video ) );
154 + update_post_meta( $post_ID, '_video', $video );
350 155 }
351 156
352 157 // Attachments.
353 158 $attachments = array();
@@ -379,20 +184,30 @@
379 184 * @return void
380 185 */
381 186 public function ajax_lesson_details() {
382 187 if ( ! tutor_utils()->is_nonce_verified() ) {
383 - $this->response_bad_request( tutor_utils()->error_message( 'nonce' ) );
188 + $this->json_response( tutor_utils()->error_message( 'nonce' ), null, HttpHelper::STATUS_BAD_REQUEST );
384 189 }
385 190
386 191 $topic_id = Input::post( 'topic_id', 0, Input::TYPE_INT );
387 192 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
388 193
389 - if ( ! $topic_id || ! $lesson_id ) {
390 - $this->response_bad_request( tutor_utils()->error_message( 'invalid_req' ) );
194 + if ( ! tutor_utils()->can_user_manage( 'topic', $topic_id ) ) {
195 + $this->json_response(
196 + tutor_utils()->error_message(),
197 + null,
198 + HttpHelper::STATUS_FORBIDDEN
199 + );
391 200 }
392 201
393 - if ( ! tutor_utils()->can_user_manage( 'topic', $topic_id ) || ! tutor_utils()->can_user_manage( 'lesson', $lesson_id ) ) {
394 - $this->response_bad_request( tutor_utils()->error_message() );
202 + if ( 0 !== $lesson_id ) {
203 + if ( ! tutor_utils()->can_user_manage( 'lesson', $lesson_id ) ) {
204 + $this->json_response(
205 + tutor_utils()->error_message(),
206 + null,
207 + HttpHelper::STATUS_FORBIDDEN
208 + );
209 + }
395 210 }
396 211
397 212 $data = LessonModel::get_lesson_details( $lesson_id );
398 213
@@ -412,9 +227,9 @@
412 227 * @return void
413 228 */
414 229 public function ajax_save_lesson() {
415 230 if ( ! tutor_utils()->is_nonce_verified() ) {
416 - $this->response_bad_request( tutor_utils()->error_message( 'nonce' ) );
231 + $this->json_response( tutor_utils()->error_message( 'nonce' ), null, HttpHelper::STATUS_BAD_REQUEST );
417 232 }
418 233
419 234 /**
420 235 * Allow iframe inside lesson content to support
@@ -423,16 +238,24 @@
423 238 * @since 2.1.6
424 239 */
425 240 add_filter( 'wp_kses_allowed_html', Input::class . '::allow_iframe', 10, 2 );
426 241
242 + $is_update = false;
243 +
427 244 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
428 245 $topic_id = Input::post( 'topic_id', 0, Input::TYPE_INT );
429 246
430 - if ( ! $topic_id || ! tutor_utils()->can_user_manage( 'topic', $topic_id ) ) {
431 - $this->response_bad_request( tutor_utils()->error_message() );
247 + if ( $lesson_id ) {
248 + $is_update = true;
432 249 }
433 250
434 - $is_update = $lesson_id > 0;
251 + if ( ! tutor_utils()->can_user_manage( 'topic', $topic_id ) ) {
252 + $this->json_response(
253 + tutor_utils()->error_message(),
254 + null,
255 + HttpHelper::STATUS_FORBIDDEN
256 + );
257 + }
435 258
436 259 $title = Input::post( 'title' );
437 260 $description = Input::post( 'description', '', Input::TYPE_KSES_POST );
438 261 $is_html_active = Input::post( 'is_html_active' ) === 'true' ? true : false;
@@ -521,14 +344,15 @@
521 344 public function ajax_delete_lesson() {
522 345 tutor_utils()->check_nonce();
523 346
524 347 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
525 - if ( ! $lesson_id ) {
526 - $this->response_bad_request( tutor_utils()->error_message( 'invalid_req' ) );
527 - }
528 348
529 349 if ( ! tutor_utils()->can_user_manage( 'lesson', $lesson_id ) ) {
530 - $this->response_bad_request( tutor_utils()->error_message() );
350 + $this->json_response(
351 + tutor_utils()->error_message(),
352 + null,
353 + HttpHelper::STATUS_FORBIDDEN
354 + );
531 355 }
532 356
533 357 $content = __( 'Lesson', 'tutor' );
534 358 $post_type = get_post_type( $lesson_id );
@@ -586,31 +410,24 @@
586 410 public function mark_lesson_complete() {
587 411 if ( 'tutor_complete_lesson' !== Input::post( 'tutor_action' ) ) {
588 412 return;
589 413 }
590 -
414 + // Checking nonce.
591 415 tutor_utils()->checking_nonce();
592 416
593 417 $user_id = get_current_user_id();
594 418
419 + // TODO: need to show view if not signed_in.
595 420 if ( ! $user_id ) {
596 421 die( esc_html__( 'Please Sign-In', 'tutor' ) );
597 422 }
598 423
599 424 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
425 +
600 426 if ( ! $lesson_id ) {
601 427 return;
602 428 }
603 429
604 - $course_id = tutor_utils()->get_course_id_by( 'lesson', $lesson_id );
605 - if ( ! $course_id ) {
606 - return;
607 - }
608 -
609 - if ( ! tutor_utils()->is_enrolled( $course_id ) ) {
610 - die( esc_html( tutor_utils()->error_message() ) );
611 - }
612 -
613 430 $validated = apply_filters( 'tutor_validate_lesson_complete', true, $user_id, $lesson_id );
614 431 if ( ! $validated ) {
615 432 return;
616 433 }
@@ -635,21 +452,20 @@
635 452 public function tutor_render_lesson_content() {
636 453 tutor_utils()->checking_nonce();
637 454
638 455 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
639 - if ( ! $lesson_id ) {
640 - $this->response_bad_request( tutor_utils()->error_message( 'invalid_req' ) );
641 - }
642 456
643 - $course_id = tutor_utils()->get_course_id_by( 'lesson', $lesson_id );
457 + $ancestors = get_post_ancestors( $lesson_id );
458 + $course_id = ! empty( $ancestors ) ? array_pop( $ancestors ) : $lesson_id;
644 459
645 460 // Course must be public or current user must be enrolled to access this lesson.
646 - if ( ! Course_List::is_public( $course_id ) && ! EnrollmentModel::is_enrolled( $course_id ) ) {
461 + if ( get_post_meta( $course_id, '_tutor_is_public_course', true ) !== 'yes' && ! tutor_utils()->is_enrolled( $course_id ) ) {
647 462
648 - $allowed = User::is_admin() ? true : tutor_utils()->is_instructor_of_this_course( get_current_user_id(), $course_id );
463 + $is_admin = tutor_utils()->has_user_role( 'administrator' );
464 + $allowed = $is_admin ? true : tutor_utils()->is_instructor_of_this_course( get_current_user_id(), $course_id );
649 465
650 466 if ( ! $allowed ) {
651 - $this->response_bad_request( tutor_utils()->error_message() );
467 + http_response_code( 400 );
652 468 exit;
653 469 }
654 470 }
655 471
@@ -675,23 +491,17 @@
675 491 */
676 492 public function autoload_next_course_content() {
677 493 tutor_utils()->checking_nonce();
678 494
679 - $post_id = Input::post( 'post_id', 0, Input::TYPE_INT );
680 - $course_id = tutor_utils()->get_course_id_by_content( $post_id );
681 - if ( ! $course_id || ! EnrollmentModel::is_enrolled( $course_id ) ) {
682 - wp_send_json_error( tutor_utils()->error_message() );
683 - }
684 -
495 + $post_id = Input::post( 'post_id', 0, Input::TYPE_INT );
685 496 $content_id = tutor_utils()->get_post_id( $post_id );
686 497 $contents = tutor_utils()->get_course_prev_next_contents_by_id( $content_id );
687 498
688 - $autoload_course_content = (bool) UserPreference::get( 'auto_play_next', false, get_current_user_id() );
499 + $autoload_course_content = (bool) get_tutor_option( 'autoload_next_course_content' );
689 500 $next_url = false;
690 - if ( $autoload_course_content && $contents->next_id ) {
501 + if ( $autoload_course_content ) {
691 502 $next_url = get_the_permalink( $contents->next_id );
692 503 }
693 -
694 504 wp_send_json_success( array( 'next_url' => $next_url ) );
695 505 }
696 506
697 507 /**
@@ -713,28 +523,8 @@
713 523 die();
714 524 }
715 525
716 526 /**
717 - * Check user can post lesson comment.
718 - *
719 - * @since 4.0.0
720 - *
721 - * @param int $lesson_id lesson id.
722 - * @param int $user_id user id. default 0 means current user id.
723 - *
724 - * @return bool true if user can post lesson comment, false otherwise.
725 - */
726 - private static function can_post_lesson_comment( $lesson_id, $user_id = 0 ) {
727 - $course_id = tutor_utils()->get_course_id_by( 'lesson', $lesson_id );
728 - if ( ! $course_id ) {
729 - return false;
730 - }
731 -
732 - $can_post = EnrollmentModel::is_enrolled( $course_id, $user_id ) || tutor_utils()->can_user_manage( 'course', $course_id, $user_id );
733 - return $can_post;
734 - }
735 -
736 - /**
737 527 * Replay lesson comment
738 528 *
739 529 * @since 1.0.0
740 530 *
@@ -739,109 +529,37 @@
739 529 * @since 1.0.0
740 530 *
741 531 * @return void|null
742 532 */
743 - public function ajax_reply_lesson_comment() {
533 + public function reply_lesson_comment() {
744 534 tutor_utils()->checking_nonce();
745 -
746 - $lesson_id = Input::post( 'comment_post_ID', 0, Input::TYPE_INT );
747 - $comment_parent = Input::post( 'comment_parent', 0, Input::TYPE_INT );
748 - $comment = Input::post( 'comment', '', Input::TYPE_TEXTAREA );
749 -
750 - if ( ! $lesson_id || ! $comment_parent || 0 === strlen( $comment ) ) {
751 - wp_send_json_error( tutor_utils()->error_message( 'invalid_req' ) );
535 + $comment = Input::post( 'comment', '', Input::TYPE_TEXTAREA );
536 + if ( 0 === strlen( $comment ) ) {
537 + wp_send_json_error();
752 538 return;
753 539 }
754 540
755 - if ( ! self::can_post_lesson_comment( $lesson_id ) ) {
756 - wp_send_json_error( tutor_utils()->error_message() );
541 + $lesson_id = Input::post( 'comment_post_ID', 0, Input::TYPE_INT );
542 + $course_id = tutor_utils()->get_course_id_by( 'lesson', $lesson_id );
543 + if ( ! tutor_utils()->is_enrolled( $course_id ) ) {
544 + wp_send_json_error( __( 'You must be enrolled to comment', 'tutor' ) );
757 545 return;
758 546 }
759 547
760 - $parent_comment = get_comment( $comment_parent );
761 - if ( ! $parent_comment || (int) $parent_comment->comment_post_ID !== $lesson_id ) {
762 - wp_send_json_error( tutor_utils()->error_message( 'invalid_req' ) );
763 - return;
764 - }
765 -
766 548 $comment_data = array(
767 549 'comment_content' => $comment,
768 550 'comment_post_ID' => $lesson_id,
769 - 'comment_parent' => $comment_parent,
551 + 'comment_parent' => Input::post( 'comment_parent', 0, Input::TYPE_INT ),
770 552 );
771 553
772 - if ( ! self::is_comment_enabled_for_lesson( $comment_data['comment_post_ID'] ) ) {
773 - $this->response_bad_request( tutor_utils()->error_message( 'invalid_req' ) );
774 - }
775 -
776 554 $comment_id = self::create_comment( $comment_data );
777 555 if ( false === $comment_id ) {
778 556 wp_send_json_error();
779 557 return;
780 558 }
781 -
782 559 $reply = get_comment( $comment_id );
783 560 do_action( 'tutor_reply_lesson_comment_thread', $comment_id, $comment_data );
784 561
785 - if ( ! $this->is_legacy_learning_mode ) {
786 - $lesson_id = $comment_data['comment_post_ID'];
787 - $parent_id = $comment_data['comment_parent'];
788 - $comment_item = get_comment( $parent_id );
789 - $user_id = get_current_user_id();
790 -
791 - $replies = self::get_comments(
792 - array(
793 - 'post_id' => $lesson_id,
794 - 'parent' => $parent_id,
795 - 'order' => 'ASC',
796 - )
797 - );
798 -
799 - $is_first_reply = ( is_array( $replies ) ? count( $replies ) : 0 ) === 1;
800 -
801 - ob_start();
802 - if ( $is_first_reply ) {
803 - // For the first reply, we need the wrapper and the toggle button.
804 - tutor_load_template(
805 - 'learning-area.lesson.comment-replies',
806 - array(
807 - 'lesson_id' => $lesson_id,
808 - 'comment_item' => $comment_item,
809 - 'user_id' => $user_id,
810 - 'replies' => $replies,
811 - )
812 - );
813 - } else {
814 - // Just the card for subsequent replies.
815 - tutor_load_template(
816 - 'learning-area.lesson.comment-card',
817 - array(
818 - 'comment_item' => get_comment( $comment_id ),
819 - 'lesson_id' => $lesson_id,
820 - 'user_id' => $user_id,
821 - 'is_reply' => true,
822 - )
823 - );
824 - }
825 - $html = ob_get_clean();
826 -
827 - $total_comments = self::get_comments(
828 - array(
829 - 'post_id' => $lesson_id,
830 - 'parent' => 0,
831 - 'count' => true,
832 - )
833 - );
834 -
835 - wp_send_json_success(
836 - array(
837 - 'html' => $html,
838 - 'count' => $total_comments,
839 - 'is_first_reply' => $is_first_reply,
840 - )
841 - );
842 - }
843 -
844 562 ob_start();
845 563 ?>
846 564 <div class="tutor-comments-list tutor-child-comment tutor-mt-32" id="lesson-comment-<?php echo esc_attr( $reply->comment_ID ); ?>">
847 565 <div class="comment-avatar">
@@ -883,27 +601,8 @@
883 601 return $comments;
884 602 }
885 603
886 604 /**
887 - * Get comment replies
888 - *
889 - * @since 4.0.0
890 - *
891 - * @param int $comment_id comment id.
892 - * @param string $order order.
893 - *
894 - * @return mixed comment replies on success, false on failure
895 - */
896 - public static function get_comment_replies( int $comment_id, string $order = 'DESC' ) {
897 - return get_comments(
898 - array(
899 - 'parent' => $comment_id,
900 - 'order' => QueryHelper::get_valid_sort_order( $order ),
901 - )
902 - );
903 - }
904 -
905 - /**
906 605 * Create comment
907 606 *
908 607 * @since 1.0.0
909 608 *
@@ -969,25 +668,12 @@
969 668 *
970 669 * @return bool True if comments are enabled, false otherwise.
971 670 */
972 671 public static function is_comment_enabled() {
973 - return tutor_utils()->get_option( 'enable_comment_for_lesson' );
672 + return tutor_utils()->get_option( 'enable_comment_for_lesson' ) && comments_open() && is_user_logged_in();
974 673 }
975 674
976 675 /**
977 - * Check if comments are enabled for lessons
978 - *
979 - * @since 4.0.0
980 - *
981 - * @param int|object $lesson Lesson ID or object. If null, current lesson will be used.
982 - *
983 - * @return bool True if comments are enabled, false otherwise.
984 - */
985 - public static function is_comment_enabled_for_lesson( $lesson = null ) {
986 - return self::is_comment_enabled() && comments_open( $lesson );
987 - }
988 -
989 - /**
990 676 * Check if lesson has comments
991 677 *
992 678 * @since 3.9.0
993 679 *
@@ -1008,69 +694,32 @@
1008 694 *
1009 695 * @return array navigation items array
1010 696 */
1011 697 public static function get_nav_items( $lesson_id ) {
1012 - $is_legacy = ( new self( false ) )->is_legacy_learning_mode;
1013 698 $nav_items = array();
1014 699
1015 - $attachments = tutor_utils()->get_attachments( $lesson_id );
700 + if ( self::has_lesson_content( $lesson_id ) ) {
701 + $nav_items['overview'] = array(
702 + 'label' => __( 'Overview', 'tutor' ),
703 + 'value' => 'overview',
704 + 'icon' => 'document-text',
705 + );
706 + }
1016 707
1017 - $definitions = array(
1018 - 'overview' => array(
1019 - 'condition' => self::has_lesson_content( $lesson_id ),
1020 - 'legacy' => array(
1021 - 'label' => __( 'Overview', 'tutor' ),
1022 - 'value' => 'overview',
1023 - 'icon' => 'document-text',
1024 - 'template' => 'single.lesson.parts.overview',
1025 - ),
1026 - 'default' => array(
1027 - 'id' => 'overview',
1028 - 'label' => __( 'Overview', 'tutor' ),
1029 - 'icon' => Icon::COURSES,
1030 - 'template' => 'learning-area.lesson.overview',
1031 - ),
1032 - ),
1033 - 'files' => array(
1034 - 'condition' => tutor_utils()->count( $attachments ),
1035 - 'legacy' => array(
1036 - 'label' => __( 'Exercise Files', 'tutor' ),
1037 - 'value' => 'files',
1038 - 'icon' => 'paperclip',
1039 - 'template' => 'single.lesson.parts.files',
1040 - ),
1041 - 'default' => array(
1042 - 'id' => 'exercise_files',
1043 - 'label' => __( 'Exercise Files', 'tutor' ),
1044 - 'icon' => Icon::FILE_ATTACHEMENT,
1045 - 'template' => 'learning-area.lesson.exercise-files',
1046 - ),
1047 - ),
1048 - 'comments' => array(
1049 - 'condition' => self::is_comment_enabled_for_lesson( $lesson_id ) && is_user_logged_in(),
1050 - 'legacy' => array(
1051 - 'label' => __( 'Comments', 'tutor' ),
1052 - 'value' => 'comments',
1053 - 'icon' => 'comment',
1054 - 'template' => 'single.lesson.parts.comments',
1055 - ),
1056 - 'default' => array(
1057 - 'id' => 'comments',
1058 - 'label' => __( 'Comments', 'tutor' ),
1059 - 'icon' => Icon::COMMENTS,
1060 - 'template' => 'learning-area.lesson.comments',
1061 - ),
1062 - ),
1063 - );
708 + if ( self::has_lesson_attachment( $lesson_id ) ) {
709 + $nav_items['files'] = array(
710 + 'label' => __( 'Exercise Files', 'tutor' ),
711 + 'value' => 'files',
712 + 'icon' => 'paperclip',
713 + );
714 + }
1064 715
1065 - foreach ( $definitions as $key => $def ) {
1066 - if ( empty( $def['condition'] ) ) {
1067 - continue;
1068 - }
1069 - $item = $is_legacy ? $def['legacy'] : $def['default'];
1070 - if ( null !== $item ) {
1071 - $nav_items[ $key ] = $item;
1072 - }
716 + if ( self::is_comment_enabled() ) {
717 + $nav_items['comments'] = array(
718 + 'label' => __( 'Comments', 'tutor' ),
719 + 'value' => 'comments',
720 + 'icon' => 'comment',
721 + );
1073 722 }
1074 723
1075 724 $nav_items = apply_filters( 'tutor_lesson_single_nav_items', $nav_items );
1076 725 $nav_items = array_values( $nav_items );
@@ -1078,172 +727,44 @@
1078 727 return $nav_items;
1079 728 }
1080 729
1081 730 /**
1082 - * Return lesson title as nav item to print on the learning area
731 + * Get navigation contents for lesson single page
1083 732 *
1084 - * @since 4.0.0
733 + * @since 3.9.0
1085 734 *
1086 - * @param WP_Post $lesson Lesson post object.
1087 - * @param bool $can_access Can user access this content.
735 + * @param int $lesson_id Lesson ID.
1088 736 *
1089 - * @return void
737 + * @return array navigation contents array
1090 738 */
1091 - public function render_nav_item( $lesson, $can_access ): void {
1092 - tutor_load_template(
1093 - 'learning-area.lesson.nav-item',
1094 - array(
1095 - 'lesson' => $lesson,
1096 - 'can_access' => $can_access,
1097 - )
1098 - );
1099 - }
739 + public static function get_nav_contents( $lesson_id ) {
740 + $nav_contents = array();
1100 741
1101 - /**
1102 - * Render content for the a single lesson
1103 - *
1104 - * @since 4.0.0
1105 - *
1106 - * @param WP_Post $lesson Lesson post object.
1107 - *
1108 - * @return void
1109 - */
1110 - public function render_single_content( $lesson ): void {
1111 - tutor_load_template(
1112 - 'learning-area.lesson.content',
1113 - array(
1114 - 'lesson' => $lesson,
1115 - )
1116 - );
1117 - }
1118 -
1119 - /**
1120 - * Load lesson comments
1121 - *
1122 - * @since 4.0.0
1123 - *
1124 - * @return void
1125 - */
1126 - public function ajax_load_lesson_comments() {
1127 - tutor_utils()->check_nonce();
1128 -
1129 - $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
1130 - $current_page = Input::post( 'current_page', 1, Input::TYPE_INT );
1131 - $offset = Input::post( 'offset', -1, Input::TYPE_INT );
1132 - $order = QueryHelper::get_valid_sort_order( Input::post( 'order', 'DESC' ) );
1133 -
1134 - if ( ! self::is_comment_enabled_for_lesson( $lesson_id ) ) {
1135 - $this->response_bad_request( tutor_utils()->error_message( 'invalid_req' ) );
742 + if ( self::has_lesson_content( $lesson_id ) ) {
743 + $nav_contents['overview'] = array(
744 + 'label' => __( 'Overview', 'tutor' ),
745 + 'value' => 'overview',
746 + 'template_path' => 'single.lesson.parts.overview',
747 + );
1136 748 }
1137 749
1138 - $user_id = get_current_user_id();
1139 - $item_per_page = tutor_utils()->get_option( 'pagination_per_page', 10 );
1140 -
1141 - $query_args = array(
1142 - 'post_id' => $lesson_id,
1143 - 'parent' => 0,
1144 - 'number' => $item_per_page,
1145 - 'order' => $order,
1146 - );
1147 -
1148 - if ( $offset >= 0 ) {
1149 - $query_args['offset'] = $offset;
1150 - } else {
1151 - $query_args['paged'] = $current_page;
750 + if ( self::has_lesson_attachment( $lesson_id ) ) {
751 + $nav_contents['files'] = array(
752 + 'label' => __( 'Files', 'tutor' ),
753 + 'value' => 'files',
754 + 'template_path' => 'single.lesson.parts.files',
755 + );
1152 756 }
1153 757
1154 - $comment_list = self::get_comments( $query_args );
1155 -
1156 - // Get total comment count to determine if there are more pages.
1157 - $total_comments = self::get_comments(
1158 - array(
1159 - 'post_id' => $lesson_id,
1160 - 'parent' => 0,
1161 - 'count' => true,
1162 - )
1163 - );
1164 -
1165 - ob_start();
1166 - tutor_load_template(
1167 - 'learning-area.lesson.comment-list',
1168 - compact( 'comment_list', 'lesson_id', 'user_id' )
1169 - );
1170 - $html = ob_get_clean();
1171 -
1172 - // Calculate if there are more items.
1173 - if ( $offset >= 0 ) {
1174 - $items_loaded = $offset + count( $comment_list );
1175 - } else {
1176 - $items_loaded = $current_page * $item_per_page;
758 + if ( self::is_comment_enabled() ) {
759 + $nav_contents['comments'] = array(
760 + 'label' => __( 'Comments', 'tutor' ),
761 + 'value' => 'comments',
762 + 'template_path' => 'single.lesson.parts.comments',
763 + );
1177 764 }
1178 - $has_more = $items_loaded < $total_comments;
1179 765
1180 - wp_send_json_success(
1181 - array(
1182 - 'html' => $html,
1183 - 'has_more' => $has_more,
1184 - 'count' => $total_comments,
1185 - )
1186 - );
1187 - }
766 + $nav_contents = apply_filters( 'tutor_lesson_single_nav_contents', $nav_contents );
1188 767
1189 - /**
1190 - * Load comment replies for dashboard.
1191 - *
1192 - * @since 4.0.0
1193 - *
1194 - * @return void
1195 - */
1196 - public function ajax_load_comment_replies() {
1197 - tutor_utils()->check_nonce();
1198 -
1199 - $comment_id = Input::post( 'comment_id', 0, Input::TYPE_INT );
1200 - $replies_order = Input::post( 'order', 'DESC' );
1201 -
1202 - if ( ! $comment_id ) {
1203 - $this->response_bad_request( __( 'Invalid comment ID', 'tutor' ) );
1204 - }
1205 -
1206 - $user_id = get_current_user_id();
1207 - $replies = self::get_comment_replies( $comment_id, $replies_order );
1208 -
1209 - ob_start();
1210 - tutor_load_template(
1211 - 'dashboard.discussions.comment-replies',
1212 - array(
1213 - 'replies' => $replies,
1214 - 'replies_order' => $replies_order,
1215 - 'user_id' => $user_id,
1216 - )
1217 - );
1218 - $html = ob_get_clean();
1219 -
1220 - wp_send_json_success( array( 'html' => $html ) );
1221 - }
1222 -
1223 - /**
1224 - * Get lesson content type info with video duration
1225 - *
1226 - * @since 4.0.0
1227 - *
1228 - * @param WP_Post $lesson Lesson post.
1229 - *
1230 - * @return string
1231 - */
1232 - public static function get_content_type_info( WP_Post $lesson ) {
1233 - $video_info = tutor_utils()->get_video_info( $lesson->ID );
1234 - $lesson_type = __( 'Reading', 'tutor' );
1235 -
1236 - if ( $video_info ) {
1237 - $lesson_type = __( 'Video', 'tutor' );
1238 - $playtime = $video_info->playtime ?? '';
1239 -
1240 - // Check if the playtime is actually a valid, positive duration.
1241 - if ( ! empty( $playtime ) ) {
1242 - /* translators: %s: duration in minutes */
1243 - $lesson_type = sprintf( __( 'Video - %s mins', 'tutor' ), $playtime );
1244 - }
1245 - }
1246 -
1247 - return $lesson_type;
768 + return $nav_contents;
1248 769 }
1249 770 }