1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Lagdo\DbAdmin\DbAdmin; |
4
|
|
|
|
5
|
|
|
use function array_key_exists; |
6
|
|
|
use function is_array; |
7
|
|
|
use function array_intersect; |
8
|
|
|
use function array_values; |
9
|
|
|
use function compact; |
10
|
|
|
use function count; |
11
|
|
|
use function array_keys; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Admin server functions |
15
|
|
|
*/ |
16
|
|
|
class ServerAdmin extends AbstractAdmin |
17
|
|
|
{ |
18
|
|
|
/** |
19
|
|
|
* The final database list |
20
|
|
|
* |
21
|
|
|
* @var array|null |
22
|
|
|
*/ |
23
|
|
|
protected $finalDatabases = null; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* The databases the user has access to |
27
|
|
|
* |
28
|
|
|
* @var array|null |
29
|
|
|
*/ |
30
|
|
|
protected $userDatabases = null; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* The constructor |
34
|
|
|
* |
35
|
|
|
* @param array $options The server config options |
36
|
|
|
*/ |
37
|
|
|
public function __construct(array $options) |
38
|
|
|
{ |
39
|
|
|
// Set the user databases, if defined. |
40
|
|
|
if (array_key_exists('access', $options) && |
41
|
|
|
is_array($options['access']) && |
42
|
|
|
array_key_exists('databases', $options['access']) && |
43
|
|
|
is_array($options['access']['databases'])) { |
44
|
|
|
$this->userDatabases = $options['access']['databases']; |
45
|
|
|
} |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Get the databases from the connected server |
50
|
|
|
* |
51
|
|
|
* @return array |
52
|
|
|
*/ |
53
|
|
|
protected function databases() |
54
|
|
|
{ |
55
|
|
|
// Get the database lists |
56
|
|
|
// Passing false as parameter to this call prevent from using the slow_query() function, |
57
|
|
|
// which outputs data to the browser are prepended to the Jaxon response. |
58
|
|
|
if ($this->finalDatabases === null) { |
59
|
|
|
$this->finalDatabases = $this->driver->databases(false); |
60
|
|
|
if (is_array($this->userDatabases)) { |
61
|
|
|
// Only keep databases that appear in the config. |
62
|
|
|
$this->finalDatabases = array_intersect($this->finalDatabases, $this->userDatabases); |
63
|
|
|
$this->finalDatabases = array_values($this->finalDatabases); |
64
|
|
|
} |
65
|
|
|
} |
66
|
|
|
return $this->finalDatabases; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Connect to a database server |
71
|
|
|
* |
72
|
|
|
* @return array |
73
|
|
|
*/ |
74
|
|
|
public function getServerInfo(): array |
75
|
|
|
{ |
76
|
|
|
$server = $this->trans->lang( |
77
|
|
|
'%s version: %s. PHP extension %s.', |
78
|
|
|
$this->driver->name(), |
79
|
|
|
"<b>" . $this->util->html($this->driver->serverInfo()) . "</b>", |
80
|
|
|
"<b>{$this->driver->extension()}</b>" |
81
|
|
|
); |
82
|
|
|
$user = $this->trans->lang('Logged as: %s.', "<b>" . $this->util->html($this->driver->user()) . "</b>"); |
83
|
|
|
|
84
|
|
|
$sqlActions = [ |
85
|
|
|
'server-command' => $this->trans->lang('SQL command'), |
86
|
|
|
'server-import' => $this->trans->lang('Import'), |
87
|
|
|
'server-export' => $this->trans->lang('Export'), |
88
|
|
|
]; |
89
|
|
|
|
90
|
|
|
// Content from the connect_error() function in connect.inc.php |
91
|
|
|
$menuActions = [ |
92
|
|
|
'databases' => $this->trans->lang('Databases'), |
93
|
|
|
]; |
94
|
|
|
// if($this->driver->support('database')) |
95
|
|
|
// { |
96
|
|
|
// $menuActions['databases'] = $this->trans->lang('Databases'); |
97
|
|
|
// } |
98
|
|
|
if ($this->driver->support('privileges')) { |
99
|
|
|
$menuActions['privileges'] = $this->trans->lang('Privileges'); |
100
|
|
|
} |
101
|
|
|
if ($this->driver->support('processlist')) { |
102
|
|
|
$menuActions['processes'] = $this->trans->lang('Process list'); |
103
|
|
|
} |
104
|
|
|
if ($this->driver->support('variables')) { |
105
|
|
|
$menuActions['variables'] = $this->trans->lang('Variables'); |
106
|
|
|
} |
107
|
|
|
if ($this->driver->support('status')) { |
108
|
|
|
$menuActions['status'] = $this->trans->lang('Status'); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
return compact('server', 'user', 'sqlActions', 'menuActions'); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Create a database |
116
|
|
|
* |
117
|
|
|
* @param string $database The database name |
118
|
|
|
* @param string $collation The database collation |
119
|
|
|
* |
120
|
|
|
* @return bool |
121
|
|
|
*/ |
122
|
|
|
public function createDatabase(string $database, string $collation = ''): bool |
123
|
|
|
{ |
124
|
|
|
return $this->driver->createDatabase($database, $collation); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Drop a database |
129
|
|
|
* |
130
|
|
|
* @param string $database The database name |
131
|
|
|
* |
132
|
|
|
* @return bool |
133
|
|
|
*/ |
134
|
|
|
public function dropDatabase(string $database): bool |
135
|
|
|
{ |
136
|
|
|
return $this->driver->dropDatabases([$database]); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* Get the collation list |
141
|
|
|
* |
142
|
|
|
* @return array |
143
|
|
|
*/ |
144
|
|
|
public function getCollations(): array |
145
|
|
|
{ |
146
|
|
|
return $this->driver->collations(); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Get the database list |
151
|
|
|
* |
152
|
|
|
* @return array |
153
|
|
|
*/ |
154
|
|
|
public function getDatabases(): array |
155
|
|
|
{ |
156
|
|
|
$mainActions = [ |
157
|
|
|
'add-database' => $this->trans->lang('Create database'), |
158
|
|
|
]; |
159
|
|
|
|
160
|
|
|
$headers = [ |
161
|
|
|
$this->trans->lang('Database'), |
162
|
|
|
$this->trans->lang('Collation'), |
163
|
|
|
$this->trans->lang('Tables'), |
164
|
|
|
$this->trans->lang('Size'), |
165
|
|
|
'', |
166
|
|
|
]; |
167
|
|
|
|
168
|
|
|
// Get the database list |
169
|
|
|
$databases = $this->databases(); |
170
|
|
|
$tables = $this->driver->countTables($databases); |
171
|
|
|
$collations = $this->driver->collations(); |
172
|
|
|
$details = []; |
173
|
|
|
foreach ($databases as $database) { |
174
|
|
|
$details[] = [ |
175
|
|
|
'name' => $this->util->html($database), |
176
|
|
|
'collation' => $this->util->html($this->driver->databaseCollation($database, $collations)), |
177
|
|
|
'tables' => array_key_exists($database, $tables) ? $tables[$database] : 0, |
178
|
|
|
'size' => $this->trans->formatNumber($this->driver->databaseSize($database)), |
179
|
|
|
]; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
return compact('headers', 'databases', 'details', 'mainActions'); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* Get the processes |
187
|
|
|
* |
188
|
|
|
* @return array |
189
|
|
|
*/ |
190
|
|
|
public function getProcesses(): array |
191
|
|
|
{ |
192
|
|
|
// From processlist.inc.php |
193
|
|
|
$processes = $this->driver->processes(); |
194
|
|
|
|
195
|
|
|
// From processlist.inc.php |
196
|
|
|
// TODO: Add a kill column in the headers |
197
|
|
|
$headers = []; |
198
|
|
|
$details = []; |
199
|
|
|
foreach ($processes as $process) { |
200
|
|
|
// Set the keys of the first etry as headers |
201
|
|
|
if (!$headers) { |
|
|
|
|
202
|
|
|
$headers = array_keys($process); |
203
|
|
|
} |
204
|
|
|
$attrs = []; |
205
|
|
|
foreach ($process as $key => $val) { |
206
|
|
|
$attrs[] = $this->driver->processAttr($process, $key, $val); |
207
|
|
|
} |
208
|
|
|
$details[] = $attrs; |
209
|
|
|
} |
210
|
|
|
return compact('headers', 'details'); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Get the variables |
215
|
|
|
* |
216
|
|
|
* @return array |
217
|
|
|
*/ |
218
|
|
|
public function getVariables(): array |
219
|
|
|
{ |
220
|
|
|
// From variables.inc.php |
221
|
|
|
$variables = $this->driver->variables(); |
222
|
|
|
|
223
|
|
|
$headers = false; |
224
|
|
|
|
225
|
|
|
$details = []; |
226
|
|
|
// From variables.inc.php |
227
|
|
|
foreach ($variables as $key => $val) { |
228
|
|
|
$details[] = [$this->util->html($key), $this->util->shortenUtf8($val, 50)]; |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
return compact('headers', 'details'); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* Get the server status |
236
|
|
|
* |
237
|
|
|
* @return array|null |
238
|
|
|
*/ |
239
|
|
|
public function getStatus() |
240
|
|
|
{ |
241
|
|
|
// From variables.inc.php |
242
|
|
|
$status = $this->driver->statusVariables(); |
243
|
|
|
|
244
|
|
|
$headers = false; |
245
|
|
|
$details = []; |
246
|
|
|
// From variables.inc.php |
247
|
|
|
foreach ($status as $key => $val) { |
248
|
|
|
$details[] = [$this->util->html($key), $this->util->html($val)]; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
return compact('headers', 'details'); |
252
|
|
|
} |
253
|
|
|
} |
254
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.