3 namespace wcf\system\database\table
;
5 use wcf\system\application\ApplicationHandler
;
6 use wcf\system\database\editor\DatabaseEditor
;
7 use wcf\system\database\table\column\IDatabaseTableColumn
;
8 use wcf\system\database\table\index\DatabaseTableForeignKey
;
9 use wcf\system\database\table\index\DatabaseTableIndex
;
12 * PHP representation of an existing database table or the intended layout of an non-existing or
13 * existing database table.
15 * @author Alexander Ebert, Matthias Schmidt
16 * @copyright 2001-2019 WoltLab GmbH
17 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
18 * @package WoltLabSuite\Core\System\Database\Table
23 use TDroppableDatabaseComponent
;
26 * intended database table's columns
27 * @var IDatabaseTableColumn[]
29 protected array $columns = [];
32 * intended database table's foreign keys
33 * @var DatabaseTableForeignKey[]
35 protected array $foreignKeys = [];
38 * intended database table's indices
39 * @var DatabaseTableIndex[]
41 protected array $indices = [];
44 * name of the database table
46 protected string $name;
49 * Creates a new instance of `DatabaseTable`.
51 * @param string $name name of the database table
53 protected function __construct(string $name)
55 $this->name
= ApplicationHandler
::insertRealDatabaseTableNames($name, true);
59 * Sets the columns of the database table.
61 * @param IDatabaseTableColumn[] $columns added/dropped columns
62 * @return $this this database table
63 * @throws \InvalidArgumentException if any column is invalid or duplicate column names exist
65 public function columns(array $columns): static
68 foreach ($columns as $column) {
69 if (!($column instanceof IDatabaseTableColumn
)) {
70 throw new \
InvalidArgumentException(
71 "Added columns have to be instances of '" . IDatabaseTableColumn
::class . "'."
75 if (isset($this->columns
[$column->getName()])) {
76 throw new \
InvalidArgumentException("Duplicate column with name '{$column->getName()}'.");
79 $this->columns
[$column->getName()] = $column;
86 * Sets the foreign keys of the database table.
88 * @param DatabaseTableForeignKey[] $foreignKeys added/dropped foreign keys
89 * @return $this this database table
90 * @throws \InvalidArgumentException if any foreign key is invalid or duplicate foreign key names exist
92 public function foreignKeys(array $foreignKeys): static
94 $this->foreignKeys
= [];
95 foreach ($foreignKeys as $foreignKey) {
96 if (!($foreignKey instanceof DatabaseTableForeignKey
)) {
97 throw new \
InvalidArgumentException(
98 "Added foreign keys have to be instances of '" . DatabaseTableForeignKey
::class . "'."
102 if ($foreignKey->getColumns() === []) {
103 throw new \
InvalidArgumentException("Missing columns for foreign key.");
106 if ($foreignKey->getName() === '') {
107 $foreignKey->name(\
md5($this->getName() . '_' . $foreignKey->getColumns()[0]) . '_fk');
110 if (isset($this->foreignKeys
[$foreignKey->getName()])) {
111 throw new \
InvalidArgumentException("Duplicate foreign key with name '{$foreignKey->getName()}'.");
114 if ($foreignKey->getOnDelete() === null && $foreignKey->getOnUpdate() === null) {
115 throw new \
InvalidArgumentException("Missing action for foreign key '{$foreignKey->getName()}'.");
118 $this->foreignKeys
[$foreignKey->getName()] = $foreignKey;
125 * Returns the columns of the table.
127 * @return IDatabaseTableColumn[]
129 public function getColumns(): array
131 return $this->columns
;
135 * Returns the foreign keys of the table.
137 * @return DatabaseTableForeignKey[]
139 public function getForeignKeys(): array
141 return $this->foreignKeys
;
145 * Returns the indices of the table.
147 * @return DatabaseTableIndex[]
149 public function getIndices(): array
151 return $this->indices
;
155 * Returns the name of the database table.
157 * @return string database table name
159 public function getName(): string
165 * Returns a `DatabaseTable` object with the given name.
167 public static function create(string $tableName): static
169 return new static($tableName);
173 * Returns a `DatabaseTable` object for an existing database table with the given name.
175 public static function createFromExistingTable(DatabaseEditor
$dbEditor, string $tableName): static
177 $table = new static($tableName);
180 foreach ($dbEditor->getColumns($tableName) as $columnData) {
181 $className = 'wcf\system\database\table\column\\' . \
ucfirst(\
strtolower($columnData['data']['type'])) . 'DatabaseTableColumn';
182 if (!\
class_exists($className)) {
183 throw new \
InvalidArgumentException(
184 "Unknown database table column type '{$columnData['data']['type']}'."
188 $columns[$columnData['name']] = $className::createFromData($columnData['name'], $columnData['data']);
190 $table->columns($columns);
193 foreach ($dbEditor->getForeignKeys($tableName) as $foreignKeysName => $foreignKeyData) {
194 $foreignKeys[$foreignKeysName] = DatabaseTableForeignKey
::createFromData(
199 $table->foreignKeys($foreignKeys);
202 foreach ($dbEditor->getIndexInformation($tableName) as $indexName => $indexData) {
203 if (!isset($foreignKeys[$indexName])) {
204 $indices[$indexName] = DatabaseTableIndex
::createFromData($indexName, $indexData);
207 $table->indices($indices);
213 * Sets the indices of the database table.
215 * @param DatabaseTableIndex[] $indices added/dropped indices
216 * @return $this this database table
217 * @throws \InvalidArgumentException if any index is invalid or duplicate index key names exist
219 public function indices(array $indices): static
222 foreach ($indices as $index) {
223 if (!($index instanceof DatabaseTableIndex
)) {
224 throw new \
InvalidArgumentException(
225 "Added indices have to be instances of '" . DatabaseTableIndex
::class . "'."
229 if ($index->getName() === '') {
230 $index->generatedName(\
md5($this->getName() . '_' . $index->getColumns()[0]));
233 if (isset($this->indices
[$index->getName()])) {
234 throw new \
InvalidArgumentException("Duplicate index with name '{$index->getName()}'.");
237 $this->indices
[$index->getName()] = $index;