PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 4.0.0
Tutor LMS – eLearning and online course solution v4.0.0
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 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 / Template.php
tutor / classes Last commit date
Addons.php 22 hours ago Admin.php 22 hours ago Ajax.php 22 hours ago Announcements.php 22 hours ago Assets.php 22 hours ago Backend_Page_Trait.php 1 year ago BaseController.php 1 year ago Config.php 22 hours ago Container.php 11 months ago Course.php 22 hours ago Course_Embed.php 3 years ago Course_Filter.php 22 hours ago Course_List.php 22 hours ago Course_Settings_Tabs.php 22 hours ago Course_Widget.php 1 year ago Custom_Validation.php 22 hours ago Dashboard.php 22 hours ago Earnings.php 9 months ago FormHandler.php 22 hours ago Frontend.php 22 hours ago Gutenberg.php 1 year ago Icon.php 22 hours ago Input.php 22 hours ago Instructor.php 22 hours ago Instructors_List.php 22 hours ago Lesson.php 22 hours ago Options_V2.php 22 hours ago Permalink.php 22 hours ago Post_types.php 1 day ago Private_Course_Access.php 22 hours ago Q_And_A.php 22 hours ago Question_Answers_List.php 11 months ago Quiz.php 22 hours ago QuizBuilder.php 22 hours ago Quiz_Attempts_List.php 22 hours ago RestAPI.php 2 years ago Reviews.php 22 hours ago Rewrite_Rules.php 2 years ago SampleCourse.php 22 hours ago Shortcode.php 22 hours ago Singleton.php 1 year ago Student.php 22 hours ago Students_List.php 1 year ago Taxonomies.php 1 year ago Template.php 22 hours ago Theme_Compatibility.php 3 years ago Tools.php 1 year ago Tools_V2.php 4 weeks ago Tutor.php 22 hours ago TutorEDD.php 22 hours ago Tutor_Base.php 2 years ago Tutor_Setup.php 22 hours ago Upgrader.php 22 hours ago User.php 22 hours ago UserPreference.php 22 hours ago Utils.php 22 hours ago Video_Stream.php 3 years ago WhatsNew.php 10 months ago Withdraw.php 22 hours ago Withdraw_Requests_List.php 11 months ago WooCommerce.php 22 hours ago
Template.php
601 lines
1 <?php
2 /**
3 * Template Class
4 *
5 * @package Tutor\Template
6 * @author Themeum <support@themeum.com>
7 * @link https://themeum.com
8 * @since 1.0.0
9 */
10
11 namespace TUTOR;
12
13 use Tutor\Helpers\UrlHelper;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Handle template before include
21 *
22 * @since 1.0.0
23 */
24 class Template extends Tutor_Base {
25
26 /**
27 * Store Shortcode Object
28 *
29 * @var Shortcode
30 */
31 public $shortcode_obj;
32
33 /**
34 * Register Hooks
35 *
36 * @since 1.0.0
37 */
38 public function __construct() {
39 parent::__construct();
40
41 /**
42 * Should Load Template Override
43 * Integration for specially oxygen builder
44 * If we found false of below filter, then we will not use this file
45 */
46
47 $template_override = apply_filters( 'tutor_lms_should_template_override', true );
48 if ( ! $template_override ) {
49 return;
50 }
51
52 add_filter( 'template_include', array( $this, 'load_course_archive_template' ), 99 );
53 add_filter( 'template_include', array( $this, 'load_single_course_template' ), 99 );
54 add_filter( 'template_include', array( $this, 'play_private_video' ), 99 );
55 add_filter( 'tutor_single_content_template', array( $this, 'load_single_lesson_template' ), 99, 2 );
56 add_filter( 'tutor_single_content_template', array( $this, 'load_quiz_template' ), 99, 2 );
57
58 add_filter( 'template_include', array( $this, 'student_public_profile' ), 99 );
59 add_filter( 'template_include', array( $this, 'tutor_dashboard' ), 99 );
60 add_filter( 'pre_get_document_title', array( $this, 'student_public_profile_title' ) );
61
62 add_filter( 'the_content', array( $this, 'convert_static_page_to_template' ) );
63 add_action( 'pre_get_posts', array( $this, 'limit_course_query_archive' ), 99 );
64 add_filter( 'template_include', array( $this, 'load_learning_template' ) );
65
66 $this->shortcode_obj = new Shortcode( false );
67 }
68
69 /**
70 * Load default template for course
71 *
72 * @since v.1.0.0
73 *
74 * @param sting $template template name.
75 *
76 * @return bool|string
77 */
78 public function load_course_archive_template( $template ) {
79 global $wp_query;
80
81 $post_type = get_query_var( 'post_type' );
82 if ( ! is_array( $post_type ) ) {
83 $post_type = array( $post_type );
84 }
85
86 $course_category = get_query_var( 'course-category' );
87
88 if ( ( in_array( $this->course_post_type, $post_type, true ) || ! empty( $course_category ) ) && $wp_query->is_archive ) {
89 $template = tutor_get_template( 'archive-course' );
90 return $template;
91 }
92
93 return $template;
94 }
95
96 /**
97 * Limit for course archive listing
98 *
99 * Make a page to archive listing for courses
100 *
101 * @since 1.0.0
102 *
103 * @param mixed $query query argument.
104 *
105 * @return void
106 */
107 public function limit_course_query_archive( $query ) {
108 $courses_per_page = (int) tutor_utils()->get_option( 'courses_per_page', 12 );
109
110 if ( $query->is_main_query() && ! $query->is_feed() && ! is_admin() && is_page() ) {
111 $queried_object = get_queried_object();
112 if ( $queried_object instanceof \WP_Post ) {
113 $page_id = $queried_object->ID;
114 $selected_archive_page = (int) apply_filters( 'tutor_filter_course_archive_page', tutor_utils()->get_option( 'course_archive_page' ) );
115
116 if ( $page_id === $selected_archive_page ) {
117 $paged = ( get_query_var( 'paged' ) ) ? absint( get_query_var( 'paged' ) ) : 1;
118 $search_query = get_search_query();
119 query_posts(
120 array(
121 'post_type' => $this->course_post_type,
122 'paged' => $paged,
123 's' => $search_query,
124 'posts_per_page' => $courses_per_page,
125 )
126 );
127 }
128 }
129 }
130
131 if ( $query->is_archive && $query->is_main_query() && ! $query->is_feed() && ! is_admin() ) {
132 $post_type = get_query_var( 'post_type' );
133 $course_category = get_query_var( 'course-category' );
134 if ( ( $post_type === $this->course_post_type || ! empty( $course_category ) ) ) {
135 $query->set( 'posts_per_page', $courses_per_page );
136 $query->set( 'post_type', apply_filters( 'tutor_course_archive_post_types', array( $this->course_post_type ) ) );
137 $query = apply_filters( 'tutor_limit_course_archive_list_filter', $query );
138
139 $course_filter = 'newest_first';
140 if ( ! empty( Input::get( 'tutor_course_filter', '' ) ) ) {
141 $course_filter = Input::get( 'tutor_course_filter' );
142 }
143 switch ( $course_filter ) {
144 case 'newest_first':
145 $query->set( 'orderby', 'post_date' );
146 $query->set( 'order', 'desc' );
147 break;
148 case 'oldest_first':
149 $query->set( 'orderby', 'post_date' );
150 $query->set( 'order', 'asc' );
151 break;
152 case 'course_title_az':
153 $query->set( 'orderby', 'post_title' );
154 $query->set( 'order', 'asc' );
155 break;
156 case 'course_title_za':
157 $query->set( 'orderby', 'post_title' );
158 $query->set( 'order', 'desc' );
159 break;
160 }
161 }
162 }
163 }
164
165 /**
166 * Load Single Course Template
167 *
168 * @since v.1.0.0
169 *
170 * @param string $template template name to load.
171 *
172 * @return bool|string
173 */
174 public function load_single_course_template( $template ) {
175 global $wp_query;
176 if ( $wp_query->is_single && ! empty( $wp_query->query_vars['post_type'] ) && $wp_query->query_vars['post_type'] === $this->course_post_type ) {
177 // Check if the slug contains subpage of learning area.
178 if ( Input::has( 'subpage' ) ) {
179 $template = tutor_get_template( 'learning-area.index' );
180 } else {
181 do_action( 'single_course_template_before_load', get_the_ID() );
182 wp_reset_query();
183 $template = tutor_get_template( 'single-course' );
184 }
185 }
186
187 return $template;
188 }
189
190 /**
191 * Get root post parent id
192 *
193 * @param int $id post id.
194 *
195 * @return int root post id
196 */
197 private function get_root_post_parent_id( $id ) {
198 $ancestors = get_post_ancestors( $id );
199 $root = is_array( $ancestors ) ? end( $ancestors ) : null;
200
201 return is_numeric( $root ) ? $root : $id;
202 }
203
204 /**
205 * Load lesson template
206 *
207 * @since v.1.0.0
208 *
209 * @since 4.0.0 Post type argument added
210 *
211 * @param string $template template name to load.
212 * @param string $post_type Post type added.
213 *
214 * @return bool|string
215 */
216 public function load_single_lesson_template( $template, $post_type ) {
217 if ( tutor()->lesson_post_type !== $post_type ) {
218 return $template;
219 }
220
221 $is_lesson_post_type = apply_filters( 'tutor_is_lesson_post_type', true, $post_type );
222
223 if ( $is_lesson_post_type ) {
224 $page_id = get_the_ID();
225
226 do_action( 'tutor_lesson_load_before', $template );
227 setup_postdata( $page_id );
228
229 if ( is_user_logged_in() ) {
230 $has_content_access = tutor_utils()->has_enrolled_content_access( 'lesson' );
231 if ( $has_content_access ) {
232 $template = tutor_get_template( 'single-lesson' );
233 } else {
234 $template = tutor_get_template( 'single.lesson.required-enroll' ); // You need to enroll first.
235 }
236 } else {
237 $template = tutor_get_template( 'login' );
238 }
239 wp_reset_postdata();
240
241 // Forcefully show lessons if it is public and not paid.
242 $course_id = $this->get_root_post_parent_id( $page_id );
243 if ( 'yes' === get_post_meta( $course_id, '_tutor_is_public_course', true ) && ! tutor_utils()->is_course_purchasable( $course_id ) ) {
244 $template = tutor_get_template( 'single-lesson' );
245 }
246
247 return apply_filters( 'tutor_lesson_template', $template );
248 }
249
250 return $template;
251 }
252
253 /**
254 * Play the video in this url.
255 *
256 * @param string $template template to load.
257 *
258 * @return mixed
259 */
260 public function play_private_video( $template ) {
261 global $wp_query;
262
263 if ( $wp_query->is_single && ! empty( $wp_query->query_vars['lesson_video'] ) && 'true' === $wp_query->query_vars['lesson_video'] ) {
264
265 $is_public_video = apply_filters( 'tutor_video_stream_is_public', false, get_the_ID() );
266 if ( $is_public_video ) {
267 $video_info = tutor_utils()->get_video_info();
268 if ( $video_info ) {
269 $stream = new Video_Stream( $video_info->path );
270 $stream->start();
271 }
272 exit();
273 }
274
275 if ( tutor_utils()->is_course_enrolled_by_lesson() ) {
276 $video_info = tutor_utils()->get_video_info();
277 if ( $video_info ) {
278 $stream = new Video_Stream( $video_info->path );
279 $stream->start();
280 }
281 } else {
282 esc_html_e( 'Permission denied', 'tutor' );
283 }
284 exit();
285 }
286
287 return $template;
288 }
289
290 /**
291 * Tutor Dashboard Page, Responsible to show dashboard stuffs
292 *
293 * @since 1.0.0
294 *
295 * @param string $content page content.
296 *
297 * @return mixed
298 */
299 public function convert_static_page_to_template( $content ) {
300 /**
301 * Avoid rendering dynamic templates or shortcodes during head generation.
302 *
303 * Some plugins (e.g., Yoast SEO) may process `the_content` while generating
304 * frontend metadata in `wp_head`, which can cause templates or shortcodes
305 * to be rendered multiple times within the same request.
306 *
307 * @since 4.0.0
308 */
309 if ( ! is_admin() && doing_action( 'wp_head' ) ) {
310 return $content;
311 }
312
313 $page_id = get_the_ID();
314
315 // Dashboard Page.
316 $student_dashboard_page_id = (int) tutor_utils()->get_option( 'tutor_dashboard_page_id' );
317 if ( $page_id === $student_dashboard_page_id ) {
318 return $this->shortcode_obj->tutor_dashboard();
319 }
320
321 // Instructor Registration Page.
322 $instructor_register_page_page_id = (int) tutor_utils()->get_option( 'instructor_register_page' );
323 if ( $page_id === $instructor_register_page_page_id ) {
324 return $this->shortcode_obj->instructor_registration_form();
325 }
326
327 $student_register_page_id = (int) tutor_utils()->get_option( 'student_register_page' );
328 if ( $page_id === $student_register_page_id ) {
329 return $this->shortcode_obj->student_registration_form();
330 }
331
332 if ( tutor_utils()->is_monetize_by_tutor() ) {
333 $tutor_cart_page_id = (int) tutor_utils()->get_option( 'tutor_cart_page_id' );
334 if ( $page_id === $tutor_cart_page_id ) {
335 return $this->shortcode_obj->tutor_cart_page();
336 }
337
338 $tutor_checkout_page_id = (int) tutor_utils()->get_option( 'tutor_checkout_page_id' );
339 if ( $page_id === $tutor_checkout_page_id ) {
340 if ( ! apply_filters( 'tutor_should_load_checkout_page', true ) ) {
341 return '';
342 }
343
344 return $this->shortcode_obj->tutor_checkout_page();
345 }
346 }
347
348 return $content;
349 }
350
351 /**
352 * Tutor dashboard
353 *
354 * @since 1.0.0
355 *
356 * @param string $template template name.
357 *
358 * @return string
359 */
360 public function tutor_dashboard( $template ) {
361 global $wp_query;
362 $is_page = apply_filters( 'tutor_determine_is_page', $wp_query->is_page, $template );
363 if ( $is_page ) {
364 $student_dashboard_page_id = (int) tutor_utils()->get_option( 'tutor_dashboard_page_id' );
365 $student_dashboard_page_id = apply_filters( 'tutor_dashboard_page_id_filter', $student_dashboard_page_id );
366 $is_dashboard_page = apply_filters( 'tutor_determine_is_dashboard_page', get_the_ID() == $student_dashboard_page_id );
367
368 if ( $is_dashboard_page ) {
369 /**
370 * Handle if logout URL
371 *
372 * @since v.1.1.2
373 */
374 if ( tutor_utils()->array_get( 'tutor_dashboard_page', $wp_query->query_vars ) === 'logout' ) {
375 $redirect = apply_filters( 'tutor_dashboard_logout_redirect_url', get_permalink( $student_dashboard_page_id ) );
376 wp_logout();
377 wp_safe_redirect( $redirect );
378 die();
379 }
380
381 $dashboard_page = tutor_utils()->array_get( 'tutor_dashboard_page', $wp_query->query_vars );
382
383 $get_dashboard_config = tutor_utils()->tutor_dashboard_permalinks();
384 $target_dashboard_page = tutor_utils()->array_get( $dashboard_page, $get_dashboard_config );
385
386 if ( isset( $target_dashboard_page['login_require'] ) && false === $target_dashboard_page['login_require'] ) {
387 $template = tutor_load_template_part( "template-part.{$dashboard_page}" );
388 } else {
389
390 /**
391 * Load view page based on dashboard Endpoint
392 */
393 if ( is_user_logged_in() ) {
394
395 global $wp;
396 $full_path = explode( '/', trim( str_replace( get_home_url(), '', home_url( $wp->request ) ), '/' ) );
397
398 $template = tutor_get_template( 'create-course' === end( $full_path ) ? 'dashboard.create-course' : 'dashboard' );
399
400 /**
401 * Check page page permission
402 *
403 * @since 1.3.4
404 */
405 $query_var = tutor_utils()->array_get( 'tutor_dashboard_page', $wp_query->query_vars );
406 $dashboard_pages = tutor_utils()->tutor_dashboard_pages();
407 $dashboard_page_item = tutor_utils()->array_get( $query_var, $dashboard_pages );
408 $auth_cap = tutor_utils()->array_get( 'auth_cap', $dashboard_page_item );
409
410 $can_access_instructor_item = tutor()->instructor_role === $auth_cap && User::can_view_instructor_dashboard();
411
412 if ( $auth_cap && ! User::is_admin() && ! current_user_can( $auth_cap ) && ! $can_access_instructor_item
413 ) {
414 $template = tutor_get_template( 'permission-denied' );
415 }
416
417 /**
418 * Account pages of dashboard.
419 *
420 * @since 4.0.0
421 */
422 if ( Dashboard::ACCOUNT_PAGE_SLUG === $dashboard_page ) {
423 $subpage = tutor_utils()->array_get( 'tutor_dashboard_sub_page', $wp_query->query_vars, 'profile' );
424 $account_pages = Dashboard::get_account_pages();
425 $page_data = $account_pages[ $subpage ] ?? array();
426 $page_template = $page_data['template'] ?? '';
427
428 if ( file_exists( $page_template ) ) {
429 $template = tutor_get_template( 'account' );
430 }
431 }
432
433 $dashboard_subpage = tutor_utils()->array_get( 'tutor_dashboard_sub_page', $wp_query->query_vars );
434 $is_isolated = Dashboard::is_isolated_page_request( $dashboard_page, $dashboard_subpage );
435
436 if ( $is_isolated ) {
437 $template = tutor_get_template( 'dashboard-isolated' );
438 }
439 } else {
440 $template = tutor_get_template( 'login' );
441 }
442 }
443 }
444 }
445 return $template;
446 }
447
448 /**
449 * Load quiz template
450 *
451 * @since 1.0.0
452 *
453 * If course public then enrollment not required
454 *
455 * @since 2.0.2
456 * @since 4.0.0 $post_type param added.
457 *
458 * @param string $template template to load.
459 * @param string $post_type Post type.
460 *
461 * @return bool|string
462 */
463 public function load_quiz_template( $template, $post_type ) {
464 if ( tutor()->quiz_post_type !== $post_type ) {
465 return $template;
466 }
467
468 global $post;
469
470 if ( is_user_logged_in() ) {
471 $has_content_access = tutor_utils()->has_enrolled_content_access( 'quiz' );
472 $course_id = tutor_utils()->get_course_id_by_content( $post );
473 $is_public = Course_List::is_public( $course_id );
474
475 // if public course don't need to be enrolled.
476 if ( $has_content_access || $is_public ) {
477 $template = tutor_get_template( 'single-quiz' );
478 } else {
479 $template = tutor_get_template( 'single.lesson.required-enroll' ); // You need to enroll first.
480 }
481 } else {
482 $template = tutor_get_template( 'login' );
483 }
484
485 return $template;
486 }
487
488 /**
489 * Student public profile
490 *
491 * @since 1.0.0
492 *
493 * @param string $template profile template.
494 *
495 * @return bool|string
496 */
497 public function student_public_profile( $template ) {
498 global $wp_query;
499 $query_var = $wp_query->query_vars;
500 if ( ! empty( $wp_query->query['tutor_profile_username'] ) ) {
501 $template = tutor_get_template( 'public-profile' );
502 }
503
504 return $template;
505 }
506
507 /**
508 * Show student Profile
509 *
510 * @since 1.0.0
511 *
512 * @return string
513 */
514 public function student_public_profile_title() {
515 global $wp_query;
516
517 if ( ! empty( $wp_query->query['tutor_profile_username'] ) ) {
518 global $wpdb;
519
520 $user_name = sanitize_text_field( $wp_query->query['tutor_profile_username'] );
521 $user = $wpdb->get_row( $wpdb->prepare( "SELECT display_name from {$wpdb->users} WHERE user_login = %s limit 1; ", $user_name ) );
522
523 if ( ! empty( $user->display_name ) ) {
524 return sprintf( "%s's %s", $user->display_name, __( 'Profile Page', 'tutor' ) );
525 }
526 }
527 return '';
528 }
529
530 /**
531 * Load learning template
532 *
533 * @since 4.0.0
534 *
535 * @param string $template template to load.
536 *
537 * @return string
538 */
539 public function load_learning_template( string $template ): string {
540 if ( tutor_utils()->is_learning_area() ) {
541 $user_id = get_current_user_id();
542 $post_type = get_post_type();
543 $post_id = get_the_ID();
544 $course_id = tutor()->course_post_type === $post_type ? $post_id : tutor_utils()->get_course_id_by_subcontent( $post_id );
545 if ( ! in_array( get_post_status( $course_id ), array( 'publish', 'private' ), true ) && ! tutor_utils()->has_user_course_content_access( $user_id, $course_id ) ) {
546 global $wp_query;
547 $wp_query->set_404();
548 status_header( 404 );
549 return get_404_template();
550 }
551
552 $legacy_mode = Options_V2::LEARNING_MODE_LEGACY === tutor_utils()->get_option( 'learning_mode' );
553
554 $template_path = apply_filters( 'tutor_single_content_template', $template, $post_type );
555
556 $template = $legacy_mode ? $template_path : tutor_get_template( 'learning-area.index' );
557 }
558
559 return $template;
560 }
561
562 /**
563 * Make learning area sub pages nav items
564 *
565 * @since 4.0.0
566 *
567 * @param string $base_url Nav items base url.
568 *
569 * @return array
570 */
571 public static function make_learning_area_sub_page_nav_items( $base_url = '' ): array {
572 if ( empty( $base_url ) ) {
573 $base_url = get_permalink();
574 }
575
576 $menu_items = apply_filters( 'tutor_learning_area_sub_page_nav_item', array(), $base_url );
577
578 $menu_items['course-info'] = array(
579 'title' => __( 'Course Info', 'tutor' ),
580 'icon' => Icon::INFO_OCTAGON,
581 'url' => UrlHelper::add_query_params( $base_url, array( 'subpage' => 'course-info' ) ),
582 'template' => tutor_get_template( 'learning-area.subpages.course-info' ),
583 );
584
585 return apply_filters( 'tutor_learning_area_sub_page_menu_items', $menu_items, $base_url );
586 }
587
588 /**
589 * Get learning area active subpage
590 *
591 * @since 4.0.0
592 *
593 * @return string
594 */
595 public static function learning_area_active_subpage(): string {
596 $active_menu = Input::get( 'subpage', '' );
597
598 return apply_filters( 'tutor_learning_area_active_subpage', $active_menu );
599 }
600 }
601