Commit fb59fbc9 authored by Benni Mack's avatar Benni Mack Committed by Oliver Bartsch
Browse files

[TASK] Use DependencyInjection in FileController

This change registers FileController as backend
controller in Services.yaml and allows to inject
all needed dependency via constructor DI.

Resolves: #94696
Releases: master
Change-Id: Idc14d1ef86bcbd5c4da77f3101b5a97f2a6aa6c3
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70188

Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Jochen's avatarJochen <rothjochen@gmail.com>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
Reviewed-by: Jochen's avatarJochen <rothjochen@gmail.com>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <bo@cedev.de>
parent 65cc0bfd
...@@ -23,7 +23,6 @@ use TYPO3\CMS\Backend\Clipboard\Clipboard; ...@@ -23,7 +23,6 @@ use TYPO3\CMS\Backend\Clipboard\Clipboard;
use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException; use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException;
use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Http\HtmlResponse; use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Http\JsonResponse; use TYPO3\CMS\Core\Http\JsonResponse;
use TYPO3\CMS\Core\Http\RedirectResponse; use TYPO3\CMS\Core\Http\RedirectResponse;
...@@ -66,7 +65,7 @@ class FileController ...@@ -66,7 +65,7 @@ class FileController
* Defines behaviour when uploading files with names that already exist; possible values are * Defines behaviour when uploading files with names that already exist; possible values are
* the values of the \TYPO3\CMS\Core\Resource\DuplicationBehavior enumeration * the values of the \TYPO3\CMS\Core\Resource\DuplicationBehavior enumeration
* *
* @var \TYPO3\CMS\Core\Resource\DuplicationBehavior * @var DuplicationBehavior
*/ */
protected $overwriteExistingFiles; protected $overwriteExistingFiles;
...@@ -77,14 +76,6 @@ class FileController ...@@ -77,14 +76,6 @@ class FileController
*/ */
protected $redirect; protected $redirect;
/**
* Internal, dynamic:
* File processor object
*
* @var ExtendedFileUtility
*/
protected $fileProcessor;
/** /**
* The result array from the file processor * The result array from the file processor
* *
...@@ -92,13 +83,26 @@ class FileController ...@@ -92,13 +83,26 @@ class FileController
*/ */
protected $fileData; protected $fileData;
protected ExtendedFileUtility $fileProcessor;
protected ResourceFactory $fileFactory;
protected IconFactory $iconFactory;
protected UriBuilder $uriBuilder;
public function __construct(ResourceFactory $resourceFactory, ExtendedFileUtility $fileProcessor, IconFactory $iconFactory, UriBuilder $uriBuilder)
{
$this->fileFactory = $resourceFactory;
$this->fileProcessor = $fileProcessor;
$this->iconFactory = $iconFactory;
$this->uriBuilder = $uriBuilder;
}
/** /**
* Injects the request object for the current request or subrequest * Injects the request object for the current request or subrequest
* As this controller goes only through the main() method, it just redirects to the given URL afterwards. * As this controller goes only through the main() method, it just redirects to the given URL afterwards.
* *
* @param ServerRequestInterface $request the current request * @param ServerRequestInterface $request the current request
* @return ResponseInterface the response with the content * @return ResponseInterface the response with the content
* @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException * @throws RouteNotFoundException
*/ */
public function mainAction(ServerRequestInterface $request): ResponseInterface public function mainAction(ServerRequestInterface $request): ResponseInterface
{ {
...@@ -186,8 +190,7 @@ class FileController ...@@ -186,8 +190,7 @@ class FileController
$fileName = $request->getParsedBody()['fileName'] ?? $request->getQueryParams()['fileName'] ?? null; $fileName = $request->getParsedBody()['fileName'] ?? $request->getQueryParams()['fileName'] ?? null;
$fileTarget = $request->getParsedBody()['fileTarget'] ?? $request->getQueryParams()['fileTarget'] ?? null; $fileTarget = $request->getParsedBody()['fileTarget'] ?? $request->getQueryParams()['fileTarget'] ?? null;
$fileFactory = GeneralUtility::makeInstance(ResourceFactory::class); $fileTargetObject = $this->fileFactory->retrieveFileOrFolderObject($fileTarget);
$fileTargetObject = $fileFactory->retrieveFileOrFolderObject($fileTarget);
$processedFileName = $fileTargetObject->getStorage()->sanitizeFileName($fileName, $fileTargetObject); $processedFileName = $fileTargetObject->getStorage()->sanitizeFileName($fileName, $fileTargetObject);
$result = []; $result = [];
...@@ -232,7 +235,6 @@ class FileController ...@@ -232,7 +235,6 @@ class FileController
$this->overwriteExistingFiles = DuplicationBehavior::cast($parsedBody['overwriteExistingFiles'] ?? $queryParams['overwriteExistingFiles'] ?? null); $this->overwriteExistingFiles = DuplicationBehavior::cast($parsedBody['overwriteExistingFiles'] ?? $queryParams['overwriteExistingFiles'] ?? null);
} }
$this->initClipboard(); $this->initClipboard();
$this->fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class);
} }
/** /**
...@@ -260,7 +262,6 @@ class FileController ...@@ -260,7 +262,6 @@ class FileController
*/ */
protected function main(): void protected function main(): void
{ {
// Initializing:
$this->fileProcessor->setActionPermissions(); $this->fileProcessor->setActionPermissions();
$this->fileProcessor->setExistingFilesConflictMode($this->overwriteExistingFiles); $this->fileProcessor->setExistingFilesConflictMode($this->overwriteExistingFiles);
$this->fileProcessor->start($this->file); $this->fileProcessor->start($this->file);
...@@ -272,7 +273,7 @@ class FileController ...@@ -272,7 +273,7 @@ class FileController
* *
* @param File $file to be edited * @param File $file to be edited
* @return string|null URI to be redirected to * @return string|null URI to be redirected to
* @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException * @throws RouteNotFoundException
*/ */
protected function getFileEditRedirect(File $file): ?string protected function getFileEditRedirect(File $file): ?string
{ {
...@@ -286,9 +287,8 @@ class FileController ...@@ -286,9 +287,8 @@ class FileController
if ($this->redirect) { if ($this->redirect) {
$urlParameters['returnUrl'] = $this->redirect; $urlParameters['returnUrl'] = $this->redirect;
} }
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
try { try {
return (string)$uriBuilder->buildUriFromRoute('file_edit', $urlParameters); return (string)$this->uriBuilder->buildUriFromRoute('file_edit', $urlParameters);
} catch (RouteNotFoundException $exception) { } catch (RouteNotFoundException $exception) {
// no route for editing files available // no route for editing files available
return ''; return '';
...@@ -314,12 +314,11 @@ class FileController ...@@ -314,12 +314,11 @@ class FileController
$thumbUrl = PathUtility::getAbsoluteWebPath($processedFile->getPublicUrl() ?? ''); $thumbUrl = PathUtility::getAbsoluteWebPath($processedFile->getPublicUrl() ?? '');
} }
} }
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$result = array_merge( $result = array_merge(
$result->toArray(), $result->toArray(),
[ [
'date' => BackendUtility::date($result->getModificationTime()), 'date' => BackendUtility::date($result->getModificationTime()),
'icon' => $iconFactory->getIconForFileExtension($result->getExtension(), Icon::SIZE_SMALL)->render(), 'icon' => $this->iconFactory->getIconForFileExtension($result->getExtension(), Icon::SIZE_SMALL)->render(),
'thumbUrl' => $thumbUrl 'thumbUrl' => $thumbUrl
] ]
); );
...@@ -329,14 +328,4 @@ class FileController ...@@ -329,14 +328,4 @@ class FileController
return $result; return $result;
} }
/**
* Returns the current BE user.
*
* @return BackendUserAuthentication
*/
protected function getBackendUser(): BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
}
} }
...@@ -119,6 +119,9 @@ services: ...@@ -119,6 +119,9 @@ services:
TYPO3\CMS\Backend\Controller\ContentElement\NewContentElementController: TYPO3\CMS\Backend\Controller\ContentElement\NewContentElementController:
tags: ['backend.controller'] tags: ['backend.controller']
TYPO3\CMS\Backend\Controller\File\FileController:
tags: ['backend.controller']
TYPO3\CMS\Backend\Form\FormDataProvider\SiteDatabaseEditRow: TYPO3\CMS\Backend\Form\FormDataProvider\SiteDatabaseEditRow:
public: true public: true
......
...@@ -18,14 +18,11 @@ namespace TYPO3\CMS\Backend\Tests\Unit\Controller\File; ...@@ -18,14 +18,11 @@ namespace TYPO3\CMS\Backend\Tests\Unit\Controller\File;
use Prophecy\Argument; use Prophecy\Argument;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Controller\File\FileController; use TYPO3\CMS\Backend\Controller\File\FileController;
use TYPO3\CMS\Core\Http\Response;
use TYPO3\CMS\Core\Http\ServerRequest;
use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Resource\File; use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\Resource\Folder; use TYPO3\CMS\Core\Resource\Folder;
use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility; use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase; use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
/** /**
...@@ -34,30 +31,25 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase; ...@@ -34,30 +31,25 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
class FileControllerTest extends UnitTestCase class FileControllerTest extends UnitTestCase
{ {
/** /**
* @var \TYPO3\CMS\Core\Resource\File|\PHPUnit\Framework\MockObject\MockObject * @var File|\PHPUnit\Framework\MockObject\MockObject
*/ */
protected $fileResourceMock; protected $fileResourceMock;
/** /**
* @var \TYPO3\CMS\Core\Resource\Folder|\PHPUnit\Framework\MockObject\MockObject * @var Folder|\PHPUnit\Framework\MockObject\MockObject
*/ */
protected $folderResourceMock; protected $folderResourceMock;
/** /**
* @var \TYPO3\CMS\Core\Utility\File\ExtendedFileUtility|\PHPUnit\Framework\MockObject\MockObject * @var ExtendedFileUtility|\PHPUnit\Framework\MockObject\MockObject
*/ */
protected $mockFileProcessor; protected $mockFileProcessor;
/** /**
* @var ServerRequest|\PHPUnit\Framework\MockObject\MockObject * @var ServerRequestInterface
*/ */
protected $request; protected $request;
/**
* @var Response|\PHPUnit\Framework\MockObject\MockObject
*/
protected $response;
/** /**
* Sets up this test case. * Sets up this test case.
*/ */
...@@ -81,10 +73,7 @@ class FileControllerTest extends UnitTestCase ...@@ -81,10 +73,7 @@ class FileControllerTest extends UnitTestCase
$this->fileResourceMock->expects(self::any())->method('getExtension')->willReturn('html'); $this->fileResourceMock->expects(self::any())->method('getExtension')->willReturn('html');
$serverRequest = $this->prophesize(ServerRequestInterface::class); $serverRequest = $this->prophesize(ServerRequestInterface::class);
$GLOBALS['TYPO3_REQUEST'] = $serverRequest->reveal(); $this->request = $serverRequest->reveal();
$this->request = new ServerRequest();
$this->response = new Response();
} }
/** /**
...@@ -92,7 +81,7 @@ class FileControllerTest extends UnitTestCase ...@@ -92,7 +81,7 @@ class FileControllerTest extends UnitTestCase
*/ */
public function flattenResultDataValueReturnsAnythingElseAsIs() public function flattenResultDataValueReturnsAnythingElseAsIs()
{ {
$subject = $this->getAccessibleMock(FileController::class, ['dummy']); $subject = $this->getAccessibleMock(FileController::class, ['init', 'main'], [], '', false);
self::assertTrue($subject->_call('flattenResultDataValue', true)); self::assertTrue($subject->_call('flattenResultDataValue', true));
self::assertSame([], $subject->_call('flattenResultDataValue', [])); self::assertSame([], $subject->_call('flattenResultDataValue', []));
} }
...@@ -102,13 +91,12 @@ class FileControllerTest extends UnitTestCase ...@@ -102,13 +91,12 @@ class FileControllerTest extends UnitTestCase
*/ */
public function flattenResultDataValueFlattensFile() public function flattenResultDataValueFlattensFile()
{ {
$subject = $this->getAccessibleMock(FileController::class, ['dummy']); $subject = $this->getAccessibleMock(FileController::class, ['init', 'main'], [], '', false);
$iconFactoryProphecy = $this->prophesize(IconFactory::class); $iconFactoryProphecy = $this->prophesize(IconFactory::class);
GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal());
$iconProphecy = $this->prophesize(Icon::class); $iconProphecy = $this->prophesize(Icon::class);
$iconProphecy->render()->shouldBeCalled()->willReturn(''); $iconProphecy->render()->shouldBeCalled()->willReturn('');
$iconFactoryProphecy->getIconForFileExtension(Argument::cetera())->willReturn($iconProphecy->reveal()); $iconFactoryProphecy->getIconForFileExtension(Argument::cetera())->willReturn($iconProphecy->reveal());
$subject->_set('iconFactory', $iconFactoryProphecy->reveal());
$result = $subject->_call('flattenResultDataValue', $this->fileResourceMock); $result = $subject->_call('flattenResultDataValue', $this->fileResourceMock);
self::assertSame( self::assertSame(
...@@ -127,16 +115,13 @@ class FileControllerTest extends UnitTestCase ...@@ -127,16 +115,13 @@ class FileControllerTest extends UnitTestCase
*/ */
public function processAjaxRequestDeleteProcessActuallyDoesNotChangeFileData() public function processAjaxRequestDeleteProcessActuallyDoesNotChangeFileData()
{ {
$subject = $this->getAccessibleMock(FileController::class, ['init', 'main']); $subject = $this->getAccessibleMock(FileController::class, ['init', 'main'], [], '', false);
$fileData = ['delete' => [true]]; $fileData = ['delete' => [true]];
$subject->_set('fileProcessor', $this->mockFileProcessor); $subject->_set('fileProcessor', $this->mockFileProcessor);
$subject->_set('fileData', $fileData); $subject->_set('fileData', $fileData);
$subject->_set('redirect', false); $subject->_set('redirect', false);
$subject->expects(self::once())->method('main'); $subject->expects(self::once())->method('main');
$subject->processAjaxRequest($this->request);
$subject->processAjaxRequest($this->request, $this->response);
} }
/** /**
...@@ -144,16 +129,13 @@ class FileControllerTest extends UnitTestCase ...@@ -144,16 +129,13 @@ class FileControllerTest extends UnitTestCase
*/ */
public function processAjaxRequestEditFileProcessActuallyDoesNotChangeFileData() public function processAjaxRequestEditFileProcessActuallyDoesNotChangeFileData()
{ {
$subject = $this->getAccessibleMock(FileController::class, ['init', 'main']); $subject = $this->getAccessibleMock(FileController::class, ['init', 'main'], [], '', false);
$fileData = ['editfile' => [true]]; $fileData = ['editfile' => [true]];
$subject->_set('fileProcessor', $this->mockFileProcessor); $subject->_set('fileProcessor', $this->mockFileProcessor);
$subject->_set('fileData', $fileData); $subject->_set('fileData', $fileData);
$subject->_set('redirect', false); $subject->_set('redirect', false);
$subject->expects(self::once())->method('main'); $subject->expects(self::once())->method('main');
$subject->processAjaxRequest($this->request);
$subject->processAjaxRequest($this->request, $this->response);
} }
/** /**
...@@ -161,15 +143,13 @@ class FileControllerTest extends UnitTestCase ...@@ -161,15 +143,13 @@ class FileControllerTest extends UnitTestCase
*/ */
public function processAjaxRequestReturnsStatus200IfNoErrorOccurs() public function processAjaxRequestReturnsStatus200IfNoErrorOccurs()
{ {
$subject = $this->getAccessibleMock(FileController::class, ['init', 'main']); $subject = $this->getAccessibleMock(FileController::class, ['init', 'main'], [], '', false);
$fileData = ['editfile' => [true]]; $fileData = ['editfile' => [true]];
$subject->_set('fileProcessor', $this->mockFileProcessor); $subject->_set('fileProcessor', $this->mockFileProcessor);
$subject->_set('fileData', $fileData); $subject->_set('fileData', $fileData);
$subject->_set('redirect', false); $subject->_set('redirect', false);
$response = $subject->processAjaxRequest($this->request);
$result = $subject->processAjaxRequest($this->request, $this->response); self::assertEquals(200, $response->getStatusCode());
self::assertEquals(200, $result->getStatusCode());
} }
/** /**
...@@ -177,10 +157,10 @@ class FileControllerTest extends UnitTestCase ...@@ -177,10 +157,10 @@ class FileControllerTest extends UnitTestCase
*/ */
public function processAjaxRequestReturnsStatus500IfErrorOccurs() public function processAjaxRequestReturnsStatus500IfErrorOccurs()
{ {
$subject = $this->getAccessibleMock(FileController::class, ['init', 'main']);
$this->mockFileProcessor->expects(self::any())->method('getErrorMessages')->willReturn(['error occurred']); $this->mockFileProcessor->expects(self::any())->method('getErrorMessages')->willReturn(['error occurred']);
$subject = $this->getAccessibleMock(FileController::class, ['init', 'main'], [], '', false);
$subject->_set('fileProcessor', $this->mockFileProcessor); $subject->_set('fileProcessor', $this->mockFileProcessor);
$result = $subject->processAjaxRequest($this->request, $this->response); $response = $subject->processAjaxRequest($this->request);
self::assertEquals(500, $result->getStatusCode()); self::assertEquals(500, $response->getStatusCode());
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment