PageAccessService   A
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 187
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 37
eloc 86
c 1
b 0
f 0
dl 0
loc 187
rs 9.44

8 Methods

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