CentralColumns.php 53 KB

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