1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2019 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17declare(strict_types=1); 18 19namespace Fisharebest\Webtrees\Schema; 20 21use Illuminate\Database\Capsule\Manager as DB; 22use Illuminate\Database\Schema\Blueprint; 23 24/** 25 * Upgrade the database schema from version 0 (empty database) to version 1. 26 */ 27class Migration0 implements MigrationInterface 28{ 29 /** 30 * Upgrade to to the next version. 31 * 32 * @return void 33 */ 34 public function upgrade(): void 35 { 36 DB::schema()->create('gedcom', static function (Blueprint $table): void { 37 $table->integer('gedcom_id', true); 38 $table->string('gedcom_name', 255); 39 $table->integer('sort_order')->default(0); 40 41 $table->unique('gedcom_name'); 42 $table->index('sort_order'); 43 }); 44 45 DB::schema()->create('site_setting', static function (Blueprint $table): void { 46 $table->string('setting_name', 32); 47 $table->string('setting_value', 2000); 48 49 $table->primary('setting_name'); 50 }); 51 52 DB::schema()->create('gedcom_setting', static function (Blueprint $table): void { 53 $table->integer('gedcom_id'); 54 $table->string('setting_name', 32); 55 $table->string('setting_value', 255); 56 57 $table->primary(['gedcom_id', 'setting_name']); 58 59 $table->foreign('gedcom_id')->references('gedcom_id')->on('gedcom'); 60 }); 61 62 DB::schema()->create('user', static function (Blueprint $table): void { 63 $table->integer('user_id', true); 64 $table->string('user_name', 32); 65 $table->string('real_name', 64); 66 $table->string('email', 64); 67 $table->string('password', 128); 68 69 $table->unique('user_name'); 70 $table->unique('email'); 71 }); 72 73 DB::schema()->create('user_setting', static function (Blueprint $table): void { 74 $table->integer('user_id'); 75 $table->string('setting_name', 32); 76 $table->string('setting_value', 255); 77 78 $table->primary(['user_id', 'setting_name']); 79 80 $table->foreign('user_id')->references('user_id')->on('user'); 81 }); 82 83 DB::schema()->create('user_gedcom_setting', static function (Blueprint $table): void { 84 $table->integer('user_id'); 85 $table->integer('gedcom_id'); 86 $table->string('setting_name', 32); 87 $table->string('setting_value', 255); 88 89 // Default constraint names are too long for MySQL. 90 $key = DB::connection()->getTablePrefix() . $table->getTable() . '_primary'; 91 92 $table->primary(['user_id', 'gedcom_id', 'setting_name'], $key); 93 $table->index('gedcom_id'); 94 95 $table->foreign('user_id')->references('user_id')->on('user'); 96 $table->foreign('gedcom_id')->references('gedcom_id')->on('gedcom'); 97 }); 98 99 DB::schema()->create('log', static function (Blueprint $table): void { 100 $table->integer('log_id', true); 101 $table->timestamp('log_time')->useCurrent(); 102 $table->enum('log_type', ['auth', 'config', 'debug', 'edit', 'error', 'media', 'search']); 103 $table->longText('log_message'); 104 $table->ipAddress('ip_address'); 105 $table->integer('user_id')->nullable(); 106 $table->integer('gedcom_id')->nullable(); 107 108 $table->index('log_time'); 109 $table->index('log_type'); 110 $table->index('ip_address'); 111 $table->index('user_id'); 112 $table->index('gedcom_id'); 113 114 $table->foreign('user_id')->references('user_id')->on('user'); 115 $table->foreign('gedcom_id')->references('gedcom_id')->on('gedcom'); 116 }); 117 118 DB::schema()->create('change', static function (Blueprint $table): void { 119 $table->integer('change_id', true); 120 $table->timestamp('change_time')->useCurrent(); 121 $table->enum('status', ['accepted', 'pending', 'rejected'])->default('pending'); 122 $table->integer('gedcom_id'); 123 $table->string('xref', 20); 124 $table->longText('old_gedcom'); 125 $table->longText('new_gedcom'); 126 $table->integer('user_id'); 127 128 $table->index(['gedcom_id', 'status', 'xref']); 129 $table->index('user_id'); 130 131 $table->foreign('user_id')->references('user_id')->on('user'); 132 $table->foreign('gedcom_id')->references('gedcom_id')->on('gedcom'); 133 }); 134 135 DB::schema()->create('message', static function (Blueprint $table): void { 136 $table->integer('message_id', true); 137 $table->string('sender', 64); 138 $table->ipAddress('ip_address'); 139 $table->integer('user_id'); 140 $table->string('subject', 255); 141 $table->longText('body'); 142 $table->timestamp('created')->useCurrent(); 143 144 $table->index('user_id'); 145 146 $table->foreign('user_id')->references('user_id')->on('user'); 147 }); 148 149 DB::schema()->create('default_resn', static function (Blueprint $table): void { 150 $table->integer('default_resn_id', true); 151 $table->integer('gedcom_id'); 152 $table->string('xref', 20)->nullable(); 153 $table->string('tag_type', 15)->nullable(); 154 $table->enum('resn', ['none', 'privacy', 'confidential', 'hidden']); 155 $table->string('comment', 255)->nullable(); 156 $table->timestamp('updated')->useCurrent(); 157 158 $table->unique(['gedcom_id', 'xref', 'tag_type']); 159 160 $table->foreign('gedcom_id')->references('gedcom_id')->on('gedcom'); 161 }); 162 163 DB::schema()->create('individuals', static function (Blueprint $table): void { 164 $table->string('i_id', 20); 165 $table->integer('i_file'); 166 $table->string('i_rin', 20); 167 $table->enum('i_sex', ['U', 'M', 'F']); 168 $table->longText('i_gedcom'); 169 170 $table->primary(['i_id', 'i_file']); 171 $table->unique(['i_file', 'i_id']); 172 }); 173 174 DB::schema()->create('families', static function (Blueprint $table): void { 175 $table->string('f_id', 20); 176 $table->integer('f_file'); 177 $table->string('f_husb', 20)->nullable(); 178 $table->string('f_wife', 20)->nullable(); 179 $table->longText('f_gedcom'); 180 $table->integer('f_numchil'); 181 182 $table->primary(['f_id', 'f_file']); 183 $table->unique(['f_file', 'f_id']); 184 $table->index('f_husb'); 185 $table->index('f_wife'); 186 }); 187 188 DB::schema()->create('places', static function (Blueprint $table): void { 189 $table->integer('p_id', true); 190 $table->string('p_place', 150); 191 $table->integer('p_parent_id')->nullable(); 192 $table->integer('p_file'); 193 $table->longText('p_std_soundex')->nullable(); 194 $table->longText('p_dm_soundex')->nullable(); 195 196 $table->index(['p_file', 'p_place']); 197 $table->unique(['p_parent_id', 'p_file', 'p_place']); 198 }); 199 200 DB::schema()->create('placelinks', static function (Blueprint $table): void { 201 $table->integer('pl_p_id'); 202 $table->string('pl_gid', 20); 203 $table->integer('pl_file'); 204 205 $table->primary(['pl_p_id', 'pl_gid', 'pl_file']); 206 $table->index('pl_p_id'); 207 $table->index('pl_gid'); 208 $table->index('pl_file'); 209 }); 210 211 DB::schema()->create('dates', static function (Blueprint $table): void { 212 $table->tinyInteger('d_day'); 213 $table->char('d_month', 5)->nullable(); 214 $table->tinyInteger('d_mon'); 215 $table->smallInteger('d_year'); 216 $table->mediumInteger('d_julianday1'); 217 $table->mediumInteger('d_julianday2'); 218 $table->string('d_fact', 15); 219 $table->string('d_gid', 20); 220 $table->integer('d_file'); 221 $table->enum('d_type', ['@#DGREGORIAN@', '@#DJULIAN@', '@#DHEBREW@', '@#DFRENCH R@', '@#DHIJRI@', '@#DROMAN@', '@#DJALALI@']); 222 223 $table->index('d_day'); 224 $table->index('d_month'); 225 $table->index('d_mon'); 226 $table->index('d_year'); 227 $table->index('d_julianday1'); 228 $table->index('d_julianday2'); 229 $table->index('d_gid'); 230 $table->index('d_file'); 231 $table->index('d_type'); 232 $table->index(['d_fact', 'd_gid']); 233 }); 234 235 DB::schema()->create('media', static function (Blueprint $table): void { 236 $table->string('m_id', 20); 237 $table->string('m_ext', 6)->nullable(); 238 $table->string('m_type', 20)->nullable(); 239 $table->string('m_titl', 248)->nullable(); 240 $table->string('m_filename', 248)->nullable(); 241 $table->integer('m_file'); 242 $table->longText('m_gedcom')->nullable(); 243 244 $table->primary(['m_file', 'm_id']); 245 $table->unique(['m_id', 'm_file']); 246 $table->index(['m_ext', 'm_type']); 247 }); 248 249 DB::schema()->create('next_id', static function (Blueprint $table): void { 250 $table->integer('gedcom_id'); 251 $table->string('record_type', 15); 252 $table->decimal('next_id', 20, 0); 253 254 $table->primary(['gedcom_id', 'record_type']); 255 256 $table->foreign('gedcom_id')->references('gedcom_id')->on('gedcom'); 257 }); 258 259 DB::schema()->create('other', static function (Blueprint $table): void { 260 $table->string('o_id', 20); 261 $table->integer('o_file'); 262 $table->string('o_type', 15); 263 $table->longText('o_gedcom'); 264 265 $table->primary(['o_id', 'o_file']); 266 $table->unique(['o_file', 'o_id']); 267 }); 268 269 DB::schema()->create('sources', static function (Blueprint $table): void { 270 $table->string('s_id', 20); 271 $table->integer('s_file'); 272 $table->string('s_name', 255); 273 $table->longText('s_gedcom'); 274 275 $table->primary(['s_id', 's_file']); 276 $table->unique(['s_file', 's_id']); 277 $table->index('s_name'); 278 }); 279 280 DB::schema()->create('link', static function (Blueprint $table): void { 281 $table->integer('l_file'); 282 $table->string('l_from', 20); 283 $table->string('l_type', 15); 284 $table->string('l_to', 20); 285 286 $table->primary(['l_from', 'l_file', 'l_type', 'l_to']); 287 $table->unique(['l_to', 'l_file', 'l_type', 'l_from']); 288 }); 289 290 DB::schema()->create('name', static function (Blueprint $table): void { 291 $table->integer('n_file'); 292 $table->string('n_id', 20); 293 $table->integer('n_num'); 294 $table->string('n_type', 15); 295 $table->string('n_sort', 255); 296 $table->string('n_full', 255); 297 $table->string('n_surname', 255)->nullable(); 298 $table->string('n_surn', 255)->nullable(); 299 $table->string('n_givn', 255)->nullable(); 300 $table->string('n_soundex_givn_std', 255)->nullable(); 301 $table->string('n_soundex_surn_std', 255)->nullable(); 302 $table->string('n_soundex_givn_dm', 255)->nullable(); 303 $table->string('n_soundex_surn_dm', 255)->nullable(); 304 305 $table->primary(['n_id', 'n_file', 'n_num']); 306 $table->index(['n_full', 'n_id', 'n_file']); 307 $table->index(['n_surn', 'n_file', 'n_type', 'n_id']); 308 $table->index(['n_givn', 'n_file', 'n_type', 'n_id']); 309 }); 310 311 DB::schema()->create('module', static function (Blueprint $table): void { 312 $table->string('module_name', 32); 313 $table->enum('status', ['enabled', 'disabled'])->default('enabled'); 314 $table->integer('tab_order')->nullable(); 315 $table->integer('menu_order')->nullable(); 316 $table->integer('sidebar_order')->nullable(); 317 318 $table->primary('module_name'); 319 }); 320 321 DB::schema()->create('module_setting', static function (Blueprint $table): void { 322 $table->string('module_name', 32); 323 $table->string('setting_name', 32); 324 $table->longText('setting_value'); 325 326 $table->primary(['module_name', 'setting_name']); 327 328 $table->foreign('module_name')->references('module_name')->on('module'); 329 }); 330 331 DB::schema()->create('module_privacy', static function (Blueprint $table): void { 332 $table->string('module_name', 32); 333 $table->integer('gedcom_id'); 334 $table->enum('component', ['block', 'chart', 'menu', 'report', 'sidebar', 'tab', 'theme']); 335 $table->tinyInteger('access_level'); 336 337 // Default constraint names are too long for MySQL. 338 $key0 = DB::connection()->getTablePrefix() . $table->getTable() . '_primary'; 339 $key1 = DB::connection()->getTablePrefix() . $table->getTable() . '_ix1'; 340 341 $table->primary(['module_name', 'gedcom_id', 'component'], $key0); 342 $table->unique(['gedcom_id', 'module_name', 'component'], $key1); 343 344 $table->foreign('module_name')->references('module_name')->on('module'); 345 $table->foreign('gedcom_id')->references('gedcom_id')->on('gedcom'); 346 }); 347 348 DB::schema()->create('block', static function (Blueprint $table): void { 349 $table->integer('block_id', true); 350 $table->integer('gedcom_id')->nullable(); 351 $table->integer('user_id')->nullable(); 352 $table->string('xref', 20)->nullable(); 353 $table->enum('location', ['main', 'side'])->nullable(); 354 $table->integer('block_order'); 355 $table->string('module_name', 32); 356 357 $table->index('module_name'); 358 $table->index('gedcom_id'); 359 $table->index('user_id'); 360 361 $table->foreign('module_name')->references('module_name')->on('module'); 362 $table->foreign('gedcom_id')->references('gedcom_id')->on('gedcom'); 363 $table->foreign('user_id')->references('user_id')->on('user'); 364 }); 365 366 DB::schema()->create('block_setting', static function (Blueprint $table): void { 367 $table->integer('block_id'); 368 $table->string('setting_name', 32); 369 $table->longText('setting_value'); 370 371 $table->primary(['block_id', 'setting_name']); 372 373 $table->foreign('block_id')->references('block_id')->on('block'); 374 }); 375 376 DB::schema()->create('hit_counter', static function (Blueprint $table): void { 377 $table->integer('gedcom_id'); 378 $table->string('page_name', 32); 379 $table->string('page_parameter', 32); 380 $table->integer('page_count'); 381 382 // Default constraint names are too long for MySQL. 383 $key = DB::connection()->getTablePrefix() . $table->getTable() . '_primary'; 384 385 $table->primary(['gedcom_id', 'page_name', 'page_parameter'], $key); 386 387 $table->foreign('gedcom_id')->references('gedcom_id')->on('gedcom'); 388 }); 389 390 DB::schema()->create('session', static function (Blueprint $table): void { 391 $table->string('session_id', 32); 392 $table->timestamp('session_time')->useCurrent(); 393 $table->integer('user_id'); 394 $table->ipAddress('ip_address'); 395 $table->binary('session_data'); 396 397 $table->primary('session_id'); 398 $table->index('session_time'); 399 $table->index(['user_id', 'ip_address']); 400 }); 401 402 // See https://github.com/laravel/framework/issues/3544 403 if (DB::connection()->getDriverName() === 'mysql') { 404 $table = DB::connection()->getSchemaGrammar()->wrapTable('session'); 405 $sql = 'ALTER TABLE ' . $table . ' MODIFY session_data LONGBLOB'; 406 DB::connection()->statement($sql); 407 } 408 409 DB::schema()->create('gedcom_chunk', static function (Blueprint $table): void { 410 $table->integer('gedcom_chunk_id', true); 411 $table->integer('gedcom_id'); 412 $table->binary('chunk_data'); 413 $table->boolean('imported')->default(0); 414 415 $table->index(['gedcom_id', 'imported']); 416 417 $table->foreign('gedcom_id')->references('gedcom_id')->on('gedcom'); 418 }); 419 420 // See https://github.com/laravel/framework/issues/3544 421 if (DB::connection()->getDriverName() === 'mysql') { 422 $table = DB::connection()->getSchemaGrammar()->wrapTable('gedcom_chunk'); 423 $sql = 'ALTER TABLE ' . $table . ' MODIFY chunk_data LONGBLOB'; 424 DB::connection()->statement($sql); 425 } 426 } 427} 428