TYPO3 v15 dev-main snapshot ()

This commit is contained in:
2026-08-10 22:31:09 +02:00
commit af8cc155b5
6818 changed files with 642608 additions and 0 deletions
@@ -0,0 +1,58 @@
<?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\Core\Schema\Struct;
use TYPO3\CMS\Core\Schema\Field\FieldCollection;
use TYPO3\CMS\Core\Schema\Field\FieldTypeInterface;
/**
* FlexForms Sheets can contain a "repeatable set of fields", which we call "Section Container".
* The section container only contains fields, which is a very simple format.
*
* @internal This is an experimental implementation and might change until TYPO3 v13 LTS
*/
final readonly class FlexSectionContainer
{
public function __construct(
// @todo: incomplete or obsolete implementation, these properties are never read.
private string $sheetIdentifier,
private string $title,
private string $description,
private FieldCollection $fields
) {}
public function getFields(): FieldCollection
{
return $this->fields;
}
public function hasField(string $fieldName): bool
{
return isset($this->fields[$fieldName]);
}
public function getField(string $fieldName): FieldTypeInterface
{
return $this->fields[$fieldName];
}
public static function __set_state(array $state): self
{
return new self(...$state);
}
}
+64
View File
@@ -0,0 +1,64 @@
<?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\Core\Schema\Struct;
use TYPO3\CMS\Core\Schema\Field\FieldCollection;
use TYPO3\CMS\Core\Schema\Field\FieldTypeInterface;
/**
* FlexForms are always separated in sheets, "sDEF" being the default sheet
* if no sheets are defined.
* Each sheet contains fields OR Section Containers (defined by <section>1</section>) which then could also
* contain fields.
*/
final readonly class FlexSheet
{
public function __construct(
// @todo: incomplete or obsolete implementation, these properties are never read.
private string $sheetIdentifier,
private string $title,
private string $description,
private FieldCollection $fields,
private array $sections,
) {}
public function getFields(): FieldCollection
{
return $this->fields;
}
public function hasField(string $fieldName): bool
{
return isset($this->fields[$fieldName]);
}
public function getField(string $fieldName): FieldTypeInterface
{
return $this->fields[$fieldName];
}
public function getSections(): array
{
return $this->sections;
}
public static function __set_state(array $state): self
{
return new self(...$state);
}
}
+283
View File
@@ -0,0 +1,283 @@
<?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\Core\Schema\Struct;
final class SelectItem implements \ArrayAccess
{
private const array LEGACY_INDEXED_KEYS_MAPPING_TABLE = [
0 => 'label',
1 => 'value',
2 => 'icon',
3 => 'group',
4 => 'description',
];
private array $container = [];
public function __construct(
private string $type,
private string $label,
private int|string|null $value,
private ?string $icon = null,
private ?string $group = null,
private string|array|null $description = null,
private bool $invertStateDisplay = false,
private ?string $iconIdentifierChecked = null,
private ?string $iconIdentifierUnchecked = null,
private ?string $labelChecked = null,
private ?string $labelUnchecked = null,
private ?string $iconOverlay = null,
) {}
public static function fromTcaItemArray(array $item, string $type = 'select'): SelectItem
{
return new self(
type: $type,
label: (string)($item['label'] ?? $item[0]),
value: $item['value'] ?? $item[1] ?? null,
icon: $item['icon'] ?? $item[2] ?? null,
group: $item['group'] ?? $item[3] ?? null,
description: $item['description'] ?? $item[4] ?? null,
invertStateDisplay: (bool)($item['invertStateDisplay'] ?? false),
iconIdentifierChecked: $item['iconIdentifierChecked'] ?? null,
iconIdentifierUnchecked: $item['iconIdentifierUnchecked'] ?? null,
labelChecked: $item['labelChecked'] ?? null,
labelUnchecked: $item['labelUnchecked'] ?? null,
iconOverlay: $item['iconOverlay'] ?? null,
);
}
public function toArray(): array
{
if ($this->type === 'radio') {
return [
'label' => $this->label,
'value' => $this->value,
];
}
if ($this->type === 'check') {
return [
'label' => $this->label,
'invertStateDisplay' => $this->invertStateDisplay,
'iconIdentifierChecked' => $this->iconIdentifierChecked,
'iconIdentifierUnchecked' => $this->iconIdentifierUnchecked,
'labelChecked' => $this->labelChecked,
'labelUnchecked' => $this->labelUnchecked,
];
}
// Default type=select
return [
'label' => $this->label,
'value' => $this->value,
'icon' => $this->icon,
'iconOverlay' => $this->iconOverlay,
'group' => $this->group,
'description' => $this->description,
];
}
public function getLabel(): string
{
return $this->label;
}
public function withLabel(string $label): SelectItem
{
$clone = clone $this;
$clone->label = $label;
return $clone;
}
public function getValue(): int|string|null
{
return $this->value;
}
public function withValue(int|string|null $value): SelectItem
{
$clone = clone $this;
$clone->value = $value;
return $clone;
}
public function getIcon(): ?string
{
return $this->icon;
}
public function hasIcon(): bool
{
return $this->icon !== null;
}
public function withIcon(?string $icon): SelectItem
{
$clone = clone $this;
$clone->icon = $icon;
return $clone;
}
public function getGroup(): ?string
{
return $this->group;
}
public function hasGroup(): bool
{
return $this->group !== null;
}
public function withGroup(?string $group): SelectItem
{
$clone = clone $this;
$clone->group = $group;
return $clone;
}
public function getDescription(): string|array|null
{
return $this->description;
}
public function hasDescription(): bool
{
return $this->description !== null;
}
public function withDescription(string|array|null $description): SelectItem
{
$clone = clone $this;
$clone->description = $description;
return $clone;
}
public function invertStateDisplay(): bool
{
return $this->invertStateDisplay;
}
public function getIconIdentifierChecked(): ?string
{
return $this->iconIdentifierChecked;
}
public function hasIconIdentifierChecked(): bool
{
return $this->iconIdentifierChecked !== null;
}
public function getIconIdentifierUnchecked(): ?string
{
return $this->iconIdentifierUnchecked;
}
public function hasIconIdentifierUnchecked(): bool
{
return $this->iconIdentifierUnchecked !== null;
}
public function getLabelChecked(): ?string
{
return $this->labelChecked;
}
public function hasLabelChecked(): bool
{
return $this->labelChecked !== null;
}
public function getLabelUnchecked(): ?string
{
return $this->labelUnchecked;
}
public function hasLabelUnchecked(): bool
{
return $this->labelUnchecked !== null;
}
public function getIconOverlay(): ?string
{
return $this->iconOverlay;
}
public function hasIconOverlay(): bool
{
return $this->iconOverlay !== null;
}
public function withIconOverlay(?string $iconOverlay): SelectItem
{
$clone = clone $this;
$clone->iconOverlay = $iconOverlay;
return $clone;
}
public function isDivider(): bool
{
return $this->value === '--div--';
}
public function offsetExists(mixed $offset): bool
{
if (array_key_exists($offset, self::LEGACY_INDEXED_KEYS_MAPPING_TABLE)) {
$offset = self::LEGACY_INDEXED_KEYS_MAPPING_TABLE[$offset];
}
if (property_exists($this, $offset)) {
return isset($this->toArray()[$offset]);
}
return isset($this->container[$offset]);
}
public function offsetGet(mixed $offset): mixed
{
if (array_key_exists($offset, self::LEGACY_INDEXED_KEYS_MAPPING_TABLE)) {
$offset = self::LEGACY_INDEXED_KEYS_MAPPING_TABLE[$offset];
}
if (property_exists($this, $offset)) {
return $this->toArray()[$offset];
}
return $this->container[$offset] ?? null;
}
public function offsetSet(mixed $offset, mixed $value): void
{
if (array_key_exists($offset, self::LEGACY_INDEXED_KEYS_MAPPING_TABLE)) {
$offset = self::LEGACY_INDEXED_KEYS_MAPPING_TABLE[$offset];
}
if (property_exists($this, $offset)) {
$this->{$offset} = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetUnset(mixed $offset): void
{
if (array_key_exists($offset, self::LEGACY_INDEXED_KEYS_MAPPING_TABLE)) {
$offset = self::LEGACY_INDEXED_KEYS_MAPPING_TABLE[$offset];
}
if (property_exists($this, $offset)) {
$this->{$offset} = null;
} else {
unset($this->container[$offset]);
}
}
}
@@ -0,0 +1,147 @@
<?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\Core\Schema\Struct;
use TYPO3\CMS\Core\Collection\CollectionInterface;
use TYPO3\CMS\Core\Collection\EditableCollectionInterface;
final class SelectItemCollection implements CollectionInterface, EditableCollectionInterface
{
private \SplDoublyLinkedList $storage;
public function __construct()
{
$this->storage = new \SplDoublyLinkedList();
}
/**
* Utility method to transform an arbitrary array to a proper SelectItem collection
*
* @param array $itemList List of SelectItem elements or legacy item arrays
* @param string $type The field type, e.g. "select"
*/
public static function createFromArray(array $itemList, string $type): self
{
$collection = new self();
foreach ($itemList as $item) {
if ($item instanceof SelectItem) {
$collection->add($item);
continue;
}
if (is_array($item)) {
$collection->add(
SelectItem::fromTcaItemArray($item, $type)
);
continue;
}
throw new \InvalidArgumentException(
'Values of $itemList must be of type ' . SelectItem::class . ' or array.',
1762417317
);
}
return $collection;
}
public function current(): SelectItem
{
return $this->storage->current();
}
public function next(): void
{
$this->storage->next();
}
public function key(): int
{
return $this->storage->key();
}
public function valid(): bool
{
return $this->storage->valid();
}
public function rewind(): void
{
$this->storage->rewind();
}
public function count(): int
{
return $this->storage->count();
}
/**
* @param mixed $data
* @todo replace this with a strict "SelectItem" type in TYPO3 v15.0
*/
public function add($data): void
{
if ($data instanceof SelectItem) {
$this->storage->push($data);
}
}
/**
* @param SelectItemCollection $other
*/
public function addAll(CollectionInterface $other): void
{
foreach ($other as $item) {
if ($item instanceof SelectItem) {
$this->storage->push($item);
}
}
}
/**
* @param mixed $data
* @todo replace this with a strict "SelectItem" type in TYPO3 v15.0
*/
public function remove($data): void
{
if (!($data instanceof SelectItem)) {
return;
}
foreach ($this->storage as $key => $value) {
if ($value === $data) {
$this->storage->offsetUnset($key);
break;
}
}
}
public function removeAll(): void
{
$this->storage = new \SplDoublyLinkedList();
}
/**
* @return SelectItem[]
*/
public function toArray(): array
{
$items = [];
foreach ($this->storage as $item) {
$items[] = $item;
}
return $items;
}
}
+49
View File
@@ -0,0 +1,49 @@
<?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\Core\Schema\Struct;
use TYPO3\CMS\Core\Schema\Field\FieldCollection;
final readonly class WizardStep
{
public function __construct(
private string $identifier,
private string $title,
private FieldCollection $fields,
) {}
public function getIdentifier(): string
{
return $this->identifier;
}
public function getTitle(): string
{
return $this->title;
}
public function getFields(): FieldCollection
{
return $this->fields;
}
public static function __set_state(array $state): self
{
return new self(...$state);
}
}