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

FilePermissionsAspect::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\Security;
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\Module\MediaModule;
12
use Fab\Media\Module\VidiModule;
13
use Fab\Vidi\Module\ModuleLoader;
14
use Fab\Vidi\Persistence\ConstraintContainer;
15
use Fab\Vidi\Service\DataService;
16
use Fab\Vidi\Utility\BackendUtility;
17
use TYPO3\CMS\Core\Resource\Folder;
18
use TYPO3\CMS\Core\Resource\ResourceFactory;
19
use TYPO3\CMS\Core\Utility\GeneralUtility;
20
use Fab\Vidi\Persistence\Matcher;
21
use Fab\Vidi\Persistence\Query;
22
use TYPO3\CMS\Extbase\Persistence\Generic\Qom\ConstraintInterface;
23
24
/**
25
 * Class which handle signal slot for Vidi Content controller
26
 */
27
class FilePermissionsAspect
28
{
29
30
    /**
31
     * Post-process the matcher object to respect the file storages.
32
     *
33
     * @param Matcher $matcher
34
     * @param string $dataType
35
     * @return void
36
     * @throws \InvalidArgumentException
37
     */
38
    public function addFilePermissionsForFileStorages(Matcher $matcher, $dataType)
39
    {
40
        if ($dataType === 'sys_file' && $this->isPermissionNecessary()) {
41
42
            if ($this->isFolderConsidered()) {
43
44
                $folder = $this->getMediaModule()->getCurrentFolder();
45
46
                if ($this->getMediaModule()->hasRecursiveSelection()) {
47
48
                    // Only add like condition if needed.
49
                    if ($folder->getStorage()->getRootLevelFolder() !== $folder) {
50
                        $matcher->like('identifier', $folder->getIdentifier() . '%', $automaticallyAddWildCard = false);
51
                    }
52
                } else {
53
54
                    // Browse only currently
55
                    $files = $this->getFileUids($folder);
56
                    $matcher->in('uid', $files);
57
                }
58
59
                $matcher->equals('storage', $folder->getStorage()->getUid());
60
            } else {
61
                $storage = $this->getMediaModule()->getCurrentStorage();
62
63
                // Set the storage identifier only if the storage is on-line.
64
                $identifier = -1;
65
                if ($storage->isOnline()) {
66
                    $identifier = $storage->getUid();
67
                }
68
69
                if ($this->getModuleLoader()->hasPlugin() && !$this->getCurrentBackendUser()->isAdmin()) {
70
71
                    $fileMounts = $this->getCurrentBackendUser()->getFileMountRecords();
72
                    $collectedFiles = [];
73
                    foreach ($fileMounts as $fileMount) {
74
75
                        $combinedIdentifier = $fileMount['base'] . ':' . $fileMount['path'];
76
                        $folder = ResourceFactory::getInstance()->getFolderObjectFromCombinedIdentifier($combinedIdentifier);
77
78
                        $files = $this->getFileUids($folder);
79
                        $collectedFiles = array_merge($collectedFiles, $files);
80
                    }
81
82
                    $matcher->in('uid', $collectedFiles);
83
                }
84
85
                $matcher->equals('storage', $identifier);
86
            }
87
        }
88
    }
89
90
    /**
91
     * @return bool
92
     */
93
    protected function isPermissionNecessary()
94
    {
95
96
        $isNecessary = true;
97
98
        $parameters = GeneralUtility::_GET(VidiModule::getParameterPrefix());
99
100 View Code Duplication
        if ($parameters['controller'] === 'Clipboard' && ($parameters['action'] === 'show' || $parameters['action'] === 'flush')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
101
            $isNecessary = false;
102
        }
103
104 View Code Duplication
        if ($parameters['controller'] === 'Content' && ($parameters['action'] === 'copyClipboard' || $parameters['action'] === 'moveClipboard')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
105
            $isNecessary = false;
106
        }
107
108
        return $isNecessary;
109
    }
110
111
    /**
112
     * @return bool
113
     */
114
    protected function isFolderConsidered()
115
    {
116
        return $this->getMediaModule()->hasFolderTree() && !$this->getModuleLoader()->hasPlugin();
117
    }
118
119
    /**
120
     * @param Folder $folder
121
     * @return array
122
     */
123
    protected function getFileUids(Folder $folder)
124
    {
125
        $files = [];
126
        foreach ($folder->getFiles() as $file) {
127
            $files[] = $file->getUid();
128
        }
129
        return $files;
130
    }
131
132
    /**
133
     * Post-process the constraints object to respect the file mounts.
134
     *
135
     * @param Query $query
136
     * @param ConstraintInterface|null $constraints
137
     * @param ConstraintContainer $constraintContainer
138
     * @throws \InvalidArgumentException
139
     * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidNumberOfConstraintsException
140
     */
141
    public function addFilePermissionsForFileMounts(Query $query, $constraints, ConstraintContainer $constraintContainer)
142
    {
143
        if ($query->getType() === 'sys_file') {
144
            if (!$this->getCurrentBackendUser()->isAdmin()) {
145
                $this->respectFileMounts($query, $constraints, $constraintContainer);
146
            }
147
        }
148
    }
149
150
    /**
151
     * @param Query $query
152
     * @param ConstraintInterface|null $constraints
153
     * @param ConstraintContainer $constraintContainer
154
     * @return array
155
     * @throws \InvalidArgumentException
156
     * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\InvalidNumberOfConstraintsException
157
     */
158
    protected function respectFileMounts(Query $query, $constraints, ConstraintContainer $constraintContainer)
159
    {
160
        $tableName = 'sys_filemounts';
161
162
        // Get the file mount identifiers for the current Backend User.
163
        $fileMounts = GeneralUtility::trimExplode(',', $this->getCurrentBackendUser()->dataLists['filemount_list']);
164
        $fileMountUids = implode(',', array_filter($fileMounts));
165
166
        // Fetch the records.
167
        $fileMountRecords = $this->getDataService()->getRecords(
168
            $tableName,
169
            [
170
                'uid' => $fileMountUids
171
            ]
172
        );
173
        $constraintsRespectingFileMounts = [];
174
        foreach ((array)$fileMountRecords as $fileMountRecord) {
175
            if ($fileMountRecord['path']) {
176
                $constraintsRespectingFileMounts[] = $query->like(
177
                    'identifier',
178
                    $fileMountRecord['path'] . '%'
179
                );
180
            }
181
        }
182
183
        $logicalOrForRespectingFileMounts = $query->logicalOr($constraintsRespectingFileMounts);
184
185
        if ($constraints) {
186
            $constraints = $query->logicalAnd(
187
                $constraints,
188
                $logicalOrForRespectingFileMounts
189
            );
190
        } else {
191
            $constraints = $logicalOrForRespectingFileMounts;
192
        }
193
194
        $constraintContainer->setConstraint($constraints);
195
196
        return [$query, $constraints, $constraintContainer];
197
    }
198
199
    /**
200
     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
201
     */
202
    protected function getCurrentBackendUser()
203
    {
204
        return $GLOBALS['BE_USER'];
205
    }
206
207
    /**
208
     * @return object|DataService
209
     */
210
    protected function getDataService(): DataService
211
    {
212
        return GeneralUtility::makeInstance(DataService::class);
213
    }
214
215
    /**
216
     * @return MediaModule|object
217
     * @throws \InvalidArgumentException
218
     */
219
    protected function getMediaModule()
220
    {
221
        return GeneralUtility::makeInstance(MediaModule::class);
222
    }
223
224
    /**
225
     * Get the Vidi Module Loader.
226
     *
227
     * @return object|ModuleLoader
228
     */
229
    protected function getModuleLoader()
230
    {
231
        return GeneralUtility::makeInstance(ModuleLoader::class);
232
    }
233
}
234