• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

FluidTYPO3 / flux / 17727369243

15 Sep 2025 08:47AM UTC coverage: 92.767% (-0.1%) from 92.901%
17727369243

push

github

NamelessCoder
[TER] 11.0.7

7080 of 7632 relevant lines covered (92.77%)

65.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.85
/Classes/Controller/AbstractFluxController.php
1
<?php
2
declare(strict_types=1);
3
namespace FluidTYPO3\Flux\Controller;
4

5
/*
6
 * This file is part of the FluidTYPO3/Flux project under GPLv2 or later.
7
 *
8
 * For the full copyright and license information, please read the
9
 * LICENSE.md file that was distributed with this source code.
10
 */
11

12
use FluidTYPO3\Flux\Builder\RenderingContextBuilder;
13
use FluidTYPO3\Flux\Builder\RequestBuilder;
14
use FluidTYPO3\Flux\Builder\ViewBuilder;
15
use FluidTYPO3\Flux\Hooks\HookHandler;
16
use FluidTYPO3\Flux\Integration\NormalizedData\DataAccessTrait;
17
use FluidTYPO3\Flux\Integration\Resolver;
18
use FluidTYPO3\Flux\Provider\Interfaces\ControllerProviderInterface;
19
use FluidTYPO3\Flux\Provider\Interfaces\DataStructureProviderInterface;
20
use FluidTYPO3\Flux\Provider\Interfaces\FluidProviderInterface;
21
use FluidTYPO3\Flux\Provider\ProviderResolver;
22
use FluidTYPO3\Flux\Service\TypoScriptService;
23
use FluidTYPO3\Flux\Service\WorkspacesAwareRecordService;
24
use FluidTYPO3\Flux\Utility\ContentObjectFetcher;
25
use FluidTYPO3\Flux\Utility\ExtensionNamingUtility;
26
use FluidTYPO3\Flux\Utility\RecursiveArrayUtility;
27
use FluidTYPO3\Flux\ViewHelpers\FormViewHelper;
28
use Psr\Http\Message\ResponseFactoryInterface;
29
use Psr\Http\Message\ServerRequestInterface;
30
use TYPO3\CMS\Core\Utility\GeneralUtility;
31
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
32
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
33
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
34
use TYPO3\CMS\Extbase\Mvc\Controller\Arguments;
35
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerInterface;
36
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
37
use TYPO3\CMS\Extbase\Mvc\Request;
38
use TYPO3\CMS\Extbase\Mvc\Response;
39
use TYPO3\CMS\Extbase\Mvc\ResponseInterface;
40
use TYPO3\CMS\Fluid\View\TemplateView;
41
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
42
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
43
use TYPO3Fluid\Fluid\Core\ViewHelper\ViewHelperVariableContainer;
44
use TYPO3Fluid\Fluid\View\ViewInterface;
45

46
/**
47
 * Abstract Flux-enabled controller
48
 *
49
 * Extends a traditional ActionController with new services and methods
50
 * to ease interaction with Flux forms. Is not required as subclass for
51
 * Controllers rendering records associated with Flux - all it does is
52
 * ease the interaction by providing a common API.
53
 */
54
abstract class AbstractFluxController extends ActionController
55
{
56
    use DataAccessTrait;
57

58
    protected string $extensionName = 'FluidTYPO3.Flux';
59
    protected ?string $fluxRecordField = 'pi_flexform';
60
    protected ?string $fluxTableName = 'tt_content';
61
    protected array $data = [];
62
    private ?array $record = null;
63

64
    protected RenderingContextBuilder $renderingContextBuilder;
65
    protected RequestBuilder $requestBuilder;
66
    protected WorkspacesAwareRecordService $recordService;
67
    protected TypoScriptService $typoScriptService;
68
    protected ProviderResolver $providerResolver;
69
    protected Resolver $resolver;
70
    protected ViewBuilder $viewBuilder;
71
    protected ?ControllerProviderInterface $provider = null;
72

73
    public function __construct(
74
        RenderingContextBuilder $renderingContextBuilder,
75
        RequestBuilder $requestBuilder,
76
        WorkspacesAwareRecordService $recordService,
77
        TypoScriptService $typoScriptService,
78
        ProviderResolver $providerResolver,
79
        Resolver $resolver,
80
        ViewBuilder $viewBuilder
81
    ) {
82
        $this->renderingContextBuilder = $renderingContextBuilder;
154✔
83
        $this->requestBuilder = $requestBuilder;
154✔
84
        $this->recordService = $recordService;
154✔
85
        $this->typoScriptService = $typoScriptService;
154✔
86
        $this->providerResolver = $providerResolver;
154✔
87
        $this->resolver = $resolver;
154✔
88
        $this->viewBuilder = $viewBuilder;
154✔
89

90
        /** @var Arguments $arguments */
91
        $arguments = GeneralUtility::makeInstance(Arguments::class);
154✔
92
        $this->arguments = $arguments;
154✔
93

94
        /** @var Request $request */
95
        $request = $requestBuilder->buildRequestFor(
154✔
96
            $this->extensionName,
154✔
97
            'Dummy',
154✔
98
            'render',
154✔
99
            '',
154✔
100
            [],
154✔
101
        );
154✔
102
        $this->request = $request;
154✔
103
    }
104

105
    protected function initializeSettings(): void
106
    {
107
        if ($this->provider === null) {
7✔
108
            return;
×
109
        }
110
        $row = $this->getRecord();
7✔
111
        $extensionKey = $this->provider->getControllerExtensionKeyFromRecord($row);
7✔
112
        $extensionName = ExtensionNamingUtility::getExtensionName($extensionKey);
7✔
113
        $pluginName = $this->request->getPluginName();
7✔
114
        $this->settings = RecursiveArrayUtility::merge(
7✔
115
            (array) $this->configurationManager->getConfiguration(
7✔
116
                ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
7✔
117
                $extensionName,
7✔
118
                $pluginName
7✔
119
            ),
7✔
120
            (array) $this->settings
7✔
121
        );
7✔
122

123
        if ($this->provider instanceof DataStructureProviderInterface) {
7✔
124
            $this->data = $this->provider->getFlexFormValues($row);
7✔
125
        }
126

127
        $overrides = HookHandler::trigger(
7✔
128
            HookHandler::CONTROLLER_SETTINGS_INITIALIZED,
7✔
129
            [
7✔
130
                'settings' => $this->settings,
7✔
131
                'data' => $this->data,
7✔
132
                'record' => $row,
7✔
133
                'provider' => $this->provider,
7✔
134
                'controller' => $this,
7✔
135
                'request' => $this->request,
7✔
136
                'extensionKey' => $extensionKey
7✔
137
            ]
7✔
138
        );
7✔
139
        $this->data = $overrides['data'];
7✔
140
        $this->settings = $overrides['settings'];
7✔
141
        $this->provider = $overrides['provider'];
7✔
142
    }
143

144
    protected function initializeOverriddenSettings(): void
145
    {
146
        if ($this->provider === null) {
35✔
147
            return;
×
148
        }
149
        $row = $this->getRecord();
35✔
150
        $extensionKey = $this->provider->getControllerExtensionKeyFromRecord($row);
35✔
151
        $extensionKey = ExtensionNamingUtility::getExtensionKey($extensionKey);
35✔
152
        if (is_array($this->data['settings'] ?? null)) {
35✔
153
            // a "settings." array is defined in the flexform configuration - extract it, use as "settings" in template
154
            // as well as the internal $this->settings array as per expected Extbase behavior.
155
            $this->settings = RecursiveArrayUtility::merge($this->settings, $this->data['settings'] ?? []);
28✔
156
        }
157
        if ($this->settings['useTypoScript'] ?? false) {
35✔
158
            // an override shared by all Flux enabled controllers: setting plugin.tx_EXTKEY.settings.useTypoScript = 1
159
            // will read the "settings" array from that location instead - thus excluding variables from the flexform
160
            // which are still available as $this->data but no longer available automatically in the template.
161
            $this->settings = $this->typoScriptService->getSettingsForExtensionName($extensionKey);
21✔
162
        }
163
    }
164

165
    protected function initializeProvider(): void
166
    {
167
        $row = $this->getRecord();
28✔
168
        $table = (string) $this->getFluxTableName();
28✔
169
        $field = $this->getFluxRecordField();
28✔
170
        $provider = $this->providerResolver->resolvePrimaryConfigurationProvider(
28✔
171
            $table,
28✔
172
            $field,
28✔
173
            $row,
28✔
174
            null,
28✔
175
            [ControllerProviderInterface::class]
28✔
176
        );
28✔
177
        if ($provider === null) {
28✔
178
            throw new \RuntimeException(
7✔
179
                'Unable to resolve a ConfigurationProvider, but controller indicates it is a Flux-enabled ' .
7✔
180
                'Controller - this is a grave error and indicates that EXT: ' . $this->extensionName . ' itself is ' .
7✔
181
                'broken - or that EXT:' . $this->extensionName . ' has been overridden by another implementation ' .
7✔
182
                'which is broken. The controller that caused this error was ' . get_class($this) . '".',
7✔
183
                1377458581
7✔
184
            );
7✔
185
        }
186
        $this->provider = $provider;
21✔
187
    }
188

189
    protected function initializeViewVariables(ViewInterface $view): void
190
    {
191
        $contentObject = $this->getContentObject();
7✔
192
        $row = $this->getRecord();
7✔
193

194
        $view->assign('contentObject', $contentObject);
7✔
195
        $view->assign('data', $contentObject instanceof ContentObjectRenderer ? $contentObject->data : null);
7✔
196
        if ($this->provider instanceof FluidProviderInterface) {
7✔
197
            $view->assignMultiple($this->provider->getTemplateVariables($row));
7✔
198
        }
199
        $view->assignMultiple($this->data);
7✔
200
        $view->assign('settings', $this->settings);
7✔
201
        $view->assign('provider', $this->provider);
7✔
202
        $view->assign('record', $row);
7✔
203

204
        HookHandler::trigger(
7✔
205
            HookHandler::CONTROLLER_VARIABLES_ASSIGNED,
7✔
206
            [
7✔
207
                'view' => $view,
7✔
208
                'record' => $row,
7✔
209
                'settings' => $this->settings,
7✔
210
                'provider' => $this->provider,
7✔
211
                'contentObject' => $contentObject,
7✔
212
            ]
7✔
213
        );
7✔
214
    }
215

216
    protected function initializeViewHelperVariableContainer(
217
        ViewHelperVariableContainer $viewHelperVariableContainer
218
    ): void {
219
        $viewHelperVariableContainer->add(FormViewHelper::class, 'provider', $this->provider);
7✔
220
        $viewHelperVariableContainer->add(
7✔
221
            FormViewHelper::class,
7✔
222
            'extensionName',
7✔
223
            $this->request->getControllerExtensionKey()
7✔
224
        );
7✔
225
        $viewHelperVariableContainer->add(
7✔
226
            FormViewHelper::class,
7✔
227
            'pluginName',
7✔
228
            $this->request->getPluginName()
7✔
229
        );
7✔
230
        $viewHelperVariableContainer->add(FormViewHelper::class, 'record', $this->getRecord());
7✔
231
    }
232

233
    protected function initializeAction(): void
234
    {
235
        $this->initializeProvider();
7✔
236
        $this->initializeSettings();
7✔
237
        $this->initializeOverriddenSettings();
7✔
238
    }
239

240
    protected function resolveView(): ViewInterface
241
    {
242
        if (!$this->provider instanceof ControllerProviderInterface) {
14✔
243
            throw new \RuntimeException(
×
244
                get_class($this) . ' cannot handle record; no ControllerProviderInterface could be resolved',
×
245
                1672082347
×
246
            );
×
247
        }
248

249
        $record = $this->getRecord();
14✔
250
        $extensionKey = ExtensionNamingUtility::getExtensionKey(
14✔
251
            $this->provider->getControllerExtensionKeyFromRecord($record)
14✔
252
        );
14✔
253

254
        $templatePathAndFilename = null;
14✔
255
        if ($this->provider instanceof FluidProviderInterface) {
14✔
256
            $templatePathAndFilename = $this->provider->getTemplatePathAndFilename($record);
14✔
257
        }
258

259
        $view = $this->viewBuilder->buildTemplateView(
14✔
260
            $extensionKey,
14✔
261
            $this->resolver->resolveControllerNameFromControllerClassName(get_class($this)),
14✔
262
            $this->provider->getControllerActionFromRecord($record),
14✔
263
            $this->provider->getPluginName() ?? $this->provider->getControllerNameFromRecord($record),
14✔
264
            $templatePathAndFilename,
14✔
265
            $this->request
14✔
266
        );
14✔
267

268
        $renderingContext = $view->getRenderingContext();
14✔
269

270
        $this->initializeViewVariables($view);
14✔
271
        $this->initializeViewHelperVariableContainer($renderingContext->getViewHelperVariableContainer());
14✔
272
        HookHandler::trigger(
14✔
273
            HookHandler::CONTROLLER_VIEW_INITIALIZED,
14✔
274
            [
14✔
275
                'view' => $view,
14✔
276
                'request' => $this->request,
14✔
277
                'provider' => $this->provider,
14✔
278
                'controller' => $this,
14✔
279
                'extensionKey' => $extensionKey
14✔
280
            ]
14✔
281
        );
14✔
282
        return $view;
14✔
283
    }
284

285
    /**
286
     * @return \Psr\Http\Message\ResponseInterface|Response
287
     */
288
    protected function createHtmlResponse(string $html = null)
289
    {
290
        if (method_exists($this, 'htmlResponse')) {
×
291
            return parent::htmlResponse($html);
×
292
        }
293
        $response = clone $this->response;
×
294
        $response->setContent((string) $html);
×
295
        return $response;
×
296
    }
297

298
    /**
299
     * Default action, proxy for "render". Added in order to
300
     * capture requests which use the Fluid-native "default"
301
     * action name when no specific action name is set in the
302
     * request. The "default" action is also returned by
303
     * vanilla Provider instances when registering them for
304
     * content object types or other ad-hoc registrations.
305
     *
306
     * @return \Psr\Http\Message\ResponseInterface|Response|ResponseInterface
307
     */
308
    public function defaultAction()
309
    {
310
        return $this->renderAction();
7✔
311
    }
312

313
    /**
314
     * Render content
315
     *
316
     * @return \Psr\Http\Message\ResponseInterface|Response|ResponseInterface
317
     */
318
    public function renderAction()
319
    {
320
        if (!$this->provider instanceof ControllerProviderInterface) {
14✔
321
            throw new \RuntimeException(
7✔
322
                get_class($this) . ' cannot handle record; no ControllerProviderInterface could be resolved',
7✔
323
                1672082347
7✔
324
            );
7✔
325
        }
326
        $row = $this->getRecord();
7✔
327
        $extensionKey = $this->provider->getControllerExtensionKeyFromRecord($row);
7✔
328
        $extensionSignature = ExtensionNamingUtility::getExtensionSignature($extensionKey);
7✔
329
        $pluginName = $this->request->getPluginName();
7✔
330
        $pluginSignature = strtolower('tx_' . $extensionSignature . '_' . $pluginName);
7✔
331
        $controllerExtensionKey = $this->provider->getControllerExtensionKeyFromRecord($row);
7✔
332
        $requestActionName = $this->resolveOverriddenFluxControllerActionNameFromRequestParameters($pluginSignature);
7✔
333
        $controllerActionName = $this->provider->getControllerActionFromRecord($row);
7✔
334
        $actualActionName = null !== $requestActionName ? $requestActionName : $controllerActionName;
7✔
335
        $controllerName = $this->request->getControllerName();
7✔
336

337
        return $this->performSubRendering(
7✔
338
            $controllerExtensionKey,
7✔
339
            $controllerName,
7✔
340
            $actualActionName,
7✔
341
            $pluginName,
7✔
342
            $pluginSignature
7✔
343
        );
7✔
344
    }
345

346
    protected function resolveOverriddenFluxControllerActionNameFromRequestParameters(string $pluginSignature): ?string
347
    {
348
        return $this->getServerRequest()->getQueryParams()[$pluginSignature]['action'] ?? null;
7✔
349
    }
350

351
    /**
352
     * @return \Psr\Http\Message\ResponseInterface|Response|ResponseInterface
353
     */
354
    protected function performSubRendering(
355
        string $extensionName,
356
        string $controllerName,
357
        string $actionName,
358
        string $pluginName,
359
        string $pluginSignature
360
    ) {
361
        if (property_exists($this, 'responseFactory') && $this->responseFactory instanceof ResponseFactoryInterface) {
21✔
362
            $response = $this->responseFactory->createResponse();
18✔
363
        } else {
364
            /** @var ResponseInterface $response */
365
            $response = GeneralUtility::makeInstance(Response::class);
3✔
366
        }
367
    
368
        $shouldRelay = $this->hasSubControllerActionOnForeignController($extensionName, $controllerName, $actionName);
21✔
369
        $foreignControllerClass = null;
21✔
370
        $content = null;
21✔
371
        if (!$shouldRelay) {
21✔
372
            if ($this->provider instanceof FluidProviderInterface) {
14✔
373
                $templatePathAndFilename = $this->provider->getTemplatePathAndFilename($this->getRecord());
7✔
374
                $vendorLessExtensionName = ExtensionNamingUtility::getExtensionName($extensionName);
7✔
375
                /** @var TemplateView $view */
376
                $view = $this->view;
7✔
377
                $renderingContext = $view->getRenderingContext();
7✔
378
                $paths = $renderingContext->getTemplatePaths();
7✔
379

380
                if (method_exists($this->request, 'setControllerExtensionName')) {
7✔
381
                    $this->request->setControllerExtensionName($vendorLessExtensionName);
4✔
382
                }
383

384
                if (method_exists($this->request, 'withControllerExtensionName')) {
7✔
385
                    $this->request = $this->request->withControllerExtensionName($vendorLessExtensionName);
6✔
386
                }
387

388
                $this->configurationManager->setConfiguration(
7✔
389
                    array_merge(
7✔
390
                        (array) $this->configurationManager->getConfiguration(
7✔
391
                            ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT,
7✔
392
                            $vendorLessExtensionName
7✔
393
                        ),
7✔
394
                        [
7✔
395
                            'extensionName' => $vendorLessExtensionName,
7✔
396
                        ]
7✔
397
                    )
7✔
398
                );
7✔
399
                $paths->setTemplatePathAndFilename((string) $templatePathAndFilename);
7✔
400
            }
401
            $content = $this->view->render();
14✔
402
        } else {
403
            $foreignControllerClass = $this->resolver->resolveFluxControllerClassNameByExtensionKeyAndControllerName(
7✔
404
                $extensionName,
7✔
405
                $controllerName
7✔
406
            );
7✔
407
            $content = $this->callSubControllerAction(
7✔
408
                $extensionName,
7✔
409
                $foreignControllerClass ?? static::class,
7✔
410
                $actionName,
7✔
411
                $pluginName,
7✔
412
                $pluginSignature
7✔
413
            );
7✔
414
        }
415
        $content = HookHandler::trigger(
21✔
416
            HookHandler::CONTROLLER_AFTER_RENDERING,
21✔
417
            [
21✔
418
                'view' => $this->view,
21✔
419
                'content' => $content,
21✔
420
                'request' => $this->request,
21✔
421
                'response' => $response,
21✔
422
                'extensionName' => $extensionName,
21✔
423
                'controllerClassName' => $foreignControllerClass,
21✔
424
                'controllerActionName' => $actionName
21✔
425
            ]
21✔
426
        )['content'];
21✔
427

428
        return $content instanceof \Psr\Http\Message\ResponseInterface || $content instanceof ResponseInterface
21✔
429
            ? $content
×
430
            : $this->createHtmlResponse($content);
21✔
431
    }
432

433
    protected function hasSubControllerActionOnForeignController(
434
        string $extensionName,
435
        string $controllerName,
436
        string $actionName
437
    ): bool {
438
        $potentialControllerClassName = $this->resolver->resolveFluxControllerClassNameByExtensionKeyAndControllerName(
7✔
439
            $extensionName,
7✔
440
            $controllerName
7✔
441
        );
7✔
442
        if ($potentialControllerClassName === null) {
7✔
443
            return false;
7✔
444
        }
445
        $isNotThis = get_class($this) !== $potentialControllerClassName;
×
446
        $isValidController = class_exists($potentialControllerClassName);
×
447
        return ($isNotThis && $isValidController
×
448
            && method_exists($potentialControllerClassName, $actionName . 'Action'));
×
449
    }
450

451
    /**
452
     * @param class-string $controllerClassName
453
     * @return \Psr\Http\Message\ResponseInterface|ResponseInterface|null
454
     */
455
    protected function callSubControllerAction(
456
        string $extensionName,
457
        string $controllerClassName,
458
        string $controllerActionName,
459
        string $pluginName,
460
        string $pluginSignature
461
    ) {
462
        $serverRequest = $this->getServerRequest();
7✔
463
        $arguments = $serverRequest->getQueryParams()[$pluginSignature] ?? [];
7✔
464
        $arguments = array_merge($arguments, ((array) $serverRequest->getParsedBody())[$pluginSignature] ?? []);
7✔
465

466
        $request = $this->requestBuilder->buildRequestFor(
7✔
467
            $extensionName,
7✔
468
            $this->resolver->resolveControllerNameFromControllerClassName(
7✔
469
                $controllerClassName
7✔
470
            ),
7✔
471
            $controllerActionName,
7✔
472
            $pluginName,
7✔
473
            $arguments
7✔
474
        );
7✔
475

476
        /** @var ControllerInterface $potentialControllerInstance */
477
        $potentialControllerInstance = GeneralUtility::makeInstance($controllerClassName);
7✔
478

479
        if (property_exists($this, 'responseFactory') && $this->responseFactory instanceof ResponseFactoryInterface) {
7✔
480
            /** @var ResponseInterface\ $response */
481
            $response = $this->responseFactory->createResponse();
6✔
482
        } else {
483
            /** @var ResponseInterface $response */
484
            $response = GeneralUtility::makeInstance(Response::class);
1✔
485
        }
486

487
        try {
488
            HookHandler::trigger(
7✔
489
                HookHandler::CONTROLLER_BEFORE_REQUEST,
7✔
490
                [
7✔
491
                    'request' => $this->request,
7✔
492
                    'response' => $response,
7✔
493
                    'extensionName' => $extensionName,
7✔
494
                    'controllerClassName' => $controllerClassName,
7✔
495
                    'controllerActionName' => $controllerActionName
7✔
496
                ]
7✔
497
            );
7✔
498

499
            /** @var \Psr\Http\Message\ResponseInterface|ResponseInterface|null $responseFromCall */
500
            $responseFromCall = $potentialControllerInstance->processRequest($request, $response);
7✔
501
            if ($responseFromCall) {
7✔
502
                $response = $responseFromCall;
7✔
503
            }
504
        } catch (StopActionException $error) {
×
505
            // intentionally left blank
506
        }
507
        HookHandler::trigger(
7✔
508
            HookHandler::CONTROLLER_AFTER_REQUEST,
7✔
509
            [
7✔
510
                'request' => $this->request,
7✔
511
                'response' => $response,
7✔
512
                'extensionName' => $extensionName,
7✔
513
                'controllerClassName' => $controllerClassName,
7✔
514
                'controllerActionName' => $controllerActionName
7✔
515
            ]
7✔
516
        );
7✔
517

518
        return $response;
7✔
519
    }
520

521
    /**
522
     * Get the data stored in a record's Flux-enabled field,
523
     * i.e. the variables of the Flux template as configured in this
524
     * particular record.
525
     */
526
    protected function getData(): array
527
    {
528
        return $this->data;
7✔
529
    }
530

531
    protected function getFluxRecordField(): ?string
532
    {
533
        return $this->fluxRecordField;
21✔
534
    }
535

536
    protected function getFluxTableName(): ?string
537
    {
538
        return $this->fluxTableName;
35✔
539
    }
540

541
    public function getRecord(): array
542
    {
543
        if ($this->record !== null) {
28✔
544
            return $this->record;
14✔
545
        }
546

547
        $contentObject = $this->getContentObject();
28✔
548
        if ($contentObject === null) {
28✔
549
            throw new \UnexpectedValueException(
7✔
550
                "Record of table " . $this->getFluxTableName() . ' not found',
7✔
551
                1666538343
7✔
552
            );
7✔
553
        }
554

555
        if (version_compare(VersionNumberUtility::getCurrentTypo3Version(), '11.5', '<')) {
21✔
556
            /** @var TypoScriptFrontendController|null $tsfe */
557
            $tsfe = $GLOBALS['TSFE'] ?? null;
3✔
558
        } else {
559
            $tsfe = $contentObject->getTypoScriptFrontendController();
18✔
560
        }
561
        if ($tsfe === null) {
21✔
562
            throw new \UnexpectedValueException(
×
563
                "Record of table " . $this->getFluxTableName() . ' not found',
×
564
                1729864782
×
565
            );
×
566
        }
567

568
        [$table, $recordUid] = GeneralUtility::trimExplode(
21✔
569
            ':',
21✔
570
            $tsfe->currentRecord ?: $contentObject->currentRecord
21✔
571
        );
21✔
572
        $record = $this->recordService->getSingle($table, '*', (integer) $recordUid);
21✔
573
        if ($record === null) {
21✔
574
            throw new \UnexpectedValueException(
×
575
                "Record of table " . $this->getFluxTableName() . ' not found',
×
576
                1729864698
×
577
            );
×
578
        }
579

580
        if ($record['_LOCALIZED_UID'] ?? false) {
21✔
581
            $record = array_merge(
×
582
                $record,
×
583
                $this->recordService->getSingle(
×
584
                    (string) $this->getFluxTableName(),
×
585
                    '*',
×
586
                    $record['_LOCALIZED_UID']
×
587
                ) ?? $record
×
588
            );
×
589
        }
590
        return $this->record = $record;
21✔
591
    }
592

593
    protected function getContentObject(): ?ContentObjectRenderer
594
    {
595
        return ContentObjectFetcher::resolve($this->configurationManager);
×
596
    }
597

598
    protected function getServerRequest(): ServerRequestInterface
599
    {
600
        /** @var ServerRequestInterface $request */
601
        $request = $GLOBALS['TYPO3_REQUEST'];
×
602
        return $request;
×
603
    }
604
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc