Completed
Push — master ( f65802...ddb531 )
by
unknown
39:08 queued 15:48
created

File::getUpdatedProperties()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the TYPO3 CMS project.
5
 *
6
 * It is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License, either version 2
8
 * of the License, or any later version.
9
 *
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 *
13
 * The TYPO3 project - inspiring people to share!
14
 */
15
16
namespace TYPO3\CMS\Core\Resource;
17
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20
/**
21
 * File representation in the file abstraction layer.
22
 */
23
class File extends AbstractFile
24
{
25
    /**
26
     * Contains the names of all properties that have been update since the
27
     * instantiation of this object
28
     *
29
     * @var array
30
     */
31
    protected $updatedProperties = [];
32
33
    /**
34
     * @var MetaDataAspect
35
     */
36
    private $metaDataAspect;
37
38
    /**
39
     * Constructor for a file object. Should normally not be used directly, use
40
     * the corresponding factory methods instead.
41
     *
42
     * @param array $fileData
43
     * @param ResourceStorage $storage
44
     * @param array $metaData
45
     */
46
    public function __construct(array $fileData, ResourceStorage $storage, array $metaData = [])
47
    {
48
        $this->identifier = $fileData['identifier'] ?? null;
49
        $this->name = $fileData['name'] ?? '';
50
        $this->properties = $fileData;
51
        $this->storage = $storage;
52
53
        if (!empty($metaData)) {
54
            $this->getMetaData()->add($metaData);
55
        }
56
    }
57
58
    /*******************************
59
     * VARIOUS FILE PROPERTY GETTERS
60
     *******************************/
61
    /**
62
     * Returns a property value
63
     *
64
     * @param string $key
65
     * @return mixed Property value
66
     */
67
    public function getProperty($key)
68
    {
69
        if (parent::hasProperty($key)) {
70
            return parent::getProperty($key);
71
        }
72
        return $this->getMetaData()[$key];
73
    }
74
75
    /**
76
     * Checks if the file has a (metadata) property which
77
     * can be retrieved by "getProperty"
78
     *
79
     * @param string $key
80
     * @return bool
81
     */
82
    public function hasProperty($key): bool
83
    {
84
        if (!parent::hasProperty($key)) {
85
            return isset($this->getMetaData()[$key]);
86
        }
87
        return true;
88
    }
89
90
    /**
91
     * Returns the properties of this object.
92
     *
93
     * @return array
94
     */
95
    public function getProperties(): array
96
    {
97
        return array_merge(parent::getProperties(), array_diff_key($this->getMetaData()->get(), parent::getProperties()));
98
    }
99
100
    /******************
101
     * CONTENTS RELATED
102
     ******************/
103
    /**
104
     * Get the contents of this file
105
     *
106
     * @return string File contents
107
     */
108
    public function getContents()
109
    {
110
        return $this->getStorage()->getFileContents($this);
111
    }
112
113
    /**
114
     * Gets SHA1 hash.
115
     *
116
     * @return string
117
     */
118
    public function getSha1()
119
    {
120
        if (empty($this->properties['sha1'])) {
121
            $this->properties['sha1'] = parent::getSha1();
122
        }
123
        return $this->properties['sha1'];
124
    }
125
126
    /**
127
     * Replace the current file contents with the given string
128
     *
129
     * @param string $contents The contents to write to the file.
130
     * @return File The file object (allows chaining).
131
     */
132
    public function setContents($contents)
133
    {
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|null
145
     */
146
    public function isIndexed()
147
    {
148
        return true;
149
    }
150
151
    /**
152
     * Updates the properties of this file, e.g. after re-indexing or moving it.
153
     * By default, only properties that exist as a key in the $properties array
154
     * are overwritten. If you want to explicitly unset a property, set the
155
     * corresponding key to NULL in the array.
156
     *
157
     * NOTE: This method should not be called from outside the File Abstraction Layer (FAL)!
158
     *
159
     * @param array $properties
160
     * @internal
161
     */
162
    public function updateProperties(array $properties)
163
    {
164
        // Setting identifier and name to update values; we have to do this
165
        // here because we might need a new identifier when loading
166
        // (and thus possibly indexing) a file.
167
        if (isset($properties['identifier'])) {
168
            $this->identifier = $properties['identifier'];
169
        }
170
        if (isset($properties['name'])) {
171
            $this->name = $properties['name'];
172
        }
173
174
        if (isset($properties['uid']) && $this->properties['uid'] != 0) {
175
            unset($properties['uid']);
176
        }
177
        foreach ($properties as $key => $value) {
178
            if ($this->properties[$key] !== $value) {
179
                if (!in_array($key, $this->updatedProperties)) {
180
                    $this->updatedProperties[] = $key;
181
                }
182
                $this->properties[$key] = $value;
183
            }
184
        }
185
        // If the mime_type property should be updated and it was changed also update the type.
186
        if (array_key_exists('mime_type', $properties) && in_array('mime_type', $this->updatedProperties)) {
187
            $this->updatedProperties[] = 'type';
188
            unset($this->properties['type']);
189
            $this->getType();
190
        }
191
        if (array_key_exists('storage', $properties) && in_array('storage', $this->updatedProperties)) {
192
            $this->storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject($properties['storage']);
193
        }
194
    }
195
196
    /**
197
     * Returns the names of all properties that have been updated in this record
198
     *
199
     * @return array
200
     */
201
    public function getUpdatedProperties()
202
    {
203
        return $this->updatedProperties;
204
    }
205
206
    /****************************************
207
     * STORAGE AND MANAGEMENT RELATED METHODS
208
     ****************************************/
209
    /**
210
     * Check if a file operation (= action) is allowed for this file
211
     *
212
     * @param string $action can be read, write, delete
213
     * @return bool
214
     */
215
    public function checkActionPermission($action)
216
    {
217
        return $this->getStorage()->checkFileActionPermission($action, $this);
218
    }
219
220
    /*****************
221
     * SPECIAL METHODS
222
     *****************/
223
    /**
224
     * Creates a MD5 hash checksum based on the combined identifier of the file,
225
     * the files' mimetype and the systems' encryption key.
226
     * used to generate a thumbnail, and this hash is checked if valid
227
     *
228
     * @return string the MD5 hash
229
     */
230
    public function calculateChecksum()
231
    {
232
        return md5(
233
            $this->getCombinedIdentifier() . '|' .
234
            $this->getMimeType() . '|' .
235
            $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']
236
        );
237
    }
238
239
    /**
240
     * Returns a modified version of the file.
241
     *
242
     * @param string $taskType The task type of this processing
243
     * @param array $configuration the processing configuration, see manual for that
244
     * @return ProcessedFile The processed file
245
     */
246
    public function process($taskType, array $configuration)
247
    {
248
        return $this->getStorage()->processFile($this, $taskType, $configuration);
249
    }
250
251
    /**
252
     * Returns an array representation of the file.
253
     * (This is used by the generic listing module vidi when displaying file records.)
254
     *
255
     * @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.
256
     */
257
    public function toArray()
258
    {
259
        $array = [
260
            'id' => $this->getCombinedIdentifier(),
261
            'name' => $this->getName(),
262
            'extension' => $this->getExtension(),
263
            'type' => $this->getType(),
264
            'mimetype' => $this->getMimeType(),
265
            'size' => $this->getSize(),
266
            'url' => $this->getPublicUrl(),
267
            'indexed' => true,
268
            'uid' => $this->getUid(),
269
            'permissions' => [
270
                'read' => $this->checkActionPermission('read'),
271
                'write' => $this->checkActionPermission('write'),
272
                'delete' => $this->checkActionPermission('delete')
273
            ],
274
            'checksum' => $this->calculateChecksum()
275
        ];
276
        foreach ($this->properties as $key => $value) {
277
            $array[$key] = $value;
278
        }
279
        $stat = $this->getStorage()->getFileInfo($this);
280
        foreach ($stat as $key => $value) {
281
            $array[$key] = $value;
282
        }
283
        return $array;
284
    }
285
286
    /**
287
     * @return bool
288
     */
289
    public function isMissing()
290
    {
291
        return (bool)$this->getProperty('missing');
292
    }
293
294
    /**
295
     * @param bool $missing
296
     */
297
    public function setMissing($missing)
298
    {
299
        $this->updateProperties(['missing' => $missing ? 1 : 0]);
300
    }
301
302
    /**
303
     * Returns a publicly accessible URL for this file
304
     * When file is marked as missing or deleted no url is returned
305
     *
306
     * WARNING: Access to the file may be restricted by further means, e.g. some
307
     * web-based authentication. You have to take care of this yourself.
308
     *
309
     * @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)
310
     *
311
     * @return string|null NULL if file is missing or deleted, the generated url otherwise
312
     */
313
    public function getPublicUrl($relativeToCurrentScript = false)
314
    {
315
        if ($this->isMissing() || $this->deleted) {
316
            return null;
317
        }
318
        return $this->getStorage()->getPublicUrl($this, $relativeToCurrentScript);
319
    }
320
321
    /**
322
     * @param string $key
323
     * @internal Only for use in Repositories and indexer
324
     * @return mixed
325
     */
326
    public function _getPropertyRaw($key)
327
    {
328
        return parent::getProperty($key);
329
    }
330
331
    /**
332
     * Loads the metadata of a file in an encapsulated aspect
333
     *
334
     * @return MetaDataAspect
335
     */
336
    public function getMetaData(): MetaDataAspect
337
    {
338
        if ($this->metaDataAspect === null) {
339
            $this->metaDataAspect = GeneralUtility::makeInstance(MetaDataAspect::class, $this);
340
        }
341
        return $this->metaDataAspect;
342
    }
343
}
344