Passed
Push — master ( d8df74...725a8f )
by Torben
08:07
created

PageAccessService::getTreeList()   C

Complexity

Conditions 12
Paths 12

Size

Total Lines 41
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 30
c 0
b 0
f 0
dl 0
loc 41
rs 6.9666
cc 12
nc 12
nop 4

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
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Extension "fe_change_pwd" for TYPO3 CMS.
7
 *
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
namespace Derhansen\FeChangePwd\Service;
13
14
use Derhansen\FeChangePwd\Exception\NoChangePasswordPidException;
15
use TYPO3\CMS\Core\Database\ConnectionPool;
16
use TYPO3\CMS\Core\Database\Query\QueryHelper;
17
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
use TYPO3\CMS\Core\Utility\StringUtility;
20
21
/**
22
 * Class PageAccessService
23
 */
24
class PageAccessService
25
{
26
    protected SettingsService $settingsService;
27
28
    /**
29
     * @param SettingsService $settingsService
30
     */
31
    public function injectSettingsService(SettingsService $settingsService)
32
    {
33
        $this->settingsService = $settingsService;
34
    }
35
36
    /**
37
     * Returns the redirect mode
38
     *
39
     * @return string
40
     */
41
    public function getRedirectMode(): string
42
    {
43
        $settings = $this->settingsService->getSettings();
44
        if ((bool)$settings['redirect']['allAccessProtectedPages']) {
45
            $redirectMode = 'allAccessProtectedPages';
46
        } elseif (isset($settings['redirect']['includePageUids']) && $settings['redirect']['includePageUids'] !== '') {
47
            $redirectMode = 'includePageUids';
48
        } else {
49
            $redirectMode = '';
50
        }
51
        return $redirectMode;
52
    }
53
54
    /**
55
     * Returns the configured redirect PID
56
     *
57
     * @return mixed
58
     */
59
    public function getRedirectPid()
60
    {
61
        $settings = $this->settingsService->getSettings();
62
        if (!isset($settings['changePasswordPid']) || (int)$settings['changePasswordPid'] === 0) {
63
            throw new NoChangePasswordPidException(
64
                'settings.changePasswordPid is not set or zero',
65
                1580040840163
66
            );
67
        }
68
        return (int)$settings['changePasswordPid'];
69
    }
70
71
    /**
72
     * Returns, if the given page uid is configured as included for redirects
73
     *
74
     * @param int $pageUid
75
     * @return bool
76
     */
77
    public function isIncludePage(int $pageUid): bool
78
    {
79
        $settings = $this->settingsService->getSettings();
80
        if (isset($settings['redirect']['includePageUids']) && $settings['redirect']['includePageUids'] !== '') {
81
            $includePids = $this->extendPidListByChildren(
82
                $settings['redirect']['includePageUids'],
83
                (int)$settings['redirect']['includePageUidsRecursionLevel']
84
            );
85
            $includePids = GeneralUtility::intExplode(',', $includePids, true);
86
        } else {
87
            $includePids = [];
88
        }
89
        return in_array($pageUid, $includePids, true);
90
    }
91
92
    /**
93
     * Returns, if the given page uid is configured as excluded from redirects
94
     *
95
     * @param int $pageUid
96
     * @return bool
97
     */
98
    public function isExcludePage(int $pageUid): bool
99
    {
100
        $settings = $this->settingsService->getSettings();
101
        if (isset($settings['redirect']['excludePageUids']) && $settings['redirect']['excludePageUids'] !== '') {
102
            $excludePids = $this->extendPidListByChildren(
103
                $settings['redirect']['excludePageUids'],
104
                (int)$settings['redirect']['excludePageUidsRecursionLevel']
105
            );
106
            $excludePids = GeneralUtility::intExplode(',', $excludePids, true);
107
        } else {
108
            $excludePids = [];
109
        }
110
        // Always add the changePasswordPid as exclude PID
111
        $excludePids[] = (int)$settings['changePasswordPid'];
112
        return in_array($pageUid, $excludePids, true);
113
    }
114
115
    /**
116
     * Returns, if the there is an access protected page in the rootline respecting 'extendToSubpages' setting
117
     *
118
     * @param array $rootline
119
     * @return bool
120
     */
121
    public function isAccessProtectedPageInRootline(array $rootline): bool
122
    {
123
        $isAccessProtected = false;
124
        $loop = 0;
125
        foreach ($rootline as $rootlinePage) {
126
            $isPublic = ($rootlinePage['fe_group'] === '' || $rootlinePage['fe_group'] === '0');
127
            $extendToSubpages = (bool)$rootlinePage['extendToSubpages'];
128
            if (!$isPublic || (!$isPublic && $extendToSubpages && $loop >= 1)) {
129
                $isAccessProtected = true;
130
                break;
131
            }
132
            $loop++;
133
        }
134
        return $isAccessProtected;
135
    }
136
137
    /**
138
     * Find all ids from given ids and level
139
     *
140
     * @param string $pidList comma separated list of ids
141
     * @param int $recursive recursive levels
142
     * @return string comma separated list of ids
143
     */
144
    protected function extendPidListByChildren(string $pidList = '', int $recursive = 0): string
145
    {
146
        if ($recursive <= 0) {
147
            return $pidList;
148
        }
149
150
        $recursiveStoragePids = $pidList;
151
        $storagePids = GeneralUtility::intExplode(',', $pidList);
152
        foreach ($storagePids as $startPid) {
153
            if ($startPid >= 0) {
154
                $pids = (string)$this->getTreeList($startPid, $recursive, 0, 1);
155
                if (strlen($pids) > 0) {
156
                    $recursiveStoragePids .= ',' . $pids;
157
                }
158
            }
159
        }
160
        return StringUtility::uniqueList($recursiveStoragePids);
161
    }
162
163
    /**
164
     * Recursively fetch all descendants of a given page. Original function from TYPO3 core used, since
165
     * QueryGenerator is deprecated since #92080
166
     *
167
     * @param int $id uid of the page
168
     * @param int $depth
169
     * @param int $begin
170
     * @param string $permClause
171
     * @return string comma separated list of descendant pages
172
     */
173
    protected function getTreeList($id, $depth, $begin = 0, $permClause = '')
174
    {
175
        $depth = (int)$depth;
176
        $begin = (int)$begin;
177
        $id = (int)$id;
178
        if ($id < 0) {
179
            $id = abs($id);
180
        }
181
        if ($begin === 0) {
182
            $theList = $id;
183
        } else {
184
            $theList = '';
185
        }
186
        if ($id && $depth > 0) {
187
            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
188
            $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
189
            $queryBuilder->select('uid')
190
                ->from('pages')
191
                ->where(
192
                    $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)),
193
                    $queryBuilder->expr()->eq('sys_language_uid', 0)
194
                )
195
                ->orderBy('uid');
196
            if ($permClause !== '') {
197
                $queryBuilder->andWhere(QueryHelper::stripLogicalOperatorPrefix((string)$permClause));
198
            }
199
            $statement = $queryBuilder->execute();
200
            while ($row = $statement->fetch()) {
201
                if ($begin <= 0) {
202
                    $theList .= ',' . $row['uid'];
203
                }
204
                if ($depth > 1) {
205
                    $theSubList = $this->getTreeList($row['uid'], $depth - 1, $begin - 1, $permClause);
206
                    if (!empty($theList) && !empty($theSubList) && ($theSubList[0] !== ',')) {
207
                        $theList .= ',';
208
                    }
209
                    $theList .= $theSubList;
210
                }
211
            }
212
        }
213
        return $theList;
214
    }
215
}
216