Use usort() instead of natsort()
[phpmyadmin.git] / libraries / controllers / table / TableRelationController.php
blob13967f29c9bafca03a606a02098e7386be6b241e
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Holds the PMA\TableRelationController
6 * @package PMA
7 */
9 namespace PMA\libraries\controllers\table;
11 require_once 'libraries/index.lib.php';
13 use PMA\libraries\controllers\TableController;
14 use PMA\libraries\DatabaseInterface;
15 use PMA\libraries\Index;
16 use PMA\libraries\Table;
17 use PMA\libraries\Template;
18 use PMA\libraries\Util;
20 /**
21 * Handles table relation logic
23 * @package PhpMyAdmin
25 class TableRelationController extends TableController
27 /**
28 * @var array $options_array
30 protected $options_array;
32 /**
33 * @var array $cfgRelation
35 protected $cfgRelation;
37 /**
38 * @var array $existrel
40 protected $existrel;
42 /**
43 * @var string $disp
45 protected $disp;
47 /**
48 * @var string $tbl_storage_engine
50 protected $tbl_storage_engine;
52 /**
53 * @var array $existrel_foreign
55 protected $existrel_foreign;
57 /**
58 * @var Table $udp_query
60 protected $upd_query;
62 /**
63 * Constructor
65 * @param array $options_array Options
66 * @param array $cfgRelation Config relation
67 * @param string $tbl_storage_engine Table storage engine
68 * @param array $existrel Relations
69 * @param array $existrel_foreign External relations
70 * @param string $disp Display
71 * @param string $upd_query Update query
73 public function __construct($options_array, $cfgRelation, $tbl_storage_engine,
74 $existrel, $existrel_foreign, $disp, $upd_query
75 ) {
76 parent::__construct();
78 $this->options_array = $options_array;
79 $this->cfgRelation = $cfgRelation;
80 $this->tbl_storage_engine = $tbl_storage_engine;
81 $this->existrel = $existrel;
82 $this->existrel_foreign = $existrel_foreign;
83 $this->disp = $disp;
84 $this->upd_query = $upd_query;
87 /**
88 * Index
90 * @return void
92 public function indexAction()
94 // Send table of column names to populate corresponding dropdowns depending
95 // on the current selection
96 if (isset($_REQUEST['getDropdownValues'])
97 && $_REQUEST['getDropdownValues'] === 'true'
98 ) {
99 // if both db and table are selected
100 if (isset($_REQUEST['foreignTable'])) {
101 $this->getDropdownValueForTableAction();
102 } else { // if only the db is selected
103 $this->getDropdownValueForDbAction();
105 return;
108 $this->response->getHeader()->getScripts()->addFiles(
109 array(
110 'tbl_relation.js',
111 'indexes.js'
115 // Gets tables information
116 include_once 'libraries/tbl_info.inc.php';
118 // updates for Internal relations
119 if (isset($_POST['destination_db']) && $this->cfgRelation['relwork']) {
120 $this->updateForInternalRelationAction();
123 // updates for foreign keys
124 if (isset($_POST['destination_foreign_db'])) {
125 $this->updateForForeignKeysAction();
128 // Updates for display field
129 if ($this->cfgRelation['displaywork'] && isset($_POST['display_field'])) {
130 $this->updateForDisplayField();
133 // If we did an update, refresh our data
134 if (isset($_POST['destination_db']) && $this->cfgRelation['relwork']) {
135 $this->existrel = PMA_getForeigners(
136 $this->db, $this->table, '', 'internal'
139 if (isset($_POST['destination_foreign_db'])
140 && Util::isForeignKeySupported($this->tbl_storage_engine)
142 $this->existrel_foreign = PMA_getForeigners(
143 $this->db, $this->table, '', 'foreign'
147 if ($this->cfgRelation['displaywork']) {
148 $this->disp = PMA_getDisplayField($this->db, $this->table);
151 // display secondary level tabs if necessary
152 $engine = $this->dbi->getTable($this->db, $this->table)
153 ->getStatusInfo('ENGINE');
155 $this->response->addHTML(
156 Template::get('table/secondary_tabs')->render(
157 array(
158 'url_params' => array(
159 'db' => $GLOBALS['db'],
160 'table' => $GLOBALS['table']
162 'engine' => $engine
166 $this->response->addHTML('<div id="structure_content">');
169 * Dialog
171 // Now find out the columns of our $table
172 // need to use DatabaseInterface::QUERY_STORE with $this->dbi->numRows()
173 // in mysqli
174 $columns = $this->dbi->getColumns($this->db, $this->table);
176 // common form
177 $this->response->addHTML(
178 Template::get('table/relation/common_form')->render(
179 array(
180 'db' => $this->db,
181 'table' => $this->table,
182 'columns' => $columns,
183 'cfgRelation' => $this->cfgRelation,
184 'tbl_storage_engine' => $this->tbl_storage_engine,
185 'existrel' => isset($this->existrel) ? $this->existrel : array(),
186 'existrel_foreign' => isset($this->existrel_foreign)
187 ? $this->existrel_foreign['foreign_keys_data'] : array(),
188 'options_array' => $this->options_array
193 if (Util::isForeignKeySupported($this->tbl_storage_engine)) {
194 $this->response->addHTML(PMA_getHtmlForDisplayIndexes());
196 $this->response->addHTML('</div>');
200 * Update for display field
202 * @return void
204 public function updateForDisplayField()
206 if ($this->upd_query->updateDisplayField(
207 $this->disp, $_POST['display_field'], $this->cfgRelation
210 $this->response->addHTML(
211 Util::getMessage(
212 __('Display column was successfully updated.'),
213 '', 'success'
220 * Update for FK
222 * @return void
224 public function updateForForeignKeysAction()
226 $multi_edit_columns_name = isset($_REQUEST['foreign_key_fields_name'])
227 ? $_REQUEST['foreign_key_fields_name']
228 : null;
230 // (for now, one index name only; we keep the definitions if the
231 // foreign db is not the same)
232 list($html, $preview_sql_data, $display_query, $seen_error)
233 = $this->upd_query->updateForeignKeys(
234 $_POST['destination_foreign_db'],
235 $multi_edit_columns_name, $_POST['destination_foreign_table'],
236 $_POST['destination_foreign_column'], $this->options_array,
237 $this->table,
238 isset($this->existrel_foreign)
239 ? $this->existrel_foreign['foreign_keys_data']
240 : null
242 $this->response->addHTML($html);
244 // If there is a request for SQL previewing.
245 if (isset($_REQUEST['preview_sql'])) {
246 PMA_previewSQL($preview_sql_data);
249 if (!empty($display_query) && !$seen_error) {
250 $GLOBALS['display_query'] = $display_query;
251 $this->response->addHTML(
252 Util::getMessage(
253 __('Your SQL query has been executed successfully.'),
254 null, 'success'
261 * Update for internal relation
263 * @return void
265 public function updateForInternalRelationAction()
267 $multi_edit_columns_name = isset($_REQUEST['fields_name'])
268 ? $_REQUEST['fields_name']
269 : null;
271 if ($this->upd_query->updateInternalRelations(
272 $multi_edit_columns_name,
273 $_POST['destination_db'],
274 $_POST['destination_table'],
275 $_POST['destination_column'],
276 $this->cfgRelation,
277 isset($this->existrel) ? $this->existrel : null
280 $this->response->addHTML(
281 Util::getMessage(
282 __('Internal relationships were successfully updated.'),
283 '', 'success'
290 * Send table columns for foreign table dropdown
292 * @return void
295 public function getDropdownValueForTableAction()
297 $foreignTable = $_REQUEST['foreignTable'];
298 $table_obj = $this->dbi->getTable($_REQUEST['foreignDb'], $foreignTable);
299 // Since views do not have keys defined on them provide the full list of
300 // columns
301 if ($table_obj->isView()) {
302 $columnList = $table_obj->getColumns(false, false);
303 } else {
304 $columnList = $table_obj->getIndexedColumns(false, false);
306 $columns = array();
307 foreach ($columnList as $column) {
308 $columns[] = htmlspecialchars($column);
310 if ($GLOBALS['cfg']['NaturalOrder']) {
311 usort($columns, 'strnatcasecmp');
313 $this->response->addJSON('columns', $columns);
315 // @todo should be: $server->db($db)->table($table)->primary()
316 $primary = Index::getPrimary($foreignTable, $_REQUEST['foreignDb']);
317 if (false === $primary) {
318 return;
321 $this->response->addJSON('primary', array_keys($primary->getColumns()));
325 * Send database selection values for dropdown
327 * @return void
330 public function getDropdownValueForDbAction()
332 $tables = array();
333 $foreign = isset($_REQUEST['foreign']) && $_REQUEST['foreign'] === 'true';
335 if ($foreign) {
336 $query = 'SHOW TABLE STATUS FROM '
337 . Util::backquote($_REQUEST['foreignDb']);
338 $tables_rs = $this->dbi->query(
339 $query,
340 null,
341 DatabaseInterface::QUERY_STORE
344 while ($row = $this->dbi->fetchArray($tables_rs)) {
345 if (isset($row['Engine'])
346 && mb_strtoupper($row['Engine']) == $this->tbl_storage_engine
348 $tables[] = htmlspecialchars($row['Name']);
351 } else {
352 $query = 'SHOW TABLES FROM '
353 . Util::backquote($_REQUEST['foreignDb']);
354 $tables_rs = $this->dbi->query(
355 $query,
356 null,
357 DatabaseInterface::QUERY_STORE
359 while ($row = $this->dbi->fetchArray($tables_rs)) {
360 $tables[] = htmlspecialchars($row[0]);
363 if ($GLOBALS['cfg']['NaturalOrder']) {
364 usort($tables, 'strnatcasecmp');
366 $this->response->addJSON('tables', $tables);