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