Passed
Push — main ( 644501...e2679f )
by Felix
02:55
created

Loader::getRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
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
            // Backend-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
        self::setRequest($this->mockRequestHandler->getRequest());
120
    }
121
122
    /**
123
     * Checks if a backend user is logged in.
124
     *
125
     * @return bool
126
     */
127
    public function hasActiveBackendUser()
128
    {
129
        return ($GLOBALS['BE_USER'] ?? null) instanceof BackendUserAuthentication &&
130
            $GLOBALS['BE_USER']->user['uid'] > 0;
131
    }
132
133
    /**
134
     * @return BackendUserAuthentication
135
     * @throws LogicException
136
     */
137
    public function getBackendUser()
138
    {
139
        if ($this->hasActiveBackendUser() === false) {
140
            throw new LogicException('be-user is not initialized - initialize with BE-user with method \'initializeBackendUser\'');
141
        }
142
        return $GLOBALS['BE_USER'];
143
    }
144
145
    /**
146
     * Initialize frontend-user with FrontendUserAuthenticator middleware.
147
     * @param string|int $pid List of page IDs (comma separated) or page ID where to look for frontend user records
148
     * @see \TYPO3\CMS\Frontend\Middleware\FrontendUserAuthenticator
149
     */
150
    public function initializeFrontendUser($pid = 0)
151
    {
152
        if ($this->hasActiveFrontendUser()) {
153
            // Frontend-User is already initialized - this can happen when we use/call internal REST-endpoints inside of a normal TYPO3-page
154
            return;
155
        }
156
157
        /* @var ServerRequestInterface $request */
158
        $request = $this->getRequest()
159
            ->withQueryParams(array_merge($_GET, ['pid' => $pid]))
160
            ->withCookieParams($_COOKIE);
161
162
        $this->frontendUserAuthenticator->process($request, $this->mockRequestHandler);
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
        self::setRequest($request);
218
219
        $this->initializeBackendUser();
220
        $this->initializeFrontendUser();
221
222
        $this->typoScriptFrontendInitialization->process($this->getRequest(), $this->mockRequestHandler);
223
        self::setRequest($this->mockRequestHandler->getRequest());
224
225
        $prepareTypoScriptFrontendRendering = new PrepareTypoScriptFrontendRendering($GLOBALS['TSFE'], $this->timeTracker);
226
        $prepareTypoScriptFrontendRendering->process($this->getRequest(), $this->mockRequestHandler);
227
        self::setRequest($this->mockRequestHandler->getRequest());
228
    }
229
230
    /**
231
     * @return string
232
     * @throws LogicException
233
     */
234
    public function renderPageContent()
235
    {
236
        if ($this->isFrontendInitialized() === false) {
237
            throw new LogicException('FrontendRendering is not initialized - initialize with method \'initializeFrontendRendering\'');
238
        }
239
240
        /** @var Response $response */
241
        $response = $this->requestHandler->handle($this->getRequest());
242
        return $response->getBody()->__toString();
243
    }
244
245
    /**
246
     * @param ServerRequestInterface $request
247
     */
248
    public static function setRequest(ServerRequestInterface $request)
249
    {
250
        $GLOBALS['RESTLER_TYPO3_REQUEST'] = $request;
251
    }
252
253
    /**
254
     * @return ServerRequestInterface
255
     */
256
    private function getRequest()
257
    {
258
        return $GLOBALS['RESTLER_TYPO3_REQUEST'];
259
    }
260
261
    /**
262
     * @return boolean
263
     */
264
    private function isFrontendInitialized()
265
    {
266
        return ($GLOBALS['TSFE'] ?? null) instanceof TypoScriptFrontendController &&
267
            $GLOBALS['TSFE']->tmpl instanceof TemplateService;
268
    }
269
}
270