• 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/Content/TypeDefinition/FluidFileBased/DropInContentTypeDefinition.php
1
<?php
2
namespace FluidTYPO3\Flux\Content\TypeDefinition\FluidFileBased;
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\Enum\ExtensionOption;
12
use FluidTYPO3\Flux\Provider\Provider;
13
use FluidTYPO3\Flux\Utility\ExtensionConfigurationUtility;
14
use Symfony\Component\Finder\Exception\DirectoryNotFoundException;
15
use Symfony\Component\Finder\Finder;
16
use TYPO3\CMS\Core\Core\Environment;
17
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19

20
/**
21
 * Drop-in Fluid Content Type Definition
22
 *
23
 * Holds one set of metadata to operate a single content type
24
 * based on a template file located in the site-wide, drop-in
25
 * resources location.
26
 */
27
class DropInContentTypeDefinition extends FluidFileBasedContentTypeDefinition
28
{
29
    public const string DESIGN_DIRECTORY = 'design/';
30
    public const string TEMPLATES_DIRECTORY = 'Templates/';
31
    public const string PARTIALS_DIRECTORY = 'Partials/';
32
    public const string LAYOUTS_DIRECTORY = 'Layouts/';
33
    public const string TEMPLATES_PATTERN = '*.html';
34
    public const string CONTENT_DIRECTORY = 'Content/';
35
    public const string PAGE_DIRECTORY = 'Page/';
36

37
    protected string $extensionIdentity = 'FluidTYPO3.Flux';
38
    protected string $basePath = 'design/';
39
    protected string $relativeFilePath = '';
40
    protected string $providerClassName = Provider::class;
41

42
    /**
43
     * Constructs a Fluid file-based content type definition
44
     *
45
     * Can be used to construct definitions based on template files
46
     * which contain Flux form definitions and supports sub-folders
47
     * for template files by specifying $relativeFilePath as a path
48
     * inside a folder relative to the $basePath.
49
     *
50
     * @param string $extensionIdentity The VendorName.ExtensionName identity of the extension that contains the file
51
     * @param string $basePath Absolute path, or EXT:... path to location of template file
52
     * @param string $relativeFilePath Path of file relative to $basePath, without leading slash
53
     * @param string $providerClassName Class name of a Flux ProviderInterface implementation that handles the CType
54
     */
55
    public function __construct(
56
        string $extensionIdentity,
57
        string $basePath,
58
        string $relativeFilePath,
59
        string $providerClassName = Provider::class
60
    ) {
61
        $this->extensionIdentity = $extensionIdentity;
8✔
62
        $this->basePath = static::determineAbsolutePathForFilename($basePath);
8✔
63
        $this->relativeFilePath = $relativeFilePath;
8✔
64
        $this->providerClassName = $providerClassName;
8✔
65
    }
66

67
    /**
68
     * @return iterable|DropInContentTypeDefinition[]
69
     */
70
    public static function fetchContentTypes(): iterable
71
    {
72
        if (!ExtensionConfigurationUtility::getOption(ExtensionOption::OPTION_PLUG_AND_PLAY)) {
16✔
73
            // Do not return or auto-create any plug and play templates if the extension config option is disabled.
74
            // Option default value is ENABLED (hence null coalesce to TRUE if not defined)
75
            return [];
4✔
76
        }
77
        // Steps:
78
        // 1) auto-create if missing, the required file structure and dummy files
79
        // 2) iterate all content types found in the file structure
80
        $plugAndPlayDirectory = ExtensionConfigurationUtility::getOption(
12✔
81
            ExtensionOption::OPTION_PLUG_AND_PLAY_DIRECTORY
12✔
82
        );
12✔
83
        if (!is_scalar($plugAndPlayDirectory)) {
12✔
84
            return [];
4✔
85
        }
86
        $basePath = trim((string) $plugAndPlayDirectory, '/.');
8✔
87
        if (empty($basePath)) {
8✔
88
            return [];
×
89
        }
90
        $basePath = static::determineAbsolutePathForFilename($basePath) . '/';
8✔
91
        static::initializeDropInFileSystemStructure($basePath);
8✔
92

93
        $contentTypesPath = $basePath . static::TEMPLATES_DIRECTORY . static::CONTENT_DIRECTORY;
8✔
94
        /** @var Finder $finder */
95
        $finder = GeneralUtility::makeInstance(Finder::class);
8✔
96
        try {
97
            /** @var \SplFileInfo[] $files */
98
            $files = $finder->in($contentTypesPath)->name(static::TEMPLATES_PATTERN)->sortByName();
8✔
99
        } catch (DirectoryNotFoundException $exception) {
4✔
100
            return [];
4✔
101
        }
102
        $types = [];
4✔
103
        $basePathLength = strlen($contentTypesPath);
4✔
104
        foreach ($files as $file) {
4✔
105
            $templateFile = $file->getPath() . '/' . $file->getFilename();
4✔
106
            // May cause some files to be ignored if the files are either symlinked or the base path was not possible
107
            // to resolve correctly. This can happen if for some reason, ENV is configured with a public path that is
108
            // not within the project path, is is configured as an absolute path (which technically isn't correct).
109
            // We ignore this case instead of throwing an exception - essentially disabling drop-in templates on systems
110
            // which contain an unexpected public path.
111
            if (strlen($templateFile) > $basePathLength
4✔
112
                && substr_compare($basePath, $templateFile, 0, $basePathLength)
4✔
113
            ) {
114
                $relativeTemplatePath = substr($templateFile, $basePathLength);
4✔
115
                $contentType = new DropInContentTypeDefinition(
4✔
116
                    'FluidTYPO3.Flux',
4✔
117
                    $contentTypesPath,
4✔
118
                    $relativeTemplatePath
4✔
119
                );
4✔
120
                $types[$contentType->getContentTypeName()] = $contentType;
4✔
121
            }
122
        }
123
        return $types;
4✔
124
    }
125

126
    public function getIconReference(): string
127
    {
128
        return '';
4✔
129
    }
130

131
    public function getProviderClassName(): ?string
132
    {
133
        return $this->providerClassName;
4✔
134
    }
135

136
    protected static function initializeDropInFileSystemStructure(string $basePath): void
137
    {
138
        if (!file_exists($basePath)) {
8✔
139
            static::createDir($basePath . static::PARTIALS_DIRECTORY);
4✔
140
            static::createDir(
4✔
141
                $basePath . static::LAYOUTS_DIRECTORY,
4✔
142
                ExtensionManagementUtility::extPath('flux', 'Resources/Private/Layouts/Default.html')
4✔
143
            );
4✔
144
            static::createDir(
4✔
145
                $basePath . static::TEMPLATES_DIRECTORY . static::CONTENT_DIRECTORY,
4✔
146
                ExtensionManagementUtility::extPath('flux', 'Resources/Private/Skeletons/Content/Standard.html')
4✔
147
            );
4✔
148
            static::createDir(
4✔
149
                $basePath . static::TEMPLATES_DIRECTORY . static::PAGE_DIRECTORY,
4✔
150
                ExtensionManagementUtility::extPath('flux', 'Resources/Private/Skeletons/Page/Standard.html')
4✔
151
            );
4✔
152
        }
153
    }
154

155
    protected static function createDir(string $directory, ?string $sourceFile = null): void
156
    {
157
        mkdir($directory, 0775, true);
4✔
158
        if ($sourceFile) {
4✔
159
            copy(
4✔
160
                $sourceFile,
4✔
161
                $directory . pathinfo($sourceFile, PATHINFO_BASENAME)
4✔
162
            );
4✔
163
        }
164
    }
165

166
    protected static function determineAbsolutePathForFilename(string $filename): string
167
    {
168
        if (strpos($filename, '://') !== false) {
12✔
169
            return $filename;
8✔
170
        }
171
        if (strpos($filename, '/') === 0) {
4✔
172
            return $filename;
4✔
173
        }
174
        return Environment::getPublicPath() . '/' . $filename;
×
175
    }
176
}
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