diff --git a/Classes/Content/ContentTypeManager.php b/Classes/Content/ContentTypeManager.php
index 39dd8f15f..bf19e9c36 100644
--- a/Classes/Content/ContentTypeManager.php
+++ b/Classes/Content/ContentTypeManager.php
@@ -83,7 +83,11 @@ public function registerTypeDefinition(ContentTypeDefinitionInterface $typeDefin
public function determineContentTypeForTypeString(string $contentTypeName): ?ContentTypeDefinitionInterface
{
- return $this->types[$contentTypeName] ?? ($this->types[$contentTypeName] = $this->loadSingleDefinitionFromCache($contentTypeName));
+ $definition = $this->loadSingleDefinitionFromCache($contentTypeName);
+ if ($definition === null) {
+ return null;
+ }
+ return $this->types[$contentTypeName] ?? ($this->types[$contentTypeName] = $definition);
}
public function determineContentTypeForRecord(array $record): ?ContentTypeDefinitionInterface
diff --git a/Classes/Content/RuntimeDefinedContentProvider.php b/Classes/Content/RuntimeDefinedContentProvider.php
index db2437fe6..a5a85fc17 100644
--- a/Classes/Content/RuntimeDefinedContentProvider.php
+++ b/Classes/Content/RuntimeDefinedContentProvider.php
@@ -77,7 +77,7 @@ public function trigger(array $row, $table, $field, $extensionKey = null)
public function getControllerExtensionKeyFromRecord(array $row)
{
- return ExtensionNamingUtility::getExtensionKey($this->getExtensionKey($row));
+ return ExtensionNamingUtility::getExtensionKey((string) $this->getExtensionKey($row));
}
public function getControllerActionFromRecord(array $row)
@@ -129,7 +129,7 @@ protected function getContentTypeDefinition(array $row): FluidRenderingContentTy
'Content type definition for %s must implement interface %s, class %s does not.',
$row['CType'],
FluidRenderingContentTypeDefinitionInterface::class,
- get_class($definition)
+ $definition !== null ? get_class($definition) : '(unknown)'
),
1556109085
);
diff --git a/Classes/Content/TypeDefinition/FluidFileBased/FluidFileBasedContentTypeDefinition.php b/Classes/Content/TypeDefinition/FluidFileBased/FluidFileBasedContentTypeDefinition.php
index 22e18d928..4638060db 100644
--- a/Classes/Content/TypeDefinition/FluidFileBased/FluidFileBasedContentTypeDefinition.php
+++ b/Classes/Content/TypeDefinition/FluidFileBased/FluidFileBasedContentTypeDefinition.php
@@ -77,11 +77,18 @@ public function getForm(array $record = []): Form
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** @var ProviderResolver $providerResolver */
$providerResolver = $objectManager->get(ProviderResolver::class);
- return $providerResolver->resolvePrimaryConfigurationProvider(
+ $provider = $providerResolver->resolvePrimaryConfigurationProvider(
'tt_content',
'pi_flexform',
$record
- )->getForm($record);
+ );
+ /** @var Form $defaultForm */
+ $defaultForm = Form::create();
+
+ if ($provider === null) {
+ return $defaultForm;
+ }
+ return $provider->getForm($record) ?? $defaultForm;
}
public function getGrid(array $record = []): Form\Container\Grid
@@ -90,11 +97,15 @@ public function getGrid(array $record = []): Form\Container\Grid
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** @var ProviderResolver $providerResolver */
$providerResolver = $objectManager->get(ProviderResolver::class);
- return $providerResolver->resolvePrimaryConfigurationProvider(
+ $provider = $providerResolver->resolvePrimaryConfigurationProvider(
'tt_content',
'pi_flexform',
$record
- )->getGrid($record);
+ );
+ if ($provider === null) {
+ return Form\Container\Grid::create();
+ }
+ return $provider->getGrid($record);
}
public static function fetchContentTypes(): iterable
diff --git a/Classes/Content/TypeDefinition/RecordBased/RecordBasedContentGridProvider.php b/Classes/Content/TypeDefinition/RecordBased/RecordBasedContentGridProvider.php
index f0f19a13d..485693d64 100644
--- a/Classes/Content/TypeDefinition/RecordBased/RecordBasedContentGridProvider.php
+++ b/Classes/Content/TypeDefinition/RecordBased/RecordBasedContentGridProvider.php
@@ -10,6 +10,7 @@
use FluidTYPO3\Flux\Content\ContentGridForm;
use FluidTYPO3\Flux\Content\ContentTypeManager;
+use FluidTYPO3\Flux\Content\TypeDefinition\ContentTypeDefinitionInterface;
use FluidTYPO3\Flux\Form\Container\Grid;
use FluidTYPO3\Flux\Provider\AbstractProvider;
use FluidTYPO3\Flux\Provider\Interfaces\GridProviderInterface;
@@ -91,6 +92,10 @@ public function getForm(array $row)
*/
public function getGrid(array $row)
{
- return $this->contentTypeDefinitions->determineContentTypeForRecord($row)->getGrid() ?? parent::getGrid($row);
+ $contentTypeDefinition = $this->contentTypeDefinitions->determineContentTypeForRecord($row);
+ if (!($contentTypeDefinition instanceof ContentTypeDefinitionInterface)) {
+ return parent::getGrid($row);
+ }
+ return $contentTypeDefinition->getGrid() ?? parent::getGrid($row);
}
}
diff --git a/Classes/Content/TypeDefinition/RecordBased/RecordBasedContentTypeDefinition.php b/Classes/Content/TypeDefinition/RecordBased/RecordBasedContentTypeDefinition.php
index ee9553761..29c865c6d 100644
--- a/Classes/Content/TypeDefinition/RecordBased/RecordBasedContentTypeDefinition.php
+++ b/Classes/Content/TypeDefinition/RecordBased/RecordBasedContentTypeDefinition.php
@@ -245,6 +245,9 @@ public function getTemplateSource(): string
$columnTemplateChunk = '' . PHP_EOL;
$grid = $this->getGrid();
+ if (!($grid instanceof Grid)) {
+ return '';
+ }
$template = '
' . PHP_EOL;
foreach ($grid->getRows() as $row) {
$template .= '
' . PHP_EOL;
diff --git a/Classes/Controller/AbstractFluxController.php b/Classes/Controller/AbstractFluxController.php
index d1f648c01..62420ee11 100644
--- a/Classes/Controller/AbstractFluxController.php
+++ b/Classes/Controller/AbstractFluxController.php
@@ -8,6 +8,8 @@
* LICENSE.md file that was distributed with this source code.
*/
+use FluidTYPO3\Flux\Form;
+use FluidTYPO3\Flux\Form\FormInterface;
use FluidTYPO3\Flux\Hooks\HookHandler;
use FluidTYPO3\Flux\Integration\NormalizedData\DataAccessTrait;
use FluidTYPO3\Flux\Provider\Interfaces\ControllerProviderInterface;
@@ -28,6 +30,7 @@
use TYPO3\CMS\Extbase\Mvc\Response;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Fluid\View\TemplatePaths;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
/**
@@ -164,16 +167,16 @@ protected function initializeOverriddenSettings()
protected function initializeProvider()
{
$row = $this->getRecord();
- $table = $this->getFluxTableName();
+ $table = (string) $this->getFluxTableName();
$field = $this->getFluxRecordField();
- $this->provider = $this->configurationService->resolvePrimaryConfigurationProvider(
+ $provider = $this->configurationService->resolvePrimaryConfigurationProvider(
$table,
$field,
$row,
null,
ControllerProviderInterface::class
);
- if (!$this->provider) {
+ if ($provider === null) {
throw new \RuntimeException(
'Unable to resolve a ConfigurationProvider, but controller indicates it is a Flux-enabled ' .
'Controller - this is a grave error and indicates that EXT: ' . $this->extensionName . ' itself is ' .
@@ -182,6 +185,7 @@ protected function initializeProvider()
1377458581
);
}
+ $this->provider = $provider;
}
/**
@@ -354,6 +358,7 @@ protected function performSubRendering($extensionName, $controllerName, $actionN
$shouldRelay = $this->hasSubControllerActionOnForeignController($extensionName, $controllerName, $actionName);
$foreignControllerClass = null;
+ $content = null;
if (!$shouldRelay) {
if ($this->provider instanceof FluidProviderInterface) {
$templatePathAndFilename = $this->provider->getTemplatePathAndFilename($this->getRecord());
@@ -385,7 +390,7 @@ protected function performSubRendering($extensionName, $controllerName, $actionN
);
$content = $this->callSubControllerAction(
$extensionName,
- $foreignControllerClass,
+ $foreignControllerClass ?? static::class,
$actionName,
$pluginSignature
);
@@ -512,7 +517,7 @@ protected function getData()
}
/**
- * @return string
+ * @return string|null
*/
protected function getFluxRecordField()
{
@@ -520,7 +525,7 @@ protected function getFluxRecordField()
}
/**
- * @return string
+ * @return string|null
*/
protected function getFluxTableName()
{
@@ -532,7 +537,11 @@ protected function getFluxTableName()
*/
public function getRecord()
{
- return $this->configurationManager->getContentObject()->data;
+ $contentObject = $this->configurationManager->getContentObject();
+ if ($contentObject === null) {
+ throw new \UnexpectedValueException("Record of table " . $this->getFluxTableName() . ' not found', 1666538343);
+ }
+ return $contentObject->data;
}
/**
@@ -541,10 +550,14 @@ public function getRecord()
public function outletAction()
{
$record = $this->getRecord();
+ $form = $this->provider->getForm($record);
$input = $this->request->getArguments();
$targetConfiguration = $this->request->getInternalArguments()['__outlet'];
- if ($this->provider->getTableName($record) !== $targetConfiguration['table']
- && $record['uid'] !== (integer) $targetConfiguration['recordUid']
+ if ($form === null
+ ||
+ ($this->provider->getTableName($record) !== $targetConfiguration['table']
+ && $record['uid'] !== (integer) $targetConfiguration['recordUid']
+ )
) {
// This instance does not match the instance that rendered the form. Forward the request
// to the default "render" action.
@@ -552,7 +565,8 @@ public function outletAction()
}
$input['settings'] = $this->settings;
try {
- $outlet = $this->provider->getForm($record)->getOutlet();
+ /** @var Form $form */
+ $outlet = $form->getOutlet();
$outlet->setView($this->view);
$outlet->fill($input);
if (!$outlet->isValid()) {
diff --git a/Classes/Controller/PageController.php b/Classes/Controller/PageController.php
index 1fea49d5a..42aa295bb 100644
--- a/Classes/Controller/PageController.php
+++ b/Classes/Controller/PageController.php
@@ -8,6 +8,7 @@
* LICENSE.md file that was distributed with this source code.
*/
+use FluidTYPO3\Flux\Provider\Interfaces\BasicProviderInterface;
use FluidTYPO3\Flux\Service\FluxService;
use FluidTYPO3\Flux\Service\PageService;
use TYPO3\CMS\Extbase\Mvc\Web\Response;
@@ -69,7 +70,12 @@ public function injectPageConfigurationService(FluxService $pageConfigurationSer
*/
protected function initializeProvider()
{
- $this->provider = $this->pageConfigurationService->resolvePageProvider($this->getRecord());
+ $record = $this->getRecord();
+ if ($record !== null) {
+ $provider = $this->pageConfigurationService->resolvePageProvider($record);
+ if ($provider instanceof BasicProviderInterface)
+ $this->provider = $provider;
+ }
}
/**
diff --git a/Classes/Form.php b/Classes/Form.php
index 035911f85..5fc9f7d04 100644
--- a/Classes/Form.php
+++ b/Classes/Form.php
@@ -103,7 +103,7 @@ public function initializeObject()
/**
* @param array $settings
- * @return FormInterface
+ * @return static
*/
public static function create(array $settings = [])
{
@@ -129,7 +129,7 @@ public function add(Form\FormInterface $child)
$this->children->rewind();
/** @var FormInterface|null $firstChild */
$firstChild = $this->children->count() > 0 ? $this->children->current() : null;
- if ($this->children->count() === 1 && $firstChild->getName() === 'options' && !$firstChild->hasChildren()) {
+ if ($firstChild instanceof FormInterface && $this->children->count() === 1 && $firstChild->getName() === 'options' && !$firstChild->hasChildren()) {
// Form has a single sheet, it's the default sheet and it has no fields. Replace it.
$this->children->detach($this->children->current());
}
diff --git a/Classes/Form/AbstractFormComponent.php b/Classes/Form/AbstractFormComponent.php
index 707f8a6e1..951e79503 100644
--- a/Classes/Form/AbstractFormComponent.php
+++ b/Classes/Form/AbstractFormComponent.php
@@ -46,7 +46,7 @@ abstract class AbstractFormComponent implements FormInterface
protected $enabled = true;
/**
- * @var string
+ * @var string|null
*/
protected $label = null;
@@ -170,7 +170,7 @@ public function createWizard($type, $name, $label = null)
* @param string $namespace
* @param string|class-string $type
* @param string $name
- * @param string|NULL $label
+ * @param string|null $label
* @return FormInterface
*/
public function createComponent($namespace, $type, $name, $label = null)
@@ -266,7 +266,7 @@ public function getExtensionName()
}
/**
- * @param string $label
+ * @param string|null $label
* @return $this
*/
public function setLabel($label)
@@ -304,7 +304,7 @@ public function getPath()
}
/**
- * @return string
+ * @return string|null
*/
public function getLabel()
{
@@ -334,7 +334,7 @@ protected function resolveLocalLanguageValueOfLabel($label, $path = null)
$relativeFilePath = $this->getLocalLanguageFileRelativePath();
$relativeFilePath = ltrim($relativeFilePath, '/');
$filePrefix = 'LLL:EXT:' . $extensionKey . '/' . $relativeFilePath;
- if (strpos($label ?? '', 'LLL:') === 0) {
+ if (strpos($label ?? '', 'LLL:') === 0 && strpos($label ?? '', ':') !== false) {
// Shorthand LLL:name.of.index reference, expand
list (, $labelIdentifier) = explode(':', $label, 2);
return $filePrefix . ':' . $labelIdentifier;
@@ -535,6 +535,12 @@ public function modify(array $structure)
unset($structure['options']);
}
foreach ($structure as $propertyName => $propertyValue) {
+ if ($propertyName === 'children') {
+ foreach ($propertyValue as $child) {
+ $this->add($child);
+ }
+ continue;
+ }
$setterMethodName = 'set' . ucfirst($propertyName);
if (true === method_exists($this, $setterMethodName)) {
ObjectAccess::setProperty($this, $propertyName, $propertyValue);
diff --git a/Classes/Form/AbstractFormContainer.php b/Classes/Form/AbstractFormContainer.php
index 95ae67486..95c16834b 100644
--- a/Classes/Form/AbstractFormContainer.php
+++ b/Classes/Form/AbstractFormContainer.php
@@ -148,7 +148,7 @@ public function getChildren()
}
/**
- * @return FormInterface|FALSE
+ * @return FormInterface|null
*/
public function last()
{
@@ -173,20 +173,21 @@ public function modify(array $structure)
{
if (isset($structure['fields']) || isset($structure['children'])) {
$data = isset($structure['children']) ? $structure['children'] : $structure['fields'];
- foreach ((array) $data as $index => $fieldData) {
- $fieldName = true === isset($fieldData['name']) ? $fieldData['name'] : $index;
+ foreach ((array) $data as $index => $childData) {
+ $childName = true === isset($childData['name']) ? $childData['name'] : $index;
// check if field already exists - if it does, modify it. If it does not, create it.
- if (true === $this->has($fieldName)) {
- /** @var FieldInterface|null $field */
- $field = $this->get($fieldName);
+ if (true === $this->has($childName)) {
+ /** @var FormInterface $child */
+ $child = $this->get($childName);
} else {
- /** @var class-string $fieldType */
- $fieldType = true === isset($fieldData['type']) ? $fieldData['type'] : 'None';
- /** @var FieldInterface|null $field */
- $field = $this->createField($fieldType, $fieldName);
+ /** @var class-string $type */
+ $type = true === isset($childData['type']) ? $childData['type'] : 'None';
+ /** @var FormInterface $child */
+ $child = $this->createField($type, $childName);
}
- $field->modify($fieldData);
+
+ $child->modify($childData);
}
unset($structure['children'], $structure['fields']);
}
diff --git a/Classes/Form/AbstractInlineFormField.php b/Classes/Form/AbstractInlineFormField.php
index 5914c3ab9..34adbbb63 100644
--- a/Classes/Form/AbstractInlineFormField.php
+++ b/Classes/Form/AbstractInlineFormField.php
@@ -470,7 +470,7 @@ public function getOverrideChildTca()
*/
public function setForeignTypes($foreignTypes)
{
- $this->foreignTypes = true === is_array($foreignTypes) ? $foreignTypes : null;
+ $this->foreignTypes = $foreignTypes ?? [];
return $this;
}
diff --git a/Classes/Form/AbstractMultiValueFormField.php b/Classes/Form/AbstractMultiValueFormField.php
index 1edf57a0e..624a5d4ff 100644
--- a/Classes/Form/AbstractMultiValueFormField.php
+++ b/Classes/Form/AbstractMultiValueFormField.php
@@ -225,7 +225,7 @@ public function getSelectedListStyle()
}
/**
- * @return string
+ * @return string|null
*/
public function getRenderType()
{
diff --git a/Classes/Form/Container/Grid.php b/Classes/Form/Container/Grid.php
index a55810475..c5f36760f 100644
--- a/Classes/Form/Container/Grid.php
+++ b/Classes/Form/Container/Grid.php
@@ -154,13 +154,13 @@ public function buildBackendLayout(int $parentRecordUid): BackendLayout
$typoScriptString = '';
$root = $this->getRoot();
- $label = $root->getLabel();
+ $label = (string) $root->getLabel();
foreach ($this->flattenSetup($configuration, 'backend_layout.') as $name => $value) {
$typoScriptString .= $name . ' = ' . $value . LF;
}
return new BackendLayout(
- $this->getRoot()->getName(),
- LocalizationUtility::translate($label)
+ (string) $this->getRoot()->getName(),
+ (string) LocalizationUtility::translate($label)
? $label
: 'LLL:EXT:flux/Resources/Private/Language/locallang.xlf:flux.grid.grids.grid',
$typoScriptString
diff --git a/Classes/Form/Container/Sheet.php b/Classes/Form/Container/Sheet.php
index 3594e33bf..5cffd72f5 100644
--- a/Classes/Form/Container/Sheet.php
+++ b/Classes/Form/Container/Sheet.php
@@ -41,7 +41,7 @@ public function setShortDescription($shortDescription)
}
/**
- * @return string
+ * @return string|null
*/
public function getShortDescription()
{
@@ -59,7 +59,7 @@ public function setDescription($description)
}
/**
- * @return string
+ * @return string|null
*/
public function getDescription()
{
diff --git a/Classes/Form/Conversion/FormToFluidTemplateConverter.php b/Classes/Form/Conversion/FormToFluidTemplateConverter.php
index 6181dad48..d2fc3b690 100644
--- a/Classes/Form/Conversion/FormToFluidTemplateConverter.php
+++ b/Classes/Form/Conversion/FormToFluidTemplateConverter.php
@@ -21,7 +21,7 @@ class FormToFluidTemplateConverter implements FormConverterInterface
* @param array $configuration
* @return string
*/
- public function convertFormAndGrid(Form $form, Form\Container\Grid $grid, array $configuration)
+ public function convertFormAndGrid(Form $form, ?Form\Container\Grid $grid, array $configuration)
{
$renderingTemplateChunk = $configuration[static::OPTION_TEMPLATE_SOURCE] ?? 'Hello world';
@@ -44,7 +44,7 @@ public function convertFormAndGrid(Form $form, Form\Container\Grid $grid, array
TEMPLATE;
$formFieldsChunk = $this->renderSheetsAndFields($form);
- $gridChunk = $this->renderGrid($grid);
+ $gridChunk = $grid !== null ? $this->renderGrid($grid) : '';
$source = sprintf($template, $form->getId(), $formFieldsChunk, $gridChunk, $renderingTemplateChunk);
diff --git a/Classes/Form/Field/ControllerActions.php b/Classes/Form/Field/ControllerActions.php
index 1d8b914b1..5dadfef84 100644
--- a/Classes/Form/Field/ControllerActions.php
+++ b/Classes/Form/Field/ControllerActions.php
@@ -18,7 +18,6 @@
*/
class ControllerActions extends Select
{
-
/**
* Name of the Extbase extension that contains the Controller
* to parse, ex. MyExtension. In vendor based extensions use
@@ -357,7 +356,7 @@ protected function buildExpectedAndExistingControllerClassName($controllerName)
/**
* @param string $controllerName
* @param string $actionName
- * @return string|NULL
+ * @return string
*/
protected function getLabelForControllerAction($controllerName, $actionName)
{
@@ -367,6 +366,9 @@ protected function getLabelForControllerAction($controllerName, $actionName)
$pluginName = $this->getPluginName();
$separator = $this->getSeparator();
$controllerClassName = $this->buildExpectedAndExistingControllerClassName($controllerName);
+ if ($controllerClassName === null) {
+ return 'INVALID: ' . $controllerName . '->' . $actionName;
+ }
$disableLocalLanguageLabels = $this->getDisableLocalLanguageLabels();
$labelPath = strtolower($pluginName . '.' . $controllerName . '.' . $actionName);
$hasLocalLanguageFile = file_exists(
diff --git a/Classes/Form/FormInterface.php b/Classes/Form/FormInterface.php
index cb5e780c4..dbddcead3 100644
--- a/Classes/Form/FormInterface.php
+++ b/Classes/Form/FormInterface.php
@@ -52,13 +52,13 @@ public function getEnabled();
public function setEnabled($enabled);
/**
- * @param string $label
+ * @param string|null $label
* @return $this
*/
public function setLabel($label);
/**
- * @return string
+ * @return string|null
*/
public function getLabel();
diff --git a/Classes/Integration/ContentTypeBuilder.php b/Classes/Integration/ContentTypeBuilder.php
index 608f280e9..7bc1eddc7 100644
--- a/Classes/Integration/ContentTypeBuilder.php
+++ b/Classes/Integration/ContentTypeBuilder.php
@@ -45,7 +45,7 @@ class ContentTypeBuilder
/**
* @param string $providerExtensionName
* @param string $templateFilename
- * @param class-string|null $providerClassName
+ * @param class-string $providerClassName
* @param string|null $contentType
* @param string $defaultControllerExtensionName
* @param string|null $controllerActionName
@@ -54,7 +54,7 @@ class ContentTypeBuilder
public function configureContentTypeFromTemplateFile(
string $providerExtensionName,
string $templateFilename,
- ?string $providerClassName = Provider::class,
+ string $providerClassName = Provider::class,
?string $contentType = null,
string $defaultControllerExtensionName = 'FluidTYPO3.Flux',
?string $controllerActionName = null
@@ -77,7 +77,7 @@ public function configureContentTypeFromTemplateFile(
$controllerClassName = str_replace('.', '\\', $defaultControllerExtensionName) . '\\Controller\\' . $controllerName . 'Controller';
$localControllerClassName = str_replace('.', '\\', $providerExtensionName) . '\\Controller\\' . $controllerName . 'Controller';
$extensionSignature = str_replace('_', '', ExtensionNamingUtility::getExtensionKey($providerExtensionName));
- $fullContentType = $contentType ?: $extensionSignature . '_' . strtolower($pluginName);
+ $fullContentType = $contentType ?: $extensionSignature . '_' . strtolower((string) $pluginName);
if (!$this->validateContentController($localControllerClassName)) {
class_alias($controllerClassName, $localControllerClassName);
}
@@ -174,7 +174,7 @@ public function registerContentType(
// errors use the most base Exception class in PHP. So instead we check for a
// specific dispatcher in the stack trace and re-throw if not matched.
$pitcher = $error->getTrace()[0] ?? false;
- if ($pitcher && ($pitcher['class'] ?? '') !== 'SplObjectStorage' && ($pitcher['function'] ?? '') !== 'serialize') {
+ if ($pitcher && ($pitcher['class'] ?? '') !== 'SplObjectStorage' && $pitcher['function'] !== 'serialize') {
throw $error;
}
}
@@ -230,7 +230,7 @@ protected function addPageTsConfig(Form $form, string $contentType): void
$formId = $form->getId() ?: $contentType;
$group = $form->getOption(Form::OPTION_GROUP);
$groupName = $this->sanitizeString($group ?? 'fluxContent');
- $extensionName = $form->getExtensionName();
+ $extensionName = $form->getExtensionName() ?? 'FluidTYPO3.Flux';
$extensionKey = ExtensionNamingUtility::getExtensionKey($extensionName);
$labelSubReference = 'flux.newContentWizard.' . $groupName;
@@ -268,7 +268,7 @@ protected function addPageTsConfig(Form $form, string $contentType): void
protected function sanitizeString(string $string): string
{
$pattern = '/([^a-z0-9\-]){1,}/i';
- $replaced = preg_replace($pattern, '_', $string);
+ $replaced = (string) preg_replace($pattern, '_', $string);
$replaced = trim($replaced, '_');
return empty($replaced) ? md5($string) : $replaced;
}
@@ -298,7 +298,7 @@ protected function registerExtbasePluginForForm(string $providerExtensionName, s
ExtensionUtility::registerPlugin(
$this->getExtensionIdentityForPluginRegistration($providerExtensionName),
$this->getPluginNamePartFromContentType($contentType),
- $form->getLabel(),
+ (string) $form->getLabel(),
MiscellaneousUtility::getIconForTemplate($form),
$providerExtensionName
);
diff --git a/Classes/Integration/FormEngine/SiteConfigurationProviderItems.php b/Classes/Integration/FormEngine/SiteConfigurationProviderItems.php
index a3ba25635..ed6bddf17 100644
--- a/Classes/Integration/FormEngine/SiteConfigurationProviderItems.php
+++ b/Classes/Integration/FormEngine/SiteConfigurationProviderItems.php
@@ -34,7 +34,7 @@ public function processPageTemplateItems(array $tca, TcaSelectItems $bar): array
foreach ($pageService->getAvailablePageTemplateFiles() as $extensionName => $templateGroup) {
foreach ($templateGroup as $form) {
$templateFilename = $form->getOption(Form::OPTION_TEMPLATEFILE);
- $label = $form->getLabel();
+ $label = (string) $form->getLabel();
$identity = $extensionName . '->' . lcfirst(pathinfo($templateFilename, PATHINFO_FILENAME));
try {
$label = LocalizationUtility::translate($label) ?: $identity;
diff --git a/Classes/Integration/HookSubscribers/DataHandlerSubscriber.php b/Classes/Integration/HookSubscribers/DataHandlerSubscriber.php
index cb9384c77..311b5c8cd 100644
--- a/Classes/Integration/HookSubscribers/DataHandlerSubscriber.php
+++ b/Classes/Integration/HookSubscribers/DataHandlerSubscriber.php
@@ -79,16 +79,18 @@ public function processDatamap_afterDatabaseOperations($command, $table, $id, $f
if (!empty($fieldArray['l18n_parent'])) {
// Command was "localize", read colPos value from the translation parent and use directly
- $newColumnPosition = $this->getSingleRecordWithoutRestrictions($table, $fieldArray['l18n_parent'], 'colPos')['colPos'];
+ $newColumnPosition = $this->getSingleRecordWithoutRestrictions($table, $fieldArray['l18n_parent'], 'colPos')['colPos'] ?? null;
} elseif (isset(static::$copiedRecords[$originalParentUid])) {
// The parent of the original version of the record that was copied, was also copied in the same request;
// this means the record that was copied, was copied as a recursion operation. Look up the most recent copy
// of the original record's parent and create a new column position number based on the new parent.
$newParentRecord = $this->getMostRecentCopyOfRecord($originalParentUid);
- $newColumnPosition = ColumnNumberUtility::calculateColumnNumberForParentAndColumn(
- $newParentRecord['uid'],
- ColumnNumberUtility::calculateLocalColumnNumber($originalRecord['colPos'])
- );
+ if ($newParentRecord !== null) {
+ $newColumnPosition = ColumnNumberUtility::calculateColumnNumberForParentAndColumn(
+ $newParentRecord['uid'],
+ ColumnNumberUtility::calculateLocalColumnNumber($originalRecord['colPos'])
+ );
+ }
} elseif (($fieldArray['colPos'] ?? 0) >= ColumnNumberUtility::MULTIPLIER) {
// Record is a child record, the updated field array still indicates it is a child (was not pasted outside
// of parent, rather, parent was pasted somewhere else).
@@ -96,14 +98,16 @@ public function processDatamap_afterDatabaseOperations($command, $table, $id, $f
// right parent for the language and update the column position accordingly.
$originalParentUid = ColumnNumberUtility::calculateParentUid($fieldArray['colPos']);
$originalParent = $this->getSingleRecordWithoutRestrictions($table, $originalParentUid, 'sys_language_uid');
- if ($originalParent['sys_language_uid'] !== $fieldArray['sys_language_uid']) {
+ if ($originalParent !== null && $originalParent['sys_language_uid'] !== $fieldArray['sys_language_uid']) {
// copyToLanguage case. Resolve the most recent translated version of the parent record in language of
// child record, and calculate the new column position number based on it.
$newParentRecord = $this->getTranslatedVersionOfParentInLanguageOnPage((int) $fieldArray['sys_language_uid'], (int) $fieldArray['pid'], (int) $originalParentUid);
- $newColumnPosition = ColumnNumberUtility::calculateColumnNumberForParentAndColumn(
- $newParentRecord['uid'],
- ColumnNumberUtility::calculateLocalColumnNumber($fieldArray['colPos'])
- );
+ if ($newParentRecord !== null) {
+ $newColumnPosition = ColumnNumberUtility::calculateColumnNumberForParentAndColumn(
+ $newParentRecord['uid'],
+ ColumnNumberUtility::calculateLocalColumnNumber($fieldArray['colPos'])
+ );
+ }
}
}
@@ -165,7 +169,7 @@ public function processDatamap_preProcessFieldArray(array &$fieldArray, $table,
// TODO: remove when expected solution, the inclusion of colPos in $fieldArray, is merged and released in TYPO3
if (!array_key_exists('colPos', $fieldArray)) {
$record = $this->getSingleRecordWithoutRestrictions($table, (int) $id, 'pid, colPos, l18n_parent');
- $uidInDefaultLanguage = $record['l18n_parent'];
+ $uidInDefaultLanguage = $record['l18n_parent'] ?? null;
if ($uidInDefaultLanguage && isset($dataHandler->datamap[$table][$uidInDefaultLanguage]['colPos'])) {
$fieldArray['colPos'] = (integer) $dataHandler->datamap[$table][$uidInDefaultLanguage]['colPos'];
}
diff --git a/Classes/Integration/NormalizedData/Converter/InlineRecordDataConverter.php b/Classes/Integration/NormalizedData/Converter/InlineRecordDataConverter.php
index e48ddcf56..976cb236e 100644
--- a/Classes/Integration/NormalizedData/Converter/InlineRecordDataConverter.php
+++ b/Classes/Integration/NormalizedData/Converter/InlineRecordDataConverter.php
@@ -149,6 +149,9 @@ protected function assertArrayHasKey(array $array, string $path): bool
{
$segments = GeneralUtility::trimExplode('.', $path);
$lastSegment = array_pop($segments);
+ if ($lastSegment === null) {
+ return false;
+ }
foreach ($segments as $segment) {
$array = $array[$segment];
}
diff --git a/Classes/Integration/NormalizedData/DataAccessTrait.php b/Classes/Integration/NormalizedData/DataAccessTrait.php
index bca37aef9..fe1d9ec58 100644
--- a/Classes/Integration/NormalizedData/DataAccessTrait.php
+++ b/Classes/Integration/NormalizedData/DataAccessTrait.php
@@ -34,6 +34,9 @@ public function injectConfigurationManager(ConfigurationManagerInterface $config
/** @var ObjectManagerInterface $objectManager */
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$contentObject = $this->configurationManager->getContentObject();
+ if ($contentObject === null) {
+ throw new \UnexpectedValueException("Record of table " . $this->getFluxTableName() . ' not found', 1666538343);
+ }
$table = $this->fluxTableName ?? $contentObject->getCurrentTable();
$field = $this->fluxRecordField ?? 'pi_flexform';
$record = $contentObject->data;
diff --git a/Classes/Outlet/Pipe/TypeConverterPipe.php b/Classes/Outlet/Pipe/TypeConverterPipe.php
index 9990b989d..07bfed2b1 100644
--- a/Classes/Outlet/Pipe/TypeConverterPipe.php
+++ b/Classes/Outlet/Pipe/TypeConverterPipe.php
@@ -90,7 +90,7 @@ public function getTargetType()
return $this->targetType;
}
- public function getPropertyName(): string
+ public function getPropertyName(): ?string
{
return $this->propertyName;
}
diff --git a/Classes/Provider/AbstractProvider.php b/Classes/Provider/AbstractProvider.php
index 07bf78e26..2b3316f6c 100644
--- a/Classes/Provider/AbstractProvider.php
+++ b/Classes/Provider/AbstractProvider.php
@@ -59,26 +59,26 @@ class AbstractProvider implements ProviderInterface
/**
* Fill with the name of the DB table which should trigger this Provider.
*
- * @var string
+ * @var string|null
*/
protected $tableName = null;
/**
* Fill with the "list_type" value that should trigger this Provider.
*
- * @var string
+ * @var string|null
*/
protected $listType = null;
/**
* Fill with the "CType" value that should trigger this Provider.
*
- * @var string
+ * @var string|null
*/
protected $contentObjectType = null;
/**
- * @var string
+ * @var string|null
*/
protected $parentFieldName = null;
@@ -237,7 +237,7 @@ public function trigger(array $row, $table, $field, $extensionKey = null)
* reading from template or overriding the getForm() method.
*
* @param array $row
- * @return string
+ * @return class-string|null
*/
protected function resolveFormClassName(array $row)
{
@@ -255,7 +255,7 @@ protected function resolveFormClassName(array $row)
*/
protected function getViewVariables(array $row)
{
- $extensionKey = $this->getExtensionKey($row);
+ $extensionKey = (string) $this->getExtensionKey($row);
$fieldName = $this->getFieldName($row);
$variables = [
'record' => $row,
@@ -309,16 +309,22 @@ protected function createCustomFormInstance(array $row)
*/
public function getGrid(array $row)
{
+ if ($this->grid instanceof Grid) {
+ return $this->grid;
+ }
$form = $this->getForm($row);
if ($form) {
$container = $this->detectContentContainerParent($form);
if ($container) {
$values = $this->getFlexFormValues($row);
- $persistedObjects = array_column(
- ObjectAccess::getProperty($values, $container->getName()) ?? [],
- $container->getContentContainer()->getName()
- );
-
+ $contentContainer = $container->getContentContainer();
+ $persistedObjects = [];
+ if ($contentContainer instanceof Form\Container\SectionObject) {
+ $persistedObjects = array_column(
+ ObjectAccess::getProperty($values, (string) $container->getName()) ?? [],
+ (string) $contentContainer->getName()
+ );
+ }
// Determine the mode to render, then create an ad-hoc grid.
$grid = Grid::create();
@@ -347,7 +353,7 @@ public function getGrid(array $row)
return $grid;
}
}
- $grid = $this->grid ?? $this->extractConfiguration($row, 'grids')['grid'] ?? Grid::create();
+ $grid = $this->extractConfiguration($row, 'grids')['grid'] ?? Grid::create();
$grid->setExtensionName($grid->getExtensionName() ?: $this->getControllerExtensionKeyFromRecord($row));
return $grid;
}
@@ -431,7 +437,7 @@ public function setListType($listType)
}
/**
- * @return string
+ * @return string|null
*/
public function getListType()
{
@@ -440,6 +446,7 @@ public function getListType()
/**
* @param string $contentObjectType
+ * @return void
*/
public function setContentObjectType($contentObjectType)
{
@@ -447,7 +454,7 @@ public function setContentObjectType($contentObjectType)
}
/**
- * @return string
+ * @return string|null
*/
public function getContentObjectType()
{
@@ -465,7 +472,7 @@ public function getFieldName(array $row)
/**
* @param array $row
- * @return string
+ * @return string|null
*/
public function getParentFieldName(array $row)
{
@@ -475,7 +482,7 @@ public function getParentFieldName(array $row)
/**
* @param array $row The record row which triggered processing
- * @return string|NULL
+ * @return string|null
*/
public function getTableName(array $row)
{
@@ -489,7 +496,7 @@ public function getTableName(array $row)
*/
public function getTemplatePathAndFilename(array $row)
{
- $templatePathAndFilename = $this->templatePathAndFilename;
+ $templatePathAndFilename = (string) $this->templatePathAndFilename;
if (!PathUtility::isAbsolutePath($templatePathAndFilename)) {
$templatePathAndFilename = GeneralUtility::getFileAbsFileName($templatePathAndFilename);
if (true === empty($templatePathAndFilename)) {
@@ -576,7 +583,7 @@ public function getTemplateVariables(array $row)
$variables['record'] = $row;
$variables['page'] = $this->getPageValues();
$variables['user'] = $GLOBALS['TSFE']->fe_user->user ?? [];
- if (file_exists($this->getTemplatePathAndFilename($row))) {
+ if (file_exists((string) $this->getTemplatePathAndFilename($row))) {
$variables['grid'] = $this->getGrid($row);
$variables['form'] = $this->getForm($row);
}
@@ -634,7 +641,10 @@ public function preProcessRecord(array &$row, $id, DataHandler $reference)
{
// TODO: move to single-fire implementation in TceMain (DataHandler)
$fieldName = $this->getFieldName($row);
- $tableName = $this->getTableName($row);
+ if ($fieldName === null) {
+ return;
+ }
+ $tableName = (string) $this->getTableName($row);
if (is_array($row[$fieldName]) && isset($row[$fieldName]['data']['options']['lDEF'])
&& is_array($row[$fieldName]['data']['options']['lDEF'])) {
foreach ($row[$fieldName]['data']['options']['lDEF'] as $key => $value) {
@@ -664,8 +674,9 @@ public function postProcessRecord($operation, $id, array &$row, DataHandler $ref
{
// TODO: move to single-fire implementation in TceMain (DataHandler)
if ('update' === $operation || 'new' === $operation) {
+ $tableName = (string) $this->getTableName($row);
$record = $reference->datamap[$this->tableName][$id];
- $stored = $this->recordService->getSingle($this->tableName, '*', $record['uid']) ?? $record;
+ $stored = $this->recordService->getSingle($tableName, '*', $record['uid']) ?? $record;
$fieldName = $this->getFieldName((array) $record);
$dontProcess = (
null === $fieldName
@@ -695,7 +706,7 @@ public function postProcessRecord($operation, $id, array &$row, DataHandler $ref
$row[$fieldName] = $stored[$fieldName];
$reference->datamap[$this->tableName][$id][$fieldName] = $row[$fieldName];
if ($stored['uid']) {
- $this->recordService->update($this->tableName, $stored);
+ $this->recordService->update($tableName, $stored);
}
}
}
@@ -717,7 +728,7 @@ public function postProcessDatabaseOperation($status, $id, &$row, DataHandler $r
// TODO: remove in Flux 10.0
// We dispatch the Outlet associated with the Form, triggering each defined
// Pipe inside the Outlet to "conduct" the data.
- $record = $this->recordService->getSingle($this->getTableName($row), '*', $id);
+ $record = $this->recordService->getSingle((string) $this->getTableName($row), '*', $id);
if (null !== $record) {
$form = $this->getForm($record);
if (true === $form instanceof Form\FormInterface) {
@@ -821,7 +832,7 @@ public function getViewForRecord(array $row, $viewClassName = TemplateView::clas
{
/** @var class-string $viewClassName */
- $controllerExtensionKey = $this->getControllerExtensionKeyFromRecord($row);
+ $controllerExtensionKey = $this->getControllerExtensionKeyFromRecord($row) ?? 'FluidTYPO3.Flux';
/** @var ObjectManagerInterface $objectManager */
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
@@ -847,7 +858,7 @@ public function getViewForRecord(array $row, $viewClassName = TemplateView::clas
$renderingContext = $objectManager->get(RenderingContext::class);
$renderingContext->setControllerContext($controllerContext);
$renderingContext->getTemplatePaths()->fillDefaultsByPackageName(ExtensionNamingUtility::getExtensionKey($controllerExtensionKey));
- $renderingContext->getTemplatePaths()->setTemplatePathAndFilename($this->getTemplatePathAndFilename($row));
+ $renderingContext->getTemplatePaths()->setTemplatePathAndFilename((string) $this->getTemplatePathAndFilename($row));
$renderingContext->setControllerName($this->getControllerNameFromRecord($row));
$renderingContext->setControllerAction($this->getControllerActionFromRecord($row));
/** @var T $view */
@@ -925,7 +936,7 @@ public function getControllerNameFromRecord(array $row)
* Stub: Get the extension key of the controller associated with $row
*
* @param array $row
- * @return string
+ * @return string|null
*/
public function getControllerExtensionKeyFromRecord(array $row)
{
@@ -940,7 +951,7 @@ public function getControllerExtensionKeyFromRecord(array $row)
*/
public function getControllerPackageNameFromRecord(array $row)
{
- $extensionKey = $this->getControllerExtensionKeyFromRecord($row);
+ $extensionKey = $this->getControllerExtensionKeyFromRecord($row) ?? 'FluidTYPO3.Flux';
$extensionName = ExtensionNamingUtility::getExtensionName($extensionKey);
$vendor = ExtensionNamingUtility::getVendorName($extensionKey);
return null !== $vendor ? $vendor . '.' . $extensionName : $extensionName;
@@ -1019,12 +1030,12 @@ public function setControllerAction($controllerAction)
}
/**
- * @param array|NULL $templateVariables
+ * @param array|null $templateVariables
* @return ProviderInterface
*/
public function setTemplateVariables($templateVariables)
{
- $this->templateVariables = $templateVariables;
+ $this->templateVariables = $templateVariables ?? [];
return $this;
}
@@ -1039,7 +1050,7 @@ public function setTemplatePathAndFilename($templatePathAndFilename)
}
/**
- * @param array|NULL $templatePaths
+ * @param array|null $templatePaths
* @return ProviderInterface
*/
public function setTemplatePaths($templatePaths)
@@ -1049,7 +1060,7 @@ public function setTemplatePaths($templatePaths)
}
/**
- * @param string|NULL $configurationSectionName
+ * @param string|null $configurationSectionName
* @return ProviderInterface
*/
public function setConfigurationSectionName($configurationSectionName)
diff --git a/Classes/Provider/Interfaces/FluidProviderInterface.php b/Classes/Provider/Interfaces/FluidProviderInterface.php
index 4ba7caed1..bf30b0878 100644
--- a/Classes/Provider/Interfaces/FluidProviderInterface.php
+++ b/Classes/Provider/Interfaces/FluidProviderInterface.php
@@ -21,7 +21,7 @@ interface FluidProviderInterface
* field and sheets configuration. EXT:myext... syntax allowed
*
* @param array $row The record which triggered the processing
- * @return string|NULL
+ * @return string|null
*/
public function getTemplatePathAndFilename(array $row);
@@ -30,7 +30,7 @@ public function getTemplatePathAndFilename(array $row);
* FlexForm configuration
*
* @param array $row The record which triggered the processing
- * @return array|NULL
+ * @return array
*/
public function getTemplateVariables(array $row);
diff --git a/Classes/Provider/Interfaces/RecordProviderInterface.php b/Classes/Provider/Interfaces/RecordProviderInterface.php
index e3ec60b8b..d3f8a86ff 100644
--- a/Classes/Provider/Interfaces/RecordProviderInterface.php
+++ b/Classes/Provider/Interfaces/RecordProviderInterface.php
@@ -26,8 +26,8 @@ interface RecordProviderInterface
*
* @param array $row
* @param string $table
- * @param string $field
- * @param string $extensionKey
+ * @param string|null $field
+ * @param string|null $extensionKey
* @return boolean
*/
public function trigger(array $row, $table, $field, $extensionKey = null);
diff --git a/Classes/Provider/PageLanguageOverlayProvider.php b/Classes/Provider/PageLanguageOverlayProvider.php
index 67542dab8..1e3d0d8d3 100644
--- a/Classes/Provider/PageLanguageOverlayProvider.php
+++ b/Classes/Provider/PageLanguageOverlayProvider.php
@@ -34,11 +34,17 @@ protected function loadRecordTreeFromDatabase($record)
$record[$parentFieldName] = $this->getParentFieldValue($record);
}
$pageRecord = $this->recordService->getSingle('pages', '*', $record['pid']);
+ if ($pageRecord === null) {
+ return [];
+ }
$records = [];
- while (0 < $pageRecord[$parentFieldName]) {
+ while ($parentFieldName !== null && $pageRecord !== null && 0 < ($pageRecord[$parentFieldName] ?? null)) {
$record = $this->recordService->get($this->tableName, '*', 'pid = ' . $pageRecord['pid']);
+ if ($record === null) {
+ break;
+ }
$parentFieldName = $this->getParentFieldName($record);
- array_push($records, $record);
+ $records[] = $record;
$pageRecord = $this->recordService->getSingle('pages', '*', $pageRecord['pid']);
}
$records = array_reverse($records);
diff --git a/Classes/Provider/PageProvider.php b/Classes/Provider/PageProvider.php
index c8f4e1d4b..d9d6a9eb4 100644
--- a/Classes/Provider/PageProvider.php
+++ b/Classes/Provider/PageProvider.php
@@ -142,7 +142,7 @@ public function getExtensionKey(array $row)
/**
* @param array $row
- * @return string
+ * @return string|null
*/
public function getTemplatePathAndFilename(array $row)
{
@@ -246,8 +246,8 @@ public function getFlexFormValuesSingle(array $row)
public function postProcessRecord($operation, $id, array &$row, DataHandler $reference, array $removals = [])
{
if ('update' === $operation) {
- $record = $this->recordService->getSingle($this->getTableName($row), '*', $id);
- if (!is_array($record)) {
+ $record = $this->recordService->getSingle((string) $this->getTableName($row), '*', $id);
+ if ($record === null) {
return;
}
if (isset($reference->datamap[$this->tableName][$id])) {
@@ -260,8 +260,8 @@ public function postProcessRecord($operation, $id, array &$row, DataHandler $ref
if ($form) {
$tableFieldName = $this->getFieldName($record);
foreach ($form->getFields() as $field) {
- $fieldName = $field->getName();
- $sheetName = $field->getParent()->getName();
+ $fieldName = (string) $field->getName();
+ $sheetName = (string) $field->getParent()->getName();
$inherit = (boolean) $field->getInherit();
$inheritEmpty = (boolean) $field->getInheritEmpty();
if (isset($record[$tableFieldName]['data']) && is_array($record[$tableFieldName]['data'])) {
@@ -315,7 +315,7 @@ protected function setDefaultValuesInFieldsWithInheritedValues(Form $form, array
{
$inheritedConfiguration = $this->getInheritedConfiguration($row);
foreach ($form->getFields() as $field) {
- $name = $field->getName();
+ $name = (string) $field->getName();
$inheritedValue = $this->getInheritedPropertyValueByDottedPath($inheritedConfiguration, $name);
if (null !== $inheritedValue && true === $field instanceof Form\FieldInterface) {
$field->setDefault($inheritedValue);
@@ -403,9 +403,9 @@ protected function getParentFieldValue(array $row)
{
$parentFieldName = $this->getParentFieldName($row);
if (null !== $parentFieldName && false === isset($row[$parentFieldName])) {
- $row = $this->recordService->getSingle($this->getTableName($row), '*', $row[$parentFieldName]);
+ $row = $this->recordService->getSingle((string) $this->getTableName($row), '*', $row[$parentFieldName]);
}
- return $row[$parentFieldName];
+ return $row[$parentFieldName] ?? null;
}
/**
diff --git a/Classes/Provider/SubPageLanguageOverlayProvider.php b/Classes/Provider/SubPageLanguageOverlayProvider.php
index ed7258598..58e7670fe 100644
--- a/Classes/Provider/SubPageLanguageOverlayProvider.php
+++ b/Classes/Provider/SubPageLanguageOverlayProvider.php
@@ -30,14 +30,17 @@ class SubPageLanguageOverlayProvider extends PageLanguageOverlayProvider impleme
/**
* @param array $row
- * @return string
+ * @return string|null
*/
public function getControllerActionReferenceFromRecord(array $row)
{
$pageRow = $this->recordService->getSingle('pages', '*', $row['pid']);
+ if ($pageRow === null) {
+ return null;
+ }
if (true === empty($pageRow[self::FIELD_ACTION_SUB])) {
$pageRow = $this->pageService->getPageTemplateConfiguration($pageRow['uid']);
}
- return $pageRow[self::FIELD_ACTION_SUB];
+ return $pageRow[self::FIELD_ACTION_SUB] ?? null;
}
}
diff --git a/Classes/Service/FluxService.php b/Classes/Service/FluxService.php
index 074e74844..0bb1548d9 100644
--- a/Classes/Service/FluxService.php
+++ b/Classes/Service/FluxService.php
@@ -22,6 +22,7 @@
use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
use TYPO3\CMS\Core\Log\LogManager;
+use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Service\FlexFormService;
use TYPO3\CMS\Core\SingletonInterface;
@@ -336,7 +337,9 @@ public function convertFileReferenceToTemplatePathAndFilename($reference)
$parts = explode(':', $reference);
$filename = array_pop($parts);
if (true === ctype_digit($filename)) {
- return $this->resourceFactory->getFileObjectFromCombinedIdentifier($reference)->getIdentifier();
+ /** @var File $file */
+ $file = $this->resourceFactory->getFileObjectFromCombinedIdentifier($reference);
+ return $file->getIdentifier();
}
$reference = GeneralUtility::getFileAbsFileName($reference);
return $reference;
diff --git a/Classes/Service/PageService.php b/Classes/Service/PageService.php
index 80b5ff092..fbe343a1e 100755
--- a/Classes/Service/PageService.php
+++ b/Classes/Service/PageService.php
@@ -167,7 +167,7 @@ public function getPageFlexFormSource($pageUid)
$resolveParentPageUid = (integer) (0 > $page['pid'] ? $page['t3ver_oid'] : $page['pid']);
$page = $this->workspacesAwareRecordService->getSingle('pages', $fieldList, $resolveParentPageUid);
}
- return $page['tx_fed_page_flexform'];
+ return $page['tx_fed_page_flexform'] ?? null;
}
/**
diff --git a/Classes/Utility/CompatibilityRegistry.php b/Classes/Utility/CompatibilityRegistry.php
index 0fc7f6a15..261dfdff8 100644
--- a/Classes/Utility/CompatibilityRegistry.php
+++ b/Classes/Utility/CompatibilityRegistry.php
@@ -194,7 +194,7 @@ public static function registerFeatureFlags($scope, array $versionedFeatureFlags
/**
* @param string $scope
- * @param string|NULL $version
+ * @param string $version
* @param mixed $default
* @return mixed
*/
diff --git a/Classes/Utility/ExtensionNamingUtility.php b/Classes/Utility/ExtensionNamingUtility.php
index ea31b751f..d27ebd26d 100644
--- a/Classes/Utility/ExtensionNamingUtility.php
+++ b/Classes/Utility/ExtensionNamingUtility.php
@@ -52,7 +52,7 @@ public static function getExtensionKey($qualifiedExtensionName)
public static function getExtensionName($qualifiedExtensionName)
{
list(, $extensionName) = static::getVendorNameAndExtensionName($qualifiedExtensionName);
- return $extensionName;
+ return (string) $extensionName;
}
/**
diff --git a/Classes/Utility/MiscellaneousUtility.php b/Classes/Utility/MiscellaneousUtility.php
index 8f4d4b3a8..5ace82d64 100644
--- a/Classes/Utility/MiscellaneousUtility.php
+++ b/Classes/Utility/MiscellaneousUtility.php
@@ -8,6 +8,9 @@
* LICENSE.md file that was distributed with this source code.
*/
+use DOMElement;
+use DOMNode;
+use DOMNodeList;
use FluidTYPO3\Flux\Form;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider;
@@ -43,7 +46,7 @@ public static function getIconForTemplate(Form $form)
return $form->getOption(Form::OPTION_ICON);
}
if (true === $form->hasOption(Form::OPTION_TEMPLATEFILE)) {
- $extensionKey = ExtensionNamingUtility::getExtensionKey($form->getExtensionName());
+ $extensionKey = ExtensionNamingUtility::getExtensionKey((string) $form->getExtensionName());
$fullTemplatePathAndName = $form->getOption(Form::OPTION_TEMPLATEFILE);
$templatePathParts = explode('/', $fullTemplatePathAndName);
$templateName = pathinfo(array_pop($templatePathParts), PATHINFO_FILENAME);
@@ -113,28 +116,30 @@ public static function cleanFlexFormXml($xml, array $removals = [])
$dom->formatOutput = true;
$fieldNodesToRemove = [];
foreach ($dom->getElementsByTagName('field') as $fieldNode) {
- /** @var \DOMElement $fieldNode */
+ /** @var DOMElement $fieldNode */
if (true === in_array($fieldNode->getAttribute('index'), $removals)) {
$fieldNodesToRemove[] = $fieldNode;
}
}
foreach ($fieldNodesToRemove as $fieldNodeToRemove) {
- /** @var \DOMElement $fieldNodeToRemove */
- $fieldNodeToRemove->parentNode->removeChild($fieldNodeToRemove);
+ /** @var DOMNode $parent */
+ $parent = $fieldNodeToRemove->parentNode;
+ /** @var DOMElement $fieldNodeToRemove */
+ $parent->removeChild($fieldNodeToRemove);
}
// Assign a hidden ID to all container-type nodes, making the value available in templates etc.
foreach ($dom->getElementsByTagName('el') as $containerNode) {
- /** @var \DOMElement $containerNode */
+ /** @var DOMElement $containerNode */
$hasIdNode = false;
- if (0 < $containerNode->attributes->length) {
+ if ($containerNode->attributes instanceof \DOMNamedNodeMap && 0 < $containerNode->attributes->length) {
// skip tags reserved for other purposes by attributes; only allow pure tags.
continue;
}
foreach ($containerNode->childNodes as $fieldNodeInContainer) {
- /** @var \DOMNode $fieldNodeInContainer */
- if (false === $fieldNodeInContainer instanceof \DOMElement) {
+ /** @var DOMNode $fieldNodeInContainer */
+ if (false === $fieldNodeInContainer instanceof DOMElement) {
continue;
}
$isFieldNode = ('field' === $fieldNodeInContainer->tagName);
@@ -167,19 +172,25 @@ public static function cleanFlexFormXml($xml, array $removals = [])
}
foreach ($nodesToBeRemoved as $node) {
- /** @var \DOMElement $node */
- $node->parentNode->removeChild($node);
+ /** @var DOMNode $parent */
+ $parent = $node->parentNode;
+ /** @var DOMElement $node */
+ $parent->removeChild($node);
}
// Return empty string in case remaining flexform XML is all empty
- $dataNode = $dom->getElementsByTagName('data')->item(0);
- if (0 === $dataNode->getElementsByTagName('sheet')->length) {
+ /** @var DOMNodeList $dataNodes */
+ $dataNodes = $dom->getElementsByTagName('data');
+ /** @var DOMElement $dataNode */
+ $dataNode = $dataNodes->item(0);
+ $elements = $dataNode->getElementsByTagName('sheet');
+ if (0 === $elements->length) {
return '';
}
$xml = (string) $dom->saveXML();
// hack-like pruning of empty-named node inserted when removing objects from a previously populated Section
- $xml = preg_replace('#\s*#', '', $xml);
- $xml = preg_replace('#\s*#', '', $xml);
+ $xml = (string) preg_replace('#\s*#', '', $xml);
+ $xml = (string) preg_replace('#\s*#', '', $xml);
return $xml;
}
}
diff --git a/Classes/ViewHelpers/Form/DataViewHelper.php b/Classes/ViewHelpers/Form/DataViewHelper.php
index 6fbea2eb0..8cd9a8676 100644
--- a/Classes/ViewHelpers/Form/DataViewHelper.php
+++ b/Classes/ViewHelpers/Form/DataViewHelper.php
@@ -179,7 +179,7 @@ public static function renderStatic(
protected static function readDataArrayFromProvidersOrUsingDefaultMethod(array $providers, $record, $field)
{
if (0 === count($providers)) {
- $dataArray = static::$configurationService->convertFlexFormContentToArray($record[$field]);
+ $dataArray = static::getFluxService()->convertFlexFormContentToArray($record[$field]);
} else {
$dataArray = [];
/** @var ProviderInterface $provider */
diff --git a/Tests/Unit/Controller/AbstractFluxControllerTestCase.php b/Tests/Unit/Controller/AbstractFluxControllerTestCase.php
index 247b51314..c7d76d134 100644
--- a/Tests/Unit/Controller/AbstractFluxControllerTestCase.php
+++ b/Tests/Unit/Controller/AbstractFluxControllerTestCase.php
@@ -518,8 +518,9 @@ public function testOutletActionForwardsUnmatchedConfigurationToRenderAction()
$subject->expects($this->once())->method('forward')->with('render')->willThrowException(new StopActionException());
$subject->expects($this->once())->method('getRecord')->willReturn([]);
$request = new Request();
- $provider = $this->getMockBuilder(Provider::class)->setMethods(['getTableName'])->getMock();
+ $provider = $this->getMockBuilder(Provider::class)->setMethods(['getTableName', 'getForm'])->getMock();
$provider->expects($this->once())->method('getTableName')->willReturn('foobar');
+ $provider->expects($this->once())->method('getForm')->willReturn(Form::create());
ObjectAccess::setProperty($request, 'internalArguments', ['outlet' => ['table' => 'xyz', 'uid' => 321]], true);
ObjectAccess::setProperty($subject, 'request', $request, true);
ObjectAccess::setProperty($subject, 'provider', $provider, true);
diff --git a/Tests/Unit/Controller/ContentControllerTest.php b/Tests/Unit/Controller/ContentControllerTest.php
index 672e4e718..685cbd9d1 100644
--- a/Tests/Unit/Controller/ContentControllerTest.php
+++ b/Tests/Unit/Controller/ContentControllerTest.php
@@ -32,9 +32,6 @@ public function canRegisterCustomControllerForContent()
*/
protected function createAndTestDummyControllerInstance()
{
- $record = Records::$contentRecordWithoutParentAndWithoutChildren;
- $record['pi_flexform'] = Xml::SIMPLE_FLEXFORM_SOURCE_DEFAULT_SHEET_ONE_FIELD;
- $record['tx_fed_fcefile'] = 'Flux:Default.html';
$this->performDummyRegistration();
$controllerClassName = 'FluidTYPO3\\Flux\\Controller\\ContentController';
/** @var AbstractFluxController $instance */
diff --git a/Tests/Unit/ViewHelpers/Content/GetViewHelperTest.php b/Tests/Unit/ViewHelpers/Content/GetViewHelperTest.php
index 2d583cca8..5d0c48d00 100644
--- a/Tests/Unit/ViewHelpers/Content/GetViewHelperTest.php
+++ b/Tests/Unit/ViewHelpers/Content/GetViewHelperTest.php
@@ -13,6 +13,7 @@
use FluidTYPO3\Flux\Form\Container\Grid;
use FluidTYPO3\Flux\Form\Container\Row;
use FluidTYPO3\Flux\Provider\Provider;
+use FluidTYPO3\Flux\Provider\ProviderInterface;
use FluidTYPO3\Flux\Tests\Fixtures\Data\Records;
use FluidTYPO3\Flux\Tests\Unit\ViewHelpers\AbstractViewHelperTestCase;
use FluidTYPO3\Flux\ViewHelpers\FormViewHelper;
@@ -56,6 +57,7 @@ public function canRenderViewHelper()
$node = $this->createNode('Text', 'Hello loopy world!');
$viewHelper = $this->buildViewHelperInstance($arguments, $variables, $node);
$renderingContext = ObjectAccess::getProperty($viewHelper, 'renderingContext', true);
+ /** @var ProviderInterface $provider */
$provider = $this->objectManager->get(Provider::class);
$provider->setGrid(Grid::create(['children' => [['type' => Row::class, 'children' => [['type' => Column::class, 'name' => 'void']]]]]));
$provider->setForm(Form::create());
diff --git a/composer.json b/composer.json
index 9267a0bf1..3261e1dd8 100644
--- a/composer.json
+++ b/composer.json
@@ -26,6 +26,7 @@
"php": "^7.4.0 || ^8",
"ext-json": "*",
"typo3/cms-core": "^8.7 || ^9 || ^10 || ^11 || dev-master",
+ "ext-dom": "*",
"typo3/cms-fluid": "^8.7 || ^9 || ^10 || ^11 || dev-master",
"typo3/cms-backend": "^8.7 || ^9 || ^10 || ^11 || dev-master",
"typo3/cms-frontend": "^8.7 || ^9 || ^10 || ^11 || dev-master",
diff --git a/phpstan.neon b/phpstan.neon
index c2605304d..586c8e08e 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -2,7 +2,7 @@ includes:
- phpstan-baseline.neon
parameters:
- level: 7
+ level: 8
reportUnmatchedIgnoredErrors: false
checkGenericClassInNonGenericObjectType: false
ignoreErrors:
@@ -34,6 +34,7 @@ parameters:
- "#^Cannot call method (rowCount|fetch|fetchAssociative|fetchAll|fetchAllAssociative)\\(\\) on (Doctrine\\\\DBAL\\\\Driver\\\\Statement|Doctrine\\\\DBAL\\\\Driver\\\\ResultStatement|Doctrine\\\\DBAL\\\\Result)\\|int\\.$#"
- "#^Static method TYPO3\\\\CMS\\\\Extbase\\\\Reflection\\\\ObjectAccess\\:\\:getProperty\\(\\) invoked with 3 parameters, 2 required\\.$#"
- "#^Call to an undefined static method TYPO3\\\\CMS\\\\Backend\\\\Utility\\\\BackendUtility\\:\\:getMovePlaceholder\\(\\)\\.$#"
+ - "#^Strict comparison using === between TYPO3\\\\CMS\\\\Frontend\\\\ContentObject\\\\ContentObjectRenderer and null will always evaluate to false\\.$#"
bootstrapFiles:
- phpstan-bootstrap.php
paths: