‪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 #[Controller]
50 {
56  protected ‪$file;
57 
63  protected ‪$CB;
64 
72 
78  protected ‪$redirect;
79 
85  protected ‪$fileData;
86 
87  public function ‪__construct(
88  protected readonly ‪ResourceFactory $fileFactory,
89  protected readonly ‪ExtendedFileUtility $fileProcessor,
90  protected readonly ‪IconFactory $iconFactory,
91  protected readonly ‪UriBuilder $uriBuilder,
92  protected readonly ‪FlashMessageService $flashMessageService
93  ) {
94  }
95 
104  public function ‪mainAction(ServerRequestInterface $request): ResponseInterface
105  {
106  $this->‪init($request);
107  $this->‪main();
108 
109  BackendUtility::setUpdateSignal('updateFolderTree');
110 
111  // go and edit the new created file
112  if ($request->getParsedBody()['edit'] ?? '') {
114  ‪$file = $this->fileData['newfile'][0];
115  if (‪$file !== null) {
116  $this->redirect = $this->‪getFileEditRedirect(‪$file) ?? ‪$this->redirect;
117  }
118  }
119  if ($this->redirect) {
120  return new ‪RedirectResponse(
121  GeneralUtility::locationHeaderUrl($this->redirect),
122  303
123  );
124  }
125  // empty response
126  return new ‪HtmlResponse('');
127  }
128 
133  public function ‪processAjaxRequest(ServerRequestInterface $request): ResponseInterface
134  {
135  $this->‪init($request);
136  $this->‪main();
137  $flatResult = [
138  'hasErrors' => false,
139  ];
140  foreach ($this->fileData as $action => $results) {
141  foreach ($results as $result) {
142  if (is_array($result)) {
143  foreach ($result as $subResult) {
144  $flatResult[$action][] = $this->‪flattenResultDataValue($subResult);
145  }
146  } else {
147  $flatResult[$action][] = $this->‪flattenResultDataValue($result);
148  }
149  }
150  }
151 
152  // Used in the FileStorageTree when moving / copying folders, or in the DragUploader
153  $messages = $this->flashMessageService->getMessageQueueByIdentifier()->getAllMessagesAndFlush();
154  if (!empty($messages)) {
155  foreach ($messages as $message) {
156  $flatResult['messages'][] = [
157  'title' => $message->getTitle(),
158  'message' => $message->getMessage(),
159  'severity' => $message->getSeverity(),
160  ];
161  if ($message->getSeverity() === ContextualFeedbackSeverity::ERROR) {
162  $flatResult['hasErrors'] = true;
163  }
164  }
165  }
166  return new ‪JsonResponse($flatResult, $flatResult['hasErrors'] ? 500 : 200);
167  }
168 
172  public function ‪fileExistsInFolderAction(ServerRequestInterface $request): ResponseInterface
173  {
174  $this->‪init($request);
175  $fileName = $request->getParsedBody()['fileName'] ?? $request->getQueryParams()['fileName'] ?? null;
176  $fileTarget = $request->getParsedBody()['fileTarget'] ?? $request->getQueryParams()['fileTarget'] ?? null;
177 
178  $fileTargetObject = $this->fileFactory->retrieveFileOrFolderObject($fileTarget);
179  $processedFileName = $fileTargetObject->getStorage()->sanitizeFileName($fileName, $fileTargetObject);
180 
181  $result = [];
182  if ($fileTargetObject->hasFile($processedFileName)) {
183  $fileInFolder = $fileTargetObject->getStorage()->getFileInFolder($processedFileName, $fileTargetObject);
184  if ($fileInFolder instanceof ‪File) {
185  $result = $this->‪flattenFileResultDataValue($fileInFolder);
186  }
187  }
188  return new ‪JsonResponse($result);
189  }
190 
194  protected function ‪init(ServerRequestInterface $request): void
195  {
196  // Set the GPvars from outside
197  $parsedBody = $request->getParsedBody();
198  $queryParams = $request->getQueryParams();
199  $this->file = (array)($parsedBody['data'] ?? $queryParams['data'] ?? []);
200  $redirectUrl = (string)($parsedBody['redirect'] ?? $queryParams['redirect'] ?? '');
201  if ($this->file === [] || $redirectUrl !== '') {
202  // This in clipboard mode or when a new folder is created
203  $this->redirect = GeneralUtility::sanitizeLocalUrl($redirectUrl);
204  } else {
205  $mode = key($this->file);
206  $elementKey = key($this->file[$mode]);
207  $this->redirect = GeneralUtility::sanitizeLocalUrl($this->file[$mode][$elementKey]['redirect'] ?? '');
208  }
209  $this->CB = (array)($parsedBody['CB'] ?? $queryParams['CB'] ?? []);
210 
211  if (isset($this->file['rename'][0]['conflictMode'])) {
212  $conflictMode = $this->file['rename'][0]['conflictMode'];
213  unset($this->file['rename'][0]['conflictMode']);
214  $this->overwriteExistingFiles = ‪DuplicationBehavior::cast($conflictMode);
215  } else {
216  $this->overwriteExistingFiles = ‪DuplicationBehavior::cast($parsedBody['overwriteExistingFiles'] ?? $queryParams['overwriteExistingFiles'] ?? null);
217  }
218  $this->‪initClipboard($request);
219  }
220 
224  protected function ‪initClipboard(ServerRequestInterface $request): void
225  {
226  if ($this->CB !== []) {
227  $clipObj = GeneralUtility::makeInstance(Clipboard::class);
228  $clipObj->initializeClipboard($request);
229  if ($this->CB['paste'] ?? false) {
230  $clipObj->setCurrentPad((string)($this->CB['pad'] ?? ''));
231  $this->‪setPasteCmd($clipObj);
232  }
233  if ($this->CB['delete'] ?? false) {
234  $clipObj->setCurrentPad((string)($this->CB['pad'] ?? ''));
235  $this->‪setDeleteCmd($clipObj);
236  }
237  }
238  }
239 
244  protected function ‪main(): void
245  {
246  $this->fileProcessor->setActionPermissions();
247  $this->fileProcessor->setExistingFilesConflictMode($this->overwriteExistingFiles);
248  $this->fileProcessor->start($this->file);
249  $this->fileData = $this->fileProcessor->processData();
250  }
251 
259  protected function ‪getFileEditRedirect(‪File ‪$file): ?string
260  {
261  if (!‪$file->isTextFile()) {
262  return null;
263  }
264  ‪$properties = ‪$file->getProperties();
265  $urlParameters = [
266  'target' => ‪$properties['storage'] . ':' . ‪$properties['identifier'],
267  ];
268  if ($this->redirect) {
269  $urlParameters['returnUrl'] = ‪$this->redirect;
270  }
271  try {
272  return (string)$this->uriBuilder->buildUriFromRoute('file_edit', $urlParameters);
273  } catch (RouteNotFoundException $exception) {
274  // no route for editing files available
275  return '';
276  }
277  }
278 
279  protected function ‪flattenFileResultDataValue(‪File $result): array
280  {
281  $thumbUrl = $result->‪isImage()
282  ? ($result->‪process(‪ProcessedFile::CONTEXT_IMAGEPREVIEW, [])->getPublicUrl() ?? '')
283  : '';
284  $path = '';
285  if (is_callable([$result->‪getParentFolder(), 'getReadablePath'])) {
286  $path = $result->‪getParentFolder()->getReadablePath();
287  }
288  return array_merge(
289  $result->toArray(),
290  [
291  'date' => BackendUtility::date($result->‪getModificationTime()),
292  'icon' => $this->iconFactory->getIconForFileExtension($result->‪getExtension(), IconSize::SMALL)->render(),
293  'thumbUrl' => $thumbUrl,
294  'path' => $path,
295  ]
296  );
297  }
298 
308  protected function ‪flattenResultDataValue($result)
309  {
310  if ($result instanceof File) {
311  $result = $this->‪flattenFileResultDataValue($result);
312  } elseif ($result instanceof Folder) {
313  $result = $result->getIdentifier();
314  }
315 
316  return $result;
317  }
318 
322  protected function ‪setPasteCmd(‪Clipboard $clipboard): void
323  {
324  $target = explode('|', (string)$this->CB['paste'])[1] ?? '';
325  $mode = $clipboard->‪currentMode() === 'copy' ? 'copy' : 'move';
326  // Traverse elements and make CMD array
327  foreach ($clipboard->‪elFromTable('_FILE') as $key => $path) {
328  $this->file[$mode][] = ['data' => $path, 'target' => $target];
329  if ($mode === 'move') {
330  $clipboard->‪removeElement($key);
331  }
332  }
333  $clipboard->‪endClipboard();
334  }
335 
339  protected function ‪setDeleteCmd(‪Clipboard $clipObj): void
340  {
341  // Traverse elements and make CMD array
342  foreach ($clipObj->‪elFromTable('_FILE') as $key => $path) {
343  $this->file['delete'][] = ['data' => $path];
344  $clipObj->‪removeElement($key);
345  }
346  $clipObj->‪endClipboard();
347  }
348 }
‪TYPO3\CMS\Backend\Controller\File\FileController\main
‪main()
Definition: FileController.php:239
‪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:189
‪TYPO3\CMS\Backend\Controller\File\FileController\setDeleteCmd
‪setDeleteCmd(Clipboard $clipObj)
Definition: FileController.php:334
‪TYPO3\CMS\Core\Resource\DuplicationBehavior
Definition: DuplicationBehavior.php:24
‪TYPO3\CMS\Backend\Clipboard\Clipboard
Definition: Clipboard.php:48
‪TYPO3\CMS\Core\Resource\AbstractFile\getParentFolder
‪getParentFolder()
Definition: AbstractFile.php:569
‪TYPO3\CMS\Backend\Controller\File\FileController\$redirect
‪string $redirect
Definition: FileController.php:74
‪TYPO3\CMS\Backend\Controller\File\FileController\$fileData
‪array $fileData
Definition: FileController.php:80
‪TYPO3\CMS\Backend\Attribute\Controller
Definition: Controller.php:25
‪TYPO3\CMS\Core\Resource\AbstractFile\getExtension
‪getExtension()
Definition: AbstractFile.php:236
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Backend\Controller\File\FileController\mainAction
‪ResponseInterface mainAction(ServerRequestInterface $request)
Definition: FileController.php:99
‪TYPO3\CMS\Core\Resource\AbstractFile\isImage
‪bool isImage()
Definition: AbstractFile.php:309
‪TYPO3\CMS\Backend\Controller\File\FileController\setPasteCmd
‪setPasteCmd(Clipboard $clipboard)
Definition: FileController.php:317
‪TYPO3\CMS\Backend\Controller\File\FileController\$overwriteExistingFiles
‪DuplicationBehavior $overwriteExistingFiles
Definition: FileController.php:68
‪TYPO3\CMS\Core\Type\ContextualFeedbackSeverity
‪ContextualFeedbackSeverity
Definition: ContextualFeedbackSeverity.php:25
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:186
‪TYPO3\CMS\Core\Utility\File\ExtendedFileUtility
Definition: ExtendedFileUtility.php:77
‪TYPO3\CMS\Backend\Clipboard\Clipboard\currentMode
‪string currentMode()
Definition: Clipboard.php:656
‪TYPO3\CMS\Backend\Controller\File\FileController\initClipboard
‪initClipboard(ServerRequestInterface $request)
Definition: FileController.php:219
‪TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
Definition: RouteNotFoundException.php:22
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:44
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:37
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:26
‪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:167
‪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:82
‪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:274
‪TYPO3\CMS\Backend\Controller\File\FileController\processAjaxRequest
‪processAjaxRequest(ServerRequestInterface $request)
Definition: FileController.php:128
‪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:303
‪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:254
‪TYPO3\CMS\Core\Http\JsonResponse
Definition: JsonResponse.php:28
‪TYPO3\CMS\Core\Resource\AbstractFile\$properties
‪array $properties
Definition: AbstractFile.php:38
‪TYPO3\CMS\Backend\Controller\File
Definition: FileController.php:18
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Backend\Controller\File\FileController\$CB
‪array $CB
Definition: FileController.php:61
‪TYPO3\CMS\Core\Resource\AbstractFile\getModificationTime
‪getModificationTime()
Definition: AbstractFile.php:225
‪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