[TASK] Use dependency injection in middlewares 22/61322/5
authorBenjamin Franzke <bfr@qbus.de>
Fri, 19 Jul 2019 04:47:46 +0000 (06:47 +0200)
committerDaniel Goerz <daniel.goerz@posteo.de>
Tue, 6 Aug 2019 09:54:00 +0000 (11:54 +0200)
Use constructor injection for middleware dependencies, moving away
from GeneralUtility::makeInstance based Singleton lookup.
Dependencies which are already configured to be optionally
injectable via constructor arguments (e.g. for unit tests) are
changed to be required constructor arguments. Since the introduction of
symfony dependency injection the fallback to GeneralUtility::makeInstance
is no longer used – therefore it is dropped.

Releases: master
Resolves: #88800
Change-Id: I6dbec2f91fc78c1b06dd179323fb7a4810c13baa
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61322
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Susanne Moog <look@susi.dev>
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Susanne Moog <look@susi.dev>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
18 files changed:
typo3/sysext/adminpanel/Classes/Middleware/SqlLogging.php
typo3/sysext/backend/Classes/Middleware/BackendUserAuthenticator.php
typo3/sysext/backend/Classes/Middleware/SiteResolver.php
typo3/sysext/backend/Tests/Unit/Middleware/SiteResolverTest.php
typo3/sysext/core/Classes/ServiceProvider.php
typo3/sysext/core/Classes/TimeTracker/TimeTracker.php
typo3/sysext/frontend/Classes/Middleware/BackendUserAuthenticator.php
typo3/sysext/frontend/Classes/Middleware/FrontendUserAuthenticator.php
typo3/sysext/frontend/Classes/Middleware/PageArgumentValidator.php
typo3/sysext/frontend/Classes/Middleware/PrepareTypoScriptFrontendRendering.php
typo3/sysext/frontend/Classes/Middleware/ShortcutAndMountPointRedirect.php
typo3/sysext/frontend/Classes/Middleware/SiteResolver.php
typo3/sysext/frontend/Classes/Middleware/StaticRouteResolver.php
typo3/sysext/frontend/Classes/Middleware/TimeTrackerInitialization.php
typo3/sysext/frontend/Classes/Middleware/TypoScriptFrontendInitialization.php
typo3/sysext/frontend/Tests/Unit/Middleware/PageArgumentValidatorTest.php
typo3/sysext/install/Classes/Middleware/Maintenance.php
typo3/sysext/install/Classes/ServiceProvider.php

index f2909f0..a80bffb 100644 (file)
@@ -32,6 +32,15 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  */
 class SqlLogging implements MiddlewareInterface
 {
+    /**
+     * @var ConnectionPool
+     */
+    protected $connectionPool;
+
+    public function __construct(ConnectionPool $connectionPool)
+    {
+        $this->connectionPool = $connectionPool;
+    }
 
     /**
      * Enable SQL Logging as early as possible to catch all queries if the admin panel is active
@@ -42,8 +51,7 @@ class SqlLogging implements MiddlewareInterface
     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
     {
         if (StateUtility::isActivatedForUser() && StateUtility::isOpen()) {
-            $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
-            $connection = $connectionPool->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
+            $connection = $this->connectionPool->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
             $connection->getConfiguration()->setSQLLogger(GeneralUtility::makeInstance(DoctrineSqlLogger::class));
         }
         return $handler->handle($request);
index 685e604..7541094 100644 (file)
@@ -50,6 +50,16 @@ class BackendUserAuthenticator implements MiddlewareInterface
     ];
 
     /**
+     * @var Context
+     */
+    protected $context;
+
+    public function __construct(Context $context)
+    {
+        $this->context = $context;
+    }
+
+    /**
      * Calls the bootstrap process to set up $GLOBALS['BE_USER'] AND $GLOBALS['LANG']
      *
      * @param ServerRequestInterface $request
@@ -65,7 +75,7 @@ class BackendUserAuthenticator implements MiddlewareInterface
         Bootstrap::initializeBackendAuthentication($this->isLoggedInBackendUserRequired($pathToRoute));
         Bootstrap::initializeLanguageObject();
         // Register the backend user as aspect
-        $this->setBackendUserAspect(GeneralUtility::makeInstance(Context::class), $GLOBALS['BE_USER']);
+        $this->setBackendUserAspect($GLOBALS['BE_USER']);
 
         return $handler->handle($request);
     }
@@ -85,12 +95,11 @@ class BackendUserAuthenticator implements MiddlewareInterface
     /**
      * Register the backend user as aspect
      *
-     * @param Context $context
      * @param BackendUserAuthentication $user
      */
-    protected function setBackendUserAspect(Context $context, BackendUserAuthentication $user)
+    protected function setBackendUserAspect(BackendUserAuthentication $user)
     {
-        $context->setAspect('backend.user', GeneralUtility::makeInstance(UserAspect::class, $user));
-        $context->setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class, $user->workspace));
+        $this->context->setAspect('backend.user', GeneralUtility::makeInstance(UserAspect::class, $user));
+        $this->context->setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class, $user->workspace));
     }
 }
index 9d601f9..a062db1 100644 (file)
@@ -21,7 +21,6 @@ use Psr\Http\Server\MiddlewareInterface;
 use Psr\Http\Server\RequestHandlerInterface;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Routing\SiteMatcher;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 
 /**
@@ -35,6 +34,16 @@ use TYPO3\CMS\Core\Utility\MathUtility;
 class SiteResolver implements MiddlewareInterface
 {
     /**
+     * @var SiteMatcher
+     */
+    protected $siteMatcher;
+
+    public function __construct(SiteMatcher $siteMatcher)
+    {
+        $this->siteMatcher = $siteMatcher;
+    }
+
+    /**
      * Resolve the site information by checking the page ID ("id" parameter) which is typically used in BE modules
      * of type "web".
      *
@@ -52,7 +61,7 @@ class SiteResolver implements MiddlewareInterface
             if ($pageId > 0) {
                 $rootLine = BackendUtility::BEgetRootLine($pageId);
             }
-            $site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId($pageId, $rootLine);
+            $site = $this->siteMatcher->matchByPageId($pageId, $rootLine);
             $request = $request->withAttribute('site', $site);
         }
         return $handler->handle($request);
index 5aa5347..f3d09ee 100644 (file)
@@ -22,6 +22,7 @@ use Psr\Http\Server\RequestHandlerInterface;
 use TYPO3\CMS\Backend\Middleware\SiteResolver;
 use TYPO3\CMS\Core\Http\JsonResponse;
 use TYPO3\CMS\Core\Http\ServerRequest;
+use TYPO3\CMS\Core\Routing\SiteMatcher;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 class SiteResolverTest extends UnitTestCase
@@ -34,7 +35,8 @@ class SiteResolverTest extends UnitTestCase
     {
         $incomingUrl = 'http://localhost:8080/typo3/index.php?route=/file/FilelistList/&token=d7d864db2b26c1d0f0537718b16890f336f4af2b&id=9831:/styleguide/';
 
-        $subject = new SiteResolver();
+        $siteMatcherProphecy = $this->prophesize(SiteMatcher::class);
+        $subject = new SiteResolver($siteMatcherProphecy->reveal());
 
         $incomingRequest = new ServerRequest($incomingUrl, 'GET');
         $incomingRequest = $incomingRequest->withQueryParams(['id' => '9831:/styleguide/']);
index 24a4d70..ccea16a 100644 (file)
@@ -38,6 +38,7 @@ class ServiceProvider extends AbstractServiceProvider
             EventDispatcher\ListenerProvider::class => [ static::class, 'getEventListenerProvider' ],
             Http\MiddlewareStackResolver::class => [ static::class, 'getMiddlewareStackResolver' ],
             Service\DependencyOrderingService::class => [ static::class, 'getDependencyOrderingService' ],
+            Crypto\PasswordHashing\PasswordHashFactory::class => [ static::class, 'getPasswordHashFactory' ],
             'middlewares' => [ static::class, 'getMiddlewares' ],
         ];
     }
@@ -91,6 +92,11 @@ class ServiceProvider extends AbstractServiceProvider
         return new Context\Context;
     }
 
+    public static function getPasswordHashFactory(ContainerInterface $container): Crypto\PasswordHashing\PasswordHashFactory
+    {
+        return new Crypto\PasswordHashing\PasswordHashFactory;
+    }
+
     public static function getMiddlewareStackResolver(ContainerInterface $container): Http\MiddlewareStackResolver
     {
         return new Http\MiddlewareStackResolver(
index a5d0bd6..c2b989a 100644 (file)
@@ -148,6 +148,14 @@ class TimeTracker implements SingletonInterface
     }
 
     /**
+     * @param bool $isEnabled
+     */
+    public function setEnabled(bool $isEnabled = true)
+    {
+        $this->isEnabled = $isEnabled;
+    }
+
+    /**
      * Sets the starting time
      *
      * @see finish()
index b9b1fdf..6f10a85 100644 (file)
@@ -40,6 +40,16 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 class BackendUserAuthenticator implements MiddlewareInterface
 {
     /**
+     * @var Context
+     */
+    protected $context;
+
+    public function __construct(Context $context)
+    {
+        $this->context = $context;
+    }
+
+    /**
      * Creates a backend user authentication object, tries to authenticate a user
      *
      * @param ServerRequestInterface $request
@@ -63,7 +73,7 @@ class BackendUserAuthenticator implements MiddlewareInterface
             Bootstrap::initializeLanguageObject();
             Bootstrap::initializeBackendRouter();
             Bootstrap::loadExtTables();
-            $this->setBackendUserAspect(GeneralUtility::makeInstance(Context::class), $GLOBALS['BE_USER']);
+            $this->setBackendUserAspect($GLOBALS['BE_USER']);
         }
 
         return $handler->handle($request);
@@ -116,12 +126,11 @@ class BackendUserAuthenticator implements MiddlewareInterface
     /**
      * Register the backend user as aspect
      *
-     * @param Context $context
      * @param BackendUserAuthentication|null $user
      */
-    protected function setBackendUserAspect(Context $context, BackendUserAuthentication $user)
+    protected function setBackendUserAspect(BackendUserAuthentication $user)
     {
-        $context->setAspect('backend.user', GeneralUtility::makeInstance(UserAspect::class, $user));
-        $context->setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class, $user->workspace));
+        $this->context->setAspect('backend.user', GeneralUtility::makeInstance(UserAspect::class, $user));
+        $this->context->setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class, $user->workspace));
     }
 }
index 09a7ee4..86234b9 100644 (file)
@@ -31,6 +31,16 @@ use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
 class FrontendUserAuthenticator implements MiddlewareInterface
 {
     /**
+     * @var Context
+     */
+    protected $context;
+
+    public function __construct(Context $context)
+    {
+        $this->context = $context;
+    }
+
+    /**
      * Creates a frontend user authentication object, tries to authenticate a user and stores
      * it in the current request as attribute.
      *
@@ -59,7 +69,7 @@ class FrontendUserAuthenticator implements MiddlewareInterface
         $frontendUser->unpack_uc();
 
         // Register the frontend user as aspect and within the session
-        $this->setFrontendUserAspect(GeneralUtility::makeInstance(Context::class), $frontendUser);
+        $this->setFrontendUserAspect($frontendUser);
         $request = $request->withAttribute('frontend.user', $frontendUser);
 
         $response = $handler->handle($request);
@@ -112,11 +122,10 @@ class FrontendUserAuthenticator implements MiddlewareInterface
     /**
      * Register the frontend user as aspect
      *
-     * @param Context $context
      * @param AbstractUserAuthentication $user
      */
-    protected function setFrontendUserAspect(Context $context, AbstractUserAuthentication $user)
+    protected function setFrontendUserAspect(AbstractUserAuthentication $user)
     {
-        $context->setAspect('frontend.user', GeneralUtility::makeInstance(UserAspect::class, $user));
+        $this->context->setAspect('frontend.user', GeneralUtility::makeInstance(UserAspect::class, $user));
     }
 }
index 6bf951d..4b6d2aa 100644 (file)
@@ -47,13 +47,21 @@ class PageArgumentValidator implements MiddlewareInterface, LoggerAwareInterface
     protected $cacheHashCalculator;
 
     /**
+     * @var TimeTracker
+     */
+    protected $timeTracker;
+
+    /**
      * @var bool will be used to set $TSFE->no_cache later-on
      */
     protected $disableCache = false;
 
-    public function __construct()
-    {
-        $this->cacheHashCalculator = GeneralUtility::makeInstance(CacheHashCalculator::class);
+    public function __construct(
+        CacheHashCalculator $cacheHashCalculator,
+        TimeTracker $timeTracker
+    ) {
+        $this->cacheHashCalculator = $cacheHashCalculator;
+        $this->timeTracker = $timeTracker;
     }
 
     /**
@@ -158,7 +166,7 @@ class PageArgumentValidator implements MiddlewareInterface, LoggerAwareInterface
         }
         // Caching is disabled now (but no 404)
         $this->disableCache = true;
-        $this->getTimeTracker()->setTSlogMessage('The incoming cHash "' . $cHash . '" and calculated cHash "' . $calculatedCacheHash . '" did not match, so caching was disabled. The fieldlist used was "' . implode(',', array_keys($relevantParameters)) . '"', 2);
+        $this->timeTracker->setTSlogMessage('The incoming cHash "' . $cHash . '" and calculated cHash "' . $calculatedCacheHash . '" did not match, so caching was disabled. The fieldlist used was "' . implode(',', array_keys($relevantParameters)) . '"', 2);
         return true;
     }
 
@@ -182,15 +190,7 @@ class PageArgumentValidator implements MiddlewareInterface, LoggerAwareInterface
         }
         // Caching is disabled now (but no 404)
         $this->disableCache = true;
-        $this->getTimeTracker()->setTSlogMessage('TSFE->reqCHash(): No &cHash parameter was sent for GET vars though required so caching is disabled', 2);
+        $this->timeTracker->setTSlogMessage('TSFE->reqCHash(): No &cHash parameter was sent for GET vars though required so caching is disabled', 2);
         return true;
     }
-
-    /**
-     * @return TimeTracker
-     */
-    protected function getTimeTracker(): TimeTracker
-    {
-        return GeneralUtility::makeInstance(TimeTracker::class);
-    }
 }
index 915efa5..3338875 100644 (file)
@@ -21,7 +21,6 @@ use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Server\MiddlewareInterface;
 use Psr\Http\Server\RequestHandlerInterface;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 
 /**
@@ -43,10 +42,10 @@ class PrepareTypoScriptFrontendRendering implements MiddlewareInterface
      */
     protected $timeTracker;
 
-    public function __construct(TypoScriptFrontendController $controller = null, TimeTracker $timeTracker = null)
+    public function __construct(TypoScriptFrontendController $controller, TimeTracker $timeTracker)
     {
-        $this->controller = $controller ?: $GLOBALS['TSFE'];
-        $this->timeTracker = $timeTracker ?: GeneralUtility::makeInstance(TimeTracker::class);
+        $this->controller = $controller;
+        $this->timeTracker = $timeTracker;
     }
 
     /**
index 2835283..a8cd817 100644 (file)
@@ -37,9 +37,9 @@ class ShortcutAndMountPointRedirect implements MiddlewareInterface
      */
     private $controller;
 
-    public function __construct(TypoScriptFrontendController $controller = null)
+    public function __construct(TypoScriptFrontendController $controller)
     {
-        $this->controller = $controller ?: $GLOBALS['TSFE'];
+        $this->controller = $controller;
     }
 
     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
index dc5e5de..3fd37fe 100644 (file)
@@ -23,8 +23,6 @@ use TYPO3\CMS\Core\Localization\Locales;
 use TYPO3\CMS\Core\Routing\SiteMatcher;
 use TYPO3\CMS\Core\Routing\SiteRouteResult;
 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
-use TYPO3\CMS\Core\Site\SiteFinder;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Identifies if a site is configured for the request, based on "id" and "L" GET/POST parameters, or the requested
@@ -40,12 +38,9 @@ class SiteResolver implements MiddlewareInterface
      */
     protected $matcher;
 
-    public function __construct(SiteMatcher $matcher = null)
+    public function __construct(SiteMatcher $matcher)
     {
-        $this->matcher = $matcher ?? GeneralUtility::makeInstance(
-            SiteMatcher::class,
-            GeneralUtility::makeInstance(SiteFinder::class)
-        );
+        $this->matcher = $matcher;
     }
 
     /**
index be1048c..80cb9fc 100644 (file)
@@ -27,7 +27,6 @@ use TYPO3\CMS\Core\Resource\File;
 use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException;
 use TYPO3\CMS\Core\Routing\RouterInterface;
 use TYPO3\CMS\Core\Site\Entity\Site;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
  * Resolves static routes - can return configured content directly or load content from file / urls
@@ -35,6 +34,24 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 class StaticRouteResolver implements MiddlewareInterface
 {
     /**
+     * @var RequestFactory
+     */
+    protected $requestFactory;
+
+    /**
+     * @var LinkService
+     */
+    protected $linkService;
+
+    public function __construct(
+        RequestFactory $requestFactory,
+        LinkService $linkService
+    ) {
+        $this->requestFactory = $requestFactory;
+        $this->linkService = $linkService;
+    }
+
+    /**
      * Checks if there is a valid site with route configuration.
      *
      * @param ServerRequestInterface $request
@@ -83,8 +100,7 @@ class StaticRouteResolver implements MiddlewareInterface
      */
     protected function getFromUri(string $uri): array
     {
-        $requestFactory = GeneralUtility::makeInstance(RequestFactory::class);
-        $response = $requestFactory->request($uri);
+        $response = $this->requestFactory->request($uri);
         $contentType = 'text/plain; charset=utf-8';
         $content = '';
         if ($response->getStatusCode() === 200) {
@@ -129,8 +145,7 @@ class StaticRouteResolver implements MiddlewareInterface
                 $contentType = 'text/plain; charset=utf-8';
                 break;
             case 'uri':
-                $linkService = GeneralUtility::makeInstance(LinkService::class);
-                $urlParams = $linkService->resolve($routeConfig['source']);
+                $urlParams = $this->linkService->resolve($routeConfig['source']);
                 if ($urlParams['type'] === 'url' || $urlParams['type'] === 'page') {
                     $uri = $urlParams['url'] ?? $this->getPageUri($request, $site, $urlParams);
                     [$content, $contentType] = $this->getFromUri($uri);
index 79abaff..f28c800 100644 (file)
@@ -20,7 +20,6 @@ use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Server\MiddlewareInterface;
 use Psr\Http\Server\RequestHandlerInterface;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 
 /**
@@ -31,6 +30,16 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 class TimeTrackerInitialization implements MiddlewareInterface
 {
     /**
+     * @var TimeTracker
+     */
+    protected $timeTracker;
+
+    public function __construct(TimeTracker $timeTracker)
+    {
+        $this->timeTracker = $timeTracker;
+    }
+
+    /**
      * Starting time tracking (by setting up a singleton object)
      *
      * @param ServerRequestInterface $request
@@ -40,21 +49,18 @@ class TimeTrackerInitialization implements MiddlewareInterface
     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
     {
         $timeTrackingEnabled = $this->isBackendUserCookieSet($request);
-        $timeTracker = GeneralUtility::makeInstance(
-            TimeTracker::class,
-            $timeTrackingEnabled
-        );
-        $timeTracker->start(microtime(true));
-        $timeTracker->push('');
+        $this->timeTracker->setEnabled($timeTrackingEnabled);
+        $this->timeTracker->start(microtime(true));
+        $this->timeTracker->push('');
 
         $response = $handler->handle($request);
 
         // Finish time tracking
-        $timeTracker->pull();
-        $timeTracker->finish();
+        $this->timeTracker->pull();
+        $this->timeTracker->finish();
 
         if ($this->isDebugModeEnabled()) {
-            return $response->withHeader('X-TYPO3-Parsetime', $timeTracker->getParseTime() . 'ms');
+            return $response->withHeader('X-TYPO3-Parsetime', $this->timeTracker->getParseTime() . 'ms');
         }
         return $response;
     }
index 44b746e..3111624 100644 (file)
@@ -44,6 +44,16 @@ use TYPO3\CMS\Frontend\Page\PageAccessFailureReasons;
 class TypoScriptFrontendInitialization implements MiddlewareInterface
 {
     /**
+     * @var Context
+     */
+    protected $context;
+
+    public function __construct(Context $context)
+    {
+        $this->context = $context;
+    }
+
+    /**
      * Creates an instance of TSFE and sets it as a global variable.
      *
      * @param ServerRequestInterface $request
@@ -65,12 +75,11 @@ class TypoScriptFrontendInitialization implements MiddlewareInterface
                 ['code' => PageAccessFailureReasons::INVALID_PAGE_ARGUMENTS]
             );
         }
-        $context = GeneralUtility::makeInstance(Context::class);
-        $context->setAspect('frontend.preview', GeneralUtility::makeInstance(PreviewAspect::class));
+        $this->context->setAspect('frontend.preview', GeneralUtility::makeInstance(PreviewAspect::class));
 
         $controller = GeneralUtility::makeInstance(
             TypoScriptFrontendController::class,
-            $context,
+            $this->context,
             $site,
             $request->getAttribute('language', $site->getDefaultLanguage()),
             $pageArguments,
@@ -90,7 +99,7 @@ class TypoScriptFrontendInitialization implements MiddlewareInterface
         if ($controller->isBackendUserLoggedIn() && !$GLOBALS['BE_USER']->doesUserHaveAccess($controller->page, Permission::PAGE_SHOW)) {
             unset($GLOBALS['BE_USER']);
             // Register an empty backend user as aspect
-            $this->setBackendUserAspect($context, null);
+            $this->setBackendUserAspect(null);
             $controller->determineId();
         }
 
@@ -102,12 +111,11 @@ class TypoScriptFrontendInitialization implements MiddlewareInterface
     /**
      * Register the backend user as aspect
      *
-     * @param Context $context
      * @param BackendUserAuthentication|null $user
      */
-    protected function setBackendUserAspect(Context $context, ?BackendUserAuthentication $user): void
+    protected function setBackendUserAspect(BackendUserAuthentication $user): void
     {
-        $context->setAspect('backend.user', GeneralUtility::makeInstance(UserAspect::class, $user));
-        $context->setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class, $user ? $user->workspace : 0));
+        $this->context->setAspect('backend.user', GeneralUtility::makeInstance(UserAspect::class, $user));
+        $this->context->setAspect('workspace', GeneralUtility::makeInstance(WorkspaceAspect::class, $user ? $user->workspace : 0));
     }
 }
index 698a216..dfed704 100644 (file)
@@ -24,24 +24,23 @@ use TYPO3\CMS\Core\Http\Response;
 use TYPO3\CMS\Core\Http\ServerRequest;
 use TYPO3\CMS\Core\Routing\PageArguments;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 use TYPO3\CMS\Frontend\Middleware\PageArgumentValidator;
 use TYPO3\CMS\Frontend\Middleware\PageResolver;
+use TYPO3\CMS\Frontend\Page\CacheHashCalculator;
 use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 class PageArgumentValidatorTest extends UnitTestCase
 {
     /**
-     * @var bool Reset singletons created by subject
+     * @var CacheHashCaluclator
      */
-    protected $resetSingletonInstances = true;
+    protected $cacheHashCalculator;
 
     /**
-     * @var TypoScriptFrontendController|AccessibleObjectInterface
+     * @var TimeTracker
      */
-    protected $controller;
+    protected $timeTrackerStub;
 
     /**
      * @var RequestHandlerInterface
@@ -56,9 +55,8 @@ class PageArgumentValidatorTest extends UnitTestCase
     protected function setUp(): void
     {
         parent::setUp();
-        $timeTrackerStub = new TimeTracker(false);
-        GeneralUtility::setSingletonInstance(TimeTracker::class, $timeTrackerStub);
-        $this->controller = $this->getAccessibleMock(TypoScriptFrontendController::class, ['dummy'], [], '', false);
+        $this->timeTrackerStub = new TimeTracker(false);
+        $this->cacheHashCalculator = new CacheHashCalculator;
 
         // A request handler which only runs through
         $this->responseOutputHandler = new class implements RequestHandlerInterface {
@@ -82,7 +80,7 @@ class PageArgumentValidatorTest extends UnitTestCase
         $request = new ServerRequest($incomingUrl, 'GET');
         $request = $request->withAttribute('routing', $pageArguments);
 
-        $subject = new PageArgumentValidator($this->controller);
+        $subject = new PageArgumentValidator($this->cacheHashCalculator, $this->timeTrackerStub);
         $subject->setLogger(new NullLogger());
 
         $response = $subject->process($request, $this->responseOutputHandler);
@@ -102,7 +100,7 @@ class PageArgumentValidatorTest extends UnitTestCase
         $request = new ServerRequest($incomingUrl, 'GET');
         $request = $request->withAttribute('routing', $pageArguments);
 
-        $subject = new PageArgumentValidator($this->controller);
+        $subject = new PageArgumentValidator($this->cacheHashCalculator, $this->timeTrackerStub);
         $response = $subject->process($request, $this->responseOutputHandler);
         static::assertEquals(404, $response->getStatusCode());
     }
@@ -115,7 +113,7 @@ class PageArgumentValidatorTest extends UnitTestCase
         $incomingUrl = 'https://king.com/lotus-flower/en/mr-magpie/bloom/';
         $request = new ServerRequest($incomingUrl, 'GET');
 
-        $subject = new PageArgumentValidator($this->controller);
+        $subject = new PageArgumentValidator($this->cacheHashCalculator, $this->timeTrackerStub);
         $response = $subject->process($request, $this->responseOutputHandler);
         static::assertEquals(404, $response->getStatusCode());
     }
@@ -132,7 +130,7 @@ class PageArgumentValidatorTest extends UnitTestCase
         $request = new ServerRequest($incomingUrl, 'GET');
         $request = $request->withAttribute('routing', $pageArguments);
 
-        $subject = new PageArgumentValidator($this->controller);
+        $subject = new PageArgumentValidator($this->cacheHashCalculator, $this->timeTrackerStub);
         $response = $subject->process($request, $this->responseOutputHandler);
         static::assertEquals(200, $response->getStatusCode());
     }
@@ -149,7 +147,7 @@ class PageArgumentValidatorTest extends UnitTestCase
         $request = new ServerRequest($incomingUrl, 'GET');
         $request = $request->withAttribute('routing', $pageArguments);
 
-        $subject = new PageArgumentValidator($this->controller);
+        $subject = new PageArgumentValidator($this->cacheHashCalculator, $this->timeTrackerStub);
         $response = $subject->process($request, $this->responseOutputHandler);
         static::assertEquals(404, $response->getStatusCode());
     }
index 451cf82..b4a081d 100644 (file)
@@ -29,9 +29,8 @@ use TYPO3\CMS\Core\Http\HtmlResponse;
 use TYPO3\CMS\Core\Http\JsonResponse;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
+use TYPO3\CMS\Core\Package\FailsafePackageManager;
 use TYPO3\CMS\Core\Package\PackageInterface;
-use TYPO3\CMS\Core\Package\PackageManager;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Install\Authentication\AuthenticationService;
 use TYPO3\CMS\Install\Controller\AbstractController;
 use TYPO3\CMS\Install\Controller\EnvironmentController;
@@ -52,11 +51,21 @@ use TYPO3\CMS\Install\Service\SessionService;
 class Maintenance implements MiddlewareInterface
 {
     /**
+     * @var FailsafePackageManager
+     */
+    protected $packageManager;
+
+    /**
      * @var ConfigurationManager
      */
     protected $configurationManager;
 
     /**
+     * @var PasswordHashFactory
+     */
+    protected $passwordHashFactory;
+
+    /**
      * @var ContainerInterface
      */
     private $container;
@@ -74,12 +83,15 @@ class Maintenance implements MiddlewareInterface
         'environment' => EnvironmentController::class,
     ];
 
-    /**
-     * @param ConfigurationManager $configurationManager
-     */
-    public function __construct(ConfigurationManager $configurationManager, ContainerInterface $container)
-    {
+    public function __construct(
+        FailsafePackageManager $packageManager,
+        ConfigurationManager $configurationManager,
+        PasswordHashFactory $passwordHashFactory,
+        ContainerInterface $container
+    ) {
+        $this->packageManager = $packageManager;
         $this->configurationManager = $configurationManager;
+        $this->passwordHashFactory = $passwordHashFactory;
         $this->container = $container;
     }
 
@@ -152,7 +164,7 @@ class Maintenance implements MiddlewareInterface
                         new FlashMessage('Please enter the install tool password', '', FlashMessage::ERROR)
                     );
                 } else {
-                    $hashInstance = GeneralUtility::makeInstance(PasswordHashFactory::class)->getDefaultHashInstance('BE');
+                    $hashInstance = $this->passwordHashFactory->getDefaultHashInstance('BE');
                     $hashedPassword = $hashInstance->getHashedPassword($password);
                     $messageQueue = (new FlashMessageQueue('install'))->enqueue(
                         new FlashMessage(
@@ -328,18 +340,13 @@ class Maintenance implements MiddlewareInterface
     protected function recreatePackageStatesFileIfMissing(): void
     {
         if (!file_exists(Environment::getLegacyConfigPath() . '/PackageStates.php')) {
-            // We need a FailsafePackageManager at this moment, however this is given
-            // As Bootstrap is registering the FailsafePackageManager object as a singleton instance
-            // of the main PackageManager class. See \TYPO3\CMS\Core\Core\Bootstrap::init()
-            /** @var \TYPO3\CMS\Core\Package\FailsafePackageManager $packageManager */
-            $packageManager = GeneralUtility::makeInstance(PackageManager::class);
-            $packages = $packageManager->getAvailablePackages();
+            $packages = $this->packageManager->getAvailablePackages();
             foreach ($packages as $package) {
                 if ($package instanceof PackageInterface && $package->isPartOfMinimalUsableSystem()) {
-                    $packageManager->activatePackage($package->getPackageKey());
+                    $this->packageManager->activatePackage($package->getPackageKey());
                 }
             }
-            $packageManager->forceSortAndSavePackageStates();
+            $this->packageManager->forceSortAndSavePackageStates();
         }
     }
 }
index c42e51f..e9689df 100644 (file)
@@ -18,6 +18,7 @@ namespace TYPO3\CMS\Install;
 use Psr\Container\ContainerInterface;
 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
 use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory;
 use TYPO3\CMS\Core\DependencyInjection\ContainerBuilder;
 use TYPO3\CMS\Core\Http\MiddlewareDispatcher;
 use TYPO3\CMS\Core\Package\AbstractServiceProvider;
@@ -84,7 +85,9 @@ class ServiceProvider extends AbstractServiceProvider
     public static function getMaintenanceMiddleware(ContainerInterface $container): Middleware\Maintenance
     {
         return new Middleware\Maintenance(
+            $container->get(PackageManager::class),
             $container->get(ConfigurationManager::class),
+            $container->get(PasswordHashFactory::class),
             $container
         );
     }