diff --git a/apps/files_sharing/lib/AppInfo/Application.php b/apps/files_sharing/lib/AppInfo/Application.php index eff4a3ac5b749..e789bce13619d 100644 --- a/apps/files_sharing/lib/AppInfo/Application.php +++ b/apps/files_sharing/lib/AppInfo/Application.php @@ -123,11 +123,6 @@ public function boot(IBootContext $context): void { Share::registerBackend('file', File::class); Share::registerBackend('folder', Folder::class, 'file'); - - /** - * Always add main sharing script - */ - Util::addScript(self::APP_ID, 'main'); } @@ -147,6 +142,12 @@ public function registerEventsScripts(IEventDispatcher $dispatcher, EventDispatc $dispatcher->addListener(ResourcesLoadAdditionalScriptsEvent::class, function () { \OCP\Util::addScript('files_sharing', 'collaboration'); }); + $dispatcher->addListener(\OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent::class, function () { + /** + * Always add main sharing script + */ + Util::addScript(self::APP_ID, 'main'); + }); // notifications api to accept incoming user shares $oldDispatcher->addListener('OCP\Share::postShare', function (OldGenericEvent $event) { diff --git a/apps/theming/lib/AppInfo/Application.php b/apps/theming/lib/AppInfo/Application.php index 48bf42252c7d3..43b854012f7d3 100644 --- a/apps/theming/lib/AppInfo/Application.php +++ b/apps/theming/lib/AppInfo/Application.php @@ -31,6 +31,7 @@ use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; +use OCP\AppFramework\Http\Events\BeforeLoginTemplateRenderedEvent; use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\Config\BeforePreferenceDeletedEvent; use OCP\Config\BeforePreferenceSetEvent; @@ -45,6 +46,7 @@ public function __construct() { public function register(IRegistrationContext $context): void { $context->registerCapability(Capabilities::class); $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); + $context->registerEventListener(BeforeLoginTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $context->registerEventListener(BeforePreferenceSetEvent::class, BeforePreferenceListener::class); $context->registerEventListener(BeforePreferenceDeletedEvent::class, BeforePreferenceListener::class); } diff --git a/core/Application.php b/core/Application.php index 592e092966681..650e992e0ccfe 100644 --- a/core/Application.php +++ b/core/Application.php @@ -53,6 +53,7 @@ use OC\Metadata\FileEventListener; use OC\TagManager; use OCP\AppFramework\App; +use OCP\AppFramework\Http\Events\BeforeLoginTemplateRenderedEvent; use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Events\Node\NodeDeletedEvent; @@ -328,6 +329,7 @@ function (GenericEvent $event) use ($container) { ); $eventDispatcher->addServiceListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); + $eventDispatcher->addServiceListener(BeforeLoginTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $eventDispatcher->addServiceListener(RemoteWipeStarted::class, RemoteWipeActivityListener::class); $eventDispatcher->addServiceListener(RemoteWipeStarted::class, RemoteWipeNotificationsListener::class); $eventDispatcher->addServiceListener(RemoteWipeStarted::class, RemoteWipeEmailListener::class); diff --git a/core/Listener/BeforeTemplateRenderedListener.php b/core/Listener/BeforeTemplateRenderedListener.php index 4b658cb550a17..0eff47449c714 100644 --- a/core/Listener/BeforeTemplateRenderedListener.php +++ b/core/Listener/BeforeTemplateRenderedListener.php @@ -25,20 +25,53 @@ */ namespace OC\Core\Listener; +use OCP\AppFramework\Http\Events\BeforeLoginTemplateRenderedEvent; use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\AppFramework\Http\TemplateResponse; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; +use OCP\IConfig; +use OCP\Util; class BeforeTemplateRenderedListener implements IEventListener { + public function __construct(private IConfig $config) { + } + public function handle(Event $event): void { - if (!($event instanceof BeforeTemplateRenderedEvent)) { + if (!($event instanceof BeforeTemplateRenderedEvent || $event instanceof BeforeLoginTemplateRenderedEvent)) { return; } if ($event->getResponse()->getRenderAs() === TemplateResponse::RENDER_AS_USER) { // Making sure to inject just after core - \OCP\Util::addScript('core', 'unsupported-browser-redirect'); + Util::addScript('core', 'unsupported-browser-redirect'); + } + + \OC_Util::addStyle('server', null, true); + + if ($event instanceof BeforeLoginTemplateRenderedEvent) { + // todo: make login work without these + Util::addScript('core', 'common'); + Util::addScript('core', 'main'); + } + + if ($event instanceof BeforeTemplateRenderedEvent) { + // include common nextcloud webpack bundle + Util::addScript('core', 'common'); + Util::addScript('core', 'main'); + Util::addTranslations('core'); + + if ($event->getResponse()->getRenderAs() !== TemplateResponse::RENDER_AS_ERROR) { + Util::addScript('core', 'merged-template-prepend', 'core', true); + Util::addScript('core', 'files_client', 'core', true); + Util::addScript('core', 'files_fileinfo', 'core', true); + + + // If installed and background job is set to ajax, add dedicated script + if ($this->config->getAppValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') { + Util::addScript('core', 'backgroundjobs'); + } + } } } } diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index e53b4fe94c6e0..99421c984563d 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -55,6 +55,7 @@ 'OCP\\AppFramework\\Http\\DownloadResponse' => $baseDir . '/lib/public/AppFramework/Http/DownloadResponse.php', 'OCP\\AppFramework\\Http\\EmptyContentSecurityPolicy' => $baseDir . '/lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php', 'OCP\\AppFramework\\Http\\EmptyFeaturePolicy' => $baseDir . '/lib/public/AppFramework/Http/EmptyFeaturePolicy.php', + 'OCP\\AppFramework\\Http\\Events\\BeforeLoginTemplateRenderedEvent' => $baseDir . '/lib/public/AppFramework/Http/Events/BeforeLoginTemplateRenderedEvent.php', 'OCP\\AppFramework\\Http\\Events\\BeforeTemplateRenderedEvent' => $baseDir . '/lib/public/AppFramework/Http/Events/BeforeTemplateRenderedEvent.php', 'OCP\\AppFramework\\Http\\FeaturePolicy' => $baseDir . '/lib/public/AppFramework/Http/FeaturePolicy.php', 'OCP\\AppFramework\\Http\\FileDisplayResponse' => $baseDir . '/lib/public/AppFramework/Http/FileDisplayResponse.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 58bdace5dcbb6..f87c125cd4593 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -88,6 +88,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\AppFramework\\Http\\DownloadResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/DownloadResponse.php', 'OCP\\AppFramework\\Http\\EmptyContentSecurityPolicy' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php', 'OCP\\AppFramework\\Http\\EmptyFeaturePolicy' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/EmptyFeaturePolicy.php', + 'OCP\\AppFramework\\Http\\Events\\BeforeLoginTemplateRenderedEvent' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Events/BeforeLoginTemplateRenderedEvent.php', 'OCP\\AppFramework\\Http\\Events\\BeforeTemplateRenderedEvent' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Events/BeforeTemplateRenderedEvent.php', 'OCP\\AppFramework\\Http\\FeaturePolicy' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/FeaturePolicy.php', 'OCP\\AppFramework\\Http\\FileDisplayResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/FileDisplayResponse.php', diff --git a/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php b/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php index ec52dde0ecd26..dceee964622e2 100644 --- a/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php +++ b/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php @@ -27,6 +27,8 @@ */ namespace OC\AppFramework\Middleware; +use OC\Core\Controller\LoginController; +use OCP\AppFramework\Http\Events\BeforeLoginTemplateRenderedEvent; use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\StandaloneTemplateResponse; @@ -54,23 +56,27 @@ public function __construct(EventDispatcherInterface $legacyDispatcher, IUserSes public function afterController($controller, $methodName, Response $response): Response { if ($response instanceof TemplateResponse) { - if (!$controller instanceof PublicShareController) { - /* - * The old event was not dispatched on the public share controller as there was - * OCA\Files_Sharing::loadAdditionalScripts for that. This is kept for compatibility reasons - * only for the old event as this is now also included in BeforeTemplateRenderedEvent - */ - $this->legacyDispatcher->dispatch(TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS, new GenericEvent()); - } - - if (!($response instanceof StandaloneTemplateResponse) && $this->userSession->isLoggedIn()) { - $this->legacyDispatcher->dispatch(TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN, new GenericEvent()); - $isLoggedIn = true; + if ($controller instanceof LoginController) { + $this->dispatcher->dispatchTyped(new BeforeLoginTemplateRenderedEvent($response)); } else { - $isLoggedIn = false; - } + if (!$controller instanceof PublicShareController) { + /* + * The old event was not dispatched on the public share controller as there was + * OCA\Files_Sharing::loadAdditionalScripts for that. This is kept for compatibility reasons + * only for the old event as this is now also included in BeforeTemplateRenderedEvent + */ + $this->legacyDispatcher->dispatch(TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS, new GenericEvent()); + } - $this->dispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($isLoggedIn, $response)); + if (!($response instanceof StandaloneTemplateResponse) && $this->userSession->isLoggedIn()) { + $this->legacyDispatcher->dispatch(TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN, new GenericEvent()); + $isLoggedIn = true; + } else { + $isLoggedIn = false; + } + + $this->dispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($isLoggedIn, $response)); + } } return $response; diff --git a/lib/private/legacy/OC_Template.php b/lib/private/legacy/OC_Template.php index 0c9fa1ccc0cdc..6694c392a7ed8 100644 --- a/lib/private/legacy/OC_Template.php +++ b/lib/private/legacy/OC_Template.php @@ -39,7 +39,6 @@ */ use OC\TemplateLayout; use OCP\AppFramework\Http\TemplateResponse; -use OCP\Util; require_once __DIR__.'/template/functions.php'; @@ -59,8 +58,6 @@ class OC_Template extends \OC\Template\Base { /** @var string */ protected $app; // app id - protected static $initTemplateEngineFirstRun = true; - /** * Constructor * @@ -73,9 +70,6 @@ class OC_Template extends \OC\Template\Base { * @param bool $registerCall = true */ public function __construct($app, $name, $renderAs = TemplateResponse::RENDER_AS_BLANK, $registerCall = true) { - // Read the selected theme from the config file - self::initTemplateEngine($renderAs); - $theme = OC_Util::getTheme(); $requestToken = (OC::$server->getSession() && $registerCall) ? \OCP\Util::callRegister() : ''; @@ -95,40 +89,6 @@ public function __construct($app, $name, $renderAs = TemplateResponse::RENDER_AS parent::__construct($template, $requestToken, $l10n, $themeDefaults); } - /** - * @param string $renderAs - */ - public static function initTemplateEngine($renderAs) { - if (self::$initTemplateEngineFirstRun) { - // apps that started before the template initialization can load their own scripts/styles - // so to make sure this scripts/styles here are loaded first we put all core scripts first - // check lib/public/Util.php - OC_Util::addStyle('server', null, true); - - // include common nextcloud webpack bundle - Util::addScript('core', 'common'); - Util::addScript('core', 'main'); - Util::addTranslations('core'); - - if (\OC::$server->getSystemConfig()->getValue('installed', false) && !\OCP\Util::needUpgrade()) { - Util::addScript('core', 'files_fileinfo'); - Util::addScript('core', 'files_client'); - Util::addScript('core', 'merged-template-prepend'); - } - - // If installed and background job is set to ajax, add dedicated script - if (\OC::$server->getSystemConfig()->getValue('installed', false) - && $renderAs !== TemplateResponse::RENDER_AS_ERROR - && !\OCP\Util::needUpgrade()) { - if (\OC::$server->getConfig()->getAppValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') { - Util::addScript('core', 'backgroundjobs'); - } - } - - self::$initTemplateEngineFirstRun = false; - } - } - /** * find the template with the given name diff --git a/lib/public/AppFramework/Http/Events/BeforeLoginTemplateRenderedEvent.php b/lib/public/AppFramework/Http/Events/BeforeLoginTemplateRenderedEvent.php new file mode 100644 index 0000000000000..99c1275f3fff5 --- /dev/null +++ b/lib/public/AppFramework/Http/Events/BeforeLoginTemplateRenderedEvent.php @@ -0,0 +1,52 @@ + + * + * @author Julius Härtl + * @author Morris Jobke + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +namespace OCP\AppFramework\Http\Events; + +use OCP\AppFramework\Http\TemplateResponse; +use OCP\EventDispatcher\Event; + +/** + * Emitted before the rendering step of the login TemplateResponse. + * + * @since 28.0.0 + */ +class BeforeLoginTemplateRenderedEvent extends Event { + /** + * @since 28.0.0 + */ + public function __construct(private TemplateResponse $response) { + parent::__construct(); + } + + /** + * @since 28.0.0 + */ + public function getResponse(): TemplateResponse { + return $this->response; + } +} diff --git a/lib/public/Util.php b/lib/public/Util.php index 64934c5f3ade6..67553a466f756 100644 --- a/lib/public/Util.php +++ b/lib/public/Util.php @@ -168,9 +168,10 @@ public static function addStyle($application, $file = null) { * @param string $application * @param string|null $file * @param string $afterAppId + * @param bool $prepend * @since 4.0.0 */ - public static function addScript(string $application, string $file = null, string $afterAppId = 'core'): void { + public static function addScript(string $application, string $file = null, string $afterAppId = 'core', bool $prepend = false): void { if (!empty($application)) { $path = "$application/js/$file"; } else { @@ -193,7 +194,11 @@ public static function addScript(string $application, string $file = null, strin self::$scriptDeps[$application]->addDep($afterAppId); } - self::$scripts[$application][] = $path; + if ($prepend) { + array_unshift(self::$scripts[$application], $path); + } else { + self::$scripts[$application][] = $path; + } } /** @@ -211,7 +216,12 @@ public static function getScripts(): array { $sortedScripts = $sortedScripts ? array_merge(...array_values(($sortedScripts))) : []; // Override core-common and core-main order - array_unshift($sortedScripts, 'core/js/common', 'core/js/main'); + if (in_array('core/js/main', $sortedScripts)) { + array_unshift($sortedScripts, 'core/js/main'); + } + if (in_array('core/js/common', $sortedScripts)) { + array_unshift($sortedScripts, 'core/js/common'); + } return array_unique($sortedScripts); }