Failed Conditions
Push — master ( 52994a...34a070 )
by Adrien
05:40
created

AbstractDatabase::loadTestData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
ccs 0
cts 5
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($remote, $dumpFile): void
23
    {
24
        $sshCmd = <<<STRING
25
        ssh $remote "cd /sites/$remote/ && php7.1 bin/dump-data $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($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($remote, $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($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
    }
91
92
    public static function loadRemoteData($remote): void
93
    {
94
        $dumpFile = "/tmp/$remote." . exec('whoami') . '.backup.sql.gz';
95
        self::dumpDataRemotely($remote, $dumpFile);
96
        self::copyFile($remote, $dumpFile);
97
        self::loadData($dumpFile);
98
99
        echo "database updated\n";
100
    }
101
102
    /**
103
     * Execute a shell command and throw exception if fails
104
     *
105
     * @param string $command
106
     *
107
     * @throws \Exception
108
     */
109
    public static function executeLocalCommand($command): void
110
    {
111
        $return_var = null;
112
        $fullCommand = "$command 2>&1";
113
        passthru($fullCommand, $return_var);
114
        if ($return_var) {
115
            throw new \Exception('FAILED executing: ' . $command);
116
        }
117
    }
118
119
    /**
120
     * Load test data
121
     */
122
    public static function loadTestData(): void
123
    {
124
        self::executeLocalCommand(PHP_BINARY . ' ./vendor/bin/doctrine orm:schema-tool:drop --ansi --full-database --force');
125
        self::executeLocalCommand(PHP_BINARY . ' ./vendor/bin/doctrine-migrations migrations:migrate --ansi --no-interaction');
126
        self::importFile('tests/data/fixture.sql');
127
    }
128
129
    /**
130
     * Import a SQL file into DB
131
     *
132
     * This use mysql command, instead of DBAL methods, to allow to see errors if any, and
133
     * also because it seems trigger creation do not work with DBAL for some unclear reasons.
134
     *
135
     * @param string $file
136
     */
137
    private static function importFile(string $file): void
138
    {
139
        $file = realpath($file);
140
        echo 'importing ' . $file . "\n";
141
        $connection = _em()->getConnection();
142
        $database = $connection->getDatabase();
143
        $username = $connection->getUsername();
144
        $password = empty($connection->getPassword()) ? '' : '-p' . $connection->getPassword();
145
146
        $importCommand = "more $file | mysql -u $username $password $database";
147
148
        self::executeLocalCommand($importCommand);
149
    }
150
}
151