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

FluidTYPO3 / flux / 27757675993

18 Jun 2026 11:55AM UTC coverage: 89.162% (-3.5%) from 92.646%
27757675993

push

github

NamelessCoder
[TASK] Address last phpstan warnings

6228 of 6985 relevant lines covered (89.16%)

40.84 hits per line

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

96.77
/Classes/Core.php
1
<?php
2
namespace FluidTYPO3\Flux;
3

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

11
use FluidTYPO3\Flux\Content\ContentTypeManager;
12
use FluidTYPO3\Flux\Hooks\HookHandler;
13
use FluidTYPO3\Flux\Provider\Provider;
14
use FluidTYPO3\Flux\Provider\ProviderInterface;
15
use FluidTYPO3\Flux\Utility\ExtensionNamingUtility;
16
use Symfony\Component\Finder\Finder;
17
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
use TYPO3\CMS\Core\Utility\PathUtility;
20

21
/**
22
 * Quick-access API methods to easily integrate with Flux
23
 */
24
class Core
25
{
26
    public const string CONTROLLER_ALL = '_all';
27

28
    protected static array $providers = [];
29
    private static array $unregisteredProviders = [];
30
    protected static array $extensions = [
31
        self::CONTROLLER_ALL => []
32
    ];
33
    protected static array $queuedContentTypeRegistrations = [];
34

35
    public static function getQueuedContentTypeRegistrations(): array
36
    {
37
        return self::$queuedContentTypeRegistrations;
24✔
38
    }
39

40
    public static function clearQueuedContentTypeRegistrations(): void
41
    {
42
        self::$queuedContentTypeRegistrations = [];
12✔
43
    }
44

45
    public static function registerProviderExtensionKey(
46
        string $extensionKey,
47
        string $providesControllerName = self::CONTROLLER_ALL
48
    ): void {
49
        if ($providesControllerName === 'Content' && !ExtensionManagementUtility::isLoaded('fluidcontent')) {
44✔
50
            // Special temporary case - when fluidcontent is not installed, Flux takes over and registers all
51
            // detected template files as native CTypes. Remove if/when fluidcontent is discontinued.
52
            $legacyKey = ExtensionNamingUtility::getExtensionKey($extensionKey);
4✔
53
            $templateRootPath = ExtensionManagementUtility::extPath($legacyKey, 'Resources/Private/Templates/Content/');
4✔
54
            /** @var ContentTypeManager $contentTypeManager */
55
            $contentTypeManager = GeneralUtility::makeInstance(ContentTypeManager::class);
4✔
56
            $finder = Finder::create()->in($templateRootPath)->name('*.html')->sortByName();
4✔
57
            foreach ($finder->files() as $file) {
4✔
58
                /** @var \SplFileInfo $file */
59
                $contentTypeName = str_replace('_', '', $legacyKey)
4✔
60
                    . '_'
4✔
61
                    . strtolower(substr(str_replace(DIRECTORY_SEPARATOR, '', $file->getRelativePathname()), 0, -5));
4✔
62
                self::registerTemplateAsContentType($extensionKey, $file->getPathname(), $contentTypeName);
4✔
63
                $contentTypeManager->registerTypeName($contentTypeName);
4✔
64
            }
65
        }
66
        if (false === isset(self::$extensions[$providesControllerName])) {
44✔
67
            self::$extensions[$providesControllerName] = [];
20✔
68
        }
69

70
        if (false === in_array($extensionKey, self::$extensions[$providesControllerName])) {
44✔
71
            $overrides = HookHandler::trigger(
20✔
72
                HookHandler::PROVIDER_EXTENSION_REGISTERED,
20✔
73
                [
20✔
74
                    'extensionKey' => $extensionKey,
20✔
75
                    'providesControllerName' => $providesControllerName
20✔
76
                ]
20✔
77
            );
20✔
78
            array_push(self::$extensions[$overrides['providesControllerName']], $overrides['extensionKey']);
20✔
79
        }
80
    }
81

82
    public static function getRegisteredProviderExtensionKeys(string $forControllerName): array
83
    {
84
        if (true === isset(self::$extensions[$forControllerName])) {
48✔
85
            return array_unique(
44✔
86
                array_merge(self::$extensions[self::CONTROLLER_ALL], self::$extensions[$forControllerName])
44✔
87
            );
44✔
88
        }
89
        return self::$extensions[self::CONTROLLER_ALL];
4✔
90
    }
91

92
    /**
93
     * Registers a class implementing one of the Flux ConfigurationProvider
94
     * interfaces.
95
     *
96
     * @param class-string|object $classNameOrInstance
97
     */
98
    public static function registerConfigurationProvider($classNameOrInstance): void
99
    {
100
        $alreadyRegistered = in_array($classNameOrInstance, self::$providers);
36✔
101
        $alreadyUnregistered = in_array($classNameOrInstance, self::$unregisteredProviders);
36✔
102
        if (!$alreadyUnregistered && !$alreadyRegistered) {
36✔
103
            $classNameOrInstance = HookHandler::trigger(
32✔
104
                HookHandler::PROVIDER_REGISTERED,
32✔
105
                [
32✔
106
                    'provider' => $classNameOrInstance
32✔
107
                ]
32✔
108
            )['provider'];
32✔
109
            array_push(self::$providers, $classNameOrInstance);
32✔
110
        }
111
    }
112

113
    /**
114
     * Registers a Fluid template for use as a Dynamic Flex Form template in the
115
     * style of Flux's Fluid Content Element and Fluid Page configurations. See
116
     * documentation web site for more detailed information about how to
117
     * configure such a FlexForm template.
118
     *
119
     * Note: you can point to your Model Object templates and place the
120
     * configuration in these templates - and get automatically transformed
121
     * values from your FlexForms, i.e. a Domain Object instance from a "group"
122
     * type select box or an ObjectStorage from a list of records. Usual output
123
     * is completely ignored, only the "Configuration" section is considered.
124
     *
125
     * @param string $extensionKey The extension key which registered this FlexForm
126
     * @param string $pluginSignature The plugin signature this FlexForm belongs to
127
     * @param string $templateFilename Location of the Fluid template containing field definitions
128
     * @param array $variables Optional array of variables to pass to Fluid template
129
     * @param string|null $section Optional section name containing the configuration
130
     * @param array|null $paths Optional paths array / Closure to return paths
131
     * @param string $fieldName Optional fieldname if not from pi_flexform
132
     */
133
    public static function registerFluidFlexFormPlugin(
134
        string $extensionKey,
135
        string $pluginSignature,
136
        string $templateFilename,
137
        array $variables = [],
138
        ?string $section = null,
139
        ?array $paths = null,
140
        string $fieldName = 'pi_flexform'
141
    ): ProviderInterface {
142
        $splitSignature = explode('_', $pluginSignature, 2);
4✔
143
        $pluginName = GeneralUtility::underscoredToUpperCamelCase(end($splitSignature));
4✔
144

145
        /** @var ProviderInterface $provider */
146
        $provider = GeneralUtility::makeInstance(Provider::class);
4✔
147
        $provider->setTableName('tt_content');
4✔
148
        $provider->setFieldName($fieldName);
4✔
149
        $provider->setExtensionKey($extensionKey);
4✔
150
        $provider->setListType($pluginSignature);
4✔
151
        $provider->setPluginName($pluginName);
4✔
152
        $provider->setTemplatePathAndFilename($templateFilename);
4✔
153
        $provider->setTemplateVariables($variables);
4✔
154
        $provider->setTemplatePaths($paths);
4✔
155
        $provider->setConfigurationSectionName($section);
4✔
156
        self::registerConfigurationProvider($provider);
4✔
157
        return $provider;
4✔
158
    }
159

160
    /**
161
     * Same as registerFluidFlexFormPlugin, but uses a content object type for
162
     * resolution - use this if you registered your Extbase plugin as a content
163
     * object in your localconf.
164
     *
165
     * @param string $extensionKey The extension key which registered this FlexForm
166
     * @param string $contentObjectType The cType of the object you registered
167
     * @param string $templateFilename Location of the Fluid template containing field definitions
168
     * @param array $variables Optional array of variables to pass to Fluid template
169
     * @param string|null $section Optional section name containing the configuration
170
     * @param array|null $paths Optional paths array / Closure to return paths
171
     * @param string $fieldName Optional fieldname if not from pi_flexform
172
     */
173
    public static function registerFluidFlexFormContentObject(
174
        string $extensionKey,
175
        string $contentObjectType,
176
        string $templateFilename,
177
        array $variables = [],
178
        ?string $section = null,
179
        ?array $paths = null,
180
        string $fieldName = 'pi_flexform'
181
    ): ProviderInterface {
182
        /** @var ProviderInterface $provider */
183
        $provider = GeneralUtility::makeInstance(Provider::class);
4✔
184
        $provider->setTableName('tt_content');
4✔
185
        $provider->setFieldName($fieldName);
4✔
186
        $provider->setExtensionKey($extensionKey);
4✔
187
        $provider->setTemplatePathAndFilename($templateFilename);
4✔
188
        $provider->setTemplateVariables($variables);
4✔
189
        $provider->setTemplatePaths($paths);
4✔
190
        $provider->setConfigurationSectionName($section);
4✔
191
        $provider->setContentObjectType($contentObjectType);
4✔
192
        self::registerConfigurationProvider($provider);
4✔
193
        return $provider;
4✔
194
    }
195

196
    /**
197
     * Same as registerFluidFlexFormPlugin, but enables registering FlexForms
198
     * for any TCA field (type "flex") or field whose TCA you have overridden
199
     * to display as a FlexForm.
200
     *
201
     * @param string $table The SQL table this FlexForm is bound to
202
     * @param string|null $fieldName The SQL field this FlexForm is bound to. If empty, binds to any/every field
203
     * @param string $templateFilename Location of the Fluid template containing field definitions
204
     * @param array $variables Optional array of variables to pass to Fluid template
205
     * @param string|null $section Optional section name containing the configuration
206
     * @param array|null $paths Optional paths array / Closure to return paths
207
     */
208
    public static function registerFluidFlexFormTable(
209
        string $table,
210
        ?string $fieldName,
211
        string $templateFilename,
212
        array $variables = [],
213
        ?string $section = null,
214
        ?array $paths = null
215
    ): ProviderInterface {
216
        /** @var ProviderInterface $provider */
217
        $provider = GeneralUtility::makeInstance(Provider::class);
4✔
218
        $provider->setTableName($table);
4✔
219
        $provider->setFieldName($fieldName);
4✔
220
        $provider->setTemplatePathAndFilename($templateFilename);
4✔
221
        $provider->setTemplateVariables($variables);
4✔
222
        $provider->setTemplatePaths($paths);
4✔
223
        $provider->setConfigurationSectionName($section);
4✔
224
        self::registerConfigurationProvider($provider);
4✔
225
        return $provider;
4✔
226
    }
227

228
    /**
229
     * Register a template directly for use as a custom CType. Once registered
230
     * the CType will appear in the "Flux content" tab in the new content
231
     * wizard, and will be driven by either a custom controller if one is
232
     * specified or detected by convention; or render through the vanilla
233
     * ContentController provided with Flux.
234
     *
235
     * @param string $providerExtensionName Vendor.ExtensionName format of extension scope of the template file
236
     * @param string $templateFilename Absolute path to template file containing Flux definition, EXT:... allowed
237
     * @param string|null $contentTypeName Optional override for the CType value this template will use
238
     * @param string|null $providerClassName Optional custom class implementing ProviderInterface from Flux
239
     */
240
    public static function registerTemplateAsContentType(
241
        string $providerExtensionName,
242
        string $templateFilename,
243
        ?string $contentTypeName = null,
244
        ?string $providerClassName = Provider::class
245
    ): void {
246
        if (!PathUtility::isAbsolutePath($templateFilename)) {
28✔
247
            $templateFilename = static::getAbsolutePathForFilename($templateFilename);
8✔
248
        }
249

250
        self::$queuedContentTypeRegistrations[] = [
28✔
251
            $providerExtensionName,
28✔
252
            $templateFilename,
28✔
253
            $providerClassName,
28✔
254
            $contentTypeName,
28✔
255
            null,
28✔
256
            null
28✔
257
        ];
28✔
258
    }
259

260
    public static function unregisterConfigurationProvider(string $providerClassName): void
261
    {
262
        if (true === in_array($providerClassName, self::$providers)) {
8✔
263
            $index = array_search($providerClassName, self::$providers);
4✔
264
            unset(self::$providers[$index]);
4✔
265
        } elseif (false === in_array($providerClassName, self::$unregisteredProviders)) {
4✔
266
            array_push(self::$unregisteredProviders, $providerClassName);
4✔
267
        }
268
    }
269

270
    /**
271
     * Gets the defined FlexForms configuration providers based on parameters
272
     * @return ProviderInterface[]
273
     */
274
    public static function getRegisteredFlexFormProviders(): array
275
    {
276
        reset(self::$providers);
16✔
277
        return self::$providers;
16✔
278
    }
279

280
    protected static function getAbsolutePathForFilename(string $filename): string
281
    {
282
        if (strpos($filename, '://') !== false) {
×
283
            return $filename;
×
284
        }
285
        return realpath($filename) ?: GeneralUtility::getFileAbsFileName($filename);
×
286
    }
287
}
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