Completed
Push — master ( 522461...c89cc2 )
by Fabien
02:24
created

MediaModule::getDataService()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
namespace Fab\Media\Module;
3
4
/*
5
 * This file is part of the Fab/Media project under GPLv2 or later.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE.md file that was distributed with this source code.
9
 */
10
11
use Fab\Media\FileUpload\UploadedFileInterface;
12
use Fab\Media\Utility\SessionUtility;
13
use Fab\Vidi\Service\DataService;
14
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
15
use TYPO3\CMS\Core\Resource\File;
16
use TYPO3\CMS\Core\Resource\Folder;
17
use TYPO3\CMS\Core\Resource\ResourceFactory;
18
use TYPO3\CMS\Core\Resource\ResourceStorage;
19
use TYPO3\CMS\Core\Resource\StorageRepository;
20
use TYPO3\CMS\Core\SingletonInterface;
21
use TYPO3\CMS\Core\Utility\GeneralUtility;
22
23
/**
24
 * Class for retrieving information about the Media module.
25
 */
26
class MediaModule implements SingletonInterface
27
{
28
29
    /**
30
     * @var string
31
     */
32
    const SIGNATURE = 'user_MediaM1';
33
34
    /**
35
     * @var string
36
     */
37
    const PARAMETER_PREFIX = 'tx_media_user_mediam1';
38
39
    /**
40
     * @var ResourceStorage
41
     */
42
    protected $currentStorage;
43
44
    /**
45
     * @return string
46
     */
47
    static public function getSignature()
48
    {
49
        return self::SIGNATURE;
50
    }
51
52
    /**
53
     * @return string
54
     */
55
    static public function getParameterPrefix()
56
    {
57
        return self::PARAMETER_PREFIX;
58
    }
59
60
    /**
61
     * Return all storage allowed for the Backend User.
62
     *
63
     * @throws \RuntimeException
64
     * @return ResourceStorage[]
65
     */
66
    public function getAllowedStorages()
67
    {
68
69
        $storages = $this->getBackendUser()->getFileStorages();
70
        if (empty($storages)) {
71
            throw new \RuntimeException('No storage is accessible for the current BE User. Forgotten to define a mount point for this BE User?', 1380801970);
72
        }
73
        return $storages;
74
    }
75
76
    /**
77
     * Returns the current file storage in use.
78
     *
79
     * @return ResourceStorage
80
     */
81
    public function getCurrentStorage()
82
    {
83
        if (is_null($this->currentStorage)) {
84
85
            $storageIdentifier = $this->getStorageIdentifierFromSessionOrArguments();
86
87
            if ($storageIdentifier > 0) {
88
                $currentStorage = ResourceFactory::getInstance()->getStorageObject($storageIdentifier);
89
            } else {
90
91
                // We differentiate the cases whether the User is admin or not.
92
                if ($this->getBackendUser()->isAdmin()) {
93
94
                    $currentStorage = ResourceFactory::getInstance()->getDefaultStorage();
95
96
                    // Not default storage has been flagged in "sys_file_storage".
97
                    // Fallback approach: take the first storage as the current.
98
                    if (!$currentStorage) {
99
                        /** @var $storageRepository StorageRepository */
100
                        $storageRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\StorageRepository::class);
101
102
                        $storages = $storageRepository->findAll();
103
                        $currentStorage = current($storages);
104
                    }
105
                } else {
106
                    $fileMounts = $this->getBackendUser()->getFileMountRecords();
107
                    $firstFileMount = current($fileMounts);
108
                    $currentStorage = ResourceFactory::getInstance()->getStorageObject($firstFileMount['base']);
109
                }
110
            }
111
112
            $this->currentStorage = $currentStorage;
113
        }
114
        return $this->currentStorage;
115
    }
116
117
    /**
118
     * Retrieve a possible storage identifier from the session or from the arguments.
119
     *
120
     * @return int
121
     */
122
    protected function getStorageIdentifierFromSessionOrArguments()
123
    {
124
125
        // Default value
126
        $storageIdentifier = 0;
127
128
        // Get last selected storage from User settings
129
        if (SessionUtility::getInstance()->get('lastSelectedStorage') > 0) {
130
            $storageIdentifier = SessionUtility::getInstance()->get('lastSelectedStorage');
131
        }
132
133
        $argumentPrefix = $this->getModuleLoader()->getParameterPrefix();
134
        $arguments = GeneralUtility::_GET($argumentPrefix);
135
136
        // Override selected storage from the session if GET argument "storage" is detected.
137
        if (!empty($arguments['storage']) && (int)$arguments['storage'] > 0) {
138
            $storageIdentifier = (int)$arguments['storage'];
139
140
            // Save state
141
            SessionUtility::getInstance()->set('lastSelectedStorage', $storageIdentifier);
142
        }
143
144
        return (int)$storageIdentifier;
145
    }
146
147
    /**
148
     * Return the combined parameter from the URL.
149
     *
150
     * @return string
151
     */
152
    public function getCombinedIdentifier()
153
    {
154
155
        // Fetch possible combined identifier.
156
        $combinedIdentifier = GeneralUtility::_GET('id');
157
158
        if ($combinedIdentifier) {
159
160
            // Fix a bug at the Core level: the "id" parameter is encoded again when translating file.
161
            // Add a loop to decode maximum 999 time!
162
            $semaphore = 0;
163
            $semaphoreLimit = 999;
164
            while (!$this->isWellDecoded($combinedIdentifier) && $semaphore < $semaphoreLimit) {
165
                $combinedIdentifier = urldecode($combinedIdentifier);
166
                $semaphore++;
167
            }
168
        }
169
170
        return $combinedIdentifier;
171
    }
172
173
    /**
174
     * @param $combinedIdentifier
175
     * @return bool
176
     */
177
    protected function isWellDecoded($combinedIdentifier)
178
    {
179
        return preg_match('/.*:.*/', $combinedIdentifier);
180
    }
181
182
    /**
183
     * @return Folder
184
     */
185
    public function getFirstAvailableFolder()
186
    {
187
188
        // Take the first object of the first storage.
189
        $storages = $this->getBackendUser()->getFileStorages();
190
        $storage = reset($storages);
191
        if ($storage) {
192
            $folder = $storage->getRootLevelFolder();
193
        } else {
194
            throw new \RuntimeException('Could not find any folder to be displayed.', 1444665954);
195
        }
196
        return $folder;
197
    }
198
199
    /**
200
     * @return Folder
201
     */
202
    public function getCurrentFolder()
203
    {
204
205
        $combinedIdentifier = $this->getCombinedIdentifier();
206
207
        if ($combinedIdentifier) {
208
            $folder = $this->getFolderForCombinedIdentifier($combinedIdentifier);
209
        } else {
210
            $folder = $this->getFirstAvailableFolder();
211
        }
212
213
        return $folder;
214
    }
215
216
    /**
217
     * @param string $combinedIdentifier
218
     * @return Folder
219
     */
220
    public function getFolderForCombinedIdentifier($combinedIdentifier)
221
    {
222
223
        // Code taken from FileListController.php
224
        $storage = ResourceFactory::getInstance()->getStorageObjectFromCombinedIdentifier($combinedIdentifier);
225
        $identifier = substr($combinedIdentifier, strpos($combinedIdentifier, ':') + 1);
226
        if (!$storage->hasFolder($identifier)) {
227
            $identifier = $storage->getFolderIdentifierFromFileIdentifier($identifier);
228
        }
229
230
        // Retrieve the folder object.
231
        $folder = ResourceFactory::getInstance()->getFolderObjectFromCombinedIdentifier($storage->getUid() . ':' . $identifier);
232
233
        // Disallow the rendering of the processing folder (e.g. could be called manually)
234
        // and all folders without any defined storage
235
        if ($folder && ($folder->getStorage()->getUid() == 0 || trim($folder->getStorage()->getProcessingFolder()->getIdentifier(), '/') === trim($folder->getIdentifier(), '/'))) {
236
            $storage = ResourceFactory::getInstance()->getStorageObjectFromCombinedIdentifier($combinedIdentifier);
237
            $folder = $storage->getRootLevelFolder();
238
        }
239
240
        return $folder;
241
    }
242
243
    /**
244
     * Tell whether the Folder Tree is display or not.
245
     *
246
     * @return bool
247
     */
248
    public function hasFolderTree()
249
    {
250
        $configuration = $this->getModuleConfiguration();
251
        return (bool)$configuration['has_folder_tree'];
252
    }
253
254
    /**
255
     * Tell whether the sub-folders must be included when browsing.
256
     *
257
     * @return bool
258
     */
259
    public function hasRecursiveSelection()
260
    {
261
262
        $parameterPrefix = $this->getModuleLoader()->getParameterPrefix();
263
        $parameters = GeneralUtility::_GET($parameterPrefix);
264
265
        $hasRecursiveSelection = true;
266
        if (isset($parameters['hasRecursiveSelection'])) {
267
            $hasRecursiveSelection = (bool)$parameters['hasRecursiveSelection'];
268
        }
269
270
        return $hasRecursiveSelection;
271
    }
272
273
    /**
274
     * Return the target folder for the uploaded file.
275
     *
276
     * @param UploadedFileInterface $uploadedFile
277
     * @param ResourceStorage $storage
278
     * @return \TYPO3\CMS\Core\Resource\Folder
279
     */
280 View Code Duplication
    public function getTargetFolderForUploadedFile(UploadedFileInterface $uploadedFile, ResourceStorage $storage)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
281
    {
282
283
        // default is the root level
284
        $folder = $storage->getRootLevelFolder(); // get the root folder by default
285
286
        // Get a possible mount point coming from the storage record.
287
        $storageRecord = $storage->getStorageRecord();
288
        $mountPointIdentifier = $storageRecord['mount_point_file_type_' . $uploadedFile->getType()];
289
        if ($mountPointIdentifier > 0) {
290
291
            // We don't have a Mount Point repository in FAL, so query the database directly.
292
            $record = $this->getDataService()->getRecord('sys_filemounts', ['uid' => $mountPointIdentifier]);
293
294
            if (!empty($record['path'])) {
295
                $folder = $storage->getFolder($record['path']);
296
            }
297
        }
298
        return $folder;
299
    }
300
301
    /**
302
     * Return a new target folder when moving file from one storage to another.
303
     *
304
     * @param ResourceStorage $storage
305
     * @param File $file
306
     * @return \TYPO3\CMS\Core\Resource\Folder
307
     */
308 View Code Duplication
    public function getDefaultFolderInStorage(ResourceStorage $storage, File $file)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
309
    {
310
311
        // default is the root level
312
        $folder = $storage->getRootLevelFolder();
313
314
        // Retrieve storage record and a possible configured mount point.
315
        $storageRecord = $storage->getStorageRecord();
316
        $mountPointIdentifier = $storageRecord['mount_point_file_type_' . $file->getType()];
317
318
        if ($mountPointIdentifier > 0) {
319
320
            // We don't have a Mount Point repository in FAL, so query the database directly.
321
            $record = $this->getDataService()->getRecord('sys_filemounts', ['uid' => $mountPointIdentifier]);
322
            if (!empty($record['path'])) {
323
                $folder = $storage->getFolder($record['path']);
324
            }
325
        }
326
        return $folder;
327
    }
328
329
    /**
330
     * @return array
331
     */
332
    protected function getModuleConfiguration()
333
    {
334
        return GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('media');
335
    }
336
337
    /**
338
     * @return object|DataService
339
     */
340
    protected function getDataService(): DataService
341
    {
342
        return GeneralUtility::makeInstance(DataService::class);
343
    }
344
345
    /**
346
     * Returns an instance of the current Backend User.
347
     *
348
     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
349
     */
350
    protected function getBackendUser()
351
    {
352
        return $GLOBALS['BE_USER'];
353
    }
354
355
    /**
356
     * Return the module loader.
357
     *
358
     * @return \Fab\Vidi\Module\ModuleLoader|object
359
     */
360
    protected function getModuleLoader()
361
    {
362
        return GeneralUtility::makeInstance(\Fab\Vidi\Module\ModuleLoader::class);
363
    }
364
365
}