Passed
Push — feature/typo3v10_fixFeRenderin... ( 2d1103...6e9561 )
by Felix
03:06
created

Loader::initializeFrontendUser()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 15
rs 10
1
<?php
2
namespace Aoe\Restler\System\TYPO3;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2021 AOE GmbH <[email protected]>
8
 *
9
 *  All rights reserved
10
 *
11
 *  This script is part of the TYPO3 project. The TYPO3 project is
12
 *  free software; you can redistribute it and/or modify
13
 *  it under the terms of the GNU General Public License as published by
14
 *  the Free Software Foundation; either version 3 of the License, or
15
 *  (at your option) any later version.
16
 *
17
 *  The GNU General Public License can be found at
18
 *  http://www.gnu.org/copyleft/gpl.html.
19
 *
20
 *  This script is distributed in the hope that it will be useful,
21
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 *  GNU General Public License for more details.
24
 *
25
 *  This copyright notice MUST APPEAR in all copies of the script!
26
 ***************************************************************/
27
28
use Psr\Http\Message\ServerRequestInterface;
29
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
30
use TYPO3\CMS\Core\Http\NormalizedParams;
31
use TYPO3\CMS\Core\Http\Response;
32
use TYPO3\CMS\Core\Routing\PageArguments;
33
use TYPO3\CMS\Core\SingletonInterface;
34
use TYPO3\CMS\Core\Site\Entity\Site;
35
use TYPO3\CMS\Core\Site\SiteFinder;
36
use TYPO3\CMS\Core\TimeTracker\TimeTracker;
37
use TYPO3\CMS\Core\TypoScript\TemplateService;
38
use TYPO3\CMS\Core\Utility\GeneralUtility;
39
use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
40
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
41
use TYPO3\CMS\Frontend\Http\RequestHandler;
42
use TYPO3\CMS\Frontend\Middleware\BackendUserAuthenticator;
43
use TYPO3\CMS\Frontend\Middleware\FrontendUserAuthenticator;
44
use TYPO3\CMS\Frontend\Middleware\PrepareTypoScriptFrontendRendering;
45
use TYPO3\CMS\Frontend\Middleware\TypoScriptFrontendInitialization;
46
use LogicException;
47
48
/**
49
 * @package Restler
50
 */
51
class Loader implements SingletonInterface
52
{
53
    /**
54
     * @var BackendUserAuthenticator
55
     */
56
    private $backendUserAuthenticator;
57
58
    /**
59
     * @var FrontendUserAuthenticator
60
     */
61
    private $frontendUserAuthenticator;
62
63
    /**
64
     * @var MockRequestHandler
65
     */
66
    private $mockRequestHandler;
67
68
    /**
69
     * @var RequestHandler
70
     */
71
    private $requestHandler;
72
73
    /**
74
     * @var TimeTracker
75
     */
76
    protected $timeTracker;
77
78
    /**
79
     * @var TypoScriptFrontendInitialization
80
     */
81
    private $typoScriptFrontendInitialization;
82
83
    /**
84
     * @param BackendUserAuthenticator         $backendUserAuthenticator
85
     * @param FrontendUserAuthenticator        $frontendUserAuthenticator
86
     * @param MockRequestHandler               $mockRequestHandler
87
     * @param RequestHandler                   $requestHandler
88
     * @param TimeTracker                      $timeTracker
89
     * @param TypoScriptFrontendInitialization $typoScriptFrontendInitialization
90
     */
91
    public function __construct(
92
        BackendUserAuthenticator $backendUserAuthenticator,
93
        FrontendUserAuthenticator $frontendUserAuthenticator,
94
        MockRequestHandler $mockRequestHandler,
95
        RequestHandler $requestHandler,
96
        TimeTracker $timeTracker,
97
        TypoScriptFrontendInitialization $typoScriptFrontendInitialization
98
    ) {
99
        $this->backendUserAuthenticator = $backendUserAuthenticator;
100
        $this->frontendUserAuthenticator = $frontendUserAuthenticator;
101
        $this->mockRequestHandler = $mockRequestHandler;
102
        $this->requestHandler = $requestHandler;
103
        $this->timeTracker = $timeTracker;
104
        $this->typoScriptFrontendInitialization = $typoScriptFrontendInitialization;
105
    }
106
107
    /**
108
     * Initialize backend user with BackendUserAuthenticator middleware.
109
     * @see \TYPO3\CMS\Frontend\Middleware\BackendUserAuthenticator
110
     */
111
    public function initializeBackendUser()
112
    {
113
        if ($this->hasActiveBackendUser()) {
114
            // Frontend-User is already initialized - this can happen when we use/call internal REST-endpoints inside of a normal TYPO3-page
115
            return;
116
        }
117
118
        $this->backendUserAuthenticator->process($this->getRequest(), $this->mockRequestHandler);
119
    }
120
121
    /**
122
     * Checks if a backend user is logged in.
123
     *
124
     * @return bool
125
     */
126
    public function hasActiveBackendUser()
127
    {
128
        return ($GLOBALS['BE_USER'] ?? null) instanceof BackendUserAuthentication &&
129
            $GLOBALS['BE_USER']->user['uid'] > 0;
130
    }
131
132
    /**
133
     * @return BackendUserAuthentication
134
     * @throws LogicException
135
     */
136
    public function getBackendUser()
137
    {
138
        if ($this->hasActiveBackendUser() === false) {
139
            throw new LogicException('be-user is not initialized - initialize with BE-user with method \'initializeBackendUser\'');
140
        }
141
        return $GLOBALS['BE_USER'];
142
    }
143
144
    /**
145
     * Initialize backend user with FrontendUserAuthenticator middleware.
146
     * @param string|int $pid List of page IDs (comma separated) or page ID where to look for frontend user records
147
     * @see \TYPO3\CMS\Frontend\Middleware\FrontendUserAuthenticator
148
     */
149
    public function initializeFrontendUser($pid = 0)
150
    {
151
        if ($this->hasActiveFrontendUser()) {
152
            // Frontend-User is already initialized - this can happen when we use/call internal REST-endpoints inside of a normal TYPO3-page
153
            return;
154
        }
155
156
        /* @var ServerRequestInterface $request */
157
        $request = $this->getRequest()
158
            ->withQueryParams(array_merge($_GET, ['pid' => $pid]))
159
            ->withCookieParams($_COOKIE);
160
161
        $this->frontendUserAuthenticator->process($request, $this->mockRequestHandler);
162
163
        self::setRequest($this->mockRequestHandler->getRequest());
164
    }
165
166
    /**
167
     * Checks if a frontend user is logged in and the session is active.
168
     *
169
     * @return bool
170
     */
171
    public function hasActiveFrontendUser()
172
    {
173
        $frontendUser = $this->getRequest()->getAttribute('frontend.user');
174
        return ($frontendUser instanceof FrontendUserAuthentication && is_array($frontendUser->user) && isset($frontendUser->user['uid']));
175
    }
176
177
    /**
178
     * @return FrontendUserAuthentication
179
     * @throws LogicException
180
     */
181
    public function getFrontendUser()
182
    {
183
        if ($this->hasActiveFrontendUser() === false) {
184
            throw new LogicException('fe-user is not initialized');
185
        }
186
        return $this->getRequest()->getAttribute('frontend.user');
187
    }
188
189
    /**
190
     * @param integer $pageId
191
     * @param integer $type
192
     *
193
     * @return void
194
     */
195
    public function initializeFrontendRendering($pageId = 0, $type = 0)
196
    {
197
        if ($this->isFrontendInitialized()) {
198
            // FE is already initialized - this can happen when we use/call internal REST-endpoints inside of a normal TYPO3-page
199
            return;
200
        }
201
202
        /** @var SiteFinder $siteFinder */
203
        $siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
204
        /** @var Site $site */
205
        $site = $siteFinder->getSiteByPageId($pageId);
206
        $pageArguments = new PageArguments($pageId, $type, [], [], []);
207
        $normalizedParams = NormalizedParams::createFromRequest($this->getRequest());
208
209
        /* @var ServerRequestInterface $request */
210
        $request = $this->getRequest()
211
            ->withAttribute('site', $site)
212
            ->withAttribute('routing', $pageArguments)
213
            ->withAttribute('language', $site->getDefaultLanguage())
214
            ->withAttribute('normalizedParams', $normalizedParams)
215
            ->withQueryParams($_GET)
216
            ->withCookieParams($_COOKIE);
217
218
        $this->backendUserAuthenticator->process($request, $this->mockRequestHandler);
219
        $request = $this->mockRequestHandler->getRequest();
220
221
        $this->frontendUserAuthenticator->process($request, $this->mockRequestHandler);
222
        $request = $this->mockRequestHandler->getRequest();
223
224
        $this->typoScriptFrontendInitialization->process($request, $this->mockRequestHandler);
225
        $request = $this->mockRequestHandler->getRequest();
226
227
        $prepareTypoScriptFrontendRendering = new PrepareTypoScriptFrontendRendering($GLOBALS['TSFE'], $this->timeTracker);
228
        $prepareTypoScriptFrontendRendering->process($request, $this->mockRequestHandler);
229
        Loader::setRequest($this->mockRequestHandler->getRequest());
230
    }
231
232
    /**
233
     * @return string
234
     * @throws LogicException
235
     */
236
    public function renderPageContent()
237
    {
238
        if ($this->isFrontendInitialized() === false) {
239
            throw new LogicException('FrontendRendering is not initialized - initialize with method \'initializeFrontendRendering\'');
240
        }
241
242
        /** @var Response $response */
243
        $response = $this->requestHandler->handle($this->getRequest());
244
        return $response->getBody()->__toString();
245
    }
246
247
    /**
248
     * @param ServerRequestInterface $request
249
     */
250
    public static function setRequest(ServerRequestInterface $request)
251
    {
252
        $GLOBALS['RESTLER_TYPO3_REQUEST'] = $request;
253
    }
254
255
    /**
256
     * @return ServerRequestInterface
257
     */
258
    private function getRequest()
259
    {
260
        return $GLOBALS['RESTLER_TYPO3_REQUEST'];
261
    }
262
263
    /**
264
     * @return boolean
265
     */
266
    private function isFrontendInitialized()
267
    {
268
        return ($GLOBALS['TSFE'] ?? null) instanceof TypoScriptFrontendController &&
269
            $GLOBALS['TSFE']->tmpl instanceof TemplateService;
270
    }
271
}
272