Merge remote-tracking branch 'origin/master'
[phpmyadmin.git] / libraries / central_columns.lib.php
blob13de8d70e6350815cd420d156c1157d722fcde7b
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Functions for displaying user preferences pages
6 * @package PhpMyAdmin
7 */
8 use PMA\libraries\Message;
9 use PMA\libraries\Util;
11 /**
12 * Defines the central_columns parameters for the current user
14 * @return array the central_columns parameters for the current user
15 * @access public
17 function PMA_centralColumnsGetParams()
19 static $cfgCentralColumns = null;
21 if (null !== $cfgCentralColumns) {
22 return $cfgCentralColumns;
25 $cfgRelation = PMA_getRelationsParam();
27 if ($cfgRelation['centralcolumnswork']) {
28 $cfgCentralColumns = array(
29 'user' => $GLOBALS['cfg']['Server']['user'],
30 'db' => $cfgRelation['db'],
31 'table' => $cfgRelation['central_columns'],
33 } else {
34 $cfgCentralColumns = false;
37 return $cfgCentralColumns;
40 /**
41 * get $num columns of given database from central columns list
42 * starting at offset $from
44 * @param string $db selected database
45 * @param int $from starting offset of first result
46 * @param int $num maximum number of results to return
48 * @return array list of $num columns present in central columns list
49 * starting at offset $from for the given database
51 function PMA_getColumnsList($db, $from=0, $num=25)
53 $cfgCentralColumns = PMA_centralColumnsGetParams();
54 if (empty($cfgCentralColumns)) {
55 return array();
57 $pmadb = $cfgCentralColumns['db'];
58 $GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);
59 $central_list_table = $cfgCentralColumns['table'];
60 //get current values of $db from central column list
61 if ($num == 0) {
62 $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '
63 . 'WHERE db_name = \'' . $db . '\';';
64 } else {
65 $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '
66 . 'WHERE db_name = \'' . $db . '\' '
67 . 'LIMIT ' . $from . ', ' . $num . ';';
69 $has_list = (array) $GLOBALS['dbi']->fetchResult(
70 $query, null, null, $GLOBALS['controllink']
72 PMA_handleColumnExtra($has_list);
73 return $has_list;
76 /**
77 * get the number of columns present in central list for given db
79 * @param string $db current database
81 * @return int number of columns in central list of columns for $db
83 function PMA_getCentralColumnsCount($db)
85 $cfgCentralColumns = PMA_centralColumnsGetParams();
86 if (empty($cfgCentralColumns)) {
87 return 0;
89 $pmadb = $cfgCentralColumns['db'];
90 $GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);
91 $central_list_table = $cfgCentralColumns['table'];
92 $query = 'SELECT count(db_name) FROM ' .
93 Util::backquote($central_list_table) . ' '
94 . 'WHERE db_name = \'' . $db . '\';';
95 $res = $GLOBALS['dbi']->fetchResult(
96 $query, null, null, $GLOBALS['controllink']
98 if (isset($res[0])) {
99 return $res[0];
100 } else {
101 return 0;
105 * return the existing columns in central list among the given list of columns
107 * @param string $db the selected database
108 * @param string $cols comma separated list of given columns
109 * @param boolean $allFields set if need all the fields of existing columns,
110 * otherwise only column_name is returned
112 * @return array list of columns in central columns among given set of columns
114 function PMA_findExistingColNames($db, $cols, $allFields=false)
116 $cfgCentralColumns = PMA_centralColumnsGetParams();
117 if (empty($cfgCentralColumns)) {
118 return array();
120 $pmadb = $cfgCentralColumns['db'];
121 $GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);
122 $central_list_table = $cfgCentralColumns['table'];
123 if ($allFields) {
124 $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' '
125 . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';
126 $has_list = (array) $GLOBALS['dbi']->fetchResult(
127 $query, null, null, $GLOBALS['controllink']
129 PMA_handleColumnExtra($has_list);
130 } else {
131 $query = 'SELECT col_name FROM '
132 . Util::backquote($central_list_table) . ' '
133 . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';
134 $has_list = (array) $GLOBALS['dbi']->fetchResult(
135 $query, null, null, $GLOBALS['controllink']
139 return $has_list;
143 * return error message to be displayed if central columns
144 * configuration storage is not completely configured
146 * @return Message
148 function PMA_configErrorMessage()
150 return Message::error(
152 'The configuration storage is not ready for the central list'
153 . ' of columns feature.'
159 * build the insert query for central columns list given PMA storage
160 * db, central_columns table, column name and corresponding definition to be added
162 * @param string $column column to add into central list
163 * @param array $def list of attributes of the column being added
164 * @param string $db PMA configuration storage database name
165 * @param string $central_list_table central columns configuration storage table name
167 * @return string query string to insert the given column
168 * with definition into central list
170 function PMA_getInsertQuery($column, $def, $db, $central_list_table)
172 $type = "";
173 $length = 0;
174 $attribute = "";
175 if (isset($def['Type'])) {
176 $extracted_columnspec = Util::extractColumnSpec($def['Type']);
177 $attribute = trim($extracted_columnspec[ 'attribute']);
178 $type = $extracted_columnspec['type'];
179 $length = $extracted_columnspec['spec_in_brackets'];
181 if (isset($def['Attribute'])) {
182 $attribute = $def['Attribute'];
184 $collation = isset($def['Collation'])?$def['Collation']:"";
185 $isNull = ($def['Null'] == "NO")?0:1;
186 $extra = isset($def['Extra'])?$def['Extra']:"";
187 $default = isset($def['Default'])?$def['Default']:"";
188 $insQuery = 'INSERT INTO '
189 . Util::backquote($central_list_table) . ' '
190 . 'VALUES ( \'' . Util::sqlAddSlashes($db) . '\' ,'
191 . '\'' . Util::sqlAddSlashes($column) . '\',\''
192 . Util::sqlAddSlashes($type) . '\','
193 . '\'' . Util::sqlAddSlashes($length) . '\',\''
194 . Util::sqlAddSlashes($collation) . '\','
195 . '\'' . Util::sqlAddSlashes($isNull) . '\','
196 . '\'' . implode(',', array($extra, $attribute))
197 . '\',\'' . Util::sqlAddSlashes($default) . '\');';
198 return $insQuery;
202 * If $isTable is true then unique columns from given tables as $field_select
203 * are added to central list otherwise the $field_select is considered as
204 * list of columns and these columns are added to central list if not already added
206 * @param array $field_select if $isTable is true selected tables list
207 * otherwise selected columns list
208 * @param bool $isTable if passed array is of tables or columns
209 * @param string $table if $isTable is false,
210 * then table name to which columns belong
212 * @return true|PMA\libraries\Message
214 function PMA_syncUniqueColumns($field_select, $isTable=true, $table=null)
216 $cfgCentralColumns = PMA_centralColumnsGetParams();
217 if (empty($cfgCentralColumns)) {
218 return PMA_configErrorMessage();
220 $db = $_REQUEST['db'];
221 $pmadb = $cfgCentralColumns['db'];
222 $central_list_table = $cfgCentralColumns['table'];
223 $GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
224 $existingCols = array();
225 $cols = "";
226 $insQuery = array();
227 $fields = array();
228 $message = true;
229 if ($isTable) {
230 foreach ($field_select as $table) {
231 $fields[$table] = (array) $GLOBALS['dbi']->getColumns(
232 $db, $table, null, true, $GLOBALS['userlink']
234 foreach ($fields[$table] as $field => $def) {
235 $cols .= "'" . Util::sqlAddSlashes($field) . "',";
239 $has_list = PMA_findExistingColNames($db, trim($cols, ','));
240 foreach ($field_select as $table) {
241 foreach ($fields[$table] as $field => $def) {
242 if (!in_array($field, $has_list)) {
243 $has_list[] = $field;
244 $insQuery[] = PMA_getInsertQuery(
245 $field, $def, $db, $central_list_table
247 } else {
248 $existingCols[] = "'" . $field . "'";
252 } else {
253 if ($table === null) {
254 $table = $_REQUEST['table'];
256 foreach ($field_select as $column) {
257 $cols .= "'" . Util::sqlAddSlashes($column) . "',";
259 $has_list = PMA_findExistingColNames($db, trim($cols, ','));
260 foreach ($field_select as $column) {
261 if (!in_array($column, $has_list)) {
262 $has_list[] = $column;
263 $field = (array) $GLOBALS['dbi']->getColumns(
264 $db, $table, $column,
265 true, $GLOBALS['userlink']
267 $insQuery[] = PMA_getInsertQuery(
268 $column, $field, $db, $central_list_table
270 } else {
271 $existingCols[] = "'" . $column . "'";
275 if (! empty($existingCols)) {
276 $existingCols = implode(",", array_unique($existingCols));
277 $message = Message::notice(
278 sprintf(
280 'Could not add %1$s as they already exist in central list!'
281 ), htmlspecialchars($existingCols)
284 $message->addMessage(
285 Message::notice(
286 "Please remove them first "
287 . "from central list if you want to update above columns"
291 $GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);
292 if (! empty($insQuery)) {
293 foreach ($insQuery as $query) {
294 if (!$GLOBALS['dbi']->tryQuery($query, $GLOBALS['controllink'])) {
295 $message = Message::error(__('Could not add columns!'));
296 $message->addMessage(
297 Message::rawError(
298 $GLOBALS['dbi']->getError($GLOBALS['controllink'])
301 break;
305 return $message;
309 * if $isTable is true it removes all columns of given tables as $field_select from
310 * central columns list otherwise $field_select is columns list and it removes
311 * given columns if present in central list
313 * @param array $field_select if $isTable selected list of tables otherwise
314 * selected list of columns to remove from central list
315 * @param bool $isTable if passed array is of tables or columns
317 * @return true|PMA\libraries\Message
319 function PMA_deleteColumnsFromList($field_select, $isTable=true)
321 $cfgCentralColumns = PMA_centralColumnsGetParams();
322 if (empty($cfgCentralColumns)) {
323 return PMA_configErrorMessage();
325 $db = $_REQUEST['db'];
326 $pmadb = $cfgCentralColumns['db'];
327 $central_list_table = $cfgCentralColumns['table'];
328 $GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
329 $message = true;
330 $colNotExist = array();
331 $fields = array();
332 if ($isTable) {
333 $cols = '';
334 foreach ($field_select as $table) {
335 $fields[$table] = (array) $GLOBALS['dbi']->getColumnNames(
336 $db, $table, $GLOBALS['userlink']
338 foreach ($fields[$table] as $col_select) {
339 $cols .= '\'' . Util::sqlAddSlashes($col_select) . '\',';
342 $cols = trim($cols, ',');
343 $has_list = PMA_findExistingColNames($db, $cols);
344 foreach ($field_select as $table) {
345 foreach ($fields[$table] as $column) {
346 if (!in_array($column, $has_list)) {
347 $colNotExist[] = "'" . $column . "'";
352 } else {
353 $cols = '';
354 foreach ($field_select as $col_select) {
355 $cols .= '\'' . Util::sqlAddSlashes($col_select) . '\',';
357 $cols = trim($cols, ',');
358 $has_list = PMA_findExistingColNames($db, $cols);
359 foreach ($field_select as $column) {
360 if (!in_array($column, $has_list)) {
361 $colNotExist[] = "'" . $column . "'";
365 if (!empty($colNotExist)) {
366 $colNotExist = implode(",", array_unique($colNotExist));
367 $message = Message::notice(
368 sprintf(
370 'Couldn\'t remove Column(s) %1$s '
371 . 'as they don\'t exist in central columns list!'
372 ), htmlspecialchars($colNotExist)
376 $GLOBALS['dbi']->selectDb($pmadb, $GLOBALS['controllink']);
378 $query = 'DELETE FROM ' . Util::backquote($central_list_table) . ' '
379 . 'WHERE db_name = \'' . $db . '\' AND col_name IN (' . $cols . ');';
381 if (!$GLOBALS['dbi']->tryQuery($query, $GLOBALS['controllink'])) {
382 $message = Message::error(__('Could not remove columns!'));
383 $message->addMessage('<br />' . htmlspecialchars($cols) . '<br />');
384 $message->addMessage(
385 Message::rawError(
386 $GLOBALS['dbi']->getError($GLOBALS['controllink'])
390 return $message;
394 * make the columns of given tables consistent with central list of columns.
395 * Updates only those columns which are not being referenced.
397 * @param string $db current database
398 * @param array $selected_tables list of selected tables.
400 * @return true|PMA\libraries\Message
402 function PMA_makeConsistentWithList($db, $selected_tables)
404 $message = true;
405 foreach ($selected_tables as $table) {
406 $query = 'ALTER TABLE ' . Util::backquote($table);
407 $has_list = PMA_getCentralColumnsFromTable($db, $table, true);
408 $GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
409 foreach ($has_list as $column) {
410 $column_status = PMA_checkChildForeignReferences(
411 $db, $table, $column['col_name']
413 //column definition can only be changed if
414 //it is not referenced by another column
415 if ($column_status['isEditable']) {
416 $query .= ' MODIFY ' . Util::backquote($column['col_name']) . ' '
417 . Util::sqlAddSlashes($column['col_type']);
418 if ($column['col_length']) {
419 $query .= '(' . $column['col_length'] . ')';
422 $query .= ' ' . $column['col_attribute'];
423 if ($column['col_isNull']) {
424 $query .= ' NULL';
425 } else {
426 $query .= ' NOT NULL';
429 $query .= ' ' . $column['col_extra'];
430 if ($column['col_default']) {
431 if ($column['col_default'] != 'CURRENT_TIMESTAMP') {
432 $query .= ' DEFAULT \'' . Util::sqlAddSlashes(
433 $column['col_default']
434 ) . '\'';
435 } else {
436 $query .= ' DEFAULT ' . Util::sqlAddSlashes(
437 $column['col_default']
441 $query .= ',';
444 $query = trim($query, " ,") . ";";
445 if (!$GLOBALS['dbi']->tryQuery($query, $GLOBALS['userlink'])) {
446 if ($message === true) {
447 $message = Message::error(
448 $GLOBALS['dbi']->getError($GLOBALS['userlink'])
450 } else {
451 $message->addMessage('<br />');
452 $message->addMessage(
453 $GLOBALS['dbi']->getError($GLOBALS['userlink'])
458 return $message;
462 * return the columns present in central list of columns for a given
463 * table of a given database
465 * @param string $db given database
466 * @param string $table given table
467 * @param boolean $allFields set if need all the fields of existing columns,
468 * otherwise only column_name is returned
470 * @return array columns present in central list from given table of given db.
472 function PMA_getCentralColumnsFromTable($db, $table, $allFields=false)
474 $cfgCentralColumns = PMA_centralColumnsGetParams();
475 if (empty($cfgCentralColumns)) {
476 return array();
478 $GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
479 $fields = (array) $GLOBALS['dbi']->getColumnNames(
480 $db, $table, $GLOBALS['userlink']
482 $cols = '';
483 foreach ($fields as $col_select) {
484 $cols .= '\'' . Util::sqlAddSlashes($col_select) . '\',';
486 $cols = trim($cols, ',');
487 $has_list = PMA_findExistingColNames($db, $cols, $allFields);
488 if (! empty($has_list)) {
489 return (array)$has_list;
490 } else {
491 return array();
496 * update a column in central columns list if a edit is requested
498 * @param string $db current database
499 * @param string $orig_col_name original column name before edit
500 * @param string $col_name new column name
501 * @param string $col_type new column type
502 * @param string $col_attribute new column attribute
503 * @param string $col_length new column length
504 * @param int $col_isNull value 1 if new column isNull is true, 0 otherwise
505 * @param string $collation new column collation
506 * @param string $col_extra new column extra property
507 * @param string $col_default new column default value
509 * @return true|PMA\libraries\Message
511 function PMA_updateOneColumn($db, $orig_col_name, $col_name, $col_type,
512 $col_attribute,$col_length, $col_isNull, $collation, $col_extra, $col_default
514 $cfgCentralColumns = PMA_centralColumnsGetParams();
515 if (empty($cfgCentralColumns)) {
516 return PMA_configErrorMessage();
518 $centralTable = $cfgCentralColumns['table'];
519 $GLOBALS['dbi']->selectDb($cfgCentralColumns['db'], $GLOBALS['controllink']);
520 if ($orig_col_name == "") {
521 $def = array();
522 $def['Type'] = $col_type;
523 if ($col_length) {
524 $def['Type'] .= '(' . $col_length . ')';
526 $def['Collation'] = $collation;
527 $def['Null'] = $col_isNull?__('YES'):__('NO');
528 $def['Extra'] = $col_extra;
529 $def['Attribute'] = $col_attribute;
530 $def['Default'] = $col_default;
531 $query = PMA_getInsertQuery($col_name, $def, $db, $centralTable);
532 } else {
533 $query = 'UPDATE ' . Util::backquote($centralTable)
534 . ' SET col_type = \'' . Util::sqlAddSlashes($col_type) . '\''
535 . ', col_name = \'' . Util::sqlAddSlashes($col_name) . '\''
536 . ', col_length = \'' . Util::sqlAddSlashes($col_length) . '\''
537 . ', col_isNull = ' . $col_isNull
538 . ', col_collation = \'' . Util::sqlAddSlashes($collation) . '\''
539 . ', col_extra = \''
540 . implode(',', array($col_extra, $col_attribute)) . '\''
541 . ', col_default = \'' . Util::sqlAddSlashes($col_default) . '\''
542 . ' WHERE db_name = \'' . Util::sqlAddSlashes($db) . '\' '
543 . 'AND col_name = \'' . Util::sqlAddSlashes($orig_col_name)
544 . '\'';
546 if (!$GLOBALS['dbi']->tryQuery($query, $GLOBALS['controllink'])) {
547 return Message::error(
548 $GLOBALS['dbi']->getError($GLOBALS['controllink'])
551 return true;
555 * Update Multiple column in central columns list if a chnage is requested
557 * @return true|PMA\libraries\Message
559 function PMA_updateMultipleColumn()
561 $db = $_POST['db'];
562 $col_name = $_POST['field_name'];
563 $orig_col_name = $_POST['orig_col_name'];
564 $col_default = $_POST['field_default_type'];
565 $col_length = $_POST['field_length'];
566 $col_attribute = $_POST['field_attribute'];
567 $col_type = $_POST['field_type'];
568 $collation = $_POST['field_collation'];
569 $col_isNull = array();
570 $col_extra = array();
571 $num_central_fields = count($orig_col_name);
572 for ($i = 0; $i < $num_central_fields ; $i++) {
573 $col_isNull[$i] = isset($_POST['field_null'][$i]) ? 1 : 0;
574 $col_extra[$i] = isset($_POST['col_extra'][$i])
575 ? $_POST['col_extra'][$i] : '';
577 if ($col_default[$i] == 'NONE') {
578 $col_default[$i] = "";
579 } else if ($col_default[$i] == 'USER_DEFINED') {
580 $col_default[$i] = $_POST['field_default_value'][$i];
583 $message = PMA_updateOneColumn(
584 $db, $orig_col_name[$i], $col_name[$i], $col_type[$i],
585 $col_attribute[$i], $col_length[$i], $col_isNull[$i], $collation[$i],
586 $col_extra[$i], $col_default[$i]
588 if (!is_bool($message)) {
589 return $message;
592 return true;
596 * get the html for table navigation in Central columns page
598 * @param int $total_rows total number of rows in complete result set
599 * @param int $pos offset of first result with complete result set
600 * @param string $db current database
602 * @return string html for table navigation in Central columns page
604 function PMA_getHTMLforTableNavigation($total_rows, $pos, $db)
606 $max_rows = $GLOBALS['cfg']['MaxRows'];
607 $pageNow = ($pos / $max_rows) + 1;
608 $nbTotalPage = ceil($total_rows / $max_rows);
609 $table_navigation_html = '<table style="display:inline-block;max-width:49%" '
610 . 'class="navigation nospacing nopadding">'
611 . '<tr>'
612 . '<td class="navigation_separator"></td>';
613 if ($pos - $max_rows >= 0) {
614 $table_navigation_html .= '<td>'
615 . '<form action="db_central_columns.php" method="post">'
616 . PMA_URL_getHiddenInputs(
619 . '<input type="hidden" name="pos" value="' . ($pos - $max_rows) . '" />'
620 . '<input type="hidden" name="total_rows" value="' . $total_rows . '"/>'
621 . '<input type="submit" name="navig"'
622 . ' class="ajax" '
623 . 'value="&lt" />'
624 . '</form>'
625 . '</td>';
627 if ($nbTotalPage > 1) {
628 $table_navigation_html .= '<td>';
629 $table_navigation_html .= '<form action="db_central_columns.php'
630 . '" method="post">'
631 . PMA_URL_getHiddenInputs(
634 . '<input type="hidden" name="total_rows" value="' . $total_rows . '"/>';
635 $table_navigation_html .= Util::pageselector(
636 'pos', $max_rows, $pageNow, $nbTotalPage
638 $table_navigation_html .= '</form>'
639 . '</td>';
641 if ($pos + $max_rows < $total_rows) {
642 $table_navigation_html .= '<td>'
643 . '<form action="db_central_columns.php" method="post">'
644 . PMA_URL_getHiddenInputs(
647 . '<input type="hidden" name="pos" value="' . ($pos + $max_rows) . '" />'
648 . '<input type="hidden" name="total_rows" value="' . $total_rows . '"/>'
649 . '<input type="submit" name="navig"'
650 . ' class="ajax" '
651 . 'value="&gt" />'
652 . '</form>'
653 . '</td>';
655 $table_navigation_html .= '</form>'
656 . '</td>'
657 . '<td class="navigation_separator"></td>'
658 . '<td>'
659 . '<span>' . __('Filter rows') . ':</span>'
660 . '<input type="text" class="filter_rows" placeholder="'
661 . __('Search this table') . '">'
662 . '</td>'
663 . '<td class="navigation_separator"></td>'
664 . '</tr>'
665 . '</table>';
667 return $table_navigation_html;
671 * function generate and return the table header for central columns page
673 * @param string $class styling class of 'th' elements
674 * @param string $title title of the 'th' elements
675 * @param integer $actionCount number of actions
677 * @return string html for table header in central columns view/edit page
679 function PMA_getCentralColumnsTableHeader($class='', $title='', $actionCount=0)
681 $action = '';
682 if ($actionCount > 0) {
683 $action .= '<th class="column_action" colspan="' . $actionCount . '">'
684 . __('Action') . '</th>';
686 $tableheader = '<thead>';
687 $tableheader .= '<tr>'
688 . '<th class="' . $class . '"></th>'
689 . '<th class="" style="display:none"></th>'
690 . $action
691 . '<th class="' . $class . '" title="' . $title . '" data-column="name">'
692 . __('Name') . '<div class="sorticon"></div></th>'
693 . '<th class="' . $class . '" title="' . $title . '" data-column="type">'
694 . __('Type') . '<div class="sorticon"></div></th>'
695 . '<th class="' . $class . '" title="' . $title . '" data-column="length">'
696 . __('Length/Values') . '<div class="sorticon"></div></th>'
697 . '<th class="' . $class . '" title="' . $title . '" data-column="default">'
698 . __('Default') . '<div class="sorticon"></div></th>'
699 . '<th class="' . $class . '" title="' . $title . '" data-column="collation"'
700 . '>' . __('Collation') . '<div class="sorticon"></div></th>'
701 . '<th class="' . $class . '" title="' . $title
702 . '" data-column="attribute">'
703 . __('Attribute') . '<div class="sorticon"></div></th>'
704 . '<th class="' . $class . '" title="' . $title . '" data-column="isnull">'
705 . __('Null') . '<div class="sorticon"></div></th>'
706 . '<th class="' . $class . '" title="' . $title . '" data-column="extra">'
707 . __('A_I') . '<div class="sorticon"></div></th>'
708 . '</tr>';
709 $tableheader .= '</thead>';
710 return $tableheader;
714 * Function generate and return the table header for
715 * multiple edit central columns page
717 * @param array $header_cells headers list
719 * @return string html for table header in central columns multi edit page
721 function PMA_getCentralColumnsEditTableHeader($header_cells)
723 $html = '<table id="table_columns" class="noclick"'
724 . ' style="min-width: 100%;">';
725 $html .= '<caption class="tblHeaders">' . __('Structure');
726 $html .= '<tr>';
727 foreach ($header_cells as $header_val) {
728 $html .= '<th>' . $header_val . '</th>';
730 $html .= '</tr>';
731 return $html;
735 * build the dropdown select html for tables of given database
737 * @param string $db current database
739 * @return string html dropdown for selecting table
741 function PMA_getHTMLforTableDropdown($db)
743 $GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
744 $tables = $GLOBALS['dbi']->getTables($db, $GLOBALS['userlink']);
745 $selectHtml = '<select name="table-select" id="table-select">'
746 . '<option value="" disabled="disabled" selected="selected">'
747 . __('Select a table') . '</option>';
748 foreach ($tables as $table) {
749 $selectHtml .= '<option value="' . htmlspecialchars($table) . '">'
750 . htmlspecialchars($table) . '</option>';
752 $selectHtml .= '</select>';
753 return $selectHtml;
757 * build dropdown select html to select column in selected table,
758 * include only columns which are not already in central list
760 * @param string $db current database to which selected table belongs
761 * @param string $selected_tbl selected table
763 * @return string html to select column
765 function PMA_getHTMLforColumnDropdown($db, $selected_tbl)
767 $existing_cols = PMA_getCentralColumnsFromTable($db, $selected_tbl);
768 $GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
769 $columns = (array) $GLOBALS['dbi']->getColumnNames(
770 $db, $selected_tbl, $GLOBALS['userlink']
772 $selectColHtml = "";
773 foreach ($columns as $column) {
774 if (!in_array($column, $existing_cols)) {
775 $selectColHtml .= '<option value="' . htmlspecialchars($column) . '">'
776 . htmlspecialchars($column)
777 . '</option>';
780 return $selectColHtml;
784 * html to display the form that let user to add a column on Central columns page
786 * @param int $total_rows total number of rows in complete result set
787 * @param int $pos offset of first result with complete result set
788 * @param string $db current database
790 * @return string html to add a column in the central list
792 function PMA_getHTMLforAddCentralColumn($total_rows, $pos, $db)
794 $columnAdd = '<table style="display:inline-block;margin-left:1%;max-width:50%" '
795 . 'class="navigation nospacing nopadding">'
796 . '<tr>'
797 . '<td class="navigation_separator"></td>'
798 . '<td style="padding:1.5% 0em">'
799 . Util::getIcon(
800 'centralColumns_add.png',
801 __('Add column')
803 . '<form id="add_column" action="db_central_columns.php" method="post">'
804 . PMA_URL_getHiddenInputs(
807 . '<input type="hidden" name="add_column" value="add">'
808 . '<input type="hidden" name="pos" value="' . $pos . '" />'
809 . '<input type="hidden" name="total_rows" value="' . $total_rows . '"/>'
810 . PMA_getHTMLforTableDropdown($db)
811 . '<select name="column-select" id="column-select">'
812 . '<option value="" selected="selected">'
813 . __('Select a column.') . '</option>'
814 . '</select></form>'
815 . '</td>'
816 . '<td class="navigation_separator"></td>'
817 . '</tr>'
818 . '</table>';
820 return $columnAdd;
824 * build html for a row in central columns table
826 * @param array $row array contains complete information of
827 * a particular row of central list table
828 * @param boolean $odd_row set true if the row is at odd number position
829 * @param int $row_num position the row in the table
830 * @param string $db current database
832 * @return string html of a particular row in the central columns table.
834 function PMA_getHTMLforCentralColumnsTableRow($row, $odd_row, $row_num, $db)
836 $tableHtml = '<tr data-rownum="' . $row_num . '" id="f_' . $row_num . '" '
837 . 'class="' . ($odd_row ? 'odd' : 'even') . '">'
838 . PMA_URL_getHiddenInputs(
841 . '<input type="hidden" name="edit_save" value="save">'
842 . '<td class="nowrap">'
843 . '<input type="checkbox" class="checkall" name="selected_fld[]" '
844 . 'value="' . htmlspecialchars($row['col_name']) . '" '
845 . 'id="checkbox_row_' . $row_num . '"/>'
846 . '</td>'
847 . '<td id="edit_' . $row_num . '" class="edit center">'
848 . '<a href="#">' . Util::getIcon('b_edit.png', __('Edit')) . '</a></td>'
849 . '<td class="del_row" data-rownum = "' . $row_num . '">'
850 . '<a hrf="#">' . Util::getIcon('b_drop.png', __('Delete')) . '</a>'
851 . '<input type="submit" data-rownum = "' . $row_num . '"'
852 . ' class="edit_cancel_form" value="Cancel"></td>'
853 . '<td id="save_' . $row_num . '" style="display:none">'
854 . '<input type="submit" data-rownum = "' . $row_num . '"'
855 . ' class="edit_save_form" value="Save"></td>';
857 $tableHtml .=
858 '<td name="col_name" class="nowrap">'
859 . '<span>' . htmlspecialchars($row['col_name']) . '</span>'
860 . '<input name="orig_col_name" type="hidden" '
861 . 'value="' . htmlspecialchars($row['col_name']) . '">'
862 . PMA\libraries\Template::get('columns_definitions/column_name')
863 ->render(
864 array(
865 'columnNumber' => $row_num,
866 'ci' => 0,
867 'ci_offset' => 0,
868 'columnMeta' => array(
869 'Field'=>$row['col_name']
871 'cfgRelation' => array(
872 'centralcolumnswork' => false
876 . '</td>';
877 $tableHtml .=
878 '<td name = "col_type" class="nowrap"><span>'
879 . htmlspecialchars($row['col_type']) . '</span>'
880 . PMA\libraries\Template::get('columns_definitions/column_type')
881 ->render(
882 array(
883 'columnNumber' => $row_num,
884 'ci' => 1,
885 'ci_offset' => 0,
886 'type_upper' => mb_strtoupper($row['col_type']),
887 'columnMeta' => array()
890 . '</td>';
891 $tableHtml .=
892 '<td class="nowrap" name="col_length">'
893 . '<span>' . ($row['col_length']?htmlspecialchars($row['col_length']):"")
894 . '</span>'
895 . PMA\libraries\Template::get('columns_definitions/column_length')->render(
896 array(
897 'columnNumber' => $row_num,
898 'ci' => 2,
899 'ci_offset' => 0,
900 'length_values_input_size' => 8,
901 'length_to_display' => $row['col_length']
904 . '</td>';
906 $meta = array();
907 if (!isset($row['col_default']) || $row['col_default'] == '') {
908 $meta['DefaultType'] = 'NONE';
909 } else {
910 if ($row['col_default'] == 'CURRENT_TIMESTAMP'
911 || $row['col_default'] == 'NULL'
913 $meta['DefaultType'] = $row['col_default'];
914 } else {
915 $meta['DefaultType'] = 'USER_DEFINED';
916 $meta['DefaultValue'] = $row['col_default'];
919 $tableHtml .=
920 '<td class="nowrap" name="col_default"><span>' . (isset($row['col_default'])
921 ? htmlspecialchars($row['col_default']) : 'None')
922 . '</span>'
923 . PMA\libraries\Template::get('columns_definitions/column_default')
924 ->render(
925 array(
926 'columnNumber' => $row_num,
927 'ci' => 3,
928 'ci_offset' => 0,
929 'type_upper' => mb_strtoupper($row['col_type']),
930 'columnMeta' => $meta
933 . '</td>';
935 $tableHtml .=
936 '<td name="collation" class="nowrap">'
937 . '<span>' . htmlspecialchars($row['col_collation']) . '</span>'
938 . PMA_generateCharsetDropdownBox(
939 PMA_CSDROPDOWN_COLLATION, 'field_collation[' . $row_num . ']',
940 'field_' . $row_num . '_4', $row['col_collation'], false
942 . '</td>';
943 $tableHtml .=
944 '<td class="nowrap" name="col_attribute">'
945 . '<span>' .
946 ($row['col_attribute']
947 ? htmlspecialchars($row['col_attribute']) : "" )
948 . '</span>'
949 . PMA\libraries\Template::get('columns_definitions/column_attribute')
950 ->render(
951 array(
952 'columnNumber' => $row_num,
953 'ci' => 5,
954 'ci_offset' => 0,
955 'extracted_columnspec' => array(),
956 'columnMeta' => $row['col_attribute'],
957 'submit_attribute' => false,
960 . '</td>';
961 $tableHtml .=
962 '<td class="nowrap" name="col_isNull">'
963 . '<span>' . ($row['col_isNull'] ? __('Yes') : __('No'))
964 . '</span>'
965 . PMA\libraries\Template::get('columns_definitions/column_null')
966 ->render(
967 array(
968 'columnNumber' => $row_num,
969 'ci' => 6,
970 'ci_offset' => 0,
971 'columnMeta' => array(
972 'Null' => $row['col_isNull']
976 . '</td>';
978 $tableHtml .=
979 '<td class="nowrap" name="col_extra"><span>'
980 . htmlspecialchars($row['col_extra']) . '</span>'
981 . PMA\libraries\Template::get('columns_definitions/column_extra')->render(
982 array(
983 'columnNumber' => $row_num,
984 'ci' => 7,
985 'ci_offset' => 0,
986 'columnMeta' => array('Extra'=>$row['col_extra'])
989 . '</td>';
991 $tableHtml .= '</tr>';
993 return $tableHtml;
997 * build html for editing a row in central columns table
999 * @param array $row array contains complete information of
1000 * a particular row of central list table
1001 * @param boolean $odd_row set true if the row is at odd number position
1002 * @param int $row_num position the row in the table
1004 * @return string html of a particular row in the central columns table.
1006 function PMA_getHTMLforCentralColumnsEditTableRow($row, $odd_row, $row_num)
1008 $tableHtml = '<tr class="' . ($odd_row ? 'odd' : 'even') . '">'
1009 . '<input name="orig_col_name[' . $row_num . ']" type="hidden" '
1010 . 'value="' . htmlspecialchars($row['col_name']) . '">'
1011 . '<td name="col_name" class="nowrap">'
1012 . PMA\libraries\Template::get('columns_definitions/column_name')
1013 ->render(
1014 array(
1015 'columnNumber' => $row_num,
1016 'ci' => 0,
1017 'ci_offset' => 0,
1018 'columnMeta' => array(
1019 'Field' => $row['col_name']
1021 'cfgRelation' => array(
1022 'centralcolumnswork' => false
1026 . '</td>';
1027 $tableHtml .=
1028 '<td name = "col_type" class="nowrap">'
1029 . PMA\libraries\Template::get('columns_definitions/column_type')
1030 ->render(
1031 array(
1032 'columnNumber' => $row_num,
1033 'ci' => 1,
1034 'ci_offset' => 0,
1035 'type_upper' => mb_strtoupper($row['col_type']),
1036 'columnMeta' => array()
1039 . '</td>';
1040 $tableHtml .=
1041 '<td class="nowrap" name="col_length">'
1042 . PMA\libraries\Template::get('columns_definitions/column_length')->render(
1043 array(
1044 'columnNumber' => $row_num,
1045 'ci' => 2,
1046 'ci_offset' => 0,
1047 'length_values_input_size' => 8,
1048 'length_to_display' => $row['col_length']
1051 . '</td>';
1052 $meta = array();
1053 if (!isset($row['col_default']) || $row['col_default'] == '') {
1054 $meta['DefaultType'] = 'NONE';
1055 } else {
1056 if ($row['col_default'] == 'CURRENT_TIMESTAMP'
1057 || $row['col_default'] == 'NULL'
1059 $meta['DefaultType'] = $row['col_default'];
1060 } else {
1061 $meta['DefaultType'] = 'USER_DEFINED';
1062 $meta['DefaultValue'] = $row['col_default'];
1065 $tableHtml .=
1066 '<td class="nowrap" name="col_default">'
1067 . PMA\libraries\Template::get('columns_definitions/column_default')
1068 ->render(
1069 array(
1070 'columnNumber' => $row_num,
1071 'ci' => 3,
1072 'ci_offset' => 0,
1073 'type_upper' => mb_strtoupper($row['col_default']),
1074 'columnMeta' => $meta
1077 . '</td>';
1078 $tableHtml .=
1079 '<td name="collation" class="nowrap">'
1080 . PMA_generateCharsetDropdownBox(
1081 PMA_CSDROPDOWN_COLLATION, 'field_collation[' . $row_num . ']',
1082 'field_' . $row_num . '_4', $row['col_collation'], false
1084 . '</td>';
1085 $tableHtml .=
1086 '<td class="nowrap" name="col_attribute">'
1087 . PMA\libraries\Template::get('columns_definitions/column_attribute')
1088 ->render(
1089 array(
1090 'columnNumber' => $row_num,
1091 'ci' => 5,
1092 'ci_offset' => 0,
1093 'extracted_columnspec' => array(
1094 'attribute' => $row['col_attribute']
1096 'columnMeta' => array(),
1097 'submit_attribute' => false,
1100 . '</td>';
1101 $tableHtml .=
1102 '<td class="nowrap" name="col_isNull">'
1103 . PMA\libraries\Template::get('columns_definitions/column_null')
1104 ->render(
1105 array(
1106 'columnNumber' => $row_num,
1107 'ci' => 6,
1108 'ci_offset' => 0,
1109 'columnMeta' => array(
1110 'Null' => $row['col_isNull']
1114 . '</td>';
1116 $tableHtml .=
1117 '<td class="nowrap" name="col_extra">'
1118 . PMA\libraries\Template::get('columns_definitions/column_extra')->render(
1119 array(
1120 'columnNumber' => $row_num,
1121 'ci' => 7,
1122 'ci_offset' => 0,
1123 'columnMeta' => array('Extra' => $row['col_extra'])
1126 . '</td>';
1127 $tableHtml .= '</tr>';
1128 return $tableHtml;
1132 * get the list of columns in given database excluding
1133 * the columns present in current table
1135 * @param string $db selected database
1136 * @param string $table current table name
1138 * @return string encoded list of columns present in central list for the given
1139 * database
1141 function PMA_getCentralColumnsListRaw($db, $table)
1143 $cfgCentralColumns = PMA_centralColumnsGetParams();
1144 if (empty($cfgCentralColumns)) {
1145 return json_encode(array());
1147 $centralTable = $cfgCentralColumns['table'];
1148 if (empty($table) || $table == '') {
1149 $query = 'SELECT * FROM ' . Util::backquote($centralTable) . ' '
1150 . 'WHERE db_name = \'' . $db . '\';';
1151 } else {
1152 $GLOBALS['dbi']->selectDb($db, $GLOBALS['userlink']);
1153 $columns = (array) $GLOBALS['dbi']->getColumnNames(
1154 $db, $table, $GLOBALS['userlink']
1156 $cols = '';
1157 foreach ($columns as $col_select) {
1158 $cols .= '\'' . Util::sqlAddSlashes($col_select) . '\',';
1160 $cols = trim($cols, ',');
1161 $query = 'SELECT * FROM ' . Util::backquote($centralTable) . ' '
1162 . 'WHERE db_name = \'' . $db . '\'';
1163 if ($cols) {
1164 $query .= ' AND col_name NOT IN (' . $cols . ')';
1166 $query .= ';';
1168 $GLOBALS['dbi']->selectDb($cfgCentralColumns['db'], $GLOBALS['controllink']);
1169 $columns_list = (array)$GLOBALS['dbi']->fetchResult(
1170 $query, null, null, $GLOBALS['controllink']
1172 PMA_handleColumnExtra($columns_list);
1173 return json_encode($columns_list);
1177 * Get HTML for "check all" check box with "with selected" dropdown
1179 * @param string $pmaThemeImage pma theme image url
1180 * @param string $text_dir url for text directory
1182 * @return string $html_output
1184 function PMA_getCentralColumnsTableFooter($pmaThemeImage, $text_dir)
1186 $html_output = Util::getWithSelected(
1187 $pmaThemeImage, $text_dir, "tableslistcontainer"
1189 $html_output .= Util::getButtonOrImage(
1190 'edit_central_columns', 'mult_submit change_central_columns',
1191 'submit_mult_change', __('Edit'), 'b_edit.png', 'edit central columns'
1193 $html_output .= Util::getButtonOrImage(
1194 'delete_central_columns', 'mult_submit',
1195 'submit_mult_central_columns_remove',
1196 __('Delete'), 'b_drop.png',
1197 'remove_from_central_columns'
1199 return $html_output;
1203 * function generate and return the table footer for
1204 * multiple edit central columns page
1206 * @return string html for table footer in central columns multi edit page
1208 function PMA_getCentralColumnsEditTableFooter()
1210 $html_output = '<fieldset class="tblFooters">'
1211 . '<input type="submit" '
1212 . 'name="save_multi_central_column_edit" value="' . __('Save') . '" />'
1213 . '</fieldset>';
1214 return $html_output;
1217 * Column `col_extra` is used to store both extra and attributes for a column.
1218 * This method separates them.
1220 * @param array &$columns_list columns list
1222 * @return void
1224 function PMA_handleColumnExtra(&$columns_list)
1226 foreach ($columns_list as &$row) {
1227 $vals = explode(',', $row['col_extra']);
1229 if (in_array('BINARY', $vals)) {
1230 $row['col_attribute'] = 'BINARY';
1231 } elseif (in_array('UNSIGNED', $vals)) {
1232 $row['col_attribute'] = 'UNSIGNED';
1233 } elseif (in_array('UNSIGNED ZEROFILL', $vals)) {
1234 $row['col_attribute'] = 'UNSIGNED ZEROFILL';
1235 } elseif (in_array('on update CURRENT_TIMESTAMP', $vals)) {
1236 $row['col_attribute'] = 'on update CURRENT_TIMESTAMP';
1237 } else {
1238 $row['col_attribute'] = '';
1241 if (in_array('auto_increment', $vals)) {
1242 $row['col_extra'] = 'auto_increment';
1243 } else {
1244 $row['col_extra'] = '';
1250 * build html for adding a new user defined column to central list
1252 * @param string $db current database
1254 * @return string html of the form to let user add a new user defined column to the
1255 * list
1257 function PMA_getHTMLforAddNewColumn($db)
1259 $addNewColumn = '<div id="add_col_div"><a href="#">'
1260 . '<span>+</span> ' . __('Add new column') . '</a>'
1261 . '<form id="add_new" style="min-width:100%;display:none" '
1262 . 'method="post" action="db_central_columns.php">'
1263 . PMA_URL_getHiddenInputs(
1266 . '<input type="hidden" name="add_new_column" value="add_new_column">'
1267 . '<table>';
1268 $addNewColumn .= PMA_getCentralColumnsTableHeader();
1269 $addNewColumn .= '<tr>'
1270 . '<td></td>'
1271 . '<td name="col_name" class="nowrap">'
1272 . PMA\libraries\Template::get('columns_definitions/column_name')
1273 ->render(
1274 array(
1275 'columnNumber' => 0,
1276 'ci' => 0,
1277 'ci_offset' => 0,
1278 'columnMeta' => array(),
1279 'cfgRelation' => array(
1280 'centralcolumnswork' => false
1284 . '</td>'
1285 . '<td name = "col_type" class="nowrap">'
1286 . PMA\libraries\Template::get('columns_definitions/column_type')
1287 ->render(
1288 array(
1289 'columnNumber' => 0,
1290 'ci' => 1,
1291 'ci_offset' => 0,
1292 'type_upper' => '',
1293 'columnMeta' => array()
1296 . '</td>'
1297 . '<td class="nowrap" name="col_length">'
1298 . PMA\libraries\Template::get('columns_definitions/column_length')->render(
1299 array(
1300 'columnNumber' => 0,
1301 'ci' => 2,
1302 'ci_offset' => 0,
1303 'length_values_input_size' => 8,
1304 'length_to_display' => ''
1307 . '</td>'
1308 . '<td class="nowrap" name="col_default">'
1309 . PMA\libraries\Template::get('columns_definitions/column_default')
1310 ->render(
1311 array(
1312 'columnNumber' => 0,
1313 'ci' => 3,
1314 'ci_offset' => 0,
1315 'type_upper' => '',
1316 'columnMeta' => array()
1319 . '</td>'
1320 . '<td name="collation" class="nowrap">'
1321 . PMA_generateCharsetDropdownBox(
1322 PMA_CSDROPDOWN_COLLATION, 'field_collation[0]',
1323 'field_0_4', null, false
1325 . '</td>'
1326 . '<td class="nowrap" name="col_attribute">'
1327 . PMA\libraries\Template::get('columns_definitions/column_attribute')
1328 ->render(
1329 array(
1330 'columnNumber' => 0,
1331 'ci' => 5,
1332 'ci_offset' => 0,
1333 'extracted_columnspec' => array(),
1334 'columnMeta' => array(),
1335 'submit_attribute' => false,
1338 . '</td>'
1339 . '<td class="nowrap" name="col_isNull">'
1340 . PMA\libraries\Template::get('columns_definitions/column_null')
1341 ->render(
1342 array(
1343 'columnNumber' => 0,
1344 'ci' => 6,
1345 'ci_offset' => 0,
1346 'columnMeta' => array()
1349 . '</td>'
1350 . '<td class="nowrap" name="col_extra">'
1351 . PMA\libraries\Template::get('columns_definitions/column_extra')->render(
1352 array(
1353 'columnNumber' => 0,
1354 'ci' => 7,
1355 'ci_offset' => 0,
1356 'columnMeta' => array()
1359 . '</td>'
1360 . ' <td>'
1361 . '<input id="add_column_save" type="submit" '
1362 . ' value="Save"/></td>'
1363 . '</tr>';
1364 $addNewColumn .= '</table></form></div>';
1365 return $addNewColumn;
1369 * Get HTML for editing page central columns
1371 * @param array $selected_fld Array containing the selected fields
1372 * @param string $selected_db String containing the name of database
1374 * @return string HTML for complete editing page for central columns
1376 function PMA_getHTMLforEditingPage($selected_fld,$selected_db)
1378 $html = '<form id="multi_edit_central_columns">';
1379 $header_cells = array(
1380 __('Name'), __('Type'), __('Length/Values'), __('Default'),
1381 __('Collation'), __('Attributes'), __('Null'), __('A_I')
1383 $html .= PMA_getCentralColumnsEditTableHeader($header_cells);
1384 $selected_fld_safe = array();
1385 foreach ($selected_fld as $key) {
1386 $selected_fld_safe[] = Util::sqlAddSlashes($key);
1388 $columns_list = implode("','", $selected_fld_safe);
1389 $columns_list = "'" . $columns_list . "'";
1390 $list_detail_cols = PMA_findExistingColNames($selected_db, $columns_list, true);
1391 $odd_row = false;
1392 $row_num = 0;
1393 foreach ($list_detail_cols as $row) {
1394 $tableHtmlRow = PMA_getHTMLforCentralColumnsEditTableRow(
1395 $row, $odd_row, $row_num
1397 $html .= $tableHtmlRow;
1398 $odd_row = !$odd_row;
1399 $row_num++;
1401 $html .= '</table>';
1402 $html .= PMA_getCentralColumnsEditTableFooter();
1403 $html .= '</form>';
1404 return $html;