[TASK] Streamline phpdoc annotations in EXT:extbase
[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;
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->configureObjectManager(true);
80 $this->initializePersistence();
81 }
82
83 /**
84 * Initializes the Object framework.
85 *
86 * @see initialize()
87 */
88 protected function initializeObjectManager()
89 {
90 $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
91 }
92
93 /**
94 * Initializes the Object framework.
95 *
96 * @param array $configuration
97 * @see initialize()
98 * @internal
99 */
100 public function initializeConfiguration($configuration)
101 {
102 $this->configurationManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::class);
103 /** @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject */
104 $contentObject = $this->cObj ?? \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class);
105 $this->configurationManager->setContentObject($contentObject);
106 $this->configurationManager->setConfiguration($configuration);
107 }
108
109 /**
110 * Configures the object manager object configuration from
111 * config.tx_extbase.objects and plugin.tx_foo.objects
112 *
113 * @param bool $isInternalCall Set to true by Boostrap, not by extensions
114 * @see initialize()
115 * @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0
116 */
117 public function configureObjectManager($isInternalCall = false)
118 {
119 if (!$isInternalCall) {
120 trigger_error(self::class . '::configureObjectManager() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
121 }
122 $frameworkSetup = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
123 if (!isset($frameworkSetup['objects']) || !is_array($frameworkSetup['objects'])) {
124 return;
125 }
126 trigger_error('Overriding object implementations via TypoScript settings config.tx_extbase.objects and plugin.tx_%plugin%.objects will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
127 $objectContainer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\Container\Container::class);
128 foreach ($frameworkSetup['objects'] as $classNameWithDot => $classConfiguration) {
129 if (isset($classConfiguration['className'])) {
130 $originalClassName = rtrim($classNameWithDot, '.');
131 $objectContainer->registerImplementation($originalClassName, $classConfiguration['className']);
132 }
133 }
134 }
135
136 /**
137 * Initializes the persistence framework
138 *
139 * @see initialize()
140 * @internal
141 */
142 public function initializePersistence()
143 {
144 $this->persistenceManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class);
145 }
146
147 /**
148 * Runs the the Extbase Framework by resolving an appropriate Request Handler and passing control to it.
149 * If the Framework is not initialized yet, it will be initialized.
150 *
151 * @param string $content The content. Not used
152 * @param array $configuration The TS configuration array
153 * @return string $content The processed content
154 */
155 public function run($content, $configuration)
156 {
157 $this->initialize($configuration);
158 return $this->handleRequest();
159 }
160
161 /**
162 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\CommandException Is thrown if the response object defined an exit code > 0
163 * @return string
164 */
165 protected function handleRequest()
166 {
167 /** @var \TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver $requestHandlerResolver */
168 $requestHandlerResolver = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver::class);
169 $requestHandler = $requestHandlerResolver->resolveRequestHandler();
170
171 $response = $requestHandler->handleRequest();
172 // If response is NULL after handling the request we need to stop
173 // This happens for instance, when a USER object was converted to a USER_INT
174 // @see TYPO3\CMS\Extbase\Mvc\Web\FrontendRequestHandler::handleRequest()
175 if ($response === null) {
176 $content = '';
177 } else {
178 $content = $response->shutdown();
179 $this->resetSingletons();
180 $this->objectManager->get(\TYPO3\CMS\Extbase\Service\CacheService::class)->clearCachesOfRegisteredPageIds();
181 if (Environment::isCli() && $response->getExitCode()) {
182 throw new \TYPO3\CMS\Extbase\Mvc\Exception\CommandException('The request has been terminated as the response defined an exit code.', $response->getExitCode());
183 }
184 }
185
186 return $content;
187 }
188
189 /**
190 * Entrypoint for backend modules, handling PSR-7 requests/responses
191 *
192 * @param ServerRequestInterface $request
193 * @return ResponseInterface
194 * @internal
195 */
196 public function handleBackendRequest(ServerRequestInterface $request): ResponseInterface
197 {
198 // build the configuration from the Server request / route
199 /** @var Route $route */
200 $route = $request->getAttribute('route');
201 $moduleConfiguration = $route->getOption('moduleConfiguration');
202 $configuration = [
203 'extensionName' => $moduleConfiguration['extensionName'],
204 'pluginName' => $route->getOption('moduleName')
205 ];
206 if (isset($moduleConfiguration['vendorName'])) {
207 $configuration['vendorName'] = $moduleConfiguration['vendorName'];
208 }
209
210 $this->initialize($configuration);
211
212 /** @var \TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver $requestHandlerResolver */
213 $requestHandlerResolver = $this->objectManager->get(\TYPO3\CMS\Extbase\Mvc\RequestHandlerResolver::class);
214 $requestHandler = $requestHandlerResolver->resolveRequestHandler();
215 /** @var Response $extbaseResponse */
216 $extbaseResponse = $requestHandler->handleRequest();
217
218 // Convert to PSR-7 response and hand it back to TYPO3 Core
219 $response = $this->convertExtbaseResponseToPsr7Response($extbaseResponse);
220 $this->resetSingletons();
221 $this->objectManager->get(\TYPO3\CMS\Extbase\Service\CacheService::class)->clearCachesOfRegisteredPageIds();
222 return $response;
223 }
224
225 /**
226 * Converts a Extbase response object into a PSR-7 Response
227 *
228 * @param Response $extbaseResponse
229 * @return ResponseInterface
230 */
231 protected function convertExtbaseResponseToPsr7Response(Response $extbaseResponse): ResponseInterface
232 {
233 $response = new \TYPO3\CMS\Core\Http\Response(
234 'php://temp',
235 $extbaseResponse->getStatusCode(),
236 $extbaseResponse->getUnpreparedHeaders()
237 );
238 $content = $extbaseResponse->getContent();
239 if ($content !== null) {
240 $response->getBody()->write($content);
241 }
242 return $response;
243 }
244
245 /**
246 * Resets global singletons for the next plugin
247 */
248 protected function resetSingletons()
249 {
250 $this->persistenceManager->persistAll();
251 }
252 }