e8b50a24b019c41f71d01cd77264f8787385e3d8
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Core / Bootstrap.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Core;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Routing\Route;
20 use TYPO3\CMS\Extbase\Mvc\Web\Response;
21
22 /**
23 * Creates a request an dispatches it to the controller which was specified
24 * by TS Setup, flexForm and returns the content.
25 *
26 * This class is the main entry point for extbase extensions.
27 */
28 class Bootstrap implements \TYPO3\CMS\Extbase\Core\BootstrapInterface
29 {
30 /**
31 * Back reference to the parent content object
32 * This has to be public as it is set directly from TYPO3
33 *
34 * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
35 */
36 public $cObj;
37
38 /**
39 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManager
40 */
41 protected $configurationManager;
42
43 /**
44 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
45 */
46 protected $objectManager;
47
48 /**
49 * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
50 */
51 protected $persistenceManager;
52
53 /**
54 * Explicitly initializes all necessary Extbase objects by invoking the various initialize* methods.
55 *
56 * Usually this method is only called from unit tests or other applications which need a more fine grained control over
57 * the initialization and request handling process. Most other applications just call the run() method.
58 *
59 * @param array $configuration The TS configuration array
60 * @throws \RuntimeException
61 * @see run()
62 * @api
63 */
64 public function initialize($configuration)
65 {
66 if (!$this->isInCliMode()) {
67 if (!isset($configuration['extensionName']) || $configuration['extensionName'] === '') {
68 throw new \RuntimeException('Invalid configuration: "extensionName" is not set', 1290623020);
69 }
70 if (!isset($configuration['pluginName']) || $configuration['pluginName'] === '') {
71 throw new \RuntimeException('Invalid configuration: "pluginName" is not set', 1290623027);
72 }
73 }
74 $this->initializeObjectManager();
75 $this->initializeConfiguration($configuration);
76 $this->configureObjectManager();
77 $this->initializePersistence();
78 }
79
80 /**
81 * Initializes the Object framework.
82 *
83 * @see initialize()
84 */
85 protected function initializeObjectManager()
86 {
87 $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
88 }
89
90 /**
91 * Initializes the Object framework.
92 *
93 * @param array $configuration
94 * @see initialize()
95 */
96 public function initializeConfiguration($configuration)
97 {
98 $this->configurationManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::class);
99 /** @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject */
100 $contentObject = $this->cObj ?? \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class);
101 $this->configurationManager->setContentObject($contentObject);
102 $this->configurationManager->setConfiguration($configuration);
103 }
104
105 /**
106 * Configures the object manager object configuration from
107 * config.tx_extbase.objects and plugin.tx_foo.objects
108 *
109 * @see initialize()
110 */
111 public function configureObjectManager()
112 {
113 $frameworkSetup = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
114 if (!isset($frameworkSetup['objects']) || !is_array($frameworkSetup['objects'])) {
115 return;
116 }
117 $objectContainer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\Container\Container::class);
118 foreach ($frameworkSetup['objects'] as $classNameWithDot => $classConfiguration) {
119 if (isset($classConfiguration['className'])) {
120 $originalClassName = rtrim($classNameWithDot, '.');
121 $objectContainer->registerImplementation($originalClassName, $classConfiguration['className']);
122 }
123 }
124 }
125
126 /**
127 * Initializes the persistence framework
128 *
129 * @see initialize()
130 */
131 public function initializePersistence()
132 {
133 $this->persistenceManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class);
134 }
135
136 /**
137 * Runs the the Extbase Framework by resolving an appropriate Request Handler and passing control to it.
138 * If the Framework is not initialized yet, it will be initialized.
139 *
140 * @param string $content The content. Not used
141 * @param array $configuration The TS configuration array
142 * @return string $content The processed content
143 * @api
144 */
145 public function run($content, $configuration)
146 {
147 $this->initialize($configuration);
148 return $this->handleRequest();
149 }
150
151 /**
152 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\CommandException Is thrown if the response object defined an exit code > 0
153 * @return string
154 */
155 protected function handleRequest()
156 {
157 /** @var $requestHandlerResolver \TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver */
158 $requestHandlerResolver = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver::class);
159 $requestHandler = $requestHandlerResolver->resolveRequestHandler();
160
161 $response = $requestHandler->handleRequest();
162 // If response is NULL after handling the request we need to stop
163 // This happens for instance, when a USER object was converted to a USER_INT
164 // @see TYPO3\CMS\Extbase\Mvc\Web\FrontendRequestHandler::handleRequest()
165 if ($response === null) {
166 $content = '';
167 } else {
168 $content = $response->shutdown();
169 $this->resetSingletons();
170 $this->objectManager->get(\TYPO3\CMS\Extbase\Service\CacheService::class)->clearCachesOfRegisteredPageIds();
171 if ($this->isInCliMode() && $response->getExitCode()) {
172 throw new \TYPO3\CMS\Extbase\Mvc\Exception\CommandException('The request has been terminated as the response defined an exit code.', $response->getExitCode());
173 }
174 }
175
176 return $content;
177 }
178
179 /**
180 * Entrypoint for backend modules, handling PSR-7 requests/responses
181 *
182 * @param ServerRequestInterface $request
183 * @return ResponseInterface
184 * @internal
185 */
186 public function handleBackendRequest(ServerRequestInterface $request): ResponseInterface
187 {
188 // build the configuration from the Server request / route
189 /** @var Route $route */
190 $route = $request->getAttribute('route');
191 $moduleConfiguration = $route->getOption('moduleConfiguration');
192 $configuration = [
193 'extensionName' => $moduleConfiguration['extensionName'],
194 'pluginName' => $route->getOption('moduleName')
195 ];
196 if (isset($moduleConfiguration['vendorName'])) {
197 $configuration['vendorName'] = $moduleConfiguration['vendorName'];
198 }
199
200 $this->initialize($configuration);
201
202 /** @var $requestHandlerResolver \TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver */
203 $requestHandlerResolver = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver::class);
204 $requestHandler = $requestHandlerResolver->resolveRequestHandler();
205 /** @var Response $extbaseResponse */
206 $extbaseResponse = $requestHandler->handleRequest();
207
208 // Convert to PSR-7 response and hand it back to TYPO3 Core
209 $response = $this->convertExtbaseResponseToPsr7Response($extbaseResponse);
210 $this->resetSingletons();
211 $this->objectManager->get(\TYPO3\CMS\Extbase\Service\CacheService::class)->clearCachesOfRegisteredPageIds();
212 return $response;
213 }
214
215 /**
216 * Converts a Extbase response object into a PSR-7 Response
217 *
218 * @param Response $extbaseResponse
219 * @return ResponseInterface
220 */
221 protected function convertExtbaseResponseToPsr7Response(Response $extbaseResponse): ResponseInterface
222 {
223 $response = new \TYPO3\CMS\Core\Http\Response(
224 'php://temp',
225 $extbaseResponse->getStatusCode(),
226 $extbaseResponse->getUnpreparedHeaders()
227 );
228 $content = $extbaseResponse->getContent();
229 if ($content !== null) {
230 $response->getBody()->write($content);
231 }
232 return $response;
233 }
234
235 /**
236 * Resets global singletons for the next plugin
237 */
238 protected function resetSingletons()
239 {
240 $this->persistenceManager->persistAll();
241 }
242
243 /**
244 * @return bool
245 */
246 protected function isInCliMode()
247 {
248 return TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI;
249 }
250 }