Failed Conditions
Push — master ( 340cc5...02656c )
by Adrien
07:49
created

AbstractDatabase::loadTestUsers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Service;
6
7
/**
8
 * Tool to reload the entire local database from remote database for a given site
9
 * Requirements:
10
 * - ssh access to remote server (via ~/.ssh/config)
11
 * - both local and remote sites must be accesible via: /sites/MY_SITE
12
 * - both local and remote config/autoload/local.php files must contains the database connection info
13
 */
14
abstract class AbstractDatabase
15
{
16
    /**
17
     * Dump data from database on $remote server
18
     *
19
     * @param string $remote
20
     * @param string $dumpFile path
21
     */
22
    private static function dumpDataRemotely(string $remote, string $dumpFile): void
23
    {
24
        $sshCmd = <<<STRING
25
        ssh $remote "cd /sites/$remote/ && php7.1 bin/dump-data.php $dumpFile"
26
STRING;
27
28
        echo "dumping data $dumpFile on $remote...\n";
29
        self::executeLocalCommand($sshCmd);
30
    }
31
32
    /**
33
     * Dump data from database
34
     *
35
     * @param string $dumpFile path
36
     */
37
    public static function dumpData(string $dumpFile): void
38
    {
39
        $config = require 'config/autoload/local.php';
40
        $dbConfig = $config['doctrine']['connection']['orm_default']['params'];
41
        $host = $dbConfig['host'];
42
        $username = $dbConfig['user'];
43
        $database = $dbConfig['dbname'];
44
        $password = $dbConfig['password'];
45
46
        echo "dumping $dumpFile...\n";
47
        $dumpCmd = "mysqldump -v --user=$username --password=$password --host=$host $database | gzip > $dumpFile";
48
        self::executeLocalCommand($dumpCmd);
49
    }
50
51
    /**
52
     * Copy a file from $remote
53
     *
54
     * @param string $remote
55
     * @param string $dumpFile
56
     */
57
    private static function copyFile(string $remote, string $dumpFile): void
58
    {
59
        $copyCmd = <<<STRING
60
        scp $remote:$dumpFile $dumpFile
61
STRING;
62
63
        echo "copying dump to $dumpFile ...\n";
64
        self::executeLocalCommand($copyCmd);
65
    }
66
67
    /**
68
     * Load SQL dump in local database
69
     *
70
     * @param string $dumpFile
71
     */
72
    public static function loadData(string $dumpFile): void
73
    {
74
        $config = require 'config/autoload/local.php';
75
        $dbConfig = $config['doctrine']['connection']['orm_default']['params'];
76
        $host = $dbConfig['host'];
77
        $username = $dbConfig['user'];
78
        $database = $dbConfig['dbname'];
79
        $password = $dbConfig['password'];
80
81
        $dumpFile = realpath($dumpFile);
82
        echo "loading dump $dumpFile...\n";
83
        if (!is_readable($dumpFile)) {
84
            throw new \Exception("Cannot read dump file \"$dumpFile\"");
85
        }
86
87
        self::executeLocalCommand(PHP_BINARY . ' ./vendor/bin/doctrine orm:schema-tool:drop --ansi --full-database --force');
88
        self::executeLocalCommand("gunzip -c \"$dumpFile\" | mysql --user=$username --password=$password --host=$host $database");
89
        self::executeLocalCommand(PHP_BINARY . ' ./vendor/bin/doctrine-migrations --ansi migrations:migrate --no-interaction');
90
        self::loadTriggers();
91
        self::loadTestUsers();
92
    }
93
94
    public static function loadRemoteData(string $remote): void
95
    {
96
        $dumpFile = "/tmp/$remote." . exec('whoami') . '.backup.sql.gz';
97
        self::dumpDataRemotely($remote, $dumpFile);
98
        self::copyFile($remote, $dumpFile);
99
        self::loadData($dumpFile);
100
101
        echo "database updated\n";
102
    }
103
104
    /**
105
     * Execute a shell command and throw exception if fails
106
     *
107
     * @param string $command
108
     *
109
     * @throws \Exception
110
     */
111 2
    public static function executeLocalCommand(string $command): void
112
    {
113 2
        $return_var = null;
114 2
        $fullCommand = "$command 2>&1";
115 2
        passthru($fullCommand, $return_var);
116 2
        if ($return_var) {
117
            throw new \Exception('FAILED executing: ' . $command);
118
        }
119 2
    }
120
121
    /**
122
     * Load test data
123
     */
124
    public static function loadTestData(): void
125
    {
126
        self::executeLocalCommand(PHP_BINARY . ' ./vendor/bin/doctrine orm:schema-tool:drop --ansi --full-database --force');
127
        self::executeLocalCommand(PHP_BINARY . ' ./vendor/bin/doctrine-migrations migrations:migrate --ansi --no-interaction');
128
        self::loadTestUsers();
129
        self::importFile('tests/data/fixture.sql');
130
        self::loadTriggers();
131
    }
132
133
    /**
134
     * Load triggers
135
     */
136
    public static function loadTriggers(): void
137
    {
138
        self::importFile('data/triggers.sql');
139
    }
140
141
    /**
142
     * Load test users
143
     */
144
    private static function loadTestUsers(): void
145
    {
146
        self::importFile('tests/data/users.sql');
147
    }
148
149
    /**
150
     * Import a SQL file into DB
151
     *
152
     * This use mysql command, instead of DBAL methods, to allow to see errors if any, and
153
     * also because it seems trigger creation do not work with DBAL for some unclear reasons.
154
     *
155
     * @param string $file
156
     */
157
    private static function importFile(string $file): void
158
    {
159
        $file = realpath($file);
160
        echo 'importing ' . $file . "\n";
161
        $connection = _em()->getConnection();
162
        $database = $connection->getDatabase();
163
        $username = $connection->getUsername();
164
        $password = empty($connection->getPassword()) ? '' : '-p' . $connection->getPassword();
165
166
        $importCommand = "more $file | mysql -u $username $password $database";
167
168
        self::executeLocalCommand($importCommand);
169
    }
170
}
171