Test Failed
Push — develop ( 38bc20...a43681 )
by Àlex
05:29
created

Mysql::getImportCommand()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 24
rs 8.9713
cc 3
eloc 16
nc 4
nop 2
1
<?php
2
/**
3
 * PHPCI - Continuous Integration for PHP.
4
 *
5
 * @copyright    Copyright 2014, Block 8 Limited.
6
 * @license      https://github.com/Block8/PHPCI/blob/master/LICENSE.md
7
 *
8
 * @link         https://www.phptesting.org/
9
 */
10
11
namespace PHPCI\Plugin;
12
13
use PDO;
14
use PHPCI\Builder;
15
use PHPCI\Helper\Lang;
16
use PHPCI\Model\Build;
17
18
/**
19
 * MySQL Plugin - Provides access to a MySQL database.
20
 *
21
 * @author       Dan Cryer <[email protected]>
22
 * @author       Steve Kamerman <[email protected]>
23
 */
24
class Mysql implements \PHPCI\Plugin
25
{
26
    /**
27
     * @var \PHPCI\Builder
28
     */
29
    protected $phpci;
30
31
    /**
32
     * @var \PHPCI\Model\Build
33
     */
34
    protected $build;
35
36
    /**
37
     * @var array
38
     */
39
    protected $queries = array();
40
41
    /**
42
     * @var string
43
     */
44
    protected $host;
45
46
    /**
47
     * @var string
48
     */
49
    protected $user;
50
51
    /**
52
     * @var string
53
     */
54
    protected $pass;
55
56
    /**
57
     * @param Builder $phpci
58
     * @param Build   $build
59
     * @param array   $options
60
     */
61
    public function __construct(Builder $phpci, Build $build, array $options = array())
62
    {
63
        $this->phpci = $phpci;
64
        $this->build = $build;
65
66
        $this->queries = $options;
67
68
        $config = \b8\Database::getConnection('write')->getDetails();
69
70
        $this->host = (defined('PHPCI_DB_HOST')) ? PHPCI_DB_HOST : null;
71
        $this->user = $config['user'];
72
        $this->pass = $config['pass'];
73
74
        $buildSettings = $phpci->getConfig('build_settings');
75
76
        if (!isset($buildSettings['mysql'])) {
77
            return;
78
        }
79
80
        if (!empty($buildSettings['mysql']['host'])) {
81
            $this->host = $this->phpci->interpolate($buildSettings['mysql']['host']);
82
        }
83
84
        if (!empty($buildSettings['mysql']['user'])) {
85
            $this->user = $this->phpci->interpolate($buildSettings['mysql']['user']);
86
        }
87
88
        if (array_key_exists('pass', $buildSettings['mysql'])) {
89
            $this->pass = $buildSettings['mysql']['pass'];
90
        }
91
    }
92
93
    /**
94
     * Connects to MySQL and runs a specified set of queries.
95
     *
96
     * @return bool
97
     */
98
    public function execute()
99
    {
100
        try {
101
            $opts = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
102
            $pdo = new PDO('mysql:host='.$this->host, $this->user, $this->pass, $opts);
103
104
            foreach ($this->queries as $query) {
105
                if (!is_array($query)) {
106
                    // Simple query
107
                    $pdo->query($this->phpci->interpolate($query));
108
                } elseif (isset($query['import'])) {
109
                    // SQL file execution
110
                    $this->executeFile($query['import']);
111
                } else {
112
                    throw new \Exception(Lang::get('invalid_command'));
113
                }
114
            }
115
        } catch (\Exception $ex) {
116
            $this->phpci->logFailure($ex->getMessage());
117
118
            return false;
119
        }
120
121
        return true;
122
    }
123
124
    /**
125
     * @param string $query
126
     *
127
     * @return bool
128
     *
129
     * @throws \Exception
130
     */
131
    protected function executeFile($query)
132
    {
133
        if (!isset($query['file'])) {
134
            throw new \Exception(Lang::get('import_file_key'));
135
        }
136
137
        $import_file = $this->phpci->buildPath.$this->phpci->interpolate($query['file']);
138
        if (!is_readable($import_file)) {
139
            throw new \Exception(Lang::get('cannot_open_import', $import_file));
140
        }
141
142
        $database = isset($query['database']) ? $this->phpci->interpolate($query['database']) : null;
143
144
        $import_command = $this->getImportCommand($import_file, $database);
145
        if (!$this->phpci->executeCommand($import_command)) {
146
            throw new \Exception(Lang::get('unable_to_execute'));
147
        }
148
149
        return true;
150
    }
151
152
    /**
153
     * Builds the MySQL import command required to import/execute the specified file.
154
     *
155
     * @param string $import_file Path to file, relative to the build root
156
     * @param string $database    If specified, this database is selected before execution
157
     *
158
     * @return string
159
     */
160
    protected function getImportCommand($import_file, $database = null)
161
    {
162
        $decompression = array(
163
            'bz2' => '| bzip2 --decompress',
164
            'gz' => '| gzip --decompress',
165
        );
166
167
        $extension = strtolower(pathinfo($import_file, PATHINFO_EXTENSION));
168
        $decomp_cmd = '';
169
        if (array_key_exists($extension, $decompression)) {
170
            $decomp_cmd = $decompression[$extension];
171
        }
172
173
        $args = array(
174
            ':import_file' => escapeshellarg($import_file),
175
            ':decomp_cmd' => $decomp_cmd,
176
            ':host' => escapeshellarg($this->host),
177
            ':user' => escapeshellarg($this->user),
178
            ':pass' => escapeshellarg($this->pass),
179
            ':database' => ($database === null) ? '' : escapeshellarg($database),
180
        );
181
182
        return strtr('cat :import_file :decomp_cmd | mysql -h:host -u:user -p:pass :database', $args);
183
    }
184
}
185