From 031e916585d62f5c9dd918cd0f9202029070303c Mon Sep 17 00:00:00 2001 From: nur-alam Date: Sun, 29 Mar 2026 03:13:09 +0600 Subject: [PATCH 01/15] Add learning mood preference to user settings and update Utils for retrieval --- classes/UserPreference.php | 3 +++ classes/Utils.php | 12 +++++++++++- .../dashboard/account/settings/preferences.php | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/classes/UserPreference.php b/classes/UserPreference.php index c5d4e0b6e2..eaa6f1713c 100644 --- a/classes/UserPreference.php +++ b/classes/UserPreference.php @@ -259,11 +259,13 @@ public function ajax_save_user_preferences() { $auto_play_next = Input::post( 'auto_play_next', false, INPUT::TYPE_BOOL ); $theme = Input::post( 'theme', self::DEFAULT_THEME ); $font_scale = Input::post( 'font_scale', self::DEFAULT_FONT_SCALE, INPUT::TYPE_INT ); + $learning_mood = Input::post( 'learning_mood', false, INPUT::TYPE_BOOL ); $preferences_settings = array( 'auto_play_next' => $auto_play_next, 'theme' => $theme, 'font_scale' => $font_scale, + 'learning_mood' => $learning_mood, ); $preference_data = $this->save_preferences( $preferences_settings, get_current_user_id() ); @@ -297,6 +299,7 @@ private static function get_default_preferences() { 'auto_play_next' => (bool) tutor_utils()->get_option( 'autoload_next_course_content' ), 'theme' => self::DEFAULT_THEME, 'font_scale' => self::DEFAULT_FONT_SCALE, + 'learning_mood' => Utils::is_kids_mode(), ) ); diff --git a/classes/Utils.php b/classes/Utils.php index 802810a52e..bf4cd74b71 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -11071,6 +11071,16 @@ public static function get_icon_by_post_type( $post_type ): string { * @return bool */ public static function is_kids_mode(): bool { - return Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(); + $admin_kids_mode = Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(); + + $user_id = get_current_user_id(); + if ( $user_id ) { + $stored = get_user_meta( $user_id, UserPreference::META_KEY, true ); + if ( is_array( $stored ) && array_key_exists( 'learning_mood', $stored ) ) { + return (bool) $stored['learning_mood']; + } + } + + return $admin_kids_mode; } } diff --git a/templates/dashboard/account/settings/preferences.php b/templates/dashboard/account/settings/preferences.php index b1a9c6decd..012f543d2d 100644 --- a/templates/dashboard/account/settings/preferences.php +++ b/templates/dashboard/account/settings/preferences.php @@ -105,6 +105,24 @@ ?> +
+
+
+ name( Icon::ADDONS )->size( 20 )->render(); ?> +
+ +
+
+ type( InputType::SWITCH ) + ->size( Size::SM ) + ->name( 'learning_mood' ) + ->attr( 'x-bind', "register('learning_mood')" ) + ->render(); + ?> +
+
From fa4ae5629d459a8bc21814fb1ae3bd9a5dd0b960 Mon Sep 17 00:00:00 2001 From: nur-alam Date: Sun, 29 Mar 2026 04:18:24 +0600 Subject: [PATCH 02/15] Refactor learning mood retrieval in UserPreference and Utils classes to utilize Options_V2 for improved clarity and maintainability. --- classes/UserPreference.php | 3 ++- classes/Utils.php | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/classes/UserPreference.php b/classes/UserPreference.php index eaa6f1713c..6a57f4f0f6 100644 --- a/classes/UserPreference.php +++ b/classes/UserPreference.php @@ -17,6 +17,7 @@ use Tutor\Cache\TutorCache; use Tutor\Helpers\HttpHelper; +use Tutor\Options_V2; use Tutor\Traits\JsonResponse; /** @@ -299,7 +300,7 @@ private static function get_default_preferences() { 'auto_play_next' => (bool) tutor_utils()->get_option( 'autoload_next_course_content' ), 'theme' => self::DEFAULT_THEME, 'font_scale' => self::DEFAULT_FONT_SCALE, - 'learning_mood' => Utils::is_kids_mode(), + 'learning_mood' => Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(), ) ); diff --git a/classes/Utils.php b/classes/Utils.php index bf4cd74b71..c860d06e4c 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -11075,10 +11075,8 @@ public static function is_kids_mode(): bool { $user_id = get_current_user_id(); if ( $user_id ) { - $stored = get_user_meta( $user_id, UserPreference::META_KEY, true ); - if ( is_array( $stored ) && array_key_exists( 'learning_mood', $stored ) ) { - return (bool) $stored['learning_mood']; - } + $user_learning_mood = UserPreference::get('learning_mood'); + return (bool) $user_learning_mood; } return $admin_kids_mode; From ee3239d6f1137883331080e1c15c2c539f69a02d Mon Sep 17 00:00:00 2001 From: nur-alam Date: Sun, 29 Mar 2026 16:00:19 +0600 Subject: [PATCH 03/15] Refactor is_kids_mode method in Utils class to improve clarity by rearranging the admin kids mode logic. --- classes/Utils.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/classes/Utils.php b/classes/Utils.php index c860d06e4c..d8795cd837 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -11071,14 +11071,13 @@ public static function get_icon_by_post_type( $post_type ): string { * @return bool */ public static function is_kids_mode(): bool { - $admin_kids_mode = Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(); - $user_id = get_current_user_id(); if ( $user_id ) { $user_learning_mood = UserPreference::get('learning_mood'); return (bool) $user_learning_mood; } + $admin_kids_mode = Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(); return $admin_kids_mode; } } From 9fbd82f73d6b1f3bbd9bf99940d9306c12f82c1c Mon Sep 17 00:00:00 2001 From: nur-alam Date: Mon, 30 Mar 2026 10:50:40 +0600 Subject: [PATCH 04/15] Add learning mood icon and update related references in the codebase --- assets/icons/learning-mood.svg | 3 +++ assets/src/js/v3/shared/icons/types.ts | 2 ++ classes/Icon.php | 1 + templates/dashboard/account/settings/preferences.php | 2 +- 4 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 assets/icons/learning-mood.svg diff --git a/assets/icons/learning-mood.svg b/assets/icons/learning-mood.svg new file mode 100644 index 0000000000..7f4f116a41 --- /dev/null +++ b/assets/icons/learning-mood.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/src/js/v3/shared/icons/types.ts b/assets/src/js/v3/shared/icons/types.ts index de28c43c5c..644a2c4595 100644 --- a/assets/src/js/v3/shared/icons/types.ts +++ b/assets/src/js/v3/shared/icons/types.ts @@ -79,6 +79,7 @@ export const icons = [ 'circumLock', 'clock', 'clock2', + 'clockFrame', 'coding', 'collapsed', 'colorOption', @@ -206,6 +207,7 @@ export const icons = [ 'landscape', 'landscapeFilled', 'league', + 'learningMood', 'left', 'lesson', 'level', diff --git a/classes/Icon.php b/classes/Icon.php index 1c1ace5779..529837774e 100644 --- a/classes/Icon.php +++ b/classes/Icon.php @@ -223,6 +223,7 @@ final class Icon { const LANDSCAPE = 'landscape'; const LANDSCAPE_FILLED = 'landscape-filled'; const LEAGUE = 'league'; + const LEARNING_MOOD = 'learning-mood'; const LEFT = 'left'; const LESSON = 'lesson'; const LEVEL = 'level'; diff --git a/templates/dashboard/account/settings/preferences.php b/templates/dashboard/account/settings/preferences.php index 012f543d2d..37cc3accbb 100644 --- a/templates/dashboard/account/settings/preferences.php +++ b/templates/dashboard/account/settings/preferences.php @@ -108,7 +108,7 @@
- name( Icon::ADDONS )->size( 20 )->render(); ?> + name( Icon::LEARNING_MOOD )->size( 20 )->render(); ?>
From c1b96effd3235684793a2ed8b74672403db9a8a6 Mon Sep 17 00:00:00 2001 From: nur-alam Date: Mon, 30 Mar 2026 16:44:57 +0600 Subject: [PATCH 05/15] refactor: add reset preferences functionality & Update theme attribute to 'data-tutor-theme' --- assets/core/scss/themes/_dark.scss | 2 +- assets/core/scss/themes/_light.scss | 2 +- assets/core/ts/components/calendar.ts | 2 +- assets/core/ts/services/Preference.ts | 2 +- .../js/frontend/dashboard/pages/settings.ts | 34 ++++++++++++++ assets/src/js/v3/shared/utils/endpoints.ts | 1 + classes/UserPreference.php | 44 ++++++++++++++++++- .../account/settings/preferences.php | 30 +++++++++++-- 8 files changed, 109 insertions(+), 8 deletions(-) diff --git a/assets/core/scss/themes/_dark.scss b/assets/core/scss/themes/_dark.scss index f5f39160e3..7eed4a1904 100644 --- a/assets/core/scss/themes/_dark.scss +++ b/assets/core/scss/themes/_dark.scss @@ -3,7 +3,7 @@ @use '../tokens' as *; -[data-theme='dark'] { +[data-tutor-theme='dark'] { // ============================================================================= // SURFACE COLORS // ============================================================================= diff --git a/assets/core/scss/themes/_light.scss b/assets/core/scss/themes/_light.scss index 4390cafb3b..58b8036faf 100644 --- a/assets/core/scss/themes/_light.scss +++ b/assets/core/scss/themes/_light.scss @@ -4,7 +4,7 @@ @use '../tokens' as *; :root, -[data-theme="light"] { +[data-tutor-theme="light"] { // ============================================================================= // SURFACE COLORS // ============================================================================= diff --git a/assets/core/ts/components/calendar.ts b/assets/core/ts/components/calendar.ts index 5744f301ba..0ebe12dad4 100644 --- a/assets/core/ts/components/calendar.ts +++ b/assets/core/ts/components/calendar.ts @@ -71,7 +71,7 @@ const TUTOR_CALENDAR_VALUES = { apply: 'apply', clear: 'clear', calendarZIndex: '100001', - themeAttrDetect: 'body[data-theme]', + themeAttrDetect: 'body[data-tutor-theme]', calendarClasses: 'vc tutor-vc-calendar', } as const; diff --git a/assets/core/ts/services/Preference.ts b/assets/core/ts/services/Preference.ts index aa18f8ec3e..c6dc2f163b 100644 --- a/assets/core/ts/services/Preference.ts +++ b/assets/core/ts/services/Preference.ts @@ -9,7 +9,7 @@ class PreferenceService { private readonly BASE_FONT_SIZE = 16; private readonly SCALE_PERCENTAGE_BASE = 100; private readonly STYLE_ID = 'tutor-font-scale'; - private readonly DATA_THEME_ATTR = 'data-theme'; + private readonly DATA_THEME_ATTR = 'data-tutor-theme'; constructor() { this.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); diff --git a/assets/src/js/frontend/dashboard/pages/settings.ts b/assets/src/js/frontend/dashboard/pages/settings.ts index 43950ffd38..5758da589a 100644 --- a/assets/src/js/frontend/dashboard/pages/settings.ts +++ b/assets/src/js/frontend/dashboard/pages/settings.ts @@ -60,9 +60,15 @@ interface PreferencesFormProps { auto_play_next: boolean; theme: string; font_scale: number; + learning_mood: boolean; formId?: string; } +interface ResetPreferencesPayload { + formId: string; + modalId: string; +} + interface UpdateNotificationProps { [key: string]: boolean | string; } @@ -77,6 +83,7 @@ interface ResetPasswordResponse { const settings = () => { const query = window.TutorCore.query; const form = window.TutorCore.form; + const modal = window.TutorCore.modal; const toast = window.TutorCore.toast; return { @@ -90,6 +97,7 @@ const settings = () => { resetPasswordMutation: null as MutationState | null, handleUpdateNotification: null as MutationState | null, savePreferencesMutation: null as MutationState> | null, + resetPreferencesMutation: null as MutationState> | null, init() { if (!this.$el) { @@ -103,6 +111,7 @@ const settings = () => { this.handleSaveBillingInfo = this.handleSaveBillingInfo.bind(this); this.handleSaveWithdrawMethod = this.handleSaveWithdrawMethod.bind(this); this.handleResetPassword = this.handleResetPassword.bind(this); + this.resetToDefault = this.resetToDefault.bind(this); this.handleUpdateNotification = query.useMutation(this.updateNotification, { onSuccess: (data: TutorMutationResponse, payload: UpdateNotificationProps) => { @@ -190,6 +199,19 @@ const settings = () => { toast.error(convertToErrorMessage(error)); }, }); + + this.resetPreferencesMutation = query.useMutation(this.resetPreferences, { + onSuccess: (data: TutorMutationResponse, payload: ResetPreferencesPayload) => { + form.reset(payload?.formId || '', (data?.data || {}) as unknown as Record); + toast.success(data?.message ?? __('Preferences reset successfully', 'tutor')); + if (payload?.modalId) { + modal.closeModal(payload.modalId); + } + }, + onError: (error: Error) => { + toast.error(convertToErrorMessage(error)); + }, + }); }, async updatePreferences(payload: PreferencesFormProps) { @@ -198,6 +220,18 @@ const settings = () => { >; }, + async resetPreferences(payload: ResetPreferencesPayload) { + // Endpoint doesn't need payload data; we use payload only to pass form/modal ids to onSuccess. + void payload; + return wpAjaxInstance.post(endpoints.RESET_USER_PREFERENCES, {}) as unknown as Promise< + TutorMutationResponse + >; + }, + + resetToDefault(formId: string, modalId: string) { + this.resetPreferencesMutation?.mutate({ formId, modalId }); + }, + async updateNotification(payload: UpdateNotificationProps) { const transformedPayload = Object.keys(payload).reduce( (formattedPayload, key) => { diff --git a/assets/src/js/v3/shared/utils/endpoints.ts b/assets/src/js/v3/shared/utils/endpoints.ts index 6a5bc00ee4..3a3898f41f 100644 --- a/assets/src/js/v3/shared/utils/endpoints.ts +++ b/assets/src/js/v3/shared/utils/endpoints.ts @@ -211,6 +211,7 @@ const endpoints = { RESET_PASSWORD: 'tutor_profile_password_reset', UPDATE_PROFILE_NOTIFICATION: 'tutor_save_notification_preference', UPDATE_USER_PREFERENCES: 'tutor_save_user_preferences', + RESET_USER_PREFERENCES: 'tutor_reset_user_preferences', REMOVE_DEVICE_MANUALLY: 'tutor_remove_device_manually', REMOVE_ALL_ACTIVE_LOGINS: 'tutor_remove_all_active_logins', diff --git a/classes/UserPreference.php b/classes/UserPreference.php index 6a57f4f0f6..246e5d26c8 100644 --- a/classes/UserPreference.php +++ b/classes/UserPreference.php @@ -114,6 +114,7 @@ public function __construct( $register_hooks = true ) { } add_action( 'wp_ajax_tutor_save_user_preferences', array( $this, 'ajax_save_user_preferences' ) ); + add_action( 'wp_ajax_tutor_reset_user_preferences', array( $this, 'ajax_reset_user_preferences' ) ); add_filter( 'body_class', array( $this, 'add_theme_attribute' ) ); add_action( 'wp_head', array( $this, 'apply_font_scale' ) ); } @@ -153,7 +154,7 @@ public function add_theme_attribute( $classes ) { if ( ! in_array( $theme, self::THEMES, true ) ) { $theme = self::DEFAULT_THEME; } - echo ' data-theme="' . esc_attr( $theme ) . '"'; + echo ' data-tutor-theme="' . esc_attr( $theme ) . '"'; return $classes; } @@ -285,6 +286,47 @@ public function ajax_save_user_preferences() { ); } + /** + * AJAX handler: reset current user's preferences back to defaults. + * + * @since 4.0.0 + * + * @return void + */ + public function ajax_reset_user_preferences() { + tutor_utils()->check_nonce(); + + if ( ! is_user_logged_in() ) { + $this->json_response( + tutor_utils()->error_message( 'forbidden' ), + null, + HttpHelper::STATUS_UNAUTHORIZED + ); + } + + $user_id = get_current_user_id(); + if ( ! $user_id ) { + $this->json_response( + __( 'Failed to reset preferences', 'tutor' ), + null, + HttpHelper::STATUS_NOT_FOUND + ); + } + + $defaults = self::get_default_preferences(); + + // Clear stored overrides; get_preferences() will fall back to defaults. + update_user_meta( $user_id, self::META_KEY, array() ); + + // Keep runtime cache consistent for this request. + TutorCache::set( 'get_preferences_' . $user_id, $defaults ); + + $this->json_response( + __( 'Preferences reset successfully', 'tutor' ), + $defaults + ); + } + /** * Get default preferences. * diff --git a/templates/dashboard/account/settings/preferences.php b/templates/dashboard/account/settings/preferences.php index 37cc3accbb..f264d0382c 100644 --- a/templates/dashboard/account/settings/preferences.php +++ b/templates/dashboard/account/settings/preferences.php @@ -13,6 +13,7 @@ use TUTOR\Icon; use Tutor\Components\SvgIcon; use TUTOR\UserPreference; +use Tutor\Components\ConfirmationModal; use Tutor\Components\InputField; use Tutor\Components\Constants\InputType; use Tutor\Components\Constants\Size; @@ -24,6 +25,9 @@ // Load current user preferences to seed the form. $user_preferences = UserPreference::get_preferences(); +// Confirmation modal id for resetting user preferences. +$reset_modal_id = 'tutor-preferences-reset-modal'; + ?>
@@ -39,9 +43,29 @@ @submit="handleSubmit((data) => { savePreferencesMutation?.mutate({...data, formId: ''}); })($event)" > -
- -
+
+
+ +
+
+ name( Icon::RELOAD_3 )->size( 16 )->render(); ?> + +
+
+ + id( $reset_modal_id ) + ->title( __( 'Reset Preferences?', 'tutor' ) ) + ->message( __( 'This will reset your Tutor preferences back to the default values.', 'tutor' ) ) + ->cancel_text( __( 'Cancel', 'tutor' ) ) + ->confirm_text( __( 'Yes, Reset', 'tutor' ) ) + ->icon( Icon::RELOAD_3, 80, 80 ) + ->confirm_handler( "resetToDefault('" . esc_js( $form_id ) . "','" . esc_js( $reset_modal_id ) . "')" ) + ->mutation_state( 'resetPreferencesMutation' ) + ->render(); + ?> +
From bb74ebfc31f74845188c3742a35ea2c3bd3979d4 Mon Sep 17 00:00:00 2001 From: nur-alam Date: Tue, 31 Mar 2026 15:09:06 +0600 Subject: [PATCH 06/15] feat: implement reset preferences feature --- .../illustrations/reset-preferences.svg | 1 + .../js/frontend/dashboard/pages/settings.ts | 15 +++++--------- .../dashboard/settings/_preferences.scss | 3 +-- .../account/settings/preferences.php | 20 ++++++++++--------- 4 files changed, 18 insertions(+), 21 deletions(-) create mode 100644 assets/images/illustrations/reset-preferences.svg diff --git a/assets/images/illustrations/reset-preferences.svg b/assets/images/illustrations/reset-preferences.svg new file mode 100644 index 0000000000..60e9921bf6 --- /dev/null +++ b/assets/images/illustrations/reset-preferences.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/src/js/frontend/dashboard/pages/settings.ts b/assets/src/js/frontend/dashboard/pages/settings.ts index 5758da589a..5b7a2d3ddc 100644 --- a/assets/src/js/frontend/dashboard/pages/settings.ts +++ b/assets/src/js/frontend/dashboard/pages/settings.ts @@ -111,7 +111,7 @@ const settings = () => { this.handleSaveBillingInfo = this.handleSaveBillingInfo.bind(this); this.handleSaveWithdrawMethod = this.handleSaveWithdrawMethod.bind(this); this.handleResetPassword = this.handleResetPassword.bind(this); - this.resetToDefault = this.resetToDefault.bind(this); + this.handleResetPreferences = this.handleResetPreferences.bind(this); this.handleUpdateNotification = query.useMutation(this.updateNotification, { onSuccess: (data: TutorMutationResponse, payload: UpdateNotificationProps) => { @@ -201,12 +201,9 @@ const settings = () => { }); this.resetPreferencesMutation = query.useMutation(this.resetPreferences, { - onSuccess: (data: TutorMutationResponse, payload: ResetPreferencesPayload) => { - form.reset(payload?.formId || '', (data?.data || {}) as unknown as Record); + onSuccess: (data: TutorMutationResponse) => { toast.success(data?.message ?? __('Preferences reset successfully', 'tutor')); - if (payload?.modalId) { - modal.closeModal(payload.modalId); - } + window.location.reload(); }, onError: (error: Error) => { toast.error(convertToErrorMessage(error)); @@ -221,14 +218,12 @@ const settings = () => { }, async resetPreferences(payload: ResetPreferencesPayload) { - // Endpoint doesn't need payload data; we use payload only to pass form/modal ids to onSuccess. - void payload; - return wpAjaxInstance.post(endpoints.RESET_USER_PREFERENCES, {}) as unknown as Promise< + return wpAjaxInstance.post(endpoints.RESET_USER_PREFERENCES, payload) as unknown as Promise< TutorMutationResponse >; }, - resetToDefault(formId: string, modalId: string) { + handleResetPreferences(formId: string, modalId: string) { this.resetPreferencesMutation?.mutate({ formId, modalId }); }, diff --git a/assets/src/scss/frontend/dashboard/settings/_preferences.scss b/assets/src/scss/frontend/dashboard/settings/_preferences.scss index d9cd3c1c1a..f3e4e4963f 100644 --- a/assets/src/scss/frontend/dashboard/settings/_preferences.scss +++ b/assets/src/scss/frontend/dashboard/settings/_preferences.scss @@ -4,7 +4,6 @@ .tutor-preferences { &-section-header { @include tutor-typography('h5', 'semibold', 'primary', 'heading'); - margin: $tutor-spacing-none $tutor-spacing-none $tutor-spacing-4 $tutor-spacing-none; @include tutor-breakpoint-down(sm) { @include tutor-typography('medium', 'semibold', 'primary', 'heading'); @@ -47,4 +46,4 @@ flex-shrink: 0; } } -} +} \ No newline at end of file diff --git a/templates/dashboard/account/settings/preferences.php b/templates/dashboard/account/settings/preferences.php index f264d0382c..46bd20cba3 100644 --- a/templates/dashboard/account/settings/preferences.php +++ b/templates/dashboard/account/settings/preferences.php @@ -17,6 +17,7 @@ use Tutor\Components\InputField; use Tutor\Components\Constants\InputType; use Tutor\Components\Constants\Size; +use Tutor\Helpers\UrlHelper; $theme_options = UserPreference::get_theme_options(); @@ -33,6 +34,7 @@
'}); })($event)" > -
+
-
+
name( Icon::RELOAD_3 )->size( 16 )->render(); ?>
- id( $reset_modal_id ) - ->title( __( 'Reset Preferences?', 'tutor' ) ) - ->message( __( 'This will reset your Tutor preferences back to the default values.', 'tutor' ) ) + ->title( __( 'Reset your Preferences?', 'tutor' ) ) + ->message( __( 'This will reset your learning preferences to the default settings. Your progress and account data won’t be affected.', 'tutor' ) ) ->cancel_text( __( 'Cancel', 'tutor' ) ) - ->confirm_text( __( 'Yes, Reset', 'tutor' ) ) - ->icon( Icon::RELOAD_3, 80, 80 ) - ->confirm_handler( "resetToDefault('" . esc_js( $form_id ) . "','" . esc_js( $reset_modal_id ) . "')" ) + ->confirm_text( __( 'Reset Preferences', 'tutor' ) ) + // ->icon( tutor()->url . 'assets/images/illustrations/reset-preferences.svg' ) + ->icon( UrlHelper::asset( 'images/illustrations/reset-preferences.svg' ) ) + ->confirm_handler( "handleResetPreferences('" . esc_js( $form_id ) . "','" . esc_js( $reset_modal_id ) . "')" ) ->mutation_state( 'resetPreferencesMutation' ) ->render(); ?> From 49936f78d3fdbb8af12f2ff0f207eeac52d8888a Mon Sep 17 00:00:00 2001 From: nur-alam Date: Tue, 31 Mar 2026 16:42:53 +0600 Subject: [PATCH 07/15] refactor: remove reset preferences SVG and update preferences reset logic --- assets/images/illustrations/reset-preferences.svg | 1 - .../frontend/dashboard/settings/_preferences.scss | 11 +++++------ classes/UserPreference.php | 11 +++-------- templates/dashboard/account/settings/preferences.php | 7 +++---- 4 files changed, 11 insertions(+), 19 deletions(-) delete mode 100644 assets/images/illustrations/reset-preferences.svg diff --git a/assets/images/illustrations/reset-preferences.svg b/assets/images/illustrations/reset-preferences.svg deleted file mode 100644 index 60e9921bf6..0000000000 --- a/assets/images/illustrations/reset-preferences.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assets/src/scss/frontend/dashboard/settings/_preferences.scss b/assets/src/scss/frontend/dashboard/settings/_preferences.scss index f3e4e4963f..98be40c795 100644 --- a/assets/src/scss/frontend/dashboard/settings/_preferences.scss +++ b/assets/src/scss/frontend/dashboard/settings/_preferences.scss @@ -2,12 +2,11 @@ @use '@Core/scss/mixins' as *; .tutor-preferences { - &-section-header { - @include tutor-typography('h5', 'semibold', 'primary', 'heading'); - - @include tutor-breakpoint-down(sm) { - @include tutor-typography('medium', 'semibold', 'primary', 'heading'); - } + &-reset-default { + @include tutor-flex(row, center, flex-end); + color: $tutor-text-secondary; + gap: $tutor-spacing-2; + cursor: pointer; } &-setting-item { diff --git a/classes/UserPreference.php b/classes/UserPreference.php index 246e5d26c8..a48defbc02 100644 --- a/classes/UserPreference.php +++ b/classes/UserPreference.php @@ -313,17 +313,12 @@ public function ajax_reset_user_preferences() { ); } - $defaults = self::get_default_preferences(); - - // Clear stored overrides; get_preferences() will fall back to defaults. - update_user_meta( $user_id, self::META_KEY, array() ); - - // Keep runtime cache consistent for this request. - TutorCache::set( 'get_preferences_' . $user_id, $defaults ); + // Delete user meta. + delete_user_meta( $user_id, self::META_KEY ); $this->json_response( __( 'Preferences reset successfully', 'tutor' ), - $defaults + null ); } diff --git a/templates/dashboard/account/settings/preferences.php b/templates/dashboard/account/settings/preferences.php index 46bd20cba3..ea93d8a55a 100644 --- a/templates/dashboard/account/settings/preferences.php +++ b/templates/dashboard/account/settings/preferences.php @@ -46,10 +46,10 @@ class="tutor-flex tutor-flex-column tutor-gap-5" >
-
+
-
+
name( Icon::RELOAD_3 )->size( 16 )->render(); ?>
@@ -61,8 +61,7 @@ class="tutor-flex tutor-flex-column tutor-gap-5" ->message( __( 'This will reset your learning preferences to the default settings. Your progress and account data won’t be affected.', 'tutor' ) ) ->cancel_text( __( 'Cancel', 'tutor' ) ) ->confirm_text( __( 'Reset Preferences', 'tutor' ) ) - // ->icon( tutor()->url . 'assets/images/illustrations/reset-preferences.svg' ) - ->icon( UrlHelper::asset( 'images/illustrations/reset-preferences.svg' ) ) + ->icon( tutor_utils()->is_kids_mode() ? UrlHelper::asset( 'images/illustrations/reset-preference.svg' ) : Icon::BIN ) ->confirm_handler( "handleResetPreferences('" . esc_js( $form_id ) . "','" . esc_js( $reset_modal_id ) . "')" ) ->mutation_state( 'resetPreferencesMutation' ) ->render(); From 78288e6af2a81351f79d869bf275fd80f77d6b9b Mon Sep 17 00:00:00 2001 From: nur-alam Date: Tue, 31 Mar 2026 16:43:11 +0600 Subject: [PATCH 08/15] mend --- assets/images/illustrations/reset-preference.svg | 1 + 1 file changed, 1 insertion(+) create mode 100644 assets/images/illustrations/reset-preference.svg diff --git a/assets/images/illustrations/reset-preference.svg b/assets/images/illustrations/reset-preference.svg new file mode 100644 index 0000000000..60e9921bf6 --- /dev/null +++ b/assets/images/illustrations/reset-preference.svg @@ -0,0 +1 @@ + \ No newline at end of file From 9b37d4af8afa55918078576ab2f7ed4e78172a50 Mon Sep 17 00:00:00 2001 From: nur-alam Date: Wed, 1 Apr 2026 13:39:24 +0600 Subject: [PATCH 09/15] update reset preference modal illustrations --- .../illustrations/kids-reset-preference.svg | 1 + .../images/illustrations/reset-preference.svg | 2 +- classes/UserPreference.php | 30 +++++++++++++++++-- classes/Utils.php | 4 +-- .../account/settings/preferences.php | 14 +++++++-- 5 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 assets/images/illustrations/kids-reset-preference.svg diff --git a/assets/images/illustrations/kids-reset-preference.svg b/assets/images/illustrations/kids-reset-preference.svg new file mode 100644 index 0000000000..5d63fc4d35 --- /dev/null +++ b/assets/images/illustrations/kids-reset-preference.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/illustrations/reset-preference.svg b/assets/images/illustrations/reset-preference.svg index 60e9921bf6..3968d5e1c6 100644 --- a/assets/images/illustrations/reset-preference.svg +++ b/assets/images/illustrations/reset-preference.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/classes/UserPreference.php b/classes/UserPreference.php index a48defbc02..63de1810c0 100644 --- a/classes/UserPreference.php +++ b/classes/UserPreference.php @@ -261,7 +261,13 @@ public function ajax_save_user_preferences() { $auto_play_next = Input::post( 'auto_play_next', false, INPUT::TYPE_BOOL ); $theme = Input::post( 'theme', self::DEFAULT_THEME ); $font_scale = Input::post( 'font_scale', self::DEFAULT_FONT_SCALE, INPUT::TYPE_INT ); - $learning_mood = Input::post( 'learning_mood', false, INPUT::TYPE_BOOL ); + $learning_mood = Input::post( 'learning_mood', Options_V2::LEARNING_MODE_MODERN ); + + // Validate learning_mood against allowed values. + $allowed_moods = array( Options_V2::LEARNING_MODE_MODERN, Options_V2::LEARNING_MODE_KIDS ); + if ( ! in_array( $learning_mood, $allowed_moods, true ) ) { + $learning_mood = Options_V2::LEARNING_MODE_MODERN; + } $preferences_settings = array( 'auto_play_next' => $auto_play_next, @@ -337,7 +343,7 @@ private static function get_default_preferences() { 'auto_play_next' => (bool) tutor_utils()->get_option( 'autoload_next_course_content' ), 'theme' => self::DEFAULT_THEME, 'font_scale' => self::DEFAULT_FONT_SCALE, - 'learning_mood' => Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(), + 'learning_mood' => User::is_student_view() ? tutor_utils()->get_option( 'learning_mode', Options_V2::LEARNING_MODE_MODERN ) : Options_V2::LEARNING_MODE_MODERN, ) ); @@ -368,6 +374,26 @@ public static function get_theme_options() { ); } + /** + * Get learning mood options for UI selects. + * + * @since 4.0.0 + * + * @return array + */ + public static function get_learning_mood_options() { + return array( + array( + 'label' => __( 'Modern', 'tutor' ), + 'value' => Options_V2::LEARNING_MODE_MODERN, + ), + array( + 'label' => __( 'Kids', 'tutor' ), + 'value' => Options_V2::LEARNING_MODE_KIDS, + ), + ); + } + /** * Get font scale options for UI selects. * diff --git a/classes/Utils.php b/classes/Utils.php index 570fab07d7..1eaaf5593f 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -11112,8 +11112,8 @@ public static function get_icon_by_post_type( $post_type ): string { public static function is_kids_mode(): bool { $user_id = get_current_user_id(); if ( $user_id ) { - $user_learning_mood = UserPreference::get('learning_mood'); - return (bool) $user_learning_mood; + $user_learning_mood = UserPreference::get( 'learning_mood', Options_V2::LEARNING_MODE_MODERN ); + return Options_V2::LEARNING_MODE_KIDS === $user_learning_mood; } $admin_kids_mode = Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(); diff --git a/templates/dashboard/account/settings/preferences.php b/templates/dashboard/account/settings/preferences.php index ea93d8a55a..c9bab08c34 100644 --- a/templates/dashboard/account/settings/preferences.php +++ b/templates/dashboard/account/settings/preferences.php @@ -18,9 +18,12 @@ use Tutor\Components\Constants\InputType; use Tutor\Components\Constants\Size; use Tutor\Helpers\UrlHelper; +use Tutor\Options_V2; $theme_options = UserPreference::get_theme_options(); +$learning_mood_options = UserPreference::get_learning_mood_options(); + $font_scale_options = UserPreference::get_font_scale_options(); // Load current user preferences to seed the form. @@ -29,6 +32,8 @@ // Confirmation modal id for resetting user preferences. $reset_modal_id = 'tutor-preferences-reset-modal'; +$saf = tutor_utils()->get_option( 'learning_mode', Options_V2::LEARNING_MODE_MODERN ); + ?>
@@ -55,13 +60,14 @@ class="tutor-flex tutor-flex-column tutor-gap-5"
is_kids_mode() ? UrlHelper::asset( 'images/illustrations/kids-reset-preference.svg' ) : UrlHelper::asset( 'images/illustrations/reset-preference.svg' ); ConfirmationModal::make() ->id( $reset_modal_id ) ->title( __( 'Reset your Preferences?', 'tutor' ) ) ->message( __( 'This will reset your learning preferences to the default settings. Your progress and account data won’t be affected.', 'tutor' ) ) ->cancel_text( __( 'Cancel', 'tutor' ) ) ->confirm_text( __( 'Reset Preferences', 'tutor' ) ) - ->icon( tutor_utils()->is_kids_mode() ? UrlHelper::asset( 'images/illustrations/reset-preference.svg' ) : Icon::BIN ) + ->icon( $reset_modal_illustration ) ->confirm_handler( "handleResetPreferences('" . esc_js( $form_id ) . "','" . esc_js( $reset_modal_id ) . "')" ) ->mutation_state( 'resetPreferencesMutation' ) ->render(); @@ -140,10 +146,14 @@ class="tutor-flex tutor-flex-column tutor-gap-5"
type( InputType::SWITCH ) + ->type( InputType::SELECT ) ->size( Size::SM ) ->name( 'learning_mood' ) + ->options( $learning_mood_options ) + ->value( $user_preferences['learning_mood'] ?? Options_V2::LEARNING_MODE_MODERN ) + ->placeholder( __( 'Select mode...', 'tutor' ) ) ->attr( 'x-bind', "register('learning_mood')" ) + ->attr( 'style', 'min-width: 140px;' ) ->render(); ?>
From d9b3a4223bf7c00002d5f7ddb5c17070c7032bdf Mon Sep 17 00:00:00 2001 From: nur-alam Date: Wed, 1 Apr 2026 15:49:32 +0600 Subject: [PATCH 10/15] refactor: simplify learning mode preference retrieval and update placeholder text --- classes/UserPreference.php | 2 +- templates/dashboard/account/settings/preferences.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/UserPreference.php b/classes/UserPreference.php index 63de1810c0..545a7e965b 100644 --- a/classes/UserPreference.php +++ b/classes/UserPreference.php @@ -343,7 +343,7 @@ private static function get_default_preferences() { 'auto_play_next' => (bool) tutor_utils()->get_option( 'autoload_next_course_content' ), 'theme' => self::DEFAULT_THEME, 'font_scale' => self::DEFAULT_FONT_SCALE, - 'learning_mood' => User::is_student_view() ? tutor_utils()->get_option( 'learning_mode', Options_V2::LEARNING_MODE_MODERN ) : Options_V2::LEARNING_MODE_MODERN, + 'learning_mood' => tutor_utils()->get_option( 'learning_mode', Options_V2::LEARNING_MODE_MODERN ), ) ); diff --git a/templates/dashboard/account/settings/preferences.php b/templates/dashboard/account/settings/preferences.php index c9bab08c34..9a6e35248f 100644 --- a/templates/dashboard/account/settings/preferences.php +++ b/templates/dashboard/account/settings/preferences.php @@ -151,7 +151,7 @@ class="tutor-flex tutor-flex-column tutor-gap-5" ->name( 'learning_mood' ) ->options( $learning_mood_options ) ->value( $user_preferences['learning_mood'] ?? Options_V2::LEARNING_MODE_MODERN ) - ->placeholder( __( 'Select mode...', 'tutor' ) ) + ->placeholder( __( 'Select mode', 'tutor' ) ) ->attr( 'x-bind', "register('learning_mood')" ) ->attr( 'style', 'min-width: 140px;' ) ->render(); From 6df6512ee7c2115eb8dba15742b829bcb3e6fb70 Mon Sep 17 00:00:00 2001 From: nur-alam Date: Thu, 2 Apr 2026 12:02:18 +0600 Subject: [PATCH 11/15] refactor: restrict learning mood setting visibility to student view and clean up preference template UI --- classes/Utils.php | 2 +- templates/dashboard/account/settings/preferences.php | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/classes/Utils.php b/classes/Utils.php index 59d961031c..aa5233a5d3 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -11121,7 +11121,7 @@ public static function is_kids_mode(): bool { $user_id = get_current_user_id(); if ( $user_id ) { $user_learning_mood = UserPreference::get( 'learning_mood', Options_V2::LEARNING_MODE_MODERN ); - return Options_V2::LEARNING_MODE_KIDS === $user_learning_mood; + return Options_V2::LEARNING_MODE_KIDS === $user_learning_mood && User::is_student_view(); } $admin_kids_mode = Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(); diff --git a/templates/dashboard/account/settings/preferences.php b/templates/dashboard/account/settings/preferences.php index 9a6e35248f..a62acbe758 100644 --- a/templates/dashboard/account/settings/preferences.php +++ b/templates/dashboard/account/settings/preferences.php @@ -19,6 +19,7 @@ use Tutor\Components\Constants\Size; use Tutor\Helpers\UrlHelper; use Tutor\Options_V2; +use TUTOR\User; $theme_options = UserPreference::get_theme_options(); @@ -32,8 +33,6 @@ // Confirmation modal id for resetting user preferences. $reset_modal_id = 'tutor-preferences-reset-modal'; -$saf = tutor_utils()->get_option( 'learning_mode', Options_V2::LEARNING_MODE_MODERN ); - ?>
@@ -56,7 +55,7 @@ class="tutor-flex tutor-flex-column tutor-gap-5"
name( Icon::RELOAD_3 )->size( 16 )->render(); ?> - +
+
@@ -145,7 +145,7 @@ class="tutor-flex tutor-flex-column tutor-gap-5"
type( InputType::SELECT ) ->size( Size::SM ) ->name( 'learning_mood' ) @@ -158,6 +158,7 @@ class="tutor-flex tutor-flex-column tutor-gap-5" ?>
+
From 3e6b2e374a49fb883a076ce3e1decbba6da31d3e Mon Sep 17 00:00:00 2001 From: nur-alam Date: Thu, 2 Apr 2026 20:55:18 +0600 Subject: [PATCH 12/15] refactor: simplify admin kids mode check by removing redundant variable --- classes/Utils.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/classes/Utils.php b/classes/Utils.php index 8f277b7f8f..714744cc1c 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -11139,7 +11139,6 @@ public static function is_kids_mode(): bool { return Options_V2::LEARNING_MODE_KIDS === $user_learning_mood && User::is_student_view(); } - $admin_kids_mode = Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(); - return $admin_kids_mode; + return Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(); } } From 54257d7fd511929796cbdbe60c8ccf2d0a411432 Mon Sep 17 00:00:00 2001 From: nur-alam Date: Fri, 3 Apr 2026 13:02:48 +0600 Subject: [PATCH 13/15] fix: correct kids mode detection and user preference handling Fix logic in is_kids_mode method to properly check student view before user ID Change method from static to instance to align with usage Refactor user preference saving to only store non-default values and avoid unnecessary updates --- classes/UserPreference.php | 63 ++++++++++++++++++++++++++++---------- classes/Utils.php | 8 ++--- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/classes/UserPreference.php b/classes/UserPreference.php index 545a7e965b..d92f3ee5fd 100644 --- a/classes/UserPreference.php +++ b/classes/UserPreference.php @@ -228,10 +228,15 @@ public function save_preferences( array $prefs, $user_id = 0 ) { return false; } - $current_preferences = $this->get_preferences( $user_id ); - $preferences = array_merge( $current_preferences, $prefs ); + // Get from database. + $current_preferences = get_user_meta( $user_id, self::META_KEY, true ); + if ( ! is_array( $current_preferences ) ) { + $current_preferences = array(); + } - $preferences = apply_filters( 'tutor_user_preference_data', $preferences, $user_id ); + $combined_preferences = array_merge( $current_preferences, $prefs ); + + $preferences = apply_filters( 'tutor_user_preference_data', $combined_preferences, $user_id ); update_user_meta( $user_id, self::META_KEY, $preferences ); @@ -258,23 +263,47 @@ public function ajax_save_user_preferences() { ); } - $auto_play_next = Input::post( 'auto_play_next', false, INPUT::TYPE_BOOL ); - $theme = Input::post( 'theme', self::DEFAULT_THEME ); - $font_scale = Input::post( 'font_scale', self::DEFAULT_FONT_SCALE, INPUT::TYPE_INT ); - $learning_mood = Input::post( 'learning_mood', Options_V2::LEARNING_MODE_MODERN ); + $auto_play_next = Input::post( 'auto_play_next', null ); + $theme = Input::post( 'theme', null ); + $font_scale = Input::post( 'font_scale', null ); + $learning_mood = Input::post( 'learning_mood', null ); + + $preferences_settings = array(); - // Validate learning_mood against allowed values. - $allowed_moods = array( Options_V2::LEARNING_MODE_MODERN, Options_V2::LEARNING_MODE_KIDS ); - if ( ! in_array( $learning_mood, $allowed_moods, true ) ) { - $learning_mood = Options_V2::LEARNING_MODE_MODERN; + if ( null !== $auto_play_next ) { + $default_auto_play_next = (bool) tutor_utils()->get_option( 'autoload_next_course_content' ); + if ( (bool) $auto_play_next !== $default_auto_play_next ) { + $preferences_settings['auto_play_next'] = (bool) $auto_play_next; + } } - $preferences_settings = array( - 'auto_play_next' => $auto_play_next, - 'theme' => $theme, - 'font_scale' => $font_scale, - 'learning_mood' => $learning_mood, - ); + if ( null !== $theme ) { + $preferences_settings['theme'] = $theme; + } + + if ( null !== $font_scale ) { + $preferences_settings['font_scale'] = (int) $font_scale; + } + + if ( null !== $learning_mood ) { + // Validate learning_mood against allowed values. + $allowed_moods = array( Options_V2::LEARNING_MODE_MODERN, Options_V2::LEARNING_MODE_KIDS ); + if ( ! in_array( $learning_mood, $allowed_moods, true ) ) { + $learning_mood = Options_V2::LEARNING_MODE_MODERN; + } + $default_learning_mood = tutor_utils()->get_option( 'learning_mode', Options_V2::LEARNING_MODE_MODERN ); + if ( $learning_mood !== $default_learning_mood ) { + $preferences_settings['learning_mood'] = $learning_mood; + } + } + + if ( empty( $preferences_settings ) ) { + $this->json_response( + __( 'No changes detected', 'tutor' ), + null, + HttpHelper::STATUS_OK + ); + } $preference_data = $this->save_preferences( $preferences_settings, get_current_user_id() ); diff --git a/classes/Utils.php b/classes/Utils.php index c871ec5a15..6aeec68e39 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -11126,17 +11126,17 @@ public static function get_icon_by_post_type( $post_type ): string { } /** - * Is kids mode active? + * Is kids mode active * * @since 4.0.0 * * @return bool */ - public static function is_kids_mode(): bool { + public function is_kids_mode(): bool { $user_id = get_current_user_id(); - if ( $user_id ) { + if ( User::is_student_view() && $user_id ) { $user_learning_mood = UserPreference::get( 'learning_mood', Options_V2::LEARNING_MODE_MODERN ); - return Options_V2::LEARNING_MODE_KIDS === $user_learning_mood && User::is_student_view(); + return Options_V2::LEARNING_MODE_KIDS === $user_learning_mood; } return Options_V2::LEARNING_MODE_KIDS === tutor_utils()->get_option( 'learning_mode' ) && User::is_student_view(); From a9574e574c5b8a9fa50165323f94de4403da2901 Mon Sep 17 00:00:00 2001 From: nur-alam Date: Fri, 3 Apr 2026 15:26:50 +0600 Subject: [PATCH 14/15] fix: prevent undefined variable warning in user preference handling Reorder condition to check user ID before calling User::is_student_view() to avoid potential undefined variable warning. Simplify user preference validation by removing redundant is_user_logged_in() checks since get_current_user_id() already handles authentication. Add type casting for auto_play_next input to ensure boolean comparison works correctly. --- classes/UserPreference.php | 23 ++++------------------- classes/Utils.php | 2 +- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/classes/UserPreference.php b/classes/UserPreference.php index d92f3ee5fd..361a029f1b 100644 --- a/classes/UserPreference.php +++ b/classes/UserPreference.php @@ -255,15 +255,7 @@ public function save_preferences( array $prefs, $user_id = 0 ) { public function ajax_save_user_preferences() { tutor_utils()->check_nonce(); - if ( ! is_user_logged_in() ) { - $this->json_response( - tutor_utils()->error_message( 'forbidden' ), - null, - HttpHelper::STATUS_UNAUTHORIZED - ); - } - - $auto_play_next = Input::post( 'auto_play_next', null ); + $auto_play_next = Input::post( 'auto_play_next', null, 'boolean' ); $theme = Input::post( 'theme', null ); $font_scale = Input::post( 'font_scale', null ); $learning_mood = Input::post( 'learning_mood', null ); @@ -272,8 +264,9 @@ public function ajax_save_user_preferences() { if ( null !== $auto_play_next ) { $default_auto_play_next = (bool) tutor_utils()->get_option( 'autoload_next_course_content' ); - if ( (bool) $auto_play_next !== $default_auto_play_next ) { - $preferences_settings['auto_play_next'] = (bool) $auto_play_next; + $auto_play_next = 'true' === $auto_play_next ? true : false; + if ( $auto_play_next !== $default_auto_play_next ) { + $preferences_settings['auto_play_next'] = $auto_play_next; } } @@ -331,14 +324,6 @@ public function ajax_save_user_preferences() { public function ajax_reset_user_preferences() { tutor_utils()->check_nonce(); - if ( ! is_user_logged_in() ) { - $this->json_response( - tutor_utils()->error_message( 'forbidden' ), - null, - HttpHelper::STATUS_UNAUTHORIZED - ); - } - $user_id = get_current_user_id(); if ( ! $user_id ) { $this->json_response( diff --git a/classes/Utils.php b/classes/Utils.php index 2a1d4f5fc3..c98c3ba911 100644 --- a/classes/Utils.php +++ b/classes/Utils.php @@ -11134,7 +11134,7 @@ public static function get_icon_by_post_type( $post_type ): string { */ public function is_kids_mode(): bool { $user_id = get_current_user_id(); - if ( User::is_student_view() && $user_id ) { + if ( $user_id && User::is_student_view() ) { $user_learning_mood = UserPreference::get( 'learning_mood', Options_V2::LEARNING_MODE_MODERN ); return Options_V2::LEARNING_MODE_KIDS === $user_learning_mood; } From fc1c67f5621c4150e734b394112967b82424f17a Mon Sep 17 00:00:00 2001 From: nur-alam Date: Fri, 3 Apr 2026 15:31:33 +0600 Subject: [PATCH 15/15] fix: remove boolean type cast from auto_play_next preference --- classes/UserPreference.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/UserPreference.php b/classes/UserPreference.php index 361a029f1b..fda8096933 100644 --- a/classes/UserPreference.php +++ b/classes/UserPreference.php @@ -255,7 +255,7 @@ public function save_preferences( array $prefs, $user_id = 0 ) { public function ajax_save_user_preferences() { tutor_utils()->check_nonce(); - $auto_play_next = Input::post( 'auto_play_next', null, 'boolean' ); + $auto_play_next = Input::post( 'auto_play_next', null ); $theme = Input::post( 'theme', null ); $font_scale = Input::post( 'font_scale', null ); $learning_mood = Input::post( 'learning_mood', null );