10c1c7615SGreg Roach<?php 23976b470SGreg Roach 30c1c7615SGreg Roach/** 40c1c7615SGreg Roach * webtrees: online genealogy 589f7189bSGreg Roach * Copyright (C) 2021 webtrees development team 60c1c7615SGreg Roach * This program is free software: you can redistribute it and/or modify 70c1c7615SGreg Roach * it under the terms of the GNU General Public License as published by 80c1c7615SGreg Roach * the Free Software Foundation, either version 3 of the License, or 90c1c7615SGreg Roach * (at your option) any later version. 100c1c7615SGreg Roach * This program is distributed in the hope that it will be useful, 110c1c7615SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 120c1c7615SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 130c1c7615SGreg Roach * GNU General Public License for more details. 140c1c7615SGreg Roach * You should have received a copy of the GNU General Public License 1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 160c1c7615SGreg Roach */ 17fcfa147eSGreg Roach 180c1c7615SGreg Roachdeclare(strict_types=1); 190c1c7615SGreg Roach 200c1c7615SGreg Roachnamespace Fisharebest\Webtrees\Services; 210c1c7615SGreg Roach 220c1c7615SGreg Roachuse Fisharebest\Webtrees\Schema\MigrationInterface; 230c1c7615SGreg Roachuse Fisharebest\Webtrees\Schema\SeedDefaultResnTable; 240c1c7615SGreg Roachuse Fisharebest\Webtrees\Schema\SeedGedcomSettingTable; 250c1c7615SGreg Roachuse Fisharebest\Webtrees\Schema\SeedGedcomTable; 260c1c7615SGreg Roachuse Fisharebest\Webtrees\Schema\SeedSiteSettingTable; 270c1c7615SGreg Roachuse Fisharebest\Webtrees\Schema\SeedUserTable; 280c1c7615SGreg Roachuse Fisharebest\Webtrees\Site; 29415cca73SGreg Roachuse Illuminate\Database\Capsule\Manager as DB; 300c1c7615SGreg Roachuse PDOException; 310c1c7615SGreg Roach 320c1c7615SGreg Roach/** 330c1c7615SGreg Roach * Update the database schema. 340c1c7615SGreg Roach */ 350c1c7615SGreg Roachclass MigrationService 360c1c7615SGreg Roach{ 370c1c7615SGreg Roach /** 380c1c7615SGreg Roach * Run a series of scripts to bring the database schema up to date. 390c1c7615SGreg Roach * 400c1c7615SGreg Roach * @param string $namespace Where to find our MigrationXXX classes 410c1c7615SGreg Roach * @param string $schema_name Which schema to update. 42415cca73SGreg Roach * @param int $target_version Upgrade to this version 430c1c7615SGreg Roach * 440c1c7615SGreg Roach * @return bool Were any updates applied 45*24f2a3afSGreg Roach * @throws PDOException 460c1c7615SGreg Roach */ 47*24f2a3afSGreg Roach public function updateSchema(string $namespace, string $schema_name, int $target_version): bool 480c1c7615SGreg Roach { 490c1c7615SGreg Roach try { 500c1c7615SGreg Roach $current_version = (int) Site::getPreference($schema_name); 510c1c7615SGreg Roach } catch (PDOException $ex) { 520c1c7615SGreg Roach // During initial installation, the site_preference table won’t exist. 530c1c7615SGreg Roach $current_version = 0; 540c1c7615SGreg Roach } 550c1c7615SGreg Roach 562289e30bSGreg Roach if ($current_version < $target_version) { 572289e30bSGreg Roach try { 582289e30bSGreg Roach $this->transactionalTables(); 592289e30bSGreg Roach } catch (PDOException $ex) { 602289e30bSGreg Roach // There is probably nothing we can do. 612289e30bSGreg Roach } 622289e30bSGreg Roach } 632289e30bSGreg Roach 640c1c7615SGreg Roach $updates_applied = false; 650c1c7615SGreg Roach 660c1c7615SGreg Roach // Update the schema, one version at a time. 670c1c7615SGreg Roach while ($current_version < $target_version) { 680c1c7615SGreg Roach $class = $namespace . '\\Migration' . $current_version; 690c1c7615SGreg Roach /** @var MigrationInterface $migration */ 700c1c7615SGreg Roach $migration = new $class(); 710c1c7615SGreg Roach $migration->upgrade(); 720c1c7615SGreg Roach $current_version++; 730c1c7615SGreg Roach Site::setPreference($schema_name, (string) $current_version); 740c1c7615SGreg Roach $updates_applied = true; 750c1c7615SGreg Roach } 760c1c7615SGreg Roach 770c1c7615SGreg Roach return $updates_applied; 780c1c7615SGreg Roach } 790c1c7615SGreg Roach 800c1c7615SGreg Roach /** 81415cca73SGreg Roach * Upgrades from older installations may have MyISAM or other non-transactional tables. 82415cca73SGreg Roach * These could prevent us from creating foreign key constraints. 83415cca73SGreg Roach * 84415cca73SGreg Roach * @return void 85415cca73SGreg Roach * @throws PDOException 86415cca73SGreg Roach */ 87415cca73SGreg Roach private function transactionalTables(): void 88415cca73SGreg Roach { 89415cca73SGreg Roach $connection = DB::connection(); 90415cca73SGreg Roach 91415cca73SGreg Roach if ($connection->getDriverName() !== 'mysql') { 92415cca73SGreg Roach return; 93415cca73SGreg Roach } 94415cca73SGreg Roach 95415cca73SGreg Roach $sql = "SELECT table_name FROM information_schema.tables JOIN information_schema.engines USING (engine) WHERE table_schema = ? AND LEFT(table_name, ?) = ? AND transactions <> 'YES'"; 96415cca73SGreg Roach 97415cca73SGreg Roach $bindings = [ 98415cca73SGreg Roach $connection->getDatabaseName(), 99415cca73SGreg Roach mb_strlen($connection->getTablePrefix()), 100415cca73SGreg Roach $connection->getTablePrefix(), 101415cca73SGreg Roach ]; 102415cca73SGreg Roach 103415cca73SGreg Roach $rows = DB::connection()->select($sql, $bindings); 104415cca73SGreg Roach 105415cca73SGreg Roach foreach ($rows as $row) { 106415cca73SGreg Roach $table = $row->TABLE_NAME ?? $row->table_name; 107415cca73SGreg Roach $alter_sql = 'ALTER TABLE `' . $table . '` ENGINE=InnoDB'; 108415cca73SGreg Roach DB::connection()->statement($alter_sql); 109415cca73SGreg Roach } 110415cca73SGreg Roach } 111415cca73SGreg Roach 112415cca73SGreg Roach /** 1130c1c7615SGreg Roach * Write default data to the database. 1140c1c7615SGreg Roach * 1150c1c7615SGreg Roach * @return void 1160c1c7615SGreg Roach */ 1170c1c7615SGreg Roach public function seedDatabase(): void 1180c1c7615SGreg Roach { 1190c1c7615SGreg Roach (new SeedSiteSettingTable())->run(); 1200c1c7615SGreg Roach (new SeedUserTable())->run(); 1210c1c7615SGreg Roach (new SeedGedcomTable())->run(); 1220c1c7615SGreg Roach (new SeedGedcomSettingTable())->run(); 1230c1c7615SGreg Roach (new SeedDefaultResnTable())->run(); 1240c1c7615SGreg Roach } 1250c1c7615SGreg Roach} 126