Passed
Push — master ( 419ce1...415cca )
by Greg
06:23
created

MigrationService   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 87
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 35
dl 0
loc 87
rs 10
c 0
b 0
f 0
wmc 8

3 Methods

Rating   Name   Duplication   Size   Complexity  
A seedDatabase() 0 7 1
A transactionalTables() 0 22 3
A updateSchema() 0 29 4
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
 */
17
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Services;
21
22
use Fisharebest\Webtrees\Schema\MigrationInterface;
23
use Fisharebest\Webtrees\Schema\SeedDefaultResnTable;
24
use Fisharebest\Webtrees\Schema\SeedGedcomSettingTable;
25
use Fisharebest\Webtrees\Schema\SeedGedcomTable;
26
use Fisharebest\Webtrees\Schema\SeedSiteSettingTable;
27
use Fisharebest\Webtrees\Schema\SeedUserTable;
28
use Fisharebest\Webtrees\Site;
29
use Illuminate\Database\Capsule\Manager as DB;
30
use PDOException;
31
32
/**
33
 * Update the database schema.
34
 */
35
class MigrationService
36
{
37
    /**
38
     * Run a series of scripts to bring the database schema up to date.
39
     *
40
     * @param string $namespace      Where to find our MigrationXXX classes
41
     * @param string $schema_name    Which schema to update.
42
     * @param int    $target_version Upgrade to this version
43
     *
44
     * @throws PDOException
45
     * @return bool  Were any updates applied
46
     */
47
    public function updateSchema($namespace, $schema_name, $target_version): bool
48
    {
49
        try {
50
            $this->transactionalTables();
51
        } catch (PDOException $ex) {
52
            // There is probably nothing we can do.
53
        }
54
55
        try {
56
            $current_version = (int) Site::getPreference($schema_name);
57
        } catch (PDOException $ex) {
58
            // During initial installation, the site_preference table won’t exist.
59
            $current_version = 0;
60
        }
61
62
        $updates_applied = false;
63
64
        // Update the schema, one version at a time.
65
        while ($current_version < $target_version) {
66
            $class = $namespace . '\\Migration' . $current_version;
67
            /** @var MigrationInterface $migration */
68
            $migration = new $class();
69
            $migration->upgrade();
70
            $current_version++;
71
            Site::setPreference($schema_name, (string) $current_version);
72
            $updates_applied = true;
73
        }
74
75
        return $updates_applied;
76
    }
77
78
    /**
79
     * Upgrades from older installations may have MyISAM or other non-transactional tables.
80
     * These could prevent us from creating foreign key constraints.
81
     *
82
     * @return void
83
     * @throws PDOException
84
     */
85
    private function transactionalTables(): void
86
    {
87
        $connection = DB::connection();
88
89
        if ($connection->getDriverName() !== 'mysql') {
90
            return;
91
        }
92
93
        $sql = "SELECT table_name FROM information_schema.tables JOIN information_schema.engines USING (engine) WHERE table_schema = ? AND LEFT(table_name, ?) = ? AND transactions <> 'YES'";
94
95
        $bindings = [
96
            $connection->getDatabaseName(),
97
            mb_strlen($connection->getTablePrefix()),
98
            $connection->getTablePrefix(),
99
        ];
100
101
        $rows = DB::connection()->select($sql, $bindings);
102
103
        foreach ($rows as $row) {
104
            $table = $row->TABLE_NAME ?? $row->table_name;
105
            $alter_sql = 'ALTER TABLE `' . $table . '` ENGINE=InnoDB';
106
            DB::connection()->statement($alter_sql);
107
        }
108
    }
109
110
    /**
111
     *  Write default data to the database.
112
     *
113
     * @return void
114
     */
115
    public function seedDatabase(): void
116
    {
117
        (new SeedSiteSettingTable())->run();
118
        (new SeedUserTable())->run();
119
        (new SeedGedcomTable())->run();
120
        (new SeedGedcomSettingTable())->run();
121
        (new SeedDefaultResnTable())->run();
122
    }
123
}
124