[TASK] Removes extra empty lines
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / File.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 use TYPO3\CMS\Core\Utility\GeneralUtility;
18
19 /**
20 * File representation in the file abstraction layer.
21 *
22 */
23 class File extends AbstractFile
24 {
25 /**
26 * @var bool
27 */
28 protected $metaDataLoaded = false;
29
30 /**
31 * @var array
32 */
33 protected $metaDataProperties = array();
34
35 /**
36 * Set to TRUE while this file is being indexed - used to prevent some endless loops
37 *
38 * @var bool
39 */
40 protected $indexingInProgress = false;
41
42 /**
43 * Contains the names of all properties that have been update since the
44 * instantiation of this object
45 *
46 * @var array
47 */
48 protected $updatedProperties = array();
49
50 /**
51 * Constructor for a file object. Should normally not be used directly, use
52 * the corresponding factory methods instead.
53 *
54 * @param array $fileData
55 * @param ResourceStorage $storage
56 * @param array $metaData
57 */
58 public function __construct(array $fileData, ResourceStorage $storage, array $metaData = array())
59 {
60 $this->identifier = $fileData['identifier'];
61 $this->name = $fileData['name'];
62 $this->properties = $fileData;
63 $this->storage = $storage;
64 if (!empty($metaData)) {
65 $this->metaDataLoaded = true;
66 $this->metaDataProperties = $metaData;
67 }
68 }
69
70 /*******************************
71 * VARIOUS FILE PROPERTY GETTERS
72 *******************************/
73 /**
74 * Returns a property value
75 *
76 * @param string $key
77 * @return mixed Property value
78 */
79 public function getProperty($key)
80 {
81 if (parent::hasProperty($key)) {
82 return parent::getProperty($key);
83 } else {
84 $metaData = $this->_getMetaData();
85 return isset($metaData[$key]) ? $metaData[$key] : null;
86 }
87 }
88
89 /**
90 * Checks if the file has a (metadata) property which
91 * can be retrieved by "getProperty"
92 *
93 * @param string $key
94 * @return bool
95 */
96 public function hasProperty($key)
97 {
98 if (!parent::hasProperty($key)) {
99 return array_key_exists($key, $this->_getMetaData());
100 }
101 return true;
102 }
103
104 /**
105 * Returns the properties of this object.
106 *
107 * @return array
108 */
109 public function getProperties()
110 {
111 return array_merge(parent::getProperties(), array_diff_key($this->_getMetaData(), parent::getProperties()));
112 }
113
114 /**
115 * Returns the MetaData
116 *
117 * @return array
118 * @internal
119 */
120 public function _getMetaData()
121 {
122 if (!$this->metaDataLoaded) {
123 $this->loadMetaData();
124 }
125 return $this->metaDataProperties;
126 }
127
128 /******************
129 * CONTENTS RELATED
130 ******************/
131 /**
132 * Get the contents of this file
133 *
134 * @return string File contents
135 */
136 public function getContents()
137 {
138 return $this->getStorage()->getFileContents($this);
139 }
140
141 /**
142 * Gets SHA1 hash.
143 *
144 * @return string
145 */
146 public function getSha1()
147 {
148 if (empty($this->properties['sha1'])) {
149 $this->properties['sha1'] = parent::getSha1();
150 }
151 return $this->properties['sha1'];
152 }
153
154 /**
155 * Replace the current file contents with the given string
156 *
157 * @param string $contents The contents to write to the file.
158 * @return File The file object (allows chaining).
159 */
160 public function setContents($contents)
161 {
162 $this->getStorage()->setFileContents($this, $contents);
163 return $this;
164 }
165
166 /***********************
167 * INDEX RELATED METHODS
168 ***********************/
169 /**
170 * Returns TRUE if this file is indexed
171 *
172 * @return bool|NULL
173 */
174 public function isIndexed()
175 {
176 return true;
177 }
178
179 /**
180 * Loads MetaData from Repository
181 * @return void
182 */
183 protected function loadMetaData()
184 {
185 if (!$this->indexingInProgress) {
186 $this->indexingInProgress = true;
187 $this->metaDataProperties = $this->getMetaDataRepository()->findByFile($this);
188 $this->metaDataLoaded = true;
189 $this->indexingInProgress = false;
190 }
191 }
192
193 /**
194 * Updates the properties of this file, e.g. after re-indexing or moving it.
195 * By default, only properties that exist as a key in the $properties array
196 * are overwritten. If you want to explicitly unset a property, set the
197 * corresponding key to NULL in the array.
198 *
199 * NOTE: This method should not be called from outside the File Abstraction Layer (FAL)!
200 *
201 * @param array $properties
202 * @return void
203 * @internal
204 */
205 public function updateProperties(array $properties)
206 {
207 // Setting identifier and name to update values; we have to do this
208 // here because we might need a new identifier when loading
209 // (and thus possibly indexing) a file.
210 if (isset($properties['identifier'])) {
211 $this->identifier = $properties['identifier'];
212 }
213 if (isset($properties['name'])) {
214 $this->name = $properties['name'];
215 }
216
217 if ($this->properties['uid'] != 0 && isset($properties['uid'])) {
218 unset($properties['uid']);
219 }
220 foreach ($properties as $key => $value) {
221 if ($this->properties[$key] !== $value) {
222 if (!in_array($key, $this->updatedProperties)) {
223 $this->updatedProperties[] = $key;
224 }
225 $this->properties[$key] = $value;
226 }
227 }
228 // If the mime_type property should be updated and it was changed also update the type.
229 if (array_key_exists('mime_type', $properties) && in_array('mime_type', $this->updatedProperties)) {
230 $this->updatedProperties[] = 'type';
231 unset($this->properties['type']);
232 $this->getType();
233 }
234 if (array_key_exists('storage', $properties) && in_array('storage', $this->updatedProperties)) {
235 $this->storage = ResourceFactory::getInstance()->getStorageObject($properties['storage']);
236 }
237 }
238
239 /**
240 * Updates MetaData properties
241 *
242 * @internal Do not use outside the FileAbstraction Layer classes
243 *
244 * @param array $properties
245 * @return void
246 */
247 public function _updateMetaDataProperties(array $properties)
248 {
249 $this->metaDataProperties = array_merge($this->metaDataProperties, $properties);
250 }
251
252 /**
253 * Returns the names of all properties that have been updated in this record
254 *
255 * @return array
256 */
257 public function getUpdatedProperties()
258 {
259 return $this->updatedProperties;
260 }
261
262 /****************************************
263 * STORAGE AND MANAGEMENT RELATED METHODS
264 ****************************************/
265 /**
266 * Check if a file operation (= action) is allowed for this file
267 *
268 * @param string $action, can be read, write, delete
269 * @return bool
270 */
271 public function checkActionPermission($action)
272 {
273 return $this->getStorage()->checkFileActionPermission($action, $this);
274 }
275
276 /*****************
277 * SPECIAL METHODS
278 *****************/
279 /**
280 * Creates a MD5 hash checksum based on the combined identifier of the file,
281 * the files' mimetype and the systems' encryption key.
282 * used to generate a thumbnail, and this hash is checked if valid
283 *
284 * @return string the MD5 hash
285 */
286 public function calculateChecksum()
287 {
288 return md5(
289 $this->getCombinedIdentifier() . '|' .
290 $this->getMimeType() . '|' .
291 $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']
292 );
293 }
294
295 /**
296 * Returns a modified version of the file.
297 *
298 * @param string $taskType The task type of this processing
299 * @param array $configuration the processing configuration, see manual for that
300 * @return ProcessedFile The processed file
301 */
302 public function process($taskType, array $configuration)
303 {
304 return $this->getStorage()->processFile($this, $taskType, $configuration);
305 }
306
307 /**
308 * Returns an array representation of the file.
309 * (This is used by the generic listing module vidi when displaying file records.)
310 *
311 * @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.
312 */
313 public function toArray()
314 {
315 $array = array(
316 'id' => $this->getCombinedIdentifier(),
317 'name' => $this->getName(),
318 'extension' => $this->getExtension(),
319 'type' => $this->getType(),
320 'mimetype' => $this->getMimeType(),
321 'size' => $this->getSize(),
322 'url' => $this->getPublicUrl(),
323 'indexed' => true,
324 'uid' => $this->getUid(),
325 'permissions' => array(
326 'read' => $this->checkActionPermission('read'),
327 'write' => $this->checkActionPermission('write'),
328 'delete' => $this->checkActionPermission('delete')
329 ),
330 'checksum' => $this->calculateChecksum()
331 );
332 foreach ($this->properties as $key => $value) {
333 $array[$key] = $value;
334 }
335 $stat = $this->getStorage()->getFileInfo($this);
336 foreach ($stat as $key => $value) {
337 $array[$key] = $value;
338 }
339 return $array;
340 }
341
342 /**
343 * @return bool
344 */
345 public function isMissing()
346 {
347 return (bool)$this->getProperty('missing');
348 }
349
350 /**
351 * @param bool $missing
352 */
353 public function setMissing($missing)
354 {
355 $this->updateProperties(array('missing' => $missing ? 1 : 0));
356 }
357
358 /**
359 * Returns a publicly accessible URL for this file
360 * When file is marked as missing or deleted no url is returned
361 *
362 * WARNING: Access to the file may be restricted by further means, e.g. some
363 * web-based authentication. You have to take care of this yourself.
364 *
365 * @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)
366 *
367 * @return string
368 */
369 public function getPublicUrl($relativeToCurrentScript = false)
370 {
371 if ($this->isMissing() || $this->deleted) {
372 return false;
373 } else {
374 return $this->getStorage()->getPublicUrl($this, $relativeToCurrentScript);
375 }
376 }
377
378 /**
379 * @return \TYPO3\CMS\Core\Resource\Index\MetaDataRepository
380 */
381 protected function getMetaDataRepository()
382 {
383 return GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Index\MetaDataRepository::class);
384 }
385
386 /**
387 * @return \TYPO3\CMS\Core\Resource\Index\FileIndexRepository
388 */
389 protected function getFileIndexRepository()
390 {
391 return GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Index\FileIndexRepository::class);
392 }
393
394 /**
395 * @return void
396 * @internal Only for usage in Indexer
397 */
398 public function setIndexingInProgess($indexingState)
399 {
400 $this->indexingInProgress = (bool)$indexingState;
401 }
402
403 /**
404 * @param $key
405 * @internal Only for use in Repositories and indexer
406 * @return mixed
407 */
408 public function _getPropertyRaw($key)
409 {
410 return parent::getProperty($key);
411 }
412 }