Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/tutor/includes/tutor-general-functions.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
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\Ecommerce\Ecommerce;
13
+
use Tutor\Ecommerce\OptionKeys;
14
+
use Tutor\Ecommerce\Settings;
15
+
use TUTOR\Input;
16
+
use Tutor\Models\CourseModel;
17
+
18
+
defined( 'ABSPATH' ) || exit;
19
+
20
+
21
+
if ( ! function_exists( 'tutor' ) ) {
22
+
/**
23
+
* Tutor helper function to get configuration like version, path etc.
24
+
*
25
+
* @since 1.0.0
26
+
* @since 3.7.0 updated with config class.
27
+
*
28
+
* @return object
29
+
*/
30
+
function tutor() {
31
+
return \TUTOR\Config::get_instance();
32
+
}
33
+
}
34
+
35
+
if ( ! function_exists( 'tutor_utils' ) ) {
36
+
/**
37
+
* Access tutor utils functions
38
+
*
39
+
* @since 1.0.0
40
+
*
41
+
* @return \TUTOR\Utils
42
+
*/
43
+
function tutor_utils() {
44
+
if ( ! isset( $GLOBALS['tutor_utils_object'] ) ) {
45
+
// Use runtime cache.
46
+
$GLOBALS['tutor_utils_object'] = new \TUTOR\Utils();
47
+
}
48
+
49
+
return $GLOBALS['tutor_utils_object'];
50
+
}
51
+
}
52
+
53
+
54
+
if ( ! function_exists( 'tutils' ) ) {
55
+
/**
56
+
* Alias of tutor_utils()
57
+
*
58
+
* @since 1.3.4
59
+
*
60
+
* @return \TUTOR\Utils
61
+
*/
62
+
function tutils() {
63
+
return tutor_utils();
64
+
}
65
+
}
66
+
67
+
/**
68
+
* Tutor input sanitization
69
+
*/
70
+
71
+
if ( ! function_exists( 'tutor_sanitize_data' ) ) {
72
+
/**
73
+
* Escaping for Sanitize data.
74
+
*
75
+
* @since 1.9.13
76
+
*
77
+
* @param string $input.
78
+
* @param string $type.
79
+
* @return string|array|object
80
+
*/
81
+
function tutor_sanitize_data( $input = null, $type = null ) {
82
+
$array = array();
83
+
$object = new stdClass();
84
+
85
+
if ( is_string( $input ) ) {
86
+
87
+
if ( 'textarea' == $type ) {
88
+
$input = sanitize_textarea_field( $input );
89
+
} elseif ( 'kses' == $type ) {
90
+
$input = wp_kses_post( $input );
91
+
} else {
92
+
$input = sanitize_text_field( $input );
93
+
}
94
+
95
+
return $input;
96
+
97
+
} elseif ( is_object( $input ) && count( get_object_vars( $input ) ) ) {
98
+
99
+
foreach ( $input as $key => $value ) {
100
+
if ( is_object( $value ) ) {
101
+
$object->$key = tutor_sanitize_data( $value );
102
+
} else {
103
+
$key = sanitize_text_field( $key );
104
+
$value = sanitize_text_field( $value );
105
+
$object->$key = $value;
106
+
}
107
+
}
108
+
return $object;
109
+
} elseif ( is_array( $input ) && count( $input ) ) {
110
+
foreach ( $input as $key => $value ) {
111
+
if ( is_array( $value ) ) {
112
+
$array[ $key ] = tutor_sanitize_data( $value );
113
+
} else {
114
+
$key = sanitize_text_field( $key );
115
+
$value = sanitize_text_field( $value );
116
+
$array[ $key ] = $value;
117
+
}
118
+
}
119
+
120
+
return $array;
121
+
}
122
+
}
123
+
}
124
+
125
+
if ( ! function_exists( 'tutor_placeholder_img_src' ) ) {
126
+
function tutor_placeholder_img_src() {
127
+
$src = tutor()->url . 'assets/images/placeholder.svg';
128
+
return apply_filters( 'tutor_placeholder_img_src', $src );
129
+
}
130
+
}
131
+
132
+
/**
133
+
* @return string
134
+
*
135
+
* Get course categories selecting UI
136
+
*
137
+
* @since v.1.3.4
138
+
*/
139
+
140
+
if ( ! function_exists( 'tutor_course_categories_dropdown' ) ) {
141
+
function tutor_course_categories_dropdown( $post_ID = 0, $args = array() ) {
142
+
143
+
$default = array(
144
+
'classes' => '',
145
+
'name' => 'tax_input[course-category]',
146
+
'multiple' => true,
147
+
);
148
+
149
+
$args = apply_filters( 'tutor_course_categories_dropdown_args', array_merge( $default, $args ) );
150
+
151
+
$multiple_select = '';
152
+
153
+
if ( tutor_utils()->array_get( 'multiple', $args ) ) {
154
+
if ( isset( $args['name'] ) ) {
155
+
$args['name'] = $args['name'] . '[]';
156
+
}
157
+
$multiple_select = "multiple='multiple'";
158
+
}
159
+
160
+
extract( $args );
161
+
162
+
$classes = (array) $classes;
163
+
$classes = implode( ' ', $classes );
164
+
165
+
$categories = tutor_utils()->get_course_categories();
166
+
167
+
$output = '';
168
+
$output .= '<select name="' . $name . '" ' . $multiple_select . ' class="' . $classes . '" data-placeholder="' . __( 'Search Course Category. ex. Design, Development, Business', 'tutor' ) . '">';
169
+
$output .= '<option value="">' . __( 'Select a category', 'tutor' ) . '</option>';
170
+
$output .= _generate_categories_dropdown_option( $post_ID, $categories, $args );
171
+
$output .= '</select>';
172
+
173
+
return $output;
174
+
}
175
+
}
176
+
177
+
/**
178
+
* @return string
179
+
*
180
+
* Get course tags selecting UI
181
+
*
182
+
* @since v.1.3.4
183
+
*/
184
+
185
+
if ( ! function_exists( 'tutor_course_tags_dropdown' ) ) {
186
+
function tutor_course_tags_dropdown( $post_ID = 0, $args = array() ) {
187
+
188
+
$default = array(
189
+
'classes' => '',
190
+
'name' => 'tax_input[course-tag]',
191
+
'multiple' => true,
192
+
);
193
+
194
+
$args = apply_filters( 'tutor_course_tags_dropdown_args', array_merge( $default, $args ) );
195
+
196
+
$multiple_select = '';
197
+
198
+
if ( tutor_utils()->array_get( 'multiple', $args ) ) {
199
+
if ( isset( $args['name'] ) ) {
200
+
$args['name'] = $args['name'] . '[]';
201
+
}
202
+
$multiple_select = "multiple='multiple'";
203
+
}
204
+
205
+
extract( $args );
206
+
207
+
$classes = (array) $classes;
208
+
$classes = implode( ' ', $classes );
209
+
210
+
$tags = tutor_utils()->get_course_tags();
211
+
212
+
$output = '';
213
+
$output .= '<select name=' . $name . ' ' . $multiple_select . ' class="' . $classes . '" data-placeholder="' . __( 'Search Course Tags. ex. Design, Development, Business', 'tutor' ) . '">';
214
+
$output .= '<option value="">' . __( 'Select a tag', 'tutor' ) . '</option>';
215
+
$output .= _generate_tags_dropdown_option( $post_ID, $tags, $args );
216
+
$output .= '</select>';
217
+
218
+
return $output;
219
+
}
220
+
}
221
+
222
+
/**
223
+
* @param $categories
224
+
* @param string $parent_name
225
+
*
226
+
* @return string
227
+
*
228
+
* Get selecting options, recursive supports
229
+
*
230
+
* @since v.1.3.4
231
+
*/
232
+
233
+
if ( ! function_exists( '_generate_categories_dropdown_option' ) ) {
234
+
function _generate_categories_dropdown_option( $post_ID = 0, $categories = array(), $args = array(), $depth = 0 ) {
235
+
$output = '';
236
+
237
+
if ( ! tutor_utils()->count( $categories ) ) {
238
+
return $output;
239
+
}
240
+
241
+
if ( ! is_numeric( $post_ID ) || $post_ID < 1 ) {
242
+
return $output;
243
+
}
244
+
245
+
foreach ( $categories as $category_id => $category ) {
246
+
if ( ! $category->parent ) {
247
+
$depth = 0;
248
+
}
249
+
250
+
$childrens = tutor_utils()->array_get( 'children', $category );
251
+
$has_in_term = has_term( $category->term_id, 'course-category', $post_ID );
252
+
253
+
$depth_seperator = '';
254
+
if ( $depth ) {
255
+
for ( $depth_i = 0; $depth_i < $depth; $depth_i++ ) {
256
+
$depth_seperator .= '-';
257
+
}
258
+
}
259
+
260
+
$output .= '<option value="' . $category->term_id . '" ' . selected( $has_in_term, true, false ) . '> ' . $depth_seperator . ' ' . $category->name . '</option>';
261
+
262
+
if ( tutor_utils()->count( $childrens ) ) {
263
+
$depth++;
264
+
$output .= _generate_categories_dropdown_option( $post_ID, $childrens, $args, $depth );
265
+
}
266
+
}
267
+
268
+
return $output;
269
+
}
270
+
}
271
+
/**
272
+
* @param $tags
273
+
* @param string $parent_name
274
+
*
275
+
* @return string
276
+
*
277
+
* Get selecting options, recursive supports
278
+
*
279
+
* @since v.1.3.4
280
+
*/
281
+
282
+
if ( ! function_exists( '_generate_tags_dropdown_option' ) ) {
283
+
function _generate_tags_dropdown_option( $post_ID = 0, $tags = array(), $args = array(), $depth = 0 ) {
284
+
$output = '';
285
+
286
+
if ( ! tutor_utils()->count( $tags ) ) {
287
+
return $output;
288
+
}
289
+
290
+
if ( ! is_numeric( $post_ID ) || $post_ID < 1 ) {
291
+
return $output;
292
+
}
293
+
294
+
foreach ( $tags as $tag ) {
295
+
296
+
$has_in_term = has_term( $tag->term_id, CourseModel::COURSE_TAG, $post_ID );
297
+
298
+
$output .= '<option value="' . esc_attr( $tag->name ) . '" ' . selected( $has_in_term, true, false ) . '>' . esc_html( $tag->name ) . '</option>';
299
+
300
+
}
301
+
302
+
return $output;
303
+
}
304
+
}
305
+
306
+
/**
307
+
* @param array $args
308
+
*
309
+
* @return string
310
+
*
311
+
* Generate course categories checkbox
312
+
* @since v.1.3.4
313
+
*/
314
+
315
+
if ( ! function_exists( 'tutor_course_categories_checkbox' ) ) {
316
+
function tutor_course_categories_checkbox( $post_ID = 0, $args = array() ) {
317
+
$default = array(
318
+
'name' => 'tax_input[course-category]',
319
+
);
320
+
321
+
$args = apply_filters( 'tutor_course_categories_checkbox_args', array_merge( $default, $args ) );
322
+
323
+
if ( isset( $args['name'] ) ) {
324
+
$args['name'] = $args['name'] . '[]';
325
+
}
326
+
327
+
extract( $args );
328
+
329
+
$categories = tutor_utils()->get_course_categories();
330
+
$output = '';
331
+
$output .= __tutor_generate_categories_checkbox( $post_ID, $categories, $args );
332
+
333
+
return $output;
334
+
}
335
+
}
336
+
337
+
/**
338
+
* @param array $args
339
+
*
340
+
* @return string
341
+
*
342
+
* Generate course tags checkbox
343
+
* @since v.1.3.4
344
+
*/
345
+
346
+
if ( ! function_exists( 'tutor_course_tags_checkbox' ) ) {
347
+
function tutor_course_tags_checkbox( $post_ID = 0, $args = array() ) {
348
+
$default = array(
349
+
'name' => 'tax_input[course-tag]',
350
+
);
351
+
352
+
$args = apply_filters( 'tutor_course_tags_checkbox_args', array_merge( $default, $args ) );
353
+
354
+
if ( isset( $args['name'] ) ) {
355
+
$args['name'] = $args['name'] . '[]';
356
+
}
357
+
358
+
extract( $args );
359
+
360
+
$tags = tutor_utils()->get_course_tags();
361
+
$output = '';
362
+
$output .= __tutor_generate_tags_checkbox( $post_ID, $tags, $args );
363
+
364
+
return $output;
365
+
}
366
+
}
367
+
368
+
/**
369
+
* @param $categories
370
+
* @param string $parent_name
371
+
* @param array $args
372
+
*
373
+
* @return string
374
+
*
375
+
* Internal function to generate course categories checkbox
376
+
*
377
+
* @since v.1.3.4
378
+
*/
379
+
if ( ! function_exists( '__tutor_generate_categories_checkbox' ) ) {
380
+
function __tutor_generate_categories_checkbox( $post_ID = 0, $categories = array(), $args = array() ) {
381
+
382
+
$output = '';
383
+
$input_name = tutor_utils()->array_get( 'name', $args );
384
+
385
+
if ( tutor_utils()->count( $categories ) ) {
386
+
$output .= '<ul class="tax-input-course-category">';
387
+
foreach ( $categories as $category_id => $category ) {
388
+
$childrens = tutor_utils()->array_get( 'children', $category );
389
+
$has_in_term = has_term( $category->term_id, 'course-category', $post_ID );
390
+
391
+
$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>';
392
+
393
+
if ( tutor_utils()->count( $childrens ) ) {
394
+
$output .= __tutor_generate_categories_checkbox( $post_ID, $childrens, $args );
395
+
}
396
+
$output .= ' </li>';
397
+
}
398
+
$output .= '</ul>';
399
+
}
400
+
401
+
return $output;
402
+
403
+
}
404
+
}
405
+
/**
406
+
* @param $tags
407
+
* @param string $parent_name
408
+
* @param array $args
409
+
*
410
+
* @return string
411
+
*
412
+
* Internal function to generate course tags checkbox
413
+
*
414
+
* @since v.1.3.4
415
+
*/
416
+
if ( ! function_exists( '__tutor_generate_tags_checkbox' ) ) {
417
+
function __tutor_generate_tags_checkbox( $post_ID = 0, $tags = array(), $args = array() ) {
418
+
419
+
$output = '';
420
+
$input_name = tutor_utils()->array_get( 'name', $args );
421
+
422
+
if ( tutor_utils()->count( $tags ) ) {
423
+
$output .= '<ul class="tax-input-course-tag">';
424
+
foreach ( $tags as $tag ) {
425
+
$has_in_term = has_term( $tag->term_id, CourseModel::COURSE_TAG, $post_ID );
426
+
427
+
$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>';
428
+
429
+
$output .= ' </li>';
430
+
}
431
+
$output .= '</ul>';
432
+
}
433
+
434
+
return $output;
435
+
}
436
+
}
437
+
438
+
/**
439
+
* @param string $content
440
+
* @param string $title
441
+
*
442
+
* @return string
443
+
*
444
+
* Wrap course builder sections within div for frontend
445
+
*
446
+
* @since v.1.3.4
447
+
*/
448
+
449
+
if ( ! function_exists( 'course_builder_section_wrap' ) ) {
450
+
function course_builder_section_wrap( $content = '', $title = '', $echo = true ) {
451
+
$template = trailingslashit( tutor()->path . 'templates' ) . 'metabox-wrapper.php';
452
+
if ( $echo ) {
453
+
if ( file_exists( $template ) ) {
454
+
include $template;
455
+
} else {
456
+
echo esc_html( $template ) . esc_html__( 'file not exists', 'tutor' );
457
+
}
458
+
} else {
459
+
ob_start();
460
+
if ( file_exists( $template ) ) {
461
+
include $template;
462
+
} else {
463
+
echo esc_html( $template ) . esc_html__( 'file not exists', 'tutor' );
464
+
}
465
+
$html = ob_get_clean();
466
+
return $html;
467
+
}
468
+
}
469
+
}
470
+
471
+
472
+
if ( ! function_exists( 'get_tutor_header' ) ) {
473
+
function get_tutor_header( $fullScreen = false ) {
474
+
$enable_spotlight_mode = tutor_utils()->get_option( 'enable_spotlight_mode' );
475
+
476
+
if ( $enable_spotlight_mode || $fullScreen ) {
477
+
?>
478
+
<!doctype html>
479
+
<html <?php language_attributes(); ?>>
480
+
481
+
<head>
482
+
<meta charset="<?php bloginfo( 'charset' ); ?>" />
483
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
484
+
<link rel="profile" href="https://gmpg.org/xfn/11" />
485
+
<?php wp_head(); ?>
486
+
</head>
487
+
488
+
<body <?php body_class(); ?>>
489
+
<div id="tutor-page-wrap" class="tutor-site-wrap site">
490
+
<?php
491
+
} else {
492
+
tutor_utils()->tutor_custom_header();
493
+
}
494
+
}
495
+
}
496
+
497
+
if ( ! function_exists( 'get_tutor_footer' ) ) {
498
+
function get_tutor_footer( $fullScreen = false ) {
499
+
$enable_spotlight_mode = tutor_utils()->get_option( 'enable_spotlight_mode' );
500
+
if ( $enable_spotlight_mode || $fullScreen ) {
501
+
?>
502
+
</div>
503
+
<?php wp_footer(); ?>
504
+
505
+
</body>
506
+
507
+
</html>
508
+
<?php
509
+
} else {
510
+
tutor_utils()->tutor_custom_footer();
511
+
}
512
+
}
513
+
}
514
+
515
+
/**
516
+
* @param null $key
517
+
* @param bool $default
518
+
*
519
+
* @return array|bool|mixed
520
+
*
521
+
* Get tutor option by this helper function
522
+
*
523
+
* @since v.1.3.6
524
+
*/
525
+
if ( ! function_exists( 'get_tutor_option' ) ) {
526
+
function get_tutor_option( $key = null, $default = false ) {
527
+
return tutor_utils()->get_option( $key, $default );
528
+
}
529
+
}
530
+
531
+
/**
532
+
* @param null $key
533
+
* @param bool $value
534
+
*
535
+
* Update tutor option by this helper function
536
+
*
537
+
* @since v.1.3.6
538
+
*/
539
+
if ( ! function_exists( 'update_tutor_option' ) ) {
540
+
function update_tutor_option( $key = null, $value = false ) {
541
+
tutor_utils()->update_option( $key, $value );
542
+
}
543
+
}
544
+
/**
545
+
* @param int $course_id
546
+
* @param null $key
547
+
* @param bool $default
548
+
*
549
+
* @return array|bool|mixed
550
+
*
551
+
* Get tutor course settings by course ID
552
+
*
553
+
* @since v.1.4.1
554
+
*/
555
+
if ( ! function_exists( 'get_tutor_course_settings' ) ) {
556
+
function get_tutor_course_settings( $course_id = 0, $key = null, $default = false ) {
557
+
return tutor_utils()->get_course_settings( $course_id, $key, $default );
558
+
}
559
+
}
560
+
561
+
/**
562
+
* @param int $lesson_id
563
+
* @param null $key
564
+
* @param bool $default
565
+
*
566
+
* @return array|bool|mixed
567
+
*
568
+
* Get lesson content drip settings
569
+
*/
570
+
571
+
if ( ! function_exists( 'get_item_content_drip_settings' ) ) {
572
+
function get_item_content_drip_settings( $lesson_id = 0, $key = null, $default = false ) {
573
+
return tutor_utils()->get_item_content_drip_settings( $lesson_id, $key, $default );
574
+
}
575
+
}
576
+
577
+
/**
578
+
* @param null $msg
579
+
* @param string $type
580
+
* @param bool $echo
581
+
*
582
+
* @return string
583
+
*
584
+
* Print Alert by tutor_alert()
585
+
*
586
+
* @since v.1.4.1
587
+
*/
588
+
if ( ! function_exists( 'tutor_alert' ) ) {
589
+
function tutor_alert( $msg = null, $type = 'warning', $echo = true ) {
590
+
if ( ! $msg ) {
591
+
592
+
if ( $type === 'any' ) {
593
+
if ( ! $msg ) {
594
+
$type = 'warning';
595
+
$msg = tutor_flash_get( $type );
596
+
}
597
+
if ( ! $msg ) {
598
+
$type = 'danger';
599
+
$msg = tutor_flash_get( $type );
600
+
}
601
+
if ( ! $msg ) {
602
+
$type = 'success';
603
+
$msg = tutor_flash_get( $type );
604
+
}
605
+
} else {
606
+
$msg = tutor_flash_get( $type );
607
+
}
608
+
}
609
+
if ( ! $msg ) {
610
+
return $msg;
611
+
}
612
+
613
+
$html = '<div class="tutor-alert tutor-' . esc_attr( $type ) . '">
614
+
<div class="tutor-alert-text">
615
+
<span class="tutor-alert-icon tutor-fs-4 tutor-icon-circle-info tutor-mr-12"></span>
616
+
<span>' . wp_kses( $msg, array( 'div', 'span' ) ) . '</span>
617
+
</div>
618
+
</div>';
619
+
if ( $echo ) {
620
+
echo tutor_kses_html( $html ); //phpcs:ignore
621
+
}
622
+
return $html;
623
+
}
624
+
}
625
+
626
+
627
+
/**
628
+
* @param bool $echo
629
+
*
630
+
* Simply call tutor_nonce_field() to generate nonce field
631
+
*
632
+
* @since v.1.4.2
633
+
*/
634
+
635
+
if ( ! function_exists( 'tutor_nonce_field' ) ) {
636
+
function tutor_nonce_field( $echo = true ) {
637
+
wp_nonce_field( tutor()->nonce_action, tutor()->nonce, $echo );
638
+
}
639
+
}
640
+
641
+
/**
642
+
* @param null $key
643
+
* @param string $message
644
+
*
645
+
* Set Flash Message
646
+
*/
647
+
648
+
if ( ! function_exists( 'tutor_flash_set' ) ) {
649
+
function tutor_flash_set( $key = null, $message = '' ) {
650
+
if ( ! $key ) {
651
+
return;
652
+
}
653
+
// ensure session is started
654
+
if ( session_status() !== PHP_SESSION_ACTIVE ) {
655
+
session_start();
656
+
}
657
+
$_SESSION[ $key ] = $message;
658
+
}
659
+
}
660
+
661
+
/**
662
+
* @param null $key
663
+
*
664
+
* @return array|bool|mixed|null
665
+
*
666
+
* @since v.1.4.2
667
+
*
668
+
* Get flash message
669
+
*/
670
+
671
+
if ( ! function_exists( 'tutor_flash_get' ) ) {
672
+
function tutor_flash_get( $key = null ) {
673
+
if ( $key ) {
674
+
// ensure session is started
675
+
if ( session_status() !== PHP_SESSION_ACTIVE ) {
676
+
@session_start();
677
+
}
678
+
if ( empty( $_SESSION ) ) {
679
+
return null;
680
+
}
681
+
$message = tutor_utils()->array_get( $key, $_SESSION );
682
+
if ( $message ) {
683
+
unset( $_SESSION[ $key ] );
684
+
}
685
+
return $message;
686
+
}
687
+
return $key;
688
+
}
689
+
}
690
+
691
+
if ( ! function_exists( 'tutor_redirect_back' ) ) {
692
+
/**
693
+
* @param null $url
694
+
*
695
+
* Redirect to back or a specific URL and terminate
696
+
*
697
+
* @since v.1.4.3
698
+
*/
699
+
function tutor_redirect_back( $url = null ) {
700
+
if ( ! $url ) {
701
+
$url = tutor_utils()->referer();
702
+
}
703
+
wp_safe_redirect( $url );
704
+
exit();
705
+
}
706
+
}
707
+
708
+
/**
709
+
* @param string $action
710
+
* @param bool $echo
711
+
*
712
+
* @return string
713
+
*
714
+
* @since v.1.4.3
715
+
*/
716
+
717
+
if ( ! function_exists( 'tutor_action_field' ) ) {
718
+
function tutor_action_field( $action = '', $echo = true ) {
719
+
$output = '';
720
+
if ( $action ) {
721
+
$output = '<input type="hidden" name="tutor_action" value="' . esc_attr( $action ) . '">';
722
+
}
723
+
724
+
if ( $echo ) {
725
+
echo wp_kses(
726
+
$output,
727
+
array(
728
+
'input' => array(
729
+
'type' => true,
730
+
'name' => true,
731
+
'value' => true,
732
+
),
733
+
)
734
+
);
735
+
} else {
736
+
return $output;
737
+
}
738
+
}
739
+
}
740
+
741
+
742
+
if ( ! function_exists( 'tutor_time' ) ) {
743
+
/**
744
+
* Return current Time from WordPress time
745
+
*
746
+
* @return int|string
747
+
* @since v.1.4.3
748
+
*/
749
+
function tutor_time() {
750
+
$gmt_offset = get_option( 'gmt_offset' );
751
+
return time() + ( $gmt_offset * HOUR_IN_SECONDS );
752
+
}
753
+
}
754
+
755
+
/**
756
+
* Toggle maintenance mode for the site.
757
+
*
758
+
* Creates/deletes the maintenance file to enable/disable maintenance mode.
759
+
*
760
+
* @since v.1.4.6
761
+
*
762
+
* @global WP_Filesystem_Base $wp_filesystem Subclass
763
+
*
764
+
* @param bool $enable True to enable maintenance mode, false to disable.
765
+
*/
766
+
if ( ! function_exists( 'tutor_maintenance_mode' ) ) {
767
+
function tutor_maintenance_mode( $enable = false ) {
768
+
$file = ABSPATH . '.tutor_maintenance';
769
+
if ( $enable ) {
770
+
// Create maintenance file to signal that we are upgrading
771
+
$maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
772
+
773
+
if ( ! file_exists( $file ) ) {
774
+
file_put_contents( $file, $maintenance_string );
775
+
}
776
+
} else {
777
+
if ( file_exists( $file ) ) {
778
+
unlink( $file );
779
+
}
780
+
}
781
+
}
782
+
}
783
+
784
+
/**
785
+
* @return bool
786
+
*
787
+
* Check if the current page is course single page
788
+
*
789
+
* @since v.1.6.0
790
+
*/
791
+
792
+
if ( ! function_exists( 'is_single_course' ) ) {
793
+
function is_single_course( $check_spotlight = false ) {
794
+
global $wp_query;
795
+
$course_post_type = tutor()->course_post_type;
796
+
797
+
$post_types = array( $course_post_type );
798
+
if ( $check_spotlight ) {
799
+
$post_types = array_merge(
800
+
$post_types,
801
+
array(
802
+
'lesson',
803
+
'tutor_quiz',
804
+
'tutor_assignments',
805
+
'tutor_zoom_meeting',
806
+
)
807
+
);
808
+
}
809
+
810
+
if ( is_single() && ! empty( $wp_query->query['post_type'] ) && in_array( $wp_query->query['post_type'], $post_types ) ) {
811
+
return true;
812
+
}
813
+
return false;
814
+
}
815
+
}
816
+
817
+
/**
818
+
* Require wp_date form return js date format.
819
+
* this is helpful for date picker
820
+
*
821
+
* @return string
822
+
*
823
+
* @since 1.9.7
824
+
*/
825
+
if ( ! function_exists( 'tutor_js_date_format_against_wp' ) ) {
826
+
function tutor_js_date_format_against_wp() {
827
+
$wp_date_format = get_option( 'date_format' );
828
+
$default_format = 'Y-M-d';
829
+
830
+
$formats = array(
831
+
'Y-m-d' => 'Y-M-d',
832
+
'm/d/Y' => 'M-d-Y',
833
+
'd/m/Y' => 'd-M-Y',
834
+
'F j, Y' => 'MMMM d, yyyy',
835
+
'j F Y' => 'MMMM d, yyyy',
836
+
);
837
+
return isset( $formats[ $wp_date_format ] ) ? $formats[ $wp_date_format ] : $default_format;
838
+
}
839
+
}
840
+
841
+
if ( ! function_exists( 'tutor_get_formated_date' ) ) {
842
+
/**
843
+
* Convert date to desire format
844
+
*
845
+
* NOTE: mysql query use formated date from here
846
+
* that's why date_i18n need to be ignore
847
+
*
848
+
* @param string $require_format string If empty Y-m-d is used.
849
+
* @param string $user_date string Date.
850
+
*
851
+
* @return string ( date )
852
+
*/
853
+
function tutor_get_formated_date( string $require_format = '', string $user_date = '' ) {
854
+
$require_format = $require_format ?: 'Y-m-d';
855
+
856
+
$date = date_create( str_replace( '/', '-', $user_date ) );
857
+
if ( is_a( $date, 'DateTime' ) ) {
858
+
$formatted_date = date_format( $date, $require_format );
859
+
} else {
860
+
$formatted_date = gmdate( $require_format, strtotime( $user_date ) );
861
+
}
862
+
return $formatted_date;
863
+
}
864
+
}
865
+
866
+
/**
867
+
* Get translated date
868
+
*
869
+
* @since v2.0.2
870
+
*
871
+
* @param string $date date in string from to translate & format.
872
+
* @param string $format optional date format, default is wp date time format.
873
+
*
874
+
* @return string translated date
875
+
*/
876
+
if ( ! function_exists( 'tutor_i18n_get_formated_date' ) ) {
877
+
function tutor_i18n_get_formated_date( string $date, string $format = '' ) {
878
+
if ( '' === $format ) {
879
+
$format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
880
+
}
881
+
return date_i18n( $format, strtotime( $date ) );
882
+
}
883
+
}
884
+
885
+
if ( ! function_exists( '_tutor_search_by_title_only' ) ) {
886
+
/**
887
+
* Search SQL filter for matching against post title only.
888
+
*
889
+
* @link http://wordpress.stackexchange.com/a/11826/1685
890
+
*
891
+
* @param string $search
892
+
* @param WP_Query $wp_query
893
+
*/
894
+
function _tutor_search_by_title_only( $search, $wp_query ) {
895
+
if ( ! empty( $search ) && ! empty( $wp_query->query_vars['search_terms'] ) ) {
896
+
global $wpdb;
897
+
898
+
$q = $wp_query->query_vars;
899
+
$n = ! empty( $q['exact'] ) ? '' : '%';
900
+
901
+
$search = array();
902
+
903
+
foreach ( (array) $q['search_terms'] as $term ) {
904
+
$search[] = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $n . $wpdb->esc_like( $term ) . $n );
905
+
}
906
+
907
+
if ( ! is_user_logged_in() ) {
908
+
$search[] = "$wpdb->posts.post_password = ''";
909
+
}
910
+
911
+
$search = ' AND ' . implode( ' AND ', $search );
912
+
}
913
+
914
+
return $search;
915
+
}
916
+
}
917
+
918
+
if ( ! function_exists( 'get_request' ) ) {
919
+
/**
920
+
* Function to get_request
921
+
*
922
+
* @param array $var .
923
+
* @return array
924
+
*/
925
+
function get_request( $var ) {
926
+
return isset( $_REQUEST[ $var ] ) ? sanitize_text_field( $_REQUEST[ $var ] ) : false;
927
+
928
+
}
929
+
}
930
+
931
+
if ( ! function_exists( 'tutor_kses_allowed_html' ) ) {
932
+
function tutor_kses_allowed_html( $allowed_tags, $context ) {
933
+
$tags = array( 'input', 'style', 'script', 'select', 'form', 'option', 'optgroup', 'iframe', 'bdi', 'source', 'a' );
934
+
$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' );
935
+
936
+
foreach ( $tags as $tag ) {
937
+
$tag_attrs = array();
938
+
939
+
foreach ( $atts as $att ) {
940
+
$tag_attrs[ $att ] = true;
941
+
}
942
+
943
+
$allowed_tags[ $tag ] = $tag_attrs;
944
+
}
945
+
946
+
return $allowed_tags;
947
+
}
948
+
}
949
+
950
+
if ( ! function_exists( 'tutor_kses_allowed_css' ) ) {
951
+
function tutor_kses_allowed_css( $styles ) {
952
+
$styles[] = 'display';
953
+
$styles[] = '--progress-value';
954
+
return $styles;
955
+
}
956
+
}
957
+
958
+
if ( ! function_exists( 'tutor_kses_html' ) ) {
959
+
function tutor_kses_html( $content ) {
960
+
961
+
return $content;
962
+
add_filter( 'wp_kses_allowed_html', 'tutor_kses_allowed_html', 10, 2 );
963
+
add_filter( 'safe_style_css', 'tutor_kses_allowed_css' );
964
+
965
+
$content = preg_replace( '/<!--(.|\s)*?-->/', '', $content );
966
+
$content = wp_kses_post( $content );
967
+
$content = str_replace( '&', '&', $content );
968
+
969
+
remove_filter( 'safe_style_css', 'tutor_kses_allowed_css' );
970
+
remove_filter( 'wp_kses_allowed_html', 'tutor_kses_allowed_html' );
971
+
972
+
return $content;
973
+
}
974
+
}
975
+
976
+
/**
977
+
* @return array
978
+
*
979
+
* Get all Withdraw Methods available on this system
980
+
*
981
+
* @since v.1.5.7
982
+
*/
983
+
if ( ! function_exists( 'get_tutor_all_withdrawal_methods' ) ) {
984
+
function get_tutor_all_withdrawal_methods() {
985
+
return apply_filters( 'tutor_withdrawal_methods_all', array() );
986
+
}
987
+
}
988
+
989
+
990
+
if ( ! function_exists( 'tutor_log' ) ) {
991
+
/**
992
+
* Logging data.
993
+
*
994
+
* @since 1.0.0
995
+
* @since 3.0.0 exception logging support added.
996
+
*
997
+
* @return void
998
+
*/
999
+
function tutor_log() {
1000
+
$arg_list = func_get_args();
1001
+
1002
+
foreach ( $arg_list as $data ) {
1003
+
ob_start();
1004
+
1005
+
if ( $data instanceof Exception ) {
1006
+
var_dump( $data->getMessage() );
1007
+
var_dump( $data->getTraceAsString() );
1008
+
} else {
1009
+
var_dump( $data );
1010
+
}
1011
+
1012
+
error_log( ob_get_clean() );
1013
+
}
1014
+
}
1015
+
}
1016
+
1017
+
if ( ! function_exists( 'tutor_wc_price_currency_format' ) ) {
1018
+
function tutor_wc_price_currency_format( $amount ) {
1019
+
1020
+
$symbol = get_woocommerce_currency_symbol();
1021
+
$position = get_option( 'woocommerce_currency_pos', 'left' );
1022
+
1023
+
switch ( $position ) {
1024
+
case 'left':
1025
+
$amount = $symbol . $amount;
1026
+
break;
1027
+
case 'left_space':
1028
+
$amount = $symbol . ' ' . $amount;
1029
+
break;
1030
+
1031
+
case 'right':
1032
+
$amount = $amount . $symbol;
1033
+
break;
1034
+
case 'right_space':
1035
+
$amount = $amount . ' ' . $symbol;
1036
+
break;
1037
+
1038
+
default:
1039
+
$amount = $symbol . $amount;
1040
+
break;
1041
+
}
1042
+
1043
+
return $amount;
1044
+
}
1045
+
}
1046
+
1047
+
if ( ! function_exists( 'tutor_meta_box_wrapper' ) ) {
1048
+
/**
1049
+
* Tutor meta box wrapper
1050
+
*
1051
+
* @since v2.0.2
1052
+
*
1053
+
* @param string $id id of meta box.
1054
+
* @param string $title meta box title.
1055
+
* @param mixed $callback callback function that meta box will call.
1056
+
* @param string $screen which screen meta box should appear.
1057
+
* @param string $context optional param. Where meta box should appear.
1058
+
* @param string $priority optional.
1059
+
* @param string $custom_class optional. If provide it will add this class along
1060
+
* with div id.
1061
+
*
1062
+
* @return void if class provided then filter hook will return class.
1063
+
*/
1064
+
function tutor_meta_box_wrapper(
1065
+
$id,
1066
+
$title,
1067
+
$callback,
1068
+
$screen,
1069
+
$context = 'advanced',
1070
+
$priority = 'default',
1071
+
$custom_class = ''
1072
+
) {
1073
+
add_meta_box(
1074
+
$id,
1075
+
$title,
1076
+
$callback,
1077
+
$screen,
1078
+
$context,
1079
+
$priority
1080
+
);
1081
+
if ( '' !== $custom_class ) {
1082
+
$post_type = tutor()->course_post_type;
1083
+
add_filter(
1084
+
"postbox_classes_{$post_type}_{$id}",
1085
+
function( $classes ) use ( $custom_class ) {
1086
+
if ( ! in_array( $custom_class, $classes ) ) {
1087
+
$classes[] = $custom_class;
1088
+
}
1089
+
return $classes;
1090
+
}
1091
+
);
1092
+
}
1093
+
}
1094
+
}
1095
+
1096
+
if ( ! function_exists( 'tutor_closeable_alert_msg' ) ) {
1097
+
/**
1098
+
* Create a close-able alert message
1099
+
*
1100
+
* @since 2.1.9
1101
+
* @since 3.7.1 param css_class added to pass any custom css class.
1102
+
*
1103
+
* @param string $message alert message.
1104
+
* @param string $alert alert key like: success, warning, danger, etc.
1105
+
* @param array $allowed_tags allowed tags to use with WP_KSES.
1106
+
* @param string $css_class custom css class.
1107
+
*
1108
+
* @return void
1109
+
*/
1110
+
function tutor_closeable_alert_msg( string $message, string $alert = 'success', $allowed_tags = array(), $css_class = '' ) {
1111
+
?>
1112
+
<div class="tutor-alert tutor-<?php echo esc_attr( $alert ); ?> <?php echo esc_attr( $css_class ); ?> tutor-mb-12 tutor-alert tutor-success tutor-mb-12 tutor-d-flex tutor-align-center tutor-justify-between">
1113
+
<span>
1114
+
<?php echo is_array( $allowed_tags ) && count( $allowed_tags ) ? wp_kses( $message, $allowed_tags ) : esc_html( $message ); ?>
1115
+
</span>
1116
+
<span class="tutor-icon-times" area-hidden="true" onclick="this.closest('div').remove()" style="cursor: pointer;"></span>
1117
+
</div>
1118
+
<?php
1119
+
}
1120
+
}
1121
+
1122
+
if ( ! function_exists( 'tutor_set_flash_message' ) ) {
1123
+
/**
1124
+
* Utility API Set flash message to show somewhere
1125
+
*
1126
+
* It will call set_cache method of FlashMessage class to set cache
1127
+
*
1128
+
* @param mixed $message message to show.
1129
+
* @param string $alert alert type as FlashMessage::$alert_types.
1130
+
*
1131
+
* @return void
1132
+
*/
1133
+
function tutor_set_flash_message( $message = '', $alert = 'success' ) {
1134
+
$flash_msg = new FlashMessage( $message, $alert );
1135
+
$flash_msg->set_cache();
1136
+
}
1137
+
}
1138
+
1139
+
1140
+
if ( ! function_exists( 'tutor_snackbar' ) ) {
1141
+
/**
1142
+
* Reuseable snackbar to show on the frontend
1143
+
*
1144
+
* Create a snackbar based on title, action buttons
1145
+
*
1146
+
* @since 2.2.0
1147
+
*
1148
+
* @param string $title title to show.
1149
+
* @param array $action_buttons 2 dimensional array of action buttons to show.
1150
+
* Supported attrs: [ [title => title, id => '', class => '' url => '', target => ''] ].
1151
+
* @param string $title_icon_class title icon to show before title.
1152
+
*
1153
+
* @return void
1154
+
*/
1155
+
function tutor_snackbar( string $title, array $action_buttons = array(), $title_icon_class = '' ) {
1156
+
?>
1157
+
<div id="tutor-reuseable-snackbar" class="tutor-snackbar-wrapper">
1158
+
<div class="tutor-snackbar">
1159
+
<p>
1160
+
<?php if ( ! empty( $title_icon_class ) ) : ?>
1161
+
<i class="tutor-snackbar-title-icon <?php echo esc_attr( $title_icon_class ); ?>"></i>
1162
+
<?php endif; ?>
1163
+
<?php echo esc_html( $title ); ?>
1164
+
</p>
1165
+
<div>
1166
+
<?php foreach ( $action_buttons as $attr => $button ) : ?>
1167
+
<a
1168
+
<?php foreach ( $button as $attr => $value ) : ?>
1169
+
<?php if ( ! empty( $value ) ) : ?>
1170
+
<?php echo esc_attr( $attr ) . '="' . esc_attr( $value ) . '" '; ?>
1171
+
<?php endif; ?>
1172
+
<?php endforeach; ?>
1173
+
>
1174
+
<?php echo esc_html( isset( $button['title'] ) ? $button['title'] : '' ); ?>
1175
+
</a>
1176
+
<?php endforeach; ?>
1177
+
<span class="tutor-icon-times" area-hidden="true" onclick="this.closest('#tutor-reuseable-snackbar').remove()" style="cursor: pointer;"></span>
1178
+
</div>
1179
+
</div>
1180
+
</div>
1181
+
<?php
1182
+
}
1183
+
}
1184
+
1185
+
if ( ! function_exists( 'tutor_is_rest' ) ) {
1186
+
/**
1187
+
* Checks if the current request is a WP REST API request.
1188
+
*
1189
+
* @since 2.6.0
1190
+
*
1191
+
* Case #1: After WP_REST_Request initialisation
1192
+
* Case #2: Support "plain" permalink settings and check if `rest_route` starts with `/`
1193
+
* Case #3: It can happen that WP_Rewrite is not yet initialized,
1194
+
* so do this (wp-settings.php)
1195
+
* Case #4: URL Path begins with wp-json/ (your REST prefix)
1196
+
* Also supports WP installations in subfolders
1197
+
*
1198
+
* @see https://wordpress.stackexchange.com/questions/221202/does-something-like-is-rest-exist
1199
+
* @returns boolean
1200
+
*/
1201
+
function tutor_is_rest() {
1202
+
$rest_route = Input::get( 'rest_route' );
1203
+
if ( defined( 'REST_REQUEST' ) && REST_REQUEST || $rest_route && strpos( $rest_route, '/', 0 ) === 0 ) {
1204
+
return true;
1205
+
}
1206
+
1207
+
// (#3)
1208
+
global $wp_rewrite;
1209
+
if ( null === $wp_rewrite ) {
1210
+
$wp_rewrite = new WP_Rewrite();
1211
+
}
1212
+
1213
+
// (#4)
1214
+
$rest_url = wp_parse_url( trailingslashit( rest_url() ) );
1215
+
$current_url = wp_parse_url( add_query_arg( array() ) );
1216
+
return strpos( $current_url['path'] ?? '/', $rest_url['path'], 0 ) === 0;
1217
+
}
1218
+
}
1219
+
1220
+
if ( ! function_exists( 'tutor_getallheaders' ) ) {
1221
+
/**
1222
+
* Wrapper of PHP getallheaders with a fallback if getallheaders not available
1223
+
*
1224
+
* @since 2.6.0
1225
+
*
1226
+
* @see https://www.php.net/manual/en/function.getallheaders.php
1227
+
*
1228
+
* @return array of headers
1229
+
*/
1230
+
function tutor_getallheaders() {
1231
+
$headers = array();
1232
+
if ( function_exists( 'getallheaders' ) ) {
1233
+
$headers = getallheaders();
1234
+
}
1235
+
1236
+
if ( ! $headers ) {
1237
+
foreach ( $_SERVER as $name => $value ) {
1238
+
if ( substr( $name, 0, 5 ) == 'HTTP_' ) {
1239
+
$headers[ str_replace( ' ', '-', ucwords( strtolower( str_replace( '_', ' ', substr( $name, 5 ) ) ) ) ) ] = $value;
1240
+
}
1241
+
}
1242
+
}
1243
+
1244
+
return $headers;
1245
+
}
1246
+
}
1247
+
1248
+
if ( ! function_exists( 'tutor_entry_box_buttons' ) ) {
1249
+
/**
1250
+
* Tutor conditional buttons for the enrollment box
1251
+
*
1252
+
* @since 2.6.0
1253
+
*
1254
+
* @param int $course_id course id.
1255
+
* @param int $user_id user id.
1256
+
*
1257
+
* @return object
1258
+
*/
1259
+
function tutor_entry_box_buttons( int $course_id = 0, int $user_id = 0 ) {
1260
+
$conditional_buttons = (object) array(
1261
+
'show_enroll_btn' => false,
1262
+
'show_add_to_cart_btn' => false,
1263
+
'show_view_cart_btn' => false,
1264
+
'show_start_learning_btn' => false,
1265
+
'show_continue_learning_btn' => false,
1266
+
'show_complete_course_btn' => false,
1267
+
'show_retake_course_btn' => false,
1268
+
'show_certificate_view_btn' => false,
1269
+
'show_course_fully_booked_btn' => false,
1270
+
);
1271
+
1272
+
$course_id = tutor_utils()->get_post_id( $course_id );
1273
+
$user_id = tutor_utils()->get_user_id( $user_id );
1274
+
1275
+
$has_course_access = tutor_utils()->has_user_course_content_access( $user_id, $course_id );
1276
+
1277
+
$is_public_course = get_post_meta( $course_id, '_tutor_is_public_course', true );
1278
+
1279
+
$is_enabled_retake = tutor_utils()->get_option( 'course_retake_feature' );
1280
+
1281
+
$is_enrolled = tutor_utils()->is_enrolled( $course_id, $user_id );
1282
+
1283
+
if ( 'yes' === $is_public_course ) {
1284
+
$conditional_buttons->show_start_learning_btn = true;
1285
+
} else {
1286
+
// Admin & instructor can manage posts.
1287
+
if ( $is_enrolled || $has_course_access ) {
1288
+
$can_complete_course = CourseModel::can_complete_course( $course_id, $user_id );
1289
+
$is_completed_course = tutor_utils()->is_completed_course( $course_id, $user_id );
1290
+
$course_progress = (int) tutor_utils()->get_course_completed_percent( $course_id, $user_id );
1291
+
1292
+
if ( $course_progress > 0 && $course_progress < 100 ) {
1293
+
$conditional_buttons->show_continue_learning_btn = true;
1294
+
}
1295
+
1296
+
if ( 0 === $course_progress ) {
1297
+
$conditional_buttons->show_start_learning_btn = true;
1298
+
}
1299
+
1300
+
if ( $can_complete_course ) {
1301
+
$conditional_buttons->show_complete_course_btn = true;
1302
+
}
1303
+
1304
+
if ( $is_completed_course ) {
1305
+
$conditional_buttons->show_certificate_view_btn = true;
1306
+
}
1307
+
1308
+
if ( $is_enabled_retake && $is_completed_course ) {
1309
+
$conditional_buttons->show_retake_course_btn = true;
1310
+
}
1311
+
} else {
1312
+
$is_paid_course = tutor_utils()->is_course_purchasable( $course_id );
1313
+
if ( $is_paid_course ) {
1314
+
if ( tutor_is_item_in_cart( $course_id ) ) {
1315
+
$conditional_buttons->show_view_cart_btn = true;
1316
+
} else {
1317
+
$conditional_buttons->show_add_to_cart_btn = true;
1318
+
}
1319
+
} else {
1320
+
$conditional_buttons->show_enroll_btn = true;
1321
+
}
1322
+
}
1323
+
}
1324
+
1325
+
if ( ! $is_public_course && ! ( $is_enrolled || $has_course_access ) ) {
1326
+
$is_fully_booked = tutor_utils()->is_course_fully_booked( $course_id );
1327
+
if ( $is_fully_booked ) {
1328
+
$conditional_buttons->show_course_fully_booked_btn = true;
1329
+
}
1330
+
}
1331
+
1332
+
return apply_filters( 'tutor_enrollment_buttons', $conditional_buttons, $course_id, $user_id );
1333
+
}
1334
+
}
1335
+
1336
+
if ( ! function_exists( 'tutor_global_timezone_lists' ) ) {
1337
+
/**
1338
+
* Get list of global timezones
1339
+
*
1340
+
* @return array
1341
+
*/
1342
+
function tutor_global_timezone_lists() {
1343
+
return array(
1344
+
'Pacific/Midway' => '(GMT-11:00) Midway Island, Samoa ',
1345
+
'Pacific/Pago_Pago' => '(GMT-11:00) Pago Pago ',
1346
+
'Pacific/Honolulu' => '(GMT-10:00) Hawaii ',
1347
+
'America/Anchorage' => '(GMT-8:00) Alaska ',
1348
+
'America/Vancouver' => '(GMT-7:00) Vancouver ',
1349
+
'America/Los_Angeles' => '(GMT-7:00) Pacific Time (US and Canada) ',
1350
+
'America/Tijuana' => '(GMT-7:00) Tijuana ',
1351
+
'America/Phoenix' => '(GMT-7:00) Arizona ',
1352
+
'America/Edmonton' => '(GMT-6:00) Edmonton ',
1353
+
'America/Denver' => '(GMT-6:00) Mountain Time (US and Canada) ',
1354
+
'America/Mazatlan' => '(GMT-6:00) Mazatlan ',
1355
+
'America/Regina' => '(GMT-6:00) Saskatchewan ',
1356
+
'America/Guatemala' => '(GMT-6:00) Guatemala ',
1357
+
'America/El_Salvador' => '(GMT-6:00) El Salvador ',
1358
+
'America/Managua' => '(GMT-6:00) Managua ',
1359
+
'America/Costa_Rica' => '(GMT-6:00) Costa Rica ',
1360
+
'America/Tegucigalpa' => '(GMT-6:00) Tegucigalpa ',
1361
+
'America/Winnipeg' => '(GMT-5:00) Winnipeg ',
1362
+
'America/Chicago' => '(GMT-5:00) Central Time (US and Canada) ',
1363
+
'America/Mexico_City' => '(GMT-5:00) Mexico City ',
1364
+
'America/Panama' => '(GMT-5:00) Panama ',
1365
+
'America/Bogota' => '(GMT-5:00) Bogota ',
1366
+
'America/Lima' => '(GMT-5:00) Lima ',
1367
+
'America/Caracas' => '(GMT-4:30) Caracas ',
1368
+
'America/Montreal' => '(GMT-4:00) Montreal ',
1369
+
'America/New_York' => '(GMT-4:00) Eastern Time (US and Canada) ',
1370
+
'America/Indianapolis' => '(GMT-4:00) Indiana (East) ',
1371
+
'America/Puerto_Rico' => '(GMT-4:00) Puerto Rico ',
1372
+
'America/Santiago' => '(GMT-4:00) Santiago ',
1373
+
'America/Halifax' => '(GMT-3:00) Halifax ',
1374
+
'America/Montevideo' => '(GMT-3:00) Montevideo ',
1375
+
'America/Araguaina' => '(GMT-3:00) Brasilia ',
1376
+
'America/Argentina/Buenos_Aires' => '(GMT-3:00) Buenos Aires, Georgetown ',
1377
+
'America/Sao_Paulo' => '(GMT-3:00) Sao Paulo ',
1378
+
'Canada/Atlantic' => '(GMT-3:00) Atlantic Time (Canada) ',
1379
+
'America/St_Johns' => '(GMT-2:30) Newfoundland and Labrador ',
1380
+
'America/Godthab' => '(GMT-2:00) Greenland ',
1381
+
'Atlantic/Cape_Verde' => '(GMT-1:00) Cape Verde Islands ',
1382
+
'Atlantic/Azores' => '(GMT+0:00) Azores ',
1383
+
'UTC' => '(GMT+0:00) Universal Time UTC ',
1384
+
'Etc/Greenwich' => '(GMT+0:00) Greenwich Mean Time ',
1385
+
'Atlantic/Reykjavik' => '(GMT+0:00) Reykjavik ',
1386
+
'Africa/Nouakchott' => '(GMT+0:00) Nouakchott ',
1387
+
'Europe/Dublin' => '(GMT+1:00) Dublin ',
1388
+
'Europe/London' => '(GMT+1:00) London ',
1389
+
'Europe/Lisbon' => '(GMT+1:00) Lisbon ',
1390
+
'Africa/Casablanca' => '(GMT+1:00) Casablanca ',
1391
+
'Africa/Bangui' => '(GMT+1:00) West Central Africa ',
1392
+
'Africa/Algiers' => '(GMT+1:00) Algiers ',
1393
+
'Africa/Tunis' => '(GMT+1:00) Tunis ',
1394
+
'Europe/Belgrade' => '(GMT+2:00) Belgrade, Bratislava, Ljubljana ',
1395
+
'CET' => '(GMT+2:00) Sarajevo, Skopje, Zagreb ',
1396
+
'Europe/Oslo' => '(GMT+2:00) Oslo ',
1397
+
'Europe/Copenhagen' => '(GMT+2:00) Copenhagen ',
1398
+
'Europe/Brussels' => '(GMT+2:00) Brussels ',
1399
+
'Europe/Berlin' => '(GMT+2:00) Amsterdam, Berlin, Rome, Stockholm, Vienna ',
1400
+
'Europe/Amsterdam' => '(GMT+2:00) Amsterdam ',
1401
+
'Europe/Rome' => '(GMT+2:00) Rome ',
1402
+
'Europe/Stockholm' => '(GMT+2:00) Stockholm ',
1403
+
'Europe/Vienna' => '(GMT+2:00) Vienna ',
1404
+
'Europe/Luxembourg' => '(GMT+2:00) Luxembourg ',
1405
+
'Europe/Paris' => '(GMT+2:00) Paris ',
1406
+
'Europe/Zurich' => '(GMT+2:00) Zurich ',
1407
+
'Europe/Madrid' => '(GMT+2:00) Madrid ',
1408
+
'Africa/Harare' => '(GMT+2:00) Harare, Pretoria ',
1409
+
'Europe/Warsaw' => '(GMT+2:00) Warsaw ',
1410
+
'Europe/Prague' => '(GMT+2:00) Prague Bratislava ',
1411
+
'Europe/Budapest' => '(GMT+2:00) Budapest ',
1412
+
'Africa/Tripoli' => '(GMT+2:00) Tripoli ',
1413
+
'Africa/Cairo' => '(GMT+2:00) Cairo ',
1414
+
'Africa/Johannesburg' => '(GMT+2:00) Johannesburg ',
1415
+
'Europe/Helsinki' => '(GMT+3:00) Helsinki ',
1416
+
'Africa/Nairobi' => '(GMT+3:00) Nairobi ',
1417
+
'Europe/Sofia' => '(GMT+3:00) Sofia ',
1418
+
'Europe/Istanbul' => '(GMT+3:00) Istanbul ',
1419
+
'Europe/Athens' => '(GMT+3:00) Athens ',
1420
+
'Europe/Bucharest' => '(GMT+3:00) Bucharest ',
1421
+
'Asia/Nicosia' => '(GMT+3:00) Nicosia ',
1422
+
'Asia/Beirut' => '(GMT+3:00) Beirut ',
1423
+
'Asia/Damascus' => '(GMT+3:00) Damascus ',
1424
+
'Asia/Jerusalem' => '(GMT+3:00) Jerusalem ',
1425
+
'Asia/Amman' => '(GMT+3:00) Amman ',
1426
+
'Europe/Moscow' => '(GMT+3:00) Moscow ',
1427
+
'Asia/Baghdad' => '(GMT+3:00) Baghdad ',
1428
+
'Asia/Kuwait' => '(GMT+3:00) Kuwait ',
1429
+
'Asia/Riyadh' => '(GMT+3:00) Riyadh ',
1430
+
'Asia/Bahrain' => '(GMT+3:00) Bahrain ',
1431
+
'Asia/Qatar' => '(GMT+3:00) Qatar ',
1432
+
'Asia/Aden' => '(GMT+3:00) Aden ',
1433
+
'Africa/Khartoum' => '(GMT+3:00) Khartoum ',
1434
+
'Africa/Djibouti' => '(GMT+3:00) Djibouti ',
1435
+
'Africa/Mogadishu' => '(GMT+3:00) Mogadishu ',
1436
+
'Europe/Kiev' => '(GMT+3:00) Kiev ',
1437
+
'Asia/Dubai' => '(GMT+4:00) Dubai ',
1438
+
'Asia/Muscat' => '(GMT+4:00) Muscat ',
1439
+
'Asia/Tehran' => '(GMT+4:30) Tehran ',
1440
+
'Asia/Kabul' => '(GMT+4:30) Kabul ',
1441
+
'Asia/Baku' => '(GMT+5:00) Baku, Tbilisi, Yerevan ',
1442
+
'Asia/Yekaterinburg' => '(GMT+5:00) Yekaterinburg ',
1443
+
'Asia/Tashkent' => '(GMT+5:00) Tashkent ',
1444
+
'Asia/Karachi' => '(GMT+5:00) Islamabad, Karachi ',
1445
+
'Asia/Calcutta' => '(GMT+5:30) India ',
1446
+
'Asia/Kolkata' => '(GMT+5:30) Mumbai, Kolkata, New Delhi ',
1447
+
'Asia/Kathmandu' => '(GMT+5:45) Kathmandu ',
1448
+
'Asia/Novosibirsk' => '(GMT+6:00) Novosibirsk ',
1449
+
'Asia/Almaty' => '(GMT+6:00) Almaty ',
1450
+
'Asia/Dacca' => '(GMT+6:00) Dacca ',
1451
+
'Asia/Dhaka' => '(GMT+6:00) Astana, Dhaka ',
1452
+
'Asia/Krasnoyarsk' => '(GMT+7:00) Krasnoyarsk ',
1453
+
'Asia/Bangkok' => '(GMT+7:00) Bangkok ',
1454
+
'Asia/Saigon' => '(GMT+7:00) Vietnam ',
1455
+
'Asia/Jakarta' => '(GMT+7:00) Jakarta ',
1456
+
'Asia/Irkutsk' => '(GMT+8:00) Irkutsk, Ulaanbaatar ',
1457
+
'Asia/Shanghai' => '(GMT+8:00) Beijing, Shanghai ',
1458
+
'Asia/Hong_Kong' => '(GMT+8:00) Hong Kong ',
1459
+
'Asia/Taipei' => '(GMT+8:00) Taipei ',
1460
+
'Asia/Kuala_Lumpur' => '(GMT+8:00) Kuala Lumpur ',
1461
+
'Asia/Singapore' => '(GMT+8:00) Singapore ',
1462
+
'Australia/Perth' => '(GMT+8:00) Perth ',
1463
+
'Asia/Yakutsk' => '(GMT+9:00) Yakutsk ',
1464
+
'Asia/Seoul' => '(GMT+9:00) Seoul ',
1465
+
'Asia/Tokyo' => '(GMT+9:00) Osaka, Sapporo, Tokyo ',
1466
+
'Australia/Darwin' => '(GMT+9:30) Darwin ',
1467
+
'Australia/Adelaide' => '(GMT+9:30) Adelaide ',
1468
+
'Asia/Vladivostok' => '(GMT+10:00) Vladivostok ',
1469
+
'Pacific/Port_Moresby' => '(GMT+10:00) Guam, Port Moresby ',
1470
+
'Australia/Brisbane' => '(GMT+10:00) Brisbane ',
1471
+
'Australia/Sydney' => '(GMT+10:00) Canberra, Melbourne, Sydney ',
1472
+
'Australia/Hobart' => '(GMT+10:00) Hobart ',
1473
+
'Asia/Magadan' => '(GMT+10:00) Magadan ',
1474
+
'SST' => '(GMT+11:00) Solomon Islands ',
1475
+
'Pacific/Noumea' => '(GMT+11:00) New Caledonia ',
1476
+
'Asia/Kamchatka' => '(GMT+12:00) Kamchatka ',
1477
+
'Pacific/Fiji' => '(GMT+12:00) Fiji Islands, Marshall Islands ',
1478
+
'Pacific/Auckland' => '(GMT+12:00) Auckland, Wellington',
1479
+
);
1480
+
}
1481
+
1482
+
if ( ! function_exists( 'tutor_get_all_active_payment_gateways' ) ) {
1483
+
/**
1484
+
* Get all active payment gateways including manual & automate
1485
+
*
1486
+
* @since 3.0.0
1487
+
*
1488
+
* @return array
1489
+
*/
1490
+
function tutor_get_all_active_payment_gateways() {
1491
+
$payment_settings = Settings::get_payment_settings();
1492
+
$payment_methods = ! empty( $payment_settings['payment_methods'] ) ? $payment_settings['payment_methods'] : array();
1493
+
1494
+
$active_gateways = array();
1495
+
1496
+
foreach ( $payment_methods as $method ) {
1497
+
$is_active = $method['is_active'] ?? false;
1498
+
$is_manual = $method['is_manual'] ?? false;
1499
+
if ( ! $is_active ) {
1500
+
continue;
1501
+
}
1502
+
1503
+
if ( ! Ecommerce::is_payment_gateway_configured( $method['name'] ) ) {
1504
+
continue;
1505
+
}
1506
+
1507
+
$fields = $method['fields'];
1508
+
unset( $method['fields'] );
1509
+
1510
+
$gateway = $method;
1511
+
if ( $is_manual ) {
1512
+
foreach ( $fields as $field ) {
1513
+
if ( 'payment_instructions' === $field['name'] || 'additional_details' === $field['name'] ) {
1514
+
$gateway[ $field['name'] ] = $field['value'];
1515
+
}
1516
+
}
1517
+
}
1518
+
1519
+
$active_gateways[] = $gateway;
1520
+
}
1521
+
1522
+
return $active_gateways;
1523
+
}
1524
+
}
1525
+
1526
+
if ( ! function_exists( 'tutor_get_subscription_supported_payment_gateways' ) ) {
1527
+
/**
1528
+
* Get all supported gateways
1529
+
*
1530
+
* This function will return only subscription supported gateways if
1531
+
* plan id provided.
1532
+
*
1533
+
* @since 3.0.0
1534
+
* @since 3.4.0 plan_id param removed
1535
+
*
1536
+
* @return array
1537
+
*/
1538
+
function tutor_get_subscription_supported_payment_gateways() {
1539
+
$payment_gateways = tutor_get_all_active_payment_gateways();
1540
+
1541
+
$supported_gateways = array();
1542
+
foreach ( $payment_gateways as $gateway ) {
1543
+
$support_subscription = $gateway['support_subscription'] ?? false;
1544
+
1545
+
if ( ! $support_subscription ) {
1546
+
continue;
1547
+
}
1548
+
1549
+
$supported_gateways[] = array(
1550
+
'name' => $gateway['name'] ?? '',
1551
+
'label' => $gateway['label'] ?? '',
1552
+
'icon' => $gateway['icon'] ?? '',
1553
+
'support_subscription' => $gateway['support_subscription'] ?? '',
1554
+
'is_manual' => $gateway['is_manual'] ?? '',
1555
+
'additional_details' => $gateway['additional_details'] ?? '',
1556
+
'payment_instructions' => $gateway['payment_instructions'] ?? '',
1557
+
);
1558
+
}
1559
+
1560
+
return $supported_gateways;
1561
+
}
1562
+
}
1563
+
1564
+
if ( ! function_exists( 'tutor_get_manual_payment_gateways' ) ) {
1565
+
/**
1566
+
* Get manual payment gateways
1567
+
*
1568
+
* @since 3.0.0
1569
+
*
1570
+
* @return array
1571
+
*/
1572
+
function tutor_get_manual_payment_gateways() {
1573
+
$payments = tutor_utils()->get_option( 'payment_settings' );
1574
+
$payments = json_decode( stripslashes( $payments ) );
1575
+
1576
+
$manual_methods = array();
1577
+
1578
+
if ( $payments ) {
1579
+
foreach ( $payments->payment_methods as $method ) {
1580
+
if ( isset( $method->is_manual ) && 1 === (int) $method->is_manual ) {
1581
+
$manual_methods[] = $method;
1582
+
}
1583
+
}
1584
+
}
1585
+
1586
+
return apply_filters( 'tutor_manual_payment_methods', $manual_methods );
1587
+
}
1588
+
}
1589
+
}
1590
+
1591
+
if ( ! function_exists( 'tutor_get_course_formatted_price_html' ) ) {
1592
+
/**
1593
+
* Get course formatted price
1594
+
* Only for monetized by tutor.
1595
+
*
1596
+
* @since 3.0.0
1597
+
*
1598
+
* @param int $course_id Course price.
1599
+
* @param boolean $echo Whether to echo content.
1600
+
*
1601
+
* @return string|void
1602
+
*/
1603
+
function tutor_get_course_formatted_price_html( $course_id, $echo = true ) {
1604
+
$price_data = tutor_utils()->get_raw_course_price( $course_id );
1605
+
1606
+
if ( ! $price_data->regular_price ) {
1607
+
return;
1608
+
}
1609
+
ob_start();
1610
+
?>
1611
+
<div class="list-item-price tutor-item-price">
1612
+
<?php if ( $price_data->sale_price ) : ?>
1613
+
<span><?php tutor_print_formatted_price( $price_data->display_price ); ?></span>
1614
+
<del><?php tutor_print_formatted_price( $price_data->regular_price ); ?></del>
1615
+
<?php else : ?>
1616
+
<span><?php tutor_print_formatted_price( $price_data->display_price ); ?></span>
1617
+
<?php endif; ?>
1618
+
</div>
1619
+
<?php if ( $price_data->show_incl_tax_label ) : ?>
1620
+
<div class="tutor-course-price-tax tutor-fs-8 tutor-fw-normal tutor-color-black"><?php esc_html_e( 'Incl. tax', 'tutor' ); ?></div>
1621
+
<?php endif; ?>
1622
+
<?php
1623
+
$content = apply_filters( 'tutor_course_formatted_price', ob_get_clean() );
1624
+
if ( $echo ) {
1625
+
echo $content; // PHPCS:ignore
1626
+
} else {
1627
+
return $content;
1628
+
}
1629
+
}
1630
+
}
1631
+
1632
+
if ( ! function_exists( 'tutor_get_formatted_price' ) ) {
1633
+
/**
1634
+
* Get course formatted price
1635
+
*
1636
+
* Formatting as per ecommerce price settings
1637
+
*
1638
+
* @since 3.0.0
1639
+
*
1640
+
* @param mixed $price Raw price.
1641
+
*
1642
+
* @return string|void
1643
+
*/
1644
+
function tutor_get_formatted_price( $price ) {
1645
+
$price = floatval( Input::sanitize( $price ) );
1646
+
$monetize_by = tutor_utils()->get_option( 'monetize_by' );
1647
+
if ( Ecommerce::MONETIZE_BY === $monetize_by ) {
1648
+
$currency_symbol = Settings::get_currency_symbol_by_code( tutor_utils()->get_option( OptionKeys::CURRENCY_CODE, 'USD' ) );
1649
+
$currency_position = tutor_utils()->get_option( OptionKeys::CURRENCY_POSITION, 'left' );
1650
+
$thousand_separator = tutor_utils()->get_option( OptionKeys::THOUSAND_SEPARATOR, ',' );
1651
+
$decimal_separator = tutor_utils()->get_option( OptionKeys::DECIMAL_SEPARATOR, '.' );
1652
+
$no_of_decimal = tutor_utils()->get_option( OptionKeys::NUMBER_OF_DECIMALS, '2' );
1653
+
1654
+
$price = number_format( $price, $no_of_decimal, $decimal_separator, $thousand_separator );
1655
+
$price = 'left' === $currency_position ? $currency_symbol . $price : $price . $currency_symbol;
1656
+
} elseif ( 'wc' === $monetize_by ) {
1657
+
$price = wc_price( $price );
1658
+
} elseif ( 'edd' === $monetize_by ) {
1659
+
$price = edd_currency_filter( edd_format_amount( $price ) );
1660
+
}
1661
+
1662
+
return $price;
1663
+
}
1664
+
}
1665
+
1666
+
if ( ! function_exists( 'tutor_print_formatted_price' ) ) {
1667
+
/**
1668
+
* A clone copy of `tutor_get_formatted_price` helper
1669
+
* To print formated price with output scaping.
1670
+
*
1671
+
* @since 3.0.0
1672
+
*
1673
+
* @param mixed $price price.
1674
+
*
1675
+
* @return void
1676
+
*/
1677
+
function tutor_print_formatted_price( $price ) {
1678
+
echo esc_html( tutor_get_formatted_price( $price ) );
1679
+
}
1680
+
}
1681
+
1682
+
if ( ! function_exists( 'tutor_get_locale_price' ) ) {
1683
+
/**
1684
+
* Get price as per locale format
1685
+
*
1686
+
* For locale settings currency code will be used
1687
+
*
1688
+
* @since 3.0.0
1689
+
*
1690
+
* @param mixed $price Raw price.
1691
+
*
1692
+
* @return mixed raw price.
1693
+
*/
1694
+
function tutor_get_locale_price( $price ) {
1695
+
// TODO: implement price formation.
1696
+
return $price;
1697
+
}
1698
+
}
1699
+
1700
+
if ( ! function_exists( 'tutor_is_json' ) ) {
1701
+
/**
1702
+
* Check a string is valid JSON.
1703
+
*
1704
+
* @param string $string string.
1705
+
*
1706
+
* @return boolean
1707
+
*/
1708
+
function tutor_is_json( $string ) {
1709
+
json_decode( $string );
1710
+
return json_last_error() === JSON_ERROR_NONE;
1711
+
}
1712
+
}
1713
+
1714
+
if ( ! function_exists( 'tutor_is_dev_mode' ) ) {
1715
+
/**
1716
+
* Check tutor is in development mode or not.
1717
+
*
1718
+
* @since 3.0.0
1719
+
*
1720
+
* @return bool True if the current environment is local, false otherwise.
1721
+
*/
1722
+
function tutor_is_dev_mode() {
1723
+
return defined( 'TUTOR_DEV_MODE' ) && TUTOR_DEV_MODE;
1724
+
}
1725
+
}
1726
+
1727
+
if ( ! function_exists( 'tutor_redirect_after_payment' ) ) {
1728
+
/**
1729
+
* Redirect after payment with status and message
1730
+
*
1731
+
* @since 3.0.0
1732
+
*
1733
+
* @param string $status Success or error status of payment.
1734
+
* @param int $order_id Order ID.
1735
+
* @param string $message Success/error message to display.
1736
+
*
1737
+
* @return void
1738
+
*/
1739
+
function tutor_redirect_after_payment( $status, $order_id, $message = '' ) {
1740
+
$query_params = array(
1741
+
'tutor_order_placement' => $status,
1742
+
'order_id' => $order_id,
1743
+
);
1744
+
1745
+
if ( $message ) {
1746
+
if ( 'success' === $status ) {
1747
+
$query_params['success_message'] = $message;
1748
+
} else {
1749
+
$query_params['error_message'] = $message;
1750
+
}
1751
+
}
1752
+
1753
+
wp_safe_redirect( apply_filters( 'tutor_redirect_url_after_checkout', add_query_arg( $query_params, home_url() ), $status, $order_id ) );
1754
+
exit();
1755
+
}
1756
+
}
1757
+
1758
+
if ( ! function_exists( 'tutor_split_amounts' ) ) {
1759
+
/**
1760
+
* Split amounts into parts for admin & instructor
1761
+
*
1762
+
* Amount split will be proportionally based on
1763
+
* admin commission rate & instructor commission rate.
1764
+
*
1765
+
* @since 3.0.0
1766
+
*
1767
+
* @param array $amounts Single amount or list of amount array. For ex: [12,20,100].
1768
+
*
1769
+
* @return array
1770
+
*/
1771
+
function tutor_split_amounts( $amounts ) {
1772
+
$amounts = is_array( $amounts ) ? $amounts : array( $amounts );
1773
+
1774
+
$admin_amount = 0;
1775
+
$instructor_amount = 0;
1776
+
1777
+
$sharing_enabled = tutor_utils()->get_option( 'enable_revenue_sharing' );
1778
+
$instructor_rate = $sharing_enabled ? tutor_utils()->get_option( 'earning_instructor_commission' ) : 0;
1779
+
$admin_rate = $sharing_enabled ? tutor_utils()->get_option( 'earning_admin_commission' ) : 100;
1780
+
1781
+
foreach ( $amounts as $amount ) {
1782
+
$instructor_amount = $instructor_rate > 0 ? ( ( $amount * $instructor_rate ) / 100 ) : 0;
1783
+
$admin_amount = $admin_rate > 0 ? ( ( $amount * $admin_rate ) / 100 ) : 0;
1784
+
}
1785
+
1786
+
return array(
1787
+
'admin' => $admin_amount,
1788
+
'instructor' => $instructor_amount,
1789
+
);
1790
+
}
1791
+
}
1792
+
1793
+
if ( ! function_exists( 'tutor_is_local_env' ) ) {
1794
+
/**
1795
+
* Check if the current environment is local.
1796
+
*
1797
+
* @since 3.2.0
1798
+
*
1799
+
* @return bool True if the current environment is local, false otherwise.
1800
+
*/
1801
+
function tutor_is_local_env() {
1802
+
$site_url = site_url();
1803
+
return (
1804
+
strpos( $site_url, '.local' ) !== false ||
1805
+
strpos( $site_url, 'localhost' ) !== false
1806
+
);
1807
+
}
1808
+
}
1809
+
1810
+
1811
+
1812
+
if ( ! function_exists( 'get_tutor_post_types' ) ) {
1813
+
/**
1814
+
* Get tutor post type list
1815
+
*
1816
+
* @since 3.6.0
1817
+
*
1818
+
* @param string $post_type the post type to get single tutor valid post type
1819
+
*
1820
+
* @return array|string
1821
+
*/
1822
+
function get_tutor_post_types( $post_type = '' ) {
1823
+
$valid_post_types = array(
1824
+
'course' => tutor()->course_post_type,
1825
+
'bundle' => tutor()->bundle_post_type,
1826
+
'lesson' => tutor()->lesson_post_type,
1827
+
'topics' => tutor()->topics_post_type,
1828
+
'quiz' => tutor()->quiz_post_type,
1829
+
'assignment' => tutor()->assignment_post_type,
1830
+
'zoom' => tutor()->zoom_post_type,
1831
+
'meet' => tutor()->meet_post_type,
1832
+
'enrollment' => tutor()->enrollment_post_type,
1833
+
'announcement' => tutor()->announcement_post_type,
1834
+
);
1835
+
1836
+
if ( $post_type && isset( $valid_post_types[ $post_type ] ) ) {
1837
+
return $valid_post_types[ $post_type ];
1838
+
}
1839
+
1840
+
return $valid_post_types;
1841
+
}
1842
+
}
1843
+
1844
+
if ( ! function_exists( 'tutor_decode_unicode_sequences' ) ) {
1845
+
/**
1846
+
* Decode Unicode escape sequences in a string to their corresponding UTF-8 characters.
1847
+
*
1848
+
* Example:
1849
+
* decode_unicode_escapes('Hello\\u0020World') => 'Hello World'
1850
+
* decode_unicode_escapes('\\u{1F600}') => '😀'
1851
+
*
1852
+
* Notes:
1853
+
* - Input and output are expected to be UTF-8 encoded.
1854
+
* - Behavior for malformed sequences is to preserve the original bytes rather than throw.
1855
+
*
1856
+
* @param string $str The input string possibly containing Unicode escape sequences.
1857
+
* @return string The string with Unicode escape sequences decoded into UTF-8 characters.
1858
+
*/
1859
+
function tutor_decode_unicode_sequences( $str ) {
1860
+
if ( empty( $str ) ) {
1861
+
return '';
1862
+
}
1863
+
1864
+
// Step 1: Decode \uXXXX or uXXXX sequences.
1865
+
$str = preg_replace_callback(
1866
+
'/\\\\?u([0-9a-fA-F]{4})/',
1867
+
function ( $m ) {
1868
+
return mb_convert_encoding( pack( 'H*', $m[1] ), 'UTF-8', 'UCS-2BE' );
1869
+
},
1870
+
$str
1871
+
);
1872
+
1873
+
// Step 2: Decode HTML entities like <, .
1874
+
$str = html_entity_decode( $str, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
1875
+
1876
+
return $str;
1877
+
}
1878
+
}
1879
+