PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.7.7
Tutor LMS – eLearning and online course solution v2.7.7
4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / includes / tutor-general-functions.php
tutor / includes Last commit date
theme-compatibility 4 years ago tinymce_translate.php 4 years ago translate-text.php 3 years ago tutor-general-functions.php 2 years ago tutor-template-functions.php 3 years ago tutor-template-hook.php 4 years ago
tutor-general-functions.php
1264 lines
1 <?php
2 /**
3 * Tutor general functions
4 *
5 * @package TutorFunctions
6 * @author Themeum <support@themeum.com>
7 * @link https://themeum.com
8 * @since 1.0.0
9 */
10
11 use Tutor\Cache\FlashMessage;
12 use TUTOR\Input;
13 use Tutor\Models\CourseModel;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Tutor input sanitization
21 */
22
23 if ( ! function_exists( 'tutor_sanitize_data' ) ) {
24 /**
25 * Escaping for Sanitize data.
26 *
27 * @since 1.9.13
28 *
29 * @param string $input.
30 * @param string $type.
31 * @return string|array|object
32 */
33 function tutor_sanitize_data( $input = null, $type = null ) {
34 $array = array();
35 $object = new stdClass();
36
37 if ( is_string( $input ) ) {
38
39 if ( 'textarea' == $type ) {
40 $input = sanitize_textarea_field( $input );
41 } elseif ( 'kses' == $type ) {
42 $input = wp_kses_post( $input );
43 } else {
44 $input = sanitize_text_field( $input );
45 }
46
47 return $input;
48
49 } elseif ( is_object( $input ) && count( get_object_vars( $input ) ) ) {
50
51 foreach ( $input as $key => $value ) {
52 if ( is_object( $value ) ) {
53 $object->$key = tutor_sanitize_data( $value );
54 } else {
55 $key = sanitize_text_field( $key );
56 $value = sanitize_text_field( $value );
57 $object->$key = $value;
58 }
59 }
60 return $object;
61 } elseif ( is_array( $input ) && count( $input ) ) {
62 foreach ( $input as $key => $value ) {
63 if ( is_array( $value ) ) {
64 $array[ $key ] = tutor_sanitize_data( $value );
65 } else {
66 $key = sanitize_text_field( $key );
67 $value = sanitize_text_field( $value );
68 $array[ $key ] = $value;
69 }
70 }
71
72 return $array;
73 }
74 }
75 }
76
77 if ( ! function_exists( 'tutor_placeholder_img_src' ) ) {
78 function tutor_placeholder_img_src() {
79 $src = tutor()->url . 'assets/images/placeholder.svg';
80 return apply_filters( 'tutor_placeholder_img_src', $src );
81 }
82 }
83
84 /**
85 * @return string
86 *
87 * Get course categories selecting UI
88 *
89 * @since v.1.3.4
90 */
91
92 if ( ! function_exists( 'tutor_course_categories_dropdown' ) ) {
93 function tutor_course_categories_dropdown( $post_ID = 0, $args = array() ) {
94
95 $default = array(
96 'classes' => '',
97 'name' => 'tax_input[course-category]',
98 'multiple' => true,
99 );
100
101 $args = apply_filters( 'tutor_course_categories_dropdown_args', array_merge( $default, $args ) );
102
103 $multiple_select = '';
104
105 if ( tutor_utils()->array_get( 'multiple', $args ) ) {
106 if ( isset( $args['name'] ) ) {
107 $args['name'] = $args['name'] . '[]';
108 }
109 $multiple_select = "multiple='multiple'";
110 }
111
112 extract( $args );
113
114 $classes = (array) $classes;
115 $classes = implode( ' ', $classes );
116
117 $categories = tutor_utils()->get_course_categories();
118
119 $output = '';
120 $output .= '<select name="' . $name . '" ' . $multiple_select . ' class="' . $classes . '" data-placeholder="' . __( 'Search Course Category. ex. Design, Development, Business', 'tutor' ) . '">';
121 $output .= '<option value="">' . __( 'Select a category', 'tutor' ) . '</option>';
122 $output .= _generate_categories_dropdown_option( $post_ID, $categories, $args );
123 $output .= '</select>';
124
125 return $output;
126 }
127 }
128
129 /**
130 * @return string
131 *
132 * Get course tags selecting UI
133 *
134 * @since v.1.3.4
135 */
136
137 if ( ! function_exists( 'tutor_course_tags_dropdown' ) ) {
138 function tutor_course_tags_dropdown( $post_ID = 0, $args = array() ) {
139
140 $default = array(
141 'classes' => '',
142 'name' => 'tax_input[course-tag]',
143 'multiple' => true,
144 );
145
146 $args = apply_filters( 'tutor_course_tags_dropdown_args', array_merge( $default, $args ) );
147
148 $multiple_select = '';
149
150 if ( tutor_utils()->array_get( 'multiple', $args ) ) {
151 if ( isset( $args['name'] ) ) {
152 $args['name'] = $args['name'] . '[]';
153 }
154 $multiple_select = "multiple='multiple'";
155 }
156
157 extract( $args );
158
159 $classes = (array) $classes;
160 $classes = implode( ' ', $classes );
161
162 $tags = tutor_utils()->get_course_tags();
163
164 $output = '';
165 $output .= '<select name=' . $name . ' ' . $multiple_select . ' class="' . $classes . '" data-placeholder="' . __( 'Search Course Tags. ex. Design, Development, Business', 'tutor' ) . '">';
166 $output .= '<option value="">' . __( 'Select a tag', 'tutor' ) . '</option>';
167 $output .= _generate_tags_dropdown_option( $post_ID, $tags, $args );
168 $output .= '</select>';
169
170 return $output;
171 }
172 }
173
174 /**
175 * @param $categories
176 * @param string $parent_name
177 *
178 * @return string
179 *
180 * Get selecting options, recursive supports
181 *
182 * @since v.1.3.4
183 */
184
185 if ( ! function_exists( '_generate_categories_dropdown_option' ) ) {
186 function _generate_categories_dropdown_option( $post_ID = 0, $categories = array(), $args = array(), $depth = 0 ) {
187 $output = '';
188
189 if ( ! tutor_utils()->count( $categories ) ) {
190 return $output;
191 }
192
193 if ( ! is_numeric( $post_ID ) || $post_ID < 1 ) {
194 return $output;
195 }
196
197 foreach ( $categories as $category_id => $category ) {
198 if ( ! $category->parent ) {
199 $depth = 0;
200 }
201
202 $childrens = tutor_utils()->array_get( 'children', $category );
203 $has_in_term = has_term( $category->term_id, 'course-category', $post_ID );
204
205 $depth_seperator = '';
206 if ( $depth ) {
207 for ( $depth_i = 0; $depth_i < $depth; $depth_i++ ) {
208 $depth_seperator .= '-';
209 }
210 }
211
212 $output .= '<option value="' . $category->term_id . '" ' . selected( $has_in_term, true, false ) . '> ' . $depth_seperator . ' ' . $category->name . '</option>';
213
214 if ( tutor_utils()->count( $childrens ) ) {
215 $depth++;
216 $output .= _generate_categories_dropdown_option( $post_ID, $childrens, $args, $depth );
217 }
218 }
219
220 return $output;
221 }
222 }
223 /**
224 * @param $tags
225 * @param string $parent_name
226 *
227 * @return string
228 *
229 * Get selecting options, recursive supports
230 *
231 * @since v.1.3.4
232 */
233
234 if ( ! function_exists( '_generate_tags_dropdown_option' ) ) {
235 function _generate_tags_dropdown_option( $post_ID = 0, $tags = array(), $args = array(), $depth = 0 ) {
236 $output = '';
237
238 if ( ! tutor_utils()->count( $tags ) ) {
239 return $output;
240 }
241
242 if ( ! is_numeric( $post_ID ) || $post_ID < 1 ) {
243 return $output;
244 }
245
246 foreach ( $tags as $tag ) {
247
248 $has_in_term = has_term( $tag->term_id, 'course-tag', $post_ID );
249
250 $output .= '<option value="' . esc_attr( $tag->name ) . '" ' . selected( $has_in_term, true, false ) . '>' . esc_html( $tag->name ) . '</option>';
251
252 }
253
254 return $output;
255 }
256 }
257
258 /**
259 * @param array $args
260 *
261 * @return string
262 *
263 * Generate course categories checkbox
264 * @since v.1.3.4
265 */
266
267 if ( ! function_exists( 'tutor_course_categories_checkbox' ) ) {
268 function tutor_course_categories_checkbox( $post_ID = 0, $args = array() ) {
269 $default = array(
270 'name' => 'tax_input[course-category]',
271 );
272
273 $args = apply_filters( 'tutor_course_categories_checkbox_args', array_merge( $default, $args ) );
274
275 if ( isset( $args['name'] ) ) {
276 $args['name'] = $args['name'] . '[]';
277 }
278
279 extract( $args );
280
281 $categories = tutor_utils()->get_course_categories();
282 $output = '';
283 $output .= __tutor_generate_categories_checkbox( $post_ID, $categories, $args );
284
285 return $output;
286 }
287 }
288
289 /**
290 * @param array $args
291 *
292 * @return string
293 *
294 * Generate course tags checkbox
295 * @since v.1.3.4
296 */
297
298 if ( ! function_exists( 'tutor_course_tags_checkbox' ) ) {
299 function tutor_course_tags_checkbox( $post_ID = 0, $args = array() ) {
300 $default = array(
301 'name' => 'tax_input[course-tag]',
302 );
303
304 $args = apply_filters( 'tutor_course_tags_checkbox_args', array_merge( $default, $args ) );
305
306 if ( isset( $args['name'] ) ) {
307 $args['name'] = $args['name'] . '[]';
308 }
309
310 extract( $args );
311
312 $tags = tutor_utils()->get_course_tags();
313 $output = '';
314 $output .= __tutor_generate_tags_checkbox( $post_ID, $tags, $args );
315
316 return $output;
317 }
318 }
319
320 /**
321 * @param $categories
322 * @param string $parent_name
323 * @param array $args
324 *
325 * @return string
326 *
327 * Internal function to generate course categories checkbox
328 *
329 * @since v.1.3.4
330 */
331 if ( ! function_exists( '__tutor_generate_categories_checkbox' ) ) {
332 function __tutor_generate_categories_checkbox( $post_ID = 0, $categories = array(), $args = array() ) {
333
334 $output = '';
335 $input_name = tutor_utils()->array_get( 'name', $args );
336
337 if ( tutor_utils()->count( $categories ) ) {
338 $output .= '<ul class="tax-input-course-category">';
339 foreach ( $categories as $category_id => $category ) {
340 $childrens = tutor_utils()->array_get( 'children', $category );
341 $has_in_term = has_term( $category->term_id, 'course-category', $post_ID );
342
343 $output .= '<li class="tax-input-course-category-item tax-input-course-category-item-' . $category->term_id . '"><label class="course-category-checkbox"> <input type="checkbox" name="' . $input_name . '" value="' . $category->term_id . '" ' . checked( $has_in_term, true, false ) . '/> <span>' . $category->name . '</span> </label>';
344
345 if ( tutor_utils()->count( $childrens ) ) {
346 $output .= __tutor_generate_categories_checkbox( $post_ID, $childrens, $args );
347 }
348 $output .= ' </li>';
349 }
350 $output .= '</ul>';
351 }
352
353 return $output;
354
355 }
356 }
357 /**
358 * @param $tags
359 * @param string $parent_name
360 * @param array $args
361 *
362 * @return string
363 *
364 * Internal function to generate course tags checkbox
365 *
366 * @since v.1.3.4
367 */
368 if ( ! function_exists( '__tutor_generate_tags_checkbox' ) ) {
369 function __tutor_generate_tags_checkbox( $post_ID = 0, $tags = array(), $args = array() ) {
370
371 $output = '';
372 $input_name = tutor_utils()->array_get( 'name', $args );
373
374 if ( tutor_utils()->count( $tags ) ) {
375 $output .= '<ul class="tax-input-course-tag">';
376 foreach ( $tags as $tag ) {
377 $has_in_term = has_term( $tag->term_id, 'course-tag', $post_ID );
378
379 $output .= '<li class="tax-input-course-tag-item tax-input-course-tag-item-' . $tag->term_id . '"><label class="course-tag-checkbox"> <input type="checkbox" name="' . $input_name . '" value="' . $tag->term_id . '" ' . checked( $has_in_term, true, false ) . ' /> <span>' . $tag->name . '</span> </label>';
380
381 $output .= ' </li>';
382 }
383 $output .= '</ul>';
384 }
385
386 return $output;
387 }
388 }
389
390 /**
391 * @param string $content
392 * @param string $title
393 *
394 * @return string
395 *
396 * Wrap course builder sections within div for frontend
397 *
398 * @since v.1.3.4
399 */
400
401 if ( ! function_exists( 'course_builder_section_wrap' ) ) {
402 function course_builder_section_wrap( $content = '', $title = '', $echo = true ) {
403 $template = trailingslashit( tutor()->path . 'templates' ) . 'metabox-wrapper.php';
404 if ( $echo ) {
405 if ( file_exists( $template ) ) {
406 include $template;
407 } else {
408 echo esc_html( $template ) . esc_html__( 'file not exists', 'tutor' );
409 }
410 } else {
411 ob_start();
412 if ( file_exists( $template ) ) {
413 include $template;
414 } else {
415 echo esc_html( $template ) . esc_html__( 'file not exists', 'tutor' );
416 }
417 $html = ob_get_clean();
418 return $html;
419 }
420 }
421 }
422
423
424 if ( ! function_exists( 'get_tutor_header' ) ) {
425 function get_tutor_header( $fullScreen = false ) {
426 $enable_spotlight_mode = tutor_utils()->get_option( 'enable_spotlight_mode' );
427
428 if ( $enable_spotlight_mode || $fullScreen ) {
429 ?>
430 <!doctype html>
431 <html <?php language_attributes(); ?>>
432
433 <head>
434 <meta charset="<?php bloginfo( 'charset' ); ?>" />
435 <meta name="viewport" content="width=device-width, initial-scale=1" />
436 <link rel="profile" href="https://gmpg.org/xfn/11" />
437 <?php wp_head(); ?>
438 </head>
439
440 <body <?php body_class(); ?>>
441 <div id="tutor-page-wrap" class="tutor-site-wrap site">
442 <?php
443 } else {
444 tutor_utils()->tutor_custom_header();
445 }
446 }
447 }
448
449 if ( ! function_exists( 'get_tutor_footer' ) ) {
450 function get_tutor_footer( $fullScreen = false ) {
451 $enable_spotlight_mode = tutor_utils()->get_option( 'enable_spotlight_mode' );
452 if ( $enable_spotlight_mode || $fullScreen ) {
453 ?>
454 </div>
455 <?php wp_footer(); ?>
456
457 </body>
458
459 </html>
460 <?php
461 } else {
462 tutor_utils()->tutor_custom_footer();
463 }
464 }
465 }
466
467 /**
468 * @param null $key
469 * @param bool $default
470 *
471 * @return array|bool|mixed
472 *
473 * Get tutor option by this helper function
474 *
475 * @since v.1.3.6
476 */
477 if ( ! function_exists( 'get_tutor_option' ) ) {
478 function get_tutor_option( $key = null, $default = false ) {
479 return tutor_utils()->get_option( $key, $default );
480 }
481 }
482
483 /**
484 * @param null $key
485 * @param bool $value
486 *
487 * Update tutor option by this helper function
488 *
489 * @since v.1.3.6
490 */
491 if ( ! function_exists( 'update_tutor_option' ) ) {
492 function update_tutor_option( $key = null, $value = false ) {
493 tutor_utils()->update_option( $key, $value );
494 }
495 }
496 /**
497 * @param int $course_id
498 * @param null $key
499 * @param bool $default
500 *
501 * @return array|bool|mixed
502 *
503 * Get tutor course settings by course ID
504 *
505 * @since v.1.4.1
506 */
507 if ( ! function_exists( 'get_tutor_course_settings' ) ) {
508 function get_tutor_course_settings( $course_id = 0, $key = null, $default = false ) {
509 return tutor_utils()->get_course_settings( $course_id, $key, $default );
510 }
511 }
512
513 /**
514 * @param int $lesson_id
515 * @param null $key
516 * @param bool $default
517 *
518 * @return array|bool|mixed
519 *
520 * Get lesson content drip settings
521 */
522
523 if ( ! function_exists( 'get_item_content_drip_settings' ) ) {
524 function get_item_content_drip_settings( $lesson_id = 0, $key = null, $default = false ) {
525 return tutor_utils()->get_item_content_drip_settings( $lesson_id, $key, $default );
526 }
527 }
528
529 /**
530 * @param null $msg
531 * @param string $type
532 * @param bool $echo
533 *
534 * @return string
535 *
536 * Print Alert by tutor_alert()
537 *
538 * @since v.1.4.1
539 */
540 if ( ! function_exists( 'tutor_alert' ) ) {
541 function tutor_alert( $msg = null, $type = 'warning', $echo = true ) {
542 if ( ! $msg ) {
543
544 if ( $type === 'any' ) {
545 if ( ! $msg ) {
546 $type = 'warning';
547 $msg = tutor_flash_get( $type );
548 }
549 if ( ! $msg ) {
550 $type = 'danger';
551 $msg = tutor_flash_get( $type );
552 }
553 if ( ! $msg ) {
554 $type = 'success';
555 $msg = tutor_flash_get( $type );
556 }
557 } else {
558 $msg = tutor_flash_get( $type );
559 }
560 }
561 if ( ! $msg ) {
562 return $msg;
563 }
564
565 $html = '<div class="asas tutor-alert tutor-' . esc_attr( $type ) . '">
566 <div class="tutor-alert-text">
567 <span class="tutor-alert-icon tutor-fs-4 tutor-icon-circle-info tutor-mr-12"></span>
568 <span>' . wp_kses( $msg, array( 'div', 'span' ) ) . '</span>
569 </div>
570 </div>';
571 if ( $echo ) {
572 echo tutor_kses_html( $html ); //phpcs:ignore
573 }
574 return $html;
575 }
576 }
577
578
579 /**
580 * @param bool $echo
581 *
582 * Simply call tutor_nonce_field() to generate nonce field
583 *
584 * @since v.1.4.2
585 */
586
587 if ( ! function_exists( 'tutor_nonce_field' ) ) {
588 function tutor_nonce_field( $echo = true ) {
589 wp_nonce_field( tutor()->nonce_action, tutor()->nonce, $echo );
590 }
591 }
592
593 /**
594 * @param null $key
595 * @param string $message
596 *
597 * Set Flash Message
598 */
599
600 if ( ! function_exists( 'tutor_flash_set' ) ) {
601 function tutor_flash_set( $key = null, $message = '' ) {
602 if ( ! $key ) {
603 return;
604 }
605 // ensure session is started
606 if ( session_status() !== PHP_SESSION_ACTIVE ) {
607 session_start();
608 }
609 $_SESSION[ $key ] = $message;
610 }
611 }
612
613 /**
614 * @param null $key
615 *
616 * @return array|bool|mixed|null
617 *
618 * @since v.1.4.2
619 *
620 * Get flash message
621 */
622
623 if ( ! function_exists( 'tutor_flash_get' ) ) {
624 function tutor_flash_get( $key = null ) {
625 if ( $key ) {
626 // ensure session is started
627 if ( session_status() !== PHP_SESSION_ACTIVE ) {
628 @session_start();
629 }
630 if ( empty( $_SESSION ) ) {
631 return null;
632 }
633 $message = tutor_utils()->array_get( $key, $_SESSION );
634 if ( $message ) {
635 unset( $_SESSION[ $key ] );
636 }
637 return $message;
638 }
639 return $key;
640 }
641 }
642
643 if ( ! function_exists( 'tutor_redirect_back' ) ) {
644 /**
645 * @param null $url
646 *
647 * Redirect to back or a specific URL and terminate
648 *
649 * @since v.1.4.3
650 */
651 function tutor_redirect_back( $url = null ) {
652 if ( ! $url ) {
653 $url = tutor_utils()->referer();
654 }
655 wp_safe_redirect( $url );
656 exit();
657 }
658 }
659
660 /**
661 * @param string $action
662 * @param bool $echo
663 *
664 * @return string
665 *
666 * @since v.1.4.3
667 */
668
669 if ( ! function_exists( 'tutor_action_field' ) ) {
670 function tutor_action_field( $action = '', $echo = true ) {
671 $output = '';
672 if ( $action ) {
673 $output = '<input type="hidden" name="tutor_action" value="' . esc_attr( $action ) . '">';
674 }
675
676 if ( $echo ) {
677 echo wp_kses(
678 $output,
679 array(
680 'input' => array(
681 'type' => true,
682 'name' => true,
683 'value' => true,
684 ),
685 )
686 );
687 } else {
688 return $output;
689 }
690 }
691 }
692
693
694 if ( ! function_exists( 'tutor_time' ) ) {
695 /**
696 * Return current Time from WordPress time
697 *
698 * @return int|string
699 * @since v.1.4.3
700 */
701 function tutor_time() {
702 $gmt_offset = get_option( 'gmt_offset' );
703 return time() + ( $gmt_offset * HOUR_IN_SECONDS );
704 }
705 }
706
707 /**
708 * Toggle maintenance mode for the site.
709 *
710 * Creates/deletes the maintenance file to enable/disable maintenance mode.
711 *
712 * @since v.1.4.6
713 *
714 * @global WP_Filesystem_Base $wp_filesystem Subclass
715 *
716 * @param bool $enable True to enable maintenance mode, false to disable.
717 */
718 if ( ! function_exists( 'tutor_maintenance_mode' ) ) {
719 function tutor_maintenance_mode( $enable = false ) {
720 $file = ABSPATH . '.tutor_maintenance';
721 if ( $enable ) {
722 // Create maintenance file to signal that we are upgrading
723 $maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
724
725 if ( ! file_exists( $file ) ) {
726 file_put_contents( $file, $maintenance_string );
727 }
728 } else {
729 if ( file_exists( $file ) ) {
730 unlink( $file );
731 }
732 }
733 }
734 }
735
736 /**
737 * @return bool
738 *
739 * Check if the current page is course single page
740 *
741 * @since v.1.6.0
742 */
743
744 if ( ! function_exists( 'is_single_course' ) ) {
745 function is_single_course( $check_spotlight = false ) {
746 global $wp_query;
747 $course_post_type = tutor()->course_post_type;
748
749 $post_types = array( $course_post_type );
750 if ( $check_spotlight ) {
751 $post_types = array_merge(
752 $post_types,
753 array(
754 'lesson',
755 'tutor_quiz',
756 'tutor_assignments',
757 'tutor_zoom_meeting',
758 )
759 );
760 }
761
762 if ( is_single() && ! empty( $wp_query->query['post_type'] ) && in_array( $wp_query->query['post_type'], $post_types ) ) {
763 return true;
764 }
765 return false;
766 }
767 }
768
769 /**
770 * Require wp_date form return js date format.
771 * this is helpful for date picker
772 *
773 * @return string
774 *
775 * @since 1.9.7
776 */
777 if ( ! function_exists( 'tutor_js_date_format_against_wp' ) ) {
778 function tutor_js_date_format_against_wp() {
779 $wp_date_format = get_option( 'date_format' );
780 $default_format = 'Y-M-d';
781
782 $formats = array(
783 'Y-m-d' => 'Y-M-d',
784 'm/d/Y' => 'M-d-Y',
785 'd/m/Y' => 'd-M-Y',
786 'F j, Y' => 'MMMM d, yyyy',
787 'j F Y' => 'MMMM d, yyyy',
788 );
789 return isset( $formats[ $wp_date_format ] ) ? $formats[ $wp_date_format ] : $default_format;
790 }
791 }
792
793 /**
794 * Convert date to desire format
795 *
796 * NOTE: mysql query use formated date from here
797 * that's why date_i18n need to be ignore
798 *
799 * @param $format string
800 *
801 * @param $date string
802 *
803 * @return string ( date )
804 */
805 if ( ! function_exists( 'tutor_get_formated_date' ) ) {
806 function tutor_get_formated_date( string $require_format, string $user_date ) {
807 $date = date_create( str_replace( '/', '-', $user_date ) );
808 if ( is_a( $date, 'DateTime' ) ) {
809 $formatted_date = date_format( $date, $require_format );
810 } else {
811 $formatted_date = date( $require_format, strtotime( $user_date ) );
812 }
813 return $formatted_date;
814 }
815 }
816
817 /**
818 * Get translated date
819 *
820 * @since v2.0.2
821 *
822 * @param string $date date in string from to translate & format.
823 * @param string $format optional date format, default is wp date time format.
824 *
825 * @return string translated date
826 */
827 if ( ! function_exists( 'tutor_i18n_get_formated_date' ) ) {
828 function tutor_i18n_get_formated_date( string $date, string $format = '' ) {
829 if ( '' === $format ) {
830 $format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
831 }
832 return date_i18n( $format, strtotime( $date ) );
833 }
834 }
835
836 if ( ! function_exists( '_tutor_search_by_title_only' ) ) {
837 /**
838 * Search SQL filter for matching against post title only.
839 *
840 * @link http://wordpress.stackexchange.com/a/11826/1685
841 *
842 * @param string $search
843 * @param WP_Query $wp_query
844 */
845 function _tutor_search_by_title_only( $search, $wp_query ) {
846 if ( ! empty( $search ) && ! empty( $wp_query->query_vars['search_terms'] ) ) {
847 global $wpdb;
848
849 $q = $wp_query->query_vars;
850 $n = ! empty( $q['exact'] ) ? '' : '%';
851
852 $search = array();
853
854 foreach ( (array) $q['search_terms'] as $term ) {
855 $search[] = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $n . $wpdb->esc_like( $term ) . $n );
856 }
857
858 if ( ! is_user_logged_in() ) {
859 $search[] = "$wpdb->posts.post_password = ''";
860 }
861
862 $search = ' AND ' . implode( ' AND ', $search );
863 }
864
865 return $search;
866 }
867 }
868
869 if ( ! function_exists( 'get_request' ) ) {
870 /**
871 * Function to get_request
872 *
873 * @param array $var .
874 * @return array
875 */
876 function get_request( $var ) {
877 return isset( $_REQUEST[ $var ] ) ? sanitize_text_field( $_REQUEST[ $var ] ) : false;
878
879 }
880 }
881
882 if ( ! function_exists( 'tutor_kses_allowed_html' ) ) {
883 function tutor_kses_allowed_html( $allowed_tags, $context ) {
884 $tags = array( 'input', 'style', 'script', 'select', 'form', 'option', 'optgroup', 'iframe', 'bdi', 'source', 'a' );
885 $atts = array( 'min', 'max', 'maxlength', 'type', 'method', 'enctype', 'action', 'selected', 'class', 'id', 'disabled', 'checked', 'readonly', 'name', 'aria-*', 'style', 'role', 'placeholder', 'value', 'data-*', 'src', 'width', 'height', 'frameborder', 'allow', 'fullscreen', 'title', 'multiple', 'tutor-hide-course-single-sidebar', 'href' );
886
887 foreach ( $tags as $tag ) {
888 $tag_attrs = array();
889
890 foreach ( $atts as $att ) {
891 $tag_attrs[ $att ] = true;
892 }
893
894 $allowed_tags[ $tag ] = $tag_attrs;
895 }
896
897 return $allowed_tags;
898 }
899 }
900
901 if ( ! function_exists( 'tutor_kses_allowed_css' ) ) {
902 function tutor_kses_allowed_css( $styles ) {
903 $styles[] = 'display';
904 $styles[] = '--progress-value';
905 return $styles;
906 }
907 }
908
909 if ( ! function_exists( 'tutor_kses_html' ) ) {
910 function tutor_kses_html( $content ) {
911
912 return $content;
913 add_filter( 'wp_kses_allowed_html', 'tutor_kses_allowed_html', 10, 2 );
914 add_filter( 'safe_style_css', 'tutor_kses_allowed_css' );
915
916 $content = preg_replace( '/<!--(.|\s)*?-->/', '', $content );
917 $content = wp_kses_post( $content );
918 $content = str_replace( '&amp;', '&', $content );
919
920 remove_filter( 'safe_style_css', 'tutor_kses_allowed_css' );
921 remove_filter( 'wp_kses_allowed_html', 'tutor_kses_allowed_html' );
922
923 return $content;
924 }
925 }
926
927 /**
928 * @return array
929 *
930 * Get all Withdraw Methods available on this system
931 *
932 * @since v.1.5.7
933 */
934 if ( ! function_exists( 'get_tutor_all_withdrawal_methods' ) ) {
935 function get_tutor_all_withdrawal_methods() {
936 return apply_filters( 'tutor_withdrawal_methods_all', array() );
937 }
938 }
939
940
941 if ( ! function_exists( 'tutor_log' ) ) {
942 function tutor_log() {
943 $arg_list = func_get_args();
944
945 foreach ( $arg_list as $data ) {
946 ob_start();
947 var_dump( $data );
948 error_log( ob_get_clean() );
949 }
950 }
951 }
952
953 if ( ! function_exists( 'tutor_wc_price_currency_format' ) ) {
954 function tutor_wc_price_currency_format( $amount ) {
955
956 $symbol = get_woocommerce_currency_symbol();
957 $position = get_option( 'woocommerce_currency_pos', 'left' );
958
959 switch ( $position ) {
960 case 'left':
961 $amount = $symbol . $amount;
962 break;
963 case 'left_space':
964 $amount = $symbol . ' ' . $amount;
965 break;
966
967 case 'right':
968 $amount = $amount . $symbol;
969 break;
970 case 'right_space':
971 $amount = $amount . ' ' . $symbol;
972 break;
973
974 default:
975 $amount = $symbol . $amount;
976 break;
977 }
978
979 return $amount;
980 }
981 }
982
983 if ( ! function_exists( 'tutor_meta_box_wrapper' ) ) {
984 /**
985 * Tutor meta box wrapper
986 *
987 * @since v2.0.2
988 *
989 * @param string $id id of meta box.
990 * @param string $title meta box title.
991 * @param mixed $callback callback function that meta box will call.
992 * @param string $screen which screen meta box should appear.
993 * @param string $context optional param. Where meta box should appear.
994 * @param string $priority optional.
995 * @param string $custom_class optional. If provide it will add this class along
996 * with div id.
997 *
998 * @return void if class provided then filter hook will return class.
999 */
1000 function tutor_meta_box_wrapper(
1001 $id,
1002 $title,
1003 $callback,
1004 $screen,
1005 $context = 'advanced',
1006 $priority = 'default',
1007 $custom_class = ''
1008 ) {
1009 add_meta_box(
1010 $id,
1011 $title,
1012 $callback,
1013 $screen,
1014 $context,
1015 $priority
1016 );
1017 if ( '' !== $custom_class ) {
1018 $post_type = tutor()->course_post_type;
1019 add_filter(
1020 "postbox_classes_{$post_type}_{$id}",
1021 function( $classes ) use ( $custom_class ) {
1022 if ( ! in_array( $custom_class, $classes ) ) {
1023 $classes[] = $custom_class;
1024 }
1025 return $classes;
1026 }
1027 );
1028 }
1029 }
1030 }
1031
1032 if ( ! function_exists( 'tutor_closeable_alert_msg' ) ) {
1033 /**
1034 * Create a close-able alert message
1035 *
1036 * @since 2.1.9
1037 *
1038 * @param string $message alert message.
1039 * @param string $alert alert key like: success, warning, danger, etc.
1040 * @param array $allowed_tags allowed tags to use with WP_KSES.
1041 *
1042 * @return void
1043 */
1044 function tutor_closeable_alert_msg( string $message, string $alert = 'success', $allowed_tags = array() ) {
1045 ?>
1046 <div class="tutor-alert tutor-<?php echo esc_attr( $alert ); ?> tutor-mb-12 tutor-alert tutor-success tutor-mb-12 tutor-d-flex tutor-align-center tutor-justify-between">
1047 <span>
1048 <?php echo is_array( $allowed_tags ) && count( $allowed_tags ) ? wp_kses( $message, $allowed_tags ) : esc_html( $message ); ?>
1049 </span>
1050 <span class="tutor-icon-times" area-hidden="true" onclick="this.closest('div').remove()" style="cursor: pointer;"></span>
1051 </div>
1052 <?php
1053 }
1054 }
1055
1056 if ( ! function_exists( 'tutor_set_flash_message' ) ) {
1057 /**
1058 * Utility API Set flash message to show somewhere
1059 *
1060 * It will call set_cache method of FlashMessage class to set cache
1061 *
1062 * @param mixed $message message to show.
1063 * @param string $alert alert type as FlashMessage::$alert_types.
1064 *
1065 * @return void
1066 */
1067 function tutor_set_flash_message( $message = '', $alert = 'success' ) {
1068 $flash_msg = new FlashMessage( $message, $alert );
1069 $flash_msg->set_cache();
1070 }
1071 }
1072
1073
1074 if ( ! function_exists( 'tutor_snackbar' ) ) {
1075 /**
1076 * Reuseable snackbar to show on the frontend
1077 *
1078 * Create a snackbar based on title, action buttons
1079 *
1080 * @since 2.2.0
1081 *
1082 * @param string $title title to show.
1083 * @param array $action_buttons 2 dimensional array of action buttons to show.
1084 * Supported attrs: [ [title => title, id => '', class => '' url => '', target => ''] ].
1085 * @param string $title_icon_class title icon to show before title.
1086 *
1087 * @return void
1088 */
1089 function tutor_snackbar( string $title, array $action_buttons = array(), $title_icon_class = '' ) {
1090 ?>
1091 <div id="tutor-reuseable-snackbar" class="tutor-snackbar-wrapper">
1092 <div class="tutor-snackbar">
1093 <p>
1094 <?php if ( ! empty( $title_icon_class ) ) : ?>
1095 <i class="tutor-snackbar-title-icon <?php echo esc_attr( $title_icon_class ); ?>"></i>
1096 <?php endif; ?>
1097 <?php echo esc_html( $title ); ?>
1098 </p>
1099 <div>
1100 <?php foreach ( $action_buttons as $attr => $button ) : ?>
1101 <a
1102 <?php foreach ( $button as $attr => $value ) : ?>
1103 <?php if ( ! empty( $value ) ) : ?>
1104 <?php echo esc_attr( $attr ) . '="' . esc_attr( $value ) . '" '; ?>
1105 <?php endif; ?>
1106 <?php endforeach; ?>
1107 >
1108 <?php echo esc_html( isset( $button['title'] ) ? $button['title'] : '' ); ?>
1109 </a>
1110 <?php endforeach; ?>
1111 <span class="tutor-icon-times" area-hidden="true" onclick="this.closest('#tutor-reuseable-snackbar').remove()" style="cursor: pointer;"></span>
1112 </div>
1113 </div>
1114 </div>
1115 <?php
1116 }
1117 }
1118
1119 if ( ! function_exists( 'tutor_is_rest' ) ) {
1120 /**
1121 * Checks if the current request is a WP REST API request.
1122 *
1123 * @since 2.6.0
1124 *
1125 * Case #1: After WP_REST_Request initialisation
1126 * Case #2: Support "plain" permalink settings and check if `rest_route` starts with `/`
1127 * Case #3: It can happen that WP_Rewrite is not yet initialized,
1128 * so do this (wp-settings.php)
1129 * Case #4: URL Path begins with wp-json/ (your REST prefix)
1130 * Also supports WP installations in subfolders
1131 *
1132 * @see https://wordpress.stackexchange.com/questions/221202/does-something-like-is-rest-exist
1133 * @returns boolean
1134 */
1135 function tutor_is_rest() {
1136 $rest_route = Input::get( 'rest_route' );
1137 if ( defined( 'REST_REQUEST' ) && REST_REQUEST || $rest_route && strpos( $rest_route, '/', 0 ) === 0 ) {
1138 return true;
1139 }
1140
1141 // (#3)
1142 global $wp_rewrite;
1143 if ( null === $wp_rewrite ) {
1144 $wp_rewrite = new WP_Rewrite();
1145 }
1146
1147 // (#4)
1148 $rest_url = wp_parse_url( trailingslashit( rest_url() ) );
1149 $current_url = wp_parse_url( add_query_arg( array() ) );
1150 return strpos( $current_url['path'] ?? '/', $rest_url['path'], 0 ) === 0;
1151 }
1152 }
1153
1154 if ( ! function_exists( 'tutor_getallheaders' ) ) {
1155 /**
1156 * Wrapper of PHP getallheaders with a fallback if getallheaders not available
1157 *
1158 * @since 2.6.0
1159 *
1160 * @see https://www.php.net/manual/en/function.getallheaders.php
1161 *
1162 * @return array of headers
1163 */
1164 function tutor_getallheaders() {
1165 $headers = array();
1166 if ( function_exists( 'getallheaders' ) ) {
1167 $headers = getallheaders();
1168 }
1169
1170 if ( ! $headers ) {
1171 foreach ( $_SERVER as $name => $value ) {
1172 if ( substr( $name, 0, 5 ) == 'HTTP_' ) {
1173 $headers[ str_replace( ' ', '-', ucwords( strtolower( str_replace( '_', ' ', substr( $name, 5 ) ) ) ) ) ] = $value;
1174 }
1175 }
1176 }
1177
1178 return $headers;
1179 }
1180 }
1181
1182 if ( ! function_exists( 'tutor_entry_box_buttons' ) ) {
1183 /**
1184 * Tutor conditional buttons for the enrollment box
1185 *
1186 * @since 2.6.0
1187 *
1188 * @param int $course_id course id.
1189 * @param int $user_id user id.
1190 *
1191 * @return object
1192 */
1193 function tutor_entry_box_buttons( int $course_id = 0, int $user_id = 0 ) {
1194 $conditional_buttons = (object) array(
1195 'show_enroll_btn' => false,
1196 'show_add_to_cart_btn' => false,
1197 'show_start_learning_btn' => false,
1198 'show_continue_learning_btn' => false,
1199 'show_complete_course_btn' => false,
1200 'show_retake_course_btn' => false,
1201 'show_certificate_view_btn' => false,
1202 'show_course_fully_booked_btn' => false,
1203 );
1204
1205 $course_id = tutor_utils()->get_post_id( $course_id );
1206 $user_id = tutor_utils()->get_user_id( $user_id );
1207
1208 $has_course_access = tutor_utils()->has_user_course_content_access( $user_id, $course_id );
1209
1210 $is_public_course = get_post_meta( $course_id, '_tutor_is_public_course', true );
1211
1212 $is_enabled_retake = tutor_utils()->get_option( 'course_retake_feature' );
1213
1214 $is_enrolled = tutor_utils()->is_enrolled( $course_id, $user_id );
1215
1216 if ( 'yes' === $is_public_course ) {
1217 $conditional_buttons->show_start_learning_btn = true;
1218 } else {
1219 // Admin & instructor can manage posts.
1220 if ( $is_enrolled || $has_course_access ) {
1221 $can_complete_course = CourseModel::can_complete_course( $course_id, $user_id );
1222 $is_completed_course = tutor_utils()->is_completed_course( $course_id, $user_id );
1223 $course_progress = (int) tutor_utils()->get_course_completed_percent( $course_id, $user_id );
1224
1225 if ( $course_progress > 0 || $course_progress < 100) {
1226 $conditional_buttons->show_continue_learning_btn = true;
1227 }
1228
1229 if ( $course_progress === 0 ) {
1230 $conditional_buttons->show_start_learning_btn = true;
1231 }
1232
1233 if ( $can_complete_course ) {
1234 $conditional_buttons->show_complete_course_btn = true;
1235 }
1236
1237 if ( $is_completed_course ) {
1238 $conditional_buttons->show_certificate_view_btn = true;
1239 }
1240
1241 if ( $is_enabled_retake && $is_completed_course ) {
1242 $conditional_buttons->show_retake_course_btn = true;
1243 }
1244 } else {
1245 $is_paid_course = tutor_utils()->is_course_purchasable( $course_id );
1246 if ( $is_paid_course ) {
1247 $conditional_buttons->show_add_to_cart_btn = true;
1248 } else {
1249 $conditional_buttons->show_enroll_btn = true;
1250 }
1251 }
1252 }
1253
1254 if ( ! $is_public_course && ! ( $is_enrolled || $has_course_access ) ) {
1255 $is_fully_booked = tutor_utils()->is_course_fully_booked( $course_id );
1256 if ( $is_fully_booked ) {
1257 $conditional_buttons->show_course_fully_booked_btn = true;
1258 }
1259 }
1260
1261 return apply_filters( 'tutor_enrollment_buttons', $conditional_buttons );
1262 }
1263 }
1264