[BUGFIX] Declare mimetype property in FAL as string
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / FileReference.php
1 <?php
2 namespace TYPO3\CMS\Core\Resource;
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 /**
18 * Representation of a specific usage of a file with possibilities to override certain
19 * properties of the original file just for this usage of the file.
20 *
21 * It acts as a decorator over the original file in the way that most method calls are
22 * directly passed along to the original file object.
23 *
24 * All file related methods are directly passed along; only meta data functionality is adopted
25 * in this decorator class to priorities possible overrides for the metadata for this specific usage
26 * of the file.
27 */
28 class FileReference implements FileInterface {
29
30 /**
31 * Various properties of the FileReference. Note that these information can be different
32 * to the ones found in the originalFile.
33 *
34 * @var array
35 */
36 protected $propertiesOfFileReference;
37
38 /**
39 * The identifier of this file to identify it on the storage.
40 * On some drivers, this is the path to the file, but drivers could also just
41 * provide any other unique identifier for this file on the specific storage.
42 *
43 * @var string
44 */
45 protected $uidOfFileReference;
46
47 /**
48 * The file name of this file. It's either the fileName of the original underlying file,
49 * or the overlay file name supplied by the user for this particular usage (FileReference) of the file.
50 *
51 * @var string
52 */
53 protected $name;
54
55 /**
56 * Reference to the original File object underlying this FileReference.
57 *
58 * @var File
59 */
60 protected $originalFile;
61
62 /**
63 * Properties merged with the parent object (File) if
64 * the value is not defined (NULL). Thus, FileReference properties act
65 * as overlays for the defined File properties.
66 *
67 * @var array
68 */
69 protected $mergedProperties = array();
70
71 /**
72 * Constructor for a file in use object. Should normally not be used
73 * directly, use the corresponding factory methods instead.
74 *
75 * @param array $fileReferenceData
76 * @param ResourceFactory $factory
77 *
78 * @throws \RuntimeException
79 * @throws \InvalidArgumentException
80 */
81 public function __construct(array $fileReferenceData, $factory = NULL) {
82 $this->propertiesOfFileReference = $fileReferenceData;
83 if (!$fileReferenceData['uid_local']) {
84 throw new \InvalidArgumentException('Incorrect reference to original file given for FileReference.', 1300098528);
85 }
86 if (!$factory) {
87 /** @var $factory ResourceFactory */
88 $factory = ResourceFactory::getInstance();
89 }
90 $this->originalFile = $factory->getFileObject($fileReferenceData['uid_local']);
91 if (!is_object($this->originalFile)) {
92 throw new \RuntimeException(
93 'Original file not found for FileReference. UID given: "' . $fileReferenceData['uid_local'] . '"',
94 1300098529
95 );
96 }
97 $this->name = $fileReferenceData['name'] !== '' ? $fileReferenceData['name'] : $this->originalFile->getName();
98 }
99
100 /*******************************
101 * VARIOUS FILE PROPERTY GETTERS
102 *******************************/
103 /**
104 * Returns true if the given key exists for this file.
105 *
106 * @param string $key The property to be looked up
107 * @return bool
108 */
109 public function hasProperty($key) {
110 return array_key_exists($key, $this->getProperties());
111 }
112
113 /**
114 * Gets a property, falling back to values of the parent.
115 *
116 * @param string $key The property to be looked up
117 * @return mixed
118 * @throws \InvalidArgumentException
119 */
120 public function getProperty($key) {
121 if (!$this->hasProperty($key)) {
122 throw new \InvalidArgumentException('Property "' . $key . '" was not found in file reference or original file.', 1314226805);
123 }
124 $properties = $this->getProperties();
125 return $properties[$key];
126 }
127
128 /**
129 * Gets a property of the file reference.
130 *
131 * @param string $key The property to be looked up
132 * @return mixed
133 * @throws \InvalidArgumentException
134 */
135 public function getReferenceProperty($key) {
136 if (!array_key_exists($key, $this->propertiesOfFileReference)) {
137 throw new \InvalidArgumentException('Property "' . $key . '" of file reference was not found.', 1360684914);
138 }
139 return $this->propertiesOfFileReference[$key];
140 }
141
142 /**
143 * Gets all properties, falling back to values of the parent.
144 *
145 * @return array
146 */
147 public function getProperties() {
148 if (empty($this->mergedProperties)) {
149 $this->mergedProperties = $this->propertiesOfFileReference;
150 \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule(
151 $this->mergedProperties,
152 $this->originalFile->getProperties(),
153 TRUE,
154 TRUE,
155 FALSE
156 );
157 array_walk($this->mergedProperties, array($this, 'restoreNonNullValuesCallback'));
158 }
159
160 return $this->mergedProperties;
161 }
162
163 /**
164 * Callback to handle the NULL value feature
165 *
166 * @param mixed $value
167 * @param mixed $key
168 */
169 protected function restoreNonNullValuesCallback(&$value, $key) {
170 if (array_key_exists($key, $this->propertiesOfFileReference) && $this->propertiesOfFileReference[$key] !== NULL) {
171 $value = $this->propertiesOfFileReference[$key];
172 }
173 }
174
175 /**
176 * Gets all properties of the file reference.
177 *
178 * @return array
179 */
180 public function getReferenceProperties() {
181 return $this->propertiesOfFileReference;
182 }
183
184 /**
185 * Returns the name of this file
186 *
187 * @return string
188 */
189 public function getName() {
190 return $this->originalFile->getName();
191 }
192
193 /**
194 * Returns the title text to this image
195 *
196 * @todo Possibly move this to the image domain object instead
197 *
198 * @return string
199 */
200 public function getTitle() {
201 return $this->getProperty('title');
202 }
203
204 /**
205 * Returns the alternative text to this image
206 *
207 * @todo Possibly move this to the image domain object instead
208 *
209 * @return string
210 */
211 public function getAlternative() {
212 return $this->getProperty('alternative');
213 }
214
215 /**
216 * Returns the description text to this file
217 *
218 * @todo Possibly move this to the image domain object instead
219 *
220 * @return string
221 */
222 public function getDescription() {
223 return $this->getProperty('description');
224 }
225
226 /**
227 * Returns the link that should be active when clicking on this image
228 *
229 * @todo Move this to the image domain object instead
230 *
231 * @return string
232 */
233 public function getLink() {
234 return $this->propertiesOfFileReference['link'];
235 }
236
237 /**
238 * Returns the uid of this File In Use
239 *
240 * @return int
241 */
242 public function getUid() {
243 return (int)$this->propertiesOfFileReference['uid'];
244 }
245
246 /**
247 * Returns the size of this file
248 *
249 * @return int
250 */
251 public function getSize() {
252 return (int)$this->originalFile->getSize();
253 }
254
255 /**
256 * Returns the Sha1 of this file
257 *
258 * @return string
259 */
260 public function getSha1() {
261 return $this->originalFile->getSha1();
262 }
263
264 /**
265 * Get the file extension of this file
266 *
267 * @return string The file extension
268 */
269 public function getExtension() {
270 return $this->originalFile->getExtension();
271 }
272
273 /**
274 * Returns the basename (the name without extension) of this file.
275 *
276 * @return string
277 */
278 public function getNameWithoutExtension() {
279 return $this->originalFile->getNameWithoutExtension();
280 }
281
282 /**
283 * Get the MIME type of this file
284 *
285 * @return string mime type
286 */
287 public function getMimeType() {
288 return $this->originalFile->getMimeType();
289 }
290
291 /**
292 * Returns the modification time of the file as Unix timestamp
293 *
294 * @return int
295 */
296 public function getModificationTime() {
297 return (int)$this->originalFile->getModificationTime();
298 }
299
300 /**
301 * Returns the creation time of the file as Unix timestamp
302 *
303 * @return int
304 */
305 public function getCreationTime() {
306 return (int)$this->originalFile->getCreationTime();
307 }
308
309 /**
310 * Returns the fileType of this file
311 *
312 * @return int $fileType
313 */
314 public function getType() {
315 return (int)$this->originalFile->getType();
316 }
317
318 /**
319 * Check if file is marked as missing by indexer
320 *
321 * @return bool
322 */
323 public function isMissing() {
324 return (bool)$this->originalFile->getProperty('missing');
325 }
326
327 /******************
328 * CONTENTS RELATED
329 ******************/
330 /**
331 * Get the contents of this file
332 *
333 * @return string File contents
334 */
335 public function getContents() {
336 return $this->originalFile->getContents();
337 }
338
339 /**
340 * Replace the current file contents with the given string
341 *
342 * @param string $contents The contents to write to the file.
343 * @return File The file object (allows chaining).
344 */
345 public function setContents($contents) {
346 return $this->originalFile->setContents($contents);
347 }
348
349 /****************************************
350 * STORAGE AND MANAGEMENT RELATED METHDOS
351 ****************************************/
352 /**
353 * Get the storage the original file is located in
354 *
355 * @return ResourceStorage
356 */
357 public function getStorage() {
358 return $this->originalFile->getStorage();
359 }
360
361 /**
362 * Returns the identifier of the underlying original file
363 *
364 * @return string
365 */
366 public function getIdentifier() {
367 return $this->originalFile->getIdentifier();
368 }
369
370 /**
371 * Returns a combined identifier of the underlying original file
372 *
373 * @return string Combined storage and file identifier, e.g. StorageUID:path/and/fileName.png
374 */
375 public function getCombinedIdentifier() {
376 return $this->originalFile->getCombinedIdentifier();
377 }
378
379 /**
380 * Deletes only this particular FileReference from the persistence layer
381 * (database table sys_file_reference) but leaves the original file untouched.
382 *
383 * @throws \BadMethodCallException
384 * @return bool TRUE if deletion succeeded
385 */
386 public function delete() {
387 // @todo Implement this function. This should only delete the
388 // FileReference (sys_file_reference) record, not the file itself.
389 throw new \BadMethodCallException('Function not implemented FileReference::delete().', 1333754461);
390 //return $this->fileRepository->removeUsageRecord($this);
391 }
392
393 /**
394 * Renames the fileName in this particular usage.
395 *
396 * @param string $newName The new name
397 * @throws \BadMethodCallException
398 * @return FileReference
399 */
400 public function rename($newName) {
401 // @todo Implement this function. This should only rename the
402 // FileReference (sys_file_reference) record, not the file itself.
403 throw new \BadMethodCallException('Function not implemented FileReference::rename().', 1333754473);
404 //return $this->fileRepository->renameUsageRecord($this, $newName);
405 }
406
407 /*****************
408 * SPECIAL METHODS
409 *****************/
410 /**
411 * Returns a publicly accessible URL for this file
412 *
413 * WARNING: Access to the file may be restricted by further means, e.g.
414 * some web-based authentication. You have to take care of this yourself.
415 *
416 * @param bool $relativeToCurrentScript Determines whether the URL returned should be relative to the current script, in case it is relative at all (only for the LocalDriver)
417 * @return string
418 */
419 public function getPublicUrl($relativeToCurrentScript = FALSE) {
420 return $this->originalFile->getPublicUrl($relativeToCurrentScript);
421 }
422
423 /**
424 * Returns TRUE if this file is indexed.
425 * This is always true for FileReference objects, as they rely on a
426 * sys_file_reference record to be present, which in turn can only exist if
427 * the original file is indexed.
428 *
429 * @return bool
430 */
431 public function isIndexed() {
432 return TRUE;
433 }
434
435 /**
436 * Returns a path to a local version of this file to process it locally (e.g. with some system tool).
437 * If the file is normally located on a remote storages, this creates a local copy.
438 * If the file is already on the local system, this only makes a new copy if $writable is set to TRUE.
439 *
440 * @param bool $writable Set this to FALSE if you only want to do read operations on the file.
441 * @return string
442 */
443 public function getForLocalProcessing($writable = TRUE) {
444 return $this->originalFile->getForLocalProcessing($writable);
445 }
446
447 /**
448 * Returns an array representation of the file.
449 * (This is used by the generic listing module vidi when displaying file records.)
450 *
451 * @return array Array of main data of the file. Don't rely on all data to be present here, it's just a selection of the most relevant information.
452 */
453 public function toArray() {
454 $array = array_merge($this->originalFile->toArray(), $this->propertiesOfFileReference);
455 return $array;
456 }
457
458 /**
459 * Gets the original file being referenced.
460 *
461 * @return File
462 */
463 public function getOriginalFile() {
464 return $this->originalFile;
465 }
466
467 /**
468 * Get hashed identifier
469 *
470 * @return string
471 */
472 public function getHashedIdentifier() {
473 return $this->getStorage()->hashFileIdentifier($this->getIdentifier());
474 }
475
476 /**
477 * Returns the parent folder.
478 *
479 * @return FolderInterface
480 */
481 public function getParentFolder() {
482 return $this->originalFile->getParentFolder();
483 }
484
485 }