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

class-lp-helper.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.3.9, at inc/class-lp-helper.php

625 lines 15.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class LP_Helper
5 */
6
7 use LearnPress\Helpers\Template;
8
9 defined( 'ABSPATH' ) || exit;
10
11 class LP_Helper {
12
13 /**
14 * Wrap function unserialize to fix issues with UTF-8 chars when encoding/decoding
15 * of serialize function.
16 *
17 * @param string $string
18 *
19 * @return mixed
20 */
21 public static function maybe_unserialize( $string ) {
22 if ( is_string( $string ) ) {
23
24 $unserialized = maybe_unserialize( $string );
25 if ( ! $unserialized && strlen( $string ) ) {
26 $string = preg_replace_callback(
27 '!s:(\d+):"(.*?)";!s',
28 array( __CLASS__, '_unserialize_replace_callback' ),
29 $string
30 );
31
32 $unserialized = maybe_unserialize( $string );
33 }
34
35 $string = $unserialized;
36 }
37
38 return $string;
39 }
40
41 public static function _unserialize_replace_callback( $m ) {
42 $len = strlen( $m[2] );
43 $result = "s:$len:\"{$m[2]}\";";
44
45 return $result;
46 }
47
48 /**
49 * Shuffle array and keep the keys
50 *
51 * @param array $array
52 *
53 * @return bool
54 */
55 public static function shuffle_assoc( &$array ) {
56 $keys = array_keys( $array );
57 shuffle( $keys );
58 $new = array();
59 foreach ( $keys as $key ) {
60 $new[ $key ] = $array[ $key ];
61 }
62 $array = $new;
63
64 return true;
65 }
66
67 /**
68 * MD5 an array.
69 *
70 * @param array $array
71 *
72 * @return string
73 */
74 public static function array_to_md5( $array ) {
75 settype( $array, 'array' );
76 ksort( $array );
77
78 return md5( serialize( $array ) );
79 }
80
81 /**
82 * Load posts from database into cache by ids
83 *
84 * @param array|int $ids
85 *
86 * @Todo: tungnx - need to review code - addon h5p v4.0.3 still use
87 * @deprecated 4.1.6.9
88 */
89 public static function cache_posts( $ids ) {
90 //_deprecated_function( __FUNCTION__, '4.1.6.9' );
91 }
92
93 /**
94 * Merge two or more classes into one.
95 *
96 * @return array
97 */
98 public static function merge_class() {
99 if ( func_num_args() == 1 ) {
100 return func_get_arg( 0 );
101 } elseif ( func_num_args() == 0 ) {
102 return null;
103 }
104
105 $classes = array();
106 foreach ( func_get_args() as $class ) {
107 if ( is_string( $class ) ) {
108 $cls = explode( ' ', $class );
109 $classes = array_merge( $classes, $cls );
110 } else {
111 $classes = array_merge( $classes, $class );
112 }
113 }
114
115 $classes = array_filter( $classes );
116 $classes = array_unique( $classes );
117
118 return $classes;
119 }
120
121 /**
122 * Sanitize order statuses.
123 * Add prefix lp- into each status if it is not exists.
124 *
125 * @param $statuses
126 *
127 * @return array|mixed
128 */
129 public static function sanitize_order_status( &$statuses ) {
130 if ( is_array( $statuses ) ) {
131 foreach ( $statuses as $k => $status ) {
132 if ( false === strpos( $status, 'lp-' ) ) {
133 $statuses[ $k ] = "lp-{$status}";
134 }
135 }
136 } else {
137 $statuses = preg_split( '#\s+#', $statuses );
138 self::sanitize_order_status( $statuses );
139 if ( sizeof( $statuses ) == 1 ) {
140 $statuses = reset( $statuses );
141 }
142 }
143
144 return $statuses;
145 }
146
147 /**
148 * Merge two arrays recursive.
149 *
150 * @param array $array1
151 * @param array $array2
152 *
153 * @return array
154 */
155 public static function array_merge_recursive( &$array1, &$array2 ) {
156 $merged = $array1;
157
158 if ( is_array( $array1 ) && is_array( $array2 ) ) {
159 foreach ( $array2 as $key => & $value ) {
160 if ( is_array( $value ) && isset( $merged[ $key ] ) && is_array( $merged[ $key ] ) ) {
161 $merged[ $key ] = self::array_merge_recursive( $merged[ $key ], $value );
162 } elseif ( is_numeric( $key ) ) {
163 if ( ! in_array( $value, $merged ) ) {
164 $merged[] = $value;
165 }
166 } else {
167 $merged[ $key ] = $value;
168 }
169 }
170 } elseif ( is_array( $array2 ) ) {
171 $merged = $array2;
172 }
173
174 return $merged;
175 }
176
177 /**
178 * Encode the object to json format.
179 * Replace number, "false", "true" in couple of quotes with
180 * original value.
181 * Example:
182 * Input: {
183 * number: "1234",
184 * true_value: "true",
185 * false_value: "false"
186 * }
187 * Output: {
188 * number: 1234,
189 * true_value: true,
190 * false_value: false
191 * }
192 *
193 * @param array $data
194 *
195 * @return false|mixed|string
196 */
197 public static function json_encode( $data ) {
198 $data = wp_json_encode( $data );
199 $data = preg_replace_callback(
200 '~:"(([0-9]+)([.,]?)([0-9]?)|true|false)"~',
201 array(
202 __CLASS__,
203 '_valid_json_value',
204 ),
205 $data
206 );
207
208 return $data;
209 }
210
211 /**
212 * Callback function for json_encode method "json_encode".
213 *
214 * @param array $m
215 *
216 * @return string
217 */
218 public static function _valid_json_value( $m ) {
219 return str_replace( array( ':"', '"' ), array( ':', '' ), $m[0] );
220 }
221
222 /**
223 * Create LP static page.
224 *
225 * @param array $args
226 * @param string $key_option
227 *
228 * @return bool|int|WP_Error
229 */
230 public static function create_page( array $args, string $key_option ) {
231 $page_id = 0;
232
233 try {
234 if ( ! isset( $args['post_title'] ) ) {
235 throw new Exception( __( 'Missing post title', 'learnpress' ) );
236 }
237
238 if ( preg_match( '#^learn_press_single_instructor_page_id.*#', $key_option ) ) {
239 $args['post_content'] = '<!-- wp:shortcode -->[learn_press_single_instructor]<!-- /wp:shortcode -->';
240 } elseif ( preg_match( '#^learn_press_instructors_page_id.*#', $key_option ) ) {
241 $args['post_content'] = '<!-- wp:shortcode -->[learn_press_instructors]<!-- /wp:shortcode -->';
242 } elseif ( preg_match( '#^learn_press_profile_page_id.*#', $key_option ) ) {
243 $args['post_content'] = '<!-- wp:shortcode -->[learn_press_profile]<!-- /wp:shortcode -->';
244 }
245
246 $args = array_merge(
247 [
248 'post_title' => '',
249 'post_name' => '',
250 'post_status' => 'publish',
251 'post_type' => 'page',
252 'comment_status' => 'closed',
253 'post_content' => '',
254 'post_author' => get_current_user_id(),
255 ],
256 $args
257 );
258
259 $page_id = wp_insert_post( $args );
260 if ( ! $page_id ) {
261 return false;
262 }
263
264 update_option( $key_option, $page_id );
265 $lp_settings_cache = new LP_Settings_Cache( true );
266 $lp_settings_cache->clean_lp_settings();
267 } catch ( Throwable $e ) {
268 error_log( __METHOD__ . ': ' . $e->getMessage() );
269 }
270
271 return $page_id;
272 }
273
274 /**
275 * Get the current url
276 *
277 * @return string
278 * @since 3.2.6.8
279 * @author tungnx
280 */
281 public static function getUrlCurrent(): string {
282 $schema = is_ssl() ? 'https://' : 'http://';
283 $http_host = LP_Helper::sanitize_params_submitted( urldecode( $_SERVER['HTTP_HOST'] ?? '' ) );
284 $request_uri = LP_Helper::sanitize_params_submitted( urldecode( $_SERVER['REQUEST_URI'] ?? '' ) );
285 //$http_host = LP_Helper::sanitize_params_submitted( filter_input( INPUT_SERVER, 'HTTP_HOST' ) ?? '' );
286 //$request_uri = LP_Helper::sanitize_params_submitted( filter_input( INPUT_SERVER, 'REQUEST_URI' ) ?? '' );
287
288 return untrailingslashit( $schema . $http_host . $request_uri );
289 }
290
291 /**
292 * Check request is rest api
293 *
294 * @return bool
295 * @author tungnx
296 * @since 4.1.6.6
297 */
298 public static function isRestApiLP(): bool {
299 $restPrefix = '/' . rest_get_url_prefix();
300 return strpos( self::getUrlCurrent(), $restPrefix . '/lp/' ) || strpos( self::getUrlCurrent(), $restPrefix . '/learnpress/' );
301 }
302
303 /**
304 * Sanitize string and array
305 *
306 * @param array|string $value
307 * @param string $type_content
308 * @param bool $unslash Set it is false when you don’t want to remove slashes (unslash) from $value
309 * for example, in cases involving LaTeX math syntax.
310 * @return array|string
311 * @since 3.2.7.1
312 * @author tungnx
313 */
314 public static function sanitize_params_submitted( $value, string $type_content = 'text', $unslash = true ) {
315 $value = $unslash ? wp_unslash( $value ) : $value;
316
317 if ( is_string( $value ) ) {
318 switch ( $type_content ) {
319 case 'html':
320 $value = Template::sanitize_html_content( $value );
321 break;
322 case 'textarea':
323 $value = sanitize_textarea_field( $value );
324 break;
325 case 'key':
326 $value = sanitize_key( $value );
327 break;
328 case 'int':
329 $value = (int) $value;
330 break;
331 case 'float':
332 $value = (float) $value;
333 break;
334 default:
335 if ( is_callable( $type_content ) ) {
336 $value = call_user_func( $type_content, $value );
337 } else {
338 $value = sanitize_text_field( $value );
339 }
340 }
341 } elseif ( is_array( $value ) ) {
342 foreach ( $value as $k => $v ) {
343 unset( $value[ $k ] );
344 $value[ sanitize_text_field( $k ) ] = self::sanitize_params_submitted( $v, $type_content, $unslash );
345 }
346 }
347
348 return $value;
349 }
350
351 public static function db_format_array( array $arr, string $format = '%d' ): string {
352 $arr_formatted = array_fill( 0, sizeof( $arr ), $format );
353
354 return join( ',', $arr_formatted );
355 }
356
357 /**
358 * Calculate percent of progress rows on db
359 *
360 * @param int $offset .
361 * @param int $limit .
362 * @param int $total_row .
363 *
364 * @return float
365 */
366 public static function progress_percent( int $offset, int $limit, int $total_row ): float {
367 if ( $total_row <= 0 ) {
368 return 0;
369 }
370
371 $percent = ( $offset + $limit ) * 100 / $total_row;
372
373 $percent = min( $percent, 100 );
374
375 return floatval( number_format( $percent, 2 ) );
376 }
377
378 /**
379 * Convert array to string
380 * Ex: array("publish", "pending") to post_status IN(%s, %s)
381 *
382 * @param array $arr
383 *
384 * @return string
385 */
386 public static function format_query_IN( array $arr ): string {
387 $format = array_fill( 0, count( $arr ), '%s' );
388
389 return join( ',', $format );
390 }
391
392 /**
393 * Get link lp checkout page
394 * without cache - because some cache(redis) will cache page with user anonymous
395 */
396 public static function get_link_no_cache( string $link ): string {
397 return esc_url_raw( add_query_arg( 'no-cache', uniqid(), $link ) );
398 }
399
400 /**
401 * Check string is json
402 *
403 * @param string $str
404 * @param null $associative
405 *
406 * @return mixed
407 * @throws Exception
408 * @since 4.1.6.4
409 * @version 1.0.1
410 */
411 public static function json_decode( string $str, $associative = null ) {
412 $obj = json_decode( $str, $associative );
413 if ( json_last_error() !== JSON_ERROR_NONE ) {
414 throw new Exception( 'JSON decode: ' . json_last_error_msg() );
415 }
416
417 return $obj;
418 }
419
420 /**
421 * Handle permalink structure for LP
422 *
423 * @return string
424 * @since 4.2.2
425 * @version 1.0.4
426 */
427 public static function handle_lp_permalink_structure( $post_link, $post ) {
428 if ( false === strpos( $post_link, '%' ) ) {
429 return $post_link;
430 }
431
432 $find = [];
433 $replace = [];
434 if ( ! empty( $post->post_date_gmt ) ) {
435 $find = array(
436 '%year%',
437 '%monthnum%',
438 '%day%',
439 '%hour%',
440 '%minute%',
441 '%second%',
442 '%post_id%',
443 );
444
445 $time = strtotime( $post->post_date_gmt );
446
447 $replace = array(
448 date_i18n( 'Y', $time ),
449 date_i18n( 'm', $time ),
450 date_i18n( 'd', $time ),
451 date_i18n( 'H', $time ),
452 date_i18n( 'i', $time ),
453 date_i18n( 's', $time ),
454 $post->ID,
455 );
456 }
457
458 if ( strpos( $post_link, '%course_category%' ) && get_post_type( $post ) === LP_COURSE_CPT ) {
459 // Get the custom taxonomy terms in use by this post
460 $terms = get_the_terms( $post->ID, 'course_category' );
461
462 if ( ! empty( $terms ) ) {
463 $terms = wp_list_sort( $terms, 'term_id' );
464 // order by IDF
465 $category_object = apply_filters(
466 'learn_press_course_post_type_link_course_category',
467 $terms[0],
468 $terms,
469 $post
470 );
471 $category_object = get_term( $category_object, 'course_category' );
472 if ( ! $category_object instanceof WP_Term ) {
473 return $post_link;
474 }
475
476 $course_category = $category_object->slug;
477 $parent = $category_object->parent;
478 if ( $parent ) {
479 $ancestors = get_ancestors( $category_object->term_id, 'course_category' );
480 foreach ( $ancestors as $ancestor ) {
481 $ancestor_object = get_term( $ancestor, 'course_category' );
482 if ( $ancestor_object instanceof WP_Term ) {
483 $course_category = $ancestor_object->slug . '/' . $course_category;
484 }
485 }
486 }
487 } else {
488 // If no terms are assigned to this post, use a string instead (can't leave the placeholder there)
489 $course_category = _x( 'uncategorized', 'slug', 'learnpress' );
490 }
491
492 $find[] = '%course_category%';
493 $replace[] = urldecode( $course_category );
494 }
495
496 return apply_filters(
497 'learn-press/single-course/permalink',
498 str_replace( $find, $replace, $post_link ),
499 $post
500 );
501 }
502
503 /**
504 * Print variable script inline script tag.
505 * If $name_variable_script is empty,
506 * the script will be print as json with set $tag_args['type'] = application/json.
507 *
508 * @param string $name_variable_script
509 * @param array $data
510 * @param array $tag_args as ['type' => 'text/javascript', 'id' => '']
511 *
512 * @return void
513 * @version 1.0.1
514 * @since 4.2.5.5
515 */
516 public static function print_inline_script_tag( string $name_variable_script, array $data, array $tag_args = [] ) {
517 foreach ( $data as $key => $value ) {
518 if ( ! is_scalar( $value ) ) {
519 continue;
520 }
521
522 $data[ $key ] = html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8' );
523 }
524
525 $data_json = wp_json_encode( $data );
526 $script = '';
527 if ( ! empty( $name_variable_script ) ) {
528 $script = "var {$name_variable_script} = {$data_json};";
529 } elseif ( isset( $tag_args['type'] ) && $tag_args['type'] === 'application/json' ) {
530 $script = $data_json;
531 }
532 wp_print_inline_script_tag( $script, $tag_args );
533 }
534
535 /**
536 * Get translation string single/plural
537 *
538 * @param float $number
539 * @param string $string_value
540 * @param bool $include_number
541 *
542 * @return string
543 * @since 4.2.7.4
544 * @version 1.0.0
545 */
546 public static function get_i18n_string_plural( float $number, string $string_value = '', bool $include_number = true ): string {
547 switch ( $string_value ) {
548 case LP_COURSE_CPT:
549 $plural = sprintf(
550 _n( 'Course', 'Courses', $number, 'learnpress' ),
551 $number
552 );
553 break;
554 case LP_LESSON_CPT:
555 $plural = sprintf(
556 _n( 'Lesson', 'Lessons', $number, 'learnpress' ),
557 $number
558 );
559 break;
560 case LP_QUIZ_CPT:
561 $plural = sprintf(
562 _n( 'Quiz', 'Quizzes', $number, 'learnpress' ),
563 $number
564 );
565 break;
566 case LP_QUESTION_CPT:
567 $plural = sprintf(
568 _n( 'Question', 'Questions', $number, 'learnpress' ),
569 $number
570 );
571 break;
572 case 'lp_assignment':
573 $plural = sprintf(
574 _n( 'Assignment', 'Assignments', $number, 'learnpress' ),
575 $number
576 );
577 break;
578 case 'lp_h5p':
579 $plural = sprintf(
580 _n( 'H5P', 'H5Ps', $number, 'learnpress' ),
581 $number
582 );
583 break;
584 default:
585 $plural = $string_value;
586 break;
587 }
588
589 if ( $include_number ) {
590 $plural = sprintf( '%s %s', $number, $plural );
591 }
592
593 return apply_filters( 'learn-press/i18n/plural', $plural, $number, $string_value, $include_number );
594 }
595
596 /**
597 * Get client ip address
598 *
599 * @return mixed|string
600 * @since 4.2.7.9
601 * @version 1.0.0
602 */
603 public static function get_client_ip(): string {
604 $ipaddress = 'ip-unknown';
605 if ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
606 $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
607 } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
608 $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
609 } elseif ( isset( $_SERVER['HTTP_X_FORWARDED'] ) ) {
610 $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
611 } elseif ( isset( $_SERVER['HTTP_FORWARDED_FOR'] ) ) {
612 $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
613 } elseif ( isset( $_SERVER['HTTP_FORWARDED'] ) ) {
614 $ipaddress = $_SERVER['HTTP_FORWARDED'];
615 } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
616 $ipaddress = $_SERVER['REMOTE_ADDR'];
617 }
618
619 $ipaddress = (string) $ipaddress;
620 $ipaddress = 'gip-' . $ipaddress;
621
622 return $ipaddress;
623 }
624 }
625