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

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