From 537c94cbd985414d5c24ade3afadddbda6472b97 Mon Sep 17 00:00:00 2001 From: Jon Stovell Date: Sun, 9 Feb 2025 00:09:52 -0700 Subject: [PATCH] Fixes logic order regarding theme initialization Signed-off-by: Jon Stovell --- Sources/Actions/Profile/Main.php | 3 +- Sources/Forum.php | 83 +++++++----- Sources/Theme.php | 224 ++++++++++++++++--------------- 3 files changed, 163 insertions(+), 147 deletions(-) diff --git a/Sources/Actions/Profile/Main.php b/Sources/Actions/Profile/Main.php index 6a95afcbc3..bdb75445a3 100644 --- a/Sources/Actions/Profile/Main.php +++ b/Sources/Actions/Profile/Main.php @@ -577,6 +577,7 @@ public function execute(): void Utils::$context['profile_updated'] = Lang::$txt['profile_updated_own']; } + $this->setProfileAreas(); $menu = $this->createMenu(); $this->securityChecks(); @@ -847,8 +848,6 @@ protected function __construct() Utils::$context['subs_available'] = !empty($num_subs); } - - $this->setProfileAreas(); } /** diff --git a/Sources/Forum.php b/Sources/Forum.php index ca2bbb60db..285c25e30f 100644 --- a/Sources/Forum.php +++ b/Sources/Forum.php @@ -446,6 +446,7 @@ public function __construct() public function execute(): void { $this->init(); + $requested_action = $_REQUEST['action'] ?? null; $current_action = $this->findAction($requested_action); @@ -457,33 +458,7 @@ public function execute(): void IntegrationHook::call('integrate_init_action', [$action]); } - $this->main(); - - // Is the forum in maintenance mode? (doesn't apply to administrators.) - if ( - !empty(Config::$maintenance) - && !User::$me->allowedTo('admin_forum') - && self::$current_action?->canShowInMaintenanceMode() === false - ) { - // Don't even try it, sonny. - self::inMaintenance(); - } - - // If guest access is off, a guest can only do one of a few actions. - if ( - empty(Config::$modSettings['allow_guestAccess']) - && User::$me->is_guest - && ( - self::$current_action?->isRestrictedGuestAccessAllowed() === false - || ( - !isset($_REQUEST['action']) - || !in_array($_REQUEST['action'] ?? '', self::$guest_access_actions) - && self::$current_action?->isRestrictedGuestAccessAllowed() === null - ) - ) - ) { - User::$me->kickIfGuest(null, false); - } + $this->preflight(); if (isset($action)) { $action->execute(); @@ -605,7 +580,7 @@ protected function init(): void } // Load the current theme. (note that ?theme=1 will also work, may be used for guest theming.) else { - Theme::load(); + Theme::load(0, false); } // Check if the user should be disallowed access. @@ -613,23 +588,36 @@ protected function init(): void } /** - * The main forum loader. - * - * This method handles the main forum logic, such as checking permissions, - * logging user activity, and tracking forum statistics. + * Runs various checks that are required before calling the action. */ - protected function main(): void + protected function preflight(): void { + Theme::$current->initialize(); + // If the user needs to accept the agreement or privacy policy, redirect now. $this->requireAgreement(); // If we are in a topic and don't have permission to approve it then duck out now. - if (!empty(Topic::$topic_id) && empty(Board::$info->cur_topic_approved) && !User::$me->allowedTo('approve_posts') && (User::$me->id != Board::$info->cur_topic_starter || User::$me->is_guest)) { + if ( + !empty(Topic::$topic_id) + && empty(Board::$info->cur_topic_approved) + && !User::$me->allowedTo('approve_posts') + && ( + User::$me->id != Board::$info->cur_topic_starter + || User::$me->is_guest + ) + ) { ErrorHandler::fatalLang('not_a_topic', false); } // Don't log if this is an attachment, avatar, toggle of editor buttons, theme option, XML feed, popup, etc. - if (self::$current_action?->canBeLogged() === true || (self::$current_action === null && !QueryString::isFilteredRequest(self::$unlogged_actions, 'action'))) { + if ( + self::$current_action?->canBeLogged() === true + || ( + self::$current_action === null + && !QueryString::isFilteredRequest(self::$unlogged_actions, 'action') + ) + ) { // Log this user as online. User::$me->logOnline(); @@ -641,6 +629,31 @@ protected function main(): void // Make sure that our scheduled tasks have been running as intended. Config::checkCron(); + + // Is the forum in maintenance mode? (doesn't apply to administrators.) + if ( + !empty(Config::$maintenance) + && !User::$me->allowedTo('admin_forum') + && self::$current_action?->canShowInMaintenanceMode() === false + ) { + // Don't even try it, sonny. + self::inMaintenance(); + } + + // If guest access is off, a guest can only do one of a few actions. + if ( + empty(Config::$modSettings['allow_guestAccess']) + && User::$me->is_guest + && ( + self::$current_action?->isRestrictedGuestAccessAllowed() !== true + && ( + !isset($_REQUEST['action']) + || !in_array($_REQUEST['action'], self::$guest_access_actions) + ) + ) + ) { + User::$me->kickIfGuest(null, false); + } } /** diff --git a/Sources/Theme.php b/Sources/Theme.php index 2a9dfa37ff..c3a446ed61 100644 --- a/Sources/Theme.php +++ b/Sources/Theme.php @@ -140,6 +140,120 @@ class Theme 'name', ]; + /**************** + * Public methods + ****************/ + + /** + * Sets a bunch of Utils::$context variables, loads templates and language + * files, and does other stuff that is required to use the theme for output. + */ + public function initialize(): void + { + $this->fixUrl(); + + // Create User::$me if it is missing (e.g., an error very early in the login process). + if (!isset(User::$me)) { + User::load(); + } + + $this->fixSmileySet(); + + // Some basic information... + if (!isset(Utils::$context['html_headers'])) { + Utils::$context['html_headers'] = ''; + } + + if (!isset(Utils::$context['javascript_files'])) { + Utils::$context['javascript_files'] = []; + } + + if (!isset(Utils::$context['css_files'])) { + Utils::$context['css_files'] = []; + } + + if (!isset(Utils::$context['css_header'])) { + Utils::$context['css_header'] = []; + } + + if (!isset(Utils::$context['javascript_inline'])) { + Utils::$context['javascript_inline'] = ['standard' => [], 'defer' => []]; + } + + if (!isset(Utils::$context['javascript_vars'])) { + Utils::$context['javascript_vars'] = []; + } + + Utils::$context['login_url'] = Config::$scripturl . '?action=login2'; + Utils::$context['menu_separator'] = !empty($this->settings['use_image_buttons']) ? ' ' : ' | '; + Utils::$context['session_var'] = $_SESSION['session_var']; + Utils::$context['session_id'] = $_SESSION['session_value']; + Utils::$context['forum_name'] = Config::$mbname; + Utils::$context['forum_name_html_safe'] = Utils::htmlspecialchars(Utils::$context['forum_name']); + Utils::$context['header_logo_url_html_safe'] = empty($this->settings['header_logo_url']) ? '' : Utils::htmlspecialchars($this->settings['header_logo_url']); + Utils::$context['current_action'] = isset($_REQUEST['action']) ? Utils::htmlspecialchars($_REQUEST['action']) : null; + Utils::$context['current_subaction'] = $_REQUEST['sa'] ?? null; + Utils::$context['can_register'] = empty(Config::$modSettings['registration_method']) || Config::$modSettings['registration_method'] != 3; + + if (isset(Config::$modSettings['load_average'])) { + Utils::$context['load_average'] = Config::$modSettings['load_average']; + } + + // Detect the browser. This is separated out because it's also used in attachment downloads + BrowserDetector::call(); + + $this->loadTemplatesAndLangFiles(); + + // Allow overriding the forum's default time/number formats. + if (empty(User::$profiles[User::$me->id]['time_format']) && !empty(Lang::$txt['time_format'])) { + User::$me->time_format = Lang::$txt['time_format']; + } + + // Set the character set from the template. + Utils::$context['character_set'] = empty(Config::$modSettings['global_character_set']) ? Lang::$txt['lang_character_set'] : Config::$modSettings['global_character_set']; + Utils::$context['right_to_left'] = !empty(Lang::$txt['lang_rtl']); + + // Guests may still need a name. + if (User::$me->is_guest && empty(User::$me->name)) { + User::$me->name = Lang::$txt['guest_title']; + } + + // Any theme-related strings that need to be loaded? + Lang::load('ThemeStrings', '', false); + + // Make a special URL for the language. + $this->settings['lang_images_url'] = $this->settings['images_url'] . '/' . (!empty(Lang::$txt['image_lang']) ? Lang::$txt['image_lang'] : User::$me->language); + + $this->loadCss(); + + $this->loadVariant(); + + Utils::$context['tabindex'] = 1; + + $this->loadJavaScript(); + + $this->setupLinktree(); + + // Any files to include at this point? + if (!empty(Config::$modSettings['integrate_theme_include'])) { + $theme_includes = explode(',', Config::$modSettings['integrate_theme_include']); + + foreach ($theme_includes as $include) { + $include = strtr(trim($include), ['$boarddir' => Config::$boarddir, '$sourcedir' => Config::$sourcedir, '$themedir' => $this->settings['theme_dir']]); + + if (file_exists($include)) { + require_once $include; + } + } + } + + // Call load theme integration functions. + IntegrationHook::call('integrate_load_theme'); + + // We are ready to go. + Utils::$context['theme_loaded'] = true; + } + /*********************** * Public static methods ***********************/ @@ -1881,116 +1995,6 @@ protected function __construct(int $id = 0, int $member = -1) } } - /** - * Sets a bunch of Utils::$context variables, loads templates and language - * files, and does other stuff that is required to use the theme for output. - */ - protected function initialize(): void - { - $this->fixUrl(); - - // Create User::$me if it is missing (e.g., an error very early in the login process). - if (!isset(User::$me)) { - User::load(); - } - - $this->fixSmileySet(); - - // Some basic information... - if (!isset(Utils::$context['html_headers'])) { - Utils::$context['html_headers'] = ''; - } - - if (!isset(Utils::$context['javascript_files'])) { - Utils::$context['javascript_files'] = []; - } - - if (!isset(Utils::$context['css_files'])) { - Utils::$context['css_files'] = []; - } - - if (!isset(Utils::$context['css_header'])) { - Utils::$context['css_header'] = []; - } - - if (!isset(Utils::$context['javascript_inline'])) { - Utils::$context['javascript_inline'] = ['standard' => [], 'defer' => []]; - } - - if (!isset(Utils::$context['javascript_vars'])) { - Utils::$context['javascript_vars'] = []; - } - - Utils::$context['login_url'] = Config::$scripturl . '?action=login2'; - Utils::$context['menu_separator'] = !empty($this->settings['use_image_buttons']) ? ' ' : ' | '; - Utils::$context['session_var'] = $_SESSION['session_var']; - Utils::$context['session_id'] = $_SESSION['session_value']; - Utils::$context['forum_name'] = Config::$mbname; - Utils::$context['forum_name_html_safe'] = Utils::htmlspecialchars(Utils::$context['forum_name']); - Utils::$context['header_logo_url_html_safe'] = empty($this->settings['header_logo_url']) ? '' : Utils::htmlspecialchars($this->settings['header_logo_url']); - Utils::$context['current_action'] = isset($_REQUEST['action']) ? Utils::htmlspecialchars($_REQUEST['action']) : null; - Utils::$context['current_subaction'] = $_REQUEST['sa'] ?? null; - Utils::$context['can_register'] = empty(Config::$modSettings['registration_method']) || Config::$modSettings['registration_method'] != 3; - - if (isset(Config::$modSettings['load_average'])) { - Utils::$context['load_average'] = Config::$modSettings['load_average']; - } - - // Detect the browser. This is separated out because it's also used in attachment downloads - BrowserDetector::call(); - - $this->loadTemplatesAndLangFiles(); - - // Allow overriding the forum's default time/number formats. - if (empty(User::$profiles[User::$me->id]['time_format']) && !empty(Lang::$txt['time_format'])) { - User::$me->time_format = Lang::$txt['time_format']; - } - - // Set the character set from the template. - Utils::$context['character_set'] = empty(Config::$modSettings['global_character_set']) ? Lang::$txt['lang_character_set'] : Config::$modSettings['global_character_set']; - Utils::$context['right_to_left'] = !empty(Lang::$txt['lang_rtl']); - - // Guests may still need a name. - if (User::$me->is_guest && empty(User::$me->name)) { - User::$me->name = Lang::$txt['guest_title']; - } - - // Any theme-related strings that need to be loaded? - Lang::load('ThemeStrings', '', false); - - // Make a special URL for the language. - $this->settings['lang_images_url'] = $this->settings['images_url'] . '/' . (!empty(Lang::$txt['image_lang']) ? Lang::$txt['image_lang'] : User::$me->language); - - $this->loadCss(); - - $this->loadVariant(); - - Utils::$context['tabindex'] = 1; - - $this->loadJavaScript(); - - $this->setupLinktree(); - - // Any files to include at this point? - if (!empty(Config::$modSettings['integrate_theme_include'])) { - $theme_includes = explode(',', Config::$modSettings['integrate_theme_include']); - - foreach ($theme_includes as $include) { - $include = strtr(trim($include), ['$boarddir' => Config::$boarddir, '$sourcedir' => Config::$sourcedir, '$themedir' => $this->settings['theme_dir']]); - - if (file_exists($include)) { - require_once $include; - } - } - } - - // Call load theme integration functions. - IntegrationHook::call('integrate_load_theme'); - - // We are ready to go. - Utils::$context['theme_loaded'] = true; - } - /** * If the user got here using an unexpected URL, fix it. */