PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.2.0
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.2.0
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 4.2.1 All 138 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.2.0, at inc/class-lp-page-controller.php

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