]> git.mxchange.org Git - friendica.git/commitdiff
Create AppHelper interface and AppLegacy class
authorArt4 <art4@wlabs.de>
Sun, 17 Nov 2024 20:06:34 +0000 (20:06 +0000)
committerArt4 <art4@wlabs.de>
Sun, 17 Nov 2024 20:06:34 +0000 (20:06 +0000)
src/App.php
src/AppHelper.php [new file with mode: 0644]
src/AppLegacy.php [new file with mode: 0644]
src/DI.php

index e302c8515412465141725c57b9540734223df75b..46639f8939497cf9616be667565e9e9b636b7edd 100644 (file)
@@ -10,7 +10,10 @@ namespace Friendica;
 use Exception;
 use Friendica\App\Arguments;
 use Friendica\App\BaseURL;
+use Friendica\App\Mode;
+use Friendica\App\Page;
 use Friendica\App\Request;
+use Friendica\App\Router;
 use Friendica\Capabilities\ICanCreateResponses;
 use Friendica\Content\Nav;
 use Friendica\Core\Config\Factory\Config;
@@ -18,14 +21,13 @@ use Friendica\Core\Session\Capability\IHandleUserSessions;
 use Friendica\Database\Definition\DbaDefinition;
 use Friendica\Database\Definition\ViewDefinition;
 use Friendica\Module\Maintenance;
+use Friendica\Network\HTTPException\InternalServerErrorException;
 use Friendica\Security\Authentication;
 use Friendica\Core\Config\ValueObject\Cache;
 use Friendica\Core\Config\Capability\IManageConfigValues;
 use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
 use Friendica\Core\L10n;
 use Friendica\Core\System;
-use Friendica\Core\Theme;
-use Friendica\Database\Database;
 use Friendica\Module\Special\HTTPException as ModuleHTTPException;
 use Friendica\Network\HTTPException;
 use Friendica\Protocol\ATProtocol\DID;
@@ -34,7 +36,6 @@ use Friendica\Util\DateTimeFormat;
 use Friendica\Util\HTTPInputData;
 use Friendica\Util\HTTPSignature;
 use Friendica\Util\Profiler;
-use Friendica\Util\Strings;
 use Psr\Log\LoggerInterface;
 
 /**
@@ -47,26 +48,14 @@ use Psr\Log\LoggerInterface;
  * before we spit the page out.
  *
  */
-class App
+class App implements AppHelper
 {
        const PLATFORM = 'Friendica';
        const CODENAME = 'Yellow Archangel';
        const VERSION  = '2024.12-dev';
 
-       // Allow themes to control internal parameters
-       // by changing App values in theme.php
-       private $theme_info = [
-               'videowidth'        => 425,
-               'videoheight'       => 350,
-       ];
-
-       private $timezone      = '';
-       private $profile_owner = 0;
-       private $contact_id    = 0;
-       private $queue         = [];
-
        /**
-        * @var App\Mode The Mode of the Application
+        * @var Mode The Mode of the Application
         */
        private $mode;
 
@@ -75,11 +64,6 @@ class App
         */
        private $baseURL;
 
-       /** @var string The name of the current theme */
-       private $currentTheme;
-       /** @var string The name of the current mobile theme */
-       private $currentMobileTheme;
-
        /** @var string */
        private $requestId;
 
@@ -101,11 +85,6 @@ class App
         */
        private $profiler;
 
-       /**
-        * @var Database The Friendica database connection
-        */
-       private $database;
-
        /**
         * @var L10n The translator
         */
@@ -116,177 +95,202 @@ class App
         */
        private $args;
 
-       /**
-        * @var IManagePersonalConfigValues
-        */
-       private $pConfig;
-
        /**
         * @var IHandleUserSessions
         */
        private $session;
 
+       /**
+        * @var AppHelper $appHelper
+        */
+       private $appHelper;
+
+       public function __construct(
+               Request $request,
+               Authentication $auth,
+               IManageConfigValues $config,
+               Mode $mode,
+               BaseURL $baseURL,
+               LoggerInterface $logger,
+               Profiler $profiler,
+               L10n $l10n,
+               Arguments $args,
+               IHandleUserSessions $session,
+               DbaDefinition $dbaDefinition,
+               ViewDefinition $viewDefinition
+       ) {
+               $this->requestId = $request->getRequestId();
+               $this->auth      = $auth;
+               $this->config    = $config;
+               $this->mode      = $mode;
+               $this->baseURL   = $baseURL;
+               $this->profiler  = $profiler;
+               $this->logger    = $logger;
+               $this->l10n      = $l10n;
+               $this->args      = $args;
+               $this->session   = $session;
+               $this->appHelper = DI::appHelper();
+
+               $this->load($dbaDefinition, $viewDefinition);
+       }
+
        /**
         * Set the profile owner ID
         *
+        * @deprecated 2024.12 Use AppHelper::setProfileOwner() instead
+        *
         * @param int $owner_id
         * @return void
         */
        public function setProfileOwner(int $owner_id)
        {
-               $this->profile_owner = $owner_id;
+               $this->appHelper->setProfileOwner($owner_id);
        }
 
        /**
         * Get the profile owner ID
         *
+        * @deprecated 2024.12 Use AppHelper::getProfileOwner() instead
+        *
         * @return int
         */
        public function getProfileOwner(): int
        {
-               return $this->profile_owner;
+               return $this->appHelper->getProfileOwner();
        }
 
        /**
         * Set the contact ID
         *
+        * @deprecated 2024.12 Use AppHelper::setContactId() instead
+        *
         * @param int $contact_id
         * @return void
         */
        public function setContactId(int $contact_id)
        {
-               $this->contact_id = $contact_id;
+               $this->appHelper->setContactId($contact_id);
        }
 
        /**
         * Get the contact ID
         *
+        * @deprecated 2024.12 Use AppHelper::getContactId() instead
+        *
         * @return int
         */
        public function getContactId(): int
        {
-               return $this->contact_id;
+               return $this->appHelper->getContactId();
        }
 
        /**
         * Set the timezone
         *
+        * @deprecated 2024.12 Use AppHelper::setTimeZone() instead
+        *
         * @param string $timezone A valid time zone identifier, see https://www.php.net/manual/en/timezones.php
         * @return void
         */
        public function setTimeZone(string $timezone)
        {
-               $this->timezone = (new \DateTimeZone($timezone))->getName();
-               DateTimeFormat::setLocalTimeZone($this->timezone);
+               $this->appHelper->setTimeZone($timezone);
        }
 
        /**
         * Get the timezone
         *
-        * @return int
+        * @deprecated 2024.12 Use AppHelper::getTimeZone() instead
         */
        public function getTimeZone(): string
        {
-               return $this->timezone;
+               return $this->appHelper->getTimeZone();
        }
 
        /**
         * Set workerqueue information
         *
+        * @deprecated 2024.12 Use AppHelper::setQueue() instead
+        *
         * @param array $queue
         * @return void
         */
        public function setQueue(array $queue)
        {
-               $this->queue = $queue;
+               $this->appHelper->setQueue($queue);
        }
 
        /**
         * Fetch workerqueue information
         *
+        * @deprecated 2024.12 Use AppHelper::getQueue() instead
+        *
         * @return array Worker queue
         */
        public function getQueue(): array
        {
-               return $this->queue ?? [];
+               return $this->appHelper->getQueue();
        }
 
        /**
         * Fetch a specific workerqueue field
         *
+        * @deprecated 2024.12 Use AppHelper::getQueueValue() instead
+        *
         * @param string $index Work queue record to fetch
         * @return mixed Work queue item or NULL if not found
         */
        public function getQueueValue(string $index)
        {
-               return $this->queue[$index] ?? null;
+               return $this->appHelper->getQueueValue($index);
        }
 
+       /**
+        * @deprecated 2024.12 Use AppHelper::setThemeInfoValue() instead
+        */
        public function setThemeInfoValue(string $index, $value)
        {
-               $this->theme_info[$index] = $value;
+               $this->appHelper->setThemeInfoValue($index, $value);
        }
 
+       /**
+        * @deprecated 2024.12 Use AppHelper::getThemeInfo() instead
+        */
        public function getThemeInfo()
        {
-               return $this->theme_info;
+               return $this->appHelper->getThemeInfo();
        }
 
+       /**
+        * @deprecated 2024.12 Use AppHelper::getThemeInfoValue() instead
+        */
        public function getThemeInfoValue(string $index, $default = null)
        {
-               return $this->theme_info[$index] ?? $default;
+               return $this->appHelper->getThemeInfoValue($index, $default);
        }
 
        /**
         * Returns the current config cache of this node
         *
+        * @deprecated 2024.12 Use AppHelper::getConfigCache() instead
+        *
         * @return Cache
         */
        public function getConfigCache()
        {
-               return $this->config->getCache();
+               return $this->appHelper->getConfigCache();
        }
 
        /**
         * The basepath of this app
         *
+        * @deprecated 2024.12 Use AppHelper::getBasePath() instead
+        *
         * @return string Base path from configuration
         */
        public function getBasePath(): string
        {
-               return $this->config->get('system', 'basepath');
-       }
-
-       /**
-        * @param Database                    $database The Friendica Database
-        * @param IManageConfigValues         $config   The Configuration
-        * @param App\Mode                    $mode     The mode of this Friendica app
-        * @param BaseURL                     $baseURL  The full base URL of this Friendica app
-        * @param LoggerInterface             $logger   The current app logger
-        * @param Profiler                    $profiler The profiler of this application
-        * @param L10n                        $l10n     The translator instance
-        * @param App\Arguments               $args     The Friendica Arguments of the call
-        * @param IManagePersonalConfigValues $pConfig  Personal configuration
-        * @param IHandleUserSessions         $session  The (User)Session handler
-        * @param DbaDefinition               $dbaDefinition
-        * @param ViewDefinition              $viewDefinition
-        */
-       public function __construct(Request $request, Authentication $auth, Database $database, IManageConfigValues $config, App\Mode $mode, BaseURL $baseURL, LoggerInterface $logger, Profiler $profiler, L10n $l10n, Arguments $args, IManagePersonalConfigValues $pConfig, IHandleUserSessions $session, DbaDefinition $dbaDefinition, ViewDefinition $viewDefinition)
-       {
-               $this->requestId      = $request->getRequestId();
-               $this->auth           = $auth;
-               $this->database       = $database;
-               $this->config         = $config;
-               $this->mode           = $mode;
-               $this->baseURL        = $baseURL;
-               $this->profiler       = $profiler;
-               $this->logger         = $logger;
-               $this->l10n           = $l10n;
-               $this->args           = $args;
-               $this->pConfig        = $pConfig;
-               $this->session        = $session;
-
-               $this->load($dbaDefinition, $viewDefinition);
+               return $this->appHelper->getBasePath();
        }
 
        /**
@@ -312,15 +316,16 @@ class App
 
                set_include_path(
                        get_include_path() . PATH_SEPARATOR
-                       . $this->getBasePath() . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR
-                       . $this->getBasePath() . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
-                       . $this->getBasePath());
+                       . $this->appHelper->getBasePath() . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR
+                       . $this->appHelper->getBasePath() . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
+                       . $this->appHelper->getBasePath()
+               );
 
                $this->profiler->reset();
 
-               if ($this->mode->has(App\Mode::DBAVAILABLE)) {
+               if ($this->mode->has(Mode::DBAVAILABLE)) {
                        Core\Hook::loadHooks();
-                       $loader = (new Config())->createConfigFileManager($this->getBasePath(), $_SERVER);
+                       $loader = (new Config())->createConfigFileManager($this->appHelper->getBasePath(), $_SERVER);
                        Core\Hook::callAll('load_config', $loader);
 
                        // Hooks are now working, reload the whole definitions with hook enabled
@@ -349,157 +354,70 @@ class App
                        $timezone = $default_timezone ?? '' ?: 'UTC';
                }
 
-               $this->setTimeZone($timezone);
+               $this->appHelper->setTimeZone($timezone);
        }
 
        /**
         * Returns the current theme name. May be overridden by the mobile theme name.
         *
+        * @deprecated 2024.12 Use AppHelper::getCurrentTheme() instead
+        *
         * @return string Current theme name or empty string in installation phase
         * @throws Exception
         */
        public function getCurrentTheme(): string
        {
-               if ($this->mode->isInstall()) {
-                       return '';
-               }
-
-               // Specific mobile theme override
-               if (($this->mode->isMobile() || $this->mode->isTablet()) && $this->session->get('show-mobile', true)) {
-                       $user_mobile_theme = $this->getCurrentMobileTheme();
-
-                       // --- means same mobile theme as desktop
-                       if (!empty($user_mobile_theme) && $user_mobile_theme !== '---') {
-                               return $user_mobile_theme;
-                       }
-               }
-
-               if (!$this->currentTheme) {
-                       $this->computeCurrentTheme();
-               }
-
-               return $this->currentTheme;
+               return $this->appHelper->getCurrentTheme();
        }
 
        /**
         * Returns the current mobile theme name.
         *
+        * @deprecated 2024.12 Use AppHelper::getCurrentMobileTheme() instead
+        *
         * @return string Mobile theme name or empty string if installer
         * @throws Exception
         */
        public function getCurrentMobileTheme(): string
        {
-               if ($this->mode->isInstall()) {
-                       return '';
-               }
-
-               if (is_null($this->currentMobileTheme)) {
-                       $this->computeCurrentMobileTheme();
-               }
-
-               return $this->currentMobileTheme;
+               return $this->appHelper->getCurrentMobileTheme();
        }
 
        /**
         * Setter for current theme name
         *
+        * @deprecated 2024.12 Use AppHelper::setCurrentTheme() instead
+        *
         * @param string $theme Name of current theme
         */
        public function setCurrentTheme(string $theme)
        {
-               $this->currentTheme = $theme;
+               $this->appHelper->setCurrentTheme($theme);
        }
 
        /**
         * Setter for current mobile theme name
         *
+        * @deprecated 2024.12 Use AppHelper::setCurrentMobileTheme() instead
+        *
         * @param string $theme Name of current mobile theme
         */
        public function setCurrentMobileTheme(string $theme)
        {
-               $this->currentMobileTheme = $theme;
-       }
-
-       /**
-        * Computes the current theme name based on the node settings, the page owner settings and the user settings
-        *
-        * @throws Exception
-        */
-       private function computeCurrentTheme()
-       {
-               $system_theme = $this->config->get('system', 'theme');
-               if (!$system_theme) {
-                       throw new Exception($this->l10n->t('No system theme config value set.'));
-               }
-
-               // Sane default
-               $this->setCurrentTheme($system_theme);
-
-               $page_theme = null;
-               // Find the theme that belongs to the user whose stuff we are looking at
-               if (!empty($this->profile_owner) && ($this->profile_owner != $this->session->getLocalUserId())) {
-                       // Allow folks to override user themes and always use their own on their own site.
-                       // This works only if the user is on the same server
-                       $user = $this->database->selectFirst('user', ['theme'], ['uid' => $this->profile_owner]);
-                       if ($this->database->isResult($user) && !$this->session->getLocalUserId()) {
-                               $page_theme = $user['theme'];
-                       }
-               }
-
-               $theme_name = $page_theme ?: $this->session->get('theme', $system_theme);
-
-               $theme_name = Strings::sanitizeFilePathItem($theme_name);
-               if ($theme_name
-                   && in_array($theme_name, Theme::getAllowedList())
-                   && (file_exists('view/theme/' . $theme_name . '/style.css')
-                       || file_exists('view/theme/' . $theme_name . '/style.php'))
-               ) {
-                       $this->setCurrentTheme($theme_name);
-               }
-       }
-
-       /**
-        * Computes the current mobile theme name based on the node settings, the page owner settings and the user settings
-        */
-       private function computeCurrentMobileTheme()
-       {
-               $system_mobile_theme = $this->config->get('system', 'mobile-theme', '');
-
-               // Sane default
-               $this->setCurrentMobileTheme($system_mobile_theme);
-
-               $page_mobile_theme = null;
-               // Find the theme that belongs to the user whose stuff we are looking at
-               if (!empty($this->profile_owner) && ($this->profile_owner != $this->session->getLocalUserId())) {
-                       // Allow folks to override user themes and always use their own on their own site.
-                       // This works only if the user is on the same server
-                       if (!$this->session->getLocalUserId()) {
-                               $page_mobile_theme = $this->pConfig->get($this->profile_owner, 'system', 'mobile-theme');
-                       }
-               }
-
-               $mobile_theme_name = $page_mobile_theme ?: $this->session->get('mobile-theme', $system_mobile_theme);
-
-               $mobile_theme_name = Strings::sanitizeFilePathItem($mobile_theme_name);
-               if ($mobile_theme_name == '---'
-                       ||
-                       in_array($mobile_theme_name, Theme::getAllowedList())
-                       && (file_exists('view/theme/' . $mobile_theme_name . '/style.css')
-                               || file_exists('view/theme/' . $mobile_theme_name . '/style.php'))
-               ) {
-                       $this->setCurrentMobileTheme($mobile_theme_name);
-               }
+               $this->appHelper->setCurrentMobileTheme($theme);
        }
 
        /**
         * Provide a sane default if nothing is chosen or the specified theme does not exist.
         *
+        * @deprecated 2024.12 Use AppHelper::getCurrentThemeStylesheetPath() instead
+        *
         * @return string Current theme's stylesheet path
         * @throws Exception
         */
        public function getCurrentThemeStylesheetPath(): string
        {
-               return Core\Theme::getStylesheetPath($this->getCurrentTheme());
+               return $this->appHelper->getCurrentThemeStylesheetPath();
        }
 
        /**
@@ -510,10 +428,10 @@ class App
         *
         * This probably should change to limit the size of this monster method.
         *
-        * @param App\Router                  $router
+        * @param Router                      $router
         * @param IManagePersonalConfigValues $pconfig
         * @param Authentication              $auth       The Authentication backend of the node
-        * @param App\Page                    $page       The Friendica page printing container
+        * @param Page                        $page       The Friendica page printing container
         * @param ModuleHTTPException         $httpException The possible HTTP Exception container
         * @param HTTPInputData               $httpInput  A library for processing PHP input streams
         * @param float                       $start_time The start time of the overall script execution
@@ -522,8 +440,17 @@ class App
         * @throws HTTPException\InternalServerErrorException
         * @throws \ImagickException
         */
-       public function runFrontend(App\Router $router, IManagePersonalConfigValues $pconfig, Authentication $auth, App\Page $page, Nav $nav, ModuleHTTPException $httpException, HTTPInputData $httpInput, float $start_time, array $server)
-       {
+       public function runFrontend(
+               Router $router,
+               IManagePersonalConfigValues $pconfig,
+               Authentication $auth,
+               Page $page,
+               Nav $nav,
+               ModuleHTTPException $httpException,
+               HTTPInputData $httpInput,
+               float $start_time,
+               array $server
+       ) {
                $requeststring = ($server['REQUEST_METHOD'] ?? '') . ' ' . ($server['REQUEST_URI'] ?? '') . ' ' . ($server['SERVER_PROTOCOL'] ?? '');
                $this->logger->debug('Request received', ['address' => $server['REMOTE_ADDR'] ?? '', 'request' => $requeststring, 'referer' => $server['HTTP_REFERER'] ?? '', 'user-agent' => $server['HTTP_USER_AGENT'] ?? '']);
                $request_start = microtime(true);
@@ -536,7 +463,7 @@ class App
 
                try {
                        // Missing DB connection: ERROR
-                       if ($this->mode->has(App\Mode::LOCALCONFIGPRESENT) && !$this->mode->has(App\Mode::DBAVAILABLE)) {
+                       if ($this->mode->has(Mode::LOCALCONFIGPRESENT) && !$this->mode->has(Mode::DBAVAILABLE)) {
                                throw new HTTPException\InternalServerErrorException($this->l10n->t('Apologies but the website is unavailable at the moment.'));
                        }
 
@@ -583,7 +510,7 @@ class App
                        }
 
                        if (!$this->mode->isBackend()) {
-                               $auth->withSession($this);
+                               $auth->withSession();
                        }
 
                        if ($this->session->isUnauthenticated()) {
@@ -601,7 +528,7 @@ class App
                        if ($this->mode->isInstall() && $moduleName !== 'install') {
                                $this->baseURL->redirect('install');
                        } else {
-                               Core\Update::check($this->getBasePath(), false);
+                               Core\Update::check($this->appHelper->getBasePath(), false);
                                Core\Addon::loadAddons();
                                Core\Hook::loadHooks();
                        }
@@ -648,7 +575,7 @@ class App
                        $page['page_title'] = $moduleName;
 
                        // The "view" module is required to show the theme CSS
-                       if (!$this->mode->isInstall() && !$this->mode->has(App\Mode::MAINTENANCEDISABLED) && $moduleName !== 'view') {
+                       if (!$this->mode->isInstall() && !$this->mode->has(Mode::MAINTENANCEDISABLED) && $moduleName !== 'view') {
                                $module = $router->getModule(Maintenance::class);
                        } else {
                                // determine the module class and save it to the module instance
@@ -665,7 +592,7 @@ class App
 
                        // Let the module run its internal process (init, get, post, ...)
                        $timestamp = microtime(true);
-                       $response = $module->run($httpException, $input);
+                       $response  = $module->run($httpException, $input);
                        $this->profiler->set(microtime(true) - $timestamp, 'content');
 
                        // Wrapping HTML responses in the theme template
@@ -688,17 +615,15 @@ class App
         * Automatically redirects to relative or absolute URL
         * Should only be used if it isn't clear if the URL is either internal or external
         *
+        * @deprecated 2024.12 Use AppHelper::redirect() instead
+        *
         * @param string $toUrl The target URL
         *
-        * @throws HTTPException\InternalServerErrorException
+        * @throws InternalServerErrorException
         */
        public function redirect(string $toUrl)
        {
-               if (!empty(parse_url($toUrl, PHP_URL_SCHEME))) {
-                       Core\System::externalRedirect($toUrl);
-               } else {
-                       $this->baseURL->redirect($toUrl);
-               }
+               $this->appHelper->redirect($toUrl);
        }
 
        /**
diff --git a/src/AppHelper.php b/src/AppHelper.php
new file mode 100644 (file)
index 0000000..66d3c61
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+namespace Friendica;
+
+use Exception;
+use Friendica\Core\Config\ValueObject\Cache;
+
+/**
+ * Helper for our main application structure for the life of this page.
+ *
+ * Primarily deals with the URL that got us here
+ * and tries to make some sense of it, and
+ * stores our page contents and config storage
+ * and anything else that might need to be passed around
+ * before we spit the page out.
+ *
+ */
+interface AppHelper
+{
+       /**
+        * Set the profile owner ID
+        */
+       public function setProfileOwner(int $owner_id);
+
+       /**
+        * Get the profile owner ID
+        */
+       public function getProfileOwner(): int;
+
+       /**
+        * Set the timezone
+        *
+        * @param string $timezone A valid time zone identifier, see https://www.php.net/manual/en/timezones.php
+        */
+       public function setTimeZone(string $timezone);
+
+       /**
+        * Get the timezone name
+        */
+       public function getTimeZone(): string;
+
+       /**
+        * Set the contact ID
+        */
+       public function setContactId(int $contact_id);
+
+       /**
+        * Get the contact ID
+        */
+       public function getContactId(): int;
+
+       /**
+        * Set workerqueue information
+        *
+        * @param array<string,mixed> $queue
+        */
+       public function setQueue(array $queue);
+
+       /**
+        * Fetch workerqueue information
+        *
+        * @return array<string,mixed> Worker queue
+        */
+       public function getQueue();
+
+       /**
+        * Fetch a specific workerqueue field
+        *
+        * @param string $index Work queue record to fetch
+        *
+        * @return mixed|null Work queue item or NULL if not found
+        */
+       public function getQueueValue(string $index);
+
+       /**
+        * Returns the current theme name. May be overridden by the mobile theme name.
+        *
+        * @return string Current theme name or empty string in installation phase
+        * @throws Exception
+        */
+       public function getCurrentTheme(): string;
+
+       /**
+        * Returns the current mobile theme name.
+        *
+        * @return string Mobile theme name or empty string if installer
+        * @throws Exception
+        */
+       public function getCurrentMobileTheme(): string;
+
+       /**
+        * Setter for current theme name
+        *
+        * @param string $theme Name of current theme
+        */
+       public function setCurrentTheme(string $theme);
+
+       /**
+        * Setter for current mobile theme name
+        *
+        * @param string $theme Name of current mobile theme
+        */
+       public function setCurrentMobileTheme(string $theme);
+
+       public function setThemeInfoValue(string $index, $value);
+
+       public function getThemeInfo();
+
+       public function getThemeInfoValue(string $index, $default = null);
+
+       /**
+        * Provide a sane default if nothing is chosen or the specified theme does not exist.
+        *
+        * @return string Current theme's stylesheet path
+        * @throws Exception
+        */
+       public function getCurrentThemeStylesheetPath(): string;
+
+       /**
+        * Returns the current config cache of this node
+        *
+        * @return Cache
+        */
+       public function getConfigCache();
+
+       /**
+        * The basepath of this app
+        *
+        * @return string Base path from configuration
+        */
+       public function getBasePath(): string;
+
+       public function redirect(string $toUrl);
+}
diff --git a/src/AppLegacy.php b/src/AppLegacy.php
new file mode 100644 (file)
index 0000000..4aa3f25
--- /dev/null
@@ -0,0 +1,399 @@
+<?php
+
+// Copyright (C) 2010-2024, the Friendica project
+// SPDX-FileCopyrightText: 2010-2024 the Friendica project
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+namespace Friendica;
+
+use DateTimeZone;
+use Exception;
+use Friendica\App\BaseURL;
+use Friendica\App\Mode;
+use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\Core\Config\ValueObject\Cache;
+use Friendica\Core\L10n;
+use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
+use Friendica\Core\Session\Capability\IHandleUserSessions;
+use Friendica\Core\System;
+use Friendica\Core\Theme;
+use Friendica\Database\Database;
+use Friendica\Network\HTTPException\InternalServerErrorException;
+use Friendica\Util\DateTimeFormat;
+use Friendica\Util\Strings;
+
+/**
+ * Helper for our main application structure for the life of this page.
+ *
+ * Primarily deals with the URL that got us here
+ * and tries to make some sense of it, and
+ * stores our page contents and config storage
+ * and anything else that might need to be passed around
+ * before we spit the page out.
+ *
+ */
+final class AppLegacy implements AppHelper
+{
+       private $profile_owner = 0;
+
+       private $timezone = '';
+
+       private $contact_id = 0;
+
+       private $queue = [];
+
+       /** @var string The name of the current theme */
+       private $currentTheme;
+
+       /** @var string The name of the current mobile theme */
+       private $currentMobileTheme;
+
+       // Allow themes to control internal parameters
+       // by changing App values in theme.php
+       private $theme_info = [
+               'videowidth'  => 425,
+               'videoheight' => 350,
+       ];
+
+       /**
+        * @var Database The Friendica database connection
+        */
+       private $database;
+
+       /**
+        * @var IManageConfigValues The config
+        */
+       private $config;
+
+       /**
+        * @var Mode The Mode of the Application
+        */
+       private $mode;
+
+       /**
+        * @var BaseURL
+        */
+       private $baseURL;
+
+       /**
+        * @var L10n The translator
+        */
+       private $l10n;
+
+       /**
+        * @var IManagePersonalConfigValues
+        */
+       private $pConfig;
+
+       /**
+        * @var IHandleUserSessions
+        */
+       private $session;
+
+       public function __construct(
+               Database $database,
+               IManageConfigValues $config,
+               Mode $mode,
+               BaseURL $baseURL,
+               L10n $l10n,
+               IManagePersonalConfigValues $pConfig,
+               IHandleUserSessions $session
+       ) {
+               $this->database = $database;
+               $this->config   = $config;
+               $this->mode     = $mode;
+               $this->l10n     = $l10n;
+               $this->baseURL  = $baseURL;
+               $this->pConfig  = $pConfig;
+               $this->session  = $session;
+       }
+
+       /**
+        * Set the profile owner ID
+        */
+       public function setProfileOwner(int $owner_id): void
+       {
+               $this->profile_owner = $owner_id;
+       }
+
+       /**
+        * Get the profile owner ID
+        */
+       public function getProfileOwner(): int
+       {
+               return $this->profile_owner;
+       }
+
+       /**
+        * Set the timezone
+        *
+        * @param string $timezone A valid time zone identifier, see https://www.php.net/manual/en/timezones.php
+        */
+       public function setTimeZone(string $timezone): void
+       {
+               $this->timezone = (new DateTimeZone($timezone))->getName();
+
+               DateTimeFormat::setLocalTimeZone($this->timezone);
+       }
+
+       /**
+        * Get the timezone name
+        */
+       public function getTimeZone(): string
+       {
+               return $this->timezone;
+       }
+
+       /**
+        * Set the contact ID
+        */
+       public function setContactId(int $contact_id): void
+       {
+               $this->contact_id = $contact_id;
+       }
+
+       /**
+        * Get the contact ID
+        */
+       public function getContactId(): int
+       {
+               return $this->contact_id;
+       }
+
+       /**
+        * Set workerqueue information
+        *
+        * @param array<string,mixed> $queue
+        */
+       public function setQueue(array $queue): void
+       {
+               $this->queue = $queue;
+       }
+
+       /**
+        * Fetch workerqueue information
+        *
+        * @return array<string,mixed> Worker queue
+        */
+       public function getQueue(): array
+       {
+               return $this->queue;
+       }
+
+       /**
+        * Fetch a specific workerqueue field
+        *
+        * @param string $index Work queue record to fetch
+        *
+        * @return mixed|null Work queue item or NULL if not found
+        */
+       public function getQueueValue(string $index)
+       {
+               return $this->queue[$index] ?? null;
+       }
+
+       /**
+        * Returns the current theme name. May be overridden by the mobile theme name.
+        *
+        * @return string Current theme name or empty string in installation phase
+        * @throws Exception
+        */
+       public function getCurrentTheme(): string
+       {
+               if ($this->mode->isInstall()) {
+                       return '';
+               }
+
+               // Specific mobile theme override
+               if (($this->mode->isMobile() || $this->mode->isTablet()) && $this->session->get('show-mobile', true)) {
+                       $user_mobile_theme = $this->getCurrentMobileTheme();
+
+                       // --- means same mobile theme as desktop
+                       if (!empty($user_mobile_theme) && $user_mobile_theme !== '---') {
+                               return $user_mobile_theme;
+                       }
+               }
+
+               if (!$this->currentTheme) {
+                       $this->computeCurrentTheme();
+               }
+
+               return $this->currentTheme;
+       }
+
+       /**
+        * Returns the current mobile theme name.
+        *
+        * @return string Mobile theme name or empty string if installer
+        * @throws Exception
+        */
+       public function getCurrentMobileTheme(): string
+       {
+               if ($this->mode->isInstall()) {
+                       return '';
+               }
+
+               if (is_null($this->currentMobileTheme)) {
+                       $this->computeCurrentMobileTheme();
+               }
+
+               return $this->currentMobileTheme;
+       }
+
+       /**
+        * Setter for current theme name
+        *
+        * @param string $theme Name of current theme
+        */
+       public function setCurrentTheme(string $theme): void
+       {
+               $this->currentTheme = $theme;
+       }
+
+       /**
+        * Setter for current mobile theme name
+        *
+        * @param string $theme Name of current mobile theme
+        */
+       public function setCurrentMobileTheme(string $theme): void
+       {
+               $this->currentMobileTheme = $theme;
+       }
+
+       public function setThemeInfoValue(string $index, $value): void
+       {
+               $this->theme_info[$index] = $value;
+       }
+
+       public function getThemeInfo(): array
+       {
+               return $this->theme_info;
+       }
+
+       public function getThemeInfoValue(string $index, $default = null)
+       {
+               return $this->theme_info[$index] ?? $default;
+       }
+
+       /**
+        * Provide a sane default if nothing is chosen or the specified theme does not exist.
+        *
+        * @return string Current theme's stylesheet path
+        * @throws Exception
+        */
+       public function getCurrentThemeStylesheetPath(): string
+       {
+               return Theme::getStylesheetPath($this->getCurrentTheme());
+       }
+
+       /**
+        * Returns the current config cache of this node
+        */
+       public function getConfigCache(): Cache
+       {
+               return $this->config->getCache();
+       }
+
+       /**
+        * The basepath of this app
+        *
+        * @return string Base path from configuration
+        */
+       public function getBasePath(): string
+       {
+               return $this->config->get('system', 'basepath');
+       }
+
+       /**
+        * Computes the current theme name based on the node settings, the page owner settings and the user settings
+        *
+        * @throws Exception
+        */
+       private function computeCurrentTheme()
+       {
+               $system_theme = $this->config->get('system', 'theme');
+               if (!$system_theme) {
+                       throw new Exception($this->l10n->t('No system theme config value set.'));
+               }
+
+               // Sane default
+               $this->setCurrentTheme($system_theme);
+
+               $page_theme    = null;
+               $profile_owner = $this->getProfileOwner();
+
+               // Find the theme that belongs to the user whose stuff we are looking at
+               if (!empty($profile_owner) && ($profile_owner != $this->session->getLocalUserId())) {
+                       // Allow folks to override user themes and always use their own on their own site.
+                       // This works only if the user is on the same server
+                       $user = $this->database->selectFirst('user', ['theme'], ['uid' => $profile_owner]);
+                       if ($this->database->isResult($user) && !$this->session->getLocalUserId()) {
+                               $page_theme = $user['theme'];
+                       }
+               }
+
+               $theme_name = $page_theme ?: $this->session->get('theme', $system_theme);
+
+               $theme_name = Strings::sanitizeFilePathItem($theme_name);
+               if ($theme_name
+                       && in_array($theme_name, Theme::getAllowedList())
+                       && (file_exists('view/theme/' . $theme_name . '/style.css')
+                               || file_exists('view/theme/' . $theme_name . '/style.php'))
+               ) {
+                       $this->setCurrentTheme($theme_name);
+               }
+       }
+
+       /**
+        * Computes the current mobile theme name based on the node settings, the page owner settings and the user settings
+        */
+       private function computeCurrentMobileTheme()
+       {
+               $system_mobile_theme = $this->config->get('system', 'mobile-theme', '');
+
+               // Sane default
+               $this->setCurrentMobileTheme($system_mobile_theme);
+
+               $page_mobile_theme = null;
+               $profile_owner     = $this->getProfileOwner();
+
+               // Find the theme that belongs to the user whose stuff we are looking at
+               if (!empty($profile_owner) && ($profile_owner != $this->session->getLocalUserId())) {
+                       // Allow folks to override user themes and always use their own on their own site.
+                       // This works only if the user is on the same server
+                       if (!$this->session->getLocalUserId()) {
+                               $page_mobile_theme = $this->pConfig->get($profile_owner, 'system', 'mobile-theme');
+                       }
+               }
+
+               $mobile_theme_name = $page_mobile_theme ?: $this->session->get('mobile-theme', $system_mobile_theme);
+
+               $mobile_theme_name = Strings::sanitizeFilePathItem($mobile_theme_name);
+               if ($mobile_theme_name == '---'
+                       ||
+                       in_array($mobile_theme_name, Theme::getAllowedList())
+                       && (file_exists('view/theme/' . $mobile_theme_name . '/style.css')
+                               || file_exists('view/theme/' . $mobile_theme_name . '/style.php'))
+               ) {
+                       $this->setCurrentMobileTheme($mobile_theme_name);
+               }
+       }
+
+       /**
+        * Automatically redirects to relative or absolute URL
+        * Should only be used if it isn't clear if the URL is either internal or external
+        *
+        * @param string $toUrl The target URL
+        *
+        * @throws InternalServerErrorException
+        */
+       public function redirect(string $toUrl)
+       {
+               if (!empty(parse_url($toUrl, PHP_URL_SCHEME))) {
+                       System::externalRedirect($toUrl);
+               } else {
+                       $this->baseURL->redirect($toUrl);
+               }
+       }
+}
index 46010ce62bee4623a9fd2c9aaf671dedf6b86006..5604fe9df24c6e3e95b224ae780994ea5b5067cf 100644 (file)
@@ -71,6 +71,8 @@ abstract class DI
        //
 
        /**
+        * @deprecated 2024.12 use DI::appHelper() instead
+        *
         * @return App
         */
        public static function app()
@@ -78,6 +80,11 @@ abstract class DI
                return self::$dice->create(App::class);
        }
 
+       public static function appHelper(): AppHelper
+       {
+               return self::$dice->create(AppHelper::class);
+       }
+
        /**
         * @return Database\Database
         */