PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 3.9.11
Tutor LMS – eLearning and online course solution v3.9.11
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 11 months ago Admin.php 2 months ago Ajax.php 9 months ago Announcements.php 1 year ago Assets.php 2 months ago Backend_Page_Trait.php 1 year ago BaseController.php 1 year ago Config.php 11 months ago Container.php 11 months ago Course.php 2 months ago Course_Embed.php 3 years ago Course_Filter.php 1 year ago Course_List.php 5 months ago Course_Settings_Tabs.php 1 year ago Course_Widget.php 1 year ago Custom_Validation.php 3 years ago Dashboard.php 1 year ago Earnings.php 9 months ago FormHandler.php 2 years ago Frontend.php 1 year ago Gutenberg.php 1 year ago Icon.php 8 months ago Input.php 1 year ago Instructor.php 2 months ago Instructors_List.php 2 months ago Lesson.php 8 months ago Options_V2.php 7 months ago Permalink.php 2 years ago Post_types.php 1 year ago Private_Course_Access.php 1 year ago Q_And_A.php 10 months ago Question_Answers_List.php 11 months ago Quiz.php 5 months ago QuizBuilder.php 3 months ago Quiz_Attempts_List.php 9 months ago RestAPI.php 2 years ago Reviews.php 9 months ago Rewrite_Rules.php 2 years ago Shortcode.php 9 months ago Singleton.php 1 year ago Student.php 2 months ago Students_List.php 1 year ago Taxonomies.php 1 year ago Template.php 9 months ago Theme_Compatibility.php 3 years ago Tools.php 1 year ago Tools_V2.php 1 year ago Tutor.php 2 months ago TutorEDD.php 1 year ago Tutor_Base.php 2 years ago Tutor_Setup.php 8 months ago Upgrader.php 9 months ago User.php 4 months ago Utils.php 2 months ago Video_Stream.php 3 years ago WhatsNew.php 9 months ago Withdraw.php 1 year ago Withdraw_Requests_List.php 11 months ago WooCommerce.php 7 months ago
Lesson.php
755 lines
1 <?php
2 /**
3 * Manage Lesson
4 *
5 * @package Tutor
6 * @author Themeum <support@themeum.com>
7 * @link https://themeum.com
8 * @since 1.0.0
9 */
10
11 namespace TUTOR;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 use Tutor\Helpers\HttpHelper;
18 use Tutor\Helpers\ValidationHelper;
19 use Tutor\Models\LessonModel;
20 use Tutor\Traits\JsonResponse;
21
22 /**
23 * Lesson class
24 *
25 * @since 1.0.0
26 */
27 class Lesson extends Tutor_Base {
28 use JsonResponse;
29
30 /**
31 * Register hooks
32 *
33 * @since 1.0.0
34 * @since 3.7.0 param register hook added.
35 *
36 * @param bool $register_hooks register hooks or not.
37 *
38 * @return void
39 */
40 public function __construct( $register_hooks = true ) {
41 parent::__construct();
42
43 if ( ! $register_hooks ) {
44 return;
45 }
46
47 add_action( 'save_post_' . $this->lesson_post_type, array( $this, 'save_lesson_meta' ) );
48
49 add_action( 'wp_ajax_tutor_lesson_details', array( $this, 'ajax_lesson_details' ) );
50 add_action( 'wp_ajax_tutor_save_lesson', array( $this, 'ajax_save_lesson' ) );
51 add_action( 'wp_ajax_tutor_delete_lesson', array( $this, 'ajax_delete_lesson' ) );
52
53 add_filter( 'get_sample_permalink', array( $this, 'change_lesson_permalink' ), 10, 2 );
54
55 /**
56 * Frontend Action
57 */
58 add_action( 'template_redirect', array( $this, 'mark_lesson_complete' ) );
59
60 add_action( 'wp_ajax_tutor_render_lesson_content', array( $this, 'tutor_render_lesson_content' ) );
61
62 /**
63 * For public course access
64 */
65 add_action( 'wp_ajax_nopriv_tutor_render_lesson_content', array( $this, 'tutor_render_lesson_content' ) );
66
67 /**
68 * Autoplay next video
69 *
70 * @since 1.4.9
71 */
72 add_action( 'wp_ajax_autoload_next_course_content', array( $this, 'autoload_next_course_content' ) );
73
74 /**
75 * Load next course item after click complete button
76 *
77 * @since 1.5.3
78 */
79 add_action( 'tutor_lesson_completed_after', array( $this, 'tutor_lesson_completed_after' ), 999 );
80
81 /**
82 * Lesson comment & reply ajax handler
83 *
84 * @since 2.0.0
85 */
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' ) );
89 }
90
91 /**
92 * Manage load more & comment create
93 *
94 * @since 2.0.6
95 * @return void send wp json data
96 */
97 public function tutor_single_course_lesson_load_more() {
98 tutor_utils()->checking_nonce();
99 $comment = Input::post( 'comment', '', Input::TYPE_KSES_POST );
100 if ( 'tutor_create_lesson_comment' === Input::post( 'action' ) && strlen( $comment ) > 0 ) {
101 $comment_data = array(
102 'comment_content' => $comment,
103 'comment_post_ID' => Input::post( 'comment_post_ID', 0, Input::TYPE_INT ),
104 'comment_parent' => Input::post( 'comment_parent', 0, Input::TYPE_INT ),
105 );
106 self::create_comment( $comment_data );
107 do_action( 'tutor_new_comment_added', $comment_data );
108 }
109 ob_start();
110 tutor_load_template( 'single.lesson.comment' );
111 $html = ob_get_clean();
112 wp_send_json_success( array( 'html' => $html ) );
113 }
114
115 /**
116 * Saving lesson meta and assets
117 *
118 * @since 1.0.0
119 *
120 * @param integer $post_ID post ID.
121 *
122 * @return void
123 */
124 public function save_lesson_meta( $post_ID ) {
125 $thumbnail_id = Input::post( 'thumbnail_id', 0, Input::TYPE_INT );
126 if ( $thumbnail_id ) {
127 update_post_meta( $post_ID, '_thumbnail_id', $thumbnail_id );
128 } else {
129 delete_post_meta( $post_ID, '_thumbnail_id' );
130 }
131
132 $video_source = sanitize_text_field( tutor_utils()->array_get( 'video.source', $_POST ) ); //phpcs:ignore
133 if ( '-1' === $video_source ) {
134 delete_post_meta( $post_ID, '_video' );
135 } elseif ( $video_source ) {
136
137 // Sanitize data through helper method.
138 $video = Input::sanitize_array(
139 $_POST['video'] ?? array(), //phpcs:ignore
140 array(
141 'source_external_url' => 'esc_url',
142 'source_embedded' => 'wp_kses_post',
143 ),
144 true
145 );
146 update_post_meta( $post_ID, '_video', $video );
147 }
148
149 // Attachments.
150 $attachments = array();
151 // phpcs:disable WordPress.Security.NonceVerification.Missing
152 if ( ! empty( $_POST['tutor_attachments'] ) ) {
153 //phpcs:ignore -- data sanitized through helper method.
154 $attachments = tutor_utils()->sanitize_array( wp_unslash( $_POST['tutor_attachments'] ) );
155 $attachments = array_unique( $attachments );
156 }
157
158 /**
159 * If !empty attachment then update meta else
160 * delete meta key to prevent empty data in db
161 *
162 * @since 1.8.9
163 */
164 if ( ! empty( $attachments ) ) {
165 update_post_meta( $post_ID, '_tutor_attachments', $attachments );
166 } else {
167 delete_post_meta( $post_ID, '_tutor_attachments' );
168 }
169 }
170
171 /**
172 * Get lesson details data.
173 *
174 * @since 3.0.0
175 *
176 * @return void
177 */
178 public function ajax_lesson_details() {
179 if ( ! tutor_utils()->is_nonce_verified() ) {
180 $this->json_response( tutor_utils()->error_message( 'nonce' ), null, HttpHelper::STATUS_BAD_REQUEST );
181 }
182
183 $topic_id = Input::post( 'topic_id', 0, Input::TYPE_INT );
184 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
185
186 if ( ! tutor_utils()->can_user_manage( 'topic', $topic_id ) ) {
187 $this->json_response(
188 tutor_utils()->error_message(),
189 null,
190 HttpHelper::STATUS_FORBIDDEN
191 );
192 }
193
194 if ( 0 !== $lesson_id ) {
195 if ( ! tutor_utils()->can_user_manage( 'lesson', $lesson_id ) ) {
196 $this->json_response(
197 tutor_utils()->error_message(),
198 null,
199 HttpHelper::STATUS_FORBIDDEN
200 );
201 }
202 }
203
204 $data = LessonModel::get_lesson_details( $lesson_id );
205
206 $this->json_response(
207 __( 'Lesson data fetched successfully', 'tutor' ),
208 $data
209 );
210 }
211
212 /**
213 * Create or update lesson.
214 *
215 * @since 1.0.0
216 * @since 1.5.1 updated
217 * @since 3.0.0 refactor and response updated.
218 *
219 * @return void
220 */
221 public function ajax_save_lesson() {
222 if ( ! tutor_utils()->is_nonce_verified() ) {
223 $this->json_response( tutor_utils()->error_message( 'nonce' ), null, HttpHelper::STATUS_BAD_REQUEST );
224 }
225
226 /**
227 * Allow iframe inside lesson content to support
228 * embed video & other stuff
229 *
230 * @since 2.1.6
231 */
232 add_filter( 'wp_kses_allowed_html', Input::class . '::allow_iframe', 10, 2 );
233
234 $is_update = false;
235
236 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
237 $topic_id = Input::post( 'topic_id', 0, Input::TYPE_INT );
238
239 if ( $lesson_id ) {
240 $is_update = true;
241 }
242
243 if ( ! tutor_utils()->can_user_manage( 'topic', $topic_id ) ) {
244 $this->json_response(
245 tutor_utils()->error_message(),
246 null,
247 HttpHelper::STATUS_FORBIDDEN
248 );
249 }
250
251 $title = Input::post( 'title' );
252 $description = Input::post( 'description', '', Input::TYPE_KSES_POST );
253 $is_html_active = Input::post( 'is_html_active' ) === 'true' ? true : false;
254 $raw_html_content = Input::post( 'tutor_lesson_modal_editor', '', Input::TYPE_KSES_POST );
255 $post_content = $is_html_active ? $raw_html_content : $description;
256
257 $rules = array(
258 'topic_id' => 'required|numeric',
259 'lesson_id' => 'if_input|numeric',
260 );
261
262 //phpcs:ignore WordPress.Security.NonceVerification.Missing
263 $params = Input::sanitize_array( $_POST, array( 'description' => 'wp_kses_post' ) );
264
265 $validation = ValidationHelper::validate( $rules, $params );
266 if ( ! $validation->success ) {
267 $this->json_response(
268 __( 'Invalid inputs', 'tutor' ),
269 $validation->errors,
270 HttpHelper::STATUS_UNPROCESSABLE_ENTITY
271 );
272 }
273
274 $lesson_data = array(
275 'post_type' => $this->lesson_post_type,
276 'post_title' => wp_slash( $title ), // Note: Added wp_slash to support latex syntaxes.
277 'post_name' => sanitize_title( $title ),
278 'post_content' => wp_slash( $post_content ),
279 'post_status' => 'publish',
280 'comment_status' => 'open',
281 'post_author' => get_current_user_id(),
282 'post_parent' => $topic_id,
283 );
284
285 if ( ! $is_update ) {
286 $lesson_data['menu_order'] = tutor_utils()->get_next_course_content_order_id( $topic_id );
287 $lesson_id = wp_insert_post( $lesson_data );
288
289 if ( $lesson_id ) {
290 do_action( 'tutor/lesson/created', $lesson_id );
291 } else {
292 $this->json_response(
293 tutor_utils()->error_message(),
294 null,
295 HttpHelper::STATUS_INTERNAL_SERVER_ERROR
296 );
297 }
298 } else {
299 $lesson_data['ID'] = $lesson_id;
300
301 if ( ! tutor_utils()->can_user_manage( 'lesson', $lesson_id ) ) {
302 $this->json_response(
303 tutor_utils()->error_message(),
304 null,
305 HttpHelper::STATUS_FORBIDDEN
306 );
307 }
308
309 do_action( 'tutor/lesson_update/before', $lesson_id );
310 wp_update_post( $lesson_data );
311 do_action( 'tutor/lesson_update/after', $lesson_id );
312 }
313
314 if ( $is_update ) {
315 $this->json_response(
316 __( 'Lesson updated successfully', 'tutor' ),
317 $lesson_id
318 );
319 } else {
320 $this->json_response(
321 __( 'Lesson created successfully', 'tutor' ),
322 $lesson_id,
323 HttpHelper::STATUS_CREATED
324 );
325 }
326 }
327
328 /**
329 * Delete Lesson from course builder by ID
330 *
331 * @since 1.0.0
332 * @since 3.0.0 refactor and update response.
333 *
334 * @return void
335 */
336 public function ajax_delete_lesson() {
337 tutor_utils()->check_nonce();
338
339 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
340
341 if ( ! tutor_utils()->can_user_manage( 'lesson', $lesson_id ) ) {
342 $this->json_response(
343 tutor_utils()->error_message(),
344 null,
345 HttpHelper::STATUS_FORBIDDEN
346 );
347 }
348
349 $content = __( 'Lesson', 'tutor' );
350 $post_type = get_post_type( $lesson_id );
351 if ( tutor()->assignment_post_type === $post_type ) {
352 $content = __( 'Assignment', 'tutor' );
353 }
354
355 do_action( 'tutor_before_delete_course_content', 0, $lesson_id );
356
357 wp_delete_post( $lesson_id, true );
358 /* translators: %s refers to the name of the content being deleted */
359 $this->json_response( sprintf( __( '%s deleted successfully', 'tutor' ), $content ) );
360 }
361
362
363 /**
364 * Changed the URI based
365 *
366 * @since 1.0.0
367 *
368 * @param string $uri URI.
369 * @param integer $lesson_id lesson ID.
370 *
371 * @return string
372 */
373 public function change_lesson_permalink( $uri, $lesson_id ) {
374 $post = get_post( $lesson_id );
375
376 if ( $post && $post->post_type === $this->lesson_post_type ) {
377 $uri_base = trailingslashit( site_url() );
378
379 $sample_course = 'sample-course';
380 $is_course = tutor_utils()->get_course_id_by( 'lesson', get_the_ID() );
381 if ( $is_course ) {
382 $course = get_post( $is_course );
383 if ( $course ) {
384 $sample_course = $course->post_name;
385 }
386 }
387
388 $new_course_base = $uri_base . "course/{$sample_course}/lesson/%pagename%/";
389 $uri[0] = $new_course_base;
390 }
391
392 return $uri;
393 }
394
395 /**
396 * Mark lesson completed
397 *
398 * @since 1.0.0
399 *
400 * @return void
401 */
402 public function mark_lesson_complete() {
403 if ( 'tutor_complete_lesson' !== Input::post( 'tutor_action' ) ) {
404 return;
405 }
406 // Checking nonce.
407 tutor_utils()->checking_nonce();
408
409 $user_id = get_current_user_id();
410
411 // TODO: need to show view if not signed_in.
412 if ( ! $user_id ) {
413 die( esc_html__( 'Please Sign-In', 'tutor' ) );
414 }
415
416 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
417
418 if ( ! $lesson_id ) {
419 return;
420 }
421
422 $validated = apply_filters( 'tutor_validate_lesson_complete', true, $user_id, $lesson_id );
423 if ( ! $validated ) {
424 return;
425 }
426
427 do_action( 'tutor_lesson_completed_before', $lesson_id );
428 /**
429 * Marking lesson at user meta, meta format, _tutor_completed_lesson_id_{id} and value = tutor_time();
430 */
431 LessonModel::mark_lesson_complete( $lesson_id );
432
433 do_action( 'tutor_lesson_completed_email_after', $lesson_id, $user_id );
434 do_action( 'tutor_lesson_completed_after', $lesson_id, $user_id );
435 }
436
437 /**
438 * Render the lesson content
439 *
440 * @since 1.0.0
441 *
442 * @return void
443 */
444 public function tutor_render_lesson_content() {
445 tutor_utils()->checking_nonce();
446
447 $lesson_id = Input::post( 'lesson_id', 0, Input::TYPE_INT );
448
449 $ancestors = get_post_ancestors( $lesson_id );
450 $course_id = ! empty( $ancestors ) ? array_pop( $ancestors ) : $lesson_id;
451
452 // Course must be public or current user must be enrolled to access this lesson.
453 if ( get_post_meta( $course_id, '_tutor_is_public_course', true ) !== 'yes' && ! tutor_utils()->is_enrolled( $course_id ) ) {
454
455 $is_admin = tutor_utils()->has_user_role( 'administrator' );
456 $allowed = $is_admin ? true : tutor_utils()->is_instructor_of_this_course( get_current_user_id(), $course_id );
457
458 if ( ! $allowed ) {
459 http_response_code( 400 );
460 exit;
461 }
462 }
463
464 ob_start();
465 global $post;
466
467 $post = get_post( $lesson_id ); //phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
468 setup_postdata( $post );
469 tutor_lesson_content();
470 wp_reset_postdata();
471
472 $html = ob_get_clean();
473
474 wp_send_json_success( array( 'html' => $html ) );
475 }
476
477 /**
478 * Load next course item automatically
479 *
480 * @since 1.4.9
481 *
482 * @return void
483 */
484 public function autoload_next_course_content() {
485 tutor_utils()->checking_nonce();
486
487 $post_id = Input::post( 'post_id', 0, Input::TYPE_INT );
488 $content_id = tutor_utils()->get_post_id( $post_id );
489 $contents = tutor_utils()->get_course_prev_next_contents_by_id( $content_id );
490
491 $autoload_course_content = (bool) get_tutor_option( 'autoload_next_course_content' );
492 $next_url = false;
493 if ( $autoload_course_content ) {
494 $next_url = get_the_permalink( $contents->next_id );
495 }
496 wp_send_json_success( array( 'next_url' => $next_url ) );
497 }
498
499 /**
500 * Load next course item after click complete button
501 *
502 * @since 1.5.3
503 *
504 * @param integer $content_id content ID.
505 * @return void
506 */
507 public function tutor_lesson_completed_after( $content_id ) {
508 $contents = tutor_utils()->get_course_prev_next_contents_by_id( $content_id );
509 $autoload_course_content = (bool) get_tutor_option( 'autoload_next_course_content' );
510 if ( $autoload_course_content ) {
511 wp_safe_redirect( get_the_permalink( $contents->next_id ) );
512 } else {
513 wp_safe_redirect( get_the_permalink( $content_id ) );
514 }
515 die();
516 }
517
518 /**
519 * Replay lesson comment
520 *
521 * @since 1.0.0
522 *
523 * @return void|null
524 */
525 public function reply_lesson_comment() {
526 tutor_utils()->checking_nonce();
527 $comment = Input::post( 'comment', '', Input::TYPE_KSES_POST );
528 if ( 0 === strlen( $comment ) ) {
529 wp_send_json_error();
530 return;
531 }
532
533 $comment_data = array(
534 'comment_content' => $comment,
535 'comment_post_ID' => Input::post( 'comment_post_ID', 0, Input::TYPE_INT ),
536 'comment_parent' => Input::post( 'comment_parent', 0, Input::TYPE_INT ),
537 );
538 $comment_id = self::create_comment( $comment_data );
539 if ( false === $comment_id ) {
540 wp_send_json_error();
541 return;
542 }
543 $reply = get_comment( $comment_id );
544 do_action( 'tutor_reply_lesson_comment_thread', $comment_id, $comment_data );
545
546 ob_start();
547 ?>
548 <div class="tutor-comments-list tutor-child-comment tutor-mt-32" id="lesson-comment-<?php echo esc_attr( $reply->comment_ID ); ?>">
549 <div class="comment-avatar">
550 <img src="<?php echo esc_url( get_avatar_url( $reply->user_id ) ); ?>" alt="">
551 </div>
552 <div class="tutor-single-comment">
553 <div class="tutor-actual-comment tutor-mb-12">
554 <div class="tutor-comment-author">
555 <span class="tutor-fs-6 tutor-fw-bold">
556 <?php echo esc_html( $reply->comment_author ); ?>
557 </span>
558 <span class="tutor-fs-7 tutor-ml-0 tutor-ml-sm-10">
559 <?php echo esc_html( human_time_diff( strtotime( $reply->comment_date ), tutor_time() ) . __( ' ago', 'tutor' ) ); ?>
560 </span>
561 </div>
562 <div class="tutor-comment-text tutor-fs-6 tutor-mt-4">
563 <?php echo esc_html( $reply->comment_content ); ?>
564 </div>
565 </div>
566 </div>
567 </div>
568 <?php
569 $html = ob_get_clean();
570 wp_send_json_success( array( 'html' => $html ) );
571 }
572
573 /**
574 * Get comments
575 *
576 * @since 2.0.6
577 * @see Checkout arguments details: https://developer.wordpress.org/reference/classes/wp_comment_query/__construct/
578 *
579 * @param array $args arguments.
580 * @return mixed based on arguments
581 */
582 public static function get_comments( array $args ) {
583 $args['type'] = 'comment';
584 $comments = get_comments( $args );
585 return $comments;
586 }
587
588 /**
589 * Create comment
590 *
591 * @since 1.0.0
592 *
593 * @param array $request request.
594 * @return mixed comment id on success, false on failure
595 */
596 public static function create_comment( array $request ) {
597 $current_user = wp_get_current_user();
598 $default_data = array(
599 'comment_content' => '',
600 'comment_post_ID' => '',
601 'comment_parent' => '',
602 'user_id' => $current_user->ID,
603 'comment_author' => $current_user->user_login,
604 'comment_author_email' => $current_user->user_email,
605 'comment_author_url' => $current_user->user_url,
606 'comment_agent' => 'Tutor',
607 );
608 $comment_data = wp_parse_args( $request, $default_data );
609 return wp_insert_comment( $comment_data );
610 }
611
612 /**
613 * Check if lesson has content
614 *
615 * @since 3.9.0
616 *
617 * @param int $lesson_id Lesson ID.
618 *
619 * @return bool True if lesson has content, false otherwise.
620 */
621 public static function has_lesson_content( $lesson_id ) {
622 /**
623 * If lesson has no content, lesson tab will be hidden.
624 * To enable elementor and SCORM, only admin can see lesson tab.
625 *
626 * @since 2.2.2
627 */
628 return apply_filters(
629 'tutor_has_lesson_content',
630 User::is_admin() || ! in_array( trim( get_the_content() ), array( null, '', '&nbsp;' ), true ),
631 $lesson_id
632 );
633 }
634
635 /**
636 * Check if lesson has attachments
637 *
638 * @since 3.9.0
639 *
640 * @param int $lesson_id Lesson ID.
641 *
642 * @return bool True if lesson has attachments, false otherwise.
643 */
644 public static function has_lesson_attachment( $lesson_id ) {
645 return count( tutor_utils()->get_attachments( $lesson_id ) ) > 0;
646 }
647
648 /**
649 * Check if comments are enabled for lessons
650 *
651 * @since 3.9.0
652 *
653 * @return bool True if comments are enabled, false otherwise.
654 */
655 public static function is_comment_enabled() {
656 return tutor_utils()->get_option( 'enable_comment_for_lesson' ) && comments_open() && is_user_logged_in();
657 }
658
659 /**
660 * Check if lesson has comments
661 *
662 * @since 3.9.0
663 *
664 * @param int $lesson_id Lesson ID.
665 *
666 * @return int Number of comments for the lesson.
667 */
668 public static function has_lesson_comment( $lesson_id ) {
669 return (int) get_comments_number( $lesson_id );
670 }
671
672 /**
673 * Get navigation items for lesson single page
674 *
675 * @since 3.9.0
676 *
677 * @param int $lesson_id Lesson ID.
678 *
679 * @return array navigation items array
680 */
681 public static function get_nav_items( $lesson_id ) {
682 $nav_items = array();
683
684 if ( self::has_lesson_content( $lesson_id ) ) {
685 $nav_items['overview'] = array(
686 'label' => __( 'Overview', 'tutor' ),
687 'value' => 'overview',
688 'icon' => 'document-text',
689 );
690 }
691
692 if ( self::has_lesson_attachment( $lesson_id ) ) {
693 $nav_items['files'] = array(
694 'label' => __( 'Exercise Files', 'tutor' ),
695 'value' => 'files',
696 'icon' => 'paperclip',
697 );
698 }
699
700 if ( self::is_comment_enabled() ) {
701 $nav_items['comments'] = array(
702 'label' => __( 'Comments', 'tutor' ),
703 'value' => 'comments',
704 'icon' => 'comment',
705 );
706 }
707
708 $nav_items = apply_filters( 'tutor_lesson_single_nav_items', $nav_items );
709 $nav_items = array_values( $nav_items );
710
711 return $nav_items;
712 }
713
714 /**
715 * Get navigation contents for lesson single page
716 *
717 * @since 3.9.0
718 *
719 * @param int $lesson_id Lesson ID.
720 *
721 * @return array navigation contents array
722 */
723 public static function get_nav_contents( $lesson_id ) {
724 $nav_contents = array();
725
726 if ( self::has_lesson_content( $lesson_id ) ) {
727 $nav_contents['overview'] = array(
728 'label' => __( 'Overview', 'tutor' ),
729 'value' => 'overview',
730 'template_path' => 'single.lesson.parts.overview',
731 );
732 }
733
734 if ( self::has_lesson_attachment( $lesson_id ) ) {
735 $nav_contents['files'] = array(
736 'label' => __( 'Files', 'tutor' ),
737 'value' => 'files',
738 'template_path' => 'single.lesson.parts.files',
739 );
740 }
741
742 if ( self::is_comment_enabled() ) {
743 $nav_contents['comments'] = array(
744 'label' => __( 'Comments', 'tutor' ),
745 'value' => 'comments',
746 'template_path' => 'single.lesson.parts.comments',
747 );
748 }
749
750 $nav_contents = apply_filters( 'tutor_lesson_single_nav_contents', $nav_contents );
751
752 return $nav_contents;
753 }
754 }
755