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

CPS-IT / handlebars / 15461925183

05 Jun 2025 08:11AM UTC coverage: 90.937% (-1.9%) from 92.804%
15461925183

push

github

web-flow
Merge pull request #434 from CPS-IT/feature/typo3-v13

[!!!][FEATURE] Add support for TYPO3 v13.4, drop support for TYPO3 v12.4

69 of 86 new or added lines in 9 files covered. (80.23%)

2 existing lines in 1 file now uncovered.

883 of 971 relevant lines covered (90.94%)

5.52 hits per line

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

93.22
/Classes/Extbase/View/ExtbaseHandlebarsViewFactory.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 Fr\Typo3Handlebars\Extbase\View;
19

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

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

42
    public function create(Core\View\ViewFactoryData $data): Core\View\ViewInterface
4✔
43
    {
44
        if (!($data->request instanceof Extbase\Mvc\RequestInterface)) {
4✔
NEW
45
            return $this->delegate->create($data);
×
46
        }
47

48
        return $this->resolveView($data) ?? $this->delegate->create($data);
4✔
49
    }
50

51
    private function resolveView(Core\View\ViewFactoryData $data): ?ExtbaseHandlebarsView
4✔
52
    {
53
        /** @var Extbase\Mvc\RequestInterface $request */
54
        $request = $data->request;
4✔
55
        $contentObjectRenderer = $request->getAttribute('currentContentObject');
4✔
56

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

61
        $contentObjectConfiguration = $this->resolveContentObjectConfiguration(
3✔
62
            $contentObjectRenderer,
3✔
63
            $request->getControllerObjectName(),
3✔
64
            $request->getControllerActionName(),
3✔
65
            $data->format ?? $request->getFormat(),
3✔
66
        );
3✔
67

68
        if ($contentObjectConfiguration !== null) {
3✔
69
            return new ExtbaseHandlebarsView($contentObjectRenderer, $this->typoScriptService, $contentObjectConfiguration);
3✔
70
        }
71

NEW
72
        return null;
×
73
    }
74

75
    /**
76
     * @return array<string, mixed>|null
77
     */
78
    private function resolveContentObjectConfiguration(
3✔
79
        Frontend\ContentObject\ContentObjectRenderer $contentObjectRenderer,
80
        string $controllerObjectName,
81
        string $actionName,
82
        string $format,
83
    ): ?array {
84
        $configuration = $this->configurationManager->getConfiguration(
3✔
85
            Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK,
3✔
86
        );
3✔
87
        $controllerAlias = $configuration['controllerConfiguration'][$controllerObjectName]['alias'] ?? null;
3✔
88

89
        // Early return if controller is not properly registered
90
        if (!is_string($controllerAlias)) {
3✔
91
            return null;
×
92
        }
93

94
        // Use hbs as default format, can be overridden with TypoScript
95
        if ($format === 'html') {
3✔
96
            $format = 'hbs';
×
97
        }
98

99
        $handlebarsConfiguration = $configuration['handlebars'] ?? null;
3✔
100
        $defaultConfiguration = [
3✔
101
            'templateName' => $controllerAlias . '/' . $actionName,
3✔
102
            'format' => $format,
3✔
103
        ];
3✔
104

105
        // Early return if no handlebars configuration is available
106
        if (!is_array($handlebarsConfiguration)) {
3✔
107
            return $defaultConfiguration;
1✔
108
        }
109

110
        // HANDLEBARSTEMPLATE content object requires TypoScript configuration, so let's convert early
111
        $typoScriptConfiguration = $this->typoScriptService->convertPlainArrayToTypoScriptArray($handlebarsConfiguration);
2✔
112

113
        // Resolve template name from controller action
114
        if (is_string($typoScriptConfiguration['templateName'] ?? null) &&
2✔
115
            is_array($typoScriptConfiguration['templateName.'] ?? null)
2✔
116
        ) {
117
            // Inject custom fields to be referenced in TypoScript when resolving the
118
            // template name, e.g. in combination with a CASE content object
119
            $contentObjectRenderer->data['controllerName'] = $controllerAlias;
2✔
120
            $contentObjectRenderer->data['controllerObjectName'] = $controllerObjectName;
2✔
121
            $contentObjectRenderer->data['controllerAction'] = $actionName;
2✔
122
            $contentObjectRenderer->data['controllerNameAndAction'] = $controllerAlias . '::' . $actionName;
2✔
123

124
            try {
125
                // Resolve template name based on the current controller action
126
                $typoScriptConfiguration['templateName'] = $contentObjectRenderer->cObjGetSingle(
2✔
127
                    $typoScriptConfiguration['templateName'],
2✔
128
                    $typoScriptConfiguration['templateName.'],
2✔
129
                );
2✔
130
            } finally {
131
                // Remove configuration which is solely responsible for template name resolving
132
                unset(
2✔
133
                    $typoScriptConfiguration['templateName.'],
2✔
134
                    $contentObjectRenderer->data['controllerName'],
2✔
135
                    $contentObjectRenderer->data['controllerObjectName'],
2✔
136
                    $contentObjectRenderer->data['controllerAction'],
2✔
137
                    $contentObjectRenderer->data['controllerNameAndAction'],
2✔
138
                );
2✔
139
            }
140
        }
141

142
        // Early return if no (valid) template name is given
143
        if (empty($typoScriptConfiguration['templateName'])) {
2✔
144
            return $defaultConfiguration;
1✔
145
        }
146

147
        // Add format
148
        if (!isset($typoScriptConfiguration['format'])) {
1✔
149
            $typoScriptConfiguration['format'] = $format;
1✔
150
        }
151

152
        return $typoScriptConfiguration;
1✔
153
    }
154
}
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