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