[TASK] Move and Namespace classes
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Resource / File.php
1 <?php
2 namespace TYPO3\CMS\Core\Resource;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2011 Ingo Renner <ingo@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * File representation in the file abstraction layer.
31 *
32 * @author Andreas Wolf <andreas.wolf@ikt-werk.de>
33 * @package TYPO3
34 * @subpackage t3lib
35 */
36 class File extends \TYPO3\CMS\Core\Resource\AbstractFile {
37
38 /**
39 * File indexing status. True, if the file is indexed in the database;
40 * NULL is the default value, this means that the index status is unknown
41 *
42 * @var bool
43 */
44 protected $indexed = NULL;
45
46 /**
47 * Set to TRUE while this file is being indexed - used to prevent some endless loops
48 *
49 * @var bool
50 */
51 protected $indexingInProgress = FALSE;
52
53 /**
54 * Contains the names of all properties that have been update since the
55 * instantiation of this object
56 *
57 * @var array
58 */
59 protected $updatedProperties = array();
60
61 /*********************************************
62 * GENERIC FILE TYPES
63 * these are generic filetypes or -groups,
64 * don't mix it up with mime types
65 *********************************************/
66 /**
67 * Constructor for a file object. Should normally not be used directly, use
68 * the corresponding factory methods instead.
69 *
70 * @param array $fileData
71 * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storage
72 */
73 public function __construct(array $fileData, $storage = NULL) {
74 if (isset($fileData['uid']) && intval($fileData['uid']) > 0) {
75 $this->indexed = TRUE;
76 }
77 $this->identifier = $fileData['identifier'];
78 $this->name = $fileData['name'];
79 $this->properties = $fileData;
80 if (is_object($storage)) {
81 $this->storage = $storage;
82 } elseif (isset($fileData['storage']) && is_object($fileData['storage'])) {
83 $this->storage = $fileData['storage'];
84 }
85 }
86
87 /*******************************
88 * VARIOUS FILE PROPERTY GETTERS
89 *******************************/
90 /**
91 * Returns a property value
92 *
93 * @param string $key
94 * @return mixed Property value
95 */
96 public function getProperty($key) {
97 if ($this->indexed === NULL) {
98 $this->loadIndexRecord();
99 }
100 return parent::getProperty($key);
101 }
102
103 /**
104 * Returns the properties of this object.
105 *
106 * @return array
107 */
108 public function getProperties() {
109 if ($this->indexed === NULL) {
110 $this->loadIndexRecord();
111 }
112 return parent::getProperties();
113 }
114
115 /******************
116 * CONTENTS RELATED
117 ******************/
118 /**
119 * Get the contents of this file
120 *
121 * @return string File contents
122 */
123 public function getContents() {
124 return $this->getStorage()->getFileContents($this);
125 }
126
127 /**
128 * Replace the current file contents with the given string
129 *
130 * @param string $contents The contents to write to the file.
131 * @return \TYPO3\CMS\Core\Resource\File The file object (allows chaining).
132 */
133 public function setContents($contents) {
134 $this->getStorage()->setFileContents($this, $contents);
135 return $this;
136 }
137
138 /***********************
139 * INDEX RELATED METHODS
140 ***********************/
141 /**
142 * Returns TRUE if this file is indexed
143 *
144 * @return bool
145 */
146 public function isIndexed() {
147 if ($this->indexed === NULL && !$this->indexingInProgress) {
148 $this->loadIndexRecord();
149 }
150 return $this->indexed;
151 }
152
153 /**
154 * @param bool $indexIfNotIndexed
155 * @return void
156 */
157 protected function loadIndexRecord($indexIfNotIndexed = TRUE) {
158 if ($this->indexed !== NULL) {
159 return;
160 }
161 /** @var $repo \TYPO3\CMS\Core\Resource\FileRepository */
162 $repo = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository');
163 $indexRecord = $repo->getFileIndexRecord($this);
164 if ($indexRecord === FALSE && $indexIfNotIndexed) {
165 $this->indexingInProgress = TRUE;
166 $indexRecord = $repo->addToIndex($this);
167 $this->mergeIndexRecord($indexRecord);
168 $this->indexed = TRUE;
169 $this->indexingInProgress = FALSE;
170 } elseif ($indexRecord !== FALSE) {
171 $this->mergeIndexRecord($indexRecord);
172 $this->indexed = TRUE;
173 } else {
174 throw new \RuntimeException(('Could not load index record for "' . $this->getIdentifier()) . '"', 1321288316);
175 }
176 }
177
178 /**
179 * Merges the contents of this file's index record into the file properties.
180 *
181 * @param array $recordData The index record as fetched from the database
182 * @return void
183 */
184 protected function mergeIndexRecord(array $recordData) {
185 if ($this->properties['uid'] != 0) {
186 throw new \InvalidArgumentException('uid property is already set. Cannot merge index record.', 1321023156);
187 }
188 $this->properties = array_merge($this->properties, $recordData);
189 }
190
191 /**
192 * Updates the properties of this file, e.g. after re-indexing or moving it.
193 * By default, only properties that exist as a key in the $properties array
194 * are overwritten. If you want to explicitly unset a property, set the
195 * corresponding key to NULL in the array.
196 *
197 * NOTE: This method should not be called from outside the File Abstraction Layer (FAL)!
198 *
199 * @param array $properties
200 * @return void
201 * @internal
202 */
203 public function updateProperties(array $properties) {
204 // Setting identifier and name to update values; we have to do this
205 // here because we might need a new identifier when loading
206 // (and thus possibly indexing) a file.
207 if (isset($properties['identifier'])) {
208 $this->identifier = $properties['identifier'];
209 }
210 if (isset($properties['name'])) {
211 $this->name = $properties['name'];
212 }
213 if ($this->indexed === NULL && !isset($properties['uid'])) {
214 $this->loadIndexRecord();
215 }
216 if ($this->properties['uid'] != 0 && isset($properties['uid'])) {
217 unset($properties['uid']);
218 }
219 foreach ($properties as $key => $value) {
220 if ($this->properties[$key] !== $value) {
221 if (!in_array($key, $this->updatedProperties)) {
222 $this->updatedProperties[] = $key;
223 }
224 // TODO check if we should completely remove properties that
225 // are set to NULL
226 $this->properties[$key] = $value;
227 }
228 }
229 // Updating indexing status
230 if (isset($properties['uid']) && intval($properties['uid']) > 0) {
231 $this->indexed = TRUE;
232 }
233 if (isset($properties['storage'])) {
234 $this->loadStorage();
235 }
236 }
237
238 /**
239 * Returns the names of all properties that have been updated in this record
240 *
241 * @return array
242 */
243 public function getUpdatedProperties() {
244 return $this->updatedProperties;
245 }
246
247 /****************************************
248 * STORAGE AND MANAGEMENT RELATED METHODS
249 ****************************************/
250 /**
251 * Check if a file operation (= action) is allowed for this file
252 *
253 * @param string $action, can be read, write, delete
254 * @return boolean
255 */
256 public function checkActionPermission($action) {
257 return $this->getStorage()->checkFileActionPermission($action, $this);
258 }
259
260 /*****************
261 * SPECIAL METHODS
262 *****************/
263 /**
264 * Creates a MD5 hash checksum based on the combined identifier of the file,
265 * the files' mimetype and the systems' encryption key.
266 * used to generate a thumbnail, and this hash is checked if valid
267 *
268 * @todo maybe t3lib_div::hmac() could be used?
269 * @param \TYPO3\CMS\Core\Resource\File $file the file to create the checksum from
270 * @return string the MD5 hash
271 */
272 public function calculateChecksum() {
273 return md5(((($this->getCombinedIdentifier() . '|') . $this->getMimeType()) . '|') . $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']);
274 }
275
276 /**
277 * Returns a modified version of the file.
278 *
279 * @param string $context the context of the configuration (see above)
280 * @param array $configuration the processing configuration, see manual for that
281 * @return \TYPO3\CMS\Core\Resource\ProcessedFile The processed file
282 */
283 public function process($context, array $configuration) {
284 return $this->getStorage()->processFile($this, $context, $configuration);
285 }
286
287 /**
288 * Returns an array representation of the file.
289 * (This is used by the generic listing module vidi when displaying file records.)
290 *
291 * @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.
292 */
293 public function toArray() {
294 $array = array(
295 'id' => $this->getCombinedIdentifier(),
296 'name' => $this->getName(),
297 'extension' => $this->getExtension(),
298 'type' => $this->getType(),
299 'mimetype' => $this->getMimeType(),
300 'size' => $this->getSize(),
301 'url' => $this->getPublicUrl(),
302 'indexed' => $this->indexed,
303 'uid' => $this->getUid(),
304 'permissions' => array(
305 'read' => $this->checkActionPermission('read'),
306 'write' => $this->checkActionPermission('write'),
307 'delete' => $this->checkActionPermission('delete')
308 ),
309 'checksum' => $this->calculateChecksum()
310 );
311 foreach ($this->properties as $key => $value) {
312 $array[$key] = $value;
313 }
314 $stat = $this->storage->getFileInfo($this);
315 foreach ($stat as $key => $value) {
316 $array[$key] = $value;
317 }
318 return $array;
319 }
320
321 }
322
323
324 ?>