diff --git a/Sources/Profile.php b/Sources/Profile.php index 395a97ff9c..0f42735b0a 100644 --- a/Sources/Profile.php +++ b/Sources/Profile.php @@ -1140,28 +1140,37 @@ public function loadCustomFields(string $area = 'summary'): void } /** - * Loads the theme options for the member. + * Populates Utils::$context['member']['options'] with this member's theme + * options. * - * @param bool $defaultSettings If true, we are loading default options. + * @param ?bool $default_only If true, only load options for the default + * theme, where "default theme" means whichever theme is used for guests. + * Default: false. */ - public function loadThemeOptions(bool $defaultSettings = false) + public function loadThemeOptions(bool $default_only = false) { - if (isset($_POST['default_options'])) { - $_POST['options'] = isset($_POST['options']) ? $_POST['options'] + $_POST['default_options'] : $_POST['default_options']; + // Get this member's current theme options. + if ($default_only && $this->theme != (Config::$modSettings['theme_guests'] ?? 1)) { + $temp = $this->data['options'] ?? []; + parent::loadOptions($this->id, $default_only); + Utils::$context['member']['options'] = $this->data['options']; + $this->data['options'] = $temp; + } else { + Utils::$context['member']['options'] = $this->data['options'] ?? []; } - Utils::$context['member']['options'] = $this->data['options'] ?? []; + // Overwrite their current options with anything that is being set to a + // new value. + $_POST['options'] = ($_POST['options'] ?? []) + ($_POST['default_options'] ?? []); - if (isset($_POST['options']) && \is_array($_POST['options'])) { - foreach ($_POST['options'] as $k => $v) { - Utils::$context['member']['options'][$k] = $v; - } + foreach ($_POST['options'] as $k => $v) { + Utils::$context['member']['options'][$k] = $v; } - // Load up the default theme options for any missing. - parent::loadOptions(-1); + // If any theme options are still missing, set them to default values. + parent::loadOptions(-1, $default_only); - foreach (parent::$profiles[-1]['options'] as $k => $v) { + foreach (parent::$profiles[-1]['options'] ?? [] as $k => $v) { if (!isset(Utils::$context['member']['options'][$k])) { Utils::$context['member']['options'][$k] = $v; } diff --git a/Sources/User.php b/Sources/User.php index 05022b005b..e677bfd0e0 100644 --- a/Sources/User.php +++ b/Sources/User.php @@ -4774,23 +4774,52 @@ protected static function loadUserData(array $users, int $type = self::LOAD_BY_I * Loads theme options for the given users. * * @param array|int $ids One or more user ID numbers. + * @param ?bool $default_only If true, only load options for the default + * theme, where "default theme" means whichever theme is used for guests. + * Default: false. */ - protected static function loadOptions(array|int $ids): void + protected static function loadOptions(array|int $ids, bool $default_only = false): void { $ids = (array) $ids; $request = Db::$db->query( 'SELECT id_member, id_theme, variable, value FROM {db_prefix}themes - WHERE id_member IN ({array_int:ids})', + WHERE id_member IN ({array_int:ids}) + ORDER BY id_theme', [ 'ids' => $ids, ], ); while ($row = Db::$db->fetch_assoc($request)) { - self::$profiles[$row['id_member']]['options'][$row['variable']] = $row['value']; + // Which theme is used for guests? + $guest_theme = (int) (Config::$modSettings['theme_guests'] ?? 1); + + // Which theme is this member using? + $user_theme = $default_only ? $guest_theme : (int) (self::$profiles[$row['id_member']]['id_theme'] ?? $guest_theme); + + if ( + // Rows are returned in ascending order by id_theme, so we start + // with theme 1's value and then overwrite as needed. + $row['id_theme'] == 1 + // If the guest theme isn't theme 1, then overwrite the value + // from theme 1 with the value from the guest theme. + || ( + $row['id_theme'] == $guest_theme + // Special check needed here to ensure the guest theme does + // not overwrite the user's preferred theme. For example, if + // the guest theme is 5 but the user's theme is 2, then we + // want to keep the value from theme 2. + && $guest_theme < $user_theme + ) + // The value from the user's preferred theme takes precedence. + || $row['id_theme'] == $user_theme + ) { + self::$profiles[$row['id_member']]['options'][$row['variable']] = $row['value']; + } } + Db::$db->free_result($request); }