1<?php 2/* vim: set expandtab sw=4 ts=4 sts=4: */ 3/** 4 * Functions for displaying user preferences pages 5 * 6 * @package PhpMyAdmin 7 */ 8namespace PhpMyAdmin; 9 10use PhpMyAdmin\Charsets; 11use PhpMyAdmin\DatabaseInterface; 12use PhpMyAdmin\Message; 13use PhpMyAdmin\Relation; 14use PhpMyAdmin\Template; 15use PhpMyAdmin\Url; 16use PhpMyAdmin\Util; 17 18/** 19 * PhpMyAdmin\CentralColumns class 20 * 21 * @package PhpMyAdmin 22 */ 23class CentralColumns 24{ 25 /** 26 * DatabaseInterface instance 27 * 28 * @var DatabaseInterface 29 */ 30 private $dbi; 31 32 /** 33 * Current user 34 * 35 * @var string 36 */ 37 private $user; 38 39 /** 40 * Number of rows displayed when browsing a result set 41 * 42 * @var int 43 */ 44 private $maxRows; 45 46 /** 47 * Which editor should be used for CHAR/VARCHAR fields 48 * 49 * @var string 50 */ 51 private $charEditing; 52 53 /** 54 * Disable use of INFORMATION_SCHEMA 55 * 56 * @var boolean 57 */ 58 private $disableIs; 59 60 /** 61 * @var Relation 62 */ 63 private $relation; 64 65 /** 66 * Constructor 67 * 68 * @param DatabaseInterface $dbi DatabaseInterface instance 69 */ 70 public function __construct(DatabaseInterface $dbi) 71 { 72 $this->dbi = $dbi; 73 74 $this->user = $GLOBALS['cfg']['Server']['user']; 75 $this->maxRows = (int) $GLOBALS['cfg']['MaxRows']; 76 $this->charEditing = $GLOBALS['cfg']['CharEditing']; 77 $this->disableIs = (bool) $GLOBALS['cfg']['Server']['DisableIS']; 78 79 $this->relation = new Relation(); 80 } 81 82 /** 83 * Defines the central_columns parameters for the current user 84 * 85 * @return array the central_columns parameters for the current user 86 * @access public 87 */ 88 public function getParams() 89 { 90 static $cfgCentralColumns = null; 91 92 if (null !== $cfgCentralColumns) { 93 return $cfgCentralColumns; 94 } 95 96 $cfgRelation = $this->relation->getRelationsParam(); 97 98 if ($cfgRelation['centralcolumnswork']) { 99 $cfgCentralColumns = array( 100 'user' => $this->user, 101 'db' => $cfgRelation['db'], 102 'table' => $cfgRelation['central_columns'], 103 ); 104 } else { 105 $cfgCentralColumns = false; 106 } 107 108 return $cfgCentralColumns; 109 } 110 111 /** 112 * get $num columns of given database from central columns list 113 * starting at offset $from 114 * 115 * @param string $db selected database 116 * @param int $from starting offset of first result 117 * @param int $num maximum number of results to return 118 * 119 * @return array list of $num columns present in central columns list 120 * starting at offset $from for the given database 121 */ 122 public function getColumnsList($db, $from = 0, $num = 25) 123 { 124 $cfgCentralColumns = $this->getParams(); 125 if (empty($cfgCentralColumns)) { 126 return array(); 127 } 128 $pmadb = $cfgCentralColumns['db']; 129 $this->dbi->selectDb($pmadb, DatabaseInterface::CONNECT_CONTROL); 130 $central_list_table = $cfgCentralColumns['table']; 131 //get current values of $db from central column list 132 if ($num == 0) { 133 $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' ' 134 . 'WHERE db_name = \'' . $this->dbi->escapeString($db) . '\';'; 135 } else { 136 $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' ' 137 . 'WHERE db_name = \'' . $this->dbi->escapeString($db) . '\' ' 138 . 'LIMIT ' . $from . ', ' . $num . ';'; 139 } 140 $has_list = (array) $this->dbi->fetchResult( 141 $query, null, null, DatabaseInterface::CONNECT_CONTROL 142 ); 143 $this->handleColumnExtra($has_list); 144 return $has_list; 145 } 146 147 /** 148 * Get the number of columns present in central list for given db 149 * 150 * @param string $db current database 151 * 152 * @return int number of columns in central list of columns for $db 153 */ 154 public function getCount($db) 155 { 156 $cfgCentralColumns = $this->getParams(); 157 if (empty($cfgCentralColumns)) { 158 return 0; 159 } 160 $pmadb = $cfgCentralColumns['db']; 161 $this->dbi->selectDb($pmadb, DatabaseInterface::CONNECT_CONTROL); 162 $central_list_table = $cfgCentralColumns['table']; 163 $query = 'SELECT count(db_name) FROM ' . 164 Util::backquote($central_list_table) . ' ' 165 . 'WHERE db_name = \'' . $this->dbi->escapeString($db) . '\';'; 166 $res = $this->dbi->fetchResult( 167 $query, null, null, DatabaseInterface::CONNECT_CONTROL 168 ); 169 if (isset($res[0])) { 170 return $res[0]; 171 } 172 173 return 0; 174 } 175 176 /** 177 * return the existing columns in central list among the given list of columns 178 * 179 * @param string $db the selected database 180 * @param string $cols comma separated list of given columns 181 * @param boolean $allFields set if need all the fields of existing columns, 182 * otherwise only column_name is returned 183 * 184 * @return array list of columns in central columns among given set of columns 185 */ 186 private function findExistingColNames( 187 $db, 188 $cols, 189 $allFields = false 190 ) { 191 $cfgCentralColumns = $this->getParams(); 192 if (empty($cfgCentralColumns)) { 193 return array(); 194 } 195 $pmadb = $cfgCentralColumns['db']; 196 $this->dbi->selectDb($pmadb, DatabaseInterface::CONNECT_CONTROL); 197 $central_list_table = $cfgCentralColumns['table']; 198 if ($allFields) { 199 $query = 'SELECT * FROM ' . Util::backquote($central_list_table) . ' ' 200 . 'WHERE db_name = \'' . $this->dbi->escapeString($db) . '\' AND col_name IN (' . $cols . ');'; 201 $has_list = (array) $this->dbi->fetchResult( 202 $query, null, null, DatabaseInterface::CONNECT_CONTROL 203 ); 204 $this->handleColumnExtra($has_list); 205 } else { 206 $query = 'SELECT col_name FROM ' 207 . Util::backquote($central_list_table) . ' ' 208 . 'WHERE db_name = \'' . $this->dbi->escapeString($db) . '\' AND col_name IN (' . $cols . ');'; 209 $has_list = (array) $this->dbi->fetchResult( 210 $query, null, null, DatabaseInterface::CONNECT_CONTROL 211 ); 212 } 213 214 return $has_list; 215 } 216 217 /** 218 * return error message to be displayed if central columns 219 * configuration storage is not completely configured 220 * 221 * @return Message 222 */ 223 private function configErrorMessage() 224 { 225 return Message::error( 226 __( 227 'The configuration storage is not ready for the central list' 228 . ' of columns feature.' 229 ) 230 ); 231 } 232 233 /** 234 * build the insert query for central columns list given PMA storage 235 * db, central_columns table, column name and corresponding definition to be added 236 * 237 * @param string $column column to add into central list 238 * @param array $def list of attributes of the column being added 239 * @param string $db PMA configuration storage database name 240 * @param string $central_list_table central columns configuration storage table name 241 * 242 * @return string query string to insert the given column 243 * with definition into central list 244 */ 245 private function getInsertQuery( 246 $column, 247 array $def, 248 $db, 249 $central_list_table 250 ) { 251 $type = ""; 252 $length = 0; 253 $attribute = ""; 254 if (isset($def['Type'])) { 255 $extracted_columnspec = Util::extractColumnSpec($def['Type']); 256 $attribute = trim($extracted_columnspec[ 'attribute']); 257 $type = $extracted_columnspec['type']; 258 $length = $extracted_columnspec['spec_in_brackets']; 259 } 260 if (isset($def['Attribute'])) { 261 $attribute = $def['Attribute']; 262 }; 263 $collation = isset($def['Collation'])?$def['Collation']:""; 264 $isNull = ($def['Null'] == "NO")?0:1; 265 $extra = isset($def['Extra'])?$def['Extra']:""; 266 $default = isset($def['Default'])?$def['Default']:""; 267 $insQuery = 'INSERT INTO ' 268 . Util::backquote($central_list_table) . ' ' 269 . 'VALUES ( \'' . $this->dbi->escapeString($db) . '\' ,' 270 . '\'' . $this->dbi->escapeString($column) . '\',\'' 271 . $this->dbi->escapeString($type) . '\',' 272 . '\'' . $this->dbi->escapeString($length) . '\',\'' 273 . $this->dbi->escapeString($collation) . '\',' 274 . '\'' . $this->dbi->escapeString($isNull) . '\',' 275 . '\'' . implode(',', array($extra, $attribute)) 276 . '\',\'' . $this->dbi->escapeString($default) . '\');'; 277 return $insQuery; 278 } 279 280 /** 281 * If $isTable is true then unique columns from given tables as $field_select 282 * are added to central list otherwise the $field_select is considered as 283 * list of columns and these columns are added to central list if not already added 284 * 285 * @param array $field_select if $isTable is true selected tables list 286 * otherwise selected columns list 287 * @param bool $isTable if passed array is of tables or columns 288 * @param string $table if $isTable is false, then table name to 289 * which columns belong 290 * 291 * @return true|PhpMyAdmin\Message 292 */ 293 public function syncUniqueColumns( 294 array $field_select, 295 $isTable = true, 296 $table = null 297 ) { 298 $cfgCentralColumns = $this->getParams(); 299 if (empty($cfgCentralColumns)) { 300 return $this->configErrorMessage(); 301 } 302 $db = $_POST['db']; 303 $pmadb = $cfgCentralColumns['db']; 304 $central_list_table = $cfgCentralColumns['table']; 305 $this->dbi->selectDb($db); 306 $existingCols = array(); 307 $cols = ""; 308 $insQuery = array(); 309 $fields = array(); 310 $message = true; 311 if ($isTable) { 312 foreach ($field_select as $table) { 313 $fields[$table] = (array) $this->dbi->getColumns( 314 $db, $table, null, true 315 ); 316 foreach ($fields[$table] as $field => $def) { 317 $cols .= "'" . $this->dbi->escapeString($field) . "',"; 318 } 319 } 320 321 $has_list = $this->findExistingColNames($db, trim($cols, ',')); 322 foreach ($field_select as $table) { 323 foreach ($fields[$table] as $field => $def) { 324 if (!in_array($field, $has_list)) { 325 $has_list[] = $field; 326 $insQuery[] = $this->getInsertQuery( 327 $field, $def, $db, $central_list_table 328 ); 329 } else { 330 $existingCols[] = "'" . $field . "'"; 331 } 332 } 333 } 334 } else { 335 if ($table === null) { 336 $table = $_POST['table']; 337 } 338 foreach ($field_select as $column) { 339 $cols .= "'" . $this->dbi->escapeString($column) . "',"; 340 } 341 $has_list = $this->findExistingColNames($db, trim($cols, ',')); 342 foreach ($field_select as $column) { 343 if (!in_array($column, $has_list)) { 344 $has_list[] = $column; 345 $field = (array) $this->dbi->getColumns( 346 $db, $table, $column, 347 true 348 ); 349 $insQuery[] = $this->getInsertQuery( 350 $column, $field, $db, $central_list_table 351 ); 352 } else { 353 $existingCols[] = "'" . $column . "'"; 354 } 355 } 356 } 357 if (! empty($existingCols)) { 358 $existingCols = implode(",", array_unique($existingCols)); 359 $message = Message::notice( 360 sprintf( 361 __( 362 'Could not add %1$s as they already exist in central list!' 363 ), htmlspecialchars($existingCols) 364 ) 365 ); 366 $message->addMessage( 367 Message::notice( 368 "Please remove them first " 369 . "from central list if you want to update above columns" 370 ) 371 ); 372 } 373 $this->dbi->selectDb($pmadb, DatabaseInterface::CONNECT_CONTROL); 374 if (! empty($insQuery)) { 375 foreach ($insQuery as $query) { 376 if (!$this->dbi->tryQuery($query, DatabaseInterface::CONNECT_CONTROL)) { 377 $message = Message::error(__('Could not add columns!')); 378 $message->addMessage( 379 Message::rawError( 380 $this->dbi->getError(DatabaseInterface::CONNECT_CONTROL) 381 ) 382 ); 383 break; 384 } 385 } 386 } 387 return $message; 388 } 389 390 /** 391 * if $isTable is true it removes all columns of given tables as $field_select from 392 * central columns list otherwise $field_select is columns list and it removes 393 * given columns if present in central list 394 * 395 * @param array $field_select if $isTable selected list of tables otherwise 396 * selected list of columns to remove from central list 397 * @param bool $isTable if passed array is of tables or columns 398 * 399 * @return true|PhpMyAdmin\Message 400 */ 401 public function deleteColumnsFromList( 402 array $field_select, 403 $isTable = true 404 ) { 405 $cfgCentralColumns = $this->getParams(); 406 if (empty($cfgCentralColumns)) { 407 return $this->configErrorMessage(); 408 } 409 $db = $_POST['db']; 410 $pmadb = $cfgCentralColumns['db']; 411 $central_list_table = $cfgCentralColumns['table']; 412 $this->dbi->selectDb($db); 413 $message = true; 414 $colNotExist = array(); 415 $fields = array(); 416 if ($isTable) { 417 $cols = ''; 418 foreach ($field_select as $table) { 419 $fields[$table] = (array) $this->dbi->getColumnNames( 420 $db, $table 421 ); 422 foreach ($fields[$table] as $col_select) { 423 $cols .= '\'' . $this->dbi->escapeString($col_select) . '\','; 424 } 425 } 426 $cols = trim($cols, ','); 427 $has_list = $this->findExistingColNames($db, $cols); 428 foreach ($field_select as $table) { 429 foreach ($fields[$table] as $column) { 430 if (!in_array($column, $has_list)) { 431 $colNotExist[] = "'" . $column . "'"; 432 } 433 } 434 } 435 436 } else { 437 $cols = ''; 438 foreach ($field_select as $col_select) { 439 $cols .= '\'' . $this->dbi->escapeString($col_select) . '\','; 440 } 441 $cols = trim($cols, ','); 442 $has_list = $this->findExistingColNames($db, $cols); 443 foreach ($field_select as $column) { 444 if (!in_array($column, $has_list)) { 445 $colNotExist[] = "'" . $column . "'"; 446 } 447 } 448 } 449 if (!empty($colNotExist)) { 450 $colNotExist = implode(",", array_unique($colNotExist)); 451 $message = Message::notice( 452 sprintf( 453 __( 454 'Couldn\'t remove Column(s) %1$s ' 455 . 'as they don\'t exist in central columns list!' 456 ), htmlspecialchars($colNotExist) 457 ) 458 ); 459 } 460 $this->dbi->selectDb($pmadb, DatabaseInterface::CONNECT_CONTROL); 461 462 $query = 'DELETE FROM ' . Util::backquote($central_list_table) . ' ' 463 . 'WHERE db_name = \'' . $this->dbi->escapeString($db) . '\' AND col_name IN (' . $cols . ');'; 464 465 if (!$this->dbi->tryQuery($query, DatabaseInterface::CONNECT_CONTROL)) { 466 $message = Message::error(__('Could not remove columns!')); 467 $message->addHtml('<br />' . htmlspecialchars($cols) . '<br />'); 468 $message->addMessage( 469 Message::rawError( 470 $this->dbi->getError(DatabaseInterface::CONNECT_CONTROL) 471 ) 472 ); 473 } 474 return $message; 475 } 476 477 /** 478 * Make the columns of given tables consistent with central list of columns. 479 * Updates only those columns which are not being referenced. 480 * 481 * @param string $db current database 482 * @param array $selected_tables list of selected tables. 483 * 484 * @return true|PhpMyAdmin\Message 485 */ 486 public function makeConsistentWithList( 487 $db, 488 array $selected_tables 489 ) { 490 $message = true; 491 foreach ($selected_tables as $table) { 492 $query = 'ALTER TABLE ' . Util::backquote($table); 493 $has_list = $this->getFromTable($db, $table, true); 494 $this->dbi->selectDb($db); 495 foreach ($has_list as $column) { 496 $column_status = $this->relation->checkChildForeignReferences( 497 $db, $table, $column['col_name'] 498 ); 499 //column definition can only be changed if 500 //it is not referenced by another column 501 if ($column_status['isEditable']) { 502 $query .= ' MODIFY ' . Util::backquote($column['col_name']) . ' ' 503 . $this->dbi->escapeString($column['col_type']); 504 if ($column['col_length']) { 505 $query .= '(' . $column['col_length'] . ')'; 506 } 507 508 $query .= ' ' . $column['col_attribute']; 509 if ($column['col_isNull']) { 510 $query .= ' NULL'; 511 } else { 512 $query .= ' NOT NULL'; 513 } 514 515 $query .= ' ' . $column['col_extra']; 516 if ($column['col_default']) { 517 if ($column['col_default'] != 'CURRENT_TIMESTAMP' 518 || $column['col_default'] != 'current_timestamp()') { 519 $query .= ' DEFAULT \'' . $this->dbi->escapeString( 520 $column['col_default'] 521 ) . '\''; 522 } else { 523 $query .= ' DEFAULT ' . $this->dbi->escapeString( 524 $column['col_default'] 525 ); 526 } 527 } 528 $query .= ','; 529 } 530 } 531 $query = trim($query, " ,") . ";"; 532 if (!$this->dbi->tryQuery($query)) { 533 if ($message === true) { 534 $message = Message::error( 535 $this->dbi->getError() 536 ); 537 } else { 538 $message->addText( 539 $this->dbi->getError(), 540 '<br />' 541 ); 542 } 543 } 544 } 545 return $message; 546 } 547 548 /** 549 * return the columns present in central list of columns for a given 550 * table of a given database 551 * 552 * @param string $db given database 553 * @param string $table given table 554 * @param boolean $allFields set if need all the fields of existing columns, 555 * otherwise only column_name is returned 556 * 557 * @return array columns present in central list from given table of given db. 558 */ 559 public function getFromTable( 560 $db, 561 $table, 562 $allFields = false 563 ) { 564 $cfgCentralColumns = $this->getParams(); 565 if (empty($cfgCentralColumns)) { 566 return array(); 567 } 568 $this->dbi->selectDb($db); 569 $fields = (array) $this->dbi->getColumnNames( 570 $db, $table 571 ); 572 $cols = ''; 573 foreach ($fields as $col_select) { 574 $cols .= '\'' . $this->dbi->escapeString($col_select) . '\','; 575 } 576 $cols = trim($cols, ','); 577 $has_list = $this->findExistingColNames($db, $cols, $allFields); 578 if (! empty($has_list)) { 579 return (array)$has_list; 580 } 581 582 return array(); 583 } 584 585 /** 586 * update a column in central columns list if a edit is requested 587 * 588 * @param string $db current database 589 * @param string $orig_col_name original column name before edit 590 * @param string $col_name new column name 591 * @param string $col_type new column type 592 * @param string $col_attribute new column attribute 593 * @param string $col_length new column length 594 * @param int $col_isNull value 1 if new column isNull is true, 0 otherwise 595 * @param string $collation new column collation 596 * @param string $col_extra new column extra property 597 * @param string $col_default new column default value 598 * 599 * @return true|PhpMyAdmin\Message 600 */ 601 public function updateOneColumn( 602 $db, 603 $orig_col_name, 604 $col_name, 605 $col_type, 606 $col_attribute, 607 $col_length, 608 $col_isNull, 609 $collation, 610 $col_extra, 611 $col_default 612 ) { 613 $cfgCentralColumns = $this->getParams(); 614 if (empty($cfgCentralColumns)) { 615 return $this->configErrorMessage(); 616 } 617 $centralTable = $cfgCentralColumns['table']; 618 $this->dbi->selectDb($cfgCentralColumns['db'], DatabaseInterface::CONNECT_CONTROL); 619 if ($orig_col_name == "") { 620 $def = array(); 621 $def['Type'] = $col_type; 622 if ($col_length) { 623 $def['Type'] .= '(' . $col_length . ')'; 624 } 625 $def['Collation'] = $collation; 626 $def['Null'] = $col_isNull?__('YES'):__('NO'); 627 $def['Extra'] = $col_extra; 628 $def['Attribute'] = $col_attribute; 629 $def['Default'] = $col_default; 630 $query = $this->getInsertQuery($col_name, $def, $db, $centralTable); 631 } else { 632 $query = 'UPDATE ' . Util::backquote($centralTable) 633 . ' SET col_type = \'' . $this->dbi->escapeString($col_type) . '\'' 634 . ', col_name = \'' . $this->dbi->escapeString($col_name) . '\'' 635 . ', col_length = \'' . $this->dbi->escapeString($col_length) . '\'' 636 . ', col_isNull = ' . $col_isNull 637 . ', col_collation = \'' . $this->dbi->escapeString($collation) . '\'' 638 . ', col_extra = \'' 639 . implode(',', array($col_extra, $col_attribute)) . '\'' 640 . ', col_default = \'' . $this->dbi->escapeString($col_default) . '\'' 641 . ' WHERE db_name = \'' . $this->dbi->escapeString($db) . '\' ' 642 . 'AND col_name = \'' . $this->dbi->escapeString($orig_col_name) 643 . '\''; 644 } 645 if (!$this->dbi->tryQuery($query, DatabaseInterface::CONNECT_CONTROL)) { 646 return Message::error( 647 $this->dbi->getError(DatabaseInterface::CONNECT_CONTROL) 648 ); 649 } 650 return true; 651 } 652 653 /** 654 * Update Multiple column in central columns list if a chnage is requested 655 * 656 * @return true|PhpMyAdmin\Message 657 */ 658 public function updateMultipleColumn() 659 { 660 $db = $_POST['db']; 661 $col_name = $_POST['field_name']; 662 $orig_col_name = $_POST['orig_col_name']; 663 $col_default = $_POST['field_default_type']; 664 $col_length = $_POST['field_length']; 665 $col_attribute = $_POST['field_attribute']; 666 $col_type = $_POST['field_type']; 667 $collation = $_POST['field_collation']; 668 $col_isNull = array(); 669 $col_extra = array(); 670 $num_central_fields = count($orig_col_name); 671 for ($i = 0; $i < $num_central_fields ; $i++) { 672 $col_isNull[$i] = isset($_POST['field_null'][$i]) ? 1 : 0; 673 $col_extra[$i] = isset($_POST['col_extra'][$i]) 674 ? $_POST['col_extra'][$i] : ''; 675 676 if ($col_default[$i] == 'NONE') { 677 $col_default[$i] = ""; 678 } elseif ($col_default[$i] == 'USER_DEFINED') { 679 $col_default[$i] = $_POST['field_default_value'][$i]; 680 } 681 682 $message = $this->updateOneColumn( 683 $db, $orig_col_name[$i], $col_name[$i], $col_type[$i], 684 $col_attribute[$i], $col_length[$i], $col_isNull[$i], $collation[$i], 685 $col_extra[$i], $col_default[$i] 686 ); 687 if (!is_bool($message)) { 688 return $message; 689 } 690 } 691 return true; 692 } 693 694 /** 695 * get the html for table navigation in Central columns page 696 * 697 * @param int $total_rows total number of rows in complete result set 698 * @param int $pos offset of first result with complete result set 699 * @param string $db current database 700 * 701 * @return string html for table navigation in Central columns page 702 */ 703 public function getHtmlForTableNavigation($total_rows, $pos, $db) 704 { 705 $pageNow = ($pos / $this->maxRows) + 1; 706 $nbTotalPage = ceil($total_rows / $this->maxRows); 707 $page_selector = ($nbTotalPage > 1)?(Util::pageselector( 708 'pos', $this->maxRows, $pageNow, $nbTotalPage 709 )):''; 710 return Template::get('database/central_columns/table_navigation')->render(array( 711 "pos" => $pos, 712 "max_rows" => $this->maxRows, 713 "db" => $db, 714 "total_rows" => $total_rows, 715 "nb_total_page" => $nbTotalPage, 716 "page_selector" => $page_selector, 717 )); 718 } 719 720 /** 721 * function generate and return the table header for central columns page 722 * 723 * @param string $class styling class of 'th' elements 724 * @param string $title title of the 'th' elements 725 * @param integer $actionCount number of actions 726 * 727 * @return string html for table header in central columns view/edit page 728 */ 729 public function getTableHeader($class = '', $title = '', $actionCount = 0) 730 { 731 $action = ''; 732 if ($actionCount > 0) { 733 $action .= '<th class="column_action" colspan="' . $actionCount . '">' 734 . __('Action') . '</th>'; 735 } 736 $tableheader = '<thead>'; 737 $tableheader .= '<tr>' 738 . '<th class="' . $class . '"></th>' 739 . '<th class="hide"></th>' 740 . $action 741 . '<th class="' . $class . '" title="' . $title . '" data-column="name">' 742 . __('Name') . '<div class="sorticon"></div></th>' 743 . '<th class="' . $class . '" title="' . $title . '" data-column="type">' 744 . __('Type') . '<div class="sorticon"></div></th>' 745 . '<th class="' . $class . '" title="' . $title . '" data-column="length">' 746 . __('Length/Values') . '<div class="sorticon"></div></th>' 747 . '<th class="' . $class . '" title="' . $title . '" data-column="default">' 748 . __('Default') . '<div class="sorticon"></div></th>' 749 . '<th class="' . $class . '" title="' . $title . '" data-column="collation"' 750 . '>' . __('Collation') . '<div class="sorticon"></div></th>' 751 . '<th class="' . $class . '" title="' . $title 752 . '" data-column="attribute">' 753 . __('Attribute') . '<div class="sorticon"></div></th>' 754 . '<th class="' . $class . '" title="' . $title . '" data-column="isnull">' 755 . __('Null') . '<div class="sorticon"></div></th>' 756 . '<th class="' . $class . '" title="' . $title . '" data-column="extra">' 757 . __('A_I') . '<div class="sorticon"></div></th>' 758 . '</tr>'; 759 $tableheader .= '</thead>'; 760 return $tableheader; 761 } 762 763 /** 764 * Function generate and return the table header for 765 * multiple edit central columns page 766 * 767 * @param array $headers headers list 768 * 769 * @return string html for table header in central columns multi edit page 770 */ 771 private function getEditTableHeader(array $headers) 772 { 773 return Template::get( 774 'database/central_columns/edit_table_header' 775 )->render([ 776 'headers' => $headers, 777 ]); 778 } 779 780 /** 781 * build the dropdown select html for tables of given database 782 * 783 * @param string $db current database 784 * 785 * @return string html dropdown for selecting table 786 */ 787 private function getHtmlForTableDropdown($db) 788 { 789 $this->dbi->selectDb($db); 790 $tables = $this->dbi->getTables($db); 791 $selectHtml = '<select name="table-select" id="table-select">' 792 . '<option value="" disabled="disabled" selected="selected">' 793 . __('Select a table') . '</option>'; 794 foreach ($tables as $table) { 795 $selectHtml .= '<option value="' . htmlspecialchars($table) . '">' 796 . htmlspecialchars($table) . '</option>'; 797 } 798 $selectHtml .= '</select>'; 799 return $selectHtml; 800 } 801 802 /** 803 * build dropdown select html to select column in selected table, 804 * include only columns which are not already in central list 805 * 806 * @param string $db current database to which selected table belongs 807 * @param string $selected_tbl selected table 808 * 809 * @return string html to select column 810 */ 811 public function getHtmlForColumnDropdown($db, $selected_tbl) 812 { 813 $existing_cols = $this->getFromTable($db, $selected_tbl); 814 $this->dbi->selectDb($db); 815 $columns = (array) $this->dbi->getColumnNames( 816 $db, $selected_tbl 817 ); 818 $selectColHtml = ""; 819 foreach ($columns as $column) { 820 if (!in_array($column, $existing_cols)) { 821 $selectColHtml .= '<option value="' . htmlspecialchars($column) . '">' 822 . htmlspecialchars($column) 823 . '</option>'; 824 } 825 } 826 return $selectColHtml; 827 } 828 829 /** 830 * HTML to display the form that let user to add a column on Central columns page 831 * 832 * @param int $total_rows total number of rows in complete result set 833 * @param int $pos offset of first result with complete result set 834 * @param string $db current database 835 * 836 * @return string html to add a column in the central list 837 */ 838 public function getHtmlForAddColumn( 839 $total_rows, 840 $pos, 841 $db 842 ) { 843 $icon = Util::getIcon( 844 'centralColumns_add', 845 __('Add column') 846 ); 847 $table_drop_down = $this->getHtmlForTableDropdown($db); 848 return Template::get('database/central_columns/add_column')->render(array( 849 'icon' => $icon, 850 'pos' => $pos, 851 'db' => $db, 852 'total_rows' => $total_rows, 853 'table_drop_down' => $table_drop_down, 854 )); 855 } 856 857 /** 858 * build html for a row in central columns table 859 * 860 * @param array $row array contains complete information of a particular row of central list table 861 * @param int $row_num position the row in the table 862 * @param string $db current database 863 * 864 * @return string html of a particular row in the central columns table. 865 */ 866 public function getHtmlForTableRow(array $row, $row_num, $db) 867 { 868 $tableHtml = '<tr data-rownum="' . $row_num . '" id="f_' . $row_num . '">' 869 . Url::getHiddenInputs( 870 $db 871 ) 872 . '<input type="hidden" name="edit_save" value="save">' 873 . '<td class="nowrap">' 874 . '<input type="checkbox" class="checkall" name="selected_fld[]" ' 875 . 'value="' . htmlspecialchars($row['col_name']) . '" ' 876 . 'id="checkbox_row_' . $row_num . '"/>' 877 . '</td>' 878 . '<td id="edit_' . $row_num . '" class="edit center">' 879 . '<a href="#">' . Util::getIcon('b_edit', __('Edit')) . '</a></td>' 880 . '<td class="del_row" data-rownum = "' . $row_num . '">' 881 . '<a hrf="#">' . Util::getIcon('b_drop', __('Delete')) . '</a>' 882 . '<input type="submit" data-rownum = "' . $row_num . '"' 883 . ' class="edit_cancel_form" value="Cancel"></td>' 884 . '<td id="save_' . $row_num . '" class="hide">' 885 . '<input type="submit" data-rownum = "' . $row_num . '"' 886 . ' class="edit_save_form" value="Save"></td>'; 887 888 $tableHtml .= 889 '<td name="col_name" class="nowrap">' 890 . '<span>' . htmlspecialchars($row['col_name']) . '</span>' 891 . '<input name="orig_col_name" type="hidden" ' 892 . 'value="' . htmlspecialchars($row['col_name']) . '">' 893 . Template::get('columns_definitions/column_name')->render(array( 894 'column_number' => $row_num, 895 'ci' => 0, 896 'ci_offset' => 0, 897 'column_meta' => array( 898 'Field'=>$row['col_name'] 899 ), 900 'cfg_relation' => array( 901 'centralcolumnswork' => false 902 ), 903 'max_rows' => $this->maxRows, 904 )) 905 . '</td>'; 906 $tableHtml .= 907 '<td name = "col_type" class="nowrap"><span>' 908 . htmlspecialchars($row['col_type']) . '</span>' 909 . Template::get('columns_definitions/column_type') 910 ->render( 911 array( 912 'column_number' => $row_num, 913 'ci' => 1, 914 'ci_offset' => 0, 915 'type_upper' => mb_strtoupper($row['col_type']), 916 'column_meta' => array() 917 ) 918 ) 919 . '</td>'; 920 $tableHtml .= 921 '<td class="nowrap" name="col_length">' 922 . '<span>' . ($row['col_length']?htmlspecialchars($row['col_length']):"") 923 . '</span>' 924 . Template::get('columns_definitions/column_length')->render( 925 array( 926 'column_number' => $row_num, 927 'ci' => 2, 928 'ci_offset' => 0, 929 'length_values_input_size' => 8, 930 'length_to_display' => $row['col_length'] 931 ) 932 ) 933 . '</td>'; 934 935 $meta = array(); 936 if (!isset($row['col_default']) || $row['col_default'] == '') { 937 $meta['DefaultType'] = 'NONE'; 938 } else { 939 if ($row['col_default'] == 'CURRENT_TIMESTAMP' 940 || $row['col_default'] == 'current_timestamp()' 941 ) { 942 $meta['DefaultType'] = 'CURRENT_TIMESTAMP'; 943 } elseif ($row['col_default'] == 'NULL') { 944 $meta['DefaultType'] = $row['col_default']; 945 } else { 946 $meta['DefaultType'] = 'USER_DEFINED'; 947 $meta['DefaultValue'] = $row['col_default']; 948 } 949 } 950 $tableHtml .= 951 '<td class="nowrap" name="col_default"><span>' . (isset($row['col_default']) 952 ? htmlspecialchars($row['col_default']) : 'None') 953 . '</span>' 954 . Template::get('columns_definitions/column_default') 955 ->render( 956 array( 957 'column_number' => $row_num, 958 'ci' => 3, 959 'ci_offset' => 0, 960 'type_upper' => mb_strtoupper($row['col_type']), 961 'column_meta' => $meta, 962 'char_editing' => $this->charEditing, 963 ) 964 ) 965 . '</td>'; 966 967 $tableHtml .= 968 '<td name="collation" class="nowrap">' 969 . '<span>' . htmlspecialchars($row['col_collation']) . '</span>' 970 . Charsets::getCollationDropdownBox( 971 $this->dbi, 972 $this->disableIs, 973 'field_collation[' . $row_num . ']', 974 'field_' . $row_num . '_4', $row['col_collation'], false 975 ) 976 . '</td>'; 977 $tableHtml .= 978 '<td class="nowrap" name="col_attribute">' 979 . '<span>' . 980 ($row['col_attribute'] 981 ? htmlspecialchars($row['col_attribute']) : "" ) 982 . '</span>' 983 . Template::get('columns_definitions/column_attribute') 984 ->render( 985 array( 986 'column_number' => $row_num, 987 'ci' => 5, 988 'ci_offset' => 0, 989 'extracted_columnspec' => array(), 990 'column_meta' => $row['col_attribute'], 991 'submit_attribute' => false, 992 'attribute_types' => $this->dbi->types->getAttributes(), 993 ) 994 ) 995 . '</td>'; 996 $tableHtml .= 997 '<td class="nowrap" name="col_isNull">' 998 . '<span>' . ($row['col_isNull'] ? __('Yes') : __('No')) 999 . '</span>' 1000 . Template::get('columns_definitions/column_null') 1001 ->render( 1002 array( 1003 'column_number' => $row_num, 1004 'ci' => 6, 1005 'ci_offset' => 0, 1006 'column_meta' => array( 1007 'Null' => $row['col_isNull'] 1008 ) 1009 ) 1010 ) 1011 . '</td>'; 1012 1013 $tableHtml .= 1014 '<td class="nowrap" name="col_extra"><span>' 1015 . htmlspecialchars($row['col_extra']) . '</span>' 1016 . Template::get('columns_definitions/column_extra')->render( 1017 array( 1018 'column_number' => $row_num, 1019 'ci' => 7, 1020 'ci_offset' => 0, 1021 'column_meta' => array('Extra'=>$row['col_extra']) 1022 ) 1023 ) 1024 . '</td>'; 1025 1026 $tableHtml .= '</tr>'; 1027 1028 return $tableHtml; 1029 } 1030 1031 /** 1032 * build html for editing a row in central columns table 1033 * 1034 * @param array $row array contains complete information of a 1035 * particular row of central list table 1036 * @param int $row_num position the row in the table 1037 * 1038 * @return string html of a particular row in the central columns table. 1039 */ 1040 private function getHtmlForEditTableRow(array $row, $row_num) 1041 { 1042 $tableHtml = '<tr>' 1043 . '<input name="orig_col_name[' . $row_num . ']" type="hidden" ' 1044 . 'value="' . htmlspecialchars($row['col_name']) . '">' 1045 . '<td name="col_name" class="nowrap">' 1046 . Template::get('columns_definitions/column_name')->render(array( 1047 'column_number' => $row_num, 1048 'ci' => 0, 1049 'ci_offset' => 0, 1050 'column_meta' => array( 1051 'Field' => $row['col_name'] 1052 ), 1053 'cfg_relation' => array( 1054 'centralcolumnswork' => false 1055 ), 1056 'max_rows' => $this->maxRows, 1057 )) 1058 . '</td>'; 1059 $tableHtml .= 1060 '<td name = "col_type" class="nowrap">' 1061 . Template::get('columns_definitions/column_type') 1062 ->render( 1063 array( 1064 'column_number' => $row_num, 1065 'ci' => 1, 1066 'ci_offset' => 0, 1067 'type_upper' => mb_strtoupper($row['col_type']), 1068 'column_meta' => array() 1069 ) 1070 ) 1071 . '</td>'; 1072 $tableHtml .= 1073 '<td class="nowrap" name="col_length">' 1074 . Template::get('columns_definitions/column_length')->render( 1075 array( 1076 'column_number' => $row_num, 1077 'ci' => 2, 1078 'ci_offset' => 0, 1079 'length_values_input_size' => 8, 1080 'length_to_display' => $row['col_length'] 1081 ) 1082 ) 1083 . '</td>'; 1084 $meta = array(); 1085 if (!isset($row['col_default']) || $row['col_default'] == '') { 1086 $meta['DefaultType'] = 'NONE'; 1087 } else { 1088 if ($row['col_default'] == 'CURRENT_TIMESTAMP' 1089 || $row['col_default'] == 'current_timestamp()' 1090 ) { 1091 $meta['DefaultType'] = 'CURRENT_TIMESTAMP'; 1092 } elseif ($row['col_default'] == 'NULL') { 1093 $meta['DefaultType'] = $row['col_default']; 1094 } else { 1095 $meta['DefaultType'] = 'USER_DEFINED'; 1096 $meta['DefaultValue'] = $row['col_default']; 1097 } 1098 } 1099 $tableHtml .= 1100 '<td class="nowrap" name="col_default">' 1101 . Template::get('columns_definitions/column_default') 1102 ->render( 1103 array( 1104 'column_number' => $row_num, 1105 'ci' => 3, 1106 'ci_offset' => 0, 1107 'type_upper' => mb_strtoupper($row['col_default']), 1108 'column_meta' => $meta, 1109 'char_editing' => $this->charEditing, 1110 ) 1111 ) 1112 . '</td>'; 1113 $tableHtml .= 1114 '<td name="collation" class="nowrap">' 1115 . Charsets::getCollationDropdownBox( 1116 $this->dbi, 1117 $this->disableIs, 1118 'field_collation[' . $row_num . ']', 1119 'field_' . $row_num . '_4', $row['col_collation'], false 1120 ) 1121 . '</td>'; 1122 $tableHtml .= 1123 '<td class="nowrap" name="col_attribute">' 1124 . Template::get('columns_definitions/column_attribute') 1125 ->render( 1126 array( 1127 'column_number' => $row_num, 1128 'ci' => 5, 1129 'ci_offset' => 0, 1130 'extracted_columnspec' => array( 1131 'attribute' => $row['col_attribute'] 1132 ), 1133 'column_meta' => array(), 1134 'submit_attribute' => false, 1135 'attribute_types' => $this->dbi->types->getAttributes(), 1136 ) 1137 ) 1138 . '</td>'; 1139 $tableHtml .= 1140 '<td class="nowrap" name="col_isNull">' 1141 . Template::get('columns_definitions/column_null') 1142 ->render( 1143 array( 1144 'column_number' => $row_num, 1145 'ci' => 6, 1146 'ci_offset' => 0, 1147 'column_meta' => array( 1148 'Null' => $row['col_isNull'] 1149 ) 1150 ) 1151 ) 1152 . '</td>'; 1153 1154 $tableHtml .= 1155 '<td class="nowrap" name="col_extra">' 1156 . Template::get('columns_definitions/column_extra')->render( 1157 array( 1158 'column_number' => $row_num, 1159 'ci' => 7, 1160 'ci_offset' => 0, 1161 'column_meta' => array('Extra' => $row['col_extra']) 1162 ) 1163 ) 1164 . '</td>'; 1165 $tableHtml .= '</tr>'; 1166 return $tableHtml; 1167 } 1168 1169 /** 1170 * get the list of columns in given database excluding 1171 * the columns present in current table 1172 * 1173 * @param string $db selected database 1174 * @param string $table current table name 1175 * 1176 * @return string encoded list of columns present in central list for the given 1177 * database 1178 */ 1179 public function getListRaw($db, $table) 1180 { 1181 $cfgCentralColumns = $this->getParams(); 1182 if (empty($cfgCentralColumns)) { 1183 return json_encode(array()); 1184 } 1185 $centralTable = $cfgCentralColumns['table']; 1186 if (empty($table) || $table == '') { 1187 $query = 'SELECT * FROM ' . Util::backquote($centralTable) . ' ' 1188 . 'WHERE db_name = \'' . $this->dbi->escapeString($db) . '\';'; 1189 } else { 1190 $this->dbi->selectDb($db); 1191 $columns = (array) $this->dbi->getColumnNames( 1192 $db, $table 1193 ); 1194 $cols = ''; 1195 foreach ($columns as $col_select) { 1196 $cols .= '\'' . $this->dbi->escapeString($col_select) . '\','; 1197 } 1198 $cols = trim($cols, ','); 1199 $query = 'SELECT * FROM ' . Util::backquote($centralTable) . ' ' 1200 . 'WHERE db_name = \'' . $this->dbi->escapeString($db) . '\''; 1201 if ($cols) { 1202 $query .= ' AND col_name NOT IN (' . $cols . ')'; 1203 } 1204 $query .= ';'; 1205 } 1206 $this->dbi->selectDb($cfgCentralColumns['db'], DatabaseInterface::CONNECT_CONTROL); 1207 $columns_list = (array)$this->dbi->fetchResult( 1208 $query, null, null, DatabaseInterface::CONNECT_CONTROL 1209 ); 1210 $this->handleColumnExtra($columns_list); 1211 return json_encode($columns_list); 1212 } 1213 1214 /** 1215 * Get HTML for "check all" check box with "with selected" dropdown 1216 * 1217 * @param string $pmaThemeImage pma theme image url 1218 * @param string $text_dir url for text directory 1219 * 1220 * @return string $html_output 1221 */ 1222 public function getTableFooter($pmaThemeImage, $text_dir) 1223 { 1224 $html_output = Template::get('select_all') 1225 ->render( 1226 array( 1227 'pma_theme_image' => $pmaThemeImage, 1228 'text_dir' => $text_dir, 1229 'form_name' => 'tableslistcontainer', 1230 ) 1231 ); 1232 $html_output .= Util::getButtonOrImage( 1233 'edit_central_columns', 'mult_submit change_central_columns', 1234 __('Edit'), 'b_edit', 'edit central columns' 1235 ); 1236 $html_output .= Util::getButtonOrImage( 1237 'delete_central_columns', 'mult_submit', 1238 __('Delete'), 'b_drop', 1239 'remove_from_central_columns' 1240 ); 1241 return $html_output; 1242 } 1243 1244 /** 1245 * function generate and return the table footer for 1246 * multiple edit central columns page 1247 * 1248 * @return string html for table footer in central columns multi edit page 1249 */ 1250 private function getEditTableFooter() 1251 { 1252 $html_output = '<fieldset class="tblFooters">' 1253 . '<input type="submit" ' 1254 . 'name="save_multi_central_column_edit" value="' . __('Save') . '" />' 1255 . '</fieldset>'; 1256 return $html_output; 1257 } 1258 1259 /** 1260 * Column `col_extra` is used to store both extra and attributes for a column. 1261 * This method separates them. 1262 * 1263 * @param array &$columns_list columns list 1264 * 1265 * @return void 1266 */ 1267 private function handleColumnExtra(array &$columns_list) 1268 { 1269 foreach ($columns_list as &$row) { 1270 $vals = explode(',', $row['col_extra']); 1271 1272 if (in_array('BINARY', $vals)) { 1273 $row['col_attribute'] = 'BINARY'; 1274 } elseif (in_array('UNSIGNED', $vals)) { 1275 $row['col_attribute'] = 'UNSIGNED'; 1276 } elseif (in_array('UNSIGNED ZEROFILL', $vals)) { 1277 $row['col_attribute'] = 'UNSIGNED ZEROFILL'; 1278 } elseif (in_array('on update CURRENT_TIMESTAMP', $vals)) { 1279 $row['col_attribute'] = 'on update CURRENT_TIMESTAMP'; 1280 } else { 1281 $row['col_attribute'] = ''; 1282 } 1283 1284 if (in_array('auto_increment', $vals)) { 1285 $row['col_extra'] = 'auto_increment'; 1286 } else { 1287 $row['col_extra'] = ''; 1288 } 1289 } 1290 } 1291 1292 /** 1293 * build html for adding a new user defined column to central list 1294 * 1295 * @param string $db current database 1296 * @param integer $total_rows number of rows in central columns 1297 * 1298 * @return string html of the form to let user add a new user defined column to the 1299 * list 1300 */ 1301 public function getHtmlForAddNewColumn($db, $total_rows) 1302 { 1303 $addNewColumn = '<div id="add_col_div" class="topmargin"><a href="#">' 1304 . '<span>+</span> ' . __('Add new column') . '</a>' 1305 . '<form id="add_new" class="new_central_col ' 1306 . ($total_rows != 0 ? 'hide"' : '"') 1307 . 'method="post" action="db_central_columns.php">' 1308 . Url::getHiddenInputs( 1309 $db 1310 ) 1311 . '<input type="hidden" name="add_new_column" value="add_new_column">' 1312 . '<div class="responsivetable">' 1313 . '<table>'; 1314 $addNewColumn .= $this->getTableHeader(); 1315 $addNewColumn .= '<tr>' 1316 . '<td></td>' 1317 . '<td name="col_name" class="nowrap">' 1318 . Template::get('columns_definitions/column_name')->render(array( 1319 'column_number' => 0, 1320 'ci' => 0, 1321 'ci_offset' => 0, 1322 'column_meta' => array(), 1323 'cfg_relation' => array( 1324 'centralcolumnswork' => false 1325 ), 1326 'max_rows' => $this->maxRows, 1327 )) 1328 . '</td>' 1329 . '<td name = "col_type" class="nowrap">' 1330 . Template::get('columns_definitions/column_type') 1331 ->render( 1332 array( 1333 'column_number' => 0, 1334 'ci' => 1, 1335 'ci_offset' => 0, 1336 'type_upper' => '', 1337 'column_meta' => array() 1338 ) 1339 ) 1340 . '</td>' 1341 . '<td class="nowrap" name="col_length">' 1342 . Template::get('columns_definitions/column_length')->render( 1343 array( 1344 'column_number' => 0, 1345 'ci' => 2, 1346 'ci_offset' => 0, 1347 'length_values_input_size' => 8, 1348 'length_to_display' => '' 1349 ) 1350 ) 1351 . '</td>' 1352 . '<td class="nowrap" name="col_default">' 1353 . Template::get('columns_definitions/column_default') 1354 ->render( 1355 array( 1356 'column_number' => 0, 1357 'ci' => 3, 1358 'ci_offset' => 0, 1359 'type_upper' => '', 1360 'column_meta' => array(), 1361 'char_editing' => $this->charEditing, 1362 ) 1363 ) 1364 . '</td>' 1365 . '<td name="collation" class="nowrap">' 1366 . Charsets::getCollationDropdownBox( 1367 $this->dbi, 1368 $this->disableIs, 1369 'field_collation[0]', 1370 'field_0_4', null, false 1371 ) 1372 . '</td>' 1373 . '<td class="nowrap" name="col_attribute">' 1374 . Template::get('columns_definitions/column_attribute') 1375 ->render( 1376 array( 1377 'column_number' => 0, 1378 'ci' => 5, 1379 'ci_offset' => 0, 1380 'extracted_columnspec' => array(), 1381 'column_meta' => array(), 1382 'submit_attribute' => false, 1383 'attribute_types' => $this->dbi->types->getAttributes(), 1384 ) 1385 ) 1386 . '</td>' 1387 . '<td class="nowrap" name="col_isNull">' 1388 . Template::get('columns_definitions/column_null') 1389 ->render( 1390 array( 1391 'column_number' => 0, 1392 'ci' => 6, 1393 'ci_offset' => 0, 1394 'column_meta' => array() 1395 ) 1396 ) 1397 . '</td>' 1398 . '<td class="nowrap" name="col_extra">' 1399 . Template::get('columns_definitions/column_extra')->render( 1400 array( 1401 'column_number' => 0, 1402 'ci' => 7, 1403 'ci_offset' => 0, 1404 'column_meta' => array() 1405 ) 1406 ) 1407 . '</td>' 1408 . ' <td>' 1409 . '<input id="add_column_save" type="submit" ' 1410 . ' value="Save"/></td>' 1411 . '</tr>'; 1412 $addNewColumn .= '</table></div></form></div>'; 1413 return $addNewColumn; 1414 } 1415 1416 /** 1417 * Get HTML for editing page central columns 1418 * 1419 * @param array $selected_fld Array containing the selected fields 1420 * @param string $selected_db String containing the name of database 1421 * 1422 * @return string HTML for complete editing page for central columns 1423 */ 1424 public function getHtmlForEditingPage(array $selected_fld, $selected_db) 1425 { 1426 $html = '<form id="multi_edit_central_columns">'; 1427 $header_cells = array( 1428 __('Name'), __('Type'), __('Length/Values'), __('Default'), 1429 __('Collation'), __('Attributes'), __('Null'), __('A_I') 1430 ); 1431 $html .= $this->getEditTableHeader($header_cells); 1432 $selected_fld_safe = array(); 1433 foreach ($selected_fld as $key) { 1434 $selected_fld_safe[] = $this->dbi->escapeString($key); 1435 } 1436 $columns_list = implode("','", $selected_fld_safe); 1437 $columns_list = "'" . $columns_list . "'"; 1438 $list_detail_cols = $this->findExistingColNames($selected_db, $columns_list, true); 1439 $row_num = 0; 1440 foreach ($list_detail_cols as $row) { 1441 $tableHtmlRow = $this->getHtmlForEditTableRow( 1442 $row, 1443 $row_num 1444 ); 1445 $html .= $tableHtmlRow; 1446 $row_num++; 1447 } 1448 $html .= '</table>'; 1449 $html .= $this->getEditTableFooter(); 1450 $html .= '</form>'; 1451 return $html; 1452 } 1453} 1454