Completed
Push — master ( c2ed6d...2771a9 )
by
unknown
19:03
created

File::updateProperties()   C

Complexity

Conditions 12
Paths 128

Size

Total Lines 31
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 17
nc 128
nop 1
dl 0
loc 31
rs 6.7333
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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