1414use TYPO3 \CMS \Frontend \Controller \TypoScriptFrontendController ;
1515use TYPO3 \CMS \Frontend \Utility \EidUtility ;
1616use TYPO3 \CMS \Lang \LanguageService ;
17+ use function class_exists ;
18+ use function intval ;
19+ use function is_int ;
20+ use function is_string ;
1721
1822
1923/**
@@ -26,6 +30,8 @@ class Bootstrap
2630 *
2731 * @param TypoScriptFrontendController|null $frontendController
2832 * @return TypoScriptFrontendController
33+ * @throws \TYPO3\CMS\Core\Error\Http\ServiceUnavailableException
34+ * @throws \TYPO3\CMS\Core\Http\ImmediateResponseException
2935 */
3036 public function init (TypoScriptFrontendController $ frontendController = null )
3137 {
@@ -57,9 +63,6 @@ public function initializeLanguageObject()
5763 }
5864 }
5965
60- /**
61- *
62- */
6366 private function initializeTimeTracker ()
6467 {
6568 if (!isset ($ GLOBALS ['TT ' ]) || !is_object ($ GLOBALS ['TT ' ])) {
@@ -82,7 +85,7 @@ private function buildFrontendController(int $pageUid): TypoScriptFrontendContro
8285
8386 return $ objectManager ->get (
8487 TypoScriptFrontendController::class,
85- $ GLOBALS [ ' TYPO3_CONF_VARS ' ] , // can be removed in TYPO3 v8
88+ null , // previously TYPO3_CONF_VARS
8689 $ pageUid ,
8790 0 , // Type
8891 0 , // no_cache
@@ -117,6 +120,8 @@ private function getFrontendControllerIsInitialized(): bool
117120 * Configure the given frontend controller
118121 *
119122 * @param TypoScriptFrontendController $frontendController
123+ * @throws \TYPO3\CMS\Core\Error\Http\ServiceUnavailableException
124+ * @throws \TYPO3\CMS\Core\Http\ImmediateResponseException
120125 */
121126 private function configureFrontendController (TypoScriptFrontendController $ frontendController )
122127 {
@@ -135,8 +140,11 @@ private function configureFrontendController(TypoScriptFrontendController $front
135140 $ frontendController ->determineId ();
136141 $ frontendController ->getConfigArray ();
137142
138- $ this ->setRequestedLanguage ($ frontendController );
139- $ frontendController ->settingLanguage ();
143+ $ this ->detectAndSetRequestedLanguage ($ frontendController );
144+ //try {
145+ // $frontendController->settingLanguage();
146+ //} catch (\RuntimeException $exception) {
147+ //}
140148 $ frontendController ->settingLocale ();
141149 }
142150
@@ -145,40 +153,57 @@ private function configureFrontendController(TypoScriptFrontendController $front
145153 *
146154 * @param TypoScriptFrontendController $frontendController
147155 */
148- private function setRequestedLanguage (TypoScriptFrontendController $ frontendController )
156+ private function detectAndSetRequestedLanguage (TypoScriptFrontendController $ frontendController )
149157 {
158+ if (!isset ($ GLOBALS ['TYPO3_REQUEST ' ]) || !class_exists (SiteMatcher::class)) {
159+ $ this ->setRequestedLanguage ($ frontendController , $ this ->getRequestedLanguageUid ($ frontendController ));
160+
161+ return ;
162+ }
163+
150164 // support new TYPO3 v9.2 Site Handling until middleware concept is implemented
151165 // see https://github.com/cundd/rest/issues/59
152- if (isset ($ GLOBALS ['TYPO3_REQUEST ' ]) && class_exists (SiteMatcher::class)) {
153- /** @var ServerRequestInterface $request */
154- $ request = $ GLOBALS ['TYPO3_REQUEST ' ];
166+ /** @var ServerRequestInterface $request */
167+ $ request = $ GLOBALS ['TYPO3_REQUEST ' ];
155168
156- /** @var SiteRouteResult $routeResult */
157- $ routeResult = GeneralUtility::makeInstance (SiteMatcher::class)->matchRequest ($ request );
169+ /**
170+ * Try to detect the language ID from request parameters or headers. If the SiteMatcher detects a language this
171+ * fallback will **not** be used
172+ *
173+ * @var int|null $fallbackLanguageId
174+ */
175+ $ fallbackLanguageId = (int )($ request ->getQueryParams ()['L ' ]
176+ ?? $ request ->getParsedBody ()['L ' ]
177+ ?? $ this ->getRequestedLanguageUid ($ frontendController ));
158178
159- $ language = $ routeResult ->getLanguage ();
160179
161- $ request = $ request ->withAttribute ('site ' , $ routeResult ->getSite ());
162- $ request = $ request ->withAttribute ('language ' , $ language );
163- $ request = $ request ->withAttribute ('routing ' , $ routeResult );
180+ /** @var SiteRouteResult $routeResult */
181+ $ routeResult = GeneralUtility::makeInstance (SiteMatcher::class)->matchRequest ($ request );
164182
165- $ GLOBALS ['TYPO3_REQUEST ' ] = $ request ;
166183
167- // Set language if defined
168- $ requestedLanguageUid = ($ language && $ language ->getLanguageId () !== null )
169- ? $ language ->getLanguageId ()
170- : $ this ->getRequestedLanguageUid ($ frontendController );
171- } else {
172- $ requestedLanguageUid = GeneralUtility::_GP ('L ' ) !== null
173- ? intval (GeneralUtility::_GP ('L ' ))
174- : $ this ->getRequestedLanguageUid ($ frontendController );
184+ $ site = $ routeResult ->getSite ();
185+ $ language = $ routeResult ->getLanguage ();
186+
187+ // If TYPO3 could not determine the language for the request use the detected fallback
188+ if (!$ language && $ fallbackLanguageId !== null ) {
189+ $ language = $ site ->getLanguageById ($ fallbackLanguageId );
175190 }
176191
177- if (null !== $ requestedLanguageUid ) {
178- $ frontendController ->config ['config ' ]['sys_language_uid ' ] = $ requestedLanguageUid ;
179- // Add LinkVars and language to work with correct localized labels
180- $ frontendController ->config ['config ' ]['linkVars ' ] = 'L(int) ' ;
181- $ frontendController ->config ['config ' ]['language ' ] = $ this ->getRequestedLanguageCode ();
192+ $ request = $ request ->withAttribute ('site ' , $ site );
193+ $ request = $ request ->withAttribute ('language ' , $ language );
194+ $ request = $ request ->withAttribute ('routing ' , $ routeResult );
195+
196+ // Patch the original Request so that at least `site` and `routing` are defined
197+ $ GLOBALS ['TYPO3_REQUEST ' ] = $ request
198+ ->withAttribute ('site ' , $ site )
199+ ->withAttribute ('language ' , $ language )
200+ ->withAttribute ('routing ' , $ routeResult );
201+
202+ // Set language if defined
203+ if ($ language && $ language ->getLanguageId () !== null ) {
204+ $ this ->setRequestedLanguage ($ frontendController , $ language ->getLanguageId ());
205+ } else {
206+ $ this ->setRequestedLanguage ($ frontendController , $ fallbackLanguageId );
182207 }
183208 }
184209
@@ -190,33 +215,38 @@ private function setRequestedLanguage(TypoScriptFrontendController $frontendCont
190215 */
191216 private function getRequestedLanguageUid (TypoScriptFrontendController $ frontendController ): ?int
192217 {
218+ if (GeneralUtility::_GP ('L ' ) !== null ) {
219+ return (int )GeneralUtility::_GP ('L ' );
220+ }
221+ if (GeneralUtility::_GP ('locale ' ) !== null ) {
222+ $ languageId = $ this ->getLanguageIdForCode ($ frontendController , GeneralUtility::_GP ('locale ' ));
223+ if ($ languageId !== null ) {
224+ return $ languageId ;
225+ }
226+ }
227+
193228 // Test the full HTTP_ACCEPT_LANGUAGE header
194229 if (isset ($ _SERVER ['HTTP_ACCEPT_LANGUAGE ' ])) {
195- $ typoscriptValue = $ this ->readConfigurationFromTyposcript (
196- ' plugin.tx_rest.settings.languages. ' . $ _SERVER [ ' HTTP_ACCEPT_LANGUAGE ' ] ,
197- $ frontendController
230+ $ languageId = $ this ->getLanguageIdForCode (
231+ $ frontendController ,
232+ ( string ) $ _SERVER [ ' HTTP_ACCEPT_LANGUAGE ' ]
198233 );
199234
200- if ($ typoscriptValue !== null ) {
201- return intval ( $ typoscriptValue ) ;
235+ if ($ languageId !== null ) {
236+ return $ languageId ;
202237 }
203238 }
204239
205240 // Retrieve and test the parsed header
206241 $ languageCode = $ this ->getRequestedLanguageCode ();
207- if ($ languageCode === null ) {
208- return null ;
209- }
210- $ typoscriptValue = $ this ->readConfigurationFromTyposcript (
211- 'plugin.tx_rest.settings.languages. ' . $ languageCode ,
212- $ frontendController
213- );
214-
215- if ($ typoscriptValue === null ) {
216- return null ;
242+ if ($ languageCode !== null ) {
243+ $ languageId = $ this ->getLanguageIdForCode ($ frontendController , $ languageCode );
244+ if ($ languageId !== null ) {
245+ return $ languageId ;
246+ }
217247 }
218248
219- return intval ( $ typoscriptValue ) ;
249+ return null ;
220250 }
221251
222252 /**
@@ -260,4 +290,40 @@ private function getRequestedLanguageCode(): ?string
260290
261291 return null ;
262292 }
293+
294+ /**
295+ * @param TypoScriptFrontendController $frontendController
296+ * @param string $languageCode
297+ * @return int
298+ */
299+ private function getLanguageIdForCode (TypoScriptFrontendController $ frontendController , string $ languageCode ): ?int
300+ {
301+ $ value = $ this ->readConfigurationFromTyposcript (
302+ 'plugin.tx_rest.settings.languages. ' . $ languageCode ,
303+ $ frontendController
304+ );
305+ if (is_int ($ value )) {
306+ return $ value ;
307+ } elseif (is_string ($ value )) {
308+ return trim ($ value ) === '' ? null : (int )$ value ;
309+ } else {
310+ return null ;
311+ }
312+ }
313+
314+ /**
315+ * @param TypoScriptFrontendController $frontendController
316+ * @param int|null $requestedLanguageUid
317+ */
318+ private function setRequestedLanguage (
319+ TypoScriptFrontendController $ frontendController ,
320+ ?int $ requestedLanguageUid
321+ ): void {
322+ if (null !== $ requestedLanguageUid ) {
323+ $ frontendController ->config ['config ' ]['sys_language_uid ' ] = $ requestedLanguageUid ;
324+ // Add LinkVars and language to work with correct localized labels
325+ $ frontendController ->config ['config ' ]['linkVars ' ] = 'L(int) ' ;
326+ $ frontendController ->config ['config ' ]['language ' ] = $ this ->getRequestedLanguageCode ();
327+ }
328+ }
263329}
0 commit comments