PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.1.6.9.4
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.1.6.9.4
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
learnpress / inc / class-lp-page-controller.php

class-lp-page-controller.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.1.6.9.4, at inc/class-lp-page-controller.php

1,065 lines 29.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class LP_Page_Controller
5 */
6 class LP_Page_Controller {
7 protected static $_instance = null;
8
9 /**
10 * Store the object has queried by WP.
11 *
12 * @var int
13 */
14 protected $_queried_object = 0;
15
16 /**
17 * @var int
18 */
19 protected $_filter_content_priority = 10000;
20
21 /**
22 * Flag for 404 content.
23 *
24 * @var bool
25 */
26 protected $_is_404 = false;
27
28 /**
29 * LP_Page_Controller constructor.
30 */
31 protected function __construct() {
32 add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ), 10 );
33 add_filter( 'template_include', array( $this, 'template_loader' ), 10 );
34 add_filter( 'template_include', array( $this, 'check_pages' ), 30 );
35 add_filter( 'template_include', array( $this, 'auto_shortcode' ), 50 );
36
37 add_filter( 'the_post', array( $this, 'setup_data_for_item_course' ) );
38 add_filter( 'request', array( $this, 'remove_course_post_format' ), 1 );
39
40 add_shortcode( 'learn_press_archive_course', array( $this, 'archive_content' ) );
41 add_filter( 'pre_get_document_title', array( $this, 'set_title_pages' ), 20, 1 );
42
43 // Yoast seo
44 add_filter( 'wpseo_opengraph_desc', array( $this, 'lp_desc_item_yoast_seo' ), 11, 1 );
45 add_filter( 'wpseo_metadesc', array( $this, 'lp_desc_item_yoast_seo' ), 11, 1 );
46
47 // edit link item course when form search default wp
48 add_filter( 'post_type_link', array( $this, 'post_type_link' ), 10, 2 );
49
50 // Set link profile to admin menu
51 add_action( 'admin_bar_menu', array( $this, 'learn_press_edit_admin_bar' ) );
52 add_action( 'plugins_loaded', array( $this, 'lp_rest_api_called' ) );
53
54 // Web hook detected PayPal request.
55 add_action( 'init', [ $this, 'check_webhook_paypal_ipn' ] );
56 }
57
58 /**
59 * Optimize when Rest API LP called
60 *
61 * @return void
62 */
63 public function lp_rest_api_called() {
64 if ( LP_Helper::isRestApiLP() ) {
65 if ( ! defined( 'SHORTINIT' ) ) {
66 define( 'SHORTINIT', true );
67 }
68
69 // Remove hook wp_loaded because query default WP run on it (it hooks 'pre_get_posts',...)
70 remove_all_actions( 'wp_loaded' );
71 }
72 }
73
74 /**
75 * Check notify papal call when done.
76 *
77 * Set in param notify_url on @see LP_Gateway_Paypal::get_paypal_args()
78 */
79 public function check_webhook_paypal_ipn() {
80 //error_log( 'xxx:' . json_encode( $_POST, JSON_UNESCAPED_UNICODE ) );
81
82 // Paypal payment done
83 if ( ! isset( $_GET['paypal_notify'] ) ) {
84 return;
85 }
86
87 if ( ! isset( $_POST['ipn_track_id'] ) ) {
88 return;
89 }
90
91 try {
92 $paypal = new LP_Gateway_Paypal();
93 $verify = $paypal->validate_ipn();
94
95 if ( $verify ) {
96 if ( isset( $_POST['custom'] ) ) {
97 $data_order = json_decode( LP_Helper::sanitize_params_submitted( $_POST['custom'] ) );
98
99 if ( json_last_error() === JSON_ERROR_NONE ) {
100 $order_id = $data_order->order_id;
101
102 $lp_order = learn_press_get_order( $order_id );
103 $lp_order->set_status( 'completed' );
104 $lp_order->save();
105 }
106 }
107 }
108 } catch ( Throwable $e ) {
109 error_log( $e->getMessage() );
110 }
111 }
112
113 /**
114 * Set link item course when form search default wp
115 *
116 * @param string $post_link
117 * @param object $post
118 */
119 public function post_type_link( $post_link, $post ) {
120 // Set item's course permalink
121 $course_item_types = learn_press_get_course_item_types();
122 $item_id = $post->ID;
123
124 if ( in_array( $post->post_type, $course_item_types ) ) {
125 $section_id = LP_Section_DB::getInstance()->get_section_id_by_item_id( $item_id );
126
127 if ( ! $section_id ) {
128 return $post_link;
129 }
130
131 $course_id = LP_Section_DB::getInstance()->get_course_id_by_section( $section_id );
132
133 if ( ! $course_id ) {
134 return $post_link;
135 }
136
137 $course = learn_press_get_course( $course_id );
138 if ( ! $course ) {
139 return $post_link;
140 }
141
142 $post_link = $course->get_item_link( $item_id );
143 } elseif ( LP_COURSE_CPT === $post->post_type ) {
144 // Abort early if the placeholder rewrite tag isn't in the generated URL
145 if ( false === strpos( $post_link, '%' ) ) {
146 return $post_link;
147 }
148
149 // Get the custom taxonomy terms in use by this post
150 $terms = get_the_terms( $post->ID, 'course_category' );
151
152 if ( ! empty( $terms ) ) {
153 $terms = _learn_press_usort_terms_by_ID( $terms ); // order by ID
154 $category_object = apply_filters(
155 'learn_press_course_post_type_link_course_category',
156 $terms[0],
157 $terms,
158 $post
159 );
160 $category_object = get_term( $category_object, 'course_category' );
161 $course_category = $category_object->slug;
162
163 $parent = $category_object->parent;
164 if ( $parent ) {
165 $ancestors = get_ancestors( $category_object->term_id, 'course_category' );
166 foreach ( $ancestors as $ancestor ) {
167 $ancestor_object = get_term( $ancestor, 'course_category' );
168 $course_category = $ancestor_object->slug . '/' . $course_category;
169 }
170 }
171 } else {
172 // If no terms are assigned to this post, use a string instead (can't leave the placeholder there)
173 $course_category = _x( 'uncategorized', 'slug', 'learnpress' );
174 }
175
176 $find = array(
177 '%year%',
178 '%monthnum%',
179 '%day%',
180 '%hour%',
181 '%minute%',
182 '%second%',
183 '%post_id%',
184 '%category%',
185 '%course_category%',
186 );
187
188 $replace = array(
189 date_i18n( 'Y', strtotime( $post->post_date ) ),
190 date_i18n( 'm', strtotime( $post->post_date ) ),
191 date_i18n( 'd', strtotime( $post->post_date ) ),
192 date_i18n( 'H', strtotime( $post->post_date ) ),
193 date_i18n( 'i', strtotime( $post->post_date ) ),
194 date_i18n( 's', strtotime( $post->post_date ) ),
195 $post->ID,
196 $course_category,
197 $course_category,
198 );
199
200 $post_link = str_replace( $find, $replace, $post_link );
201 }
202
203 return $post_link;
204 }
205
206 private function has_block_template( $template_name ) {
207 if ( ! $template_name ) {
208 return false;
209 }
210
211 $has_template = false;
212 $template_name = str_replace( 'course', LP_COURSE_CPT, $template_name );
213 $template_filename = $template_name . '.html';
214 // Since Gutenberg 12.1.0, the conventions for block templates directories have changed,
215 // we should check both these possible directories for backwards-compatibility.
216 $possible_templates_dirs = array( 'templates', 'block-templates' );
217
218 // Combine the possible root directory names with either the template directory
219 // or the stylesheet directory for child themes, getting all possible block templates
220 // locations combinations.
221 $filepath = DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . $template_filename;
222 $legacy_filepath = DIRECTORY_SEPARATOR . 'block-templates' . DIRECTORY_SEPARATOR . $template_filename;
223 $possible_paths = array(
224 get_stylesheet_directory() . $filepath,
225 get_stylesheet_directory() . $legacy_filepath,
226 get_template_directory() . $filepath,
227 get_template_directory() . $legacy_filepath,
228 );
229
230 // Check the first matching one.
231 foreach ( $possible_paths as $path ) {
232 if ( is_readable( $path ) ) {
233 $has_template = true;
234 break;
235 }
236 }
237
238 /**
239 * Filters the value of the result of the block template check.
240 *
241 * @since x.x.x
242 *
243 * @param boolean $has_template value to be filtered.
244 * @param string $template_name The name of the template.
245 */
246 return (bool) apply_filters( 'learnpress_has_block_template', $has_template, $template_name );
247 }
248
249 /**
250 * Set title of pages
251 *
252 * 1. Title course archive page
253 * 2. Title item of course
254 * 3. Title page Profile
255 *
256 * @param string $title
257 *
258 * @return string
259 * @author tungnx
260 * @since 3.2.7.7
261 */
262 public function set_title_pages( $title = '' ) {
263 global $wp_query;
264 $flag_title_course = false;
265
266 $course_archive_page_id = LP_Settings::instance()->get( 'courses_page_id', 0 );
267
268 // Set title course archive page
269 if ( ! empty( $course_archive_page_id ) && $wp_query->post &&
270 $course_archive_page_id == $wp_query->post->ID ) {
271 $title = get_the_title( $course_archive_page_id );
272 $flag_title_course = true;
273 } elseif ( learn_press_is_course() ) {
274 $item = LP_Global::course_item();
275 if ( $item ) {
276 $title = apply_filters( 'learn-press/document-course-title-parts', get_the_title() . ' &rarr; ' . $item->get_title(), $item );
277
278 $flag_title_course = true;
279 }
280 } elseif ( learn_press_is_courses() ) {
281 if ( learn_press_is_search() ) {
282 $title = __( 'Course Search Results', 'learnpress' );
283 } else {
284 $title = __( 'Courses', 'learnpress' );
285 }
286
287 $flag_title_course = true;
288 } elseif ( learn_press_is_profile() ) {
289 $profile = LP_Profile::instance();
290 $tab_slug = $profile->get_current_tab();
291 $tab = $profile->get_tab_at( $tab_slug );
292
293 if ( $page_id = learn_press_get_page_id( 'profile' ) ) {
294 $page_title = get_the_title( $page_id );
295 } else {
296 $page_title = '';
297 }
298 if ( $tab ) {
299 $title = join(
300 ' ',
301 apply_filters(
302 'learn-press/document-profile-title-parts',
303 array(
304 $page_title,
305 '&rarr;',
306 $tab['title'],
307 )
308 )
309 );
310 }
311
312 $flag_title_course = true;
313 }
314
315 if ( $flag_title_course ) {
316 $title .= ' - ' . get_bloginfo( 'name', 'display' );
317 }
318
319 return apply_filters( 'learn-press/title-page', $title );
320 }
321
322 /**
323 * Set description of course's item for yoast seo
324 *
325 * @param $desc
326 *
327 * @return mixed
328 * @author tungnx
329 * @since 3.2.7.9
330 */
331 public function lp_desc_item_yoast_seo( $desc ) {
332 if ( learn_press_is_course() ) {
333
334 $item = LP_Global::course_item();
335
336 if ( empty( $item ) ) {
337 return $desc;
338 }
339
340 $desc = get_post_meta( $item->get_id(), '_yoast_wpseo_metadesc', true );
341 }
342
343 return $desc;
344 }
345
346 public function check_pages( $template ) {
347 if ( learn_press_is_checkout() ) {
348 $available_gateways = LP_Gateways::instance()->get_available_payment_gateways();
349
350 if ( ! $available_gateways ) {
351 learn_press_add_message( __( 'No payment method is available.', 'learnpress' ), 'error' );
352 }
353 } else {
354 global $wp_query;
355
356 $logout_slug = learn_press_profile_logout_slug();
357
358 if ( $logout_slug && ( $wp_query->get( 'view' ) === $logout_slug ) ) {
359 wp_safe_redirect( str_replace( '&amp;', '&', wp_logout_url( learn_press_get_page_link( 'profile' ) ) ) );
360 exit;
361 }
362 }
363
364 return $template;
365 }
366
367 /**
368 * Auto inserting a registered shortcode to a specific page
369 * if that page is viewing in single mode.
370 *
371 * @param string $template
372 *
373 * @return string;
374 * @since 3.3.0
375 */
376 public function auto_shortcode( $template ) {
377 global $post;
378 $the_post = $post;
379 if ( $the_post && is_page( $the_post->ID ) ) {
380
381 // Filter here to insert the shortcode
382 $auto_shortcodes = apply_filters( 'learn-press/auto-shortcode-pages', array() );
383
384 if ( ! empty( $auto_shortcodes[ $the_post->ID ] ) ) {
385 $shortcode_tag = $auto_shortcodes[ $the_post->ID ];
386
387 preg_match( '/\[' . $shortcode_tag . '\s?(.*)\]/', $the_post->post_content, $results );
388
389 if ( empty( $results ) ) {
390 $content = $the_post->post_content . "[$shortcode_tag]";
391 $the_post->post_content = $content;
392 }
393 }
394 }
395
396 return $template;
397 }
398
399 /**
400 * Load data for item of course
401 *
402 * @param $post
403 *
404 * @return mixed
405 * @editor tungnx
406 * Todo: should remove this function when load true type post's item
407 */
408 public function setup_data_for_item_course( $post ): WP_Post {
409 /**
410 * @var WP $wp
411 * @var WP_Query $wp_query
412 * @var LP_Course $lp_course
413 * @var LP_Course_Item|LP_Quiz|LP_Lesson $lp_course_item
414 */
415 global $wp, $wp_query, $lp_course_item;
416
417 if ( LP_COURSE_CPT !== $post->post_type ) {
418 return $post;
419 }
420
421 $course = learn_press_get_course();
422 if ( ! $course ) {
423 return $post;
424 }
425
426 /**
427 * @deprecated v4.1.6.1 LP()->global['course'], $GLOBALS['course']
428 * Some theme still use: global $course; LP()->global['course']
429 */
430 //LP()->global['course'] = $GLOBALS['course'] = $GLOBALS['lp_course'] = $course;
431 LP()->global['course'] = $GLOBALS['course'] = $course;
432
433 if ( wp_verify_nonce( LP_Request::get( 'preview' ), 'preview-' . $post->ID ) ) {
434 $GLOBALS['preview_course'] = $post->ID;
435 }
436
437 $vars = $wp->query_vars;
438
439 if ( empty( $vars['course-item'] ) ) {
440 return $post;
441 }
442
443 if ( ! $wp_query->is_main_query() ) {
444 return $post;
445 }
446
447 try {
448 $user = learn_press_get_current_user();
449
450 // If item name is set in query vars
451 if ( ! is_numeric( $vars['course-item'] ) ) {
452 $item_type = $vars['item-type'];
453 $post_item = learn_press_get_post_by_name( $vars['course-item'], $item_type );
454 } else {
455 $post_item = get_post( absint( $vars['course-item'] ) );
456 }
457
458 if ( ! $post_item ) {
459 return $post;
460 }
461
462 $lp_course_item = apply_filters( 'learn-press/single-course-request-item', $course->get_item( $post_item->ID ) );
463
464 if ( ! $lp_course_item ) {
465 return $post;
466 }
467
468 // Set item viewing
469 $user->set_viewing_item( $lp_course_item );
470 } catch ( Exception $ex ) {
471 learn_press_add_message( $ex->getMessage(), 'error' );
472 }
473
474 return $post;
475 }
476
477 /**
478 * Set page 404
479 *
480 * @return mixed
481 * @editor tungnx
482 * @reason not use
483 * @deprecated 4.0.0
484 */
485 /*
486 public function set_404( $is_404 ) {
487 global $wp_query;
488 $wp_query->is_404 = $this->_is_404 = (bool) $is_404;
489 }*/
490
491 public function is_404() {
492 return apply_filters( 'learn-press/query/404', $this->_is_404 );
493 }
494
495 /**
496 * In preview mode, if there is a 'post_format' in query var
497 * wp check and replace our post-type to post. This make preview
498 * course item become 404
499 *
500 * @param $qv
501 *
502 * @return mixed
503 */
504 public function remove_course_post_format( $qv ) {
505 if ( ! empty( $qv['post_type'] ) && LP_COURSE_CPT === $qv['post_type'] ) {
506 if ( ! empty( $qv['post_format'] ) ) {
507 unset( $qv['post_format'] );
508 }
509 }
510
511 return $qv;
512 }
513
514 /**
515 * @return bool
516 */
517 protected function _is_archive() {
518 return learn_press_is_courses() || learn_press_is_course_tag() || learn_press_is_course_category() || learn_press_is_search() || learn_press_is_course_tax();
519 }
520
521 /**
522 * @return bool
523 */
524 protected function _is_single() {
525 return learn_press_is_course() && is_single();
526 }
527
528 /**
529 * Load content of course depending on query.
530 *
531 * @param string $template
532 *
533 * @return bool|string
534 */
535 public function template_loader( $template ) {
536
537 if ( is_embed() ) {
538 return $template;
539 }
540
541 // $this->_maybe_redirect_courses_page();
542
543 $default_template = $this->get_page_template();
544
545 if ( $default_template ) {
546 $templates = $this->get_page_templates( $default_template );
547
548 /**
549 * Disable override templates in theme by default since LP 4.0.0
550 */
551 if ( learn_press_override_templates() ) {
552 $new_template = locate_template( $templates );
553 }
554
555 if ( ! isset( $new_template ) || ! $new_template ) {
556 $new_template = LP_TEMPLATE_PATH . $default_template;
557 }
558
559 $template = $new_template;
560 }
561
562 return $template;
563 }
564
565 /**
566 * Get the default filename for a template.
567 *
568 * @return string
569 * @since 4.0.0
570 */
571 private function get_page_template() {
572 $page_template = '';
573
574 if ( is_singular( LP_COURSE_CPT ) ) {
575 if ( ! self::has_block_template( 'single-course' ) ) {
576 $page_template = 'single-course.php';
577 }
578
579 if ( $this->_is_single() ) {
580 global $post;
581 setup_postdata( $post );
582
583 $course_item = LP_Global::course_item();
584 if ( $course_item && ! self::has_block_template( 'content-single-course-item' ) ) {
585 $page_template = 'content-single-item.php';
586 }
587 }
588 } elseif ( learn_press_is_course_taxonomy() ) {
589 $object = get_queried_object();
590
591 if ( is_tax( 'course_category' ) || is_tax( 'course_tag' ) ) {
592 $page_template = 'taxonomy-' . $object->taxonomy . '.php';
593
594 if ( self::has_block_template( 'taxonomy-' . $object->taxonomy ) ) {
595 $page_template = '';
596 } elseif ( ! file_exists( learn_press_locate_template( $page_template ) ) && ! self::has_block_template( 'archive-course' ) ) {
597 $page_template = 'archive-course.php';
598 }
599 } elseif ( ! self::has_block_template( 'archive-course' ) ) {
600 $page_template = 'archive-course.php';
601 }
602 } elseif ( ( is_post_type_archive( LP_COURSE_CPT ) || ( ! empty( learn_press_get_page_id( 'courses' ) ) && is_page( learn_press_get_page_id( 'courses' ) ) ) ) && ! self::has_block_template( 'archive-course' ) ) {
603 $page_template = 'archive-course.php';
604 } elseif ( learn_press_is_checkout() && ! self::has_block_template( 'page-lp_checkout' ) ) {
605 $page_template = 'pages/checkout.php';
606 }
607
608 return apply_filters( 'learn-press/page-template', $page_template );
609 }
610
611 private function get_page_templates( $default_template ) {
612 $templates = apply_filters( 'learn-press/page-templates', array(), $default_template );
613
614 if ( is_page_template() ) {
615 $page_template = get_page_template_slug();
616
617 if ( $page_template ) {
618 $validated_file = validate_file( $page_template );
619 if ( 0 === $validated_file ) {
620 $templates[] = $page_template;
621 } else {
622 error_log( "LearnPress: Unable to validate template path: \"$page_template\". Error Code: $validated_file." );
623 }
624 }
625 }
626
627 if ( is_singular( LP_COURSE_CPT ) ) {
628 $object = get_queried_object();
629 $name_decoded = urldecode( $object->post_name );
630
631 if ( $name_decoded !== $object->post_name ) {
632 $templates[] = "single-course-{$name_decoded}.php";
633 }
634
635 $templates[] = "single-product-{$object->post_name}.php";
636 }
637
638 if ( learn_press_is_course_taxonomy() ) {
639 $object = get_queried_object();
640 $templates[] = 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php';
641 $templates[] = learn_press_template_path( true ) . 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php';
642 $templates[] = 'taxonomy-' . $object->taxonomy . '.php';
643 $templates[] = learn_press_template_path( true ) . 'taxonomy-' . $object->taxonomy . '.php';
644 }
645
646 $templates[] = $default_template;
647 $templates[] = learn_press_template_path( true ) . $default_template;
648
649 return array_unique( $templates );
650 }
651
652 /**
653 * Filter to allow search more templates in theme for wp page template hierarchy.
654 * Theme twentytwenty used 'singular.php' instead of 'page.php'
655 *
656 * @param array $templates
657 *
658 * @return array
659 * @since 3.x.x
660 * @depecated 4.1.6.9.2
661 */
662 /*public function page_template_hierarchy( $templates ) {
663 $templates = array_merge( $templates, array( 'singular.php' ) );
664
665 return $templates;
666 }*/
667
668 /**
669 * Archive course content.
670 *
671 * @return false|string
672 */
673 public function archive_content() {
674 ob_start();
675 learn_press_get_template( 'content-archive-course.php' );
676
677 return ob_get_clean();
678 }
679
680 /**
681 * @param $title
682 *
683 * @return mixed
684 */
685 public function page_title( $title ) {
686 global $wp_query;
687 if ( ! empty( $wp_query->queried_object_id ) ) {
688 $title['title'] = get_the_title( $wp_query->queried_object_id );
689 }
690
691 return $title;
692 }
693
694 /**
695 * Query courses if page is archive courses
696 *
697 * @param $q WP_Query
698 *
699 * @return WP_Query
700 * @editor tungnx
701 * @modify 4.1.2
702 * @throws Exception
703 */
704 public function pre_get_posts( WP_Query $q ): WP_Query {
705 // Affect only the main query and not in admin
706 if ( ! $q->is_main_query() && ! is_admin() ) {
707 return $q;
708 }
709
710 // Exclude item not assign
711 if ( $q->is_search() ) {
712 // Exclude item not assign any course
713 $course_item_types = learn_press_get_course_item_types();
714 $list_ids_exclude = array();
715
716 foreach ( $course_item_types as $item_type ) {
717 $filter = new LP_Post_Type_Filter();
718 $filter->post_type = $item_type;
719 $exclude_item = LP_Course_DB::getInstance()->get_item_ids_unassigned( $filter );
720 $exclude_item = LP_Course_DB::get_values_by_key( $exclude_item );
721
722 $list_ids_exclude = array_merge( $list_ids_exclude, $exclude_item );
723 }
724
725 // Exclude question not assign any quiz
726 $question_ids = LP_Question_DB::getInstance()->get_questions_not_assign_quiz();
727 $question_ids = LP_Course_DB::get_values_by_key( $question_ids );
728 $list_ids_exclude = array_merge( $list_ids_exclude, $question_ids );
729
730 if ( ! empty( $list_ids_exclude ) ) {
731 $q->set( 'post__not_in', $list_ids_exclude );
732 }
733 }
734
735 $is_archive_course = false;
736
737 // Handle 404 if user are viewing course item directly.
738 $this->set_link_item_course_default_wp_to_page_404( $q );
739
740 $this->_queried_object = ! empty( $q->queried_object_id ) ? $q->queried_object : false;
741
742 /**
743 * If current page is used for courses page
744 * Set on both: "Homepage" and "Posts page" on Reading Settings
745 */
746 $page_courses_id = learn_press_get_page_id( 'courses' );
747
748 if ( $q->is_home() && 'page' == get_option( 'show_on_front' ) && get_option( 'page_on_front' ) == $page_courses_id ) {
749 $is_archive_course = 1;
750 // $q->is_home = false;
751 // $q->set( 'page_id', get_option( 'page_on_front' ) );
752 }
753
754 /**
755 * If current page is used for courses page and set as "Homepage"
756 */
757 if ( $q->is_page() && 'page' == get_option( 'show_on_front' ) && $page_courses_id && $q->get( 'page_id' ) == $page_courses_id ) {
758 $is_archive_course = 1;
759
760 /*
761 global $wp_post_types;
762
763 $course_page = get_post( $page_courses_id );
764 $this->_queried_object = $course_page;
765 $wp_post_types[ LP_COURSE_CPT ]->ID = $course_page->ID;
766 $wp_post_types[ LP_COURSE_CPT ]->post_title = $course_page->post_title;
767 $wp_post_types[ LP_COURSE_CPT ]->post_name = $course_page->post_name;
768 $wp_post_types[ LP_COURSE_CPT ]->post_type = $course_page->post_type;
769 $wp_post_types[ LP_COURSE_CPT ]->ancestors = get_ancestors( $course_page->ID, $course_page->post_type );*/
770 }
771
772 // Set custom posts per page
773 if ( $this->_is_archive() ) {
774 $is_archive_course = 1;
775 }
776
777 $apply_lazy_load_for_theme = apply_filters( 'lp/page/courses/query/lazy_load', false );
778
779 if ( $is_archive_course ) {
780 if ( ( LP_Settings_Courses::is_ajax_load_courses() && ! LP_Settings_Courses::is_no_load_ajax_first_courses() ) ) {
781 LP()->template( 'course' )->remove_callback( 'learn-press/after-courses-loop', 'loop/course/pagination.php', 10 );
782 /**
783 * If page is archive course - query set posts_per_page = 1
784 * For fastest - because when page loaded - call API to load list courses
785 *
786 * Current, apply only for LP, not apply for theme Thimpress, because theme override
787 */
788 $q->set( 'posts_per_page', 1 );
789 $q->set( 'posts_per_archive_page', 1 );
790 $q->set( 'nopaging', true );
791 } else {
792 $filter = new LP_Course_Filter();
793 $filter->only_fields = [ 'ID' ];
794 $filter->max_limit = $filter->limit = 1000;
795 $is_need_check_in_arr = false;
796 $limit = LP_Settings::get_option( 'archive_course_limit', 6 );
797
798 $q->set( 'posts_per_page', $limit );
799 // $q->set( 'cache_results', true ); // it default true
800
801 // Search courses by keyword
802 // $q->set( 's', $_REQUEST['c_search'] ?? '' );
803 if ( ! empty( $_REQUEST['c_search'] ) ) {
804 $filter->post_title = LP_Helper::sanitize_params_submitted( $_REQUEST['c_search'] );
805 $is_need_check_in_arr = true;
806 }
807
808 $author_ids_str = LP_Helper::sanitize_params_submitted( $_REQUEST['c_authors'] ?? 0 );
809 if ( ! empty( $author_ids_str ) ) {
810 $q->set( 'author', $author_ids_str );
811 }
812
813 // Meta query
814 $meta_query = [];
815 if ( isset( $_REQUEST['sort_by'] ) ) {
816 $sort_by = LP_Helper::sanitize_params_submitted( $_REQUEST['sort_by'] );
817 if ( 'on_paid' === $sort_by ) {
818 $meta_query[] = array(
819 'key' => '_lp_price',
820 'value' => 0,
821 'compare' => '>',
822 );
823 }
824
825 if ( 'on_free' === $sort_by ) {
826 $meta_query[] = array(
827 'key' => '_lp_price',
828 'value' => 0,
829 'compare' => '=',
830 );
831 }
832 }
833 $q->set( 'meta_query', $meta_query );
834 // End Meta query
835
836 // Tax query
837 $tax_query = [];
838 $term_ids_str = LP_Helper::sanitize_params_submitted( urldecode( $_REQUEST['term_id'] ?? '' ) );
839 if ( ! empty( $term_ids_str ) ) {
840 $term_ids = explode( ',', $term_ids_str );
841
842 $tax_query[] = array(
843 'taxonomy' => 'course_category',
844 'field' => 'term_id',
845 'terms' => $term_ids,
846 'operator' => 'IN',
847 );
848 }
849
850 $q->set( 'tax_query', $tax_query );
851 // End Tax query
852
853 // Author query
854 if ( isset( $_REQUEST['c_author'] ) ) {
855 $author_ids = LP_Helper::sanitize_params_submitted( $_REQUEST['c_author'] );
856 $q->set( 'author__in', $author_ids );
857 }
858 // End Author query
859
860 // Order query
861 if ( isset( $_REQUEST['order_by'] ) ) {
862 $order_by = LP_Helper::sanitize_params_submitted( $_REQUEST['order_by'] );
863 $order = 'DESC';
864
865 switch ( $order_by ) {
866 case 'post_title':
867 $order_by = 'title';
868 $order = 'ASC';
869 break;
870 case 'popular':
871 $filter->order_by = 'popular';
872 $order_by = 'post__in';
873 $is_need_check_in_arr = true;
874 break;
875 default:
876 $order_by = 'date';
877 break;
878 }
879
880 $q->set( 'orderby', $order_by );
881 $q->set( 'order', $order );
882 }
883
884 if ( $is_need_check_in_arr ) {
885 $posts_in = LP_Course::get_courses( $filter );
886 if ( ! empty( $posts_in ) ) {
887 $posts_in = LP_Database::get_values_by_key( $posts_in );
888 $q->set( 'post__in', $posts_in );
889 } else {
890 $q->set( 'post__in', 0 );
891 }
892 }
893
894 $q = apply_filters( 'lp/page-courses/query/legacy', $q );
895 }
896 }
897
898 return $q;
899 }
900
901 /**
902 * Handle 404 if user are viewing course item directly.
903 * Example: http://example.com/lesson/slug-lesson
904 * Apply for user not admin, instructor, co-instructor
905 *
906 * @param WP_Query $q
907 *
908 * @return mixed
909 * @editor tungnx
910 * @since 3.2.7.5
911 */
912 public function set_link_item_course_default_wp_to_page_404( $q ) {
913 if ( ! $q->is_main_query() || is_admin() ) {
914 return $q;
915 }
916
917 $post_type_apply_404 = array( LP_LESSON_CPT, LP_QUIZ_CPT, LP_QUESTION_CPT, 'lp_assignment' );
918
919 if ( isset( $q->query_vars['post_type'] ) && in_array( $q->query_vars['post_type'], $post_type_apply_404 ) ) {
920 $flag_load_404 = true;
921 $user = wp_get_current_user();
922 $post_author = 0;
923
924 if ( $user ) {
925 $post = null;
926
927 if ( isset( $_GET['preview_id'] ) ) {
928 $post_id = absint( $_GET['preview_id'] );
929 $post = get_post( $post_id );
930 $post_author = $post->post_author;
931 } elseif ( isset( $_GET['preview'] ) && isset( $_GET['p'] ) ) {
932 $post_id = absint( $_GET['p'] );
933 $post = get_post( $post_id );
934 $post_author = $post->post_author;
935 } else {
936 $post_author = LP_Database::getInstance()->getPostAuthorByTypeAndSlug( $q->query_vars['post_type'], $q->query_vars[ $q->query_vars['post_type'] ] );
937 }
938
939 if ( $user->has_cap( 'administrator' ) ) {
940 $flag_load_404 = false;
941 } elseif ( $user->has_cap( LP_TEACHER_ROLE ) && $post_author == $user->ID ) {
942 $flag_load_404 = false;
943 }
944 }
945
946 $flag_load_404 = apply_filters( 'learnpress/page/set-link-item-course-404', $flag_load_404, $post_author, $user );
947
948 if ( $flag_load_404 ) {
949 learn_press_404_page();
950 $q->set( 'post_type', '' );
951 }
952 }
953
954 return $q;
955 }
956
957 /**
958 * @depecated 4.1.6.9.2
959 */
960 /*public function the_content_callback( $content ) {
961 if ( $this->_archive_contents ) {
962 preg_match( '/\[learn_press_archive_course\s?(.*)\]/', $content, $results );
963 $this->_shortcode_exists = ! empty( $results );
964 if ( $this->_shortcode_exists ) {
965 $this->_shortcode_tag = $results[0];
966 $content = str_replace( $this->_shortcode_tag, $this->_archive_contents, $content );
967 } else {
968 $content .= $this->_archive_contents;
969 }
970 }
971
972 return $content;
973 }*/
974
975 /**
976 * Check is page Become a teacher
977 *
978 * @return bool|mixed|void
979 * @since 3.2.8
980 * @author tungnx
981 */
982 public static function is_page_become_a_teacher() {
983 $page_id = learn_press_get_page_id( 'become_a_teacher' );
984
985 if ( $page_id && is_page( $page_id ) ) {
986 return true;
987 }
988
989 return apply_filters( 'learnpress/is-page/become-a-teacher', false );
990 }
991
992 /**
993 * Get page current on frontend
994 *
995 * @return string
996 * @since 3.2.8
997 * @author tungnx
998 */
999 public static function page_current(): string {
1000 if ( learn_press_is_checkout() ) {
1001 return LP_PAGE_CHECKOUT;
1002 } elseif ( LP_Global::course_item_quiz() ) {
1003 return LP_PAGE_QUIZ;
1004 } elseif ( learn_press_is_course() && is_single() && LP_Global::course_item() ) {
1005 return LP_PAGE_SINGLE_COURSE_CURRICULUM;
1006 } elseif ( learn_press_is_courses() ) {
1007 return LP_PAGE_COURSES;
1008 } elseif ( learn_press_is_course() ) {
1009 return LP_PAGE_SINGLE_COURSE;
1010 } elseif ( self::is_page_become_a_teacher() ) {
1011 return LP_PAGE_BECOME_A_TEACHER;
1012 } elseif ( learn_press_is_profile() ) {
1013 return LP_PAGE_PROFILE;
1014 } else {
1015 return apply_filters( 'learnpress/page/current', '' );
1016 }
1017 }
1018
1019 public static function instance() {
1020 if ( is_admin() ) {
1021 return null;
1022 }
1023
1024 if ( ! self::$_instance ) {
1025 self::$_instance = new self();
1026 }
1027
1028 return self::$_instance;
1029 }
1030
1031 /**
1032 * Add user profile link into admin bar
1033 *
1034 * @editor tungnx
1035 * @version 1.0.1
1036 * @since 3.0.0
1037 */
1038 public function learn_press_edit_admin_bar() {
1039 global $wp_admin_bar;
1040
1041 $current_user = wp_get_current_user();
1042
1043 if ( ! in_array( LP_TEACHER_ROLE, $current_user->roles ) && ! in_array( 'administrator', $current_user->roles ) ) {
1044 return;
1045 }
1046
1047 $page_profile_id = learn_press_get_page_id( 'profile' );
1048
1049 if ( $page_profile_id && get_post_status( $page_profile_id ) != 'trash' ) {
1050 $user_id = $current_user->ID;
1051
1052 $wp_admin_bar->add_menu(
1053 array(
1054 'id' => 'course_profile',
1055 'parent' => 'user-actions',
1056 'title' => get_the_title( $page_profile_id ),
1057 'href' => learn_press_user_profile_link( $user_id, false ),
1058 )
1059 );
1060 }
1061 }
1062 }
1063
1064 return LP_Page_Controller::instance();
1065