TYPO3 CMS  TYPO3_8-7
UploadedFileReferenceConverter.php
Go to the documentation of this file.
1 <?php
2 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 
28 
36 {
37 
42 
47 
52 
56  protected $defaultUploadFolder = '1:/user_upload/';
57 
63  protected $defaultConflictMode = 'rename';
64 
68  protected $sourceTypes = ['array'];
69 
73  protected $targetType = ExtbaseFileReference::class;
74 
80  protected $priority = 12;
81 
85  protected $convertedResources = [];
86 
90  protected $resourceFactory;
91 
95  protected $hashService;
96 
101 
106  public function injectResourceFactory(\TYPO3\CMS\Core\Resource\ResourceFactory $resourceFactory)
107  {
108  $this->resourceFactory = $resourceFactory;
109  }
110 
115  public function injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)
116  {
117  $this->hashService = $hashService;
118  }
119 
124  public function injectPersistenceManager(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface $persistenceManager)
125  {
126  $this->persistenceManager = $persistenceManager;
127  }
128 
140  public function convertFrom($source, $targetType, array $convertedChildProperties = [], PropertyMappingConfigurationInterface $configuration = null)
141  {
142  if (!isset($source['error']) || $source['error'] === \UPLOAD_ERR_NO_FILE) {
143  if (isset($source['submittedFile']['resourcePointer'])) {
144  try {
145  // File references use numeric resource pointers, direct
146  // file relations are using "file:" prefix (e.g. "file:5")
147  $resourcePointer = $this->hashService->validateAndStripHmac($source['submittedFile']['resourcePointer']);
148  if (strpos($resourcePointer, 'file:') === 0) {
149  $fileUid = (int)substr($resourcePointer, 5);
150  return $this->createFileReferenceFromFalFileObject($this->resourceFactory->getFileObject($fileUid));
151  }
153  $this->resourceFactory->getFileReferenceObject($resourcePointer),
154  (int)$resourcePointer
155  );
156  } catch (\InvalidArgumentException $e) {
157  // Nothing to do. No file is uploaded and resource pointer is invalid. Discard!
158  }
159  }
160  return null;
161  }
162 
163  if ($source['error'] !== \UPLOAD_ERR_OK) {
164  return $this->objectManager->get(Error::class, $this->getUploadErrorMessage($source['error']), 1471715915);
165  }
166 
167  if (isset($this->convertedResources[$source['tmp_name']])) {
168  return $this->convertedResources[$source['tmp_name']];
169  }
170 
171  try {
172  $resource = $this->importUploadedResource($source, $configuration);
173  } catch (\Exception $e) {
174  return $this->objectManager->get(Error::class, $e->getMessage(), $e->getCode());
175  }
176 
177  $this->convertedResources[$source['tmp_name']] = $resource;
178  return $resource;
179  }
180 
189  protected function importUploadedResource(
190  array $uploadInfo,
193  if (!GeneralUtility::verifyFilenameAgainstDenyPattern($uploadInfo['name'])) {
194  throw new TypeConverterException('Uploading files with PHP file extensions is not allowed!', 1471710357);
195  }
196 
197  $uploadFolderId = $configuration->getConfigurationValue(self::class, self::CONFIGURATION_UPLOAD_FOLDER) ?: $this->defaultUploadFolder;
198  $conflictMode = $configuration->getConfigurationValue(self::class, self::CONFIGURATION_UPLOAD_CONFLICT_MODE) ?: $this->defaultConflictMode;
199 
200  $uploadFolder = $this->resourceFactory->retrieveFileOrFolderObject($uploadFolderId);
201  $uploadedFile = $uploadFolder->addUploadedFile($uploadInfo, $conflictMode);
202 
203  $validators = $configuration->getConfigurationValue(self::class, self::CONFIGURATION_FILE_VALIDATORS);
204  if (is_array($validators)) {
205  foreach ($validators as $validator) {
206  if ($validator instanceof AbstractValidator) {
207  $validationResult = $validator->validate($uploadedFile);
208  if ($validationResult->hasErrors()) {
209  $uploadedFile->getStorage()->deleteFile($uploadedFile);
210  throw new TypeConverterException($validationResult->getErrors()[0]->getMessage(), 1471708999);
211  }
212  }
213  }
214  }
215 
216  $resourcePointer = isset($uploadInfo['submittedFile']['resourcePointer']) && strpos($uploadInfo['submittedFile']['resourcePointer'], 'file:') === false
217  ? (int)$this->hashService->validateAndStripHmac($uploadInfo['submittedFile']['resourcePointer'])
218  : null;
219 
220  $fileReferenceModel = $this->createFileReferenceFromFalFileObject($uploadedFile, $resourcePointer);
221 
222  return $fileReferenceModel;
223  }
224 
231  File $file,
232  int $resourcePointer = null
234  $fileReference = $this->resourceFactory->createFileReferenceObject(
235  [
236  'uid_local' => $file->getUid(),
237  'uid_foreign' => uniqid('NEW_'),
238  'uid' => uniqid('NEW_'),
239  'crop' => null,
240  ]
241  );
242  return $this->createFileReferenceFromFalFileReferenceObject($fileReference, $resourcePointer);
243  }
244 
255  CoreFileReference $falFileReference,
256  int $resourcePointer = null
258  if ($resourcePointer === null) {
259  $fileReference = $this->objectManager->get(ExtbaseFileReference::class);
260  } else {
261  $fileReference = $this->persistenceManager->getObjectByIdentifier($resourcePointer, ExtbaseFileReference::class, false);
262  }
263 
264  $fileReference->setOriginalResource($falFileReference);
265  return $fileReference;
266  }
267 
275  protected function getUploadErrorMessage(int $errorCode): string
276  {
277  switch ($errorCode) {
278  case \UPLOAD_ERR_INI_SIZE:
279  return 'The uploaded file exceeds the upload_max_filesize directive in php.ini';
280  case \UPLOAD_ERR_FORM_SIZE:
281  return 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
282  case \UPLOAD_ERR_PARTIAL:
283  return 'The uploaded file was only partially uploaded';
284  case \UPLOAD_ERR_NO_FILE:
285  return 'No file was uploaded';
286  case \UPLOAD_ERR_NO_TMP_DIR:
287  return 'Missing a temporary folder';
288  case \UPLOAD_ERR_CANT_WRITE:
289  return 'Failed to write file to disk';
290  case \UPLOAD_ERR_EXTENSION:
291  return 'File upload stopped by extension';
292  default:
293  return 'Unknown upload error';
294  }
295  }
296 }
injectPersistenceManager(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface $persistenceManager)
createFileReferenceFromFalFileReferenceObject(CoreFileReference $falFileReference, int $resourcePointer=null)
static verifyFilenameAgainstDenyPattern($filename)
importUploadedResource(array $uploadInfo, PropertyMappingConfigurationInterface $configuration)
injectResourceFactory(\TYPO3\CMS\Core\Resource\ResourceFactory $resourceFactory)
injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)
convertFrom($source, $targetType, array $convertedChildProperties=[], PropertyMappingConfigurationInterface $configuration=null)