‪TYPO3CMS  ‪main
FileController.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\ResponseInterface;
21 use Psr\Http\Message\ServerRequestInterface;
26 use TYPO3\CMS\Backend\Utility\BackendUtility;
31 use TYPO3\CMS\Core\Imaging\IconSize;
41 
48 #[AsController]
50 {
56  protected ‪$file;
57 
63  protected ‪$CB;
64 
69 
75  protected ‪$redirect;
76 
82  protected ‪$fileData;
83 
84  public function ‪__construct(
85  protected readonly ‪ResourceFactory $fileFactory,
86  protected readonly ‪ExtendedFileUtility $fileProcessor,
87  protected readonly ‪IconFactory $iconFactory,
88  protected readonly ‪UriBuilder $uriBuilder,
89  protected readonly ‪FlashMessageService $flashMessageService
90  ) {}
91 
100  public function ‪mainAction(ServerRequestInterface $request): ResponseInterface
101  {
102  $this->‪init($request);
103  $this->‪main();
104 
105  BackendUtility::setUpdateSignal('updateFolderTree');
106 
107  // go and edit the new created file
108  if ($request->getParsedBody()['edit'] ?? '') {
110  ‪$file = $this->fileData['newfile'][0];
111  if (‪$file !== null) {
112  $this->redirect = $this->‪getFileEditRedirect(‪$file) ?? ‪$this->redirect;
113  }
114  }
115  if ($this->redirect) {
116  return new ‪RedirectResponse(
117  GeneralUtility::locationHeaderUrl($this->redirect),
118  303
119  );
120  }
121  // empty response
122  return new ‪HtmlResponse('');
123  }
124 
129  public function ‪processAjaxRequest(ServerRequestInterface $request): ResponseInterface
130  {
131  $this->‪init($request);
132  $this->‪main();
133  $flatResult = [
134  'hasErrors' => false,
135  ];
136  foreach ($this->fileData as $action => $results) {
137  foreach ($results as $result) {
138  if (is_array($result)) {
139  foreach ($result as $subResult) {
140  $flatResult[$action][] = $this->‪flattenResultDataValue($subResult);
141  }
142  } else {
143  $flatResult[$action][] = $this->‪flattenResultDataValue($result);
144  }
145  }
146  }
147 
148  // Used in the FileStorageTree when moving / copying folders, or in the DragUploader
149  $messages = $this->flashMessageService->getMessageQueueByIdentifier()->getAllMessagesAndFlush();
150  if (!empty($messages)) {
151  foreach ($messages as $message) {
152  $flatResult['messages'][] = [
153  'title' => $message->getTitle(),
154  'message' => $message->getMessage(),
155  'severity' => $message->getSeverity(),
156  ];
157  if ($message->getSeverity() === ContextualFeedbackSeverity::ERROR) {
158  $flatResult['hasErrors'] = true;
159  }
160  }
161  }
162  return new ‪JsonResponse($flatResult, $flatResult['hasErrors'] ? 500 : 200);
163  }
164 
168  public function ‪fileExistsInFolderAction(ServerRequestInterface $request): ResponseInterface
169  {
170  $this->‪init($request);
171  $fileName = $request->getParsedBody()['fileName'] ?? $request->getQueryParams()['fileName'] ?? null;
172  $fileTarget = $request->getParsedBody()['fileTarget'] ?? $request->getQueryParams()['fileTarget'] ?? null;
173 
174  $fileTargetObject = $this->fileFactory->retrieveFileOrFolderObject($fileTarget);
175  $processedFileName = $fileTargetObject->getStorage()->sanitizeFileName($fileName, $fileTargetObject);
176 
177  $result = [];
178  if ($fileTargetObject->hasFile($processedFileName)) {
179  $fileInFolder = $fileTargetObject->getStorage()->getFileInFolder($processedFileName, $fileTargetObject);
180  if ($fileInFolder instanceof ‪File) {
181  $result = $this->‪flattenFileResultDataValue($fileInFolder);
182  }
183  }
184  return new ‪JsonResponse($result);
185  }
186 
190  protected function ‪init(ServerRequestInterface $request): void
191  {
192  // Set the GPvars from outside
193  $parsedBody = $request->getParsedBody();
194  $queryParams = $request->getQueryParams();
195  $this->file = (array)($parsedBody['data'] ?? $queryParams['data'] ?? []);
196  $redirectUrl = (string)($parsedBody['redirect'] ?? $queryParams['redirect'] ?? '');
197  if ($this->file === [] || $redirectUrl !== '') {
198  // This in clipboard mode or when a new folder is created
199  $this->redirect = GeneralUtility::sanitizeLocalUrl($redirectUrl);
200  } else {
201  $mode = key($this->file);
202  $elementKey = key($this->file[$mode]);
203  $this->redirect = GeneralUtility::sanitizeLocalUrl($this->file[$mode][$elementKey]['redirect'] ?? '');
204  }
205  $this->CB = (array)($parsedBody['CB'] ?? $queryParams['CB'] ?? []);
206 
207  if (isset($this->file['rename'][0]['conflictMode'])) {
208  $conflictMode = $this->file['rename'][0]['conflictMode'];
209  unset($this->file['rename'][0]['conflictMode']);
210  $this->overwriteExistingFiles = DuplicationBehavior::tryFrom($conflictMode) ?? ‪DuplicationBehavior::getDefaultDuplicationBehaviour();
211  } else {
212  $duplicationBehaviorFromRequest = $parsedBody['overwriteExistingFiles'] ?? $queryParams['overwriteExistingFiles'] ?? '';
213  $this->overwriteExistingFiles = DuplicationBehavior::tryFrom($duplicationBehaviorFromRequest) ?? ‪DuplicationBehavior::getDefaultDuplicationBehaviour();
214  }
215  $this->‪initClipboard($request);
216  }
217 
221  protected function ‪initClipboard(ServerRequestInterface $request): void
222  {
223  if ($this->CB !== []) {
224  $clipObj = GeneralUtility::makeInstance(Clipboard::class);
225  $clipObj->initializeClipboard($request);
226  if ($this->CB['paste'] ?? false) {
227  $clipObj->setCurrentPad((string)($this->CB['pad'] ?? ''));
228  $this->‪setPasteCmd($clipObj);
229  }
230  if ($this->CB['delete'] ?? false) {
231  $clipObj->setCurrentPad((string)($this->CB['pad'] ?? ''));
232  $this->‪setDeleteCmd($clipObj);
233  }
234  }
235  }
236 
241  protected function ‪main(): void
242  {
243  $this->fileProcessor->setActionPermissions();
244  $this->fileProcessor->setExistingFilesConflictMode($this->overwriteExistingFiles);
245  $this->fileProcessor->start($this->file);
246  $this->fileData = $this->fileProcessor->processData();
247  }
248 
256  protected function ‪getFileEditRedirect(‪File ‪$file): ?string
257  {
258  if (!‪$file->isTextFile()) {
259  return null;
260  }
261  ‪$properties = ‪$file->getProperties();
262  $urlParameters = [
263  'target' => ‪$properties['storage'] . ':' . ‪$properties['identifier'],
264  ];
265  if ($this->redirect) {
266  $urlParameters['returnUrl'] = ‪$this->redirect;
267  }
268  try {
269  return (string)$this->uriBuilder->buildUriFromRoute('file_edit', $urlParameters);
270  } catch (RouteNotFoundException $exception) {
271  // no route for editing files available
272  return '';
273  }
274  }
275 
276  protected function ‪flattenFileResultDataValue(‪File $result): array
277  {
278  $thumbUrl = $result->‪isImage()
279  ? ($result->‪process(‪ProcessedFile::CONTEXT_IMAGEPREVIEW, [])->getPublicUrl() ?? '')
280  : '';
281  $path = '';
282  if (is_callable([$result->‪getParentFolder(), 'getReadablePath'])) {
283  $path = $result->‪getParentFolder()->getReadablePath();
284  }
285  return array_merge(
286  $result->toArray(),
287  [
288  'date' => BackendUtility::date($result->‪getModificationTime()),
289  'icon' => $this->iconFactory->getIconForFileExtension($result->‪getExtension(), IconSize::SMALL)->render(),
290  'thumbUrl' => $thumbUrl,
291  'path' => $path,
292  ]
293  );
294  }
295 
305  protected function ‪flattenResultDataValue($result)
306  {
307  if ($result instanceof File) {
308  $result = $this->‪flattenFileResultDataValue($result);
309  } elseif ($result instanceof Folder) {
310  $result = $result->getIdentifier();
311  }
312 
313  return $result;
314  }
315 
319  protected function ‪setPasteCmd(‪Clipboard $clipboard): void
320  {
321  $target = explode('|', (string)$this->CB['paste'])[1] ?? '';
322  $mode = $clipboard->‪currentMode() === 'copy' ? 'copy' : 'move';
323  // Traverse elements and make CMD array
324  foreach ($clipboard->‪elFromTable('_FILE') as $key => $path) {
325  $this->file[$mode][] = ['data' => $path, 'target' => $target];
326  if ($mode === 'move') {
327  $clipboard->‪removeElement($key);
328  }
329  }
330  $clipboard->‪endClipboard();
331  }
332 
336  protected function ‪setDeleteCmd(‪Clipboard $clipObj): void
337  {
338  // Traverse elements and make CMD array
339  foreach ($clipObj->‪elFromTable('_FILE') as $key => $path) {
340  $this->file['delete'][] = ['data' => $path];
341  $clipObj->‪removeElement($key);
342  }
343  $clipObj->‪endClipboard();
344  }
345 }
‪TYPO3\CMS\Backend\Controller\File\FileController\main
‪main()
Definition: FileController.php:237
‪TYPO3\CMS\Core\Resource\ProcessedFile\CONTEXT_IMAGEPREVIEW
‪const CONTEXT_IMAGEPREVIEW
Definition: ProcessedFile.php:55
‪TYPO3\CMS\Backend\Controller\File\FileController\init
‪init(ServerRequestInterface $request)
Definition: FileController.php:186
‪TYPO3\CMS\Backend\Controller\File\FileController\setDeleteCmd
‪setDeleteCmd(Clipboard $clipObj)
Definition: FileController.php:332
‪TYPO3\CMS\Backend\Clipboard\Clipboard
Definition: Clipboard.php:48
‪TYPO3\CMS\Core\Resource\AbstractFile\getParentFolder
‪getParentFolder()
Definition: AbstractFile.php:594
‪TYPO3\CMS\Backend\Controller\File\FileController\$redirect
‪string $redirect
Definition: FileController.php:72
‪TYPO3\CMS\Backend\Controller\File\FileController\$fileData
‪array $fileData
Definition: FileController.php:78
‪TYPO3\CMS\Core\Resource\AbstractFile\getExtension
‪getExtension()
Definition: AbstractFile.php:243
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Backend\Controller\File\FileController\mainAction
‪ResponseInterface mainAction(ServerRequestInterface $request)
Definition: FileController.php:96
‪TYPO3\CMS\Core\Resource\AbstractFile\isImage
‪bool isImage()
Definition: AbstractFile.php:301
‪TYPO3\CMS\Backend\Controller\File\FileController\setPasteCmd
‪setPasteCmd(Clipboard $clipboard)
Definition: FileController.php:315
‪TYPO3\CMS\Backend\Controller\File\FileController\$overwriteExistingFiles
‪DuplicationBehavior $overwriteExistingFiles
Definition: FileController.php:66
‪TYPO3\CMS\Core\Type\ContextualFeedbackSeverity
‪ContextualFeedbackSeverity
Definition: ContextualFeedbackSeverity.php:25
‪TYPO3\CMS\Core\Utility\File\ExtendedFileUtility
Definition: ExtendedFileUtility.php:76
‪TYPO3\CMS\Backend\Clipboard\Clipboard\currentMode
‪string currentMode()
Definition: Clipboard.php:656
‪TYPO3\CMS\Core\Resource\Enum\getDefaultDuplicationBehaviour
‪@ getDefaultDuplicationBehaviour
Definition: DuplicationBehavior.php:53
‪TYPO3\CMS\Backend\Controller\File\FileController\initClipboard
‪initClipboard(ServerRequestInterface $request)
Definition: FileController.php:217
‪TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
Definition: RouteNotFoundException.php:21
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:44
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:38
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:42
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:26
‪TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior
‪DuplicationBehavior
Definition: DuplicationBehavior.php:28
‪TYPO3\CMS\Backend\Clipboard\Clipboard\removeElement
‪removeElement(string $elementKey)
Definition: Clipboard.php:636
‪TYPO3\CMS\Backend\Controller\File\FileController\fileExistsInFolderAction
‪fileExistsInFolderAction(ServerRequestInterface $request)
Definition: FileController.php:164
‪TYPO3\CMS\Backend\Controller\File\FileController\__construct
‪__construct(protected readonly ResourceFactory $fileFactory, protected readonly ExtendedFileUtility $fileProcessor, protected readonly IconFactory $iconFactory, protected readonly UriBuilder $uriBuilder, protected readonly FlashMessageService $flashMessageService)
Definition: FileController.php:80
‪TYPO3\CMS\Backend\Clipboard\Clipboard\endClipboard
‪endClipboard()
Definition: Clipboard.php:207
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:30
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:47
‪TYPO3\CMS\Backend\Controller\File\FileController\flattenFileResultDataValue
‪flattenFileResultDataValue(File $result)
Definition: FileController.php:272
‪TYPO3\CMS\Backend\Controller\File\FileController\processAjaxRequest
‪processAjaxRequest(ServerRequestInterface $request)
Definition: FileController.php:125
‪TYPO3\CMS\Backend\Controller\File\FileController
Definition: FileController.php:50
‪TYPO3\CMS\Backend\Controller\File\FileController\flattenResultDataValue
‪bool string array flattenResultDataValue($result)
Definition: FileController.php:301
‪TYPO3\CMS\Core\Resource\File\process
‪process(string $taskType, array $configuration)
Definition: File.php:238
‪TYPO3\CMS\Backend\Controller\File\FileController\getFileEditRedirect
‪string null getFileEditRedirect(File $file)
Definition: FileController.php:252
‪TYPO3\CMS\Core\Http\JsonResponse
Definition: JsonResponse.php:28
‪TYPO3\CMS\Backend\Attribute\AsController
Definition: AsController.php:25
‪TYPO3\CMS\Core\Resource\AbstractFile\$properties
‪array $properties
Definition: AbstractFile.php:39
‪TYPO3\CMS\Backend\Controller\File
Definition: FileController.php:18
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Backend\Controller\File\FileController\$CB
‪array $CB
Definition: FileController.php:61
‪TYPO3\CMS\Core\Resource\AbstractFile\getModificationTime
‪getModificationTime()
Definition: AbstractFile.php:232
‪TYPO3\CMS\Backend\Controller\File\FileController\$file
‪array $file
Definition: FileController.php:55
‪TYPO3\CMS\Backend\Clipboard\Clipboard\elFromTable
‪array elFromTable(string $matchTable='', string $padIdentifier='')
Definition: Clipboard.php:699
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:27
‪TYPO3\CMS\Core\Http\HtmlResponse
Definition: HtmlResponse.php:28