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,24 @@
<?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\Database\Schema\Parser\AST;
/**
* Base class for all definition items that can occur in the definition
* of a table, namely fields, indexes and foreign keys.
*/
abstract class AbstractCreateDefinitionItem {}
@@ -0,0 +1,24 @@
<?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\Database\Schema\Parser\AST;
/**
* Base class for all create type statements like CREATE TABLE
* or CREATE VIEW.
*/
abstract class AbstractCreateStatement {}
@@ -0,0 +1,53 @@
<?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\Database\Schema\Parser\AST;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\AbstractDataType;
/**
* Syntax tree node for column definitions within "create table" statements.
* Holds basic attributes common to all types of columns.
*
* @internal
*/
final class CreateColumnDefinitionItem extends AbstractCreateDefinitionItem
{
public bool $allowNull = true;
// Has explicit default value?
public bool $hasDefaultValue = false;
// The explicit default value
public mixed $defaultValue = null;
public bool $autoIncrement = false;
// Create non-unique index for column?
public bool $index = false;
// Create unique constraint for column?
public bool $unique = false;
// Use column as primary key for table?
public bool $primary = false;
public ?string $comment = null;
// Column format: "dynamic" or "fixed"
public ?string $columnFormat = null;
// The storage type for the column (ignored unless MySQL Cluster with NDB Engine)
public ?string $storage = null;
public ?ReferenceDefinition $reference = null;
public function __construct(
public readonly Identifier $columnName,
public readonly AbstractDataType $dataType,
) {}
}
@@ -0,0 +1,34 @@
<?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\Database\Schema\Parser\AST;
/**
* Syntax node for the whole definition of a table/view. Collects
* the nodes for fields, indexes and foreign keys.
*
* @internal
*/
final readonly class CreateDefinition
{
/**
* @param AbstractCreateDefinitionItem[] $items
*/
public function __construct(
public array $items
) {}
}
@@ -0,0 +1,35 @@
<?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\Database\Schema\Parser\AST;
/**
* Syntax node to structure a foreign key definition.
*
* @internal
*/
final class CreateForeignKeyDefinitionItem extends AbstractCreateDefinitionItem
{
/**
* @param IndexColumnName[] $columnNames
*/
public function __construct(
public readonly Identifier $indexName,
public readonly array $columnNames,
public readonly ReferenceDefinition $reference,
) {}
}
@@ -0,0 +1,41 @@
<?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\Database\Schema\Parser\AST;
/**
* Syntax node to structure an index definition.
*
* @internal
*/
final class CreateIndexDefinitionItem extends AbstractCreateDefinitionItem
{
// Use a special index type (MySQL: BTREE | HASH)
public string $indexType = '';
// @var IndexColumnName[]
public array $columnNames = [];
// Index options KEY_BLOCK_SIZE, USING, WITH PARSER or COMMENT
public array $options = [];
public function __construct(
public readonly ?Identifier $indexName = null,
public readonly bool $isPrimary = false,
public readonly bool $isUnique = false,
public readonly bool $isSpatial = false,
public readonly bool $isFulltext = false
) {}
}
@@ -0,0 +1,33 @@
<?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\Database\Schema\Parser\AST;
/**
* Syntax node to represent the initial CREATE TABLE statement in the
* syntax tree. Represents everything up to the start of the definition
* of fields/indexes/foreign keys.
*
* @internal
*/
final class CreateTableClause
{
public function __construct(
public readonly Identifier $tableName,
public bool $isTemporary = false
) {}
}
@@ -0,0 +1,38 @@
<?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\Database\Schema\Parser\AST;
/**
* Root node for a CREATE TABLE statement in the syntax tree.
*
* @internal
*/
final class CreateTableStatement extends AbstractCreateStatement
{
public Identifier $tableName;
public bool $isTemporary = false;
public array $tableOptions = [];
public function __construct(
CreateTableClause $createTableClause,
public readonly CreateDefinition $createDefinition
) {
$this->tableName = $createTableClause->tableName;
$this->isTemporary = $createTableClause->isTemporary;
}
}
@@ -0,0 +1,112 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Base class for all data types that contains properties
* common to all data types.
*
* @internal
*/
abstract class AbstractDataType
{
/** Used by most field types for length/precision information */
protected int $length = 0;
/** Used for floating point type columns. -1 is used to indicate no value has been set. */
protected int $precision = -1;
/** Used for floating point type columns. -1 is used to indicate that no value has been set. */
protected int $scale = -1;
/** Differentiate between CHAR/VARCHAR and BINARY/VARBINARY */
protected bool $fixed = false;
/** Unsigned flag for numeric columns */
protected bool $unsigned = false;
/** Extra options for a column that control specific features/flags */
protected array $options = [];
/** Options for ENUM/SET data types */
protected array $values = [];
public function getLength(): int
{
return $this->length;
}
public function setLength(int $length): void
{
$this->length = $length;
}
public function getPrecision(): int
{
return $this->precision;
}
public function setPrecision(int $precision): void
{
$this->precision = $precision;
}
public function getScale(): int
{
return $this->scale;
}
public function setScale(int $scale): void
{
$this->scale = $scale;
}
public function isFixed(): bool
{
return $this->fixed;
}
public function setFixed(bool $fixed): void
{
$this->fixed = $fixed;
}
public function getOptions(): array
{
return $this->options;
}
public function setOptions(array $options): void
{
$this->options = $options;
}
public function isUnsigned(): bool
{
return $this->unsigned;
}
public function setUnsigned(bool $unsigned): void
{
$this->unsigned = $unsigned;
}
public function getValues(): array
{
return $this->values;
}
public function setValues(array $values): void
{
$this->values = $values;
}
}
@@ -0,0 +1,25 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the BIGINT SQL column type
*
* @internal
*/
final class BigIntDataType extends IntegerDataType {}
@@ -0,0 +1,36 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the BINARY SQL column type
*
* @internal
*/
final class BinaryDataType extends AbstractDataType
{
public function __construct(int $length)
{
/**
* BINARY is "fixed type". Setting it here instructs Doctrine DBAL to use this type instead of
* the "variable type" when being transformed within the {@see TableBuilder::addColumn()} method.
*/
$this->fixed = true;
$this->length = $length;
}
}
@@ -0,0 +1,31 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the BIT SQL column type
*
* @internal
*/
final class BitDataType extends AbstractDataType
{
public function __construct(int $length)
{
$this->length = $length;
}
}
@@ -0,0 +1,32 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the BLOB SQL column type
*
* @internal
*/
class BlobDataType extends AbstractDataType
{
public function __construct()
{
// MySQL BLOB can store 64KB
$this->length = 65535;
}
}
@@ -0,0 +1,37 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the CHAR SQL column type
*
* @internal
*/
final class CharDataType extends AbstractDataType
{
public function __construct(int $length, array $options)
{
/**
* CHAR is "fixed type". Setting it here instructs Doctrine DBAL to use this type instead of
* the "variable type" when being transformed within the {@see TableBuilder::addColumn()} method.
*/
$this->fixed = true;
$this->length = $length;
$this->options = $options;
}
}
@@ -0,0 +1,25 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the DATE SQL column type
*
* @internal
*/
final class DateDataType extends AbstractDataType {}
@@ -0,0 +1,31 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the DATETIME SQL column type
*
* @internal
*/
final class DateTimeDataType extends AbstractDataType
{
public function __construct(int $length)
{
$this->length = $length;
}
}
@@ -0,0 +1,33 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the DECIMAL SQL column type
*
* @internal
*/
class DecimalDataType extends AbstractDataType
{
public function __construct(array $dataTypeDecimals, array $dataTypeOptions)
{
$this->precision = $dataTypeDecimals['length'] ?? -1;
$this->scale = $dataTypeDecimals['decimals'] ?? -1;
$this->options = $dataTypeOptions;
}
}
@@ -0,0 +1,25 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the DOUBLE SQL column type
*
* @internal
*/
final class DoubleDataType extends FloatDataType {}
@@ -0,0 +1,32 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the ENUM SQL column type
*
* @internal
*/
final class EnumDataType extends AbstractDataType
{
public function __construct(array $values, array $options)
{
$this->values = $values;
$this->options = $options;
}
}
@@ -0,0 +1,34 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the FLOAT SQL column type
*
* @internal
*/
class FloatDataType extends AbstractDataType
{
public function __construct(array $dataTypeDecimals, array $dataTypeOptions)
{
// -1 is used to indicate that no value has been provided
$this->precision = $dataTypeDecimals['length'] ?? -1;
$this->scale = $dataTypeDecimals['decimals'] ?? -1;
$this->options = $dataTypeOptions;
}
}
@@ -0,0 +1,35 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the INT SQL column type
*
* @internal
*/
class IntegerDataType extends AbstractDataType
{
public function __construct(int $length, array $options)
{
$this->length = $length;
$this->options = $options;
if (array_key_exists('unsigned', $options) && $options['unsigned']) {
$this->setUnsigned(true);
}
}
}
@@ -0,0 +1,34 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the JSON SQL column type
*
* @internal
*/
final class JsonDataType extends AbstractDataType
{
public function __construct()
{
// JSON is not yet supported by Doctrine 2.5 and will be remapped
// to a TEXT type. Setting the length here will ensure a LONGTEXT
// column type is selected.
$this->length = 2147483647;
}
}
@@ -0,0 +1,33 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the LONGBLOB SQL column type
*
* @internal
*/
final class LongBlobDataType extends BlobDataType
{
public function __construct()
{
parent::__construct();
// MySQL LONGBLOB can store 4GB of data, to be 32bit safe only claim 2GB
$this->length = 2147483647;
}
}
@@ -0,0 +1,33 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the LONGTEXT SQL column type
*
* @internal
*/
final class LongTextDataType extends TextDataType
{
public function __construct(array $options)
{
parent::__construct($options);
// MySQL LONGTEXT can store 4GB of data, to be 32bit safe only claim 2GB
$this->length = 2147483647;
}
}
@@ -0,0 +1,33 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the MEDIUMBLOB SQL column type
*
* @internal
*/
final class MediumBlobDataType extends BlobDataType
{
public function __construct()
{
parent::__construct();
// MySQL MEDIUMBLOB can store 16MB
$this->length = 16777215;
}
}
@@ -0,0 +1,25 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the MEDIUMINT SQL column type
*
* @internal
*/
final class MediumIntDataType extends IntegerDataType {}
@@ -0,0 +1,33 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the MEDIUMTEXT SQL column type
*
* @internal
*/
final class MediumTextDataType extends TextDataType
{
public function __construct(array $options)
{
parent::__construct($options);
// MySQL MEDIUMTEXT can store 16MB
$this->length = 16777215;
}
}
@@ -0,0 +1,25 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the NUMERIC SQL column type
*
* @internal
*/
final class NumericDataType extends DecimalDataType {}
@@ -0,0 +1,25 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the REAL SQL column type
*
* @internal
*/
final class RealDataType extends FloatDataType {}
@@ -0,0 +1,32 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the SET SQL column type
*
* @internal
*/
final class SetDataType extends AbstractDataType
{
public function __construct(array $values, array $options)
{
$this->values = $values;
$this->options = $options;
}
}
@@ -0,0 +1,25 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the SMALLINT SQL column type
*
* @internal
*/
final class SmallIntDataType extends IntegerDataType {}
@@ -0,0 +1,33 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the TEXT SQL column type
*
* @internal
*/
class TextDataType extends AbstractDataType
{
public function __construct(array $options)
{
// MySQL TEXT can store 64KB
$this->length = 65535;
$this->options = $options;
}
}
@@ -0,0 +1,31 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the TIME SQL column type
*
* @internal
*/
final class TimeDataType extends AbstractDataType
{
public function __construct(int $length)
{
$this->length = $length;
}
}
@@ -0,0 +1,31 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the TIMESTAMP SQL column type
*
* @internal
*/
final class TimestampDataType extends AbstractDataType
{
public function __construct(int $length)
{
$this->length = $length;
}
}
@@ -0,0 +1,33 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the TINYBLOB SQL column type
*
* @internal
*/
final class TinyBlobDataType extends BlobDataType
{
public function __construct()
{
parent::__construct();
// MySQL TINYBLOB can store 255 bytes
$this->length = 255;
}
}
@@ -0,0 +1,25 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the TINYINT SQL column type
*
* @internal
*/
final class TinyIntDataType extends IntegerDataType {}
@@ -0,0 +1,33 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the TINYTEXT SQL column type
*
* @internal
*/
final class TinyTextDataType extends TextDataType
{
public function __construct(array $options)
{
parent::__construct($options);
// MySQL TINYTEXT can store 255 characters
$this->length = 255;
}
}
@@ -0,0 +1,23 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* @internal for `EXT:core` internal usage and not part of public API.
*/
final class UuidDataType extends AbstractDataType {}
@@ -0,0 +1,31 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the VARBINARY SQL column type
*
* @internal
*/
final class VarBinaryDataType extends AbstractDataType
{
public function __construct(int $length)
{
$this->length = $length;
}
}
@@ -0,0 +1,32 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the VARCHAR SQL column type
*
* @internal
*/
final class VarCharDataType extends AbstractDataType
{
public function __construct(int $length, array $options)
{
$this->length = $length;
$this->options = $options;
}
}
@@ -0,0 +1,25 @@
<?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\Database\Schema\Parser\AST\DataType;
/**
* Node representing the YEAR SQL column type
*
* @internal
*/
final class YearDataType extends AbstractDataType {}
@@ -0,0 +1,42 @@
<?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\Database\Schema\Parser\AST;
/**
* Syntax node to represent identifiers used in various parts of a
* SQL statements like table, field or index names.
*
* @internal
*/
final class Identifier
{
private string $quoteChar = '`';
public function __construct(
public readonly string $schemaObjectName
) {}
/**
* Quotes the schema object name.
*/
public function getQuotedName(): string
{
$c = $this->quoteChar;
return $c . str_replace($c, $c . $c, $this->schemaObjectName) . $c;
}
}
@@ -0,0 +1,34 @@
<?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\Database\Schema\Parser\AST;
/**
* Syntax node to represent a column within an index, which can in MySQL
* context consist of the actual column name, length information for a partial
* index and a direction which influences default sorting and access patterns.
*
* @internal
*/
final readonly class IndexColumnName
{
public function __construct(
public Identifier $columnName,
public int $length,
public ?string $direction = null
) {}
}
@@ -0,0 +1,43 @@
<?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\Database\Schema\Parser\AST;
/**
* Syntax node to represent the REFERENCES part of a foreign key
* definition, encapsulating ON UPDATE/ON DELETE actions as well
* as the foreign table name and columns.
*
* @internal
*/
final class ReferenceDefinition
{
// Match type if given: FULL, PARTIAL or SIMPLE
public ?string $match = null;
// Reference option if given: RESTRICT | CASCADE | SET NULL | NO ACTION
public ?string $onDelete = null;
// Reference option if given: RESTRICT | CASCADE | SET NULL | NO ACTION
public ?string $onUpdate = null;
/**
* @param IndexColumnName[] $columnNames
*/
public function __construct(
public readonly Identifier $tableName,
public readonly array $columnNames,
) {}
}
+266
View File
@@ -0,0 +1,266 @@
<?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\Database\Schema\Parser;
use Doctrine\Common\Lexer\AbstractLexer;
/**
* Scans a MySQL CREATE TABLE statement for tokens.
*/
class Lexer extends AbstractLexer
{
// All tokens that are not valid identifiers must be < 100
public const T_NONE = 1;
public const T_STRING = 2;
public const T_INPUT_PARAMETER = 3;
public const T_CLOSE_PARENTHESIS = 4;
public const T_OPEN_PARENTHESIS = 5;
public const T_COMMA = 6;
public const T_DIVIDE = 7;
public const T_DOT = 8;
public const T_EQUALS = 9;
public const T_GREATER_THAN = 10;
public const T_LOWER_THAN = 11;
public const T_MINUS = 12;
public const T_MULTIPLY = 13;
public const T_NEGATE = 14;
public const T_PLUS = 15;
public const T_OPEN_CURLY_BRACE = 16;
public const T_CLOSE_CURLY_BRACE = 17;
public const T_SEMICOLON = 18;
// All tokens that are identifiers or keywords that could be considered as identifiers should be >= 100
public const T_IDENTIFIER = 100;
// All tokens that could be considered as a data type should be >= 200
public const T_BIT = 201;
public const T_TINYINT = 202;
public const T_SMALLINT = 203;
public const T_MEDIUMINT = 204;
public const T_INT = 205;
public const T_INTEGER = 206;
public const T_BIGINT = 207;
public const T_REAL = 208;
public const T_DOUBLE = 209;
public const T_FLOAT = 210;
public const T_DECIMAL = 211;
public const T_NUMERIC = 212;
public const T_DATE = 213;
public const T_TIME = 214;
public const T_TIMESTAMP = 215;
public const T_DATETIME = 216;
public const T_YEAR = 217;
public const T_CHAR = 218;
public const T_VARCHAR = 219;
public const T_BINARY = 220;
public const T_VARBINARY = 221;
public const T_TINYBLOB = 222;
public const T_BLOB = 223;
public const T_MEDIUMBLOB = 224;
public const T_LONGBLOB = 225;
public const T_TINYTEXT = 226;
public const T_TEXT = 227;
public const T_MEDIUMTEXT = 228;
public const T_LONGTEXT = 229;
public const T_ENUM = 230;
public const T_SET = 231;
public const T_JSON = 232;
public const T_UUID = 233;
// All keyword tokens should be >= 300
public const T_CREATE = 300;
public const T_TEMPORARY = 301;
public const T_TABLE = 302;
public const T_IF = 303;
public const T_NOT = 304;
public const T_EXISTS = 305;
public const T_CONSTRAINT = 306;
public const T_INDEX = 307;
public const T_KEY = 308;
public const T_FULLTEXT = 309;
public const T_SPATIAL = 310;
public const T_PRIMARY = 311;
public const T_UNIQUE = 312;
public const T_CHECK = 313;
public const T_DEFAULT = 314;
public const T_AUTO_INCREMENT = 315;
public const T_COMMENT = 316;
public const T_COLUMN_FORMAT = 317;
public const T_STORAGE = 318;
public const T_REFERENCES = 319;
public const T_NULL = 320;
public const T_FIXED = 321;
public const T_DYNAMIC = 322;
public const T_MEMORY = 323;
public const T_DISK = 324;
public const T_UNSIGNED = 325;
public const T_ZEROFILL = 326;
public const T_CURRENT_TIMESTAMP = 327;
public const T_CHARACTER = 328;
public const T_COLLATE = 329;
public const T_ASC = 330;
public const T_DESC = 331;
public const T_MATCH = 332;
public const T_FULL = 333;
public const T_PARTIAL = 334;
public const T_SIMPLE = 335;
public const T_ON = 336;
public const T_UPDATE = 337;
public const T_DELETE = 338;
public const T_RESTRICT = 339;
public const T_CASCADE = 340;
public const T_NO = 341;
public const T_ACTION = 342;
public const T_USING = 343;
public const T_BTREE = 344;
public const T_HASH = 345;
public const T_KEY_BLOCK_SIZE = 346;
public const T_WITH = 347;
public const T_PARSER = 348;
public const T_FOREIGN = 349;
public const T_ENGINE = 350;
public const T_AVG_ROW_LENGTH = 351;
public const T_CHECKSUM = 352;
public const T_COMPRESSION = 353;
public const T_CONNECTION = 354;
public const T_DATA = 355;
public const T_DIRECTORY = 356;
public const T_DELAY_KEY_WRITE = 357;
public const T_ENCRYPTION = 358;
public const T_INSERT_METHOD = 359;
public const T_MAX_ROWS = 360;
public const T_MIN_ROWS = 361;
public const T_PACK_KEYS = 362;
public const T_PASSWORD = 363;
public const T_ROW_FORMAT = 364;
public const T_STATS_AUTO_RECALC = 365;
public const T_STATS_PERSISTENT = 366;
public const T_STATS_SAMPLE_PAGES = 367;
public const T_TABLESPACE = 368;
public const T_UNION = 369;
public const T_PRECISION = 370;
/**
* Lexical catchable patterns.
*/
protected function getCatchablePatterns(): array
{
return [
'(?:-?[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?', // numbers
'`(?:[^`]|``)*`', // quoted identifiers
"'(?:[^']|'')*'", // quoted strings
'\)', // closing parenthesis
'[a-z0-9$_][\w$]*', // unquoted identifiers
];
}
/**
* Lexical non-catchable patterns.
*/
protected function getNonCatchablePatterns(): array
{
return ['\s+'];
}
/**
* Retrieve token type. Also processes the token value if necessary.
*
* @param string $value
*/
protected function getType(&$value): int
{
$type = self::T_NONE;
// Recognize numeric values
if (is_numeric($value)) {
if (str_contains($value, '.') || stripos($value, 'e') !== false) {
return self::T_FLOAT;
}
return self::T_INTEGER;
}
// Recognize quoted strings
if ($value[0] === "'") {
$value = str_replace("''", "'", substr($value, 1, -1));
return self::T_STRING;
}
// Recognize quoted strings
if ($value[0] === '`') {
$value = str_replace('``', '`', substr($value, 1, -1));
return self::T_IDENTIFIER;
}
// Recognize identifiers, aliased or qualified names
if (ctype_alpha($value[0])) {
$name = 'TYPO3\\CMS\\Core\\Database\\Schema\\Parser\\Lexer::T_' . strtoupper($value);
if (defined($name)) {
$type = constant($name);
if ($type > 100) {
return $type;
}
}
return self::T_STRING;
}
switch ($value) {
// Recognize symbols
case '.':
return self::T_DOT;
case ';':
return self::T_SEMICOLON;
case ',':
return self::T_COMMA;
case '(':
return self::T_OPEN_PARENTHESIS;
case ')':
return self::T_CLOSE_PARENTHESIS;
case '=':
return self::T_EQUALS;
case '>':
return self::T_GREATER_THAN;
case '<':
return self::T_LOWER_THAN;
case '+':
return self::T_PLUS;
case '-':
return self::T_MINUS;
case '*':
return self::T_MULTIPLY;
case '/':
return self::T_DIVIDE;
case '!':
return self::T_NEGATE;
case '{':
return self::T_OPEN_CURLY_BRACE;
case '}':
return self::T_CLOSE_CURLY_BRACE;
// Default
default:
// Do nothing
}
return $type;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,451 @@
<?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\Database\Schema\Parser;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Types;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateColumnDefinitionItem;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateForeignKeyDefinitionItem;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateIndexDefinitionItem;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\CreateTableStatement;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\AbstractDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BigIntDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BinaryDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\BlobDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\CharDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DateDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DateTimeDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DecimalDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\DoubleDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\EnumDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\FloatDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\IntegerDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\JsonDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\LongBlobDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\LongTextDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\MediumBlobDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\MediumIntDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\MediumTextDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\NumericDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\RealDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\SetDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\SmallIntDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TextDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TimeDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TimestampDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TinyBlobDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TinyIntDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\TinyTextDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\UuidDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\VarBinaryDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\VarCharDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\DataType\YearDataType;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\IndexColumnName;
use TYPO3\CMS\Core\Database\Schema\Parser\AST\ReferenceDefinition;
use TYPO3\CMS\Core\Database\Schema\Types\SetType;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Converts a CreateTableStatement syntax node into a Doctrine Table
* object that represents the table defined in the original SQL statement.
*/
class TableBuilder
{
/**
* @var Table
*/
protected $table;
/**
* @var AbstractPlatform
*/
protected $platform;
/**
* TableBuilder constructor.
*
* @throws \InvalidArgumentException
* @throws \Doctrine\DBAL\Exception
*/
public function __construct(?AbstractPlatform $platform = null)
{
// Register custom data types as no connection might have
// been established yet so the types would not be available
// when building tables/columns.
ConnectionPool::registerDoctrineTypes();
$this->platform = $platform ?: GeneralUtility::makeInstance(MySQLPlatform::class);
}
/**
* Create a Doctrine Table object based on the parsed MySQL SQL command.
*
* @throws \Doctrine\DBAL\Schema\SchemaException
* @throws \RuntimeException
* @throws \InvalidArgumentException
*/
public function create(CreateTableStatement $tableStatement): Table
{
$this->table = GeneralUtility::makeInstance(
Table::class,
$tableStatement->tableName->getQuotedName(),
[],
[],
[],
[],
$this->buildTableOptions($tableStatement->tableOptions)
);
foreach ($tableStatement->createDefinition->items as $item) {
switch (get_class($item)) {
case CreateColumnDefinitionItem::class:
$this->addColumn($item);
break;
case CreateIndexDefinitionItem::class:
$this->addIndex($item);
break;
case CreateForeignKeyDefinitionItem::class:
$this->addForeignKey($item);
break;
default:
throw new \RuntimeException(
'Unknown item definition of type "' . get_class($item) . '" encountered.',
1472044085
);
}
}
return $this->table;
}
/**
* @throws \Doctrine\DBAL\Schema\SchemaException
* @throws \RuntimeException
*/
protected function addColumn(CreateColumnDefinitionItem $item): Column
{
$column = $this->table->addColumn(
$item->columnName->getQuotedName(),
$this->getDoctrineColumnTypeName($item->dataType)
);
$column->setNotnull($item->allowNull === false);
$column->setAutoincrement($item->autoIncrement);
$column->setComment((string)$item->comment);
// Set default value (unless it's an auto increment column)
if ($item->hasDefaultValue && !$column->getAutoincrement()) {
$column->setDefault($item->defaultValue);
}
if ($item->dataType->getLength()) {
$column->setLength($item->dataType->getLength());
}
if ($item->dataType->getPrecision() >= 0) {
$column->setPrecision($item->dataType->getPrecision());
}
if ($item->dataType->getScale() >= 0) {
$column->setScale($item->dataType->getScale());
}
if ($item->dataType->isUnsigned()) {
$column->setUnsigned(true);
}
// Select CHAR/VARCHAR or BINARY/VARBINARY
if ($item->dataType->isFixed()) {
$column->setFixed(true);
}
if ($item->dataType instanceof SetDataType) {
$column->setValues($item->dataType->getValues());
}
if ($item->dataType instanceof EnumDataType) {
$column->setValues($item->dataType->getValues());
}
$dataTypeSupportsCharsetAndCollation = (
$item->dataType instanceof CharDataType
|| $item->dataType instanceof VarCharDataType
|| $item->dataType instanceof TextDataType
);
$options = $item->dataType->getOptions();
if ($dataTypeSupportsCharsetAndCollation && ($options['charset'] ?? null)) {
$column->setPlatformOption('charset', $options['charset']);
}
if ($dataTypeSupportsCharsetAndCollation && ($options['charset'] ?? null)) {
$column->setPlatformOption('collation', $options['collation']);
}
if ($item->index) {
$this->table->addIndex([$item->columnName->getQuotedName()]);
}
if ($item->unique) {
$this->table->addUniqueIndex([$item->columnName->getQuotedName()]);
}
if ($item->primary) {
$this->table->setPrimaryKey([$item->columnName->getQuotedName()]);
}
if ($item->reference !== null) {
$this->addForeignKeyConstraint(
[$item->columnName->getQuotedName()],
$item->reference
);
}
return $column;
}
/**
* @throws \Doctrine\DBAL\Schema\SchemaException
* @throws \InvalidArgumentException
*/
protected function addIndex(CreateIndexDefinitionItem $item): Index
{
$indexName = $item->indexName->getQuotedName();
$columnNames = array_map(
static function (IndexColumnName $columnName): string {
if ($columnName->length) {
return $columnName->columnName->getQuotedName() . '(' . $columnName->length . ')';
}
return $columnName->columnName->getQuotedName();
},
$item->columnNames
);
if ($item->isPrimary) {
$this->table->setPrimaryKey($columnNames);
$index = $this->table->getPrimaryKey();
} else {
$index = GeneralUtility::makeInstance(
Index::class,
$indexName,
$columnNames,
$item->isUnique,
$item->isPrimary
);
if ($item->isFulltext) {
$index->addFlag('fulltext');
} elseif ($item->isSpatial) {
$index->addFlag('spatial');
}
// Doctrine keys the indexes by a normalized name of its own. Do not rely on that key
// here, but build the list explicitly from the index names, so that re-defining an
// index replaces the previously added one - independent of how Doctrine keys them.
$indexes = [];
foreach ($this->table->getIndexes() as $existingIndex) {
$indexes[strtolower($existingIndex->getName())] = $existingIndex;
}
$indexes[strtolower($index->getName())] = $index;
$this->table = new Table(
$this->table->getQuotedName($this->platform),
$this->table->getColumns(),
array_values($indexes),
[],
$this->table->getForeignKeys(),
$this->table->getOptions()
);
}
return $index;
}
/**
* Prepare an explicit foreign key definition item to be added to the table being built.
*/
protected function addForeignKey(CreateForeignKeyDefinitionItem $item)
{
$indexName = $item->indexName->getQuotedName() ?: null;
$localColumnNames = array_map(
static function (IndexColumnName $columnName): string {
return $columnName->columnName->getQuotedName();
},
$item->columnNames
);
$this->addForeignKeyConstraint($localColumnNames, $item->reference, $indexName);
}
/**
* Add a foreign key constraint to the table being built.
*
* @param string[] $localColumnNames
*/
protected function addForeignKeyConstraint(
array $localColumnNames,
ReferenceDefinition $referenceDefinition,
?string $indexName = null
) {
$foreignTableName = $referenceDefinition->tableName->getQuotedName();
$foreignColumnNames = array_map(
static function (IndexColumnName $columnName): string {
return $columnName->columnName->getQuotedName();
},
$referenceDefinition->columnNames
);
$options = [
'onDelete' => $referenceDefinition->onDelete,
'onUpdate' => $referenceDefinition->onUpdate,
];
$this->table->addForeignKeyConstraint(
$foreignTableName,
$localColumnNames,
$foreignColumnNames,
$options,
$indexName
);
}
/**
* @throws \RuntimeException
*/
protected function getDoctrineColumnTypeName(AbstractDataType $dataType): string
{
switch (get_class($dataType)) {
case TinyIntDataType::class:
// TINYINT is MySQL specific and mapped to a standard SMALLINT
case SmallIntDataType::class:
$doctrineType = Types::SMALLINT;
break;
case MediumIntDataType::class:
// MEDIUMINT is MySQL specific and mapped to a standard INT
case IntegerDataType::class:
$doctrineType = Types::INTEGER;
break;
case BigIntDataType::class:
$doctrineType = Types::BIGINT;
break;
case BinaryDataType::class:
case VarBinaryDataType::class:
// CHAR/VARCHAR is determined by "fixed" column property
$doctrineType = Types::BINARY;
break;
case TinyBlobDataType::class:
case MediumBlobDataType::class:
case BlobDataType::class:
case LongBlobDataType::class:
// Actual field type is determined by field length
$doctrineType = Types::BLOB;
break;
case DateDataType::class:
$doctrineType = Types::DATE_MUTABLE;
break;
case TimestampDataType::class:
case DateTimeDataType::class:
// TIMESTAMP or DATETIME are determined by "version" column property
$doctrineType = Types::DATETIME_MUTABLE;
break;
case NumericDataType::class:
case DecimalDataType::class:
$doctrineType = Types::DECIMAL;
break;
case RealDataType::class:
case FloatDataType::class:
case DoubleDataType::class:
$doctrineType = Types::FLOAT;
break;
case TimeDataType::class:
$doctrineType = Types::TIME_MUTABLE;
break;
case TinyTextDataType::class:
case MediumTextDataType::class:
case TextDataType::class:
case LongTextDataType::class:
$doctrineType = Types::TEXT;
break;
case CharDataType::class:
case VarCharDataType::class:
$doctrineType = Types::STRING;
break;
case EnumDataType::class:
$doctrineType = Types::ENUM;
break;
case SetDataType::class:
$doctrineType = SetType::TYPE;
break;
case JsonDataType::class:
$doctrineType = Types::JSON;
break;
case YearDataType::class:
// The YEAR data type is MySQL specific and offers little to no benefit.
// The two-digit year logic implemented in this data type (1-69 mapped to
// 2001-2069, 70-99 mapped to 1970-1999) can be easily implemented in the
// application and for all other accounts it's an integer with a valid
// range of 1901 to 2155.
// Using a SMALLINT covers the value range and ensures database compatibility.
$doctrineType = Types::SMALLINT;
break;
case UuidDataType::class:
// UUID/GUID is only supported by PostgreSQL for now, but Doctrine DBAL implemented a fallback
// for other platforms and we can safely use `Types::GUID` here in case `UUID` has been set in
// `ext_tables.sql` for a table column.
$doctrineType = Types::GUID;
break;
default:
throw new \RuntimeException(
'Unsupported data type: ' . get_class($dataType) . '!',
1472046376
);
}
return $doctrineType;
}
/**
* Build the table specific options as far as they are supported by Doctrine.
*/
protected function buildTableOptions(array $tableOptions): array
{
$options = [];
if (!empty($tableOptions['engine'])) {
$options['engine'] = (string)$tableOptions['engine'];
}
if (!empty($tableOptions['character_set'])) {
$options['charset'] = (string)$tableOptions['character_set'];
}
if (!empty($tableOptions['collation'])) {
$options['collate'] = (string)$tableOptions['collation'];
}
if (!empty($tableOptions['auto_increment'])) {
$options['auto_increment'] = (string)$tableOptions['auto_increment'];
}
if (!empty($tableOptions['comment'])) {
$options['comment'] = (string)$tableOptions['comment'];
}
if (!empty($tableOptions['row_format'])) {
$options['row_format'] = (string)$tableOptions['row_format'];
}
return $options;
}
}