PluginProbe
Tutor LMS – eLearning and online course solution / 3.9.2
Tutor LMS – eLearning and online course solution v3.9.2
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 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 All 191 releases
tutor / classes / Options_V2.php

Options_V2.php in Tutor LMS – eLearning and online course solution 3.9.2, at classes/Options_V2.php

2,088 lines 67.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Settings options
4 *
5 * @package Tutor\Settings
6 * @author Themeum <support@themeum.com>
7 * @link https://themeum.com
8 * @since 2.0.0
9 */
10
11 namespace Tutor;
12
13 use TUTOR\Input;
14 use Tutor\Traits\JsonResponse;
15 use Tutor\Ecommerce\OptionKeys;
16
17 if ( ! defined( 'ABSPATH' ) ) {
18 exit;
19 }
20
21 /**
22 * Contains all the settings options
23 *
24 * @since 2.0.0
25 */
26 class Options_V2 {
27
28 use JsonResponse;
29
30 /**
31 * Undocumented variable
32 *
33 * @since 2.0.0
34 *
35 * @var array $options
36 */
37 private $options;
38
39 /**
40 * Settings fields
41 *
42 * @since 2.0.0
43 *
44 * @var mixed $setting_fields
45 */
46 private $setting_fields;
47
48 /**
49 * Register hooks
50 *
51 * @since 2.0.0
52 *
53 * @param boolean $register_hook should register hook or not.
54 *
55 * @return void
56 */
57 public function __construct( $register_hook = true ) {
58 if ( ! $register_hook ) {
59 return;
60 }
61
62 // Saving option.
63 add_action( 'tutor_option_save_before', array( $this, 'validate_options' ) );
64 add_action( 'wp_ajax_tutor_option_save', array( $this, 'tutor_option_save' ) );
65 add_action( 'wp_ajax_tutor_option_default_save', array( $this, 'tutor_option_default_save' ) );
66 add_action( 'wp_ajax_tutor_option_search', array( $this, 'tutor_option_search' ) );
67 add_action( 'wp_ajax_tutor_export_settings', array( $this, 'tutor_export_settings' ) );
68 add_action( 'wp_ajax_tutor_export_single_settings', array( $this, 'tutor_export_single_settings' ) );
69 add_action( 'wp_ajax_tutor_delete_single_settings', array( $this, 'tutor_delete_single_settings' ) );
70 add_action( 'wp_ajax_tutor_import_settings', array( $this, 'tutor_import_settings' ) );
71 add_action( 'wp_ajax_tutor_apply_settings', array( $this, 'tutor_apply_settings' ) );
72 add_action( 'wp_ajax_load_saved_data', array( $this, 'load_saved_data' ) );
73 add_action( 'wp_ajax_reset_settings_data', array( $this, 'reset_settings_data' ) );
74 add_action( 'tutor_option_monetize_by_changed', array( $this, 'handle_changed_monetization_option' ) );
75 }
76
77 /**
78 * Get settings value
79 *
80 * @since 2.0.0
81 *
82 * @param mixed $key option key.
83 * @param mixed $default default value.
84 *
85 * @return mixed
86 */
87 private function get( $key = null, $default = false ) {
88
89 if ( ! $this->options ) {
90 // Get if already not prepared.
91 $this->options = (array) maybe_unserialize( get_option( 'tutor_option' ) );
92 }
93
94 $option = $this->options;
95
96 if ( empty( $option ) || ! is_array( $option ) ) {
97 return $default;
98 }
99
100 if ( ! $key ) {
101 return $option;
102 }
103
104 if ( array_key_exists( $key, $option ) ) {
105 return apply_filters( $key, $option[ $key ] );
106 }
107
108 // Access array value via dot notation, such as option->get('value.subvalue').
109 if ( strpos( $key, '.' ) ) {
110 $option_key_array = explode( '.', $key );
111 $new_option = $option;
112 foreach ( $option_key_array as $dot_key ) {
113 if ( isset( $new_option[ $dot_key ] ) ) {
114 $new_option = $new_option[ $dot_key ];
115 } else {
116 return $default;
117 }
118 }
119
120 return apply_filters( $key, $new_option );
121 }
122
123 return $default;
124 }
125
126 /**
127 * Get only list of options.
128 *
129 * @since 3.0.0
130 *
131 * @param array $only only options.
132 *
133 * @return array
134 */
135 public static function get_only( $only = array() ) {
136 $settings = get_option( 'tutor_option', array() );
137 return array_intersect_key( $settings, array_flip( $only ) );
138 }
139
140 /**
141 * Prepare settings search item.
142 *
143 * @since 3.0.0
144 *
145 * @param array $section section item.
146 * @param array $block block item.
147 * @param array $field field item.
148 *
149 * @return array prepared searchable field item.
150 */
151 private function prepare_search_item( $section, $block, $field ) {
152 $field['section_label'] = isset( $section['label'] ) ? $section['label'] : '';
153 $field['section_slug'] = isset( $section['slug'] ) ? $section['slug'] : '';
154 $field['block_label'] = isset( $block['label'] ) ? $block['label'] : '';
155
156 return $field;
157 }
158
159 /**
160 * Function to get all fields for search tutor_option_search
161 *
162 * @since 2.0.0
163 *
164 * @return void send wp_json response
165 */
166 public function tutor_option_search() {
167 tutor_utils()->checking_nonce();
168
169 $data_array = array();
170 foreach ( $this->get_setting_fields() as $sections ) {
171 if ( is_array( $sections ) && ! empty( $sections ) ) {
172 foreach ( Input::sanitize_array( $sections ) as $section ) {
173 foreach ( $section['blocks'] as $blocks ) {
174 if ( isset( $blocks['fields'] ) && ! empty( $blocks['fields'] ) ) {
175 foreach ( $blocks['fields'] as $fields ) {
176 $data_array['fields'][] = $this->prepare_search_item( $section, $blocks, $fields );
177 }
178 }
179 }
180
181 /**
182 * Submenu item search.
183 *
184 * @since 3.0.0
185 */
186 if ( isset( $section['submenu'] ) && is_array( $section['submenu'] ) ) {
187 foreach ( Input::sanitize_array( $section['submenu'] ) as $submenu_section ) {
188 foreach ( $submenu_section['blocks'] as $block ) {
189 if ( isset( $block['fields'] ) && ! empty( $block['fields'] ) ) {
190 foreach ( $block['fields'] as $fields ) {
191 $data_array['fields'][] = $this->prepare_search_item( $submenu_section, $block, $fields );
192 }
193 }
194 }
195 }
196 }
197 }
198 }
199 }
200
201 wp_send_json_success( $data_array );
202 }
203
204 /**
205 * Export settings
206 *
207 * @since 2.0.0
208 *
209 * @return void send wp_json response
210 */
211 public function tutor_export_settings() {
212 tutor_utils()->checking_nonce();
213 // Check if user is privileged.
214 if ( ! current_user_can( 'administrator' ) ) {
215 wp_send_json_error( tutor_utils()->error_message() );
216 }
217
218 $tutor_option = get_option( 'tutor_option' );
219 $data = maybe_unserialize( $tutor_option );
220
221 $export_data = $this->get_export_json_schema();
222
223 $prepare_data = array(
224 'content_type' => 'settings',
225 'data' => $data,
226 );
227
228 $export_data['data'][] = $prepare_data;
229
230 $response = array(
231 'job_progress' => '100',
232 'exported_data' => $export_data,
233 'completed_contents' => array(
234 'settings' => true,
235 ),
236 );
237
238 // Update settings log.
239 $this->update_settings_log( $data, 'Exported' );
240
241 $this->json_response( __( 'Settings exported successfully', 'tutor' ), $response );
242 }
243
244 /**
245 * Export single settings
246 *
247 * @since 2.0.0
248 *
249 * @return void send wp_json response
250 */
251 public function tutor_export_single_settings() {
252
253 tutor_utils()->checking_nonce();
254
255 // Check if user is privileged.
256 if ( ! current_user_can( 'administrator' ) ) {
257 wp_send_json_error( tutor_utils()->error_message() );
258 }
259
260 $tutor_settings_log = get_option( 'tutor_settings_log' );
261 $export_id = $this->get_request_data( 'export_id' );
262
263 $export_data = $this->get_export_json_schema();
264
265 $prepare_data = array(
266 'content_type' => 'settings',
267 'data' => $tutor_settings_log[ $export_id ]['dataset'],
268 );
269
270 $export_data['data'][] = $prepare_data;
271 wp_send_json_success( $export_data );
272 }
273
274 /**
275 * Apply settings
276 *
277 * @since 2.0.0
278 *
279 * @return void send wp_json response
280 */
281 public function tutor_apply_settings() {
282
283 tutor_utils()->checking_nonce();
284
285 // Check if user is privileged.
286 if ( ! current_user_can( 'administrator' ) ) {
287 wp_send_json_error( tutor_utils()->error_message() );
288 }
289
290 $tutor_settings_log = get_option( 'tutor_settings_log' );
291 $apply_id = $this->get_request_data( 'apply_id' );
292
293 update_option( 'tutor_option', $tutor_settings_log[ $apply_id ]['dataset'] );
294
295 wp_send_json_success( $tutor_settings_log[ $apply_id ] );
296 }
297
298 /**
299 * Delete single setting
300 *
301 * @since 2.0.0
302 *
303 * @return void send wp_json response
304 */
305 public function tutor_delete_single_settings() {
306
307 tutor_utils()->checking_nonce();
308
309 // Check if user is privileged.
310 if ( ! current_user_can( 'administrator' ) ) {
311 wp_send_json_error( tutor_utils()->error_message() );
312 }
313
314 $tutor_settings_log = get_option( 'tutor_settings_log' );
315 $delete_id = $this->get_request_data( 'delete_id' );
316 unset( $tutor_settings_log[ $delete_id ] );
317 update_option( 'tutor_settings_log', $tutor_settings_log, false );
318
319 wp_send_json_success( $tutor_settings_log );
320 }
321
322 /**
323 * Get request data
324 *
325 * @since 2.0.0
326 *
327 * @param mixed $var option key.
328 *
329 * @return mixed
330 */
331 public function get_request_data( $var ) {
332 return isset( $_REQUEST[ $var ] ) ? sanitize_text_field( wp_unslash( $_REQUEST[ $var ] ) ) : null;
333 }
334
335 /**
336 * Tutor default settings update options
337 * and send json response
338 *
339 * @since 2.0.0
340 *
341 * @return void send wp_json response
342 */
343 public function tutor_default_settings() {
344 $attr = $this->get_setting_fields();
345
346 foreach ( $attr as $sections ) {
347
348 foreach ( $sections as $section ) {
349 foreach ( $section['blocks'] as $blocks ) {
350 foreach ( $blocks['fields'] as $field ) {
351 if ( isset( $field['default'] ) ) {
352 $attr_default[ $field['key'] ] = $field['default'];
353 }
354 }
355 }
356 }
357 }
358
359 update_option( 'tutor_option', $attr_default );
360
361 wp_send_json_success( $attr_default );
362 }
363
364 /**
365 * Tutor settings log
366 *
367 * @since 2.0.0
368 *
369 * @return void send wp_json response
370 */
371 public function load_saved_data() {
372 tutor_utils()->checking_nonce();
373
374 // Check if user is privileged.
375 if ( ! current_user_can( 'administrator' ) ) {
376 wp_send_json_error( tutor_utils()->error_message() );
377 }
378
379 wp_send_json_success( get_option( 'tutor_settings_log' ) );
380 }
381
382 /**
383 * Reset settings
384 *
385 * @since 2.0.0
386 *
387 * @return void send wp_json response
388 */
389 public function reset_settings_data() {
390 tutor_utils()->checking_nonce();
391
392 // Check if user is privileged.
393 if ( ! current_user_can( 'administrator' ) ) {
394 wp_send_json_error( tutor_utils()->error_message() );
395 }
396
397 $reset_fields = $return_fields = $return_fields_group = array(); //phpcs:ignore
398 $reset_page = Input::post( 'reset_page' );
399 $setting_data = $this->get_setting_fields()['option_fields'][ $reset_page ]['blocks'];
400
401 foreach ( $setting_data as $blocks ) {
402
403 $block_fields = isset( $blocks['fields'] ) ? $blocks['fields'] : array();
404 foreach ( $block_fields as $fields ) {
405 $return_fields[] = $fields;
406 }
407
408 $block_fields_group = isset( $blocks['fields_group'] ) ? $blocks['fields_group'] : array();
409 foreach ( $block_fields_group as $fields ) {
410 $return_fields_group[] = $fields;
411 }
412 }
413
414 $reset_fields = array_merge( $return_fields, $return_fields_group );
415
416 wp_send_json_success( $reset_fields );
417 }
418
419 /**
420 * Import settings
421 *
422 * @since 2.0.0
423 *
424 * @return void
425 */
426 public function tutor_import_settings() {
427 tutor_utils()->checking_nonce();
428
429 // Check if user is privileged.
430 if ( ! current_user_can( 'administrator' ) ) {
431 wp_send_json_error( tutor_utils()->error_message() );
432 }
433
434 $data = $_FILES['data'];
435
436 if ( ! isset( $data['tmp_name'] ) ) {
437 $this->response_bad_request( __( 'Invalid file', 'tutor' ) );
438 }
439
440 $request = json_decode( file_get_contents( $data['tmp_name'] ), true );
441
442 unlink( $data['tmp_name'] );
443
444 $settings_found = false;
445
446 if ( json_last_error() ) {
447 $this->response_bad_request( __( 'Invalid json file', 'tutor' ) );
448 }
449
450 if ( ! isset( $request['data'] ) ) {
451 $this->response_bad_request( __( 'Data not found or invalid', 'tutor' ) );
452 }
453
454 if ( is_array( $request['data'] ) && count( $request['data'] ) ) {
455 foreach ( $request['data'] as $content ) {
456 if ( isset( $content['content_type'] ) && 'settings' === $content['content_type'] ) {
457 $settings_found = true;
458 }
459 }
460 }
461
462 if ( ! $settings_found ) {
463 $this->response_bad_request( __( 'Settings not found', 'tutor' ) );
464 }
465
466 $settings_data = is_array( $request ) && isset( $request['data'] ) ? $request['data'][0]['data'] : array();
467 $update_settings = $this->update_settings_log( $settings_data, 'Imported' );
468
469 $response = array(
470 'job_progress' => '100',
471 'exported_data' => $update_settings,
472 );
473
474 $this->json_response( __( 'Settings imported successfully!', 'tutor' ), $response );
475 }
476
477 /**
478 * Validate options before save.
479 *
480 * @since 2.8.0
481 *
482 * @param array $options option submitted to save.
483 *
484 * @return void
485 */
486 public function validate_options( $options ) {
487 $success = true;
488 $message = '';
489
490 $enable_sharing = $options['enable_revenue_sharing'] ?? 'off';
491 $admin_commission = (int) $options['earning_admin_commission'] ?? 0;
492 $instructor_commission = (int) $options['earning_instructor_commission'] ?? 0;
493
494 if ( 'on' === $enable_sharing && ( $admin_commission + $instructor_commission ) > 100 ) {
495 $success = false;
496 $message = __( 'Total share percentage must be 100% or less', 'tutor' );
497 }
498
499 if ( ! $success ) {
500 wp_send_json(
501 array(
502 'success' => $success,
503 'message' => $message,
504 )
505 );
506 }
507 }
508
509 /**
510 * Function tutor_option_save
511 *
512 * @since 2.0.0
513 *
514 * @return void send wp_json response
515 */
516 public function tutor_option_save() {
517 tutor_utils()->checking_nonce();
518
519 ! current_user_can( 'manage_options' ) ? wp_send_json_error() : 0;
520
521 $data_before = get_option( 'tutor_option' );
522 $option = (array) tutor_utils()->array_get( 'tutor_option', $_POST, array() ); //phpcs:ignore
523
524 do_action( 'tutor_option_save_before', $option );
525
526 $option = Input::sanitize_array(
527 $option,
528 array(
529 'payment_settings' => 'wp_kses_post',
530 'tutor_bank_transfer_withdraw_instruction' => 'sanitize_textarea_field',
531 'certificate_showcase_desc' => 'sanitize_textarea_field',
532 'invoice_from_address' => 'sanitize_textarea_field',
533 'fees_name' => 'sanitize_textarea_field',
534 )
535 );
536 $option = apply_filters( 'tutor_option_input', $option );
537
538 $time = strtotime( 'now' ) + ( 6 * 60 * 60 );
539 $save_import_data['datetime'] = $time;
540 $save_import_data['history_date'] = gmdate( 'j M, Y, g:i a', $time );
541 $save_import_data['datatype'] = 'saved';
542 $save_import_data['dataset'] = $option;
543 $import_data[ 'tutor-saved-' . $time ] = $save_import_data;
544 $update_option = array();
545 $get_option_data = get_option( 'tutor_settings_log', array() );
546
547 if ( ! empty( $get_option_data ) ) {
548 $update_option = array_merge( $import_data, $get_option_data );
549 } else {
550 $update_option = array_merge( $update_option, $import_data );
551 }
552
553 $update_option = array_slice( $update_option, 0, 10 );
554
555 update_option( 'tutor_settings_log', $update_option, false );
556 update_option( 'tutor_option', $option );
557 update_option( 'tutor_option_update_time', gmdate( 'j M, Y, g:i a', $time ) );
558
559 /**
560 * Hook for each tutor settings option change detection.
561 * Example: `tutor_option_{course_permalink_base}_changed`
562 *
563 * @since 2.6.0
564 */
565 $data_after = get_option( 'tutor_option' );
566 if ( $data_before !== $data_after && is_array( $data_after ) ) {
567 foreach ( $data_after as $key => $value ) {
568 $from = $data_before[ $key ] ?? null;
569 $to = $value;
570 if ( $from !== $to ) {
571 do_action( "tutor_option_{$key}_changed", $from, $to );
572 }
573 }
574 }
575
576 do_action( 'tutor_option_save_after' );
577
578 $data = apply_filters(
579 'tutor_option_saved_data',
580 array(
581 'success' => true,
582 'message' => __( 'Settings Saved', 'tutor' ),
583 'options' => $option,
584 )
585 );
586
587 wp_send_json( $data );
588 }
589
590 /**
591 * Handle monetization option value change.
592 *
593 * @since 3.0.0
594 *
595 * @return void
596 */
597 public function handle_changed_monetization_option() {
598 add_filter(
599 'tutor_option_saved_data',
600 function ( $res ) {
601 $res['reload_required'] = true;
602 return $res;
603 }
604 );
605 }
606
607 /**
608 * Function tutor_option_save
609 *
610 * @since 2.0.0
611 *
612 * @return void send wp_json response
613 */
614 public function tutor_option_default_save() {
615 tutor_utils()->checking_nonce();
616
617 ! current_user_can( 'manage_options' ) ? wp_send_json_error() : 0;
618 $attr = $this->get_setting_fields();
619 $tutor_default_option = get_option( 'tutor_default_option' );
620 $tutor_saved_option = get_option( 'tutor_option' );
621
622 foreach ( $attr as $sections ) {
623 if ( is_array( $sections ) && count( $sections ) ) {
624 foreach ( $sections as $section ) {
625 foreach ( $section['blocks'] as $blocks ) {
626 if ( isset( $blocks['fields'] ) ) {
627 foreach ( $blocks['fields'] as $field ) {
628 if ( isset( $field['key'] ) ) {
629 if ( isset( $tutor_default_option[ $field['key'] ] ) ) {
630 $attr_default[ $field['key'] ] = $tutor_saved_option[ $field['key'] ];
631 } else {
632 $attr_default[ $field['key'] ] = $field['default'] ?? '';
633 }
634 }
635 }
636 }
637 }
638 }
639 }
640 }
641
642 update_option( 'tutor_option', $attr_default );
643
644 wp_send_json_success( $attr_default );
645 }
646
647 /**
648 * Load settings page
649 *
650 * @since 2.0.0
651 *
652 * @return void
653 */
654 public function load_settings_page() {
655 extract( $this->get_setting_fields() ); //phpcs:ignore
656
657 if ( ! $template_path ) {
658 $template_path = tutor()->path . '/views/options/settings.php';
659 }
660 include $template_path;
661 }
662
663 /**
664 * Get settings fields
665 *
666 * @since 2.0.0
667 *
668 * @return mixed
669 */
670 public function get_setting_fields() {
671 if ( $this->setting_fields ) {
672 // Return from property if already prepared.
673 return $this->setting_fields;
674 }
675
676 $pages = tutor_utils()->get_pages();
677
678 $site_url = site_url();
679 $course_base = $this->get( 'course_permalink_base', 'courses' );
680 $lesson_key = $this->get( 'lesson_permalink_base', 'lessons' );
681 $quiz_key = $this->get( 'quiz_permalink_base', 'quizzes' );
682
683 $course_url = $site_url . '/<code>' . $course_base . '</code>/sample-course';
684 $lesson_url = $site_url . '/' . $course_base . '/sample-course/<code>' . $lesson_key . '</code>/sample-lesson/';
685 $quiz_url = $site_url . '/' . $course_base . '/sample-course/<code>' . $quiz_key . '</code>/sample-quiz/';
686
687 $student_url = tutor_utils()->profile_url( 0, false );
688 $methods_array = array();
689 $withdrawl_methods = apply_filters( 'tutor_withdrawal_methods_all', array() );
690
691 foreach ( $withdrawl_methods as $key => $method ) {
692 $methods_array[ $key ] = $method['method_name'];
693 }
694
695 $page_args = array(
696 'post_type' => 'page',
697 'post_status' => 'publish',
698 'posts_per_page' => 1,
699 'title' => 'Courses',
700 );
701
702 $page_posts = get_posts( $page_args );
703 $course_archive_page_id = ( is_array( $page_posts ) && count( $page_posts ) ) ? $page_posts[0] : null;
704
705 $attr = array(
706 'general' => array(
707 'label' => __( 'General', 'tutor' ),
708 'slug' => 'general',
709 'desc' => __( 'General Settings', 'tutor' ),
710 'template' => 'basic',
711 'icon' => 'tutor-icon-earth',
712 'blocks' => array(
713 array(
714 'label' => false,
715 'block_type' => 'uniform',
716 'slug' => 'general-page',
717 'fields' => array(
718 array(
719 'key' => 'tutor_dashboard_page_id',
720 'type' => 'select',
721 'label' => __( 'Dashboard Page', 'tutor' ),
722 'default' => '0',
723 'options' => $pages,
724 'desc' => __( 'This page will be used for student and instructor dashboard', 'tutor' ),
725 'searchable' => true,
726 ),
727 ),
728 ),
729 array(
730 'label' => false,
731 'block_type' => 'uniform',
732 'slug' => 'general-page',
733 'fields' => array(
734 array(
735 'key' => 'tutor_toc_page_id',
736 'type' => 'select',
737 'label' => __( 'Terms and Conditions Page', 'tutor' ),
738 'default' => '0',
739 'options' => $pages,
740 'desc' => __( 'This page will be used as the Terms and Conditions page', 'tutor' ),
741 'searchable' => true,
742 ),
743 array(
744 'key' => OptionKeys::PRIVACY_POLICY,
745 'type' => 'select',
746 'label' => __( 'Privacy Policy', 'tutor' ),
747 'default' => 0,
748 'options' => $pages,
749 'desc' => __( 'Choose the page for privacy policy.', 'tutor' ),
750 'searchable' => true,
751 ),
752 ),
753 ),
754 array(
755 'label' => __( 'Others', 'tutor' ),
756 'slug' => 'others',
757 'block_type' => 'isolate',
758 'fields' => array(
759 array(
760 'key' => 'enable_course_marketplace',
761 'type' => 'toggle_switch',
762 'label' => __( 'Enable Marketplace', 'tutor' ),
763 'label_title' => '',
764 'default' => 'off',
765 'desc' => __( 'Allow multiple instructors to sell their courses.', 'tutor' ),
766 ),
767 array(
768 'key' => 'pagination_per_page',
769 'type' => 'number',
770 'number_type' => 'integer',
771 'label' => __( 'Pagination', 'tutor' ),
772 'default' => '20',
773 'desc' => __( 'Set the number of rows to be displayed per page', 'tutor' ),
774 ),
775 ),
776 ),
777 array(
778 'label' => __( 'Instructor', 'tutor' ),
779 'slug' => 'instructor',
780 'block_type' => 'uniform',
781 'fields' => array(
782 array(
783 'key' => 'enable_become_instructor_btn',
784 'type' => 'toggle_switch',
785 'label' => __( 'Become an Instructor Button', 'tutor' ),
786 'label_title' => '',
787 'default' => 'off',
788 'desc' => __( 'Enable the option to display this button on the student dashboard.', 'tutor' ),
789 ),
790 array(
791 'key' => 'instructor_can_publish_course',
792 'type' => 'toggle_switch',
793 'label' => __( 'Allow Instructors to Publish Courses', 'tutor' ),
794 'label_title' => '',
795 'default' => 'off',
796 'desc' => __( 'Enable instructors to publish the course directly. If disabled, admins will be able to review course content before publishing.', 'tutor' ),
797 ),
798 array(
799 'key' => 'instructor_can_delete_course',
800 'type' => 'toggle_switch',
801 'label' => __( 'Allow Instructors to Trash Courses', 'tutor' ),
802 'label_title' => '',
803 'default' => 'on',
804 'desc' => __( 'Enable this setting to allow instructors to delete courses.', 'tutor' ),
805 ),
806 ),
807 ),
808 ),
809 ),
810 'course' => array(
811 'label' => __( 'Course', 'tutor' ),
812 'slug' => 'course',
813 'desc' => __( 'Course Settings', 'tutor' ),
814 'template' => 'basic',
815 'icon' => 'tutor-icon-book-open',
816 'blocks' => array(
817 'block_course' => array(
818 'label' => '',
819 'slug' => 'course',
820 'block_type' => 'uniform',
821 'fields' => array(
822 array(
823 'key' => 'student_must_login_to_view_course',
824 'type' => 'toggle_switch',
825 'label' => __( 'Course Visibility', 'tutor' ),
826 'label_title' => '',
827 'default' => 'off',
828 'desc' => __( 'Students must be logged in to view course', 'tutor' ),
829 ),
830 array(
831 'key' => 'course_content_access_for_ia',
832 'type' => 'toggle_switch',
833 'label' => __( 'Course Content Access', 'tutor' ),
834 'default' => 'off',
835 'label_title' => '',
836 'desc' => __( 'Allow instructors and admins to view the course content without enrolling', 'tutor' ),
837 ),
838 array(
839 'key' => 'course_content_summary',
840 'type' => 'toggle_switch',
841 'label' => __( 'Content Summary', 'tutor' ),
842 'default' => 'on',
843 'desc' => __( 'Enabling this feature will show a course content summary on the Course Details page.', 'tutor' ),
844 ),
845 array(
846 'key' => 'enable_spotlight_mode',
847 'type' => 'toggle_switch',
848 'label' => __( 'Spotlight Mode', 'tutor' ),
849 'default' => 'off',
850 'label_title' => '',
851 'desc' => __( 'This will hide the header and the footer and enable spotlight (full screen) mode when students view lessons.', 'tutor' ),
852 ),
853 array(
854 'key' => 'auto_course_complete_on_all_lesson_completion',
855 'type' => 'toggle_switch',
856 'label' => __( 'Auto Complete Course on All Lesson Completion', 'tutor' ),
857 'default' => 'off',
858 'label_title' => '',
859 'desc' => __( 'If enabled, an Enrolled Course will be automatically completed if all its Lessons, Quizzes, and Assignments are already completed by the Student', 'tutor' ),
860 ),
861 array(
862 'key' => 'course_completion_process',
863 'type' => 'radio_vertical',
864 'label' => __( 'Course Completion Process', 'tutor' ),
865 'default' => 'flexible',
866 'select_options' => false,
867 'options' => array(
868 'flexible' => array(
869 'label' => __( 'Flexible', 'tutor' ),
870 'desc' => __( 'Students can complete courses anytime in the Flexible mode', 'tutor' ),
871 ),
872 'strict' => array(
873 'label' => __( 'Strict', 'tutor' ),
874 'desc' => __( 'Students must complete all lessons, quizzes, and assignments to mark their courses as complete.', 'tutor' ),
875 ),
876 ),
877 'desc' => __( 'Choose when a user can click on the <strong>“Complete Course”</strong> button', 'tutor' ),
878 ),
879 array(
880 'key' => 'course_retake_feature',
881 'type' => 'toggle_switch',
882 'label' => __( 'Course Retake', 'tutor' ),
883 'default' => 'off',
884 'label_title' => '',
885 'desc' => __( 'Enabling this feature will allow students to reset course progress and start over.', 'tutor' ),
886 ),
887 array(
888 'key' => 'enable_course_review_moderation',
889 'type' => 'toggle_switch',
890 'label' => __( "Publish Course Review on Admin's Approval", 'tutor' ),
891 'default' => 'off',
892 'label_title' => '',
893 'desc' => __( 'Enable to publish/re-publish Course Review after the approval of Site Admin', 'tutor' ),
894 ),
895 ),
896 ),
897 'block_lesson' => array(
898 'label' => __( 'Lesson', 'tutor' ),
899 'slug' => 'lesson',
900 'block_type' => 'uniform',
901 'fields' => array(
902 array(
903 'key' => 'enable_lesson_classic_editor',
904 'type' => 'toggle_switch',
905 'label' => __( 'WP Editor for Lesson', 'tutor' ),
906 'label_title' => '',
907 'default' => 'off',
908 'desc' => __( 'Enable classic editor to edit lesson.', 'tutor' ),
909 ),
910 array(
911 'key' => 'autoload_next_course_content',
912 'type' => 'toggle_switch',
913 'label' => __( 'Automatically Load Next Course Content.', 'tutor' ),
914 'label_title' => '',
915 'default' => 'off',
916 'desc' => __( 'Enable this feature to automatically load the next course content after the current one is finished.', 'tutor' ),
917 ),
918 array(
919 'key' => 'enable_comment_for_lesson',
920 'type' => 'toggle_switch',
921 'label' => __( 'Enable Lesson Comment', 'tutor' ),
922 'label_title' => '',
923 'default' => 'off',
924 'desc' => __( 'Enable this feature to allow students to post comments on lessons.', 'tutor' ),
925 ),
926 ),
927 ),
928 'block_quiz' => array(
929 'label' => __( 'Quiz', 'tutor' ),
930 'slug' => 'quiz',
931 'block_type' => 'uniform',
932 'fields' => array(
933 array(
934 'key' => 'quiz_when_time_expires',
935 'type' => 'radio_vertical',
936 'label' => __( 'When time expires', 'tutor' ),
937 'default' => 'auto_abandon',
938 'select_options' => false,
939 'options' => array(
940 'auto_submit' => array(
941 'label' => __( 'Auto Submit', 'tutor' ),
942 'desc' => __( 'The current quiz answers are submitted automatically.', 'tutor' ),
943 ),
944 'auto_abandon' => array(
945 'label' => __( 'Auto Abandon', 'tutor' ),
946 'desc' => __( 'Attempts must be submitted before time expires, otherwise they will not be counted.', 'tutor' ),
947 ),
948 ),
949 'desc' => __( 'Choose which action to follow when the quiz time expires.', 'tutor' ),
950 ),
951 array(
952 'key' => 'quiz_answer_display_time',
953 'type' => 'number',
954 'label' => __( 'Correct Answer Display Time (When Reveal Mode is enabled)', 'tutor' ),
955 'default' => '2',
956 'desc' => __( 'Put the answer display time in seconds', 'tutor' ),
957 ),
958 array(
959 'key' => 'quiz_attempts_allowed',
960 'type' => 'number',
961 'number_type' => 'integer',
962 'label' => __( 'Default Quiz Attempt limit (When Retry Mode is enabled)', 'tutor' ),
963 'default' => '10',
964 'desc' => __( 'The highest number of attempts allowed for students to participate a quiz. 0 means unlimited. This will work as the default Quiz Attempt limit in case of Quiz Retry Mode.', 'tutor' ),
965 ),
966 array(
967 'key' => 'quiz_previous_button_enabled',
968 'type' => 'toggle_switch',
969 'label' => __( 'Show Quiz Previous Button', 'tutor' ),
970 'default' => 'on',
971 'desc' => __( 'Choose whether to show or hide the previous button for each question.', 'tutor' ),
972 ),
973 array(
974 'key' => 'quiz_grade_method',
975 'type' => 'radio_horizontal_full',
976 'label' => __( 'Final Grade Calculation', 'tutor' ),
977 'desc' => __( 'When multiple attempts are allowed, select which method should be used to calculate a student\'s final grade for the quiz.', 'tutor' ),
978 'default' => 'highest_grade',
979 'options' => array(
980 'highest_grade' => __( 'Highest Grade', 'tutor' ),
981 'average_grade' => __( 'Average Grade', 'tutor' ),
982 'first_attempt' => __( 'First Attempt', 'tutor' ),
983 'last_attempt' => __( 'Last Attempt', 'tutor' ),
984 ),
985 ),
986 ),
987 ),
988 array(
989 'label' => __( 'Video', 'tutor' ),
990 'slug' => 'video',
991 'block_type' => 'uniform',
992 'fields' => array(
993 array(
994 'key' => 'supported_video_sources',
995 'type' => 'checkbox_vertical',
996 'default' => array( 'youtube', 'vimeo' ),
997 'label' => __( 'Preferred Video Source', 'tutor' ),
998 'label_title' => __( 'Preferred Video Source', 'tutor' ),
999 'options' => tutor_utils()->get_video_sources( true ),
1000 'desc' => __( 'Select the video hosting platform(s) you want to enable.', 'tutor' ),
1001 ),
1002 array(
1003 'key' => 'disable_default_player_youtube',
1004 'type' => 'toggle_switch',
1005 'label' => __( 'Use Tutor Player for YouTube', 'tutor' ),
1006 'label_title' => '',
1007 'default' => 'off',
1008 'desc' => __( 'Enable this option to use Tutor LMS video player for YouTube.', 'tutor' ),
1009 ),
1010 array(
1011 'key' => 'disable_default_player_vimeo',
1012 'type' => 'toggle_switch',
1013 'label' => __( 'Use Tutor Player for Vimeo', 'tutor' ),
1014 'label_title' => '',
1015 'default' => 'off',
1016 'desc' => __( 'Enable this option to use Tutor LMS video player for Vimeo.', 'tutor' ),
1017 ),
1018 ),
1019 ),
1020 ),
1021 ),
1022 'monetization' => array(
1023 'label' => __( 'Monetization', 'tutor' ),
1024 'slug' => 'monetization',
1025 'desc' => __( 'Monetization Settings', 'tutor' ),
1026 'template' => 'basic',
1027 'icon' => 'tutor-icon-badge-discount',
1028 'blocks' => array(
1029 'block_options' => array(
1030 'label' => __( 'Options', 'tutor' ),
1031 'slug' => 'options',
1032 'block_type' => 'uniform',
1033 'fields' => array(
1034 array(
1035 'key' => 'monetize_by',
1036 'type' => 'select',
1037 'label' => __( 'Select eCommerce Engine', 'tutor' ),
1038 'select_options' => false,
1039 'options' => apply_filters(
1040 'tutor_monetization_options',
1041 array(
1042 'free' => __( 'Disable Monetization', 'tutor' ),
1043 )
1044 ),
1045 'default' => 'free',
1046 'desc' => __( 'Select a monetization option to generate revenue by selling courses.', 'tutor' ),
1047 ),
1048 ),
1049 ),
1050 'block_woocommerce' => array(
1051 'label' => __( 'WooCommerce', 'tutor' ),
1052 'slug' => 'woocommerce',
1053 'block_type' => 'uniform',
1054 'fields' => array(
1055 array(
1056 'key' => 'tutor_woocommerce_order_auto_complete',
1057 'type' => 'toggle_switch',
1058 'label' => __( 'Automatically Complete WooCommerce Orders', 'tutor' ),
1059 'label_title' => '',
1060 'default' => 'off',
1061 'desc' => __( 'If enabled, in the case of Courses, WooCommerce Orders will get the "Completed" status .', 'tutor' ),
1062 ),
1063 array(
1064 'key' => 'wc_automatic_order_complete_redirect_to_courses',
1065 'type' => 'toggle_switch',
1066 'label' => __( 'Auto Redirect to Courses', 'tutor' ),
1067 'default' => 'off',
1068 'label_title' => '',
1069 'desc' => __( 'When a user\'s WooCommerce order is auto-completed, they will be redirected to enrolled courses', 'tutor' ),
1070 ),
1071 array(
1072 'key' => 'enable_guest_course_cart',
1073 'type' => 'toggle_switch',
1074 'label' => __( 'Enable Guest Mode', 'tutor' ),
1075 'label_title' => '',
1076 'default' => 'off',
1077 'desc' => __( 'Allow customers to place orders without an account.', 'tutor' ),
1078 ),
1079 ),
1080 ),
1081 'block_revenue_sharing' => array(
1082 'label' => __( 'Revenue Sharing', 'tutor' ),
1083 'slug' => 'revenue_sharing',
1084 'block_type' => 'uniform',
1085 'fields' => array(
1086 array(
1087 'key' => 'enable_revenue_sharing',
1088 'type' => 'toggle_switch',
1089 'label' => __( 'Enable Revenue Sharing', 'tutor' ),
1090 'label_title' => '',
1091 'default' => 'off',
1092 'desc' => __( 'Allow revenue generated from selling courses to be shared with course creators.', 'tutor' ),
1093 'toggle_fields' => 'sharing_percentage',
1094 'toggle_blocks' => 'fees,withdraw',
1095 ),
1096 array(
1097 'key' => 'sharing_percentage',
1098 'type' => 'double_input',
1099 'label' => __( 'Sharing Percentage', 'tutor' ),
1100 'label_title' => '',
1101 'default' => '',
1102 'fields' => array(
1103 'earning_instructor_commission' => array(
1104 'id' => 'revenue-instructor',
1105 'type' => 'ratio',
1106 'title' => __( 'Instructor Takes', 'tutor' ),
1107 'default' => 20,
1108 ),
1109 'earning_admin_commission' => array(
1110 'id' => 'revenue-admin',
1111 'type' => 'ratio',
1112 'title' => __( 'Admin Takes', 'tutor' ),
1113 'default' => 80,
1114 ),
1115 ),
1116 'desc' => __( 'Set how the sales revenue will be shared among admins and instructors.', 'tutor' ),
1117 ),
1118 ),
1119 ),
1120 'block_fees' => array(
1121 'label' => __( 'Fees', 'tutor' ),
1122 'slug' => 'fees',
1123 'block_type' => 'uniform',
1124 'fields' => array(
1125 array(
1126 'key' => 'enable_fees_deducting',
1127 'type' => 'toggle_switch',
1128 'label' => __( 'Deduct Fees', 'tutor' ),
1129 'label_title' => '',
1130 'default' => 'off',
1131 'desc' => __( 'Fees are charged from the entire sales amount. The remaining amount will be divided among admin and instructors.', 'tutor' ),
1132 'toggle_fields' => 'fees_name,fee_amount_type',
1133 ),
1134 array(
1135 'key' => 'fees_name',
1136 'type' => 'textarea',
1137 'label' => __( 'Fee Description', 'tutor' ),
1138 'placeholder' => __( 'Fee Description', 'tutor' ),
1139 'desc' => __( 'Set a description for the fee that you are deducting. Make sure to give a reasonable explanation to maintain transparency with your site’s instructors.', 'tutor' ),
1140 'maxlength' => 200,
1141 'rows' => 5,
1142 'default' => 'Maintenance Fees',
1143 ),
1144 array(
1145 'key' => 'fee_amount_type',
1146 'type' => 'group_fields',
1147 'label' => __( 'Fee Amount & Type', 'tutor' ),
1148 'desc' => __( 'Select the fee type and add fee amount/percentage', 'tutor' ),
1149 'group_fields' => array(
1150 'fees_type' => array(
1151 'type' => 'select',
1152 'default' => 'fixed',
1153 'select_options' => false,
1154 'options' => array(
1155 'percent' => __( 'Percent', 'tutor' ),
1156 'fixed' => __( 'Fixed', 'tutor' ),
1157 ),
1158 ),
1159 'fees_amount' => array(
1160 'type' => 'number',
1161 'default' => '0',
1162 ),
1163 ),
1164 ),
1165 ),
1166 ),
1167 'block_withdraw' => array(
1168 'label' => __( 'Withdraw', 'tutor' ),
1169 'slug' => 'withdraw',
1170 'block_type' => 'uniform',
1171 'fields' => array(
1172 array(
1173 'key' => 'min_withdraw_amount',
1174 'type' => 'number',
1175 'label' => __( 'Minimum Withdrawal Amount', 'tutor' ),
1176 'default' => '80',
1177 'desc' => __( 'Instructors should earn equal or above this amount to make a withdraw request.', 'tutor' ),
1178 ),
1179 array(
1180 'key' => 'minimum_days_for_balance_to_be_available',
1181 'type' => 'number',
1182 'number_type' => 'integer',
1183 'label' => __( 'Minimum Days Before Balance is Available', 'tutor' ),
1184 'default' => '7',
1185 'min' => 1,
1186 'desc' => __( 'Any income has to remain this many days in the platform before it is available for withdrawal.', 'tutor' ),
1187 ),
1188 array(
1189 'key' => 'tutor_withdrawal_methods',
1190 'type' => 'checkbox_horizontal',
1191 'label' => __( 'Enable Withdraw Method', 'tutor' ),
1192 'default' => array( 'bank_transfer_withdraw' ),
1193 'options' => $methods_array,
1194 'desc' => __( 'Set how you would like to withdraw money from the website.', 'tutor' ),
1195 ),
1196 array(
1197 'key' => 'tutor_bank_transfer_withdraw_instruction',
1198 'type' => 'textarea',
1199 'label' => __( 'Bank Instructions', 'tutor' ),
1200 'default' => __( 'Write the up to date bank informations of your instructor here.', 'tutor' ),
1201 'desc' => __( 'Write bank instructions for the instructors to conduct withdrawals.', 'tutor' ),
1202 ),
1203 ),
1204 ),
1205 ),
1206 ),
1207 'design' => array(
1208 'label' => __( 'Design', 'tutor' ),
1209 'slug' => 'design',
1210 'desc' => __( 'Design Settings', 'tutor' ),
1211 'template' => 'design',
1212 'icon' => 'tutor-icon-color-palette',
1213 'blocks' => array(
1214 'block_course' => array(
1215 'label' => __( 'Course', 'tutor' ),
1216 'slug' => 'course',
1217 'block_type' => 'uniform',
1218 'fields' => array(
1219 array(
1220 'key' => 'courses_col_per_row',
1221 'type' => 'radio_horizontal',
1222 'label' => __( 'Column Per Row', 'tutor' ),
1223 'default' => '3',
1224 'options' => array(
1225 '1' => __( 'One', 'tutor' ),
1226 '2' => __( 'Two', 'tutor' ),
1227 '3' => __( 'Three', 'tutor' ),
1228 '4' => __( 'Four', 'tutor' ),
1229 ),
1230 'desc' => __( 'Define how many columns you want to use to display courses.', 'tutor' ),
1231 ),
1232 array(
1233 'key' => 'courses_per_page',
1234 'type' => 'number',
1235 'number_type' => 'integer',
1236 'label' => __( 'Courses Per Page', 'tutor' ),
1237 'default' => '12',
1238 'desc' => __( 'Set the number of courses to display per page on the Course List page.', 'tutor' ),
1239 ),
1240 array(
1241 'key' => 'course_archive_filter',
1242 'type' => 'toggle_switch',
1243 'label' => __( 'Course Filter', 'tutor' ),
1244 'label_title' => '',
1245 'default' => 'off',
1246 'desc' => __( 'Show sorting and filtering options on course archive page', 'tutor' ),
1247 'toggle_fields' => 'supported_course_filters',
1248 ),
1249 array(
1250 'key' => 'supported_course_filters',
1251 'type' => 'checkbox_horizontal',
1252 'label' => __( 'Preferred Course Filters', 'tutor' ),
1253 'default' => array( 'search', 'category' ),
1254 'options' => array(
1255 'search' => __( 'Keyword Search', 'tutor' ),
1256 'category' => __( 'Category', 'tutor' ),
1257 'tag' => __( 'Tag', 'tutor' ),
1258 'difficulty_level' => __( 'Difficulty Level', 'tutor' ),
1259 'price_type' => __( 'Price Type', 'tutor' ),
1260 ),
1261 'desc' => __( 'Choose preferred filter options you\'d like to show on the course archive page.', 'tutor' ),
1262 ),
1263 array(
1264 'key' => 'course_archive_filter_sorting',
1265 'type' => 'toggle_switch',
1266 'label' => __( 'Course Sorting', 'tutor' ),
1267 'label_title' => '',
1268 'default' => 'on',
1269 'desc' => __( 'If enabled, the courses will be sortable by Course Name or Creation Date in either Ascending or Descending order', 'tutor' ),
1270 ),
1271 ),
1272 ),
1273 'layout' => array(
1274 'label' => __( 'Layout', 'tutor' ),
1275 'slug' => 'layout',
1276 'block_type' => 'uniform',
1277 'fields' => array(
1278 array(
1279 'key' => 'instructor_list_layout',
1280 'type' => 'group_radio',
1281 'label' => __( 'Instructor List Layout', 'tutor' ),
1282 'desc' => __( 'Choose a layout for the list of instructors inside a course page. You can change this at any time.', 'tutor' ),
1283 'default' => 'portrait',
1284 'group_options' => array(
1285 'vertical' => array(
1286 'default' => array(
1287 'title' => __( 'Portrait', 'tutor' ),
1288 'image' => 'instructor-layout/instructor-portrait.svg',
1289 ),
1290 'cover' => array(
1291 'title' => __( 'Cover', 'tutor' ),
1292 'image' => 'instructor-layout/instructor-cover.svg',
1293 ),
1294 'minimal' => array(
1295 'title' => __( 'Minimal', 'tutor' ),
1296 'image' => 'instructor-layout/instructor-minimal.svg',
1297 ),
1298 ),
1299 'horizontal' => array(
1300 'portrait-horizontal' => array(
1301 'title' => __( 'Portrait Horizontal', 'tutor' ),
1302 'image' => 'instructor-layout/instructor-horizontal-portrait.svg',
1303 ),
1304 'minimal-horizontal' => array(
1305 'title' => __( 'Minimal Horizontal', 'tutor' ),
1306 'image' => 'instructor-layout/instructor-horizontal-minimal.svg',
1307 ),
1308 ),
1309 ),
1310 ),
1311 array(
1312 'key' => 'public_profile_layout',
1313 'type' => 'group_radio_full_3',
1314 'label' => __( 'Instructor Public Profile Layout', 'tutor' ),
1315 'desc' => __( 'Choose a layout design for a instructor’s public profile', 'tutor' ),
1316 'default' => 'pp-rectangle',
1317 'group_options' => array(
1318 'private' => array(
1319 'title' => __( 'Private', 'tutor' ),
1320 'image' => 'profile-layout/profile-private.svg',
1321 ),
1322 'pp-circle' => array(
1323 'title' => __( 'Modern', 'tutor' ),
1324 'image' => 'profile-layout/profile-modern.svg',
1325 ),
1326 'no-cp' => array(
1327 'title' => __( 'Minimal', 'tutor' ),
1328 'image' => 'profile-layout/profile-minimal.svg',
1329 ),
1330 'pp-rectangle' => array(
1331 'title' => __( 'Classic', 'tutor' ),
1332 'image' => 'profile-layout/profile-classic.svg',
1333 ),
1334 ),
1335 ),
1336 array(
1337 'key' => 'student_public_profile_layout',
1338 'type' => 'group_radio_full_3',
1339 'label' => __( 'Student Public Profile Layout', 'tutor' ),
1340 'desc' => __( 'Choose a layout design for a student’s public profile', 'tutor' ),
1341 'default' => 'pp-rectangle',
1342 'group_options' => array(
1343 'private' => array(
1344 'title' => __( 'Private', 'tutor' ),
1345 'image' => 'profile-layout/profile-private.svg',
1346 ),
1347 'pp-circle' => array(
1348 'title' => __( 'Modern', 'tutor' ),
1349 'image' => 'profile-layout/profile-modern.svg',
1350 ),
1351 'no-cp' => array(
1352 'title' => __( 'Minimal', 'tutor' ),
1353 'image' => 'profile-layout/profile-minimal.svg',
1354 ),
1355 'pp-rectangle' => array(
1356 'title' => __( 'Classic', 'tutor' ),
1357 'image' => 'profile-layout/profile-classic.svg',
1358 ),
1359 ),
1360 ),
1361 ),
1362 ),
1363 'course-details' => array(
1364 'label' => __( 'Course Details', 'tutor' ),
1365 'slug' => 'course-details',
1366 'block_type' => 'isolate',
1367 'fields' => array(
1368 array(
1369 'key' => 'course_details_adjustments',
1370 'type' => 'checkgroup',
1371 'label' => __( 'Page Features', 'tutor' ),
1372 'desc' => __( 'You can keep the following features active or inactive as per the need of your business model', 'tutor' ),
1373 'group_options' => array(
1374 array(
1375 'key' => 'display_course_instructors',
1376 'type' => 'toggle_single',
1377 'label' => __( 'Instructor Info', 'tutor' ),
1378 'default' => 'on',
1379 'desc' => __( 'Toggle to show instructor info', 'tutor' ),
1380 ),
1381 array(
1382 'key' => 'enable_wishlist',
1383 'type' => 'toggle_single',
1384 'label' => __( 'Wishlist', 'tutor' ),
1385 'default' => 'on',
1386 'desc' => __( 'Toggle to disable/enable wishlist', 'tutor' ),
1387 ),
1388 array(
1389 'key' => 'enable_q_and_a_on_course',
1390 'type' => 'toggle_single',
1391 'label' => __( 'Q&A', 'tutor' ),
1392 'default' => 'on',
1393 'desc' => __( 'Enable to add a Q&A section', 'tutor' ),
1394 ),
1395 array(
1396 'key' => 'enable_course_author',
1397 'type' => 'toggle_single',
1398 'label' => __( 'Author', 'tutor' ),
1399 'label_title' => __( 'Enable', 'tutor' ),
1400 'default' => 'off',
1401 'desc' => __( 'Enable to show course author name', 'tutor' ),
1402 ),
1403 array(
1404 'key' => 'enable_course_level',
1405 'type' => 'toggle_single',
1406 'label' => __( 'Level', 'tutor' ),
1407 'label_title' => __( 'Enable', 'tutor' ),
1408 'default' => 'on',
1409 'desc' => __( 'Enable to show course level', 'tutor' ),
1410 ),
1411 array(
1412 'key' => 'enable_course_share',
1413 'type' => 'toggle_single',
1414 'label' => __( 'Social Share', 'tutor' ),
1415 'label_title' => __( 'Enable', 'tutor' ),
1416 'default' => 'on',
1417 'desc' => __( 'Toggle to enable course social share', 'tutor' ),
1418 ),
1419 array(
1420 'key' => 'enable_course_duration',
1421 'type' => 'toggle_single',
1422 'label' => __( 'Duration', 'tutor' ),
1423 'label_title' => __( 'Disable', 'tutor' ),
1424 'default' => 'on',
1425 'desc' => __( 'Enable to show course duration', 'tutor' ),
1426 ),
1427 array(
1428 'key' => 'enable_course_total_enrolled',
1429 'type' => 'toggle_single',
1430 'label' => __( 'Total Enrolled', 'tutor' ),
1431 'label_title' => __( 'Enable', 'tutor' ),
1432 'default' => 'on',
1433 'desc' => __( 'Enable to show total enrolled students', 'tutor' ),
1434 ),
1435 array(
1436 'key' => 'enable_course_update_date',
1437 'type' => 'toggle_single',
1438 'label' => __( 'Update Date', 'tutor' ),
1439 'label_title' => __( 'Enable', 'tutor' ),
1440 'default' => 'on',
1441 'desc' => __( 'Enable to show course update information', 'tutor' ),
1442 ),
1443 array(
1444 'key' => 'enable_course_progress_bar',
1445 'type' => 'toggle_single',
1446 'label' => __( 'Progress Bar', 'tutor' ),
1447 'label_title' => __( 'Enable', 'tutor' ),
1448 'default' => 'on',
1449 'desc' => __( 'Enable to show course progress for Students', 'tutor' ),
1450 ),
1451 array(
1452 'key' => 'enable_course_material',
1453 'type' => 'toggle_single',
1454 'label' => __( 'Material', 'tutor' ),
1455 'label_title' => __( 'Enable', 'tutor' ),
1456 'default' => 'on',
1457 'desc' => __( 'Enable to show course materials', 'tutor' ),
1458 ),
1459 array(
1460 'key' => 'enable_course_about',
1461 'type' => 'toggle_single',
1462 'label' => __( 'About', 'tutor' ),
1463 'label_title' => __( 'Enable', 'tutor' ),
1464 'default' => 'on',
1465 'desc' => __( 'Enable to show course about section', 'tutor' ),
1466 ),
1467 array(
1468 'key' => 'enable_course_description',
1469 'type' => 'toggle_single',
1470 'label' => __( 'Description', 'tutor' ),
1471 'label_title' => __( 'Enable', 'tutor' ),
1472 'default' => 'on',
1473 'desc' => __( 'Enable to show course description', 'tutor' ),
1474 ),
1475 array(
1476 'key' => 'enable_course_benefits',
1477 'type' => 'toggle_single',
1478 'label' => __( 'Benefits', 'tutor' ),
1479 'label_title' => __( 'Enable', 'tutor' ),
1480 'default' => 'on',
1481 'desc' => __( 'Enable to show course benefits section', 'tutor' ),
1482 ),
1483 array(
1484 'key' => 'enable_course_requirements',
1485 'type' => 'toggle_single',
1486 'label' => __( 'Requirements', 'tutor' ),
1487 'label_title' => __( 'Enable', 'tutor' ),
1488 'default' => 'on',
1489 'desc' => __( 'Enable to show courses requirements section', 'tutor' ),
1490 ),
1491 array(
1492 'key' => 'enable_course_target_audience',
1493 'type' => 'toggle_single',
1494 'label' => __( 'Target Audience', 'tutor' ),
1495 'label_title' => __( 'Disable', 'tutor' ),
1496 'default' => 'on',
1497 'desc' => __( 'Enable to show course target audience section', 'tutor' ),
1498 ),
1499 array(
1500 'key' => 'enable_course_announcements',
1501 'type' => 'toggle_single',
1502 'label' => __( 'Announcements', 'tutor' ),
1503 'label_title' => __( 'Enable', 'tutor' ),
1504 'default' => 'on',
1505 'desc' => __( 'Enable to show course announcements section', 'tutor' ),
1506 ),
1507 array(
1508 'key' => 'enable_course_review',
1509 'type' => 'toggle_single',
1510 'label' => __( 'Review', 'tutor' ),
1511 'label_title' => __( 'Enable', 'tutor' ),
1512 'default' => 'on',
1513 'desc' => __( 'Enable to show course review section', 'tutor' ),
1514 )
1515 ),
1516 ),
1517 ),
1518 ),
1519 'colors' => array(
1520 'label' => __( 'Colors', 'tutor' ),
1521 'slug' => 'colors',
1522 'block_type' => 'color_picker',
1523 'fields_group' => array(
1524 array(
1525 'key' => 'color_preset_type',
1526 'type' => 'color_preset',
1527 'label' => __( 'Preset Colors', 'tutor' ),
1528 'desc' => __( 'These colors will be used throughout your website. Choose between these presets or create your own custom palette.', 'tutor' ),
1529 'default' => 'default',
1530 'fields' => array(
1531 /* First 4 preset_name should be same as color_fields */
1532 array(
1533 'key' => 'default',
1534 'label' => __( 'Default', 'tutor' ),
1535 'colors' => array(
1536 array(
1537 'slug' => 'tutor_primary_color',
1538 'preset_name' => 'primary',
1539 'value' => '#3E64DE',
1540 ),
1541 array(
1542 'slug' => 'tutor_primary_hover_color',
1543 'preset_name' => 'hover',
1544 'value' => '#395BCA',
1545 ),
1546 array(
1547 'slug' => 'tutor_text_color',
1548 'preset_name' => 'text',
1549 'value' => '#212327',
1550 ),
1551 array(
1552 'slug' => 'tutor_gray_color',
1553 'preset_name' => 'gray',
1554 'value' => '#E3E5EB',
1555 ),
1556 array(
1557 'slug' => 'tutor_border_color',
1558 'preset_name' => 'border',
1559 'value' => '#CDCFD5',
1560 ),
1561 ),
1562 ),
1563 array(
1564 'key' => 'landscape',
1565 'label' => __( 'Landscape', 'tutor' ),
1566 'colors' => array(
1567 array(
1568 'slug' => 'tutor_primary_color',
1569 'preset_name' => 'primary',
1570 'value' => '#239371',
1571 ),
1572 array(
1573 'slug' => 'tutor_primary_hover_color',
1574 'preset_name' => 'hover',
1575 'value' => '#117D5D',
1576 ),
1577 array(
1578 'slug' => 'tutor_text_color',
1579 'preset_name' => 'text',
1580 'value' => '#212327',
1581 ),
1582 array(
1583 'slug' => 'tutor_gray_color',
1584 'preset_name' => 'gray',
1585 'value' => '#E3E5EB',
1586 ),
1587 array(
1588 'slug' => 'tutor_border_color',
1589 'preset_name' => 'border',
1590 'value' => '#CDCFD5',
1591 ),
1592 ),
1593 ),
1594 array(
1595 'key' => 'ocean',
1596 'label' => __( 'Ocean', 'tutor' ),
1597 'colors' => array(
1598 array(
1599 'slug' => 'tutor_primary_color',
1600 'preset_name' => 'primary',
1601 'value' => '#5A18C2',
1602 ),
1603 array(
1604 'slug' => 'tutor_primary_hover_color',
1605 'preset_name' => 'hover',
1606 'value' => '#3F02A0',
1607 ),
1608 array(
1609 'slug' => 'tutor_text_color',
1610 'preset_name' => 'text',
1611 'value' => '#212327',
1612 ),
1613 array(
1614 'slug' => 'tutor_gray_color',
1615 'preset_name' => 'gray',
1616 'value' => '#E3E5EB',
1617 ),
1618 array(
1619 'slug' => 'tutor_border_color',
1620 'preset_name' => 'border',
1621 'value' => '#CDCFD5',
1622 ),
1623 ),
1624 ),
1625 array(
1626 'key' => 'custom',
1627 'label' => __( 'Custom', 'tutor' ),
1628 'colors' => array(
1629 array(
1630 'slug' => 'tutor_primary_color',
1631 'preset_name' => 'primary',
1632 'value' => '#3E64DE',
1633 ),
1634 array(
1635 'slug' => 'tutor_primary_hover_color',
1636 'preset_name' => 'hover',
1637 'value' => '#28408E',
1638 ),
1639 array(
1640 'slug' => 'tutor_text_color',
1641 'preset_name' => 'text',
1642 'value' => '#1A1B1E',
1643 ),
1644 array(
1645 'slug' => 'tutor_gray_color',
1646 'preset_name' => 'gray',
1647 'value' => '#E3E5EB',
1648 ),
1649 array(
1650 'slug' => 'tutor_border_color',
1651 'preset_name' => 'border',
1652 'value' => '#CDCFD5',
1653 ),
1654 ),
1655 ),
1656 ),
1657 ),
1658 array(
1659 'key' => 'tutor_color_presets',
1660 'type' => 'color_fields',
1661 'label' => __( 'Preset Colors', 'tutor' ),
1662 'fields' => array(
1663 array(
1664 'key' => 'tutor_primary_color',
1665 'type' => 'color_field',
1666 'preset_name' => 'primary',
1667 'preset_exist' => true,
1668 'label' => __( 'Primary Color', 'tutor' ),
1669 'default' => '#3E64DE',
1670 'desc' => __( 'Choose a primary color', 'tutor' ),
1671 ),
1672 array(
1673 'key' => 'tutor_primary_hover_color',
1674 'type' => 'color_field',
1675 'preset_name' => 'hover',
1676 'preset_exist' => true,
1677 'label' => __( 'Primary Hover Color', 'tutor' ),
1678 'default' => '#395BCA',
1679 'desc' => __( 'Choose a primary hover color', 'tutor' ),
1680 ),
1681 array(
1682 'key' => 'tutor_text_color',
1683 'type' => 'color_field',
1684 'preset_name' => 'text',
1685 'preset_exist' => true,
1686 'label' => __( 'Text Color', 'tutor' ),
1687 'default' => '#212327',
1688 'desc' => __( 'Choose a text color for your website', 'tutor' ),
1689 ),
1690 array(
1691 'key' => 'tutor_gray_color',
1692 'type' => 'color_field',
1693 'preset_name' => 'gray',
1694 'preset_exist' => false,
1695 'label' => __( 'Gray', 'tutor' ),
1696 'default' => '#E3E5EB',
1697 'desc' => __( 'Choose a color for elements like table, card etc', 'tutor' ),
1698 ),
1699 array(
1700 'key' => 'tutor_border_color',
1701 'type' => 'color_field',
1702 'preset_name' => 'border',
1703 'preset_exist' => false,
1704 'label' => __( 'Border', 'tutor' ),
1705 'default' => '#CDCFD5',
1706 'desc' => __( 'Choose a border color for your website', 'tutor' ),
1707 ),
1708 ),
1709 ),
1710 ),
1711 ),
1712 ),
1713 ),
1714 'advanced' => array(
1715 'label' => __( 'Advanced', 'tutor' ),
1716 'slug' => 'advanced',
1717 'desc' => __( 'Advanced Settings', 'tutor' ),
1718 'template' => 'basic',
1719 'icon' => 'tutor-icon-filter',
1720 'blocks' => array(
1721 array(
1722 'label' => __( 'Course', 'tutor' ),
1723 'slug' => 'options',
1724 'block_type' => 'uniform',
1725 'fields' => array(
1726 array(
1727 'key' => 'enable_gutenberg_course_edit',
1728 'type' => 'toggle_switch',
1729 'label' => __( 'Gutenberg Editor', 'tutor' ),
1730 'default' => 'off',
1731 'desc' => __( 'Enable this to create courses using the Gutenberg Editor.', 'tutor' ),
1732 ),
1733 array(
1734 'key' => 'hide_course_from_shop_page',
1735 'type' => 'toggle_switch',
1736 'label' => __( 'Hide Course Products on Shop Page', 'tutor' ),
1737 'default' => 'off',
1738 'desc' => __( 'Enable to hide course products on shop page.', 'tutor' ),
1739 ),
1740 array(
1741 'key' => 'course_archive_page',
1742 'type' => 'select',
1743 'label' => __( 'Course Archive Page', 'tutor' ),
1744 'default' => $course_archive_page_id->ID ?? '0',
1745 'options' => $pages,
1746 'desc' => __( 'This page will be used to list all the published courses.', 'tutor' ),
1747 'searchable' => true,
1748 ),
1749 array(
1750 'key' => 'instructor_register_page',
1751 'type' => 'select',
1752 'label' => __( 'Instructor Registration Page', 'tutor' ),
1753 'default' => '0',
1754 'options' => $pages,
1755 'desc' => __( 'Choose the page for instructor registration.', 'tutor' ),
1756 'searchable' => true,
1757 ),
1758 array(
1759 'key' => 'student_register_page',
1760 'type' => 'select',
1761 'label' => __( 'Student Registration Page', 'tutor' ),
1762 'default' => '0',
1763 'options' => $pages,
1764 'desc' => __( 'Choose the page for student registration.', 'tutor' ),
1765 'searchable' => true,
1766 ),
1767 array(
1768 'key' => 'lesson_video_duration_youtube_api_key',
1769 'type' => 'text',
1770 'label' => __( 'YouTube API Key', 'tutor' ),
1771 'default' => '',
1772 'desc' => __(
1773 'To host live videos on your platform using YouTube, enter your YouTube API key.',
1774 'tutor'
1775 ),
1776 'placeholder' => __( 'Insert API key here', 'tutor' ),
1777 ),
1778 ),
1779 ),
1780 array(
1781 'label' => __( 'Base Permalink', 'tutor' ),
1782 'slug' => 'base_permalink',
1783 'block_type' => 'uniform',
1784 'fields' => array(
1785 array(
1786 'key' => 'course_permalink_base',
1787 'type' => 'text',
1788 'label' => __( 'Course Permalink', 'tutor' ),
1789 'default' => 'courses',
1790 'desc' => $course_url,
1791 ),
1792 array(
1793 'key' => 'lesson_permalink_base',
1794 'type' => 'text',
1795 'label' => __( 'Lesson Permalink', 'tutor' ),
1796 'default' => 'lessons',
1797 'desc' => $lesson_url,
1798 ),
1799 array(
1800 'key' => 'quiz_permalink_base',
1801 'type' => 'text',
1802 'label' => __( 'Quiz Permalink', 'tutor' ),
1803 'default' => 'quizzes',
1804 'desc' => $quiz_url,
1805 ),
1806 ),
1807 ),
1808 array(
1809 'label' => __( 'Options', 'tutor' ),
1810 'slug' => 'options',
1811 'block_type' => 'uniform',
1812 'fields' => array(
1813 array(
1814 'key' => 'enable_profile_completion',
1815 'type' => 'toggle_switch',
1816 'label' => __( 'Profile Completion', 'tutor' ),
1817 'label_title' => '',
1818 'default' => 'off',
1819 'desc' => __( 'Enabling this feature will show a notification bar to students and instructors to complete their profile information', 'tutor' ),
1820 ),
1821 array(
1822 'key' => 'enable_tutor_native_login',
1823 'type' => 'toggle_switch',
1824 'label' => __( 'Enable Tutor LMS Login', 'tutor' ),
1825 'label_title' => '',
1826 'default' => 'on',
1827 'desc' => __( 'Enable to use the Tutor LMS native login system instead of the WordPress login page', 'tutor' ),
1828 ),
1829 array(
1830 'key' => 'delete_on_uninstall',
1831 'type' => 'toggle_switch',
1832 'label' => __( 'Erase upon uninstallation', 'tutor' ),
1833 'label_title' => '',
1834 'default' => 'off',
1835 'desc' => __( 'Delete all data during uninstallation', 'tutor' ),
1836 ),
1837 array(
1838 'key' => 'enable_tutor_maintenance_mode',
1839 'type' => 'toggle_switch',
1840 'label' => __( 'Maintenance Mode', 'tutor' ),
1841 'label_title' => '',
1842 'default' => 'off',
1843 'desc' => __( 'Enabling maintenance mode will display a custom message on the frontend. During maintenance mode, visitors cannot access site content, but the wp-admin dashboard remains accessible.', 'tutor' ),
1844 ),
1845 ),
1846 ),
1847 ),
1848 ),
1849 );
1850
1851 $attrs = apply_filters( 'tutor/options/extend/attr', apply_filters( 'tutor/options/attr', $attr ) );
1852
1853 // Get the active tab.
1854 $tab_page = tutor_utils()->array_get( 'tab_page', $_REQUEST, 'general' );
1855 $tab_data = null;
1856 $template = null;
1857
1858 foreach ( $attrs as $key => $section ) {
1859 if ( $tab_page == $key ) {
1860 if ( isset( $section['template_path'] ) && $section['template_path'] ) {
1861 $template = $section['template_path'];
1862 $tab_data = $section;
1863 }
1864 break;
1865 }
1866 }
1867
1868 // Store in runtime cache.
1869 $this->setting_fields = array(
1870 'option_fields' => $attrs,
1871 'active_tab' => $tab_page,
1872 'active_tab_data' => $tab_data,
1873 'template_path' => $template,
1874 );
1875
1876 return $this->setting_fields;
1877 }
1878
1879 /**
1880 * Generate field
1881 *
1882 * @since 2.0.0
1883 *
1884 * @param array $field field array.
1885 * @param array $blocks blocks array.
1886 *
1887 * @return void
1888 *
1889 * Generate Option Field
1890 */
1891 public function generate_field( $field = array(), $blocks = array() ) {
1892 ob_start();
1893 if ( isset( $field['type'] ) ) {
1894 include tutor()->path . "views/options/field-types/{$field['type']}.php";
1895 }
1896 echo ob_get_clean();//phpcs:ignore
1897 }
1898
1899 /**
1900 * Include field type template & return buffered
1901 * string data.
1902 *
1903 * @since 2.0.0
1904 *
1905 * @param array $field field.
1906 *
1907 * @return string
1908 */
1909 public function field_type( $field = array() ) {
1910 ob_start();
1911 if ( isset( $field['type'] ) ) {
1912 include tutor()->path . "views/options/field-types/{$field['type']}.php";
1913 }
1914 return ob_get_clean();
1915 }
1916
1917 /**
1918 * Include Option blocks template & return
1919 * buffered string data.
1920 *
1921 * @since 2.0.0
1922 *
1923 * @param array $blocks blocks.
1924 *
1925 * @return string
1926 */
1927 public function blocks( $blocks = array() ) {
1928 ob_start();
1929 include apply_filters( 'tutor_settings_block_template_path', tutor()->path . 'views/options/option_blocks.php', $blocks );
1930 return ob_get_clean();
1931 }
1932
1933 /**
1934 * Include options template & returns
1935 * buffered string data.
1936 *
1937 * @since 2.0.0
1938 *
1939 * @param array $section section.
1940 *
1941 * @return string
1942 */
1943 public function template( $section = array() ) {
1944 ob_start();
1945 $blocks = $section['blocks'];
1946 if ( isset( $section['template'] ) ) {
1947 include apply_filters( 'tutor_option_template_path', tutor()->path . "views/options/template/{$section['template']}.php", $section['template'] );
1948 }
1949 return ob_get_clean();
1950 }
1951
1952
1953 /**
1954 * Load template inside template directory
1955 *
1956 * @since 2.0.0
1957 *
1958 * @param mixed $template_slug template slug.
1959 * @param mixed $section section.
1960 *
1961 * @return string
1962 */
1963 public function view_template( $template_slug, $section = array() ) {
1964 ob_start();
1965 if ( isset( $template_slug ) ) {
1966 require tutor()->path . "views/options/template/{$template_slug}";
1967 }
1968 return ob_get_clean();
1969 }
1970
1971 /**
1972 * Get field name
1973 *
1974 * It's useful when a field has event key like course.lessons
1975 *
1976 * @since 3.5.0
1977 *
1978 * @param array $field Option field array.
1979 *
1980 * @return string
1981 */
1982 public function get_field_name( array $field ) {
1983 $events = $field['event'] ?? null;
1984 $field_name = 'tutor_option';
1985 if ( $events ) {
1986 $events = explode( '.', $events );
1987 foreach ( $events as $event ) {
1988 $field_name .= '[' . $event . ']';
1989 }
1990 $field_name .= '[' . $field['key'] . ']';
1991 } else {
1992 $field_name .= '[' . $field['key'] . ']';
1993 }
1994
1995 return $field_name;
1996 }
1997
1998 /**
1999 * Json schema data
2000 *
2001 * @since 1.0.0
2002 *
2003 * @return array
2004 */
2005 public function get_export_json_schema() {
2006 $export_data = array(
2007 'schema_version' => '1.0.0',
2008 'exported_at' => current_time( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ),
2009 'keep_media_files' => false,
2010 'keep_user_data' => false,
2011 'data' => array(),
2012 );
2013
2014 return $export_data;
2015 }
2016
2017 /**
2018 * Update settings log based on the new data
2019 *
2020 * @since 3.6.0
2021 *
2022 * @param array $new_settings_data New exported/import settings data.
2023 * @param string $action_type Action type Imported/Exported.
2024 *
2025 * @return array Settings log data
2026 */
2027 public function update_settings_log( $new_settings_data, $action_type ) {
2028 $get_final_data = array();
2029
2030 $action = strtolower( $action_type );
2031
2032 $time = tutor_time();
2033
2034 $save_import_data['datetime'] = $time;
2035 $save_import_data['history_date'] = gmdate( 'j M, Y, g:i a', $time );
2036 $save_import_data['datatype'] = $action_type;
2037 $save_import_data['dataset'] = $new_settings_data;
2038 $import_data[ 'tutor-imported-' . $time ] = $save_import_data;
2039
2040 $get_option_data = get_option( 'tutor_settings_log' );
2041 if ( empty( $get_option_data ) ) {
2042 $get_option_data = array();
2043 }
2044 if ( ! empty( $get_option_data ) && null !== $save_import_data['dataset'] ) {
2045
2046 $update_option = array_merge( $import_data, $get_option_data );
2047
2048 $update_option = Input::sanitize_array(
2049 $update_option,
2050 array(
2051 'payment_settings' => 'wp_kses_post',
2052 'tutor_bank_transfer_withdraw_instruction' => 'sanitize_textarea_field',
2053 'certificate_showcase_desc' => 'sanitize_textarea_field',
2054 'invoice_from_address' => 'sanitize_textarea_field',
2055 'fees_name' => 'sanitize_textarea_field',
2056 )
2057 );
2058
2059 if ( ! empty( $update_option ) ) {
2060 update_option( 'tutor_settings_log', $update_option );
2061 }
2062
2063 if ( 'imported' === $action ) {
2064 if ( ! empty( $save_import_data ) ) {
2065 update_option( 'tutor_option', $save_import_data['dataset'] );
2066 }
2067 }
2068
2069 $get_final_data = get_option( 'tutor_settings_log' );
2070
2071 } else {
2072 if ( ! empty( $import_data ) ) {
2073 update_option( 'tutor_settings_log', $import_data );
2074 }
2075
2076 if ( 'imported' === $action ) {
2077 if ( ! empty( $save_import_data ) ) {
2078 update_option( 'tutor_option', $save_import_data['dataset'] );
2079 }
2080 }
2081
2082 $get_final_data = get_option( 'tutor_settings_log' );
2083 }
2084
2085 return $get_final_data;
2086 }
2087 }
2088