1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* PHPPgAdmin 6.1.3 |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
namespace PHPPgAdmin\Controller; |
8
|
|
|
|
9
|
|
|
use PHPPgAdmin\Decorators\Decorator; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Base controller class. |
13
|
|
|
*/ |
14
|
|
|
class ColpropertiesController extends BaseController |
15
|
|
|
{ |
16
|
|
|
public $tableName = ''; |
17
|
|
|
|
18
|
|
|
public $table_place = 'colproperties-colproperties'; |
19
|
|
|
|
20
|
|
|
public $controller_title = 'strtables'; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Default method to render the controller according to the action parameter. |
24
|
|
|
*/ |
25
|
|
|
public function render(): void |
26
|
|
|
{ |
27
|
|
|
if (isset($_REQUEST['table']) && !empty($_REQUEST['table'])) { |
28
|
|
|
$this->tableName = &$_REQUEST['table']; |
29
|
|
|
} elseif (isset($_REQUEST['view'])) { |
30
|
|
|
$this->tableName = &$_REQUEST['view']; |
31
|
|
|
} elseif (isset($_REQUEST['matview'])) { |
32
|
|
|
$this->tableName = &$_REQUEST['matview']; |
33
|
|
|
} else { |
34
|
|
|
$this->halt($this->lang['strnotableprovided']); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
$this->printHeader($this->headerTitle('', '', $this->tableName), null, true, 'header_select2.twig'); |
38
|
|
|
$this->printBody(); |
39
|
|
|
|
40
|
|
|
if (isset($_REQUEST['view']) || isset($_REQUEST['matview'])) { |
41
|
|
|
$this->doDefault(null, false); |
42
|
|
|
} else { |
43
|
|
|
switch ($this->action) { |
44
|
|
|
case 'properties': |
45
|
|
|
if (null !== $this->getPostParam('cancel')) { |
46
|
|
|
$this->doDefault(); |
47
|
|
|
} else { |
48
|
|
|
$this->doAlter(); |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
break; |
52
|
|
|
|
53
|
|
|
default: |
54
|
|
|
$this->doDefault(); |
55
|
|
|
|
56
|
|
|
break; |
57
|
|
|
} |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
$this->printFooter(); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Show default list of columns in the table. |
65
|
|
|
* |
66
|
|
|
* @param string $msg message to display |
67
|
|
|
* @param bool $isTable tells if we're showing table properties |
68
|
|
|
*/ |
69
|
|
|
public function doDefault($msg = '', $isTable = true): void |
70
|
|
|
{ |
71
|
|
|
if (!isset($_REQUEST['table']) || empty($_REQUEST['table'])) { |
72
|
|
|
$isTable = false; |
73
|
|
|
} |
74
|
|
|
$data = $this->misc->getDatabaseAccessor(); |
75
|
|
|
|
76
|
|
|
$attPre = static function (&$rowdata) use ($data): void { |
77
|
|
|
$rowdata->fields['+type'] = $data->formatType($rowdata->fields['type'], $rowdata->fields['atttypmod']); |
78
|
|
|
}; |
79
|
|
|
|
80
|
|
|
if (empty($_REQUEST['column'])) { |
81
|
|
|
$msg .= "<br/>{$this->lang['strnoobjects']}"; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
$this->printTrail('column'); |
85
|
|
|
//$this->printTitle($this->lang['strcolprop']); |
86
|
|
|
$this->printTabs('column', 'properties'); |
87
|
|
|
$this->printMsg($msg); |
88
|
|
|
|
89
|
|
|
if (!empty($_REQUEST['column'])) { |
90
|
|
|
// Get table |
91
|
|
|
$tdata = $data->getTable($this->tableName); |
92
|
|
|
// Get columns |
93
|
|
|
$attrs = $data->getTableAttributes($this->tableName, $_REQUEST['column']); |
94
|
|
|
|
95
|
|
|
// Show comment if any |
96
|
|
|
if (null !== $attrs->fields['comment']) { |
97
|
|
|
echo '<p class="comment">', $this->misc->printVal($attrs->fields['comment']), '</p>' . \PHP_EOL; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
$column = [ |
101
|
|
|
'column' => [ |
102
|
|
|
'title' => $this->lang['strcolumn'], |
103
|
|
|
'field' => Decorator::field('attname'), |
104
|
|
|
], |
105
|
|
|
'type' => [ |
106
|
|
|
'title' => $this->lang['strtype'], |
107
|
|
|
'field' => Decorator::field('+type'), |
108
|
|
|
], |
109
|
|
|
]; |
110
|
|
|
|
111
|
|
|
if ($isTable) { |
112
|
|
|
$column['notnull'] = [ |
113
|
|
|
'title' => $this->lang['strnotnull'], |
114
|
|
|
'field' => Decorator::field('attnotnull'), |
115
|
|
|
'type' => 'bool', |
116
|
|
|
'params' => ['true' => 'NOT NULL', 'false' => ''], |
117
|
|
|
]; |
118
|
|
|
$column['default'] = [ |
119
|
|
|
'title' => $this->lang['strdefault'], |
120
|
|
|
'field' => Decorator::field('adsrc'), |
121
|
|
|
]; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
$actions = []; |
125
|
|
|
echo $this->printTable($attrs, $column, $actions, $this->table_place, $this->lang['strnodata'], $attPre); |
126
|
|
|
|
127
|
|
|
echo '<br />' . \PHP_EOL; |
128
|
|
|
|
129
|
|
|
$f_attname = $_REQUEST['column']; |
130
|
|
|
$f_table = $this->tableName; |
131
|
|
|
$f_schema = $data->_schema; |
132
|
|
|
$data->fieldClean($f_attname); |
133
|
|
|
$data->fieldClean($f_table); |
134
|
|
|
$data->fieldClean($f_schema); |
135
|
|
|
|
136
|
|
|
if ($isTable) { |
137
|
|
|
$navlinks = [ |
138
|
|
|
'browse' => [ |
139
|
|
|
'attr' => [ |
140
|
|
|
'href' => [ |
141
|
|
|
'url' => 'display', |
142
|
|
|
'method' => 'post', |
143
|
|
|
'urlvars' => [ |
144
|
|
|
'subject' => 'column', |
145
|
|
|
'server' => $_REQUEST['server'], |
146
|
|
|
'database' => $_REQUEST['database'], |
147
|
|
|
'schema' => $_REQUEST['schema'], |
148
|
|
|
'table' => $this->tableName, |
149
|
|
|
'column' => $_REQUEST['column'], |
150
|
|
|
'return' => 'column', |
151
|
|
|
'f_attname' => $f_attname, |
152
|
|
|
'f_table' => $f_table, |
153
|
|
|
'f_schema' => $f_schema, |
154
|
|
|
], |
155
|
|
|
], |
156
|
|
|
], |
157
|
|
|
'content' => $this->lang['strbrowse'], |
158
|
|
|
], |
159
|
|
|
'alter' => [ |
160
|
|
|
'attr' => [ |
161
|
|
|
'href' => [ |
162
|
|
|
'url' => 'colproperties', |
163
|
|
|
'urlvars' => [ |
164
|
|
|
'action' => 'properties', |
165
|
|
|
'server' => $_REQUEST['server'], |
166
|
|
|
'database' => $_REQUEST['database'], |
167
|
|
|
'schema' => $_REQUEST['schema'], |
168
|
|
|
'table' => $this->tableName, |
169
|
|
|
'column' => $_REQUEST['column'], |
170
|
|
|
], |
171
|
|
|
], |
172
|
|
|
], |
173
|
|
|
'content' => $this->lang['stralter'], |
174
|
|
|
], |
175
|
|
|
'drop' => [ |
176
|
|
|
'attr' => [ |
177
|
|
|
'href' => [ |
178
|
|
|
'url' => 'tblproperties', |
179
|
|
|
'urlvars' => [ |
180
|
|
|
'action' => 'confirm_drop', |
181
|
|
|
'server' => $_REQUEST['server'], |
182
|
|
|
'database' => $_REQUEST['database'], |
183
|
|
|
'schema' => $_REQUEST['schema'], |
184
|
|
|
'table' => $this->tableName, |
185
|
|
|
'column' => $_REQUEST['column'], |
186
|
|
|
], |
187
|
|
|
], |
188
|
|
|
], |
189
|
|
|
'content' => $this->lang['strdrop'], |
190
|
|
|
], |
191
|
|
|
]; |
192
|
|
|
} else { |
193
|
|
|
// Browse link |
194
|
|
|
$navlinks = [ |
195
|
|
|
'browse' => [ |
196
|
|
|
'attr' => [ |
197
|
|
|
'href' => [ |
198
|
|
|
'url' => 'display', |
199
|
|
|
'method' => 'post', |
200
|
|
|
'urlvars' => [ |
201
|
|
|
'subject' => 'column', |
202
|
|
|
'server' => $_REQUEST['server'], |
203
|
|
|
'database' => $_REQUEST['database'], |
204
|
|
|
'schema' => $_REQUEST['schema'], |
205
|
|
|
'view' => $this->tableName, |
206
|
|
|
'column' => $_REQUEST['column'], |
207
|
|
|
'return' => 'column', |
208
|
|
|
'f_attname' => $f_attname, |
209
|
|
|
'f_table' => $f_table, |
210
|
|
|
'f_schema' => $f_schema, |
211
|
|
|
], |
212
|
|
|
], |
213
|
|
|
], |
214
|
|
|
'content' => $this->lang['strbrowse'], |
215
|
|
|
], |
216
|
|
|
]; |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
$this->printNavLinks($navlinks, $this->table_place, \get_defined_vars()); |
220
|
|
|
} |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Displays a screen where they can alter a column. |
225
|
|
|
* |
226
|
|
|
* @param mixed $msg |
227
|
|
|
*/ |
228
|
|
|
public function doAlter($msg = ''): void |
229
|
|
|
{ |
230
|
|
|
$data = $this->misc->getDatabaseAccessor(); |
231
|
|
|
|
232
|
|
|
$this->coalesceArr($_REQUEST, 'stage', 1); |
233
|
|
|
|
234
|
|
|
switch ($_REQUEST['stage']) { |
235
|
|
|
case 1: |
236
|
|
|
$this->printTrail('column'); |
237
|
|
|
$this->printTitle($this->lang['stralter'], 'pg.column.alter'); |
238
|
|
|
$this->printMsg($msg); |
239
|
|
|
|
240
|
|
|
echo '<script src="' . \containerInstance()->subFolder . '/assets/js/tables.js" type="text/javascript"></script>'; |
241
|
|
|
echo '<form action="' . \containerInstance()->subFolder . '/src/views/colproperties" method="post">' . \PHP_EOL; |
242
|
|
|
|
243
|
|
|
// Output table header |
244
|
|
|
echo '<table>' . \PHP_EOL; |
245
|
|
|
echo "<tr><th class=\"data required\">{$this->lang['strname']}</th>" . \PHP_EOL; |
246
|
|
|
|
247
|
|
|
if ($data->hasAlterColumnType()) { |
248
|
|
|
echo "<th class=\"data required\" colspan=\"2\">{$this->lang['strtype']}</th>" . \PHP_EOL; |
249
|
|
|
echo "<th class=\"data\">{$this->lang['strlength']}</th>" . \PHP_EOL; |
250
|
|
|
} else { |
251
|
|
|
echo "<th class=\"data required\">{$this->lang['strtype']}</th>" . \PHP_EOL; |
252
|
|
|
} |
253
|
|
|
echo "<th class=\"data\">{$this->lang['strnotnull']}</th>\n<th class=\"data\">{$this->lang['strdefault']}</th>\n<th class=\"data\">{$this->lang['strcomment']}</th></tr>" . \PHP_EOL; |
|
|
|
|
254
|
|
|
|
255
|
|
|
$column = $data->getTableAttributes($_REQUEST['table'], $_REQUEST['column']); |
256
|
|
|
$column->fields['attnotnull'] = $data->phpBool($column->fields['attnotnull']); |
257
|
|
|
|
258
|
|
|
// Upon first drawing the screen, load the existing column information |
259
|
|
|
// from the database. |
260
|
|
|
if (!isset($_REQUEST['default'])) { |
261
|
|
|
$_REQUEST['field'] = $column->fields['attname']; |
262
|
|
|
$_REQUEST['type'] = $column->fields['base_type']; |
263
|
|
|
// Check to see if its' an array type... |
264
|
|
|
// @todo this is pretty hacky! |
265
|
|
|
if ('[]' === \mb_substr($column->fields['base_type'], \mb_strlen($column->fields['base_type']) - 2)) { |
266
|
|
|
$_REQUEST['type'] = \mb_substr($column->fields['base_type'], 0, \mb_strlen($column->fields['base_type']) - 2); |
267
|
|
|
$_REQUEST['array'] = '[]'; |
268
|
|
|
} else { |
269
|
|
|
$_REQUEST['type'] = $column->fields['base_type']; |
270
|
|
|
$_REQUEST['array'] = ''; |
271
|
|
|
} |
272
|
|
|
// To figure out the length, look in the brackets :( |
273
|
|
|
// @todo this is pretty hacky |
274
|
|
|
if ($column->fields['type'] !== $column->fields['base_type'] && \preg_match('/\\(([0-9, ]*)\\)/', $column->fields['type'], $bits)) { |
275
|
|
|
$_REQUEST['length'] = $bits[1]; |
276
|
|
|
} else { |
277
|
|
|
$_REQUEST['length'] = ''; |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
$_REQUEST['default'] = $_REQUEST['olddefault'] = $column->fields['adsrc']; |
281
|
|
|
|
282
|
|
|
if ($column->fields['attnotnull']) { |
283
|
|
|
$_REQUEST['notnull'] = 'YES'; |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
$_REQUEST['comment'] = $column->fields['comment']; |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
// Column name |
290
|
|
|
echo "<tr><td><input name=\"field\" size=\"16\" maxlength=\"{$data->_maxNameLen}\" value=\"", |
291
|
|
|
\htmlspecialchars($_REQUEST['field']), '" /></td>' . \PHP_EOL; |
292
|
|
|
|
293
|
|
|
// Column type |
294
|
|
|
$escaped_predef_types = []; // the JS escaped array elements |
295
|
|
|
|
296
|
|
|
if ($data->hasAlterColumnType()) { |
297
|
|
|
// Fetch all available types |
298
|
|
|
$types = $data->getTypes(true, false, true); |
299
|
|
|
$types_for_js = []; |
300
|
|
|
|
301
|
|
|
echo "<td><select name=\"type\" id=\"type\" class=\"select2\" onchange=\"checkLengths(document.getElementById('type').value,'');\">" . \PHP_EOL; |
302
|
|
|
|
303
|
|
|
while (!$types->EOF) { |
304
|
|
|
$typname = $types->fields['typname']; |
305
|
|
|
$types_for_js[] = $typname; |
306
|
|
|
echo "\t<option value=\"", \htmlspecialchars($typname), '"', ($typname === $_REQUEST['type']) ? ' selected="selected"' : '', '>', |
307
|
|
|
$this->misc->printVal($typname), '</option>' . \PHP_EOL; |
308
|
|
|
$types->moveNext(); |
309
|
|
|
} |
310
|
|
|
echo '</select>' . \PHP_EOL; |
311
|
|
|
echo '</td>' . \PHP_EOL; |
312
|
|
|
|
313
|
|
|
// Output array type selector |
314
|
|
|
echo '<td><select name="array">' . \PHP_EOL; |
315
|
|
|
echo "\t<option value=\"\"", ('' === $_REQUEST['array']) ? ' selected="selected"' : '', '></option>' . \PHP_EOL; |
316
|
|
|
echo "\t<option value=\"[]\"", ('[]' === $_REQUEST['array']) ? ' selected="selected"' : '', '>[ ]</option>' . \PHP_EOL; |
317
|
|
|
echo '</select></td>' . \PHP_EOL; |
318
|
|
|
$predefined_size_types = \array_intersect($data->predefined_size_types, $types_for_js); |
319
|
|
|
|
320
|
|
|
foreach ($predefined_size_types as $value) { |
321
|
|
|
$escaped_predef_types[] = "'{$value}'"; |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
echo '<td><input name="length" id="lengths" size="8" value="', |
325
|
|
|
\htmlspecialchars($_REQUEST['length']), '" /></td>' . \PHP_EOL; |
326
|
|
|
} else { |
327
|
|
|
// Otherwise draw the read-only type name |
328
|
|
|
echo '<td>', $this->misc->printVal($data->formatType($column->fields['type'], $column->fields['atttypmod'])), '</td>' . \PHP_EOL; |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
echo '<td><input type="checkbox" name="notnull"', (isset($_REQUEST['notnull'])) ? ' checked="checked"' : '', ' /></td>' . \PHP_EOL; |
332
|
|
|
echo '<td><input name="default" size="20" value="', |
333
|
|
|
\htmlspecialchars($_REQUEST['default']), '" /></td>' . \PHP_EOL; |
334
|
|
|
echo '<td><input name="comment" size="40" value="', |
335
|
|
|
\htmlspecialchars($_REQUEST['comment']), '" /></td></tr>' . \PHP_EOL; |
336
|
|
|
echo '</table>' . \PHP_EOL; |
337
|
|
|
echo '<p><input type="hidden" name="action" value="properties" />' . \PHP_EOL; |
338
|
|
|
echo '<input type="hidden" name="stage" value="2" />' . \PHP_EOL; |
339
|
|
|
echo $this->view->form; |
340
|
|
|
echo \sprintf('<input type="hidden" name="table" value="%s" />%s', \htmlspecialchars($_REQUEST['table']), \PHP_EOL); |
341
|
|
|
echo '<input type="hidden" name="column" value="', \htmlspecialchars($_REQUEST['column']), '" />' . \PHP_EOL; |
342
|
|
|
echo '<input type="hidden" name="olddefault" value="', \htmlspecialchars($_REQUEST['olddefault']), '" />' . \PHP_EOL; |
343
|
|
|
|
344
|
|
|
if ($column->fields['attnotnull']) { |
345
|
|
|
echo '<input type="hidden" name="oldnotnull" value="on" />' . \PHP_EOL; |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
echo '<input type="hidden" name="oldtype" value="', \htmlspecialchars($data->formatType($column->fields['type'], $column->fields['atttypmod'])), '" />' . \PHP_EOL; |
349
|
|
|
// Add hidden variables to suppress error notices if we don't support altering column type |
350
|
|
|
if (!$data->hasAlterColumnType()) { |
351
|
|
|
echo '<input type="hidden" name="type" value="', \htmlspecialchars($_REQUEST['type']), '" />' . \PHP_EOL; |
352
|
|
|
echo '<input type="hidden" name="length" value="', \htmlspecialchars($_REQUEST['length']), '" />' . \PHP_EOL; |
353
|
|
|
echo '<input type="hidden" name="array" value="', \htmlspecialchars($_REQUEST['array']), '" />' . \PHP_EOL; |
354
|
|
|
} |
355
|
|
|
echo "<input type=\"submit\" value=\"{$this->lang['stralter']}\" />" . \PHP_EOL; |
356
|
|
|
echo \sprintf('<input type="submit" name="cancel" value="%s" /></p>%s', $this->lang['strcancel'], \PHP_EOL); |
357
|
|
|
echo '</form>' . \PHP_EOL; |
358
|
|
|
echo '<script type="text/javascript">predefined_lengths = new Array(' . \implode(',', $escaped_predef_types) . ");checkLengths(document.getElementById('type').value,'');</script>" . \PHP_EOL; |
|
|
|
|
359
|
|
|
|
360
|
|
|
break; |
361
|
|
|
case 2: |
362
|
|
|
// Check inputs |
363
|
|
|
if ('' === \trim($_REQUEST['field'])) { |
364
|
|
|
$_REQUEST['stage'] = 1; |
365
|
|
|
$this->doAlter($this->lang['strcolneedsname']); |
366
|
|
|
|
367
|
|
|
return; |
368
|
|
|
} |
369
|
|
|
$this->coalesceArr($_REQUEST, 'length', ''); |
370
|
|
|
|
371
|
|
|
[$status, $sql] = $data->alterColumn( |
372
|
|
|
$_REQUEST['table'], |
373
|
|
|
$_REQUEST['column'], |
374
|
|
|
$_REQUEST['field'], |
375
|
|
|
isset($_REQUEST['notnull']), |
376
|
|
|
isset($_REQUEST['oldnotnull']), |
377
|
|
|
$_REQUEST['default'], |
378
|
|
|
$_REQUEST['olddefault'], |
379
|
|
|
$_REQUEST['type'], |
380
|
|
|
$_REQUEST['length'], |
381
|
|
|
$_REQUEST['array'], |
382
|
|
|
$_REQUEST['oldtype'], |
383
|
|
|
$_REQUEST['comment'] |
384
|
|
|
); |
385
|
|
|
|
386
|
|
|
if (0 === $status) { |
387
|
|
|
if ($_REQUEST['column'] !== $_REQUEST['field']) { |
388
|
|
|
$_REQUEST['column'] = $_REQUEST['field']; |
389
|
|
|
$this->view->setReloadBrowser(true); |
390
|
|
|
} |
391
|
|
|
$this->doDefault($sql . "<br/>{$this->lang['strcolumnaltered']}"); |
392
|
|
|
} else { |
393
|
|
|
$_REQUEST['stage'] = 1; |
394
|
|
|
$this->doAlter($sql . "<br/>{$this->lang['strcolumnalteredbad']}"); |
395
|
|
|
|
396
|
|
|
return; |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
break; |
400
|
|
|
|
401
|
|
|
default: |
402
|
|
|
echo "<p>{$this->lang['strinvalidparam']}</p>" . \PHP_EOL; |
403
|
|
|
} |
404
|
|
|
} |
405
|
|
|
} |
406
|
|
|
|
Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.