• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CPS-IT / handlebars / 23363698435

20 Mar 2026 09:40PM UTC coverage: 89.861% (-0.4%) from 90.285%
23363698435

Pull #543

github

web-flow
Merge 223a31852 into 86597a598
Pull Request #543: [TASK] Update codebase to match PHPStan max level

139 of 157 new or added lines in 43 files covered. (88.54%)

26 existing lines in 11 files now uncovered.

1356 of 1509 relevant lines covered (89.86%)

6.82 hits per line

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

97.01
/Classes/View/HandlebarsViewFactory.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the TYPO3 CMS extension "handlebars".
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17

18
namespace CPSIT\Typo3Handlebars\View;
19

20
use CPSIT\Typo3Handlebars\Controller;
21
use Symfony\Component\DependencyInjection;
22
use TYPO3\CMS\Core;
23
use TYPO3\CMS\Extbase;
24
use TYPO3\CMS\Fluid;
25
use TYPO3\CMS\Frontend;
26

27
/**
28
 * HandlebarsViewFactory
29
 *
30
 * @author Elias Häußler <e.haeussler@familie-redlich.de>
31
 * @license GPL-2.0-or-later
32
 */
33
#[DependencyInjection\Attribute\AsAlias(Core\View\ViewFactoryInterface::class, public: true)]
34
final readonly class HandlebarsViewFactory implements Core\View\ViewFactoryInterface
35
{
36
    public function __construct(
12✔
37
        private Extbase\Configuration\ConfigurationManagerInterface $configurationManager,
38
        #[DependencyInjection\Attribute\Autowire(service: Fluid\View\FluidViewFactory::class)]
39
        private Core\View\ViewFactoryInterface $delegate,
40
        private Core\TypoScript\TypoScriptService $typoScriptService,
41
    ) {}
12✔
42

43
    public function create(Core\View\ViewFactoryData $data): Core\View\ViewInterface
12✔
44
    {
45
        return $this->resolveView($data) ?? $this->delegate->create($data);
12✔
46
    }
47

48
    private function resolveView(Core\View\ViewFactoryData $data): ?HandlebarsView
12✔
49
    {
50
        $request = $data->request;
12✔
51
        $contentObjectRenderer = $request?->getAttribute('currentContentObject');
12✔
52

53
        if ($request === null) {
12✔
54
            return null;
1✔
55
        }
56

57
        if (!($contentObjectRenderer instanceof Frontend\ContentObject\ContentObjectRenderer)) {
11✔
58
            return null;
2✔
59
        }
60

61
        if ($request instanceof Extbase\Mvc\RequestInterface) {
9✔
62
            $contentObjectConfiguration = $this->resolveExtbaseContentObjectConfiguration(
8✔
63
                $request->getControllerObjectName(),
8✔
64
                $request->getControllerActionName(),
8✔
65
                $data->format ?? $request->getFormat(),
8✔
66
            );
8✔
67
        } else {
68
            $contentObjectConfiguration = array_filter(
1✔
69
                [
1✔
70
                    'templateName' => $data->templatePathAndFilename,
1✔
71
                    'templateRootPaths.' => $data->templateRootPaths,
1✔
72
                    'partialRootPaths.' => $data->partialRootPaths,
1✔
73
                    'layoutRootPaths.' => $data->layoutRootPaths,
1✔
74
                    'format' => $data->format,
1✔
75
                ],
1✔
76
                static fn(mixed $value) => $value !== null,
1✔
77
            );
1✔
78
        }
79

80
        if ($contentObjectConfiguration !== null) {
9✔
81
            return new HandlebarsView($contentObjectRenderer, $this->typoScriptService, $contentObjectConfiguration, $request);
8✔
82
        }
83

84
        return null;
1✔
85
    }
86

87
    /**
88
     * @return array<string|int, mixed>|null
89
     */
90
    private function resolveExtbaseContentObjectConfiguration(
8✔
91
        string $controllerObjectName,
92
        string $actionName,
93
        string $format,
94
    ): ?array {
95
        $configuration = $this->configurationManager->getConfiguration(
8✔
96
            Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK,
8✔
97
        );
8✔
98
        $controllerAlias = $configuration['controllerConfiguration'][$controllerObjectName]['alias'] ?? null;
8✔
99

100
        // Early return if controller is not properly registered
101
        if (!is_string($controllerAlias)) {
8✔
UNCOV
102
            return null;
×
103
        }
104

105
        // Use hbs as default format, can be overridden with TypoScript
106
        if ($format === 'html') {
8✔
UNCOV
107
            $format = 'hbs';
×
108
        }
109

110
        $handlebarsConfiguration = $configuration['handlebars'] ?? null;
8✔
111
        $defaultConfiguration = [
8✔
112
            'templateName' => $controllerAlias . '/' . $actionName,
8✔
113
            'format' => $format,
8✔
114
        ];
8✔
115

116
        // Early return if no handlebars configuration is available
117
        if (!is_array($handlebarsConfiguration)) {
8✔
118
            if (is_a($controllerObjectName, Controller\HandlebarsController::class, true)) {
2✔
119
                return $defaultConfiguration;
1✔
120
            }
121

122
            return null;
1✔
123
        }
124

125
        // HANDLEBARSTEMPLATE content object requires TypoScript configuration, so let's convert early
126
        $typoScriptConfiguration = $this->typoScriptService->convertPlainArrayToTypoScriptArray($handlebarsConfiguration);
6✔
127

128
        // Resolve TypoScript configuration based on controller context
129
        $resolvedConfiguration = [];
6✔
130
        $possibleConfigurationKeys = [
6✔
131
            // Fallback
132
            'default',
6✔
133
            // Controller only
134
            $controllerAlias,
6✔
135
            // Controller & action
136
            $controllerAlias . '::' . $actionName,
6✔
137
            // Controller FQCN
138
            $controllerObjectName,
6✔
139
        ];
6✔
140
        foreach ($possibleConfigurationKeys as $possibleConfigurationKey) {
6✔
141
            if (is_array($typoScriptConfiguration[$possibleConfigurationKey . '.'] ?? null)) {
6✔
142
                Core\Utility\ArrayUtility::mergeRecursiveWithOverrule(
5✔
143
                    $resolvedConfiguration,
5✔
144
                    $typoScriptConfiguration[$possibleConfigurationKey . '.'],
5✔
145
                );
5✔
146
            }
147
        }
148

149
        // Early return if no configuration was resolved
150
        if ($resolvedConfiguration === []) {
6✔
151
            return $defaultConfiguration;
1✔
152
        }
153

154
        // Add format
155
        if (!isset($resolvedConfiguration['format'])) {
5✔
156
            $resolvedConfiguration['format'] = $format;
5✔
157
        }
158

159
        return $resolvedConfiguration;
5✔
160
    }
161
}
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