TYPO3 v15 dev-main snapshot ()

This commit is contained in:
2026-08-10 22:31:00 +02:00
commit f9941541b7
1178 changed files with 135377 additions and 0 deletions
+184
View File
@@ -0,0 +1,184 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Backend\Form;
use TYPO3\CMS\Core\Domain\DateTimeFormat;
use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction;
use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Base class for container and single elements - their abstracts extend from here.
*/
abstract class AbstractNode implements NodeInterface
{
/**
* Main data array to work on, given from parent to child elements
*/
protected array $data = [];
/**
* A list of default field information added to the element / container.
*
* @var array
*/
protected $defaultFieldInformation = [];
/**
* A list of default field controls added to the element / container.
* This property is often reset by single elements.
*
* @var array
*/
protected $defaultFieldControl = [];
/**
* A list of default field wizards added to the element / container.
* This property is often reset by single elements.
*
* @var array
*/
protected $defaultFieldWizard = [];
/**
* Retrieve the current data array from NodeFactory.
*/
public function setData(array $data): void
{
$this->data = $data;
}
/**
* Handler for single nodes
*
* @return array As defined in initializeResultArray() of AbstractNode
*/
abstract public function render(): array;
/**
* Initialize the array that is returned to parent after calling. This structure
* is identical for *all* nodes. Parent will merge the return of a child with its
* own stuff and in itself return an array of the same structure.
*
* @return array{
* additionalInlineLanguageLabelFiles: list<string>,
* stylesheetFiles: list<string>,
* javaScriptModules: list<JavaScriptModuleInstruction>,
* inlineData: array<string, mixed>,
* html: string,
* }
*/
protected function initializeResultArray(): array
{
return [
'additionalInlineLanguageLabelFiles' => [],
'stylesheetFiles' => [],
'javaScriptModules' => [],
'inlineData' => [],
'html' => '',
];
}
/**
* Merge existing data with a child return array.
* The incoming $childReturn array should be initialized
* using initializeResultArray() beforehand.
*
* @param array $existing Currently merged array
* @param array $childReturn Array returned by child
* @param bool $mergeHtml If false, the ['html'] section of $childReturn will NOT be added to $existing
* @return array Result array
*/
protected function mergeChildReturnIntoExistingResult(array $existing, array $childReturn, bool $mergeHtml = true): array
{
if ($mergeHtml && !empty($childReturn['html'])) {
$existing['html'] .= LF . $childReturn['html'];
}
foreach ($childReturn['stylesheetFiles'] ?? [] as $value) {
$existing['stylesheetFiles'][] = $value;
}
foreach ($childReturn['javaScriptModules'] ?? [] as $module) {
$existing['javaScriptModules'][] = $module;
}
foreach ($childReturn['additionalInlineLanguageLabelFiles'] ?? [] as $inlineLanguageLabelFile) {
$existing['additionalInlineLanguageLabelFiles'][] = $inlineLanguageLabelFile;
}
if (!empty($childReturn['inlineData'])) {
$existingInlineData = $existing['inlineData'];
$childInlineData = $childReturn['inlineData'];
ArrayUtility::mergeRecursiveWithOverrule($existingInlineData, $childInlineData);
$existing['inlineData'] = $existingInlineData;
}
return $existing;
}
/**
* Build JSON string for validations rules.
*/
protected function getValidationDataAsJsonString(array $config): string
{
$validationRules = [];
if (!empty($config['eval'])) {
$evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
foreach ($evalList as $evalType) {
$validationRules[] = [
'type' => $evalType,
];
}
}
if (!empty($config['range'])) {
$newValidationRule = [
'type' => 'range',
];
$isDateTime = ($config['type'] ?? '') === 'datetime';
if (!empty($config['range']['lower'])) {
$lower = (int)$config['range']['lower'];
if ($isDateTime) {
$lower = date(DateTimeFormat::ISO8601_LOCALTIME, $lower);
}
$newValidationRule['lower'] = $lower;
}
if (!empty($config['range']['upper'])) {
$upper = (int)$config['range']['upper'];
if ($isDateTime) {
$upper = date(DateTimeFormat::ISO8601_LOCALTIME, $upper);
}
$newValidationRule['upper'] = $upper;
}
$validationRules[] = $newValidationRule;
}
if (!empty($config['maxitems']) || !empty($config['minitems'])) {
$minItems = isset($config['minitems']) ? (int)$config['minitems'] : 0;
$maxItems = isset($config['maxitems']) ? (int)$config['maxitems'] : 99999;
$type = $config['type'] ?: 'range';
$validationRules[] = [
'type' => $type,
'minItems' => $minItems,
'maxItems' => $maxItems,
];
}
if (!empty($config['required'])) {
$validationRules[] = ['type' => 'required'];
}
if (!empty($config['min'])) {
$validationRules[] = ['type' => 'min'];
}
return json_encode($validationRules);
}
}