PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
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
← All changes | inc/class-lp-page-controller.php +803 -497 4.1.6.9.24.4.8 View file →
@@ -1,6 +1,12 @@
1 1 <?php
2 2
3 +use LearnPress\CourseBuilder\CourseBuilder;
4 +use LearnPress\Helpers\Template;
5 +use LearnPress\Models\CourseModel;
6 +use LearnPress\Models\Courses;
7 +use LearnPress\Models\UserModel;
8 +
3 9 /**
4 10 * Class LP_Page_Controller
5 11 */
6 12 class LP_Page_Controller {
@@ -10,14 +16,14 @@
10 16 * Store the object has queried by WP.
11 17 *
12 18 * @var int
13 19 */
14 - protected $_queried_object = 0;
20 + //protected $_queried_object = 0;
15 21
16 22 /**
17 23 * @var int
18 24 */
19 - protected $_filter_content_priority = 10000;
25 + //protected $_filter_content_priority = 10000;
20 26
21 27 /**
22 28 * Flag for 404 content.
23 29 *
@@ -28,49 +34,142 @@
28 34 /**
29 35 * LP_Page_Controller constructor.
30 36 */
31 37 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 );
38 + // Set link course, item course.
39 + add_filter( 'post_type_link', array( $this, 'post_type_link' ), 10, 2 );
36 40
37 - add_filter( 'the_post', array( $this, 'setup_data_for_item_course' ) );
38 - add_filter( 'request', array( $this, 'remove_course_post_format' ), 1 );
41 + if ( LP_Page_Controller::is_page_lp_ajax() ) {
42 + if ( ! isset( $_REQUEST['lp-load-ajax'] ) ) {
43 + wp_die( 'Invalid request!', 400 );
44 + }
45 + }
39 46
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 );
47 + if ( is_admin() ) {
48 + add_action( 'admin_init', [ $this, 'redirect_admin_to_course_builder' ] );
49 + } else {
50 + //add_filter( 'post_type_archive_link', [ $this, 'link_archive_course' ], 10, 2 );
51 + add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ), - 1 );
52 + // For debug mysql query post of WP.
53 + /*add_filter(
54 + 'posts_request',
55 + function ( $request, $q ) {
56 + LP_Debug::var_dump( $request );
57 + return $request;
58 + },
59 + 10,
60 + 2
61 + );*/
62 + /*add_filter(
63 + 'posts_clauses_request',
64 + function ( $clauses, $wp_query ) {
65 + if ( ! $wp_query->is_search() ) {
66 + return $clauses;
67 + }
42 68
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 );
69 + $lp_db = LP_Database::getInstance();
70 + $clauses['where'] .= sprintf( " OR ( post_type = '%s' AND meta_key = '_lp_preview' AND meta_value = 'yes')", LP_LESSON_CPT );
71 + $clauses['join'] .= ' INNER JOIN ' . $lp_db->tb_postmeta . ' ON post_id = wp_posts.ID ';
46 72
47 - // edit link item course when form search default wp
48 - add_filter( 'post_type_link', array( $this, 'post_type_link' ), 10, 2 );
73 + return $clauses;
74 + },
75 + 10,
76 + 2
77 + );*/
78 + // For return result query course to cache.
79 + //add_action( 'posts_pre_query', [ $this, 'posts_pre_query' ], 10, 2 );
80 + add_filter( 'template_include', array( $this, 'template_loader' ), 10 );
81 + add_filter( 'template_include', array( $this, 'logout' ), 30 );
82 + add_action( 'template_redirect', array( $this, 'template_redirect' ), -1 );
49 83
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' ) );
84 + add_filter( 'the_post', array( $this, 'setup_data_for_item_course' ) );
85 + add_filter( 'request', array( $this, 'remove_course_post_format' ), 1 );
86 +
87 + //add_shortcode( 'learn_press_archive_course', array( $this, 'archive_content' ) );
88 + add_filter( 'pre_get_document_title', array( $this, 'set_title_pages' ), 10, 1 );
89 +
90 + // Yoast seo
91 + add_filter( 'wpseo_opengraph_desc', array( $this, 'lp_desc_item_yoast_seo' ), 11, 1 );
92 + add_filter( 'wpseo_metadesc', array( $this, 'lp_desc_item_yoast_seo' ), 11, 1 );
93 +
94 + // Set link profile to admin menu
95 + //add_action( 'admin_bar_menu', array( $this, 'learn_press_edit_admin_bar' ) );
96 +
97 + // Set again x-wp-nonce on header when has cache with not login.
98 + add_filter( 'rest_send_nocache_headers', array( $this, 'check_x_wp_nonce_cache' ) );
99 +
100 + // Rewrite lesson comment links
101 + add_filter( 'get_comment_link', array( $this, 'edit_lesson_comment_links' ), 10, 2 );
102 + // Active menu
103 + add_filter( 'wp_nav_menu_objects', [ $this, 'menu_active' ], 10, 1 );
104 + // Canonical
105 + add_filter(
106 + 'get_canonical_url',
107 + function ( $canonical_url ) {
108 + if ( LP_Page_Controller::is_page_instructor() ) {
109 + $canonical_url = LP_Helper::getUrlCurrent();
110 + }
111 +
112 + return $canonical_url;
113 + }
114 + );
115 + }
116 +
117 + // Disable create sitemap for items type of Course.
118 + add_filter(
119 + 'wp_sitemaps_post_types',
120 + function ( $post_types ) {
121 + $item_types = CourseModel::item_types_support();
122 + $item_types[] = LP_QUESTION_CPT;
123 + foreach ( $item_types as $item_type ) {
124 + if ( isset( $post_types[ $item_type ] ) ) {
125 + unset( $post_types[ $item_type ] );
126 + }
127 + }
128 +
129 + return $post_types;
130 + }
131 + );
132 +
133 + /**
134 + * Disable create sitemap for YoastSEO, Rank Math, but can affect to all logic, ex: it makes link edit of items course lose.
135 + *
136 + * @var WP_Post_Type $post_type
137 + */
138 + /*add_filter(
139 + 'is_post_type_viewable',
140 + function ( $is_viewable, $post_type ) {
141 + $item_types = CourseModel::item_types_support();
142 + $item_types[] = LP_QUESTION_CPT;
143 + if ( in_array( $post_type->name, $item_types ) ) {
144 + $is_viewable = false;
145 + }
146 +
147 + return $is_viewable;
148 + },
149 + 10,
150 + 2
151 + );*/
53 152 }
54 153
55 154 /**
56 - * Optimize when Rest API LP called
155 + * Set link archive course.
57 156 *
58 - * @return void
157 + * @param string $link
158 + * @param string $post_type
159 + *
160 + * @return string
59 161 */
60 - public function lp_rest_api_called() {
61 - if ( LP_Helper::isRestApiLP() ) {
62 - if ( ! defined( 'SHORTINIT' ) ) {
63 - define( 'SHORTINIT', true );
64 - }
162 + public function link_archive_course( string $link, string $post_type ): string {
163 + if ( $post_type == LP_COURSE_CPT && learn_press_get_page_id( 'courses' ) ) {
164 + $link = learn_press_get_page_link( 'courses' );
165 + }
65 166
66 - // Remove hook wp_loaded because query default WP run on it (it hooks 'pre_get_posts',...)
67 - remove_all_actions( 'wp_loaded' );
68 - }
167 + return $link;
69 168 }
70 169
71 170 /**
72 - * Set link item course when form search default wp
171 + * Set link course, item course
73 172 *
74 173 * @param string $post_link
75 174 * @param object $post
76 175 */
@@ -75,133 +174,37 @@
75 174 * @param object $post
76 175 */
77 176 public function post_type_link( $post_link, $post ) {
78 177 // Set item's course permalink
79 - $course_item_types = learn_press_get_course_item_types();
178 + $course_item_types = CourseModel::item_types_support();
80 179 $item_id = $post->ID;
81 180
82 - if ( in_array( $post->post_type, $course_item_types ) ) {
181 + // Link item course on search page of WP.
182 + if ( in_array( $post->post_type, $course_item_types ) && is_search() ) {
83 183 $section_id = LP_Section_DB::getInstance()->get_section_id_by_item_id( $item_id );
84 -
85 184 if ( ! $section_id ) {
86 185 return $post_link;
87 186 }
88 187
89 188 $course_id = LP_Section_DB::getInstance()->get_course_id_by_section( $section_id );
90 -
91 189 if ( ! $course_id ) {
92 190 return $post_link;
93 191 }
94 192
95 - $course = learn_press_get_course( $course_id );
96 - $post_link = $course->get_item_link( $item_id );
97 -
98 - } elseif ( LP_COURSE_CPT === $post->post_type ) {
99 - // Abort early if the placeholder rewrite tag isn't in the generated URL
100 - if ( false === strpos( $post_link, '%' ) ) {
193 + $course = learn_press_get_course( $course_id );
194 + if ( ! $course ) {
101 195 return $post_link;
102 196 }
103 197
104 - // Get the custom taxonomy terms in use by this post
105 - $terms = get_the_terms( $post->ID, 'course_category' );
106 -
107 - if ( ! empty( $terms ) ) {
108 - $terms = _learn_press_usort_terms_by_ID( $terms ); // order by ID
109 - $category_object = apply_filters(
110 - 'learn_press_course_post_type_link_course_category',
111 - $terms[0],
112 - $terms,
113 - $post
114 - );
115 - $category_object = get_term( $category_object, 'course_category' );
116 - $course_category = $category_object->slug;
117 -
118 - $parent = $category_object->parent;
119 - if ( $parent ) {
120 - $ancestors = get_ancestors( $category_object->term_id, 'course_category' );
121 - foreach ( $ancestors as $ancestor ) {
122 - $ancestor_object = get_term( $ancestor, 'course_category' );
123 - $course_category = $ancestor_object->slug . '/' . $course_category;
124 - }
125 - }
126 - } else {
127 - // If no terms are assigned to this post, use a string instead (can't leave the placeholder there)
128 - $course_category = _x( 'uncategorized', 'slug', 'learnpress' );
129 - }
130 -
131 - $find = array(
132 - '%year%',
133 - '%monthnum%',
134 - '%day%',
135 - '%hour%',
136 - '%minute%',
137 - '%second%',
138 - '%post_id%',
139 - '%category%',
140 - '%course_category%',
141 - );
142 -
143 - $replace = array(
144 - date_i18n( 'Y', strtotime( $post->post_date ) ),
145 - date_i18n( 'm', strtotime( $post->post_date ) ),
146 - date_i18n( 'd', strtotime( $post->post_date ) ),
147 - date_i18n( 'H', strtotime( $post->post_date ) ),
148 - date_i18n( 'i', strtotime( $post->post_date ) ),
149 - date_i18n( 's', strtotime( $post->post_date ) ),
150 - $post->ID,
151 - $course_category,
152 - $course_category,
153 - );
154 -
155 - $post_link = str_replace( $find, $replace, $post_link );
198 + $post_link = $course->get_item_link( $item_id );
199 + } elseif ( LP_COURSE_CPT === $post->post_type ) {
200 + // Link single course (with %course_category%).
201 + $post_link = LP_Helper::handle_lp_permalink_structure( $post_link, $post );
156 202 }
157 203
158 204 return $post_link;
159 205 }
160 206
161 - private function has_block_template( $template_name ) {
162 - if ( ! $template_name ) {
163 - return false;
164 - }
165 -
166 - $has_template = false;
167 - $template_name = str_replace( 'course', LP_COURSE_CPT, $template_name );
168 - $template_filename = $template_name . '.html';
169 - // Since Gutenberg 12.1.0, the conventions for block templates directories have changed,
170 - // we should check both these possible directories for backwards-compatibility.
171 - $possible_templates_dirs = array( 'templates', 'block-templates' );
172 -
173 - // Combine the possible root directory names with either the template directory
174 - // or the stylesheet directory for child themes, getting all possible block templates
175 - // locations combinations.
176 - $filepath = DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . $template_filename;
177 - $legacy_filepath = DIRECTORY_SEPARATOR . 'block-templates' . DIRECTORY_SEPARATOR . $template_filename;
178 - $possible_paths = array(
179 - get_stylesheet_directory() . $filepath,
180 - get_stylesheet_directory() . $legacy_filepath,
181 - get_template_directory() . $filepath,
182 - get_template_directory() . $legacy_filepath,
183 - );
184 -
185 - // Check the first matching one.
186 - foreach ( $possible_paths as $path ) {
187 - if ( is_readable( $path ) ) {
188 - $has_template = true;
189 - break;
190 - }
191 - }
192 -
193 - /**
194 - * Filters the value of the result of the block template check.
195 - *
196 - * @since x.x.x
197 - *
198 - * @param boolean $has_template value to be filtered.
199 - * @param string $template_name The name of the template.
200 - */
201 - return (bool) apply_filters( 'learnpress_has_block_template', $has_template, $template_name );
202 - }
203 -
204 207 /**
205 208 * Set title of pages
206 209 *
207 210 * 1. Title course archive page
@@ -210,23 +213,21 @@
210 213 *
211 214 * @param string $title
212 215 *
213 216 * @return string
217 + * @throws Exception
218 + * @since 3.2.7.7
219 + * @version 1.0.2
214 220 * @author tungnx
215 - * @since 3.2.7.7
216 221 */
217 - public function set_title_pages( $title = '' ) {
218 - global $wp_query;
222 + public function set_title_pages( $title = '' ): string {
219 223 $flag_title_course = false;
224 + $user_id = get_current_user_id();
220 225
221 - $course_archive_page_id = LP_Settings::instance()->get( 'courses_page_id', 0 );
226 + $course_archive_page_id = LP_Settings::get_option( 'courses_page_id', 0 );
222 227
223 - // Set title course archive page
224 - if ( ! empty( $course_archive_page_id ) && $wp_query->post &&
225 - $course_archive_page_id == $wp_query->post->ID ) {
226 - $title = get_the_title( $course_archive_page_id );
227 - $flag_title_course = true;
228 - } elseif ( learn_press_is_course() ) {
228 + // Set title single course.
229 + if ( learn_press_is_course() ) {
229 230 $item = LP_Global::course_item();
230 231 if ( $item ) {
231 232 $title = apply_filters( 'learn-press/document-course-title-parts', get_the_title() . ' &rarr; ' . $item->get_title(), $item );
232 233
@@ -231,27 +232,41 @@
231 232 $title = apply_filters( 'learn-press/document-course-title-parts', get_the_title() . ' &rarr; ' . $item->get_title(), $item );
232 233
233 234 $flag_title_course = true;
234 235 }
235 - } elseif ( learn_press_is_courses() ) {
236 - if ( learn_press_is_search() ) {
236 + } elseif ( LP_Page_Controller::is_page_courses() ) { // Set title course archive page.
237 + if ( isset( $_GET['c_search'] ) ) {
237 238 $title = __( 'Course Search Results', 'learnpress' );
239 + } elseif ( is_tax( LP_COURSE_CATEGORY_TAX ) || is_tax( LP_COURSE_TAXONOMY_TAG ) ) {
240 + /**
241 + * @var WP_Query $wp_query
242 + */
243 + global $wp_query;
244 + if ( $wp_query->queried_object ) {
245 + $title = $wp_query->queried_object->name;
246 + }
238 247 } else {
239 - $title = __( 'Courses', 'learnpress' );
248 + $title = $course_archive_page_id ? get_the_title( $course_archive_page_id ) : __( 'Courses', 'learnpress' );
240 249 }
241 250
242 251 $flag_title_course = true;
243 - } elseif ( learn_press_is_profile() ) {
244 - $profile = LP_Profile::instance();
245 - $tab_slug = $profile->get_current_tab();
246 - $tab = $profile->get_tab_at( $tab_slug );
252 + } elseif ( LP_Page_Controller::is_page_profile() ) {
253 + $userModel = UserModel::find( get_current_user_id(), true );
254 + $profile = LP_Profile::instance( $user_id );
255 + $page_id = learn_press_get_page_id( 'profile' );
256 + $tab = false;
257 + if ( $userModel ) {
258 + $tab_slug = $profile->get_current_tab();
259 + $tab = $profile->get_tab_at( $tab_slug );
260 + }
247 261
248 - if ( $page_id = learn_press_get_page_id( 'profile' ) ) {
262 + if ( $page_id ) {
249 263 $page_title = get_the_title( $page_id );
250 264 } else {
251 265 $page_title = '';
252 266 }
253 - if ( $tab ) {
267 +
268 + if ( $tab instanceof LP_Profile_Tab ) {
254 269 $title = join(
255 270 ' ',
256 271 apply_filters(
257 272 'learn-press/document-profile-title-parts',
@@ -257,12 +272,14 @@
257 272 'learn-press/document-profile-title-parts',
258 273 array(
259 274 $page_title,
260 275 '&rarr;',
261 - $tab['title'],
276 + $tab->get( 'title' ),
262 277 )
263 278 )
264 279 );
280 + } else {
281 + $title = $page_title;
265 282 }
266 283
267 284 $flag_title_course = true;
268 285 }
@@ -270,8 +287,12 @@
270 287 if ( $flag_title_course ) {
271 288 $title .= ' - ' . get_bloginfo( 'name', 'display' );
272 289 }
273 290
291 + if ( ! is_string( $title ) ) {
292 + $title = get_bloginfo( 'name', 'display' );
293 + }
294 +
274 295 return apply_filters( 'learn-press/title-page', $title );
275 296 }
276 297
277 298 /**
@@ -297,56 +318,19 @@
297 318
298 319 return $desc;
299 320 }
300 321
301 - public function check_pages( $template ) {
302 - if ( learn_press_is_checkout() ) {
303 - $available_gateways = LP_Gateways::instance()->get_available_payment_gateways();
304 -
305 - if ( ! $available_gateways ) {
306 - learn_press_add_message( __( 'No payment method is available.', 'learnpress' ), 'error' );
307 - }
308 - } else {
309 - global $wp_query;
310 -
311 - $logout_slug = learn_press_profile_logout_slug();
312 -
313 - if ( $logout_slug && ( $wp_query->get( 'view' ) === $logout_slug ) ) {
314 - wp_safe_redirect( str_replace( '&amp;', '&', wp_logout_url( learn_press_get_page_link( 'profile' ) ) ) );
315 - exit;
316 - }
317 - }
318 -
319 - return $template;
320 - }
321 -
322 322 /**
323 - * Auto inserting a registered shortcode to a specific page
324 - * if that page is viewing in single mode.
325 - *
326 - * @param string $template
327 - *
328 - * @return string;
329 - * @since 3.3.0
323 + * Handle logout
330 324 */
331 - public function auto_shortcode( $template ) {
332 - global $post;
333 - $the_post = $post;
334 - if ( $the_post && is_page( $the_post->ID ) ) {
325 + public function logout( $template ) {
326 + global $wp_query;
335 327
336 - // Filter here to insert the shortcode
337 - $auto_shortcodes = apply_filters( 'learn-press/auto-shortcode-pages', array() );
328 + $logout_slug = learn_press_profile_logout_slug();
338 329
339 - if ( ! empty( $auto_shortcodes[ $the_post->ID ] ) ) {
340 - $shortcode_tag = $auto_shortcodes[ $the_post->ID ];
341 -
342 - preg_match( '/\[' . $shortcode_tag . '\s?(.*)\]/', $the_post->post_content, $results );
343 -
344 - if ( empty( $results ) ) {
345 - $content = $the_post->post_content . "[$shortcode_tag]";
346 - $the_post->post_content = $content;
347 - }
348 - }
330 + if ( $logout_slug && ( $wp_query->get( 'view' ) === $logout_slug ) ) {
331 + wp_safe_redirect( str_replace( '&amp;', '&', wp_logout_url( learn_press_get_page_link( 'profile' ) ) ) );
332 + exit;
349 333 }
350 334
351 335 return $template;
352 336 }
@@ -367,8 +351,12 @@
367 351 * @var LP_Course $lp_course
368 352 * @var LP_Course_Item|LP_Quiz|LP_Lesson $lp_course_item
369 353 */
370 354 global $wp, $wp_query, $lp_course_item;
355 + $vars = $wp->query_vars;
356 + if ( empty( $vars['course-item'] ) ) {
357 + return $post;
358 + }
371 359
372 360 if ( LP_COURSE_CPT !== $post->post_type ) {
373 361 return $post;
374 362 }
@@ -378,24 +366,30 @@
378 366 return $post;
379 367 }
380 368
381 369 /**
382 - * @deprecated v4.1.6.1 LP()->global['course'], $GLOBALS['course']
383 - * Some theme still use: global $course; LP()->global['course']
370 + * Use for case not load course via send params, use global instead.
371 + * Not recommended for use
372 + * This method is only purpose instead get_the_ID(), on file item of course.
373 + * When all file write by standard callback send param courseModel, this method will be removed.
374 + *
375 + * @return false|CourseModel
376 + * @since 4.2.7.4
384 377 */
385 - //LP()->global['course'] = $GLOBALS['course'] = $GLOBALS['lp_course'] = $course;
386 - LP()->global['course'] = $GLOBALS['course'] = $course;
378 + global $lpCourseModel;
379 + $lpCourseModel = CourseModel::find( $course->get_id(), true );
387 380
388 - if ( wp_verify_nonce( LP_Request::get( 'preview' ), 'preview-' . $post->ID ) ) {
381 + /**
382 + * @deprecated v4.1.6.1 LearnPress::instance()->global['course'], $GLOBALS['course']
383 + * Some theme still use: global $course; LearnPress::instance()->global['course']
384 + */
385 + //LearnPress::instance()->global['course'] = $GLOBALS['course'] = $GLOBALS['lp_course'] = $course;
386 + LearnPress::instance()->global['course'] = $GLOBALS['course'] = $course;
387 +
388 + if ( wp_verify_nonce( LP_Request::get_param( 'preview' ), 'preview-' . $post->ID ) ) {
389 389 $GLOBALS['preview_course'] = $post->ID;
390 390 }
391 391
392 - $vars = $wp->query_vars;
393 -
394 - if ( empty( $vars['course-item'] ) ) {
395 - return $post;
396 - }
397 -
398 392 if ( ! $wp_query->is_main_query() ) {
399 393 return $post;
400 394 }
401 395
@@ -402,14 +396,10 @@
402 396 try {
403 397 $user = learn_press_get_current_user();
404 398
405 399 // If item name is set in query vars
406 - if ( ! is_numeric( $vars['course-item'] ) ) {
407 - $item_type = $vars['item-type'];
408 - $post_item = learn_press_get_post_by_name( $vars['course-item'], $item_type );
409 - } else {
410 - $post_item = get_post( absint( $vars['course-item'] ) );
411 - }
400 + $item_type = $vars['item-type'];
401 + $post_item = learn_press_get_post_by_name( $vars['course-item'], $item_type );
412 402
413 403 if ( ! $post_item ) {
414 404 return $post;
415 405 }
@@ -421,29 +411,15 @@
421 411 }
422 412
423 413 // Set item viewing
424 414 $user->set_viewing_item( $lp_course_item );
425 - } catch ( Exception $ex ) {
426 - learn_press_add_message( $ex->getMessage(), 'error' );
415 + } catch ( Throwable $e ) {
416 + error_log( $e->getMessage() );
427 417 }
428 418
429 419 return $post;
430 420 }
431 421
432 - /**
433 - * Set page 404
434 - *
435 - * @return mixed
436 - * @editor tungnx
437 - * @reason not use
438 - * @deprecated 4.0.0
439 - */
440 - /*
441 - public function set_404( $is_404 ) {
442 - global $wp_query;
443 - $wp_query->is_404 = $this->_is_404 = (bool) $is_404;
444 - }*/
445 -
446 422 public function is_404() {
447 423 return apply_filters( 'learn-press/query/404', $this->_is_404 );
448 424 }
449 425
@@ -467,17 +443,23 @@
467 443 }
468 444
469 445 /**
470 446 * @return bool
447 + * @deprecated v4.2.7.6
471 448 */
472 449 protected function _is_archive() {
450 + _deprecated_function( __METHOD__, '4.1.7.3' );
451 + return false;
473 452 return learn_press_is_courses() || learn_press_is_course_tag() || learn_press_is_course_category() || learn_press_is_search() || learn_press_is_course_tax();
474 453 }
475 454
476 455 /**
477 456 * @return bool
457 + * @deprecated v4.2.7.6
478 458 */
479 459 protected function _is_single() {
460 + _deprecated_function( __METHOD__, '4.1.7.3' );
461 + return false;
480 462 return learn_press_is_course() && is_single();
481 463 }
482 464
483 465 /**
@@ -487,8 +469,11 @@
487 469 *
488 470 * @return bool|string
489 471 */
490 472 public function template_loader( $template ) {
473 + if ( wp_is_block_theme() ) {
474 + return $template;
475 + }
491 476
492 477 if ( is_embed() ) {
493 478 return $template;
494 479 }
@@ -517,8 +502,18 @@
517 502 return $template;
518 503 }
519 504
520 505 /**
506 + * Check if current page is Course Builder
507 + */
508 + public function template_redirect() {
509 + if ( LP_Page_Controller::is_page_course_builder() ) {
510 + include LP_TEMPLATE_PATH . 'pages/course-builder.php';
511 + die;
512 + }
513 + }
514 +
515 + /**
521 516 * Get the default filename for a template.
522 517 *
523 518 * @return string
524 519 * @since 4.0.0
@@ -524,40 +519,59 @@
524 519 * @since 4.0.0
525 520 */
526 521 private function get_page_template() {
527 522 $page_template = '';
523 + $object = get_queried_object();
528 524
529 - if ( is_singular( LP_COURSE_CPT ) ) {
530 - if ( ! self::has_block_template( 'single-course' ) ) {
525 + if ( self::is_page_single_course() ) {
526 + $page_template = 'single-course-layout.php';
527 + // Check condition to load single course layout classic or modern.
528 + $is_override_single_course = Template::check_template_is_override( 'single-course.php' )
529 + || Template::check_template_is_override( 'content-course.php' )
530 + || Template::check_template_is_override( 'content-single-course.php' )
531 + || Template::check_template_is_override( 'loop/single-course/loop-section.php' )
532 + || Template::check_template_is_override( 'single-course/loop-section.php' )
533 + || Template::check_template_is_override( 'single-course/tabs/curriculum.php' )
534 + || Template::check_template_is_override( 'single-course/tabs/curriculum-v2.php' );
535 + $option_single_course_layout = LP_Settings::get_option( 'layout_single_course', '' );
536 +
537 + if ( $is_override_single_course ) { // Old file template
531 538 $page_template = 'single-course.php';
539 + } elseif ( empty( $option_single_course_layout )
540 + || $option_single_course_layout === 'classic' ) {
541 + $page_template = 'single-course-layout-classic.php';
542 + // Set temporary old single course layout.
543 + $page_template = 'single-course.php';
532 544 }
533 545
534 - if ( $this->_is_single() ) {
535 - global $post;
536 - setup_postdata( $post );
546 + // Old single course layout.
547 + //$page_template = 'single-course.php';
537 548
538 - $course_item = LP_Global::course_item();
539 - if ( $course_item && ! self::has_block_template( 'content-single-course-item' ) ) {
540 - $page_template = 'content-single-item.php';
549 + global $post;
550 + setup_postdata( $post );
551 +
552 + $course_item = LP_Global::course_item();
553 + if ( $course_item ) {
554 + $page_template = 'content-single-item.php';
555 + } elseif ( $object ) {
556 + $course = CourseModel::find( $object->ID, true );
557 + if ( $course && $course->is_offline() ) {
558 + $page_template = 'single-course-offline.php';
541 559 }
542 560 }
543 561 } elseif ( learn_press_is_course_taxonomy() ) {
544 - $object = get_queried_object();
545 -
546 562 if ( is_tax( 'course_category' ) || is_tax( 'course_tag' ) ) {
547 563 $page_template = 'taxonomy-' . $object->taxonomy . '.php';
548 564
549 - if ( self::has_block_template( 'taxonomy-' . $object->taxonomy ) ) {
550 - $page_template = '';
551 - } elseif ( ! file_exists( learn_press_locate_template( $page_template ) ) && ! self::has_block_template( 'archive-course' ) ) {
565 + if ( ! file_exists( learn_press_locate_template( $page_template ) ) ) {
552 566 $page_template = 'archive-course.php';
553 567 }
554 - } elseif ( ! self::has_block_template( 'archive-course' ) ) {
568 + } else {
555 569 $page_template = 'archive-course.php';
556 570 }
557 - } 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' ) ) {
571 + } elseif ( self::is_page_courses() ) {
558 572 $page_template = 'archive-course.php';
559 - } elseif ( learn_press_is_checkout() && ! self::has_block_template( 'page-lp_checkout' ) ) {
573 + } elseif ( learn_press_is_checkout() ) {
560 574 $page_template = 'pages/checkout.php';
561 575 }
562 576
563 577 return apply_filters( 'learn-press/page-template', $page_template );
@@ -578,62 +592,34 @@
578 592 }
579 593 }
580 594 }
581 595
582 - if ( is_singular( LP_COURSE_CPT ) ) {
596 + /*if ( is_singular( LP_COURSE_CPT ) ) {
583 597 $object = get_queried_object();
584 598 $name_decoded = urldecode( $object->post_name );
585 599
586 600 if ( $name_decoded !== $object->post_name ) {
587 - $templates[] = "single-course-{$name_decoded}.php";
601 + $templates[] = "single-course-$name_decoded.php";
588 602 }
589 603
590 - $templates[] = "single-product-{$object->post_name}.php";
591 - }
604 + $templates[] = "single-product-$object->post_name.php";
605 + }*/
592 606
593 607 if ( learn_press_is_course_taxonomy() ) {
594 608 $object = get_queried_object();
595 609 $templates[] = 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php';
596 - $templates[] = learn_press_template_path( true ) . 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php';
610 + $templates[] = learn_press_template_path() . '/taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php';
597 611 $templates[] = 'taxonomy-' . $object->taxonomy . '.php';
598 - $templates[] = learn_press_template_path( true ) . 'taxonomy-' . $object->taxonomy . '.php';
612 + $templates[] = learn_press_template_path() . '/taxonomy-' . $object->taxonomy . '.php';
599 613 }
600 614
601 615 $templates[] = $default_template;
602 - $templates[] = learn_press_template_path( true ) . $default_template;
616 + $templates[] = learn_press_template_path() . '/' . $default_template;
603 617
604 618 return array_unique( $templates );
605 619 }
606 620
607 621 /**
608 - * Filter to allow search more templates in theme for wp page template hierarchy.
609 - * Theme twentytwenty used 'singular.php' instead of 'page.php'
610 - *
611 - * @param array $templates
612 - *
613 - * @return array
614 - * @since 3.x.x
615 - * @depecated 4.1.6.9.2
616 - */
617 - /*public function page_template_hierarchy( $templates ) {
618 - $templates = array_merge( $templates, array( 'singular.php' ) );
619 -
620 - return $templates;
621 - }*/
622 -
623 - /**
624 - * Archive course content.
625 - *
626 - * @return false|string
627 - */
628 - public function archive_content() {
629 - ob_start();
630 - learn_press_get_template( 'content-archive-course.php' );
631 -
632 - return ob_get_clean();
633 - }
634 -
635 - /**
636 622 * @param $title
637 623 *
638 624 * @return mixed
639 625 */
@@ -652,10 +638,11 @@
652 638 * @param $q WP_Query
653 639 *
654 640 * @return WP_Query
655 641 * @editor tungnx
656 - * @modify 4.1.2
657 642 * @throws Exception
643 + * @version 4.1.3
644 + * @since 3.0.0
658 645 */
659 646 public function pre_get_posts( WP_Query $q ): WP_Query {
660 647 // Affect only the main query and not in admin
661 648 if ( ! $q->is_main_query() && ! is_admin() ) {
@@ -661,194 +648,195 @@
661 648 if ( ! $q->is_main_query() && ! is_admin() ) {
662 649 return $q;
663 650 }
664 651
665 - // Exclude item not assign
666 - if ( $q->is_search() ) {
667 - // Exclude item not assign any course
668 - $course_item_types = learn_press_get_course_item_types();
669 - $list_ids_exclude = array();
652 + try {
653 + if ( LP_Page_Controller::is_page_courses() ) {
654 + if ( LP_Settings_Courses::is_ajax_load_courses() && ! LP_Settings_Courses::is_no_load_ajax_first_courses()
655 + && ! LP_Settings::theme_no_support_load_courses_ajax() ) {
656 + /**
657 + * If page is archive course - query set posts_per_page = 1
658 + * For fastest - because when page loaded - call API to load list courses
659 + *
660 + * Current, apply only for LP, not apply for theme Thimpress, because theme override
661 + */
662 + $q->set( 'posts_per_page', 1 );
663 + $q->set( 'suppress_filters', true );
664 + //$q->set( 'posts_per_archive_page', 1 );
665 + //$q->set( 'nopaging', true );
666 + } else {
667 + $filter = new LP_Course_Filter();
668 + $filter->only_fields = [ 'ID' ];
669 + $filter->limit = - 1;
670 + $is_need_check_in_arr = false;
671 + $limit = LP_Settings::get_option( 'archive_course_limit', 6 );
670 672
671 - foreach ( $course_item_types as $item_type ) {
672 - $filter = new LP_Post_Type_Filter();
673 - $filter->post_type = $item_type;
674 - $exclude_item = LP_Course_DB::getInstance()->get_item_ids_unassigned( $filter );
675 - $exclude_item = LP_Course_DB::get_values_by_key( $exclude_item );
673 + if ( LP_Settings_Courses::is_ajax_load_courses() &&
674 + LP_Settings_Courses::get_type_pagination() != 'number' &&
675 + ! LP_Settings::theme_no_support_load_courses_ajax() ) {
676 + $q->set( 'paged', 1 );
677 + }
676 678
677 - $list_ids_exclude = array_merge( $list_ids_exclude, $exclude_item );
678 - }
679 + $q->set( 'posts_per_page', $limit );
680 + // $q->set( 'cache_results', true ); // it default true
679 681
680 - // Exclude question not assign any quiz
681 - $question_ids = LP_Question_DB::getInstance()->get_questions_not_assign_quiz();
682 - $question_ids = LP_Course_DB::get_values_by_key( $question_ids );
683 - $list_ids_exclude = array_merge( $list_ids_exclude, $question_ids );
682 + // Search courses by keyword
683 + if ( ! empty( $_REQUEST['c_search'] ) ) {
684 + $filter->post_title = LP_Helper::sanitize_params_submitted( $_REQUEST['c_search'] );
685 + $is_need_check_in_arr = true;
686 + }
684 687
685 - if ( ! empty( $list_ids_exclude ) ) {
686 - $q->set( 'post__not_in', $list_ids_exclude );
687 - }
688 - }
688 + $author_ids_str = LP_Helper::sanitize_params_submitted( $_REQUEST['c_authors'] ?? 0 );
689 + if ( ! empty( $author_ids_str ) ) {
690 + $q->set( 'author', $author_ids_str );
691 + }
689 692
690 - $is_archive_course = false;
693 + // Search course has price/free
694 + $meta_query = [];
695 + if ( isset( $_REQUEST['sort_by'] ) ) {
696 + $sort_by = LP_Helper::sanitize_params_submitted( $_REQUEST['sort_by'] );
697 + if ( 'on_paid' === $sort_by ) {
698 + $meta_query[] = array(
699 + 'key' => '_lp_price',
700 + 'value' => 0,
701 + 'compare' => '>',
702 + );
703 + }
691 704
692 - // Handle 404 if user are viewing course item directly.
693 - $this->set_link_item_course_default_wp_to_page_404( $q );
705 + if ( 'on_free' === $sort_by ) {
706 + $meta_query[] = array(
707 + 'relation' => 'OR',
708 + [
709 + 'key' => '_lp_price',
710 + 'value' => 0,
711 + 'compare' => '=',
712 + ],
713 + [
714 + 'key' => '_lp_price',
715 + 'value' => '',
716 + 'compare' => '=',
717 + ],
718 + [
719 + 'key' => '_lp_price',
720 + 'compare' => 'NOT EXISTS',
721 + ],
722 + );
723 + }
724 + }
694 725
695 - $this->_queried_object = ! empty( $q->queried_object_id ) ? $q->queried_object : false;
726 + // Search by level
727 + $c_level = LP_Helper::sanitize_params_submitted( urldecode( $_REQUEST['c_level'] ?? '' ) );
728 + if ( ! empty( $c_level ) ) {
729 + $c_level = str_replace( 'all', '', $c_level );
730 + $c_level = explode( ',', $c_level );
731 + $meta_query[] = array(
732 + 'key' => '_lp_level',
733 + 'value' => $c_level,
734 + 'compare' => 'IN',
735 + );
736 + }
696 737
697 - /**
698 - * If current page is used for courses page
699 - * Set on both: "Homepage" and "Posts page" on Reading Settings
700 - */
701 - $page_courses_id = learn_press_get_page_id( 'courses' );
738 + $q->set( 'meta_query', $meta_query );
739 + // End Meta query
702 740
703 - if ( $q->is_home() && 'page' == get_option( 'show_on_front' ) && get_option( 'page_on_front' ) == $page_courses_id ) {
704 - $is_archive_course = 1;
705 - // $q->is_home = false;
706 - // $q->set( 'page_id', get_option( 'page_on_front' ) );
707 - }
741 + // Search on Category
742 + $args_cat = lp_archive_skeleton_get_args();
743 + $tax_query = [];
744 + $term_ids_str = LP_Helper::sanitize_params_submitted(
745 + urldecode( $_REQUEST['term_id'] ?? $args_cat['page_term_id_current'] ?? '' )
746 + );
747 + if ( ! empty( $term_ids_str ) ) {
748 + $term_ids = explode( ',', $term_ids_str );
708 749
709 - /**
710 - * If current page is used for courses page and set as "Homepage"
711 - */
712 - if ( $q->is_page() && 'page' == get_option( 'show_on_front' ) && $page_courses_id && $q->get( 'page_id' ) == $page_courses_id ) {
713 - $is_archive_course = 1;
750 + $tax_query[] = array(
751 + 'taxonomy' => 'course_category',
752 + 'field' => 'term_id',
753 + 'terms' => $term_ids,
754 + 'operator' => 'IN',
755 + 'include_children' => false,
756 + );
757 + }
714 758
715 - /*
716 - global $wp_post_types;
759 + // Tag query
760 + $tag_ids_str = LP_Helper::sanitize_params_submitted( urldecode( $_REQUEST['tag_id'] ?? '' ) );
761 + if ( ! empty( $tag_ids_str ) ) {
762 + $term_ids = explode( ',', $tag_ids_str );
717 763
718 - $course_page = get_post( $page_courses_id );
719 - $this->_queried_object = $course_page;
720 - $wp_post_types[ LP_COURSE_CPT ]->ID = $course_page->ID;
721 - $wp_post_types[ LP_COURSE_CPT ]->post_title = $course_page->post_title;
722 - $wp_post_types[ LP_COURSE_CPT ]->post_name = $course_page->post_name;
723 - $wp_post_types[ LP_COURSE_CPT ]->post_type = $course_page->post_type;
724 - $wp_post_types[ LP_COURSE_CPT ]->ancestors = get_ancestors( $course_page->ID, $course_page->post_type );*/
725 - }
764 + $tax_query[] = array(
765 + 'taxonomy' => 'course_tag',
766 + 'field' => 'term_id',
767 + 'terms' => $term_ids,
768 + 'operator' => 'IN',
769 + );
770 + }
726 771
727 - // Set custom posts per page
728 - if ( $this->_is_archive() ) {
729 - $is_archive_course = 1;
730 - }
772 + $q->set( 'tax_query', $tax_query );
773 + // End Tax query
731 774
732 - $apply_lazy_load_for_theme = apply_filters( 'lp/page/courses/query/lazy_load', false );
775 + // Author query
776 + if ( isset( $_REQUEST['c_author'] ) ) {
777 + $author_ids = LP_Helper::sanitize_params_submitted( $_REQUEST['c_author'] );
778 + $q->set( 'author__in', $author_ids );
779 + }
780 + // End Author query
733 781
734 - if ( $is_archive_course ) {
735 - if ( ( LP_Settings_Courses::is_ajax_load_courses() && ! LP_Settings_Courses::is_no_load_ajax_first_courses() ) ) {
736 - LP()->template( 'course' )->remove_callback( 'learn-press/after-courses-loop', 'loop/course/pagination.php', 10 );
737 - /**
738 - * If page is archive course - query set posts_per_page = 1
739 - * For fastest - because when page loaded - call API to load list courses
740 - *
741 - * Current, apply only for LP, not apply for theme Thimpress, because theme override
742 - */
743 - $q->set( 'posts_per_page', 1 );
744 - $q->set( 'posts_per_archive_page', 1 );
745 - $q->set( 'nopaging', true );
746 - } else {
747 - $filter = new LP_Course_Filter();
748 - $filter->only_fields = [ 'ID' ];
749 - $filter->max_limit = $filter->limit = 1000;
750 - $is_need_check_in_arr = false;
751 - $limit = LP_Settings::get_option( 'archive_course_limit', 6 );
782 + // Order query
783 + if ( isset( $_REQUEST['order_by'] ) ) {
784 + $order_by = LP_Helper::sanitize_params_submitted( $_REQUEST['order_by'] );
785 + $order = 'DESC';
752 786
753 - $q->set( 'posts_per_page', $limit );
754 - // $q->set( 'cache_results', true ); // it default true
787 + switch ( $order_by ) {
788 + case 'post_title':
789 + $order_by = 'title';
790 + $order = 'ASC';
791 + break;
792 + case 'popular':
793 + $filter->order_by = 'popular';
794 + $order_by = 'post__in';
795 + $is_need_check_in_arr = true;
796 + break;
797 + default:
798 + $order_by = 'date';
799 + break;
800 + }
755 801
756 - // Search courses by keyword
757 - // $q->set( 's', $_REQUEST['c_search'] ?? '' );
758 - if ( ! empty( $_REQUEST['c_search'] ) ) {
759 - $filter->post_title = LP_Helper::sanitize_params_submitted( $_REQUEST['c_search'] );
760 - $is_need_check_in_arr = true;
761 - }
762 -
763 - $author_ids_str = LP_Helper::sanitize_params_submitted( $_REQUEST['c_authors'] ?? 0 );
764 - if ( ! empty( $author_ids_str ) ) {
765 - $q->set( 'author', $author_ids_str );
766 - }
767 -
768 - // Meta query
769 - $meta_query = [];
770 - if ( isset( $_REQUEST['sort_by'] ) ) {
771 - $sort_by = LP_Helper::sanitize_params_submitted( $_REQUEST['sort_by'] );
772 - if ( 'on_paid' === $sort_by ) {
773 - $meta_query[] = array(
774 - 'key' => '_lp_price',
775 - 'value' => 0,
776 - 'compare' => '>',
777 - );
802 + $q->set( 'orderby', $order_by );
803 + $q->set( 'order', $order );
778 804 }
779 805
780 - if ( 'on_free' === $sort_by ) {
781 - $meta_query[] = array(
782 - 'key' => '_lp_price',
783 - 'value' => 0,
784 - 'compare' => '=',
785 - );
806 + if ( $is_need_check_in_arr ) {
807 + $posts_in = Courses::get_courses( $filter );
808 + if ( ! empty( $posts_in ) ) {
809 + $posts_in = LP_Database::get_values_by_key( $posts_in );
810 + $q->set( 'post__in', $posts_in );
811 + } else {
812 + $q->set( 'post__in', 0 );
813 + }
786 814 }
787 - }
788 - $q->set( 'meta_query', $meta_query );
789 - // End Meta query
790 815
791 - // Tax query
792 - $tax_query = [];
793 - $term_ids_str = LP_Helper::sanitize_params_submitted( urldecode( $_REQUEST['term_id'] ?? '' ) );
794 - if ( ! empty( $term_ids_str ) ) {
795 - $term_ids = explode( ',', $term_ids_str );
796 -
797 - $tax_query[] = array(
798 - 'taxonomy' => 'course_category',
799 - 'field' => 'term_id',
800 - 'terms' => $term_ids,
801 - 'operator' => 'IN',
802 - );
816 + $q = apply_filters( 'lp/page-courses/query/legacy', $q );
803 817 }
804 818
805 - $q->set( 'tax_query', $tax_query );
806 - // End Tax query
819 + return $q;
820 + }
807 821
808 - // Author query
809 - if ( isset( $_REQUEST['c_author'] ) ) {
810 - $author_ids = LP_Helper::sanitize_params_submitted( $_REQUEST['c_author'] );
811 - $q->set( 'author__in', $author_ids );
812 - }
813 - // End Author query
822 + // Exclude item not assign
823 + if ( $q->is_search() ) {
824 + return $q;
825 + }
814 826
815 - // Order query
816 - if ( isset( $_REQUEST['order_by'] ) ) {
817 - $order_by = LP_Helper::sanitize_params_submitted( $_REQUEST['order_by'] );
818 - $order = 'DESC';
827 + // Handle 404 if user are viewing course item directly.
828 + $this->set_link_item_course_default_wp_to_page_404( $q );
819 829
820 - switch ( $order_by ) {
821 - case 'post_title':
822 - $order_by = 'title';
823 - $order = 'ASC';
824 - break;
825 - case 'popular':
826 - $filter->order_by = 'popular';
827 - $order_by = 'post__in';
828 - $is_need_check_in_arr = true;
829 - break;
830 - default:
831 - $order_by = 'date';
832 - break;
833 - }
834 -
835 - $q->set( 'orderby', $order_by );
836 - $q->set( 'order', $order );
830 + // set 404 if viewing single instructor but not logged
831 + $slug_instructor = get_query_var( 'instructor_name' );
832 + if ( get_query_var( 'is_single_instructor' ) ) {
833 + if ( empty( $slug_instructor ) && ! is_user_logged_in() ) {
834 + self::set_page_404();
837 835 }
838 -
839 - if ( $is_need_check_in_arr ) {
840 - $posts_in = LP_Course::get_courses( $filter );
841 - if ( ! empty( $posts_in ) ) {
842 - $posts_in = LP_Database::get_values_by_key( $posts_in );
843 - $q->set( 'post__in', $posts_in );
844 - } else {
845 - $q->set( 'post__in', 0 );
846 - }
847 - }
848 -
849 - $q = apply_filters( 'lp/page-courses/query/legacy', $q );
850 836 }
837 + } catch ( Throwable $e ) {
838 + error_log( $e->getMessage() );
851 839 }
852 840
853 841 return $q;
854 842 }
@@ -859,27 +847,32 @@
859 847 * Apply for user not admin, instructor, co-instructor
860 848 *
861 849 * @param WP_Query $q
862 850 *
863 - * @return mixed
864 851 * @editor tungnx
865 852 * @since 3.2.7.5
866 853 */
867 854 public function set_link_item_course_default_wp_to_page_404( $q ) {
868 - if ( ! $q->is_main_query() || is_admin() ) {
869 - return $q;
855 + $post_type_apply_404 = apply_filters(
856 + 'lp/page-controller/',
857 + array(
858 + LP_LESSON_CPT,
859 + LP_QUIZ_CPT,
860 + LP_QUESTION_CPT,
861 + 'lp_assignment',
862 + )
863 + );
864 +
865 + if ( ! isset( $q->query_vars['post_type'] ) || ! in_array( $q->query_vars['post_type'], $post_type_apply_404 ) ) {
866 + return;
870 867 }
871 868
872 - $post_type_apply_404 = array( LP_LESSON_CPT, LP_QUIZ_CPT, LP_QUESTION_CPT, 'lp_assignment' );
873 -
874 - if ( isset( $q->query_vars['post_type'] ) && in_array( $q->query_vars['post_type'], $post_type_apply_404 ) ) {
869 + try {
875 870 $flag_load_404 = true;
876 871 $user = wp_get_current_user();
877 872 $post_author = 0;
878 873
879 874 if ( $user ) {
880 - $post = null;
881 -
882 875 if ( isset( $_GET['preview_id'] ) ) {
883 876 $post_id = absint( $_GET['preview_id'] );
884 877 $post = get_post( $post_id );
885 878 $post_author = $post->post_author;
@@ -887,9 +880,9 @@
887 880 $post_id = absint( $_GET['p'] );
888 881 $post = get_post( $post_id );
889 882 $post_author = $post->post_author;
890 883 } else {
891 - $post_author = LP_Database::getInstance()->getPostAuthorByTypeAndSlug( $q->query_vars['post_type'], $q->query_vars[ $q->query_vars['post_type'] ] );
884 + $post_author = LP_Database::getInstance()->getPostAuthorByTypeAndSlug( $q->query_vars['post_type'] ?? '', $q->query_vars['name'] ?? '' );
892 885 }
893 886
894 887 if ( $user->has_cap( 'administrator' ) ) {
895 888 $flag_load_404 = false;
@@ -900,83 +893,295 @@
900 893
901 894 $flag_load_404 = apply_filters( 'learnpress/page/set-link-item-course-404', $flag_load_404, $post_author, $user );
902 895
903 896 if ( $flag_load_404 ) {
904 - learn_press_404_page();
905 - $q->set( 'post_type', '' );
897 + self::set_page_404();
906 898 }
899 + } catch ( Throwable $e ) {
900 + error_log( $e->getMessage() );
907 901 }
902 + }
908 903
909 - return $q;
904 + /**
905 + * Get page current on frontend
906 + *
907 + * @return string
908 + * @since 3.2.8
909 + * @author tungnx
910 + */
911 + public static function page_current(): string {
912 + /**
913 + * @var WP_Query $wp_query
914 + */
915 + global $wp_query;
916 +
917 + // Course Builder page detection
918 + if ( self::is_page_course_builder() ) {
919 + return LP_PAGE_COURSE_BUILDER;
920 + }
921 +
922 + if ( ! is_object( $wp_query ) || ! $wp_query->get_queried_object() ) {
923 + return '';
924 + }
925 +
926 + if ( self::is_page_checkout() ) {
927 + return LP_PAGE_CHECKOUT;
928 + } elseif ( LP_Global::course_item_quiz() ) {
929 + return LP_PAGE_QUIZ;
930 + } elseif ( learn_press_is_course() && LP_Global::course_item() ) {
931 + return LP_PAGE_SINGLE_COURSE_CURRICULUM;
932 + } elseif ( self::is_page_courses() ) {
933 + return LP_PAGE_COURSES;
934 + } elseif ( learn_press_is_course() ) {
935 + return LP_PAGE_SINGLE_COURSE;
936 + } elseif ( self::is_page_become_a_teacher() ) {
937 + return LP_PAGE_BECOME_A_TEACHER;
938 + } elseif ( self::is_page_profile() ) {
939 + return LP_PAGE_PROFILE;
940 + } elseif ( learn_press_is_instructors() ) {
941 + return LP_PAGE_INSTRUCTORS;
942 + } elseif ( self::is_page_instructor() ) {
943 + return LP_PAGE_INSTRUCTOR;
944 + } else {
945 + return apply_filters( 'learnpress/page/current', '' );
946 + }
910 947 }
911 948
912 949 /**
913 - * @depecated 4.1.6.9.2
950 + * Check is page viewing
951 + *
952 + * @param string $name
953 + *
954 + * @return bool
914 955 */
915 - /*public function the_content_callback( $content ) {
916 - if ( $this->_archive_contents ) {
917 - preg_match( '/\[learn_press_archive_course\s?(.*)\]/', $content, $results );
918 - $this->_shortcode_exists = ! empty( $results );
919 - if ( $this->_shortcode_exists ) {
920 - $this->_shortcode_tag = $results[0];
921 - $content = str_replace( $this->_shortcode_tag, $this->_archive_contents, $content );
956 + public static function page_is( string $name = '' ): bool {
957 + $page_id = learn_press_get_page_id( $name );
958 + if ( ! $page_id || 'page' !== get_post_type( $page_id ) ) {
959 + return false;
960 + }
961 +
962 + // If pages of LP set to homepage will return false
963 + $link_page = urldecode( get_the_permalink( $page_id ) );
964 + $home_url = home_url( '/' );
965 + if ( $home_url === $link_page ) {
966 + return false;
967 + }
968 +
969 + $page_profile_option = untrailingslashit( $link_page );
970 + $page_profile_option = str_replace( '/', '\/', $page_profile_option );
971 + $pattern = "/^$page_profile_option/";
972 + if ( preg_match( $pattern, LP_Helper::getUrlCurrent() ) ) {
973 + return true;
974 + }
975 +
976 + return false;
977 + }
978 +
979 + /**
980 + * Check is page is single course
981 + *
982 + * @since 4.2.7.6
983 + * @version 1.0.0
984 + * @return bool
985 + */
986 + public static function is_page_single_course(): bool {
987 + static $flag;
988 + if ( ! is_null( $flag ) ) {
989 + return $flag;
990 + }
991 +
992 + try {
993 + $flag = is_singular( LP_COURSE_CPT );
994 + } catch ( Throwable $e ) {
995 + $flag = false;
996 + }
997 +
998 + return $flag;
999 + }
1000 +
1001 + /**
1002 + * Check is page courses
1003 + *
1004 + * @return bool
1005 + */
1006 + public static function is_page_courses(): bool {
1007 + static $flag;
1008 + if ( ! is_null( $flag ) ) {
1009 + return $flag;
1010 + }
1011 +
1012 + $is_tag = is_tax( LP_COURSE_TAXONOMY_TAG );
1013 + $is_category = is_tax( LP_COURSE_CATEGORY_TAX );
1014 +
1015 + if ( $is_category || $is_tag || is_post_type_archive( 'lp_course' ) ) {
1016 + $flag = true;
1017 + } else {
1018 + $page_courses_id = learn_press_get_page_id( 'courses' );
1019 + $page_courses_url = untrailingslashit( get_the_permalink( $page_courses_id ) );
1020 + if ( empty( $page_courses_url ) ) {
1021 + $page_courses_url = home_url( 'courses' );
1022 + }
1023 +
1024 + $page_courses_regex = str_replace( '/', '\/', $page_courses_url );
1025 + $pattern = '/' . $page_courses_regex . '\/?(page\/[0-9]*)?$/';
1026 + if ( preg_match( $pattern, LP_Helper::getUrlCurrent() ) ) {
1027 + $flag = true;
922 1028 } else {
923 - $content .= $this->_archive_contents;
1029 + $flag = false;
924 1030 }
925 1031 }
926 1032
927 - return $content;
928 - }*/
1033 + return $flag;
1034 + }
929 1035
930 1036 /**
1037 + * Check is page profile
1038 + *
1039 + * @return bool
1040 + */
1041 + public static function is_page_profile(): bool {
1042 + static $flag;
1043 + if ( ! is_null( $flag ) ) {
1044 + return $flag;
1045 + }
1046 +
1047 + $flag = self::page_is( 'profile' );
1048 +
1049 + return $flag;
1050 + }
1051 +
1052 + /**
1053 + * Check is page instructor
1054 + *
1055 + * @return bool
1056 + */
1057 + public static function is_page_instructors(): bool {
1058 + static $flag;
1059 + if ( ! is_null( $flag ) ) {
1060 + return $flag;
1061 + }
1062 +
1063 + $flag = self::page_is( 'instructors' );
1064 +
1065 + return $flag;
1066 + }
1067 +
1068 + /**
1069 + * Check is page instructor
1070 + *
1071 + * @return bool
1072 + */
1073 + public static function is_page_instructor(): bool {
1074 + global $wp_query;
1075 + static $flag;
1076 + if ( ! is_null( $flag ) ) {
1077 + return $flag;
1078 + }
1079 +
1080 + $flag = false;
1081 + if ( $wp_query->get( 'is_single_instructor' ) ) {
1082 + $flag = true;
1083 + }
1084 +
1085 + return $flag;
1086 + }
1087 +
1088 + /**
1089 + * Check is page profile
1090 + *
1091 + * @return bool
1092 + */
1093 + public static function is_page_checkout(): bool {
1094 + return self::page_is( 'checkout' );
1095 + }
1096 +
1097 + /**
931 1098 * Check is page Become a teacher
932 1099 *
933 - * @return bool|mixed|void
1100 + * @return bool
934 1101 * @since 3.2.8
935 1102 * @author tungnx
936 1103 */
937 - public static function is_page_become_a_teacher() {
938 - $page_id = learn_press_get_page_id( 'become_a_teacher' );
1104 + public static function is_page_become_a_teacher(): bool {
1105 + return self::page_is( 'become_a_teacher' );
1106 + }
939 1107
940 - if ( $page_id && is_page( $page_id ) ) {
1108 + /**
1109 + * Check page is LP Ajax
1110 + *
1111 + * @return bool
1112 + * @since 4.2.7.7
1113 + */
1114 + public static function is_page_lp_ajax(): bool {
1115 + // If pages of LP set to homepage will return false
1116 + $pattern = '/lp-ajax-handle/';
1117 + if ( preg_match( $pattern, LP_Helper::getUrlCurrent() ) ) {
941 1118 return true;
942 1119 }
943 1120
944 - return apply_filters( 'learnpress/is-page/become-a-teacher', false );
1121 + return false;
945 1122 }
946 1123
947 1124 /**
948 - * Get page current on frontend
1125 + * Redirect admin to course builder if hide instructor access admin screen
949 1126 *
1127 + * @since 4.3.6
1128 + * @version 1.0.0
1129 + */
1130 + public function redirect_admin_to_course_builder() {
1131 + // Skip AJAX requests
1132 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
1133 + return;
1134 + }
1135 +
1136 + // Check hide instructor access admin screen
1137 + $hide_instructor_access_admin_screen = LP_Settings::is_hide_instructor_access_admin_screen();
1138 + if ( $hide_instructor_access_admin_screen
1139 + && current_user_can( UserModel::ROLE_INSTRUCTOR ) ) {
1140 + $cb_url = CourseBuilder::get_link_course_builder();
1141 +
1142 + // Avoid infinite redirect
1143 + if ( strpos( LP_Helper::getUrlCurrent(), $cb_url ) !== false ) {
1144 + return;
1145 + }
1146 +
1147 + wp_redirect( $cb_url );
1148 + exit;
1149 + }
1150 + }
1151 +
1152 + public static function is_page_course_builder(): bool {
1153 + /** @var WP_Query $wp_query */
1154 + global $wp_query;
1155 + return $wp_query->get( 'is_course_builder' );
1156 + }
1157 +
1158 + /**
1159 + * Get link page by name
1160 + *
1161 + * @param string $page_name
1162 + * @param array $args
1163 + * @param bool $no_cache
1164 + *
950 1165 * @return string
951 - * @since 3.2.8
952 - * @author tungnx
1166 + * @since 4.2.7.8
1167 + * @version 1.0.0
953 1168 */
954 - public static function page_current(): string {
955 - if ( learn_press_is_checkout() ) {
956 - return LP_PAGE_CHECKOUT;
957 - } elseif ( LP_Global::course_item_quiz() ) {
958 - return LP_PAGE_QUIZ;
959 - } elseif ( learn_press_is_course() && is_single() && LP_Global::course_item() ) {
960 - return LP_PAGE_SINGLE_COURSE_CURRICULUM;
961 - } elseif ( learn_press_is_courses() ) {
962 - return LP_PAGE_COURSES;
963 - } elseif ( learn_press_is_course() ) {
964 - return LP_PAGE_SINGLE_COURSE;
965 - } elseif ( self::is_page_become_a_teacher() ) {
966 - return LP_PAGE_BECOME_A_TEACHER;
967 - } elseif ( learn_press_is_profile() ) {
968 - return LP_PAGE_PROFILE;
969 - } else {
970 - return apply_filters( 'learnpress/page/current', '' );
1169 + public static function get_link_page( string $page_name, array $args = [], bool $no_cache = false ): string {
1170 + $page_link = learn_press_get_page_link( $page_name );
1171 +
1172 + if ( ! empty( $args ) ) {
1173 + $page_link = add_query_arg( $args, $page_link );
971 1174 }
1175 +
1176 + if ( $no_cache ) {
1177 + $page_link = LP_Helper::get_link_no_cache( $page_link );
1178 + }
1179 +
1180 + return $page_link;
972 1181 }
973 1182
974 1183 public static function instance() {
975 - if ( is_admin() ) {
976 - return null;
977 - }
978 -
979 1184 if ( ! self::$_instance ) {
980 1185 self::$_instance = new self();
981 1186 }
982 1187
@@ -988,10 +1193,14 @@
988 1193 *
989 1194 * @editor tungnx
990 1195 * @version 1.0.1
991 1196 * @since 3.0.0
1197 + * @deprecated 4.1.7.3
992 1198 */
993 1199 public function learn_press_edit_admin_bar() {
1200 + _deprecated_function( __METHOD__, '4.1.7.3' );
1201 + return;
1202 +
994 1203 global $wp_admin_bar;
995 1204
996 1205 $current_user = wp_get_current_user();
997 1206
@@ -999,11 +1208,11 @@
999 1208 return;
1000 1209 }
1001 1210
1002 1211 $page_profile_id = learn_press_get_page_id( 'profile' );
1003 -
1004 1212 if ( $page_profile_id && get_post_status( $page_profile_id ) != 'trash' ) {
1005 1213 $user_id = $current_user->ID;
1214 + $profile = LP_Profile::instance( $user_id );
1006 1215
1007 1216 $wp_admin_bar->add_menu(
1008 1217 array(
1009 1218 'id' => 'course_profile',
@@ -1008,12 +1217,109 @@
1008 1217 array(
1009 1218 'id' => 'course_profile',
1010 1219 'parent' => 'user-actions',
1011 1220 'title' => get_the_title( $page_profile_id ),
1012 - 'href' => learn_press_user_profile_link( $user_id, false ),
1221 + 'href' => $profile->get_tab_link(),
1013 1222 )
1014 1223 );
1015 1224 }
1016 1225 }
1226 +
1227 + /**
1228 + * Set again HTTP_X_WP_NONCE when cache make 403 error.
1229 + *
1230 + * @param $send_no_cache_headers
1231 + *
1232 + * @return mixed
1233 + * @since 4.1.7
1234 + * @version 1.0.0
1235 + */
1236 + public function check_x_wp_nonce_cache( $send_no_cache_headers ) {
1237 + if ( ! $send_no_cache_headers && ! is_admin() && $_SERVER['REQUEST_METHOD'] == 'GET' && LP_Helper::isRestApiLP() ) {
1238 + $nonce = wp_create_nonce( 'wp_rest' );
1239 + $_SERVER['HTTP_X_WP_NONCE'] = $nonce;
1240 + }
1241 +
1242 + return $send_no_cache_headers;
1243 + }
1244 +
1245 + /**
1246 + * Override lesson comment permalink.
1247 + *
1248 + * @param string $link The comment permalink with '#comment-$id' appended.
1249 + * @param WP_Comment $comment The current comment object.
1250 + *
1251 + * @return string $link The comment permalink with '#comment-$id' appended.
1252 + * @since 4.2.3
1253 + * @version 1.0.0
1254 + */
1255 + public function edit_lesson_comment_links( $link, $comment ): string {
1256 + try {
1257 + $comment = get_comment( $comment );
1258 + if ( get_post_type( $comment->comment_post_ID ) == LP_LESSON_CPT ) {
1259 + $link = wp_get_referer() . '#comment-' . $comment->comment_ID;
1260 + }
1261 +
1262 + return $link;
1263 + } catch ( Throwable $e ) {
1264 + error_log( $e->getMessage() );
1265 + }
1266 +
1267 + return $link;
1268 + }
1269 +
1270 + /**
1271 + * Set menu active for page courses.
1272 + *
1273 + * @param $menu_items
1274 + *
1275 + * @return mixed
1276 + */
1277 + public function menu_active( $menu_items ) {
1278 + $course_page = learn_press_get_page_id( 'courses' );
1279 + $page_for_posts = (int) get_option( 'page_for_posts' );
1280 +
1281 + if ( is_array( $menu_items ) && ! empty( $menu_items ) ) {
1282 + foreach ( $menu_items as $key => $menu_item ) {
1283 + $classes = (array) $menu_item->classes;
1284 + $menu_id = (int) $menu_item->object_id;
1285 +
1286 + // Unset active class for blog page.
1287 + if ( $page_for_posts === $menu_id ) {
1288 + $menu_item->current = false;
1289 +
1290 + if ( in_array( 'current_page_parent', $classes, true ) ) {
1291 + unset( $classes[ array_search( 'current_page_parent', $classes, true ) ] );
1292 + }
1293 +
1294 + if ( in_array( 'current-menu-item', $classes, true ) ) {
1295 + unset( $classes[ array_search( 'current-menu-item', $classes, true ) ] );
1296 + }
1297 + } elseif ( ( is_post_type_archive( 'lp_course' ) || is_page( $course_page ) ) && $course_page === $menu_id && 'page' === $menu_item->object ) {
1298 + // Set active state if this is the shop page link.
1299 + $menu_item->current = true;
1300 + $classes[] = 'current-menu-item';
1301 + $classes[] = 'current_page_item';
1302 + } elseif ( is_singular( 'lp_course' ) && $course_page === $menu_id ) {
1303 + // Set parent state if this is a product page.
1304 + $classes[] = 'current_page_parent';
1305 + }
1306 +
1307 + $menu_item->classes = array_unique( $classes );
1308 + $menu_items[ $key ] = $menu_item;
1309 + }
1310 + }
1311 +
1312 + return $menu_items;
1313 + }
1314 +
1315 + /**
1316 + * Set Page viewing to 404
1317 + *
1318 + * @return void
1319 + */
1320 + public static function set_page_404() {
1321 + global $wp_query;
1322 + $wp_query->set_404();
1323 + status_header( 404 );
1324 + }
1017 1325 }
1018 -
1019 -return LP_Page_Controller::instance();