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

lp-core-functions.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.1.6.9.1, at inc/lp-core-functions.php

3,884 lines 96.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * LearnPress Core Functions
4 * Define common functions for both front-end and back-end
5 *
6 * @author ThimPress
7 * @package LearnPress/Functions
8 * @version 1.0
9 */
10
11 defined( 'ABSPATH' ) || exit;
12
13 /**
14 * Vue write php has script, so when sanitize will error, so use code is mask pass check sanitize, esc
15 *
16 * @param $content
17 *
18 * @return void
19 * @since 4.1.6.9
20 */
21 function learn_press_echo_vuejs_write_on_php( $content ) {
22 echo ( $content );
23 }
24
25 function learnpress_gutenberg_disable_cpt( $can_edit, $post_type ) {
26 $post_types = array(
27 LP_COURSE_CPT => LP_Settings::get_option( 'enable_gutenberg_course', 'no' ),
28 LP_LESSON_CPT => LP_Settings::get_option( 'enable_gutenberg_lesson', 'no' ),
29 LP_QUIZ_CPT => LP_Settings::get_option( 'enable_gutenberg_quiz', 'no' ),
30 LP_QUESTION_CPT => LP_Settings::get_option( 'enable_gutenberg_question', 'no' ),
31 );
32
33 foreach ( $post_types as $key => $pt ) {
34 if ( $post_type === $key && $pt !== 'yes' ) {
35 $can_edit = false;
36 }
37 }
38
39 return $can_edit;
40 }
41 add_filter( 'use_block_editor_for_post_type', 'learnpress_gutenberg_disable_cpt', 10, 2 );
42
43 /**
44 * Get instance of a CURD class by type
45 *
46 * @param string $type
47 *
48 * @return bool|LP_Course_CURD|LP_User_CURD|LP_Quiz_CURD|LP_Question_CURD
49 */
50 function learn_press_get_curd( $type ) {
51 $curds = array(
52 'user' => 'LP_User_CURD',
53 'course' => 'LP_Course_CURD',
54 'quiz' => 'LP_Quiz_CURD',
55 'question' => 'LP_Question_CURD',
56 );
57
58 $curd = false;
59
60 if ( ! empty( $curds[ $type ] ) && class_exists( $curds[ $type ] ) ) {
61 $curd = new $curds[ $type ]();
62 }
63
64 return apply_filters( 'learn-press/curd', $curd, $type, $curds );
65 }
66
67 if ( ! function_exists( 'lp_add_body_class' ) ) {
68 function lp_add_body_class( $classes ) {
69 $classes = (array) $classes;
70
71 if ( learn_press_is_profile() ) {
72 $classes[] = 'learnpress-profile';
73 } elseif ( learn_press_is_checkout() ) {
74 $classes[] = 'learnpress-checkout';
75 }
76
77 return $classes;
78 }
79 add_filter( 'body_class', 'lp_add_body_class' );
80 }
81
82 /**
83 * Short function to get name of a theme
84 *
85 * @param string $folder
86 *
87 * @return mixed|string
88 */
89 function learn_press_get_theme_name( $folder ) {
90 $theme = wp_get_theme( $folder );
91
92 return ! empty( $theme['Name'] ) ? $theme['Name'] : '';
93 }
94
95 /**
96 * Clean.
97 *
98 * @param [type] $var
99 *
100 * @version 4.0.0
101 * @author Nhamdv <daonham95@gmail.com>
102 */
103 function learnpress_clean( $var ) {
104 if ( is_array( $var ) ) {
105 return array_map( 'learnpress_clean', $var );
106 } else {
107 return is_scalar( $var ) ? sanitize_text_field( $var ) : $var;
108 }
109 }
110
111 /**
112 * Display HTML of element for building QuickTip JS.
113 *
114 * @param string $tip
115 * @param bool $echo
116 * @param array $options
117 *
118 * @return string
119 * @since 3.0.0
120 */
121 function learn_press_quick_tip( $tip, $echo = true, $options = array() ) {
122 $atts = '';
123 if ( $options ) {
124 foreach ( $options as $k => $v ) {
125 $options[ $k ] = "data-{$k}=\"{$v}\"";
126 }
127 $atts = ' ' . implode( ' ', $options );
128 }
129
130 $tip = sprintf( '<span class="learn-press-tip" ' . $atts . '>%s</span>', $tip );
131
132 if ( $echo ) {
133 echo wp_kses_post( $tip );
134 }
135
136 return $tip;
137 }
138
139 /**
140 * Return TRUE if defined WP_DEBUG and is true or 1.
141 *
142 * @return bool
143 * @editor tungnx
144 * @depecated 4.1.6.4
145 */
146 function learn_press_is_debug() {
147 _deprecated_function( __FUNCTION__, '4.1.6.4' );
148 return LP_Debug::is_debug();
149 }
150
151 /**
152 * Get current post ID.
153 *
154 * @return int
155 */
156 function learn_press_get_post() {
157 global $post;
158
159 $post_id = learn_press_get_request( 'post' );
160
161 if ( ! $post_id ) {
162 $post_id = ! empty( $post ) ? $post->ID : 0;
163 }
164 if ( empty( $post_id ) ) {
165 $post_id = learn_press_get_request( 'post_ID' );
166 }
167
168 return absint( $post_id );
169 }
170
171 /**
172 * Get the LearnPress plugin url
173 *
174 * @param string $sub_dir
175 *
176 * @return string
177 */
178 function learn_press_plugin_url( $sub_dir = '' ) {
179 return LP()->plugin_url( $sub_dir );
180 }
181
182 /**
183 * Get the LearnPress plugin path.
184 *
185 * @param string $sub_dir
186 *
187 * @return string
188 */
189 function learn_press_plugin_path( $sub_dir = '' ) {
190 return LP()->plugin_path( $sub_dir );
191 }
192
193 /**
194 * Includes file base on LearnPress path
195 *
196 * @param string $file
197 * @param string $folder
198 * @param bool $include_once
199 *
200 * @return bool
201 */
202 function learn_press_include( $file, $folder = 'inc', $include_once = true ) {
203 $include = learn_press_plugin_path( "{$folder}/{$file}" );
204
205 if ( file_exists( $include ) ) {
206 if ( $include_once ) {
207 include_once $include;
208 } else {
209 include $include;
210 }
211
212 return true;
213 }
214
215 return false;
216 }
217
218 /**
219 * Get current IP of the user
220 *
221 * @return mixed
222 */
223 function learn_press_get_ip() {
224 if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) {
225 return sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_REAL_IP'] ) );
226 } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
227 // Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2
228 // Make sure we always only send through the first IP in the list which should always be the client IP.
229 return (string) rest_is_ip_address( trim( current( preg_split( '/,/', sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) ) ) );
230 } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
231 return sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) );
232 }
233 return '';
234 }
235
236 /**
237 * Get user agent.
238 *
239 * @return string
240 */
241 function learn_press_get_user_agent(): string {
242 return LP_Helper::sanitize_params_submitted( $_SERVER['HTTP_USER_AGENT'] ?? '' );
243 }
244
245 /**
246 * Generate an unique string.
247 *
248 * @param string $prefix
249 *
250 * @return string
251 */
252 function learn_press_uniqid( $prefix = '' ) {
253 $hash = str_replace( '.', '', microtime( true ) . uniqid() );
254
255 return apply_filters( 'learn-press/generate-hash', $prefix . $hash, $prefix );
256 }
257
258 function learn_press_random_value( $len = 8 ) {
259 return substr( md5( uniqid( mt_rand(), true ) ), 0, $len );
260 }
261
262 function learn_press_map_columns_format( $columns, $format ) {
263 $return = array();
264 foreach ( $columns as $k => $v ) {
265 if ( ! empty( $format[ $k ] ) ) {
266 $return[] = $format[ $k ];
267 } else {
268 $return[] = '%s'; // default is string
269 }
270 }
271
272 return $return;
273 }
274
275 /**
276 * Check to see if an endpoint is showing in current URL.
277 *
278 * @param bool $endpoint
279 *
280 * @return bool
281 */
282 function learn_press_is_endpoint_url( $endpoint = false ) {
283 global $wp;
284
285 $endpoints = array();
286
287 if ( $endpoint !== false ) {
288 if ( ! isset( $endpoints[ $endpoint ] ) ) {
289 return false;
290 } else {
291 $endpoint_var = $endpoints[ $endpoint ];
292 }
293
294 return isset( $wp->query_vars[ $endpoint_var ] );
295 } else {
296 foreach ( $endpoints as $key => $value ) {
297 if ( isset( $wp->query_vars[ $key ] ) ) {
298 return true;
299 }
300 }
301
302 return false;
303 }
304 }
305
306 /**
307 * Get current URL user is viewing.
308 *
309 * @return string
310 */
311 function learn_press_get_current_url() {
312 static $current_url;
313
314 if ( ! $current_url ) {
315 $url = untrailingslashit( esc_url_raw( $_SERVER['REQUEST_URI'] ) );
316
317 if ( ! preg_match( '!^https?!', $url ) ) {
318 $siteurl = trailingslashit( get_home_url() );
319 $home_query = '';
320
321 if ( strpos( $siteurl, '?' ) !== false ) {
322 $parts = explode( '?', $siteurl );
323 $home_query = $parts[1];
324 $siteurl = $parts[0];
325 }
326
327 if ( $home_query ) {
328 parse_str( untrailingslashit( $home_query ), $home_query );
329 $url = esc_url_raw( add_query_arg( $home_query, $url ) );
330 }
331
332 $segs1 = explode( '/', $siteurl );
333 $segs2 = explode( '/', $url );
334
335 if ( $removed = array_intersect( $segs1, $segs2 ) ) {
336 if ( $segs2 = array_diff( $segs2, $removed ) ) {
337 $current_url = $siteurl . join( '/', $segs2 );
338 if ( strpos( $current_url, '?' ) === false ) {
339 $current_url = trailingslashit( $current_url );
340 }
341 }
342 }
343 }
344 }
345
346 return $current_url;
347 }
348
349 /**
350 * Compares an url with current URL user is viewing
351 *
352 * @param string $url
353 *
354 * @return bool
355 */
356 function learn_press_is_current_url( $url ) {
357 $current_url = learn_press_get_current_url();
358
359 return ( $current_url && $url ) && strcmp( $current_url, learn_press_sanitize_url( $url ) ) == 0;
360 }
361
362 /**
363 * Remove unneeded characters in an URL
364 *
365 * @param string $url
366 * @param bool $trailingslashit
367 *
368 * @return string
369 */
370 function learn_press_sanitize_url( $url, $trailingslashit = true ) {
371 if ( $url ) {
372 preg_match( '!(https?://)?(.*)!', $url, $matches );
373 $url_without_http = $matches[2];
374 $url_without_http = preg_replace( '![/]+!', '/', $url_without_http );
375 $url = $matches[1] . $url_without_http;
376
377 return ( $trailingslashit &&
378 strpos( $url, '?' ) === false ) ? trailingslashit( $url ) : untrailingslashit( $url );
379 }
380
381 return $url;
382 }
383
384 /**
385 * Get all types of question supported
386 *
387 * @return mixed
388 */
389 function learn_press_question_types() {
390 return LP_Question::get_types();
391 }
392
393 /**
394 * Get human name of question's type by slug
395 *
396 * @param string $slug
397 *
398 * @return array
399 */
400 function learn_press_question_name_from_slug( $slug ) {
401 $types = learn_press_question_types();
402 $name = ! empty( $types[ $slug ] ) ? $types[ $slug ] : '';
403
404 return apply_filters( 'learn-press/question/slug-to-name', $name, $slug );
405 }
406
407 /**
408 * Get the post types which supported to insert into course's section
409 *
410 * @return array
411 */
412 function learn_press_section_item_types() {
413 $types = array(
414 'lp_lesson' => esc_html__( 'Lesson', 'learnpress' ),
415 'lp_quiz' => esc_html__( 'Quiz', 'learnpress' ),
416 );
417
418 return apply_filters( 'learn-press/section/support-item-type', $types );
419 }
420
421 /**
422 * Enqueue js code to print out
423 *
424 * @param string $code
425 * @param bool $script_tag - wrap code between <script> tag
426 * @depecated 4.1.6.8
427 */
428 function learn_press_enqueue_script( $code, $script_tag = false ) {
429 _deprecated_function( __FUNCTION__, '4.1.6.8' );
430 global $learn_press_queued_js, $learn_press_queued_js_tag;
431
432 if ( $script_tag ) {
433 if ( empty( $learn_press_queued_js_tag ) ) {
434 $learn_press_queued_js_tag = '';
435 }
436 $learn_press_queued_js_tag .= "\n" . $code . "\n";
437 } else {
438 if ( empty( $learn_press_queued_js ) ) {
439 $learn_press_queued_js = '';
440 }
441
442 $learn_press_queued_js .= "\n" . $code . "\n";
443 }
444 }
445
446 /**
447 * Get terms of a course by taxonomy.
448 * E.g: course_tag, course_category
449 *
450 * @param int $course_id
451 * @param string $taxonomy
452 * @param array $args
453 *
454 * @return array|mixed
455 */
456 function learn_press_get_course_terms( $course_id, $taxonomy, $args = array() ) {
457 if ( ! taxonomy_exists( $taxonomy ) ) {
458 return array();
459 }
460
461 // Support ordering by parent
462 if ( ! empty( $args['orderby'] ) && in_array( $args['orderby'], array( 'name_num', 'parent' ) ) ) {
463 $fields = isset( $args['fields'] ) ? $args['fields'] : 'all';
464 $orderby = $args['orderby'];
465
466 // Unset for wp_get_post_terms
467 unset( $args['orderby'] );
468 unset( $args['fields'] );
469
470 $terms = wp_get_post_terms( $course_id, $taxonomy, $args );
471
472 switch ( $orderby ) {
473 case 'name_num':
474 usort( $terms, '_learn_press_get_course_terms_name_num_usort_callback' );
475 break;
476 case 'parent':
477 usort( $terms, '_learn_press_get_course_terms_parent_usort_callback' );
478 break;
479 }
480
481 switch ( $fields ) {
482 case 'names':
483 $terms = wp_list_pluck( $terms, 'name' );
484 break;
485 case 'ids':
486 $terms = wp_list_pluck( $terms, 'term_id' );
487 break;
488 case 'slugs':
489 $terms = wp_list_pluck( $terms, 'slug' );
490 break;
491 }
492 } elseif ( ! empty( $args['orderby'] ) && $args['orderby'] === 'menu_order' ) {
493 // wp_get_post_terms doesn't let us use custom sort order
494 $args['include'] = wp_get_post_terms( $course_id, $taxonomy, array( 'fields' => 'ids' ) );
495
496 if ( empty( $args['include'] ) ) {
497 $terms = array();
498 } else {
499 // This isn't needed for get_terms
500 unset( $args['orderby'] );
501
502 // Set args for get_terms
503 $args['menu_order'] = isset( $args['order'] ) ? $args['order'] : 'ASC';
504 $args['hide_empty'] = isset( $args['hide_empty'] ) ? $args['hide_empty'] : 0;
505 $args['fields'] = isset( $args['fields'] ) ? $args['fields'] : 'names';
506
507 // Ensure slugs is valid for get_terms - slugs isn't supported
508 $args['fields'] = $args['fields'] === 'slugs' ? 'id=>slug' : $args['fields'];
509 $terms = get_terms( $taxonomy, $args );
510 }
511 } else {
512 $terms = wp_get_post_terms( $course_id, $taxonomy, $args );
513 }
514
515 // @deprecated
516 $terms = apply_filters( 'learn_press_get_course_terms', $terms, $course_id, $taxonomy, $args );
517
518 return apply_filters( 'learn-press/course/terms', $terms, $course_id, $taxonomy, $args );
519 }
520
521 /**
522 * Callback function for sorting terms of course by name.
523 *
524 * @param object $a
525 * @param object $b
526 *
527 * @return int
528 */
529 function _learn_press_get_course_terms_name_num_usort_callback( $a, $b ) {
530 if ( $a->name + 0 === $b->name + 0 ) {
531 return 0;
532 }
533
534 return ( $a->name + 0 < $b->name + 0 ) ? - 1 : 1;
535 }
536
537 /**
538 * Callback function for sorting terms of course by parent.
539 *
540 * @param object $a
541 * @param object $b
542 *
543 * @return int
544 */
545 function _learn_press_get_course_terms_parent_usort_callback( $a, $b ) {
546 if ( $a->parent === $b->parent ) {
547 return 0;
548 }
549
550 return ( $a->parent < $b->parent ) ? 1 : - 1;
551 }
552
553 /**
554 * Get posts by it's post-name (slug).
555 *
556 * @param string $name
557 * @param string $type
558 * @param bool $single
559 *
560 * @return array|bool|null|WP_Post
561 */
562 function learn_press_get_post_by_name( $name, $type, $single = true ) {
563 $post_name = sanitize_title( $name );
564 $id = LP_Object_Cache::get( $type . '-' . $post_name, 'learn-press/post-names' );
565
566 if ( false === $id ) {
567 foreach ( array( $name, urldecode( $name ) ) as $_name ) {
568 $args = array(
569 'name' => $_name,
570 'post_type' => array( $type ),
571 );
572
573 $posts = get_posts( $args );
574
575 if ( $posts ) {
576 $post = $posts[0];
577 $id = $post->ID;
578 wp_cache_set( $id, $post, 'posts' );
579 LP_Object_Cache::set( $type . '-' . $name, $id, 'learn-press/post-names' );
580 break;
581 }
582 }
583 }
584
585 return $id ? get_post( $id ) : false;
586 }
587
588 /**
589 * Cache static pages
590 *
591 * @deprecated 4.1.6.8
592 */
593 /*function learn_press_setup_pages() {
594 global $wpdb;
595
596 $page_ids = LP_Object_Cache::get( 'static-page-ids', 'learn-press' );
597
598 if ( false === $page_ids ) {
599 $pages = learn_press_static_pages( true );
600 $page_ids = array();
601
602 foreach ( $pages as $page ) {
603 $id = get_option( 'learn_press_' . $page . '_page_id' );
604
605 if ( absint( $id ) > 0 ) {
606 $page_ids[] = $id;
607 }
608 }
609
610 if ( ! $page_ids ) {
611 return;
612 }
613
614 $query = $wpdb->prepare(
615 "
616 SELECT ID, post_title, post_name, post_date, post_date_gmt, post_modified, post_modified_gmt, post_content, post_parent, post_type
617 FROM {$wpdb->posts}
618 WHERE %d AND ID IN(" . join( ',', $page_ids ) . ')
619 AND post_status <> %s
620 ',
621 1,
622 'trash'
623 );
624
625 if ( ! $rows = $wpdb->get_results( $query ) ) {
626 return;
627 }
628
629 foreach ( $rows as $page ) {
630 $page = sanitize_post( $page, 'raw' );
631 wp_cache_add( $page->ID, $page, 'posts' );
632 }
633 }
634 }*/
635
636 function learn_press_get_course_item_object( $post_type ) {
637 switch ( $post_type ) {
638 case 'lp_quiz':
639 $class = 'LP_Quiz';
640 break;
641 case 'lp_lesson':
642 $class = 'LP_Lesson';
643 break;
644 case 'lp_question':
645 $class = 'LP_Question';
646 }
647 }
648
649 /**
650 * Print out js code in the queue
651 *
652 * @depecated 4.1.6.8
653 */
654 function learn_press_print_script() {
655 _deprecated_function( __FUNCTION__, '4.1.6.8' );
656 global $learn_press_queued_js, $learn_press_queued_js_tag;
657
658 if ( ! empty( $learn_press_queued_js ) ) {
659 ?>
660 <!-- LearnPress JavaScript -->
661 <script type="text/javascript">
662 jQuery(function ($) {
663 <?php
664 $learn_press_queued_js = wp_check_invalid_utf8( $learn_press_queued_js );
665 $learn_press_queued_js = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", $learn_press_queued_js );
666 $learn_press_queued_js = str_replace( "\r", '', $learn_press_queued_js );
667
668 // echo $learn_press_queued_js;
669 ?>
670 })
671 </script>
672
673 <?php
674 unset( $learn_press_queued_js );
675 }
676
677 if ( ! empty( $learn_press_queued_js_tag ) ) {
678 // echo $learn_press_queued_js_tag;
679 }
680 }
681
682 // add_action( 'wp_footer', 'learn_press_print_script' );
683 // add_action( 'admin_footer', 'learn_press_print_script' );
684
685
686 /**
687 * @param string $str
688 * @param int $lines
689 * @depecated 4.1.6.8
690 */
691 /*function learn_press_email_new_line( $lines = 1, $str = "\r\n" ) {
692 echo str_repeat( $str, $lines );
693 }*/
694
695 if ( ! function_exists( 'learn_press_is_ajax' ) ) {
696 function learn_press_is_ajax() {
697 return defined( 'LP_DOING_AJAX' ) && LP_DOING_AJAX && 'yes' != learn_press_get_request( 'noajax' );
698 }
699 }
700
701 /**
702 * Get page id from admin settings page
703 *
704 * @param string $name
705 *
706 * @return int
707 */
708 function learn_press_get_page_id( string $name ): int {
709 $page_id = LP_Settings::instance()->get( "{$name}_page_id", false );
710
711 if ( function_exists( 'icl_object_id' ) ) {
712 $page_id = icl_object_id( $page_id, 'page', false, defined( 'ICL_LANGUAGE_CODE' ) ? ICL_LANGUAGE_CODE : '' );
713 }
714
715 $page_id = (int) $page_id;
716
717 return apply_filters( 'learn_press_get_page_id', $page_id, $name );
718 }
719
720 /**
721 * display the seconds in time format h:i:s
722 *
723 * @param $seconds
724 * @param string $separator
725 *
726 * @return string
727 */
728 function learn_press_seconds_to_time( $seconds, $separator = ':' ) {
729 return sprintf(
730 '%02d%s%02d%s%02d',
731 floor( $seconds / 3600 ),
732 $separator,
733 ( $seconds / 60 ) % 60,
734 $separator,
735 $seconds % 60
736 );
737 }
738
739 /* nav */
740 if ( ! function_exists( 'learn_press_course_paging_nav' ) ) {
741
742 /**
743 * Display navigation to next/previous set of posts when applicable.
744 *
745 * @param array
746 */
747 function learn_press_course_paging_nav( $args = array() ) {
748 learn_press_paging_nav(
749 array(
750 'num_pages' => $GLOBALS['wp_query']->max_num_pages,
751 'wrapper_class' => 'navigation pagination',
752 )
753 );
754 }
755 }
756
757 /* nav */
758 if ( ! function_exists( 'learn_press_paging_nav' ) ) {
759 function learn_press_paging_nav( $args = array() ) {
760 $args = wp_parse_args(
761 $args,
762 array(
763 'num_pages' => 0,
764 'paged' => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1,
765 'wrapper_class' => 'learn-press-pagination',
766 'base' => false,
767 'format' => '',
768 'echo' => true,
769 )
770 );
771
772 if ( $args['num_pages'] < 2 ) {
773 return false;
774 }
775
776 $paged = $args['paged'];
777 $pagenum_link = html_entity_decode( $args['base'] === false ? get_pagenum_link() : $args['base'] );
778
779 $query_args = array();
780 $url_parts = explode( '?', $pagenum_link );
781
782 if ( isset( $url_parts[1] ) ) {
783 wp_parse_str( $url_parts[1], $query_args );
784 }
785
786 $pagenum_link = esc_url_raw( remove_query_arg( array_keys( $query_args ), $pagenum_link ) );
787 $pagenum_link = trailingslashit( $pagenum_link ) . '%_%';
788
789 $format = $GLOBALS['wp_rewrite']->using_index_permalinks() && ! strpos(
790 $pagenum_link,
791 'index.php'
792 ) ? 'index.php/' : '';
793 $format .= $args['format'] ? $args['format'] : ( $GLOBALS['wp_rewrite']->using_permalinks() ? user_trailingslashit(
794 'page/%#%',
795 'paged'
796 ) : '?paged=%#%' );
797
798 $link_args = array(
799 'base' => $pagenum_link,
800 'format' => $format,
801 'total' => $args['num_pages'],
802 'current' => max( 1, $paged ),
803 'mid_size' => 1,
804 'add_args' => array_map( 'urlencode', $query_args ),
805 'prev_text' => __( '<', 'learnpress' ),
806 'next_text' => __( '>', 'learnpress' ),
807 'type' => 'list',
808 );
809
810 // Set up paginated links.
811 $links = paginate_links( $link_args );
812
813 ob_start();
814
815 if ( $links ) {
816 ?>
817 <div class="<?php echo esc_attr( $args['wrapper_class'] ); ?>">
818 <?php echo wp_kses_post( $links ); ?>
819 </div>
820 <?php
821 }
822
823 $output = ob_get_clean();
824
825 if ( $args['echo'] ) {
826 echo wp_kses_post( $output );
827 }
828
829 return $output;
830 }
831 }
832
833 /**
834 * Get number of pages by rows and items per page.
835 *
836 * @param int $total
837 * @param int $limit
838 *
839 * @return int
840 */
841 function learn_press_get_num_pages( $total, $limit = 10 ) {
842 $limit = $limit <= 0 ? 10 : $limit;
843
844 if ( $total <= $limit ) {
845 return 1;
846 }
847
848 $pages = absint( $total / $limit );
849
850 if ( $total % $limit != 0 ) {
851 $pages ++;
852 }
853
854 return $pages;
855 }
856
857 /**
858 * Get text
859 *
860 * @param $status_id
861 *
862 * @return mixed
863 */
864 function learn_press_get_status_text( $status_id ) {
865 switch ( $status_id ) {
866 case 1:
867 $text = 'pending';
868 break;
869 case 2:
870 $text = 'complete';
871 break;
872 case - 1:
873 $text = 'cancel';
874 break;
875 case - 2:
876 $text = 'refund';
877 break;
878 default:
879 $text = 'on-hold';
880 }
881
882 return $text;
883 }
884
885 function learn_press_get_course_duration_support() {
886 return apply_filters(
887 'learn_press_course_duration_support',
888 array(
889 'minute' => esc_html__( 'Minute(s)', 'learnpress' ),
890 'hour' => esc_html__( 'Hour(s)', 'learnpress' ),
891 'day' => esc_html__( 'Day(s)', 'learnpress' ),
892 'week' => esc_html__( 'Week(s)', 'learnpress' ),
893 )
894 );
895 }
896
897 function learn_press_number_to_string_time( $number ) {
898 $str = $number;
899
900 if ( preg_match( '!([0-9.]+) (minute|hour|day|week)!', $number, $matches ) ) {
901 switch ( $matches[2] ) {
902 case 'hour':
903 $minute = $matches[1] * 60;
904 $str = sprintf( '%s hour %s minute', absint( $minute / 60 ), $minute % 60 );
905 break;
906 case 'day':
907 $hour = $matches[1] * 24;
908 $str = sprintf( '%s day %s hour', absint( $hour / 24 ), $hour % 24 );
909 break;
910 case 'week':
911 $day = $matches[1] * 7;
912 $str = sprintf( '%s week %s day', absint( $day / 7 ), $day % 7 );
913 break;
914 }
915 }
916
917 return $str;
918 }
919
920 function learn_press_human_time_to_seconds( $time, $default = '' ) {
921 $duration = learn_press_get_course_duration_support();
922 $duration_keys = array_keys( $duration );
923
924 if ( preg_match_all( '!([0-9]+)\s*(' . join( '|', $duration_keys ) . ')?!', $time, $matches ) ) {
925 $a1 = $matches[1][0];
926 $a2 = in_array( $matches[2][0], $duration_keys ) ? $matches[2][0] : '';
927 } else {
928 $a1 = absint( $time );
929 $a2 = '';
930 }
931
932 if ( $a2 ) {
933 $b = array(
934 'minute' => 60,
935 'hour' => 3600,
936 'day' => 3600 * 24,
937 'week' => 3600 * 24 * 7,
938 );
939 $a1 = $a1 * $b[ $a2 ];
940 }
941
942 return $a1;
943 }
944
945 /**
946 * Send email notification.
947 *
948 * @param string $to .
949 * @param string $action .
950 * @param array $vars .
951 *
952 * @return bool
953 */
954 function learn_press_send_mail( $to = '', $action = '', $vars = array() ) {
955 $email_settings = LP_Settings::instance();
956
957 if ( ! $email_settings->get( $action . '.enable' ) ) {
958 return "The action {$action} doesnt support";
959 }
960
961 $user = get_user_by( 'email', $to );
962
963 $vars['log_in'] = apply_filters( 'learn_press_site_url', get_home_url() );
964
965 // Send email.
966 $email = new LP_Email();
967 $email->set_action( $action );
968 $email->parse_email( $vars );
969 $email->add_recipient( $to );
970
971 return $email->send();
972 }
973
974 /*
975 * Send email notification when a course be published
976 */
977 function learn_press_publish_course( $new_status, $old_status, $post ) {
978 if ( $old_status == 'pending' && $new_status == 'publish' && $post->post_type == 'lp_course' ) {
979 $instructor = get_userdata( $post->post_author );
980 $mail_to = $instructor->user_email;
981
982 learn_press_send_mail(
983 $mail_to,
984 'published_course',
985 apply_filters(
986 'learn_press_vars_enrolled_course',
987 array(
988 'user_name' => $instructor->display_name,
989 'course_name' => $post->post_title,
990 'course_link' => get_permalink( $post->ID ),
991 ),
992 $post,
993 $instructor
994 )
995 );
996 }
997 }
998
999 add_action( 'transition_post_status', 'learn_press_publish_course', 10, 3 );
1000
1001 /**
1002 * @param $user_id
1003 *
1004 * @return WP_Query
1005 * @depecated 4.1.6.4
1006 */
1007 function learn_press_get_enrolled_courses( $user_id ) {
1008 return LP()->get_user( $user_id )->get( 'enrolled-courses' );
1009 }
1010
1011 /**
1012 * @param $user_id
1013 *
1014 * @return WP_Query
1015 */
1016 function learn_press_get_own_courses( $user_id ) {
1017 $arr_query = array(
1018 'post_type' => 'lp_course',
1019 'author' => $user_id,
1020 'post_status' => 'publish',
1021 'ignore_sticky_posts' => true,
1022 'posts_per_page' => - 1,
1023 );
1024 $my_query = new WP_Query( $arr_query );
1025
1026 return $my_query;
1027 }
1028
1029 /**
1030 * Return array list of currency positions.
1031 *
1032 * @param bool|string $currency
1033 *
1034 * @return array
1035 */
1036 function learn_press_currency_positions( $currency = false ) {
1037 $positions = array(
1038 'left' => __( 'Left', 'learnpress' ),
1039 'right' => __( 'Right', 'learnpress' ),
1040 'left_with_space' => __( 'Left with space', 'learnpress' ),
1041 'right_with_space' => __( 'Right with space', 'learnpress' ),
1042 );
1043
1044 if ( false === $currency ) {
1045 $currency = learn_press_get_currency_symbol();
1046 }
1047
1048 $settings = LP_Settings::instance();
1049
1050 $thousands_separator = '';
1051 $decimals_separator = $settings->get( 'decimals_separator', '.' );
1052 $number_of_decimals = $settings->get( 'number_of_decimals', 2 );
1053
1054 if ( $number_of_decimals > 0 ) {
1055 $example = '69' . $decimals_separator . str_repeat( '9', $number_of_decimals );
1056 } else {
1057 $example = '69';
1058 }
1059
1060 foreach ( $positions as $pos => $text ) {
1061 switch ( $pos ) {
1062 case 'left':
1063 $text = sprintf( '%s ( %s%s )', $text, $currency, $example );
1064 break;
1065 case 'right':
1066 $text = sprintf( '%s ( %s%s )', $text, $example, $currency );
1067 break;
1068 case 'left_with_space':
1069 $text = sprintf( '%s ( %s %s )', $text, $currency, $example );
1070 break;
1071 case 'right_with_space':
1072 $text = sprintf( '%s ( %s %s )', $text, $example, $currency );
1073 break;
1074 }
1075 $positions[ $pos ] = $text;
1076 }
1077
1078 $positions = apply_filters( 'learn_press_currency_positions', $positions );
1079
1080 return apply_filters( 'learn-press/currency-positions', $positions );
1081 }
1082
1083 /**
1084 * @return array
1085 */
1086 function learn_press_get_payment_currencies() {
1087 return apply_filters( 'learn_press_get_payment_currencies', learn_press_currencies() );
1088 }
1089
1090 /**
1091 * Get the list of currencies with code and name.
1092 *
1093 * @return array
1094 * @version 3.0.0
1095 *
1096 * @author ThimPress
1097 */
1098 function learn_press_currencies() {
1099 $currencies = array(
1100 'AFN' => __( 'Afghan afghani', 'learnpress' ),
1101 'ALL' => __( 'Albanian lek', 'learnpress' ),
1102 'DZD' => __( 'Algerian dinar', 'learnpress' ),
1103 'EUR' => __( 'Euro', 'learnpress' ),
1104 'AOA' => __( 'Angolan kwanza', 'learnpress' ),
1105 'XCD' => __( 'East Caribbean dollar', 'learnpress' ),
1106 'ARS' => __( 'Argentine peso', 'learnpress' ),
1107 'AMD' => __( 'Armenian dram', 'learnpress' ),
1108 'AWG' => __( 'Aruban florin', 'learnpress' ),
1109 'AUD' => __( 'Australian dollar', 'learnpress' ),
1110 'AZN' => __( 'Azerbaijani manat', 'learnpress' ),
1111 'BSD' => __( 'Bahamian dollar', 'learnpress' ),
1112 'BHD' => __( 'Bahraini dinar', 'learnpress' ),
1113 'BDT' => __( 'Bangladeshi taka', 'learnpress' ),
1114 'BBD' => __( 'Barbadian dollar', 'learnpress' ),
1115 'BYR' => __( 'Belarusian ruble', 'learnpress' ),
1116 'BZD' => __( 'Belizean dollar', 'learnpress' ),
1117 'XOF' => __( 'West African CFA franc', 'learnpress' ),
1118 'BMD' => __( 'Bermudian dollar', 'learnpress' ),
1119 'BTN' => __( 'Bhutanese ngultrum', 'learnpress' ),
1120 'BOB' => __( 'Bolivian boliviano', 'learnpress' ),
1121 'USD' => __( 'US dollar', 'learnpress' ),
1122 'BAM' => __( 'Bosnia and Herzegovina convertible mark', 'learnpress' ),
1123 'BWP' => __( 'Botswana pula', 'learnpress' ),
1124 'BRL' => __( 'Brazilian real', 'learnpress' ),
1125 'BND' => __( 'Brunei dollar', 'learnpress' ),
1126 'BGN' => __( 'Bulgarian lev', 'learnpress' ),
1127 'MMK' => __( 'Burmese kyat', 'learnpress' ),
1128 'BIF' => __( 'Burundian franc', 'learnpress' ),
1129 'KHR' => __( 'Cambodian riel', 'learnpress' ),
1130 'XAF' => __( 'Central African CFA franc', 'learnpress' ),
1131 'CAD' => __( 'Canadian dollar', 'learnpress' ),
1132 'CVE' => __( 'Cape Verdean escudo', 'learnpress' ),
1133 'KYD' => __( 'Cayman Islands dollar', 'learnpress' ),
1134 'CLP' => __( 'Chilean peso', 'learnpress' ),
1135 'CNY' => __( 'Chinese renminbi', 'learnpress' ),
1136 'COP' => __( 'Colombian peso', 'learnpress' ),
1137 'KMF' => __( 'Comorian franc', 'learnpress' ),
1138 'CDF' => __( 'Congolese franc', 'learnpress' ),
1139 'NZD' => __( 'New Zealand dollar', 'learnpress' ),
1140 'CRC' => __( 'Costa Rican colón', 'learnpress' ),
1141 'HRK' => __( 'Croatian kuna', 'learnpress' ),
1142 'CUC' => __( 'Cuban peso', 'learnpress' ),
1143 'ANG' => __( 'Netherlands Antilles guilder', 'learnpress' ),
1144 'CZK' => __( 'Czech koruna', 'learnpress' ),
1145 'DKK' => __( 'Danish krone', 'learnpress' ),
1146 'DJF' => __( 'Djiboutian franc', 'learnpress' ),
1147 'DOP' => __( 'Dominican peso', 'learnpress' ),
1148 'EGP' => __( 'Egyptian pound', 'learnpress' ),
1149 'SVC' => __( 'Salvadoran colón', 'learnpress' ),
1150 'ERN' => __( 'Eritrean nakfa', 'learnpress' ),
1151 'ETB' => __( 'Ethiopian birr', 'learnpress' ),
1152 'FKP' => __( 'Falkland Islands pound', 'learnpress' ),
1153 'FJD' => __( 'Fijian dollar', 'learnpress' ),
1154 'XPF' => __( 'CFP franc', 'learnpress' ),
1155 'GMD' => __( 'Gambian dalasi', 'learnpress' ),
1156 'GEL' => __( 'Georgian lari', 'learnpress' ),
1157 'GHS' => __( 'Ghanian cedi', 'learnpress' ),
1158 'GIP' => __( 'Gibraltar pound', 'learnpress' ),
1159 'GTQ' => __( 'Guatemalan quetzal', 'learnpress' ),
1160 'GBP' => __( 'British pound', 'learnpress' ),
1161 'GNF' => __( 'Guinean franc', 'learnpress' ),
1162 'GYD' => __( 'Guyanese dollar', 'learnpress' ),
1163 'HTG' => __( 'Haitian gourde', 'learnpress' ),
1164 'HNL' => __( 'Honduran lempira', 'learnpress' ),
1165 'HKD' => __( 'Hong Kong dollar', 'learnpress' ),
1166 'HUF' => __( 'Hungarian forint', 'learnpress' ),
1167 'ISK' => __( 'Icelandic króna', 'learnpress' ),
1168 'INR' => __( 'Indian rupee', 'learnpress' ),
1169 'IDR' => __( 'Indonesian rupiah', 'learnpress' ),
1170 'IRR' => __( 'Iranian rial', 'learnpress' ),
1171 'IQD' => __( 'Iraqi dinar', 'learnpress' ),
1172 'ILS' => __( 'Israeli new sheqel', 'learnpress' ),
1173 'JMD' => __( 'Jamaican dollar', 'learnpress' ),
1174 'JPY' => __( 'Japanese yen ', 'learnpress' ),
1175 'JOD' => __( 'Jordanian dinar', 'learnpress' ),
1176 'KZT' => __( 'Kazakhstani tenge', 'learnpress' ),
1177 'KES' => __( 'Kenyan shilling', 'learnpress' ),
1178 'KPW' => __( 'North Korean won', 'learnpress' ),
1179 'KWD' => __( 'Kuwaiti dinar', 'learnpress' ),
1180 'KGS' => __( 'Kyrgyzstani som', 'learnpress' ),
1181 'KRW' => __( 'South Korean won', 'learnpress' ),
1182 'LAK' => __( 'Lao kip', 'learnpress' ),
1183 'LVL' => __( 'Latvian lats', 'learnpress' ),
1184 'LBP' => __( 'Lebanese pound', 'learnpress' ),
1185 'LSL' => __( 'Lesotho loti', 'learnpress' ),
1186 'LRD' => __( 'Liberian dollar', 'learnpress' ),
1187 'LD' => __( 'Libyan dinar', 'learnpress' ),
1188 'CHF' => __( 'Swiss franc', 'learnpress' ),
1189 'LTL' => __( 'Lithuanian litas', 'learnpress' ),
1190 'MOP' => __( 'Macanese pataca', 'learnpress' ),
1191 'MKD' => __( 'Macedonian denar', 'learnpress' ),
1192 'MGA' => __( 'Malagasy ariary', 'learnpress' ),
1193 'MWK' => __( 'Malawian kwacha', 'learnpress' ),
1194 'MYR' => __( 'Malaysian ringgit', 'learnpress' ),
1195 'MVR' => __( 'Maldivian rufiyaa', 'learnpress' ),
1196 'MRO' => __( 'Mauritanian ouguiya', 'learnpress' ),
1197 'MUR' => __( 'Mauritian rupee', 'learnpress' ),
1198 'MXN' => __( 'Mexican peso', 'learnpress' ),
1199 'MDL' => __( 'Moldovan leu', 'learnpress' ),
1200 'MNT' => __( 'Mongolian tugrik', 'learnpress' ),
1201 'MAD' => __( 'Moroccan dirham', 'learnpress' ),
1202 'MZN' => __( 'Mozambican metical', 'learnpress' ),
1203 'NAD' => __( 'Namibian dollar', 'learnpress' ),
1204 'NPR' => __( 'Nepalese rupee', 'learnpress' ),
1205 'NIO' => __( 'Nicaraguan córdoba', 'learnpress' ),
1206 'NGN' => __( 'Nigerian naira', 'learnpress' ),
1207 'NOK' => __( 'Norwegian krone', 'learnpress' ),
1208 'OMR' => __( 'Omani rial', 'learnpress' ),
1209 'PKR' => __( 'Pakistani rupee', 'learnpress' ),
1210 'PAB' => __( 'Panamanian balboa', 'learnpress' ),
1211 'PGK' => __( 'Papua New Guinea kina', 'learnpress' ),
1212 'PYG' => __( 'Paraguayan guarani', 'learnpress' ),
1213 'PEN' => __( 'Peruvian nuevo sol', 'learnpress' ),
1214 'PHP' => __( 'Philippine peso', 'learnpress' ),
1215 'PLN' => __( 'Polish zloty', 'learnpress' ),
1216 'QAR' => __( 'Qatari riyal', 'learnpress' ),
1217 'RON' => __( 'Romanian leu', 'learnpress' ),
1218 'RUB' => __( 'Russian ruble', 'learnpress' ),
1219 'RWF' => __( 'Rwandan franc', 'learnpress' ),
1220 'WST' => __( 'Samoan tālā', 'learnpress' ),
1221 'STD' => __( 'São Tomé and Príncipe dobra', 'learnpress' ),
1222 'SAR' => __( 'Saudi riyal', 'learnpress' ),
1223 'RSD' => __( 'Serbian dinar', 'learnpress' ),
1224 'SCR' => __( 'Seychellois rupee', 'learnpress' ),
1225 'SLL' => __( 'Sierra Leonean leone', 'learnpress' ),
1226 'SGD' => __( 'Singapore dollar', 'learnpress' ),
1227 'SBD' => __( 'Solomon Islands dollar', 'learnpress' ),
1228 'SOS' => __( 'Somali shilling', 'learnpress' ),
1229 'ZAR' => __( 'South African rand', 'learnpress' ),
1230 'LKR' => __( 'Sri Lankan rupee', 'learnpress' ),
1231 'SHP' => __( 'St. Helena pound', 'learnpress' ),
1232 'SDG' => __( 'Sudanese pound', 'learnpress' ),
1233 'SRD' => __( 'Surinamese dollar', 'learnpress' ),
1234 'SZL' => __( 'Swazi lilangeni', 'learnpress' ),
1235 'SEK' => __( 'Swedish krona', 'learnpress' ),
1236 'SYP' => __( 'Syrian pound', 'learnpress' ),
1237 'TWD' => __( 'New Taiwan dollar', 'learnpress' ),
1238 'TJS' => __( 'Tajikistani somoni', 'learnpress' ),
1239 'TZS' => __( 'Tanzanian shilling', 'learnpress' ),
1240 'THB' => __( 'Thai baht ', 'learnpress' ),
1241 'TOP' => __( 'Tongan pa’anga', 'learnpress' ),
1242 'TTD' => __( 'Trinidad and Tobago dollar', 'learnpress' ),
1243 'TND' => __( 'Tunisian dinar', 'learnpress' ),
1244 'TRY' => __( 'Turkish lira', 'learnpress' ),
1245 'TMT' => __( 'Turkmenistani manat', 'learnpress' ),
1246 'UGX' => __( 'Ugandan shilling', 'learnpress' ),
1247 'UAH' => __( 'Ukrainian hryvnia', 'learnpress' ),
1248 'AED' => __( 'United Arab Emirates dirham', 'learnpress' ),
1249 'UYU' => __( 'Uruguayan peso', 'learnpress' ),
1250 'UZS' => __( 'Uzbekistani som', 'learnpress' ),
1251 'VUV' => __( 'Vanuatu vatu', 'learnpress' ),
1252 'VEF' => __( 'Venezuelan bolivar', 'learnpress' ),
1253 'VND' => __( 'Vietnamese dong', 'learnpress' ),
1254 'YER' => __( 'Yemeni rial', 'learnpress' ),
1255 'ZMK' => __( 'Zambian kwacha', 'learnpress' ),
1256 'ZWL' => __( 'Zimbabwean dollar', 'learnpress' ),
1257 'JEP' => __( 'Jersey pound', 'learnpress' ),
1258 'LYD' => __( 'Libyan dinar', 'learnpress' ),
1259 );
1260
1261 asort( $currencies );
1262
1263 return apply_filters( 'learn-press/currencies', $currencies );
1264 }
1265
1266 /**
1267 * Get current setting of currency.
1268 *
1269 * @return string
1270 */
1271 function learn_press_get_currency() {
1272 $currency = apply_filters( 'learn_press_currency', LP_Settings::instance()->get( 'currency', 'USD' ) );
1273
1274 return apply_filters( 'learn-press/currency', $currency );
1275 }
1276
1277 /**
1278 * Return list of common symbols of the currencies on the world.
1279 *
1280 * @return array
1281 */
1282 function learn_press_currency_symbols() {
1283 $symbols = array(
1284 'AED' => '&#x62f;.&#x625;',
1285 'AFN' => '&#x60b;',
1286 'ALL' => 'L',
1287 'AMD' => 'AMD',
1288 'ANG' => '&fnof;',
1289 'AOA' => 'Kz',
1290 'ARS' => '&#36;',
1291 'AUD' => '&#36;',
1292 'AWG' => 'Afl.',
1293 'AZN' => 'AZN',
1294 'BAM' => 'KM',
1295 'BBD' => '&#36;',
1296 'BDT' => '&#2547;&nbsp;',
1297 'BGN' => '&#1083;&#1074;.',
1298 'BHD' => '.&#x62f;.&#x628;',
1299 'BIF' => 'Fr',
1300 'BMD' => '&#36;',
1301 'BND' => '&#36;',
1302 'BOB' => 'Bs.',
1303 'BRL' => '&#82;&#36;',
1304 'BSD' => '&#36;',
1305 'BTC' => '&#3647;',
1306 'BTN' => 'Nu.',
1307 'BWP' => 'P',
1308 'BYR' => 'Br',
1309 'BYN' => 'Br',
1310 'BZD' => '&#36;',
1311 'CAD' => '&#36;',
1312 'CDF' => 'Fr',
1313 'CHF' => '&#67;&#72;&#70;',
1314 'CLP' => '&#36;',
1315 'CNY' => '&yen;',
1316 'COP' => '&#36;',
1317 'CRC' => '&#x20a1;',
1318 'CUC' => '&#36;',
1319 'CUP' => '&#36;',
1320 'CVE' => '&#36;',
1321 'CZK' => '&#75;&#269;',
1322 'DJF' => 'Fr',
1323 'DKK' => 'DKK',
1324 'DOP' => 'RD&#36;',
1325 'DZD' => '&#x62f;.&#x62c;',
1326 'EGP' => 'EGP',
1327 'ERN' => 'Nfk',
1328 'ETB' => 'Br',
1329 'EUR' => '&euro;',
1330 'FJD' => '&#36;',
1331 'FKP' => '&pound;',
1332 'GBP' => '&pound;',
1333 'GEL' => '&#x20be;',
1334 'GGP' => '&pound;',
1335 'GHS' => '&#x20b5;',
1336 'GIP' => '&pound;',
1337 'GMD' => 'D',
1338 'GNF' => 'Fr',
1339 'GTQ' => 'Q',
1340 'GYD' => '&#36;',
1341 'HKD' => '&#36;',
1342 'HNL' => 'L',
1343 'HRK' => 'kn',
1344 'HTG' => 'G',
1345 'HUF' => '&#70;&#116;',
1346 'IDR' => 'Rp',
1347 'ILS' => '&#8362;',
1348 'IMP' => '&pound;',
1349 'INR' => '&#8377;',
1350 'IQD' => '&#x639;.&#x62f;',
1351 'IRR' => '&#xfdfc;',
1352 'IRT' => '&#x062A;&#x0648;&#x0645;&#x0627;&#x0646;',
1353 'ISK' => 'kr.',
1354 'JEP' => '&pound;',
1355 'JMD' => '&#36;',
1356 'JOD' => '&#x62f;.&#x627;',
1357 'JPY' => '&yen;',
1358 'KES' => 'KSh',
1359 'KGS' => '&#x441;&#x43e;&#x43c;',
1360 'KHR' => '&#x17db;',
1361 'KMF' => 'Fr',
1362 'KPW' => '&#x20a9;',
1363 'KRW' => '&#8361;',
1364 'KWD' => '&#x62f;.&#x643;',
1365 'KYD' => '&#36;',
1366 'KZT' => '&#8376;',
1367 'LAK' => '&#8365;',
1368 'LBP' => '&#x644;.&#x644;',
1369 'LKR' => '&#xdbb;&#xdd4;',
1370 'LRD' => '&#36;',
1371 'LSL' => 'L',
1372 'LYD' => '&#x644;.&#x62f;',
1373 'MAD' => '&#x62f;.&#x645;.',
1374 'MDL' => 'MDL',
1375 'MGA' => 'Ar',
1376 'MKD' => '&#x434;&#x435;&#x43d;',
1377 'MMK' => 'Ks',
1378 'MNT' => '&#x20ae;',
1379 'MOP' => 'P',
1380 'MRU' => 'UM',
1381 'MUR' => '&#x20a8;',
1382 'MVR' => '.&#x783;',
1383 'MWK' => 'MK',
1384 'MXN' => '&#36;',
1385 'MYR' => '&#82;&#77;',
1386 'MZN' => 'MT',
1387 'NAD' => 'N&#36;',
1388 'NGN' => '&#8358;',
1389 'NIO' => 'C&#36;',
1390 'NOK' => '&#107;&#114;',
1391 'NPR' => '&#8360;',
1392 'NZD' => '&#36;',
1393 'OMR' => '&#x631;.&#x639;.',
1394 'PAB' => 'B/.',
1395 'PEN' => 'S/',
1396 'PGK' => 'K',
1397 'PHP' => '&#8369;',
1398 'PKR' => '&#8360;',
1399 'PLN' => '&#122;&#322;',
1400 'PRB' => '&#x440;.',
1401 'PYG' => '&#8370;',
1402 'QAR' => '&#x631;.&#x642;',
1403 'RMB' => '&yen;',
1404 'RON' => 'lei',
1405 'RSD' => '&#1088;&#1089;&#1076;',
1406 'RUB' => '&#8381;',
1407 'RWF' => 'Fr',
1408 'SAR' => '&#x631;.&#x633;',
1409 'SBD' => '&#36;',
1410 'SCR' => '&#x20a8;',
1411 'SDG' => '&#x62c;.&#x633;.',
1412 'SEK' => '&#107;&#114;',
1413 'SGD' => '&#36;',
1414 'SHP' => '&pound;',
1415 'SLL' => 'Le',
1416 'SOS' => 'Sh',
1417 'SRD' => '&#36;',
1418 'SSP' => '&pound;',
1419 'STN' => 'Db',
1420 'SYP' => '&#x644;.&#x633;',
1421 'SZL' => 'L',
1422 'THB' => '&#3647;',
1423 'TJS' => '&#x405;&#x41c;',
1424 'TMT' => 'm',
1425 'TND' => '&#x62f;.&#x62a;',
1426 'TOP' => 'T&#36;',
1427 'TRY' => '&#8378;',
1428 'TTD' => '&#36;',
1429 'TWD' => '&#78;&#84;&#36;',
1430 'TZS' => 'Sh',
1431 'UAH' => '&#8372;',
1432 'UGX' => 'UGX',
1433 'USD' => '&#36;',
1434 'UYU' => '&#36;',
1435 'UZS' => 'UZS',
1436 'VEF' => 'Bs F',
1437 'VES' => 'Bs.S',
1438 'VND' => '&#8363;',
1439 'VUV' => 'Vt',
1440 'WST' => 'T',
1441 'XAF' => 'CFA',
1442 'XCD' => '&#36;',
1443 'XOF' => 'CFA',
1444 'XPF' => 'Fr',
1445 'YER' => '&#xfdfc;',
1446 'ZAR' => '&#82;',
1447 'ZMW' => 'ZK',
1448 );
1449
1450 return apply_filters( 'learn-press/currency-symbols', $symbols );
1451 }
1452
1453 /**
1454 * Return currency symbol from the code.
1455 *
1456 * @param string $currency
1457 *
1458 * @return string
1459 */
1460 function learn_press_get_currency_symbol( $currency = '' ) {
1461 if ( ! $currency ) {
1462 $currency = learn_press_get_currency();
1463 }
1464 $symbols = learn_press_currency_symbols();
1465 $currency_symbol = isset( $symbols[ $currency ] ) ? $symbols[ $currency ] : '';
1466
1467 $currency_symbol = apply_filters( 'learn_press_currency_symbol', $currency_symbol, $currency );
1468
1469 return apply_filters( 'learn-press/currency-symbol', $currency_symbol, $currency );
1470 }
1471
1472 /**
1473 * Get static page for LP page by name.
1474 *
1475 * @param string $key
1476 *
1477 * @return string
1478 * @editor tungnx
1479 * @modify 4.1.4
1480 */
1481 function learn_press_get_page_link( string $key ): string {
1482 $page_id = learn_press_get_page_id( $key );
1483 $link = '';
1484
1485 if ( $page_id && get_post_status( $page_id ) == 'publish' ) {
1486 $permalink = get_permalink( $page_id );
1487 $link = apply_filters( 'learn-press/get-page-link', trailingslashit( $permalink ), $page_id, $key );
1488 }
1489
1490 return $link;
1491 }
1492
1493 /**
1494 * Get static page for LP page by name.
1495 *
1496 * @param string $key
1497 *
1498 * @return string
1499 */
1500 function learn_press_get_page_title( $key ) {
1501 $page_id = LP_Settings::instance()->get( $key . '_page_id' );
1502 $title = '';
1503
1504 if ( $page_id && get_post_status( $page_id ) == 'publish' ) {
1505 $title = apply_filters( 'learn-press/get-page-title', get_the_title( $page_id ), $page_id, $key );
1506 }
1507
1508 return apply_filters( 'learn-press/get-page-' . $key . '-title', $title, $page_id );
1509 }
1510
1511 /**
1512 * get the ID of a course by order ID
1513 *
1514 * @param $order_id
1515 *
1516 * @return bool|mixed
1517 */
1518 function learn_press_get_course_by_order( $order_id ) {
1519 $order_items = get_post_meta( $order_id, '_learn_press_order_items', true );
1520
1521 if ( $order_items && $order_items->products ) {
1522 $array_keys = array_keys( $order_items->products );
1523
1524 return reset( $array_keys );
1525 }
1526
1527 return false;
1528 }
1529
1530 /**
1531 * Convert a number of seconds to weeks/days/hours.
1532 *
1533 * @param int $secs
1534 *
1535 * @return bool|string
1536 */
1537 function learn_press_seconds_to_weeks( int $secs = 0 ) {
1538 $secs = (int) $secs;
1539
1540 if ( 0 === $secs ) {
1541 return false;
1542 }
1543 // variables for holding values.
1544 $mins = 0;
1545 $hours = 0;
1546 $days = 0;
1547 $weeks = 0;
1548 // calculations.
1549 if ( $secs >= 60 ) {
1550 $mins = (int) ( $secs / 60 );
1551 $secs = $secs % 60;
1552 }
1553 if ( $mins >= 60 ) {
1554 $hours = (int) ( $mins / 60 );
1555 $mins = $mins % 60;
1556 }
1557 if ( $hours >= 24 ) {
1558 $days = (int) ( $hours / 24 );
1559 $hours = $hours % 24;
1560 }
1561 if ( $days >= 7 ) {
1562 $weeks = (int) ( $days / 7 );
1563 $days = $days % 7;
1564 }
1565 // format result.
1566 $result = '';
1567 if ( $weeks ) {
1568 $result .= sprintf( _n( '%s week', '%s weeks', $weeks, 'learnpress' ), $weeks ) . ' ';
1569 }
1570
1571 if ( $days ) {
1572 $result .= sprintf( _n( '%s day', '%s days', $days, 'learnpress' ), $days ) . ' ';
1573 }
1574
1575 if ( ! $weeks ) {
1576 if ( $hours ) {
1577 $result .= sprintf( _n( '%s hour', '%s hours', $hours, 'learnpress' ), $hours ) . ' ';
1578 }
1579
1580 if ( $mins ) {
1581 $result .= sprintf( _n( '%s minute', '%s minutes', $mins, 'learnpress' ), $mins ) . ' ';
1582 }
1583 }
1584
1585 $result = rtrim( $result );
1586
1587 return $result;
1588 }
1589
1590 /**
1591 * @depecated since version 4.1.6.6
1592 */
1593 /*function learn_press_get_query_var( $var ) {
1594 global $wp_query;
1595
1596 $return = null;
1597 if ( ! empty( $wp_query->query_vars[ $var ] ) ) {
1598 $return = $wp_query->query_vars[ $var ];
1599 } elseif ( ! empty( $_REQUEST[ $var ] ) ) {
1600 $return = $_REQUEST[ $var ];
1601 }
1602
1603 return apply_filters( 'learn_press_query_var', $return, $var );
1604 }*/
1605
1606 function learn_press_course_lesson_permalink_friendly( $permalink, $lesson_id, $course_id ) {
1607 if ( '' != get_option( 'permalink_structure' ) ) {
1608 if ( preg_match( '!\?lesson=([^\?\&]*)!', $permalink, $matches ) ) {
1609 $permalink = preg_replace(
1610 '!/?\?lesson=([^\?\&]*)!',
1611 '/' . basename( get_permalink( $matches[1] ) ),
1612 untrailingslashit( $permalink )
1613 );
1614 }
1615 }
1616
1617 return $permalink;
1618 }
1619
1620 function learn_press_course_question_permalink_friendly( $permalink, $lesson_id, $course_id ) {
1621 if ( '' != get_option( 'permalink_structure' ) ) {
1622 if ( preg_match( '!\?lesson=([^\?\&]*)!', $permalink, $matches ) ) {
1623 $permalink = preg_replace(
1624 '!/?\?lesson=([^\?\&]*)!',
1625 '/' . basename( get_permalink( $matches[1] ) ),
1626 untrailingslashit( $permalink )
1627 );
1628 }
1629 }
1630
1631 return $permalink;
1632 }
1633
1634 add_filter( 'learn_press_course_lesson_permalink', 'learn_press_course_lesson_permalink_friendly', 10, 3 );
1635
1636 function learn_press_user_maybe_is_a_teacher( $user = null ) {
1637 if ( ! $user ) {
1638 $user = learn_press_get_current_user();
1639 } elseif ( is_numeric( $user ) ) {
1640 $user = learn_press_get_user( $user );
1641 }
1642 if ( ! $user ) {
1643 return false;
1644 }
1645
1646 $role = $user->has_role( 'administrator' ) ? 'administrator' : false;
1647 if ( ! $role ) {
1648 $role = $user->has_role( 'lp_teacher' ) ? 'lp_teacher' : false;
1649 }
1650
1651 return apply_filters( 'learn-press/user/is-teacher', $role, $user->get_id() );
1652 }
1653
1654 function learn_press_become_teacher_sent( $user_id = 0 ) {
1655 if ( func_num_args() == 0 ) {
1656 $user_id = get_current_user_id();
1657 }
1658
1659 return 'yes' === get_user_meta( $user_id, '_requested_become_teacher', true );
1660 }
1661
1662 function _learn_press_translate_user_roles( $translations, $text, $context, $domain ) {
1663 $plugin_domain = 'learnpress';
1664 $roles = array( 'LP Instructor' );
1665
1666 if ( $context === 'User role' && in_array( $text, $roles ) && $domain !== $plugin_domain ) {
1667 return translate_with_gettext_context( $text, $context, $plugin_domain );
1668 }
1669
1670 return $translations;
1671 }
1672
1673 add_filter( 'gettext_with_context', '_learn_press_translate_user_roles', 10, 4 );
1674
1675 /**
1676 * Modifies the statement $where to make the search works correct
1677 *
1678 * @param string
1679 *
1680 * @return string
1681 */
1682 function learn_press_posts_where_statement_search( $where ) {
1683 // gets the global query var object
1684 global $wp_query, $wpdb;
1685
1686 /**
1687 * Need to wrap this block into () in order to make it works correctly when filter by specific post type => maybe a bug :)
1688 * from => ( wp_2_posts.post_status = 'publish' OR wp_2_posts.post_status = 'private') OR wp_2_terms.name LIKE '%s%'
1689 * to => ( ( wp_2_posts.post_status = 'publish' OR wp_2_posts.post_status = 'private') OR wp_2_terms.name LIKE '%s%' )
1690 */
1691 $a = preg_match( '!(' . $wpdb->posts . '.post_status)!', $where );
1692 $b = preg_match( '!(OR\s+' . $wpdb->terms . '.name LIKE \'%' . $wp_query->get( 's' ) . '%\')!', $where );
1693
1694 if ( $a && $b ) {
1695 // append ( to the start of the block
1696 $where = preg_replace( '!(' . $wpdb->posts . '.post_status)!', '( $1', $where, 1 );
1697
1698 // append ) to the end of the block
1699 $where = preg_replace(
1700 '!(OR\s+' . $wpdb->terms . '.name LIKE \'%' . $wp_query->get( 's' ) . '%\')!',
1701 '$1 )',
1702 $where
1703 );
1704 }
1705 remove_filter( 'posts_where', 'learn_press_posts_where_statement_search', 99 );
1706
1707 return $where;
1708 }
1709
1710 /**
1711 * Filter post type for search function
1712 * Only search lpr_course if see the param ref=course in request
1713 *
1714 * @param WP_Query $q
1715 */
1716 function learn_press_filter_search( $q ) {
1717 if ( $q->is_main_query() && $q->is_search() && ( ! empty( $_REQUEST['ref'] ) && sanitize_text_field( $_REQUEST['ref'] ) == 'course' ) ) {
1718 $q->set( 'post_type', 'lp_course' );
1719
1720 add_filter( 'posts_where', 'learn_press_posts_where_statement_search', 99 );
1721 remove_filter( 'pre_get_posts', 'learn_press_filter_search', 99 );
1722 }
1723 }
1724
1725 add_filter( 'pre_get_posts', 'learn_press_filter_search', 99 );
1726
1727 if ( ! function_exists( 'learn_press_send_json' ) ) {
1728 function learn_press_send_json( $data ) {
1729 echo '<-- LP_AJAX_START -->';
1730 echo wp_json_encode( $data );
1731 echo '<-- LP_AJAX_END -->';
1732 die;
1733 }
1734 }
1735
1736 /**
1737 * Send json with success signal to browser.
1738 *
1739 * @param array|object|WP_Error $data
1740 *
1741 * @since 3.0.1
1742 */
1743 function learn_press_send_json_error( $data = '' ) {
1744 $response = array( 'success' => false );
1745
1746 if ( isset( $data ) ) {
1747 if ( is_wp_error( $data ) ) {
1748 $result = array();
1749 foreach ( $data->errors as $code => $messages ) {
1750 foreach ( $messages as $message ) {
1751 $result[] = array(
1752 'code' => $code,
1753 'message' => $message,
1754 );
1755 }
1756 }
1757
1758 $response['data'] = $result;
1759 } else {
1760 $response['data'] = $data;
1761 }
1762 }
1763
1764 learn_press_send_json( $response );
1765 }
1766
1767 /**
1768 * Send json with error signal to browser.
1769 *
1770 * @param array|object|WP_Error $data
1771 *
1772 * @since 3.0.0
1773 */
1774 function learn_press_send_json_success( $data = '' ) {
1775 $response = array( 'success' => true );
1776
1777 if ( isset( $data ) ) {
1778 $response['data'] = $data;
1779 }
1780
1781 learn_press_send_json( $response );
1782 }
1783
1784 /**
1785 * Check if ajax is calling then send json data.
1786 *
1787 * @param array $data
1788 * @param mixed $callback
1789 *
1790 * @return bool
1791 */
1792 function learn_press_maybe_send_json( $data, $callback = null ) {
1793 if ( learn_press_is_ajax() ) {
1794 is_callable( $callback ) && call_user_func( $callback );
1795 if ( empty( $data['message'] ) && ( $message = learn_press_get_messages( true ) ) ) {
1796 $data['message'] = $message;
1797 }
1798 learn_press_send_json( $data );
1799 }
1800
1801 return false;
1802 }
1803
1804 /**
1805 * Get data from request.
1806 *
1807 * @param string $key
1808 * @param mixed $default
1809 * @param mixed $hash
1810 *
1811 * @return mixed
1812 */
1813 function learn_press_get_request( $key, $default = null, $hash = null ) {
1814 $return = LP_Helper::sanitize_params_submitted( $default );
1815
1816 if ( $hash ) {
1817 if ( ! empty( $hash[ $key ] ) ) {
1818 $return = LP_Helper::sanitize_params_submitted( $hash[ $key ] );
1819 }
1820 } else {
1821 if ( ! empty( $_POST[ $key ] ) ) {
1822 $return = LP_Helper::sanitize_params_submitted( $_POST[ $key ] );
1823 } elseif ( ! empty( $_GET[ $key ] ) ) {
1824 $return = LP_Helper::sanitize_params_submitted( $_GET[ $key ] );
1825 } elseif ( ! empty( $_REQUEST[ $key ] ) ) {
1826 $return = LP_Helper::sanitize_params_submitted( $_REQUEST[ $key ] );
1827 }
1828 }
1829
1830 return $return;
1831 }
1832
1833 /**
1834 * @return mixed
1835 */
1836 function is_learnpress() {
1837 return apply_filters(
1838 'is_learnpress',
1839 ( learn_press_is_course_archive() || learn_press_is_course_taxonomy() || learn_press_is_course() || learn_press_is_quiz() || learn_press_is_search() ) ? true : false
1840 );
1841 }
1842
1843 if ( ! function_exists( 'learn_press_is_search' ) ) {
1844 function learn_press_is_search() {
1845 return array_key_exists( 's', $_REQUEST ) && array_key_exists( 'ref', $_REQUEST ) && sanitize_text_field( $_REQUEST['ref'] ) == 'course';
1846 }
1847 }
1848
1849 if ( ! function_exists( 'learn_press_is_courses' ) ) {
1850 function learn_press_is_courses() {
1851 return learn_press_is_course_archive();
1852 }
1853 }
1854
1855
1856 if ( ! function_exists( 'learn_press_is_course_archive' ) ) {
1857 function learn_press_is_course_archive() {
1858 global $wp_query;
1859
1860 $queried_object_id = ! empty( $wp_query->queried_object ) ? $wp_query->queried_object : 0;
1861 $is_courses = defined( 'LEARNPRESS_IS_COURSES' ) && LEARNPRESS_IS_COURSES;
1862 $is_tag = defined( 'LEARNPRESS_IS_TAG' ) && LEARNPRESS_IS_TAG || is_tax( 'course_tag' );
1863 $is_category = defined( 'LEARNPRESS_IS_CATEGORY' ) && LEARNPRESS_IS_CATEGORY || is_tax( 'course_category' );
1864 $page_id = learn_press_get_page_id( 'courses' );
1865
1866 return ( $is_courses || $is_category || $is_tag ) || is_post_type_archive( 'lp_course' ) || ( $page_id && ( $queried_object_id && is_page( $page_id ) ) );
1867 }
1868 }
1869
1870 if ( ! function_exists( 'learn_press_is_course_tax' ) ) {
1871 function learn_press_is_course_tax() {
1872 return is_tax( get_object_taxonomies( LP_COURSE_CPT ) );
1873 }
1874 }
1875
1876 if ( ! function_exists( 'learn_press_is_course_taxonomy' ) ) {
1877 function learn_press_is_course_taxonomy() {
1878 return ( defined( 'LEARNPRESS_IS_TAX' ) && LEARNPRESS_IS_TAX ) || learn_press_is_course_tax();
1879 }
1880 }
1881
1882
1883 if ( ! function_exists( 'learn_press_is_course_category' ) ) {
1884 function learn_press_is_course_category( $term = '' ) {
1885 return ( defined( 'LEARNPRESS_IS_CATEGORY' ) && LEARNPRESS_IS_CATEGORY ) || is_tax( 'course_category', $term );
1886 }
1887 }
1888
1889
1890 if ( ! function_exists( 'learn_press_is_course_tag' ) ) {
1891 function learn_press_is_course_tag( $term = '' ) {
1892 return ( defined( 'LEARNPRESS_IS_TAG' ) && LEARNPRESS_IS_TAG ) || is_tax( 'course_tag', $term );
1893 }
1894 }
1895
1896 if ( ! function_exists( 'learn_press_is_course' ) ) {
1897 function learn_press_is_course() {
1898 return is_singular( array( LP_COURSE_CPT ) );
1899 }
1900 }
1901
1902 if ( ! function_exists( 'learn_press_is_lesson' ) ) {
1903 function learn_press_is_lesson() {
1904 return is_singular( array( LP_LESSON_CPT ) );
1905 }
1906 }
1907
1908 if ( ! function_exists( 'learn_press_is_quiz' ) ) {
1909 function learn_press_is_quiz() {
1910 return is_singular( array( LP_QUIZ_CPT ) );
1911 }
1912 }
1913
1914 function lp_content_has_shortcode( $tag = '' ) {
1915 global $post;
1916
1917 return is_singular() && is_a( $post, 'WP_Post' ) && has_shortcode( $post->post_content, $tag );
1918 }
1919
1920 /**
1921 * Returns true when viewing profile page.
1922 *
1923 * @return bool
1924 */
1925 function learn_press_is_profile() {
1926 $page_id = learn_press_get_page_id( 'profile' );
1927
1928 if ( $page_id && is_page( $page_id ) || lp_content_has_shortcode( 'learn_press_profile' ) ) {
1929 return true;
1930 }
1931
1932 return apply_filters( 'learn-press/is-profile', false );
1933 }
1934
1935 /**
1936 * Return true if user is in checking out page
1937 *
1938 * @return bool
1939 */
1940 function learn_press_is_checkout() {
1941 $page_id = learn_press_get_page_id( 'checkout' );
1942
1943 if ( $page_id && is_page( $page_id ) ) {
1944 return true;
1945 }
1946
1947 return apply_filters( 'learn-press/is-checkout', false );
1948 }
1949
1950 /**
1951 * Return register permalink
1952 *
1953 * @return mixed
1954 */
1955 function learn_press_get_register_url() {
1956 return apply_filters( 'learn_press_register_url', wp_registration_url() );
1957 }
1958
1959 /**
1960 * Add a new notice into queue
1961 *
1962 * @param string
1963 * @param string
1964 *
1965 * @return mixed
1966 */
1967 function learn_press_add_notice( $message, $type = 'updated' ) {
1968 LP_Admin_Notice::instance()->add( $message, $type );
1969 }
1970
1971 /**
1972 * Set user's cookie
1973 *
1974 * @param $name
1975 * @param $value
1976 * @param int $expire
1977 * @param bool $secure
1978 *
1979 * @editor tungnx
1980 * @version 1.0.2
1981 */
1982 function learn_press_setcookie( $name, $value, $expire = 0, $secure = false, $httponly = false ) {
1983 $secure = ( 'https' === parse_url( wp_login_url(), PHP_URL_SCHEME ) );
1984
1985 @setcookie( $name, $value, $expire, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN, $secure, $httponly );
1986 }
1987
1988 /**
1989 * Clear cookie
1990 *
1991 * @param $name
1992 */
1993 function learn_press_remove_cookie( $name ) {
1994 setcookie( $name, '', time() - YEAR_IN_SECONDS, COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN );
1995
1996 if ( array_key_exists( $name, $_COOKIE ) ) {
1997 unset( $_COOKIE[ $name ] );
1998 }
1999 }
2000
2001 /**
2002 * Filter the login url so third-party can be customize
2003 *
2004 * @param string $redirect
2005 *
2006 * @return mixed
2007 */
2008 function learn_press_get_login_url( $redirect = null ) {
2009 $url = wp_login_url( $redirect );
2010 $profile_page = learn_press_get_page_link( 'profile' );
2011
2012 if ( 'yes' === LP_Settings::instance()->get( 'enable_login_profile' ) && $profile_page ) {
2013 $parse_url = parse_url( $url );
2014 $url = $profile_page . ( ! empty( $parse_url['query'] ) ? '?' . $parse_url['query'] : '' );
2015 }
2016
2017 return apply_filters( 'learn-press/login-url', $url );
2018 }
2019
2020 /**
2021 * Add variable to an url by checking the permalink structure.
2022 *
2023 * @param string $name
2024 * @param string $value
2025 * @param string $url
2026 *
2027 * @return string
2028 */
2029 function learn_press_get_endpoint_url( $name, $value, $url ) {
2030 if ( ! $url ) {
2031 $url = get_permalink();
2032 }
2033
2034 // Map endpoint to options
2035 $name = isset( LP()->query_vars[ $name ] ) ? LP()->query_vars[ $name ] : $name;
2036
2037 if ( get_option( 'permalink_structure' ) ) {
2038 if ( strstr( $url, '?' ) ) {
2039 $query_string = '?' . parse_url( $url, PHP_URL_QUERY );
2040 $url = current( explode( '?', $url ) );
2041 } else {
2042 $query_string = '';
2043 }
2044 $url = trailingslashit( $url ) . ( $name ? $name . '/' : '' ) . $value . $query_string;
2045
2046 } else {
2047 $url = esc_url_raw( add_query_arg( $name, $value, $url ) );
2048 }
2049
2050 return apply_filters( 'learn_press_get_endpoint_url', esc_url_raw( $url ), $name, $value, $url );
2051 }
2052
2053 /**
2054 * Add all endpoints from settings to the pages.
2055 */
2056 function learn_press_add_endpoints() {
2057 $settings = LP_Settings::instance();
2058
2059 $endpoints = $settings->get_checkout_endpoints();
2060 if ( $endpoints ) {
2061 foreach ( $endpoints as $endpoint => $value ) {
2062 LP()->query_vars[ $endpoint ] = $value;
2063 add_rewrite_endpoint( $value, EP_PAGES );
2064 }
2065 }
2066
2067 $endpoints = $settings->get_profile_endpoints();
2068 if ( $endpoints ) {
2069 foreach ( $endpoints as $endpoint => $value ) {
2070 LP()->query_vars[ $endpoint ] = $value;
2071 add_rewrite_endpoint( $value, EP_PAGES );
2072 }
2073 }
2074
2075 $endpoints = $settings->get( 'quiz_endpoints' );
2076 if ( $endpoints ) {
2077 foreach ( $endpoints as $endpoint => $value ) {
2078 $endpoint = preg_replace( '!_!', '-', $endpoint );
2079 LP()->query_vars[ $endpoint ] = $value;
2080 add_rewrite_endpoint(
2081 $value, /*EP_ROOT | */
2082 EP_PAGES
2083 );
2084 }
2085 }
2086 }
2087
2088 add_action( 'init', 'learn_press_add_endpoints' );
2089
2090 function learn_press_is_yes( $value ) {
2091 return ( $value === 1 ) || ( $value === '1' ) || ( $value == 'yes' ) || ( $value == true ) || ( $value == 'on' );
2092 }
2093
2094 /**
2095 * @param mixed $value
2096 *
2097 * @return bool
2098 */
2099 function _is_false_value( $value ) {
2100 if ( is_numeric( $value ) ) {
2101 return $value == 0;
2102 } elseif ( is_string( $value ) ) {
2103 return ( empty( $value ) || is_null( $value ) || in_array( $value, array( 'no', 'off', 'false' ) ) );
2104 }
2105
2106 return ! ! $value;
2107 }
2108
2109 /**
2110 * Map the query vars from LP to query vars of WP core
2111 * when WP parse the requesting.
2112 */
2113 function learn_press_parse_request() {
2114 global $wp;
2115
2116 // Map query vars to their keys, or get them if endpoints are not supported
2117 foreach ( LP()->query_vars as $key => $var ) {
2118 if ( isset( $_GET[ $var ] ) ) {
2119 $wp->query_vars[ $key ] = LP_Helper::sanitize_params_submitted( $_GET[ $var ] ?? '' );
2120 } elseif ( isset( $wp->query_vars[ $var ] ) ) {
2121 $wp->query_vars[ $key ] = LP_Helper::sanitize_params_submitted( $wp->query_vars[ $var ] ?? '' );
2122 }
2123 }
2124 }
2125
2126 add_action( 'parse_request', 'learn_press_parse_request' );
2127
2128 if ( ! function_exists( 'learn_press_reset_auto_increment' ) ) {
2129 /**
2130 * Reset AUTO INCREMENT of the table.
2131 *
2132 * @param $table
2133 */
2134 function learn_press_reset_auto_increment( $table ) {
2135 global $wpdb;
2136 $wpdb->query( $wpdb->prepare( "ALTER TABLE {$wpdb->prefix}$table AUTO_INCREMENT = %d", 1 ) );
2137 }
2138 }
2139
2140 /**
2141 * @param string $handle
2142 * @param bool $hash
2143 *
2144 * @return string
2145 */
2146 function learn_press_get_log_file_path( $handle, $hash = false ) {
2147 if ( $hash ) {
2148 $hash = '-' . sanitize_file_name( wp_hash( $handle ) );
2149 }
2150
2151 return trailingslashit( LP_LOG_PATH ) . $handle . $hash . '.log';
2152 }
2153
2154 /**
2155 * Get the cart object in checkout page
2156 *
2157 * @return LP_Cart
2158 */
2159 function learn_press_get_checkout_cart() {
2160 return apply_filters( 'learn_press_checkout_cart', LP()->cart );
2161 }
2162
2163 /*function learn_press_front_scripts() {
2164 if ( is_admin() ) {
2165 return;
2166 }
2167 $js = array(
2168 'ajax' => admin_url( 'admin-ajax.php' ),
2169 'plugin_url' => LP()->plugin_url(),
2170 'siteurl' => home_url(),
2171 'current_url' => learn_press_get_current_url(),
2172 'localize' => array(
2173 'button_ok' => __( 'OK', 'learnpress' ),
2174 'button_cancel' => __( 'Cancel', 'learnpress' ),
2175 'button_yes' => __( 'Yes', 'learnpress' ),
2176 'button_no' => __( 'No', 'learnpress' ),
2177 ),
2178 );
2179 foreach ( $js as $k => $v ) {
2180 LP_Assets::add_param( $k, $v, array( 'learn-press-single-course', 'learn-press-global' ), 'LP_Settings' );
2181 }
2182 }
2183
2184 add_action( 'wp_print_scripts', 'learn_press_front_scripts' );*/
2185
2186 function learn_press_user_time( $time, $format = 'timestamp' ) {
2187 if ( is_string( $time ) ) {
2188 $time = @strtotime( $time );
2189 }
2190 $time = $time + ( get_option( 'gmt_offset' ) - $_COOKIE['timezone'] / 60 ) * HOUR_IN_SECONDS;
2191 switch ( $format ) {
2192 case 'timestamp':
2193 return $time;
2194 default:
2195 return date( 'Y-m-d H:i:s', $time );
2196 }
2197 }
2198
2199 function learn_press_get_current_version() {
2200 $data = get_plugin_data( LP_PLUGIN_FILE, $markup = true, $translate = true );
2201
2202 return $data['Version'];
2203 }
2204
2205 /**
2206 * Get current tab is displaying in user profile.
2207 * If there is no tab then get the first tab in
2208 * the list of tabs.
2209 *
2210 * @param bool $default
2211 *
2212 * @return mixed|string
2213 */
2214 function learn_press_get_current_profile_tab( $default = true ) {
2215 global $wp_query, $wp;
2216 $current = '';
2217
2218 if ( ! empty( $_REQUEST['tab'] ) ) {
2219 $current = LP_Helper::sanitize_params_submitted( $_REQUEST['tab'] );
2220 } elseif ( ! empty( $wp_query->query_vars['tab'] ) ) {
2221 $current = $wp_query->query_vars['tab'];
2222 } elseif ( ! empty( $wp->query_vars['view'] ) ) {
2223 $current = $wp->query_vars['view'];
2224 } else {
2225 $tabs = learn_press_get_user_profile_tabs();
2226 if ( $default && $tabs ) {
2227 // Fixed for array_keys does not work with ArrayAccess instance
2228 if ( $tabs instanceof LP_Profile_Tabs ) {
2229 $tabs = $tabs->tabs();
2230 }
2231
2232 $tab_keys = array_keys( $tabs );
2233 $current = reset( $tab_keys );
2234 }
2235 }
2236
2237 return $current;
2238 }
2239
2240 add_action( 'init', 'learn_press_get_current_profile_tab' );
2241
2242 function learn_press_profile_tab_exists( $tab ) {
2243 $tabs = learn_press_get_user_profile_tabs();
2244
2245 if ( $tabs ) {
2246 return ! empty( $tabs[ $tab ] ) ? true : false;
2247 }
2248
2249 return false;
2250 }
2251
2252 /**
2253 * Replace the spacing with the + (plus) char.
2254 *
2255 * @param string $string
2256 *
2257 * @return string
2258 */
2259 function _learn_press_urlencode( $string ) {
2260 return preg_replace( '/\s/', '+', $string );
2261 }
2262
2263 /**
2264 * Point the archive post type link to course page if current
2265 * post type is course and the page for displaying course is
2266 * setup.
2267 *
2268 * @param string $link
2269 * @param string $post_type
2270 *
2271 * @return string
2272 */
2273 function learn_press_post_type_archive_link( $link, $post_type ) {
2274 if ( $post_type == LP_COURSE_CPT && learn_press_get_page_id( 'courses' ) ) {
2275 $link = learn_press_get_page_link( 'courses' );
2276 }
2277
2278 return $link;
2279 }
2280
2281 add_filter( 'post_type_archive_link', 'learn_press_post_type_archive_link', 10, 2 );
2282
2283 function learn_press_single_term_title( $prefix = '', $display = true ) {
2284 $term = get_queried_object();
2285
2286 if ( ! $term ) {
2287 return '';
2288 }
2289
2290 if ( learn_press_is_course_category() ) {
2291 $term_name = apply_filters( 'single_course_category_title', $term->name );
2292 } elseif ( learn_press_is_course_tag() ) {
2293 $term_name = apply_filters( 'single_course_tag_title', $term->name );
2294 } elseif ( learn_press_is_course_taxonomy() ) {
2295 $term_name = apply_filters( 'single_course_term_title', $term->name );
2296 } else {
2297 return single_term_title( $prefix, $display );
2298 }
2299
2300 if ( empty( $term_name ) ) {
2301 return single_term_title( $prefix, $display );
2302 }
2303
2304 if ( $display ) {
2305 echo $prefix . $term_name;
2306 }
2307
2308 return $prefix . $term_name;
2309 }
2310
2311 /**
2312 * Control the template file if user is searching course.
2313 * Use the template of archive course to display the
2314 * result if there is a flag in request to search course.
2315 *
2316 * @param string $template
2317 *
2318 * @return string
2319 */
2320 function learn_press_search_template( $template ) {
2321 if ( ! empty( $_REQUEST['ref'] ) && sanitize_text_field( $_REQUEST['ref'] ) == 'course' ) {
2322 $template = learn_press_locate_template( 'archive-course.php' );
2323 }
2324
2325 return $template;
2326 }
2327
2328 /**
2329 * Auto enroll user to a course after an order is completed
2330 * if the option auto-enroll is turn on.
2331 *
2332 * @param int $order_id
2333 *
2334 * @return mixed
2335 * @editor tungnx
2336 */
2337 function learn_press_auto_enroll_user_to_courses( $order_id ) {
2338 _deprecated_function( __FUNCTION__, '4.1.3' );
2339 }
2340
2341 // add_action( 'learn_press_order_status_completed', 'learn_press_auto_enroll_user_to_courses' );
2342
2343 /**
2344 * Return true if enable cart
2345 *
2346 * @return bool
2347 */
2348 function learn_press_is_enable_cart() {
2349 return defined( 'LP_ENABLE_CART' ) && LP_ENABLE_CART == true;
2350 }
2351
2352 /**
2353 * Short way to get checkout object
2354 *
2355 * @param array
2356 *
2357 * @return LP_Checkout
2358 */
2359 function learn_press_get_checkout( $args = null ) {
2360 $checkout = LP_Checkout::instance();
2361
2362 if ( is_array( $args ) ) {
2363 foreach ( $args as $k => $v ) {
2364 $checkout->{$k} = $v;
2365 }
2366 }
2367
2368 return $checkout;
2369 }
2370
2371 if ( defined( 'LP_ENABLE_CART' ) && LP_ENABLE_CART ) {
2372 add_filter( 'learn_press_checkout_settings', '_learn_press_cart_settings', 10, 2 );
2373 function _learn_press_cart_settings( $settings, $class ) {
2374 $settings = array_merge(
2375 $settings,
2376 array(
2377 array(
2378 'title' => __( 'Cart', 'learnpress' ),
2379 'type' => 'title',
2380 ),
2381 array(
2382 'title' => __( 'Enable cart', 'learnpress' ),
2383 'desc' => __(
2384 'Check this option to enable user purchase multiple courses at one time.',
2385 'learnpress'
2386 ),
2387 'id' => $class->get_field_name( 'enable_cart' ),
2388 'default' => 'yes',
2389 'type' => 'checkbox',
2390 ),
2391 array(
2392 'title' => __( 'Add to cart redirect', 'learnpress' ),
2393 'desc' => __( 'Redirect to checkout immediately after adding course to cart.', 'learnpress' ),
2394 'id' => $class->get_field_name( 'redirect_after_add' ),
2395 'default' => 'yes',
2396 'type' => 'checkbox',
2397 ),
2398 array(
2399 'title' => __( 'AJAX add to cart', 'learnpress' ),
2400 'desc' => __( 'Using AJAX to add course to cart.', 'learnpress' ),
2401 'id' => $class->get_field_name( 'ajax_add_to_cart' ),
2402 'default' => 'no',
2403 'type' => 'checkbox',
2404 ),
2405 array(
2406 'title' => __( 'Cart page', 'learnpress' ),
2407 'id' => $class->get_field_name( 'cart_page_id' ),
2408 'default' => '',
2409 'type' => 'pages-dropdown',
2410 ),
2411 )
2412 );
2413
2414 return $settings;
2415 }
2416 } else {
2417 add_filter( 'learn_press_enable_cart', '_learn_press_enable_cart', 1000 );
2418 function _learn_press_enable_cart( $r ) {
2419 return false;
2420 }
2421
2422 add_filter( 'learn_press_get_template', '_learn_press_enroll_button', 1000, 5 );
2423 function _learn_press_enroll_button( $located, $template_name, $args, $template_path, $default_path ) {
2424 if ( $template_name == 'single-course/enroll-button.php' ) {
2425 $located = learn_press_locate_template(
2426 'single-course/enroll-button-new.php',
2427 $template_path,
2428 $default_path
2429 );
2430 }
2431
2432 return $located;
2433 }
2434 }
2435
2436 /**
2437 * Returns checkout url from setting
2438 *
2439 * @return string
2440 */
2441 function learn_press_get_checkout_url() {
2442 $checkout_url = learn_press_get_page_link( 'checkout' );
2443
2444 return apply_filters( 'learn_press_get_checkout_url', $checkout_url );
2445 }
2446
2447 /**
2448 * @return string
2449 */
2450 function learn_press_checkout_needs_payment() {
2451 return LP()->cart->needs_payment();
2452 }
2453
2454 /**
2455 * Return plugin basename
2456 *
2457 * @param string $filepath
2458 *
2459 * @return string
2460 */
2461 /*
2462 function learn_press_plugin_basename( $filepath ) {
2463 $file = str_replace( '\\', '/', $filepath );
2464 $file = preg_replace( '|/+|', '/', $file );
2465 $plugin_dir = str_replace( '\\', '/', WP_PLUGIN_DIR );
2466 $plugin_dir = preg_replace( '|/+|', '/', $plugin_dir );
2467 $mu_plugin_dir = str_replace( '\\', '/', WPMU_PLUGIN_DIR );
2468 $mu_plugin_dir = preg_replace( '|/+|', '/', $mu_plugin_dir );
2469 $sp_plugin_dir = dirname( $filepath );
2470 $sp_plugin_dir = dirname( $sp_plugin_dir );
2471 $sp_plugin_dir = str_replace( '\\', '/', $sp_plugin_dir );
2472 $sp_plugin_dir = preg_replace( '|/+|', '/', $sp_plugin_dir );
2473
2474 $file = preg_replace(
2475 '#^' . preg_quote( $sp_plugin_dir, '#' ) . '/|^' . preg_quote(
2476 $plugin_dir,
2477 '#'
2478 ) . '/|^' . preg_quote(
2479 $mu_plugin_dir,
2480 '#'
2481 ) . '/#',
2482 '',
2483 $file
2484 );
2485 $file = trim( $file, '/' );
2486
2487 return strtolower( $file );
2488 }*/
2489
2490 /**
2491 * Update log data for each LP version into wp option.
2492 *
2493 * @param string $version
2494 * @param mixed $data
2495 */
2496 function learn_press_update_log( $version, $data ) {
2497 $logs = get_option( 'learn_press_update_logs' );
2498 if ( ! $logs ) {
2499 $logs = array( $version => $data );
2500 } else {
2501 $logs[ $version ] = $data;
2502 }
2503 update_option( 'learn_press_update_logs', $logs );
2504 }
2505
2506 /**
2507 * Output variables to screen for debugging.
2508 */
2509 function learn_press_debug() {
2510 $args = func_get_args();
2511 $debug = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS );
2512
2513 echo '<pre>';
2514 print_r( $debug );
2515 $arg = false;
2516
2517 if ( $args ) {
2518 foreach ( $args as $arg ) {
2519 echo "\n======LearnPress Debug=======\n";
2520 print_r( $arg );
2521 echo "\n=============================\n";
2522 }
2523 }
2524 echo '</pre>';
2525
2526 if ( true === $arg ) {
2527 die( __FUNCTION__ );
2528 }
2529 }
2530
2531 /**
2532 * Get current time to user for calculate remaining time of quiz.
2533 *
2534 * @return int
2535 */
2536 function learn_press_get_current_time() {
2537 $current_time = apply_filters( 'learn_press_get_current_time', 0 );
2538
2539 if ( $current_time > 0 ) {
2540 return $current_time;
2541 }
2542
2543 $a = current_time( 'timestamp' );
2544 $b = time();
2545 $c = current_time( 'mysql' );
2546 $d = strtotime( $c );
2547
2548 if ( $d == $a ) {
2549 return $a;
2550 } else {
2551 return $b;
2552 }
2553 }
2554
2555 function learn_press_get_requested_post_type() {
2556 global $pagenow;
2557 if ( $pagenow == 'post-new.php' && ! empty( $_REQUEST['post_type'] ) ) {
2558 $post_type = LP_Helper::sanitize_params_submitted( $_REQUEST['post_type'] );
2559 } else {
2560 $post_id = learn_press_get_post();
2561 $post_type = learn_press_get_post_type( $post_id );
2562 }
2563
2564 return $post_type;
2565 }
2566
2567 /**
2568 * Get human string from grade slug.
2569 *
2570 * @param string $slug
2571 *
2572 * @return string
2573 */
2574 function learn_press_get_graduation_text( $slug ) {
2575 switch ( $slug ) {
2576 case 'passed':
2577 $text = esc_html__( 'Passed', 'learnpress' );
2578 break;
2579 case 'failed':
2580 $text = esc_html__( 'Failed', 'learnpress' );
2581 break;
2582 case 'in-progress':
2583 $text = esc_html__( 'In Progress', 'learnpress' );
2584 break;
2585 default:
2586 $text = $slug;
2587 }
2588
2589 return apply_filters( 'learn-press/get-graduation-text', $text, $slug );
2590 }
2591
2592 /*function learn_press_execute_time( $n = 1 ) {
2593 static $time;
2594 if ( empty( $time ) ) {
2595 $time = microtime( true );
2596
2597 return $time;
2598 } else {
2599 $execute_time = microtime( true ) - $time;
2600
2601 echo 'Execute time ' . $n * $execute_time . "\n";
2602 $time = 0;
2603
2604 return $execute_time;
2605 }
2606 }*/
2607
2608 if ( ! function_exists( 'learn_press_is_negative_value' ) ) {
2609 function learn_press_is_negative_value( $value ) {
2610 $return = in_array( $value, array( 'no', 'off', 'false', '0' ) ) || ! $value || $value == '' || $value == null;
2611
2612 return $return;
2613 }
2614 }
2615
2616 /**
2617 * Filter to comment reply link to fix bug the link is invalid for
2618 * lesson or quiz.
2619 *
2620 * @param string $link
2621 * @param array $args
2622 * @param WP_Comment $comment
2623 * @param WP_Post $post
2624 *
2625 * @return string
2626 */
2627 function learn_press_comment_reply_link( $link, $args = array(), $comment = null, $post = null ) {
2628
2629 $post_type = learn_press_get_post_type( $post );
2630
2631 if ( ! learn_press_is_support_course_item_type( $post_type ) ) {
2632 return $link;
2633 }
2634
2635 $course_item = LP_Global::course_item();
2636
2637 if ( get_option( 'comment_registration' ) && ! is_user_logged_in() ) {
2638 $link = sprintf(
2639 '<a rel="nofollow" class="comment-reply-login" href="%s">%s</a>',
2640 esc_url_raw( wp_login_url( get_permalink() ) ),
2641 $args['login_text']
2642 );
2643 } elseif ( $course_item ) {
2644 $onclick = sprintf(
2645 'return addComment.moveForm( "%1$s-%2$s", "%2$s", "%3$s", "%4$s" )',
2646 $args['add_below'],
2647 $comment->comment_ID,
2648 $args['respond_id'],
2649 $post->ID
2650 );
2651
2652 $link = sprintf(
2653 "<a rel='nofollow' class='comment-reply-link' href='%s' onclick='%s' aria-label='%s'>%s</a>",
2654 esc_url_raw(
2655 add_query_arg(
2656 array(
2657 'replytocom' => $comment->comment_ID,
2658 ),
2659 $course_item->get_permalink()
2660 )
2661 ) . '#' . $args['respond_id'],
2662 $onclick,
2663 esc_attr( sprintf( $args['reply_to_text'], $comment->comment_author ) ),
2664 $args['reply_text']
2665 );
2666 }
2667
2668 return $link;
2669 }
2670
2671 add_filter( 'comment_reply_link', 'learn_press_comment_reply_link', 10, 4 );
2672
2673 function learn_press_deprecated_function( $function, $version, $replacement = null ) {
2674 if ( LP_Debug::is_debug() ) {
2675 _deprecated_function( $function, $version, $replacement );
2676 }
2677 }
2678
2679
2680 /**
2681 * Sanitize content of tooltip
2682 *
2683 * @param string $tooltip
2684 * @param bool $html
2685 *
2686 * @return string
2687 */
2688 function learn_press_sanitize_tooltip( $tooltip, $html = false ) {
2689 if ( $html ) {
2690 $tooltip = htmlspecialchars(
2691 wp_kses(
2692 html_entity_decode( $tooltip ),
2693 array(
2694 'br' => array(),
2695 'em' => array(),
2696 'strong' => array(),
2697 'small' => array(),
2698 'span' => array(),
2699 'ul' => array(),
2700 'li' => array(),
2701 'ol' => array(),
2702 'p' => array(),
2703 )
2704 )
2705 );
2706 } else {
2707 $tooltip = esc_attr( $tooltip );
2708 }
2709
2710 return $tooltip;
2711 }
2712
2713 function learn_press_tooltip( $tooltip, $html = false ) {
2714 $tooltip = learn_press_sanitize_tooltip( $tooltip, $html );
2715 echo '<span class="learn-press-tooltip" data-tooltip="' . esc_attr( $tooltip ) . '"></span>';
2716 }
2717
2718 /**
2719 * Get timezone offset from wp settings.
2720 *
2721 * @return float|int
2722 * @since 3.0.0
2723 */
2724 function learn_press_timezone_offset() {
2725 if ( $tz = get_option( 'timezone_string' ) ) {
2726 $timezone = new DateTimeZone( $tz );
2727
2728 return $timezone->getOffset( new DateTime( 'now' ) );
2729 } else {
2730 return floatval( get_option( 'gmt_offset', 0 ) ) * HOUR_IN_SECONDS;
2731 }
2732 }
2733
2734 /**
2735 * Get default static pages of LP.
2736 *
2737 * @return array
2738 *
2739 * @since 3.0.0
2740 */
2741 function learn_press_static_page_ids() {
2742 $pages = LP_Object_Cache::get( 'static-page-ids', 'learn-press' );
2743
2744 if ( false === $pages ) {
2745 $pages = array(
2746 'checkout' => learn_press_get_page_id( 'checkout' ),
2747 'courses' => learn_press_get_page_id( 'courses' ),
2748 'profile' => learn_press_get_page_id( 'profile' ),
2749 'become_a_teacher' => learn_press_get_page_id( 'become_a_teacher' ),
2750 );
2751
2752 foreach ( $pages as $name => $id ) {
2753 if ( ! get_post( $id ) ) {
2754 $pages[ $name ] = 0;
2755 }
2756 }
2757
2758 LP_Object_Cache::set( 'static-page-ids', $pages, 'learn-press' );
2759 }
2760
2761 return apply_filters( 'learn-press/static-page-ids', $pages );
2762 }
2763
2764 /**
2765 * Get default static pages of LP.
2766 *
2767 * @param bool $name - Optional. TRUE will return name only.
2768 *
2769 * @return array
2770 *
2771 * @since 3.0.0
2772 */
2773 function learn_press_static_pages( $name = false ) {
2774 $pages = apply_filters(
2775 'learn-press/static-pages',
2776 array(
2777 'checkout' => _x( 'Checkout', 'static-page-name', 'learnpress' ),
2778 'courses' => _x( 'Courses', 'static-page-name', 'learnpress' ),
2779 'profile' => _x( 'Profile', 'static-page-name', 'learnpress' ),
2780 'become_a_teacher' => _x( 'Become a Teacher', 'static-page-name', 'learnpress' ),
2781 )
2782 );
2783
2784 if ( $name ) {
2785 return array_keys( $pages );
2786 }
2787
2788 return $pages;
2789 }
2790
2791 /*function learn_press_cache_path( $group, $key = '' ) {
2792 $path = LP_PLUGIN_PATH . 'cache';
2793 if ( ! file_exists( $path ) ) {
2794 @mkdir( $path );
2795 }
2796 $path = $path . '/' . $group;
2797
2798 if ( ! file_exists( $path ) ) {
2799 @mkdir( $path );
2800 }
2801 if ( $key ) {
2802 $path = $path . '/' . $key . '.ch';
2803 }
2804
2805 return $path;
2806 }*/
2807
2808 function learn_press_cache_get( $key, $group, $found = null ) {
2809 //$file = learn_press_cache_path( $group, $key );
2810 $data = wp_cache_get( $key, $group, $found );
2811
2812 /*if ( ! file_exists( $file ) ) {
2813 return false;
2814 }*/
2815
2816 /*if ( false === $data ) {
2817 $content = file_get_contents( $file );
2818
2819 if ( file_exists( $file ) && $content ) {
2820 try {
2821 $data = unserialize( $content );
2822 } catch ( Exception $ex ) {
2823 print_r( $content );
2824 die();
2825 }
2826 wp_cache_set( $key, $data, $group, $found );
2827 }
2828 }*/
2829
2830 return $data;
2831 }
2832
2833 function learn_press_cache_set( $key, $data, $group = '', $expire = 0 ) {
2834 //$file = learn_press_cache_path( $group, $key );
2835 wp_cache_set( $key, $data, $group, $expire );
2836
2837 /*if ( ! is_string( $data ) ) {
2838 $data = serialize( $data );
2839 }
2840 file_put_contents( $file, $data );*/
2841 }
2842
2843 function learn_press_cache_replace( $key, $data, $group = '', $expire = 0 ) {
2844 wp_cache_replace( $key, $data, $group, $expire );
2845 }
2846
2847 function learn_press_cache_add( $key, $data, $group = '', $expire = 0 ) {
2848 wp_cache_add( $key, $data, $group, $expire );
2849 }
2850
2851 if ( ! function_exists( 'learn_press_get_widget_course_object' ) ) {
2852 /**
2853 * Get course object for widget query.
2854 *
2855 * @param $query
2856 *
2857 * @return array
2858 * @deprecated v4.1.6.1 - we will remove on the version 4.1.7
2859 */
2860 function learn_press_get_widget_course_object( $query ) {
2861
2862 _deprecated_function( __FUNCTION__, '4.1.6.1' );
2863
2864 global $wpdb;
2865
2866 $posts = $wpdb->get_results( $query );
2867 if ( $posts ) {
2868 // get lp courses object from WordPress post
2869 $courses = array_map( 'learn_press_get_lp_course', $posts );
2870 $courses = array_filter( $courses );
2871
2872 } else {
2873 $courses = array();
2874 }
2875
2876 return $courses;
2877 }
2878 }
2879
2880 if ( ! function_exists( 'learn_press_get_lp_course' ) ) {
2881 /**
2882 * Get learn press course from WordPress post object
2883 *
2884 * @param object - reference $post WordPress post object
2885 *
2886 * @return LP_Course course
2887 * @deprecated v4.1.6.1 - we will remove on the version 4.1.7
2888 */
2889 function learn_press_get_lp_course( $post ) {
2890 _deprecated_function( __FUNCTION__, '4.1.6.1' );
2891
2892 $id = $post->ID;
2893 $course = null;
2894 if ( ! empty( $id ) ) {
2895 // $course = new LP_Course( $id );
2896 $course = learn_press_get_course( $id );
2897 }
2898
2899 return $course;
2900 }
2901 }
2902
2903 /**
2904 * Get all items are unassigned to any course.
2905 *
2906 * @param string|array $type - Optional. Types of items to get, default is all.
2907 *
2908 * @return array
2909 * @since 3.0.0
2910 * @deprecated 4.1.4.1 - Will remove on version 4.1.7
2911 */
2912 function learn_press_get_unassigned_items( $type = '' ) {
2913 _deprecated_function( __FUNCTION__, '4.1.6.1' );
2914
2915 global $wpdb;
2916
2917 if ( ! $type ) {
2918 $type = learn_press_course_get_support_item_types();
2919 $type = array_keys( $type );
2920 }
2921
2922 settype( $type, 'array' );
2923 $key = 'items-' . md5( serialize( $type ) );
2924
2925 if ( false === ( $items = LP_Object_Cache::get( $key, 'learn-press/unassigned' ) ) ) {
2926 $format = array_fill( 0, sizeof( $type ), '%s' );
2927
2928 $query = $wpdb->prepare(
2929 "
2930 SELECT p.ID
2931 FROM {$wpdb->posts} p
2932 WHERE p.post_type IN(" . join( ',', $format ) . ")
2933 AND p.ID NOT IN(
2934 SELECT si.item_id
2935 FROM {$wpdb->learnpress_section_items} si
2936 INNER JOIN {$wpdb->posts} p ON p.ID = si.item_id
2937 WHERE p.post_type IN(" . join( ',', $format ) . ')
2938 )
2939 AND p.post_status NOT IN(%s, %s)
2940 ',
2941 array_merge( $type, $type, array( 'auto-draft', 'trash' ) )
2942 );
2943
2944 $items = $wpdb->get_col( $query );
2945
2946 //LP_Debug::var_dump($query, __FILE__, __LINE__);
2947
2948 LP_Object_Cache::set( $key, $items, 'learn-press/unassigned' );
2949 }
2950
2951 return $items;
2952 }
2953
2954 /**
2955 * Get all questions are unassigned to any quiz.
2956 *
2957 * @return array
2958 * @since 3.0.0
2959 * @deprecated 4.1.6.1 - Will remove on version 4.1.7
2960 */
2961 function learn_press_get_unassigned_questions() {
2962 _deprecated_function( __FUNCTION__, '4.1.6.1' );
2963
2964 global $wpdb;
2965
2966 if ( false === ( $questions = LP_Object_Cache::get( 'questions', 'learn-press/unassigned' ) ) ) {
2967 $query = $wpdb->prepare(
2968 "
2969 SELECT p.ID
2970 FROM {$wpdb->posts} p
2971 WHERE p.post_type = %s
2972 AND p.ID NOT IN(
2973 SELECT qq.question_id
2974 FROM {$wpdb->learnpress_quiz_questions} qq
2975 INNER JOIN {$wpdb->posts} p ON p.ID = qq.question_id
2976 WHERE p.post_type = %s
2977 )
2978 AND p.post_status NOT IN(%s, %s)
2979 ",
2980 LP_QUESTION_CPT,
2981 LP_QUESTION_CPT,
2982 'auto-draft',
2983 'trash'
2984 );
2985
2986 $questions = $wpdb->get_col( $query );
2987 LP_Object_Cache::set( 'questions', $questions, 'learn-press/unassigned' );
2988 }
2989
2990 return $questions;
2991 }
2992
2993 /**
2994 * Callback function for sorting to array|object by key|prop priority.
2995 *
2996 * @param array|object $a
2997 * @param array|object $b
2998 *
2999 * @return int
3000 * @since 3.0.0
3001 */
3002 function learn_press_sort_list_by_priority_callback( $a, $b ) {
3003 $a_priority = null;
3004 $b_priority = null;
3005
3006 if ( is_array( $a ) && array_key_exists( 'priority', $a ) ) {
3007 $a_priority = $a['priority'];
3008 } elseif ( is_object( $a ) ) {
3009 if ( is_callable( array( $a, 'get_priority' ) ) ) {
3010 $a_priority = $a->get_priority();
3011 } elseif ( property_exists( $a, 'priority' ) ) {
3012 $a_priority = $a->priority;
3013 }
3014 }
3015
3016 if ( is_array( $b ) && array_key_exists( 'priority', $b ) ) {
3017 $b_priority = $b['priority'];
3018 } elseif ( is_object( $b ) ) {
3019 if ( is_callable( array( $b, 'get_priority' ) ) ) {
3020 $b_priority = $b->get_priority();
3021 } elseif ( property_exists( $b, 'priority' ) ) {
3022 $b_priority = $b->priority;
3023 }
3024 }
3025
3026 if ( $a_priority === $b_priority ) {
3027 return 0;
3028 }
3029
3030 return ( $a_priority < $b_priority ) ? - 1 : 1;
3031 }
3032
3033 /**
3034 * Localize date with custom format.
3035 *
3036 * @param string $timestamp
3037 * @param string $format
3038 * @param bool $gmt
3039 *
3040 * @return string
3041 * @since 3.0.0
3042 */
3043 function learn_press_date_i18n( $timestamp = '', $format = '', $gmt = false ) {
3044 if ( ! $format ) {
3045 $format = get_option( 'date_format' );
3046 }
3047
3048 return date_i18n( $format, $timestamp, $gmt );
3049 }
3050
3051 function learn_press_date() {
3052
3053 }
3054
3055 /**
3056 * Remove user items.
3057 *
3058 * @param int $item_id
3059 * @param int $course_id
3060 * @param int $user_id
3061 * @param int $keep
3062 *
3063 * @since 3.0.8
3064 * @deprecated 4.1.6.1 - Will remove on version 4.1.7
3065 */
3066 function learn_press_remove_user_items_history( $item_id, $course_id, $user_id, $keep = 10 ) {
3067 _deprecated_function( __FUNCTION__, '4.1.6.1' );
3068
3069 $user = learn_press_get_user( $user_id );
3070 if ( $rows = $user->get_item_archive( $item_id, $course_id ) ) {
3071
3072 global $wpdb;
3073
3074 $args = array( $user_id, $item_id, $course_id );
3075 $query = $wpdb->prepare(
3076 "
3077 DELETE
3078 FROM {$wpdb->learnpress_user_items}
3079 WHERE user_id = %d AND item_id = %d
3080 AND ref_id = %d
3081 ",
3082 $args
3083 );
3084
3085 if ( $keep ) {
3086 $user_item_ids = array_keys( $rows );
3087 $user_item_ids = array_splice( $user_item_ids, 0, $keep );
3088 $format = array_fill( 0, sizeof( $user_item_ids ), '%d' );
3089
3090 $query .= $wpdb->prepare( ' AND user_item_id NOT IN(' . join( ',', $format ) . ')', $user_item_ids );
3091 }
3092
3093 $wpdb->query( $query );
3094 }
3095 }
3096
3097 /**
3098 * Get item types of course support for blocking. Default is lp_lesson
3099 *
3100 * @return array
3101 * @since 3.0.0
3102 */
3103 function learn_press_get_block_course_item_types() {
3104 return apply_filters( 'learn-press/block-course-item-types', array( LP_LESSON_CPT, LP_QUIZ_CPT ) );
3105 }
3106
3107 /**
3108 * Get post type of a post from cache.
3109 * If there is no data stored in cache then
3110 * get it from WP API.
3111 *
3112 * @param int|WP_Post $post
3113 *
3114 * @return string
3115 * @since 3.1.0
3116 */
3117 function learn_press_get_post_type( $post ) {
3118 $post_types = LP_Object_Cache::get( 'post-types', 'learn-press' );
3119
3120 if ( false === $post_types ) {
3121 $post_types = array();
3122 }
3123
3124 if ( is_object( $post ) ) {
3125 $post_id = $post->ID;
3126 } else {
3127 $post_id = absint( $post );
3128 }
3129
3130 if ( empty( $post_types[ $post_id ] ) ) {
3131 $post_type = get_post_type( $post_id );
3132 $post_types[ $post_id ] = $post_type;
3133 LP_Object_Cache::set( 'post-types', $post_types, 'learn-press' );
3134 } else {
3135 $post_type = $post_types[ $post_id ];
3136 }
3137
3138 return $post_type;
3139 }
3140
3141 /**
3142 * Add post type of a post into cache
3143 *
3144 * @param int|array $id
3145 * @param string $type
3146 *
3147 * @since 3.1.0
3148 */
3149 function learn_press_cache_add_post_type( $id, $type = '' ) {
3150 if ( false === ( $post_types = LP_Object_Cache::get( 'post-types', 'learn-press' ) ) ) {
3151 $post_types = array();
3152 }
3153
3154 if ( func_num_args() == 1 && is_array( $id ) ) {
3155 $post_types = $post_types + $id;
3156 } else {
3157 $post_types[ $id ] = $type;
3158 }
3159
3160 LP_Object_Cache::set( 'post-types', $post_types, 'learn-press' );
3161 }
3162
3163 function learn_press_has_option( $name ) {
3164 global $wpdb;
3165
3166 $query = $wpdb->prepare( "SELECT option_id FROM {$wpdb->options} WHERE option_name = %s", $name );
3167
3168 return $wpdb->get_var( $query ) > 0;
3169 }
3170
3171 /**
3172 * Update option to enable shuffle themes for ad.
3173 *
3174 * @since 3.2.1
3175 */
3176 function _learn_press_schedule_enable_shuffle_themes() {
3177 update_option( 'learn_press_ad_shuffle_themes', 'yes' );
3178 }
3179
3180 add_action( 'learn-press/schedule-enable-shuffle-themes', '_learn_press_schedule_enable_shuffle_themes' );
3181
3182 function learn_press_show_log() {
3183 if ( trim( LP_Request::get( 'show_log' ) ) === md5( AUTH_KEY ) ) {
3184 call_user_func_array( 'learn_press_debug', func_get_args() );
3185 }
3186 }
3187
3188 /**
3189 * @return array
3190 * @since 3.2.6
3191 */
3192 function learn_press_global_script_params() {
3193 $js = array(
3194 'ajax' => admin_url( 'admin-ajax.php' ),
3195 'plugin_url' => LP()->plugin_url(),
3196 'siteurl' => home_url(),
3197 'current_url' => learn_press_get_current_url(),
3198 'theme' => get_stylesheet(),
3199 'localize' => array(
3200 'button_ok' => __( 'OK', 'learnpress' ),
3201 'button_cancel' => __( 'Cancel', 'learnpress' ),
3202 'button_yes' => __( 'Yes', 'learnpress' ),
3203 'button_no' => __( 'No', 'learnpress' ),
3204 ),
3205 'root' => esc_url_raw( rest_url() ),
3206 'nonce' => wp_create_nonce( 'wp_rest' ),
3207 );
3208
3209 return $js;
3210 }
3211
3212 /**
3213 * Get url for setup cron job on server.
3214 *
3215 * @return string
3216 * @since 3.3.0
3217 */
3218 function learn_press_get_cron_url() {
3219 $nonce = get_option( 'learnpress_cron_url_nonce' );
3220
3221 if ( ! $nonce ) {
3222 $nonce = md5( microtime( true ) );
3223 update_option( 'learnpress_cron_url_nonce', $nonce );
3224 }
3225 $url = add_query_arg(
3226 array(
3227 'lp-ajax' => 'cron',
3228 'sid' => $nonce,
3229 ),
3230 get_home_url()
3231 );
3232
3233 return $url;
3234 }
3235
3236 /**
3237 * Get courses expired.
3238 *
3239 * @return array
3240 * @since 3.3.0
3241 */
3242 function learn_press_get_expired_courses() {
3243 global $wpdb;
3244
3245 $query = $wpdb->prepare(
3246 "
3247 SELECT X.*
3248 FROM(
3249 SELECT ui.*
3250 FROM {$wpdb->learnpress_user_items} ui
3251 LEFT JOIN {$wpdb->learnpress_user_items} uix
3252 ON ui.item_id = uix.item_id
3253 AND ui.user_id = uix.user_id
3254 AND ui.user_item_id < uix.user_item_id
3255 WHERE uix.user_item_id IS NULL
3256 ) X
3257 INNER JOIN {$wpdb->users} u ON u.ID = X.user_id
3258 INNER JOIN {$wpdb->posts} p ON p.ID = X.item_id
3259 WHERE X.item_type = %s
3260 AND X.status = %s
3261 #AND expiration_time_gmt <= UTC_TIMESTAMP()
3262 AND expiration_time <= UTC_TIMESTAMP()
3263 LIMIT 0, 10
3264 ",
3265 LP_COURSE_CPT,
3266 'enrolled'
3267 );
3268
3269 }
3270
3271 /**
3272 * Add new error log. Support message as an array|object.
3273 * Convert message to string if it is not a string.
3274 *
3275 * @param mixed $value
3276 *
3277 * @since 4.0.0
3278 */
3279 function learn_press_error_log( $value ) {
3280 if ( is_array( $value ) || is_object( $value ) ) {
3281 ob_start();
3282 print_r( $value );
3283 $value = ob_get_clean();
3284 }
3285
3286 error_log( $value );
3287 }
3288
3289 /**
3290 * Get status of global course for current user.
3291 *
3292 * @param int $user_id
3293 * @param int $course_id
3294 *
3295 * @return bool|string
3296 * @since 3.3.0
3297 * @editor tungnx
3298 * @modify 4.1.3 - comment - not use
3299 */
3300 /*function learn_press_user_course_status( $user_id = 0, $course_id = 0 ) {
3301 if ( ! $user = learn_press_get_user( $user_id ? $user_id : get_current_user_id() ) ) {
3302 return false;
3303 }
3304
3305 if ( ! $userCourse = $user->get_course_data( $course_id ) ) {
3306 return false;
3307 }
3308
3309 return $userCourse->get_status();
3310 }*/
3311
3312 /**
3313 * Return list types of questions that support answer options.
3314 *
3315 * @return array
3316 * @since 3.3.0
3317 */
3318 function learn_press_get_question_support_answer_options() {
3319 $questions = learn_press_get_question_support_feature( 'answer-options' );
3320
3321 return apply_filters( 'learn-press/questions-support-answer-options', $questions );
3322 }
3323
3324 /**
3325 * Return list types of question that support a feature.
3326 *
3327 * @param string $feature
3328 *
3329 * @return array
3330 * @since 3.3.0
3331 */
3332 function learn_press_get_question_support_feature( $feature ) {
3333 $questions = array();
3334 $types = LP_Global::get_object_supports( 'question' );
3335
3336 if ( $types ) {
3337 foreach ( $types as $type => $features ) {
3338 if ( array_key_exists( $feature, $features ) ) {
3339 $questions[] = $type;
3340 }
3341 }
3342 }
3343
3344 return $questions;
3345 }
3346
3347 /**
3348 * Helper function to output html for rendering a 'circle progress bar'
3349 *
3350 * @param int $percent
3351 * @param int $width
3352 * @param int $border
3353 * @param string $color
3354 *
3355 * @since 3.3.0
3356 */
3357 function learn_press_circle_progress_html( $percent = 0, $width = 32, $border = 4, $color = '' ) {
3358 $radius = $width / 2;
3359 $r = ( $width - $border ) / 2;
3360 $circumference = $r * 2 * pi();
3361 $offset = $circumference - $percent / 100 * $circumference;
3362
3363 printf(
3364 '<svg class="circle-progress-bar" width="%d" height="%d">
3365 <circle class="circle-progress-bar__circle"
3366 stroke="%s"
3367 stroke-width="%d"
3368 style="stroke-dasharray:%s %s; stroke-dashoffset:%s;"
3369 fill="transparent"
3370 r="%d" cx="%d" cy="%d"></circle>
3371 </svg>',
3372 $width,
3373 $width,
3374 $color,
3375 $border,
3376 $circumference,
3377 $circumference,
3378 $offset,
3379 $r,
3380 $radius,
3381 $radius
3382 );
3383 }
3384
3385 function learn_press_is_page( $page_name ) {
3386 $page_id = learn_press_get_page_id( $page_name );
3387
3388 return $page_id && is_page( $page_id );
3389 }
3390
3391 /**
3392 * Get end-date from start date with a duration.
3393 *
3394 * @param string|int $duration
3395 * @param string|int $start
3396 *
3397 * @return false|string
3398 * @since 3.x.x
3399 */
3400 function learn_press_date_end_from( $duration, $start = '' ) {
3401 $format = 'Y-m-d H:i:s';
3402
3403 if ( ! $start ) {
3404 $start = time();
3405 } elseif ( ! is_numeric( $start ) ) {
3406 $start = strtotime( $start );
3407 }
3408
3409 // is LP duration format, e.g: 10 weeks
3410 if ( preg_match( '/^[0-9]+ [a-z]+$/', $duration ) ) {
3411 $duration = ( new LP_Duration( $duration ) )->get();
3412 } elseif ( ! is_numeric( $duration ) ) {
3413 // 10 days 5 hours ...
3414 $duration = strtotime( $duration, 0 );
3415 }
3416
3417 return date( $format, $start + $duration );
3418 }
3419
3420 function learn_press_date_diff( $from, $to ) {
3421
3422 }
3423
3424 function learn_press_cookie_get( $name, $namespace = 'LP' ) {
3425 if ( $namespace ) {
3426 $cookie = ! empty( $_COOKIE[ $namespace ] ) ? (array) json_decode( LP_Helper::sanitize_params_submitted( stripslashes( $_COOKIE[ $namespace ] ), 'html' ) ) : array();
3427 } else {
3428 $cookie = $_COOKIE;
3429 }
3430
3431 return $cookie[ $name ] ?? null;
3432 }
3433
3434 /**
3435 * Get list of levels support in course.
3436 *
3437 * @return array
3438 * @since 3.x.x
3439 * @editor tungnx
3440 * @reason comment - not use
3441 */
3442 /*
3443 function learn_press_default_course_levels() {
3444 $levels = array(
3445 'beginner' => __( 'Beginner', 'learnpress' ),
3446 'intermediate' => __( 'Intermediate', 'learnpress' ),
3447 'expert' => __( 'Expert', 'learnpress' ),
3448 '' => __( 'All levels', 'learnpress' ),
3449 );
3450
3451 return apply_filters( 'learn-press/default-course-levels', $levels );
3452 }*/
3453
3454 /**
3455 * Get default methods to evaluate course results.
3456 *
3457 * @param string $return - Optional. 'keys' will return keys instead of all.
3458 *
3459 * @return array
3460 * @since 3.x.x
3461 */
3462 function learn_press_course_evaluation_methods( $postid, $return = '', $final_quizz_passing = '' ) {
3463 $course_tip = '<span class="learn-press-tip">%s</span>';
3464 $final_quiz_btn = '<a href="#" class="lp-metabox-get-final-quiz" data-postid="' . $postid . '" data-loading="' . esc_attr__(
3465 'Loading...',
3466 'learnpress'
3467 ) . '">' . esc_html__( 'Get Passing Grade', 'learnpress' ) . '</a>';
3468
3469 $course_desc = array(
3470 'evaluate_lesson' => sprintf(
3471 '<p>%s<br/>%s</p>',
3472 __( 'Evaluate by the number of lessons completed per total number of lessons.', 'learnpress' ),
3473 __( 'E.g: Course has 10 lessons and user completed 5 lessons then the result = 5/10 (50.%)', 'learnpress' )
3474 ),
3475 'evaluate_final_quiz' => __(
3476 'Evaluate by result of final quiz in the course. You have to add a quiz to the end of the course.',
3477 'learnpress'
3478 ),
3479 'evaluate_quiz' => sprintf(
3480 '<p>%s<br/>%s</p>',
3481 __( 'Evaluate by the number of quizzes passed per total number of quizzes.', 'learnpress' ),
3482 __(
3483 'E.g: The course has 10 quizzes and the user passed 5 quizzes then the result = 5/10 (50%).',
3484 'learnpress'
3485 )
3486 ),
3487 'evaluate_questions' => sprintf(
3488 '<p>%s<br/>%s</p>',
3489 __( 'Evaluate by total number of correct answers per total number of questions.', 'learnpress' ),
3490 __(
3491 'E.g: Course has 10 questions. User correct 5 questions. Result is 5/10 (50%).',
3492 'learnpress'
3493 )
3494 ),
3495 'evaluate_mark' => __( 'Evaluate by total score achieved per total score of the questions.', 'learnpress' ),
3496 );
3497
3498 $methods = apply_filters(
3499 'learnpress/course-evaluation/methods',
3500 array(
3501 'evaluate_lesson' => __(
3502 'Evaluate via lessons',
3503 'learnpress'
3504 ) . learn_press_quick_tip( $course_desc['evaluate_lesson'], false ),
3505 'evaluate_final_quiz' => __( 'Evaluate via results of the final quiz', 'learnpress' ) . sprintf(
3506 $course_tip,
3507 $course_desc['evaluate_final_quiz']
3508 ) . $final_quiz_btn . $final_quizz_passing,
3509 'evaluate_quiz' => __( 'Evaluate via quizzes passed', 'learnpress' ) . sprintf(
3510 $course_tip,
3511 $course_desc['evaluate_quiz']
3512 ),
3513 'evaluate_questions' => __( 'Evaluate via questions', 'learnpress' ) . sprintf(
3514 $course_tip,
3515 $course_desc['evaluate_questions']
3516 ),
3517 'evaluate_mark' => __( 'Evaluate via mark', 'learnpress' ) . sprintf(
3518 $course_tip,
3519 $course_desc['evaluate_mark']
3520 ),
3521 )
3522 );
3523
3524 return apply_filters(
3525 'learn-press/course-evaluation-methods',
3526 $return === 'keys' ? array_keys( $methods ) : $methods,
3527 $return
3528 );
3529 }
3530
3531 /**
3532 * Wrap WP Core function current_time with mysql format.
3533 *
3534 * @param bool $gmt
3535 *
3536 * @return int|string
3537 * @since 4.0.0
3538 * @editor tungnx
3539 * @modify 4.1.4.1 - comment - not use
3540 */
3541 /*function learn_press_mysql_time( $gmt = true ) {
3542 return current_time( 'mysql', $gmt );
3543 }*/
3544
3545 /**
3546 * Wrap WP Core function current_time with timestamp format.
3547 *
3548 * @param bool $gmt
3549 *
3550 * @return int|string
3551 * @since 4.0.0
3552 */
3553 function learn_press_timestamp( $gmt = true ) {
3554 return current_time( 'timestamp', $gmt );
3555 }
3556
3557 /**
3558 * Convert time from GMT to local.
3559 *
3560 * @param string|int|LP_Datetime $gmt_time
3561 * @param string $format
3562 *
3563 * @return false|int|string
3564 * @since 4.0.0
3565 */
3566 function learn_press_time_from_gmt( $gmt_time, $format = 'Y-m-d H:i:s' ) {
3567 if ( is_string( $gmt_time ) ) {
3568 $gmt_time = strtotime( $gmt_time );
3569 } elseif ( $gmt_time instanceof LP_Datetime ) {
3570 $gmt_time = strtotime( $gmt_time . '' );
3571 }
3572
3573 $current_time = $gmt_time + get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
3574
3575 if ( $format ) {
3576 return date( $format, $current_time );
3577 }
3578
3579 return $current_time;
3580 }
3581
3582 /**
3583 * Count all users has enrolled courses of an instructor.
3584 *
3585 * @param int $instructor_id . Author of course
3586 *
3587 SELECT COUNT(DISTINCT (user_id)) AS total
3588 FROM wp_learnpress_user_items
3589 WHERE 1 = 1
3590 AND item_type = 'lp_course'
3591 AND item_id IN (
3592 SELECT ID
3593 FROM wp_posts
3594 WHERE post_author = 1
3595 AND post_type = 'lp_course'
3596 AND post_status = 'publish'
3597 );
3598 *
3599 * @return int
3600 * @since 4.0.0
3601 * @editor tungnx
3602 * @version 1.0.1
3603 * @deprecated 4.1.6 replace to "get_statistic_info" function
3604 */
3605 //function learn_press_count_instructor_users( int $instructor_id = 0 ): int {
3606 // try {
3607 // $filter_course = new LP_Course_Filter();
3608 // $filter_course->only_fields = array( 'ID' );
3609 // $filter_course->post_author = $instructor_id;
3610 // $filter_course->post_status = 'publish';
3611 // $filter_course->return_string_query = true;
3612 // $query_courses_str = LP_Course_DB::getInstance()->get_courses( $filter_course );
3613 //
3614 // $filter = new LP_User_Items_Filter();
3615 // $filter->only_fields = array( 'DISTINCT (ui.user_id)' );
3616 // $filter->field_count = 'DISTINCT (ui.user_id)';
3617 // $filter->where[] = "AND item_id IN ({$query_courses_str})";
3618 // $filter->query_count = true;
3619 //
3620 // return LP_User_Item_Course::get_user_courses( $filter );
3621 // //return LP_User_Items_DB::getInstance()->get_user_courses( $filter );
3622 // } catch ( Throwable $e ) {
3623 // error_log( __FUNCTION__ . ': ' . $e->getMessage() );
3624 //
3625 // return 0;
3626 // }
3627 //
3628 // /*$curd = new LP_User_CURD();
3629 // $own_courses = $curd->query_own_courses( $instructor_id );
3630 // $course_ids = $own_courses->get_items();*/
3631 //
3632 // /*
3633 // global $wpdb;
3634 // $filter = new LP_Course_Filter();
3635 // $filter->post_author = $instructor_id;
3636 // $filter->limit = -1;
3637 // $courses = LP_Course::get_courses( $filter );
3638 // $course_ids = LP_Course::get_course_ids( $courses );
3639 //
3640 // if ( ! empty( $course_ids ) ) {
3641 // $query = $wpdb->prepare(
3642 // "
3643 // SELECT COUNT(user_id)
3644 // FROM (
3645 // SELECT item_id, user_id
3646 // FROM {$wpdb->learnpress_user_items}
3647 // WHERE item_type = %s
3648 // GROUP BY item_id, user_id
3649 // HAVING item_id IN(" . join( ',', $course_ids ) . ')
3650 // ) X
3651 // GROUP BY item_id
3652 // ',
3653 // LP_COURSE_CPT
3654 // );
3655 //
3656 // $rows = $wpdb->get_col( $query );
3657 //
3658 // if ( $rows ) {
3659 // return array_sum( $rows );
3660 // }
3661 // }
3662 //
3663 // return 0;*/
3664 //}
3665
3666 /**
3667 * Get max retrying quiz allowed.
3668 *
3669 * @param int $quiz_id
3670 * @param int $course_id
3671 *
3672 * @return int
3673 * @since 4.0.0
3674 */
3675 function learn_press_get_quiz_max_retrying( $quiz_id = 0, $course_id = 0 ) {
3676 return apply_filters( 'learn-press/max-retry-quiz-allowed', 1, $quiz_id, $course_id );
3677 }
3678
3679 /**
3680 * Get max retrying course allowed.
3681 *
3682 * @param int $course_id
3683 *
3684 * @return int
3685 * @since 4.0.0
3686 */
3687 function learn_press_get_course_max_retrying( $course_id ) {
3688 return apply_filters( 'learn-press/max-retry-course-allowed', 1, $course_id );
3689 }
3690
3691 /**
3692 * Get slug for status of course/lesson/quiz if user
3693 * completed/finished and graduation is failed.
3694 *
3695 * @param string $type
3696 *
3697 * @return string
3698 * @since 4.0.0
3699 */
3700 function learn_press_user_item_failed_slug( $type = '' ) {
3701 return apply_filters( 'learn-press/user-item-failed-slug', 'failed', $type );
3702 }
3703
3704 /**
3705 * Get slug for status of course/lesson/quiz if user
3706 * completed/finished and graduation is passed.
3707 *
3708 * @param string $type
3709 *
3710 * @return string
3711 * @since 4.0.0
3712 */
3713 function learn_press_user_item_passed_slug( $type = '' ) {
3714 return apply_filters( 'learn-press/user-item-passed-slug', 'passed', $type );
3715 }
3716
3717 /**
3718 * Get slug for status of course/lesson/quiz if user
3719 * completed/finished and graduation is passed.
3720 *
3721 * @param string $type
3722 *
3723 * @return string
3724 * @since 4.0.0
3725 */
3726 function learn_press_user_item_in_progress_slug( $type = '' ) {
3727 return apply_filters( 'learn-press/user-item-in-progress-slug', 'in-progress', $type );
3728 }
3729
3730 /**
3731 * Get slug for status of course/lesson/quiz if user
3732 * completed/finished and result is under-evaluation
3733 *
3734 * @param string $item - Optional. Type of item
3735 *
3736 * @return string
3737 * @since 4.0.0
3738 */
3739 function learn_press_user_item_under_evaluation_slug( $item = '' ) {
3740 return apply_filters( 'learn-press/user-item-under-evaluation-slug', 'in-progress', $item );
3741 }
3742
3743 function learn_press_is_enrolled_slug( $slug ) {
3744 return in_array(
3745 $slug,
3746 array(
3747 'in-progress',
3748 'enrolled',
3749 )
3750 );
3751 }
3752
3753 /**
3754 * @return array
3755 * @since 4.0.0
3756 * @editor tungnx
3757 * @modify 4.1.3 - comment - not use
3758 */
3759 function learn_press_course_enrolled_slugs(): array {
3760 _deprecated_function( __FUNCTION__, '4.1.3' );
3761 return apply_filters(
3762 'learn-press/course-enrolled-slugs',
3763 array(
3764 learn_press_user_item_passed_slug(),
3765 learn_press_user_item_failed_slug(),
3766 'in-progress',
3767 'enrolled',
3768 'finished', // deprecated
3769 )
3770 );
3771 }
3772
3773 /**
3774 * @return array
3775 * @since 4.0.0
3776 */
3777 function lp_item_course_class( $class = array() ) {
3778 $classes = array_merge(
3779 $class,
3780 array( 'learn-press-courses' )
3781 );
3782 echo 'class="' . esc_attr( implode( ' ', apply_filters( 'lp_item_course_class', $classes ) ) ) . '"';
3783 }
3784
3785 //require_once dirname( __FILE__ ) . '/lp-custom-hooks.php';
3786
3787
3788 /**
3789 * Disable auto update
3790 *
3791 * @param $update
3792 * @param $item
3793 *
3794 * @return false
3795 * @author hungkv
3796 */
3797 /*function learnpress_disable_auto_update( $update, $item ) {
3798 $plugins = array( // Plugins to auto-update
3799 'learnpress',
3800 );
3801 // Auto-update specified plugins
3802 if ( in_array( $item->slug, $plugins ) ) {
3803 return false;
3804 }
3805 }
3806 add_filter( 'auto_update_plugin', 'learnpress_disable_auto_update', 10, 2 );*/
3807
3808 add_action(
3809 'in_plugin_update_message-learnpress/learnpress.php',
3810 function ( $plugin_data ) {
3811 version_update_warning( LEARNPRESS_VERSION, $plugin_data['new_version'] );
3812 }
3813 );
3814 /**
3815 * Custom message warning have new version
3816 *
3817 * @param $current_version
3818 * @param $new_version
3819 * @author hungkv
3820 */
3821 function version_update_warning( $current_version, $new_version ) {
3822 $current_version_minor_part = explode( '.', $current_version )[1];
3823 $new_version_minor_part = explode( '.', $new_version )[1];
3824 if ( $current_version_minor_part === $new_version_minor_part ) {
3825 return;
3826 }
3827
3828 $info = get_plugin_data( LP_PLUGIN_FILE );
3829 ?>
3830 <hr class="lp-update--warning__separator"/>
3831 <div class="lp-update--warning">
3832 <div>
3833 <div class="lp-update-warning__title">
3834 <?php echo esc_html__( 'Heads up, Please backup before upgrade!', 'learnpress' ); ?>
3835 </div>
3836 <div class="lp-update-warning__message">
3837 <?php echo esc_html__( 'The latest update includes some substantial changes across different areas of the plugin. We highly recommend you backup your site before upgrading, and make sure you first update in a staging environment', 'learnpress' ); ?>
3838 <?php echo esc_html__( 'Learners require WordPress version ' . $info['Requires at least'] . ' or higher.', 'learnpress' ); ?>
3839 </div>
3840 </div>
3841 </div>
3842
3843 <?php
3844 }
3845
3846 // If profile content don't have shortcode profile.
3847 function lp_add_shortcode_profile() {
3848 global $post;
3849
3850 if ( learn_press_is_profile() && is_object( $post ) ) {
3851 if ( ! has_shortcode( $post->post_content, 'learn_press_profile' ) ) {
3852 $post->post_content .= '<!-- wp:shortcode -->[' . apply_filters( 'learn-press/shortcode/profile/tag', 'learn_press_profile' ) . ']<!-- /wp:shortcode -->';
3853 }
3854
3855 wp_update_post( $post );
3856 }
3857 }
3858
3859 add_action( 'template_redirect', 'lp_add_shortcode_profile' );
3860
3861 /**
3862 * If Elementor Pro set Theme builder type "Archive", will not show content on page "Archive course"
3863 *
3864 * @editor tungnx
3865 * @author nhamdv
3866 *
3867 * @since 4.0.6
3868 * @version 1.0.1
3869 */
3870 add_filter(
3871 'elementor/theme/get_location_templates/template_id',
3872 function( $theme_template_id ) {
3873 $elementor_template_type = get_post_meta( $theme_template_id, '_elementor_template_type', true );
3874
3875 if ( in_array( $elementor_template_type, array( 'archive' ) ) ) {
3876 if ( LP_PAGE_COURSES === LP_Page_Controller::page_current() && class_exists( 'ElementorPro\Modules\ThemeBuilder\Conditions\Archive' ) ) {
3877 return false;
3878 }
3879 }
3880
3881 return $theme_template_id;
3882 }
3883 );
3884