[TASK] Use FQCN's when registering plugins/modules
[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\Core\Core\Environment;
21 use TYPO3\CMS\Extbase\Mvc\Web\Response as ExtbaseResponse;
22
23 /**
24 * Creates a request an dispatches it to the controller which was specified
25 * by TS Setup, flexForm and returns the content.
26 *
27 * This class is the main entry point for extbase extensions.
28 */
29 class Bootstrap implements \TYPO3\CMS\Extbase\Core\BootstrapInterface
30 {
31 /**
32 * Back reference to the parent content object
33 * This has to be public as it is set directly from TYPO3
34 *
35 * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
36 */
37 public $cObj;
38
39 /**
40 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManager
41 */
42 protected $configurationManager;
43
44 /**
45 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
46 */
47 protected $objectManager;
48
49 /**
50 * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
51 */
52 protected $persistenceManager;
53
54 /**
55 * Explicitly initializes all necessary Extbase objects by invoking the various initialize* methods.
56 *
57 * Usually this method is only called from unit tests or other applications which need a more fine grained control over
58 * the initialization and request handling process. Most other applications just call the run() method.
59 *
60 * @param array $configuration The TS configuration array
61 * @throws \RuntimeException
62 * @see run()
63 */
64 public function initialize($configuration)
65 {
66 if (!Environment::isCli()) {
67 if (!isset($configuration['vendorName']) || $configuration['vendorName'] === '') {
68 throw new \RuntimeException('Invalid configuration: "vendorName" is not set', 1526629315);
69 }
70 if (!isset($configuration['extensionName']) || $configuration['extensionName'] === '') {
71 throw new \RuntimeException('Invalid configuration: "extensionName" is not set', 1290623020);
72 }
73 if (!isset($configuration['pluginName']) || $configuration['pluginName'] === '') {
74 throw new \RuntimeException('Invalid configuration: "pluginName" is not set', 1290623027);
75 }
76 }
77 $this->initializeObjectManager();
78 $this->initializeConfiguration($configuration);
79 $this->initializePersistence();
80 }
81
82 /**
83 * Initializes the Object framework.
84 *
85 * @see initialize()
86 */
87 protected function initializeObjectManager()
88 {
89 $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
90 }
91
92 /**
93 * Initializes the Object framework.
94 *
95 * @param array $configuration
96 * @see initialize()
97 * @internal
98 */
99 public function initializeConfiguration($configuration)
100 {
101 $this->configurationManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::class);
102 /** @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject */
103 $contentObject = $this->cObj ?? \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class);
104 $this->configurationManager->setContentObject($contentObject);
105 $this->configurationManager->setConfiguration($configuration);
106 // todo: Shouldn't the configuration manager object – which is a singleton – be stateless?
107 // todo: At this point we give the configuration manager a state, while we could directly pass the
108 // todo: configuration (i.e. controllerName, actionName, vendorName and such), directly to the request
109 // todo: handler, which then creates stateful request objects.
110 // todo: Once this has changed, \TYPO3\CMS\Extbase\Mvc\Web\RequestBuilder::loadDefaultValues does not need
111 // todo: to fetch this configuration from the configuration manager.
112 }
113
114 /**
115 * Initializes the persistence framework
116 *
117 * @see initialize()
118 * @internal
119 */
120 public function initializePersistence()
121 {
122 $this->persistenceManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class);
123 }
124
125 /**
126 * Runs the the Extbase Framework by resolving an appropriate Request Handler and passing control to it.
127 * If the Framework is not initialized yet, it will be initialized.
128 *
129 * @param string $content The content. Not used
130 * @param array $configuration The TS configuration array
131 * @return string $content The processed content
132 */
133 public function run($content, $configuration)
134 {
135 $this->initialize($configuration);
136 return $this->handleRequest();
137 }
138
139 /**
140 * @return string
141 */
142 protected function handleRequest()
143 {
144 /** @var \TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver $requestHandlerResolver */
145 $requestHandlerResolver = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver::class);
146 $requestHandler = $requestHandlerResolver->resolveRequestHandler();
147
148 $response = $requestHandler->handleRequest();
149 // If response is NULL after handling the request we need to stop
150 // This happens for instance, when a USER object was converted to a USER_INT
151 // @see TYPO3\CMS\Extbase\Mvc\Web\FrontendRequestHandler::handleRequest()
152 if ($response === null) {
153 $content = '';
154 } else {
155 $content = $response->shutdown();
156 $this->resetSingletons();
157 $this->objectManager->get(\TYPO3\CMS\Extbase\Service\CacheService::class)->clearCachesOfRegisteredPageIds();
158 }
159
160 return $content;
161 }
162
163 /**
164 * Entrypoint for backend modules, handling PSR-7 requests/responses
165 *
166 * @param ServerRequestInterface $request
167 * @return ResponseInterface
168 * @internal
169 */
170 public function handleBackendRequest(ServerRequestInterface $request): ResponseInterface
171 {
172 // build the configuration from the Server request / route
173 /** @var Route $route */
174 $route = $request->getAttribute('route');
175 $moduleConfiguration = $route->getOption('moduleConfiguration');
176 $configuration = [
177 'extensionName' => $moduleConfiguration['extensionName'],
178 'pluginName' => $route->getOption('moduleName')
179 ];
180 if (isset($moduleConfiguration['vendorName'])) {
181 $configuration['vendorName'] = $moduleConfiguration['vendorName'];
182 }
183
184 $this->initialize($configuration);
185
186 /** @var \TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver $requestHandlerResolver */
187 $requestHandlerResolver = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver::class);
188 $requestHandler = $requestHandlerResolver->resolveRequestHandler();
189 /** @var ExtbaseResponse $extbaseResponse */
190 $extbaseResponse = $requestHandler->handleRequest();
191
192 // Convert to PSR-7 response and hand it back to TYPO3 Core
193 $response = $this->convertExtbaseResponseToPsr7Response($extbaseResponse);
194 $this->resetSingletons();
195 $this->objectManager->get(\TYPO3\CMS\Extbase\Service\CacheService::class)->clearCachesOfRegisteredPageIds();
196 return $response;
197 }
198
199 /**
200 * Converts a Extbase response object into a PSR-7 Response
201 *
202 * @param ExtbaseResponse $extbaseResponse
203 * @return ResponseInterface
204 */
205 protected function convertExtbaseResponseToPsr7Response(ExtbaseResponse $extbaseResponse): ResponseInterface
206 {
207 $response = new \TYPO3\CMS\Core\Http\Response(
208 'php://temp',
209 $extbaseResponse->getStatusCode(),
210 $extbaseResponse->getUnpreparedHeaders()
211 );
212 $content = $extbaseResponse->getContent();
213 if ($content !== null) {
214 $response->getBody()->write($content);
215 }
216 return $response;
217 }
218
219 /**
220 * Resets global singletons for the next plugin
221 */
222 protected function resetSingletons()
223 {
224 $this->persistenceManager->persistAll();
225 }
226 }