|
1
|
|
|
<?php |
|
2
|
|
|
namespace Fab\Media\Controller; |
|
3
|
|
|
|
|
4
|
|
|
/** |
|
5
|
|
|
* This file is part of the TYPO3 CMS project. |
|
6
|
|
|
* |
|
7
|
|
|
* It is free software; you can redistribute it and/or modify it under |
|
8
|
|
|
* the terms of the GNU General Public License, either version 2 |
|
9
|
|
|
* of the License, or any later version. |
|
10
|
|
|
* |
|
11
|
|
|
* For the full copyright and license information, please read the |
|
12
|
|
|
* LICENSE.txt file that was distributed with this source code. |
|
13
|
|
|
* |
|
14
|
|
|
* The TYPO3 project - inspiring people to share! |
|
15
|
|
|
*/ |
|
16
|
|
|
|
|
17
|
|
|
use Fab\Media\Module\MediaModule; |
|
18
|
|
|
use TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException; |
|
19
|
|
|
use TYPO3\CMS\Core\Resource\Exception\IllegalFileExtensionException; |
|
20
|
|
|
use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException; |
|
21
|
|
|
use TYPO3\CMS\Core\Resource\Exception\InsufficientUserPermissionsException; |
|
22
|
|
|
use TYPO3\CMS\Core\Resource\Exception\UploadException; |
|
23
|
|
|
use TYPO3\CMS\Core\Resource\Exception\UploadSizeException; |
|
24
|
|
|
use TYPO3\CMS\Core\Resource\File; |
|
25
|
|
|
use TYPO3\CMS\Core\Resource\ResourceFactory; |
|
26
|
|
|
use TYPO3\CMS\Core\Resource\ResourceStorage; |
|
27
|
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility; |
|
28
|
|
|
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; |
|
29
|
|
|
use Fab\Media\FileUpload\UploadedFileInterface; |
|
30
|
|
|
use Fab\Media\Thumbnail\ThumbnailInterface; |
|
31
|
|
|
use Fab\Media\Thumbnail\ThumbnailService; |
|
32
|
|
|
use Fab\Vidi\Persistence\MatcherObjectFactory; |
|
33
|
|
|
use Fab\Vidi\Tca\Tca; |
|
34
|
|
|
|
|
35
|
|
|
/** |
|
36
|
|
|
* Controller which handles actions related to Asset. |
|
37
|
|
|
*/ |
|
38
|
|
|
class AssetController extends ActionController |
|
39
|
|
|
{ |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* @var \TYPO3\CMS\Core\Page\PageRenderer |
|
43
|
|
|
* @inject |
|
44
|
|
|
*/ |
|
45
|
|
|
protected $pageRenderer; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* @var string |
|
49
|
|
|
*/ |
|
50
|
|
|
protected $dataType = 'sys_file'; |
|
51
|
|
|
|
|
52
|
|
|
/** |
|
53
|
|
|
* @throws \Fab\Media\Exception\StorageNotOnlineException |
|
54
|
|
|
*/ |
|
55
|
|
View Code Duplication |
public function initializeAction() |
|
|
|
|
|
|
56
|
|
|
{ |
|
57
|
|
|
$this->pageRenderer->addInlineLanguageLabelFile('EXT:media/Resources/Private/Language/locallang.xlf'); |
|
58
|
|
|
|
|
59
|
|
|
// Configure property mapping to retrieve the file object. |
|
60
|
|
|
if ($this->arguments->hasArgument('file')) { |
|
61
|
|
|
|
|
62
|
|
|
/** @var \Fab\Media\TypeConverter\FileConverter $typeConverter */ |
|
63
|
|
|
$typeConverter = $this->objectManager->get('Fab\Media\TypeConverter\FileConverter'); |
|
64
|
|
|
|
|
65
|
|
|
$propertyMappingConfiguration = $this->arguments->getArgument('file')->getPropertyMappingConfiguration(); |
|
66
|
|
|
$propertyMappingConfiguration->setTypeConverter($typeConverter); |
|
67
|
|
|
} |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* Force download of the file. |
|
72
|
|
|
* |
|
73
|
|
|
* @param File $file |
|
74
|
|
|
* @param bool $forceDownload |
|
75
|
|
|
* @return bool|string |
|
76
|
|
|
*/ |
|
77
|
|
|
public function downloadAction(File $file, $forceDownload = FALSE) |
|
78
|
|
|
{ |
|
79
|
|
|
|
|
80
|
|
|
if ($file->exists() && $file->getStorage()->isWithinFileMountBoundaries($file->getParentFolder())) { |
|
81
|
|
|
|
|
82
|
|
|
// Emit signal before downloading the file. |
|
83
|
|
|
$this->emitBeforeDownloadSignal($file); |
|
84
|
|
|
|
|
85
|
|
|
// Read the file and dump it with the flag "forceDownload" set to TRUE or FALSE. |
|
86
|
|
|
$file->getStorage()->dumpFileContents($file, $forceDownload); |
|
87
|
|
|
|
|
88
|
|
|
$result = TRUE; |
|
89
|
|
|
} else { |
|
90
|
|
|
$result = 'Access denied!'; |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
|
|
return $result; |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
/** |
|
97
|
|
|
* Handle file upload for a new file. |
|
98
|
|
|
* |
|
99
|
|
|
* @param string $combinedIdentifier |
|
100
|
|
|
* @validate $combinedIdentifier \Fab\Media\Domain\Validator\StorageValidator |
|
101
|
|
|
* @return string |
|
102
|
|
|
*/ |
|
103
|
|
|
public function createAction($combinedIdentifier) |
|
104
|
|
|
{ |
|
105
|
|
|
/** @var UploadedFileInterface $uploadedFile */ |
|
106
|
|
|
$uploadedFile = $this->handleUpload(); |
|
107
|
|
|
if (!is_object($uploadedFile)) { |
|
108
|
|
|
return htmlspecialchars(json_encode($uploadedFile), ENT_NOQUOTES); |
|
109
|
|
|
} |
|
110
|
|
|
|
|
111
|
|
|
// Get the target folder. |
|
112
|
|
|
if ($this->getMediaModule()->hasFolderTree()) { |
|
113
|
|
|
$targetFolder = $this->getMediaModule()->getFolderForCombinedIdentifier($combinedIdentifier); |
|
114
|
|
|
} else { |
|
115
|
|
|
$storage = ResourceFactory::getInstance()->getStorageObjectFromCombinedIdentifier($combinedIdentifier); |
|
116
|
|
|
$targetFolder = $this->getMediaModule()->getTargetFolderForUploadedFile($uploadedFile, $storage); |
|
117
|
|
|
} |
|
118
|
|
|
|
|
119
|
|
|
try { |
|
120
|
|
|
$conflictMode = 'changeName'; |
|
121
|
|
|
$fileName = $uploadedFile->getName(); |
|
122
|
|
|
$file = $targetFolder->addFile($uploadedFile->getFileWithAbsolutePath(), $fileName, $conflictMode); |
|
123
|
|
|
|
|
124
|
|
|
// Run the indexer for extracting metadata. |
|
125
|
|
|
$this->getMediaIndexer($file->getStorage()) |
|
126
|
|
|
->extractMetadata($file) |
|
127
|
|
|
->applyDefaultCategories($file); |
|
128
|
|
|
|
|
129
|
|
|
$response = array( |
|
130
|
|
|
'success' => TRUE, |
|
131
|
|
|
'uid' => $file->getUid(), |
|
132
|
|
|
'name' => $file->getName(), |
|
133
|
|
|
'thumbnail' => $this->getThumbnailService($file)->create(), |
|
134
|
|
|
); |
|
135
|
|
|
} catch (UploadException $e) { |
|
|
|
|
|
|
136
|
|
|
$response = array('error' => 'The upload has failed, no uploaded file found!'); |
|
137
|
|
|
} catch (InsufficientUserPermissionsException $e) { |
|
|
|
|
|
|
138
|
|
|
$response = array('error' => 'You are not allowed to upload files!'); |
|
139
|
|
|
} catch (UploadSizeException $e) { |
|
|
|
|
|
|
140
|
|
|
$response = array('error' => vsprintf('The uploaded file "%s" exceeds the size-limit', array($uploadedFile->getName()))); |
|
141
|
|
|
} catch (InsufficientFolderWritePermissionsException $e) { |
|
|
|
|
|
|
142
|
|
|
$response = array('error' => vsprintf('Destination path "%s" was not within your mount points!', array($targetFolder->getIdentifier()))); |
|
143
|
|
|
} catch (IllegalFileExtensionException $e) { |
|
|
|
|
|
|
144
|
|
|
$response = array('error' => vsprintf('Extension of file name "%s" is not allowed in "%s"!', array($uploadedFile->getName(), $targetFolder->getIdentifier()))); |
|
145
|
|
|
} catch (ExistingTargetFileNameException $e) { |
|
|
|
|
|
|
146
|
|
|
$response = array('error' => vsprintf('No unique filename available in "%s"!', array($targetFolder->getIdentifier()))); |
|
147
|
|
|
} catch (\RuntimeException $e) { |
|
148
|
|
|
$response = array('error' => vsprintf('Uploaded file could not be moved! Write-permission problem in "%s"?', array($targetFolder->getIdentifier()))); |
|
149
|
|
|
} |
|
150
|
|
|
|
|
151
|
|
|
// to pass data through iframe you will need to encode all html tags |
|
152
|
|
|
header("Content-Type: text/plain"); |
|
153
|
|
|
return htmlspecialchars(json_encode($response), ENT_NOQUOTES); |
|
154
|
|
|
} |
|
155
|
|
|
|
|
156
|
|
|
/** |
|
157
|
|
|
* Handle file upload for an existing file. |
|
158
|
|
|
* |
|
159
|
|
|
* @param File $file |
|
160
|
|
|
* @return string |
|
161
|
|
|
*/ |
|
162
|
|
|
public function updateAction(File $file) |
|
163
|
|
|
{ |
|
164
|
|
|
$uploadedFile = $this->handleUpload(); |
|
165
|
|
|
if (!is_object($uploadedFile)) { |
|
166
|
|
|
return htmlspecialchars(json_encode($uploadedFile), ENT_NOQUOTES); |
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
/** @var $file File */ |
|
170
|
|
|
$targetFolder = $file->getStorage()->getFolder(dirname($file->getIdentifier())); |
|
171
|
|
|
|
|
172
|
|
|
try { |
|
173
|
|
|
$storage = $file->getStorage(); |
|
174
|
|
|
$storage->replaceFile($file, $uploadedFile->getFileWithAbsolutePath()); |
|
175
|
|
|
|
|
176
|
|
|
// Run the indexer for extracting metadata. |
|
177
|
|
|
$this->getMediaIndexer($file->getStorage()) |
|
178
|
|
|
->updateIndex($file) |
|
179
|
|
|
->extractMetadata($file); |
|
180
|
|
|
|
|
181
|
|
|
// Clear cache on pages holding a reference to this file. |
|
182
|
|
|
$this->getCacheService()->clearCache($file); |
|
183
|
|
|
|
|
184
|
|
|
$response = array( |
|
185
|
|
|
'success' => TRUE, |
|
186
|
|
|
'uid' => $file->getUid(), |
|
187
|
|
|
'name' => $file->getName(), |
|
188
|
|
|
'thumbnail' => $this->getThumbnailService($file)->create(), |
|
189
|
|
|
'fileInfo' => $this->getMetadataViewHelper()->render($file), |
|
190
|
|
|
); |
|
191
|
|
|
} catch (UploadException $e) { |
|
|
|
|
|
|
192
|
|
|
$response = array('error' => 'The upload has failed, no uploaded file found!'); |
|
193
|
|
|
} catch (InsufficientUserPermissionsException $e) { |
|
|
|
|
|
|
194
|
|
|
$response = array('error' => 'You are not allowed to upload files!'); |
|
195
|
|
|
} catch (UploadSizeException $e) { |
|
|
|
|
|
|
196
|
|
|
$response = array('error' => vsprintf('The uploaded file "%s" exceeds the size-limit', array($uploadedFile->getName()))); |
|
197
|
|
|
} catch (InsufficientFolderWritePermissionsException $e) { |
|
|
|
|
|
|
198
|
|
|
$response = array('error' => vsprintf('Destination path "%s" was not within your mount points!', array($targetFolder->getIdentifier()))); |
|
199
|
|
|
} catch (IllegalFileExtensionException $e) { |
|
|
|
|
|
|
200
|
|
|
$response = array('error' => vsprintf('Extension of file name "%s" is not allowed in "%s"!', array($uploadedFile->getName(), $targetFolder->getIdentifier()))); |
|
201
|
|
|
} catch (ExistingTargetFileNameException $e) { |
|
|
|
|
|
|
202
|
|
|
$response = array('error' => vsprintf('No unique filename available in "%s"!', array($targetFolder->getIdentifier()))); |
|
203
|
|
|
} catch (\RuntimeException $e) { |
|
204
|
|
|
$response = array('error' => vsprintf('Uploaded file could not be moved! Write-permission problem in "%s"?', array($targetFolder->getIdentifier()))); |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
// to pass data through iframe you will need to encode all html tags |
|
208
|
|
|
header("Content-Type: text/plain"); |
|
209
|
|
|
return htmlspecialchars(json_encode($response), ENT_NOQUOTES); |
|
210
|
|
|
} |
|
211
|
|
|
|
|
212
|
|
|
/** |
|
213
|
|
|
* Returns an editing form for moving Files between storage. |
|
214
|
|
|
* |
|
215
|
|
|
* @param array $matches |
|
216
|
|
|
* @throws \Exception |
|
217
|
|
|
*/ |
|
218
|
|
|
public function editStorageAction(array $matches = array()) |
|
219
|
|
|
{ |
|
220
|
|
|
|
|
221
|
|
|
$this->view->assign('storages', $this->getMediaModule()->getAllowedStorages()); |
|
222
|
|
|
$this->view->assign('storageTitle', Tca::table('sys_file_storage')->getTitle()); |
|
223
|
|
|
|
|
224
|
|
|
$fieldName = 'storage'; |
|
225
|
|
|
|
|
226
|
|
|
// Instantiate the Matcher object according different rules. |
|
227
|
|
|
$matcher = MatcherObjectFactory::getInstance()->getMatcher($matches, $this->dataType); |
|
228
|
|
|
|
|
229
|
|
|
// Fetch objects via the Content Service. |
|
230
|
|
|
$contentService = $this->getContentService()->findBy($matcher); |
|
231
|
|
|
|
|
232
|
|
|
$fieldType = Tca::table($this->dataType)->field($fieldName)->getType(); |
|
233
|
|
|
|
|
234
|
|
|
$this->view->assign('fieldType', ucfirst($fieldType)); |
|
235
|
|
|
$this->view->assign('dataType', $this->dataType); |
|
236
|
|
|
$this->view->assign('matches', $matches); |
|
237
|
|
|
$this->view->assign('fieldNameAndPath', $fieldName); |
|
238
|
|
|
$this->view->assign('numberOfObjects', $contentService->getNumberOfObjects()); |
|
239
|
|
|
$this->view->assign('editWholeSelection', empty($matches['uid'])); // necessary?? |
|
240
|
|
|
} |
|
241
|
|
|
|
|
242
|
|
|
/** |
|
243
|
|
|
* Handle file upload. |
|
244
|
|
|
* |
|
245
|
|
|
* @return \Fab\Media\FileUpload\UploadedFileInterface|array |
|
246
|
|
|
*/ |
|
247
|
|
|
protected function handleUpload() |
|
248
|
|
|
{ |
|
249
|
|
|
|
|
250
|
|
|
/** @var $uploadManager \Fab\Media\FileUpload\UploadManager */ |
|
251
|
|
|
$uploadManager = GeneralUtility::makeInstance('Fab\Media\FileUpload\UploadManager'); |
|
252
|
|
|
|
|
253
|
|
|
try { |
|
254
|
|
|
/** @var $result \Fab\Media\FileUpload\UploadedFileInterface */ |
|
255
|
|
|
$result = $uploadManager->handleUpload(); |
|
256
|
|
|
} catch (\Exception $e) { |
|
257
|
|
|
$result = array('error' => $e->getMessage()); |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
return $result; |
|
261
|
|
|
} |
|
262
|
|
|
|
|
263
|
|
|
/** |
|
264
|
|
|
* @return \Fab\Media\ViewHelpers\MetadataViewHelper |
|
265
|
|
|
*/ |
|
266
|
|
|
protected function getMetadataViewHelper() |
|
267
|
|
|
{ |
|
268
|
|
|
return GeneralUtility::makeInstance('Fab\Media\ViewHelpers\MetadataViewHelper'); |
|
269
|
|
|
} |
|
270
|
|
|
|
|
271
|
|
|
/** |
|
272
|
|
|
* @param File $file |
|
273
|
|
|
* @return ThumbnailService |
|
274
|
|
|
*/ |
|
275
|
|
|
protected function getThumbnailService(File $file) |
|
276
|
|
|
{ |
|
277
|
|
|
|
|
278
|
|
|
/** @var $thumbnailService ThumbnailService */ |
|
279
|
|
|
$thumbnailService = GeneralUtility::makeInstance('Fab\Media\Thumbnail\ThumbnailService', $file); |
|
280
|
|
|
$thumbnailService->setAppendTimeStamp(TRUE) |
|
281
|
|
|
->setOutputType(ThumbnailInterface::OUTPUT_IMAGE_WRAPPED); |
|
282
|
|
|
return $thumbnailService; |
|
283
|
|
|
} |
|
284
|
|
|
|
|
285
|
|
|
/** |
|
286
|
|
|
* Get the instance of the Indexer service to update the metadata of the file. |
|
287
|
|
|
* |
|
288
|
|
|
* @param int|ResourceStorage $storage |
|
289
|
|
|
* @return \Fab\Media\Index\MediaIndexer |
|
290
|
|
|
*/ |
|
291
|
|
|
protected function getMediaIndexer($storage) |
|
292
|
|
|
{ |
|
293
|
|
|
return GeneralUtility::makeInstance('Fab\Media\Index\MediaIndexer', $storage); |
|
294
|
|
|
} |
|
295
|
|
|
|
|
296
|
|
|
/** |
|
297
|
|
|
* @return \Fab\Media\Cache\CacheService |
|
298
|
|
|
*/ |
|
299
|
|
|
protected function getCacheService() |
|
300
|
|
|
{ |
|
301
|
|
|
return GeneralUtility::makeInstance('Fab\Media\Cache\CacheService'); |
|
302
|
|
|
} |
|
303
|
|
|
|
|
304
|
|
|
/** |
|
305
|
|
|
* Signal that is emitted before a file is downloaded. |
|
306
|
|
|
* |
|
307
|
|
|
* @param File $file |
|
308
|
|
|
* @return void |
|
309
|
|
|
* @signal |
|
310
|
|
|
*/ |
|
311
|
|
|
protected function emitBeforeDownloadSignal(File $file) |
|
312
|
|
|
{ |
|
313
|
|
|
$this->getSignalSlotDispatcher()->dispatch('Fab\Media\Controller\Backend\AssetController', 'beforeDownload', array($file)); |
|
314
|
|
|
} |
|
315
|
|
|
|
|
316
|
|
|
/** |
|
317
|
|
|
* Get the SignalSlot dispatcher. |
|
318
|
|
|
* |
|
319
|
|
|
* @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher |
|
320
|
|
|
*/ |
|
321
|
|
|
protected function getSignalSlotDispatcher() |
|
322
|
|
|
{ |
|
323
|
|
|
return $this->objectManager->get('TYPO3\CMS\Extbase\SignalSlot\Dispatcher'); |
|
324
|
|
|
} |
|
325
|
|
|
|
|
326
|
|
|
/** |
|
327
|
|
|
* Get the Vidi Module Loader. |
|
328
|
|
|
* |
|
329
|
|
|
* @return \Fab\Vidi\Service\ContentService |
|
330
|
|
|
*/ |
|
331
|
|
|
protected function getContentService() |
|
332
|
|
|
{ |
|
333
|
|
|
return GeneralUtility::makeInstance('Fab\Vidi\Service\ContentService', $this->dataType); |
|
334
|
|
|
} |
|
335
|
|
|
|
|
336
|
|
|
/** |
|
337
|
|
|
* @return MediaModule |
|
338
|
|
|
*/ |
|
339
|
|
|
protected function getMediaModule() |
|
340
|
|
|
{ |
|
341
|
|
|
return GeneralUtility::makeInstance('Fab\Media\Module\MediaModule'); |
|
342
|
|
|
} |
|
343
|
|
|
|
|
344
|
|
|
} |
|
345
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.