ExportFacade   A
last analyzed

Complexity

Total Complexity 42

Size/Duplication

Total Lines 266
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 109
dl 0
loc 266
rs 9.0399
c 0
b 0
f 0
wmc 42

10 Methods

Rating   Name   Duplication   Size   Complexity  
A dumpViewsAndFKeys() 0 11 4
A dumpRoutines() 0 25 6
A dumpCreateDatabaseQuery() 0 13 4
A getCreateDatabaseQuery() 0 7 3
A getExportOptions() 0 15 2
A dumpEvents() 0 14 4
A dumpDatabase() 0 25 6
A getDatabaseExportHeaders() 0 22 4
A exportDatabases() 0 28 4
A dumpUseDatabaseQuery() 0 8 5

How to fix   Complexity   

Complex Class

Complex classes like ExportFacade often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ExportFacade, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Lagdo\DbAdmin\Db\Facades;
4
5
use Exception;
6
7
use function count;
8
use function preg_match;
9
use function str_replace;
10
use function array_unique;
11
use function array_merge;
12
use function array_pop;
13
14
/**
15
 * Facade to export functions
16
 */
17
class ExportFacade extends AbstractFacade
18
{
19
    use Traits\TableExportTrait;
0 ignored issues
show
Bug introduced by
The trait Lagdo\DbAdmin\Db\Facades\Traits\TableExportTrait requires the property $trans which is not provided by Lagdo\DbAdmin\Db\Facades\ExportFacade.
Loading history...
20
    use Traits\TableDumpTrait;
0 ignored issues
show
introduced by
The trait Lagdo\DbAdmin\Db\Facades\Traits\TableDumpTrait requires some properties which are not provided by Lagdo\DbAdmin\Db\Facades\ExportFacade: $fullType, $type
Loading history...
21
22
    /**
23
     * The databases to dump
24
     *
25
     * @var array
26
     */
27
    private $databases;
28
29
    /**
30
     * The tables to dump
31
     *
32
     * @var array
33
     */
34
    private $tables;
35
36
    /**
37
     * Get data for export
38
     *
39
     * @param string $database      The database name
40
     * @param string $table
41
     *
42
     * @return array
43
     */
44
    public function getExportOptions(string $database, string $table = ''): array
45
    {
46
        $results = [
47
            'options' => $this->getBaseOptions($database, $table),
48
            'prefixes' => [],
49
            'labels' => [
50
                'export' => $this->utils->trans->lang('Export'),
51
            ],
52
        ];
53
        if (($database)) {
54
            $results['tables'] = $this->getDbTables();
55
        } else {
56
            $results['databases'] = $this->getDatabases();
57
        }
58
        return $results;
59
    }
60
61
    /**
62
     * Dump routines in the connected database
63
     *
64
     * @param string $database      The database name
65
     *
66
     * @return void
67
     */
68
    private function dumpRoutines(string $database)
69
    {
70
        // From dump.inc.php
71
        $style = $this->options['db_style'];
72
73
        if ($this->options['routines']) {
74
            $sql = 'SHOW FUNCTION STATUS WHERE Db = ' . $this->driver->quote($database);
75
            foreach ($this->driver->rows($sql) as $row) {
76
                $sql = 'SHOW CREATE FUNCTION ' . $this->driver->escapeId($row['Name']);
77
                $create = $this->driver->removeDefiner($this->driver->result($sql, 2));
78
                $this->queries[] = $this->driver->setUtf8mb4($create);
79
                if ($style != 'DROP+CREATE') {
80
                    $this->queries[] = 'DROP FUNCTION IF EXISTS ' . $this->driver->escapeId($row['Name']) . ';;';
81
                }
82
                $this->queries[] = "$create;;\n";
83
            }
84
            $sql = 'SHOW PROCEDURE STATUS WHERE Db = ' . $this->driver->quote($database);
85
            foreach ($this->driver->rows($sql) as $row) {
86
                $sql = 'SHOW CREATE PROCEDURE ' . $this->driver->escapeId($row['Name']);
87
                $create = $this->driver->removeDefiner($this->driver->result($sql, 2));
88
                $this->queries[] = $this->driver->setUtf8mb4($create);
89
                if ($style != 'DROP+CREATE') {
90
                    $this->queries[] = 'DROP PROCEDURE IF EXISTS ' . $this->driver->escapeId($row['Name']) . ';;';
91
                }
92
                $this->queries[] = "$create;;\n";
93
            }
94
        }
95
    }
96
97
    /**
98
     * Dump events in the connected database
99
     *
100
     * @return void
101
     */
102
    private function dumpEvents()
103
    {
104
        // From dump.inc.php
105
        $style = $this->options['db_style'];
106
107
        if ($this->options['events']) {
108
            foreach ($this->driver->rows('SHOW EVENTS') as $row) {
109
                $sql = 'SHOW CREATE EVENT ' . $this->driver->escapeId($row['Name']);
110
                $create = $this->driver->removeDefiner($this->driver->result($sql, 3));
111
                $this->queries[] = $this->driver->setUtf8mb4($create);
112
                if ($style != 'DROP+CREATE') {
113
                    $this->queries[] = 'DROP EVENT IF EXISTS ' . $this->driver->escapeId($row['Name']) . ';;';
114
                }
115
                $this->queries[] = "$create;;\n";
116
            }
117
        }
118
    }
119
120
    /**
121
     * @return void
122
     */
123
    private function dumpViewsAndFKeys()
124
    {
125
        // Add FKs after creating tables (except in MySQL which uses SET FOREIGN_KEY_CHECKS=0)
126
        if ($this->driver->support('fkeys_sql')) {
127
            foreach ($this->fkeys as $table) {
128
                $this->queries[] = $this->driver->getForeignKeysQuery($table);
129
            }
130
        }
131
        // Dump the views after all the tables
132
        foreach ($this->views as $view) {
133
            $this->dumpCreateTableOrView($view, $this->options['table_style'], 1);
134
        }
135
    }
136
137
    /**
138
     * @param string $database
139
     *
140
     * @return string
141
     */
142
    private function getCreateDatabaseQuery(string $database): string
143
    {
144
        if (!$this->options['is_sql'] || preg_match('~CREATE~', $this->options['db_style']) === false) {
145
            return '';
146
        }
147
        $sql = 'SHOW CREATE DATABASE ' . $this->driver->escapeId($database);
148
        return $this->driver->result($sql, 1);
149
    }
150
151
    /**
152
     * @param string $database
153
     *
154
     * @return void
155
     */
156
    private function dumpUseDatabaseQuery(string $database)
157
    {
158
        if (!$this->options['is_sql'] || !$this->options['db_style'] || $this->driver->jush() !== 'sql') {
159
            return;
160
        }
161
        if (($query = $this->driver->getUseDatabaseQuery($database))) {
162
            $this->queries[] = $query . ';';
163
            $this->queries[] = ''; // Empty line
164
        }
165
    }
166
167
    /**
168
     * @param string $database
169
     *
170
     * @return void
171
     */
172
    private function dumpCreateDatabaseQuery(string $database)
173
    {
174
        if (!($create = $this->getCreateDatabaseQuery($database))) {
175
            return;
176
        }
177
        if (($query = $this->driver->setUtf8mb4($create))) {
178
            $this->queries[] = $query . ';';
179
        }
180
        if ($this->options['db_style'] === 'DROP+CREATE') {
181
            $this->queries[] = 'DROP DATABASE IF EXISTS ' . $this->driver->escapeId($database) . ';';
182
        }
183
        $this->queries[] = $create . ';';
184
        $this->queries[] = ''; // Empty line
185
    }
186
187
    /**
188
     * @param string $database
189
     *
190
     * @return void
191
     */
192
    private function dumpDatabase(string $database)
193
    {
194
        $this->driver->connect($database); // New connection
195
        $this->dumpCreateDatabaseQuery($database);
196
        $this->dumpUseDatabaseQuery($database);
197
        if ($this->options['is_sql'] && $this->driver->jush() === 'sql') {
198
            $count = count($this->queries);
199
            $this->queries[] = "DELIMITER ;;\n";
200
            // Dump routines and events currently works only for MySQL.
201
            $this->dumpRoutines($database);
202
            $this->dumpEvents();
203
            $this->queries[] = "DELIMITER ;;\n";
204
            if ($count + 2 === count($this->queries)) {
205
                // No routine or event were dumped, so the last 2 entries are removed.
206
                array_pop($this->queries);
207
                array_pop($this->queries);
208
            }
209
        }
210
211
        if (!$this->options['table_style'] && !$this->options['data_style']) {
212
            return;
213
        }
214
215
        $this->dumpTables($database);
216
        $this->dumpViewsAndFKeys();
217
    }
218
219
    /**
220
     * @return array|null
221
     */
222
    private function getDatabaseExportHeaders(): ?array
223
    {
224
        if (!$this->options['is_sql']) {
225
            return null;
226
        }
227
        $headers = [
228
            'version' => $this->driver->version(),
229
            'driver' => $this->driver->name(),
230
            'server' => str_replace("\n", ' ', $this->driver->serverInfo()),
231
            'sql' => false,
232
            'data_style' => false,
233
        ];
234
        if ($this->driver->jush() == 'sql') {
235
            $headers['sql'] = true;
236
            if (isset($this->options['data_style'])) {
237
                $headers['data_style'] = true;
238
            }
239
            // Set some options in database server
240
            $this->driver->query("SET time_zone = '+00:00'");
241
            $this->driver->query("SET sql_mode = ''");
242
        }
243
        return $headers;
244
    }
245
246
    /**
247
     * Export databases
248
     *
249
     * @param array  $databases     The databases to dump
250
     * @param array  $tables        The tables to dump
251
     * @param array  $options       The export options
252
     *
253
     * @return array|string
254
     */
255
    public function exportDatabases(array $databases, array $tables, array $options)
256
    {
257
        // From dump.inc.php
258
        // $tables = array_flip($options['tables']) + array_flip($options['data']);
259
        // $ext = dump_headers((count($tables) == 1 ? key($tables) : DB), (DB == '' || count($tables) > 1));
260
        $options['is_sql'] = preg_match('~sql~', $options['format']);
261
        $this->databases = $databases;
262
        $this->tables = $tables;
263
        $this->options = $options;
264
265
        $headers = $this->getDatabaseExportHeaders();
266
267
        foreach (array_unique(array_merge($databases['list'], $databases['data'])) as $database) {
268
            try {
269
                $this->dumpDatabase($database);
270
            }
271
            catch (Exception $e) {
272
                return $e->getMessage();
273
            }
274
        }
275
276
        if ($this->options['is_sql']) {
277
            $this->queries[] = '-- ' . $this->driver->result('SELECT NOW()');
278
        }
279
280
        return [
281
            'headers' => $headers,
282
            'queries' => $this->queries,
283
        ];
284
    }
285
}
286