Designer.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Holds the PhpMyAdmin\Database\Designer class
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. namespace PhpMyAdmin\Database;
  9. use PhpMyAdmin\DatabaseInterface;
  10. use PhpMyAdmin\Message;
  11. use PhpMyAdmin\Plugins;
  12. use PhpMyAdmin\Plugins\SchemaPlugin;
  13. use PhpMyAdmin\Relation;
  14. use PhpMyAdmin\Template;
  15. use PhpMyAdmin\Util;
  16. /**
  17. * Set of functions related to database designer
  18. *
  19. * @package PhpMyAdmin
  20. */
  21. class Designer
  22. {
  23. /**
  24. * @var Relation $relation
  25. */
  26. private $relation;
  27. /**
  28. * Constructor
  29. */
  30. public function __construct()
  31. {
  32. $this->relation = new Relation();
  33. }
  34. /**
  35. * Function to get html for displaying the page edit/delete form
  36. *
  37. * @param string $db database name
  38. * @param string $operation 'edit' or 'delete' depending on the operation
  39. *
  40. * @return string html content
  41. */
  42. public function getHtmlForEditOrDeletePages($db, $operation)
  43. {
  44. $cfgRelation = $this->relation->getRelationsParam();
  45. return Template::get('database/designer/edit_delete_pages')->render([
  46. 'db' => $db,
  47. 'operation' => $operation,
  48. 'pdfwork' => $cfgRelation['pdfwork'],
  49. 'pages' => $this->getPageIdsAndNames($db),
  50. ]);
  51. }
  52. /**
  53. * Function to get html for displaying the page save as form
  54. *
  55. * @param string $db database name
  56. *
  57. * @return string html content
  58. */
  59. public function getHtmlForPageSaveAs($db)
  60. {
  61. $cfgRelation = $this->relation->getRelationsParam();
  62. return Template::get('database/designer/page_save_as')->render([
  63. 'db' => $db,
  64. 'pdfwork' => $cfgRelation['pdfwork'],
  65. 'pages' => $this->getPageIdsAndNames($db),
  66. ]);
  67. }
  68. /**
  69. * Retrieve IDs and names of schema pages
  70. *
  71. * @param string $db database name
  72. *
  73. * @return array array of schema page id and names
  74. */
  75. private function getPageIdsAndNames($db)
  76. {
  77. $result = [];
  78. $cfgRelation = $this->relation->getRelationsParam();
  79. if (! $cfgRelation['pdfwork']) {
  80. return $result;
  81. }
  82. $page_query = "SELECT `page_nr`, `page_descr` FROM "
  83. . Util::backquote($cfgRelation['db']) . "."
  84. . Util::backquote($cfgRelation['pdf_pages'])
  85. . " WHERE db_name = '" . $GLOBALS['dbi']->escapeString($db) . "'"
  86. . " ORDER BY `page_descr`";
  87. $page_rs = $this->relation->queryAsControlUser(
  88. $page_query,
  89. false,
  90. DatabaseInterface::QUERY_STORE
  91. );
  92. while ($curr_page = $GLOBALS['dbi']->fetchAssoc($page_rs)) {
  93. $result[intval($curr_page['page_nr'])] = $curr_page['page_descr'];
  94. }
  95. return $result;
  96. }
  97. /**
  98. * Function to get html for displaying the schema export
  99. *
  100. * @param string $db database name
  101. * @param int $page the page to be exported
  102. *
  103. * @return string
  104. */
  105. public function getHtmlForSchemaExport($db, $page)
  106. {
  107. /* Scan for schema plugins */
  108. /* @var $export_list SchemaPlugin[] */
  109. $export_list = Plugins::getPlugins(
  110. "schema",
  111. 'libraries/classes/Plugins/Schema/',
  112. null
  113. );
  114. /* Fail if we didn't find any schema plugin */
  115. if (empty($export_list)) {
  116. return Message::error(
  117. __('Could not load schema plugins, please check your installation!')
  118. )->getDisplay();
  119. }
  120. return Template::get('database/designer/schema_export')
  121. ->render(
  122. [
  123. 'db' => $db,
  124. 'page' => $page,
  125. 'export_list' => $export_list
  126. ]
  127. );
  128. }
  129. /**
  130. * Returns HTML for including some variable to be accessed by JavaScript
  131. *
  132. * @param array $script_tables array on foreign key support for each table
  133. * @param array $script_contr initialization data array
  134. * @param Designer\DesignerTable[] $script_display_field displayed tables in designer with their display fields
  135. * @param int $display_page page number of the selected page
  136. *
  137. * @return string html
  138. */
  139. public function getHtmlForJsFields(
  140. array $script_tables,
  141. array $script_contr,
  142. array $script_display_field,
  143. $display_page
  144. ) {
  145. $displayedFields = [];
  146. foreach ($script_display_field as $designerTable) {
  147. if ($designerTable->getDisplayField() !== null) {
  148. $displayedFields[$designerTable->getTableName()] = $designerTable->getDisplayField();
  149. }
  150. }
  151. $cfgRelation = $this->relation->getRelationsParam();
  152. $designerConfig = new \stdClass();
  153. $designerConfig->db = $_GET['db'];
  154. $designerConfig->scriptTables = $script_tables;
  155. $designerConfig->scriptContr = $script_contr;
  156. $designerConfig->server = $GLOBALS['server'];
  157. $designerConfig->scriptDisplayField = $displayedFields;
  158. $designerConfig->displayPage = (int) $display_page;
  159. $designerConfig->tablesEnabled = $cfgRelation['pdfwork'];
  160. return Template::get('database/designer/js_fields')->render([
  161. 'designer_config' => json_encode($designerConfig)
  162. ]);
  163. }
  164. /**
  165. * Returns HTML for the menu bar of the designer page
  166. *
  167. * @param boolean $visualBuilder whether this is visual query builder
  168. * @param string $selectedPage name of the selected page
  169. * @param array $paramsArray array with class name for various buttons
  170. * on side menu
  171. *
  172. * @return string html
  173. */
  174. public function getPageMenu($visualBuilder, $selectedPage, array $paramsArray)
  175. {
  176. return Template::get('database/designer/side_menu')->render([
  177. 'visual_builder' => $visualBuilder,
  178. 'selected_page' => $selectedPage,
  179. 'params_array' => $paramsArray,
  180. 'theme' => $GLOBALS['PMA_Theme'],
  181. ]);
  182. }
  183. /**
  184. * Returns array of stored values of Designer Settings
  185. *
  186. * @return array stored values
  187. */
  188. private function getSideMenuParamsArray()
  189. {
  190. $params = [];
  191. $cfgRelation = $this->relation->getRelationsParam();
  192. if ($cfgRelation['designersettingswork']) {
  193. $query = 'SELECT `settings_data` FROM '
  194. . Util::backquote($cfgRelation['db']) . '.'
  195. . Util::backquote($cfgRelation['designer_settings'])
  196. . ' WHERE ' . Util::backquote('username') . ' = "'
  197. . $GLOBALS['dbi']->escapeString($GLOBALS['cfg']['Server']['user'])
  198. . '";';
  199. $result = $GLOBALS['dbi']->fetchSingleRow($query);
  200. $params = json_decode($result['settings_data'], true);
  201. }
  202. return $params;
  203. }
  204. /**
  205. * Returns class names for various buttons on Designer Side Menu
  206. *
  207. * @return array class names of various buttons
  208. */
  209. public function returnClassNamesFromMenuButtons()
  210. {
  211. $classes_array = [];
  212. $params_array = $this->getSideMenuParamsArray();
  213. if (isset($params_array['angular_direct'])
  214. && $params_array['angular_direct'] == 'angular'
  215. ) {
  216. $classes_array['angular_direct'] = 'M_butt_Selected_down';
  217. } else {
  218. $classes_array['angular_direct'] = 'M_butt';
  219. }
  220. if (isset($params_array['snap_to_grid'])
  221. && $params_array['snap_to_grid'] == 'on'
  222. ) {
  223. $classes_array['snap_to_grid'] = 'M_butt_Selected_down';
  224. } else {
  225. $classes_array['snap_to_grid'] = 'M_butt';
  226. }
  227. if (isset($params_array['pin_text'])
  228. && $params_array['pin_text'] == 'true'
  229. ) {
  230. $classes_array['pin_text'] = 'M_butt_Selected_down';
  231. } else {
  232. $classes_array['pin_text'] = 'M_butt';
  233. }
  234. if (isset($params_array['relation_lines'])
  235. && $params_array['relation_lines'] == 'false'
  236. ) {
  237. $classes_array['relation_lines'] = 'M_butt_Selected_down';
  238. } else {
  239. $classes_array['relation_lines'] = 'M_butt';
  240. }
  241. if (isset($params_array['small_big_all'])
  242. && $params_array['small_big_all'] == 'v'
  243. ) {
  244. $classes_array['small_big_all'] = 'M_butt_Selected_down';
  245. } else {
  246. $classes_array['small_big_all'] = 'M_butt';
  247. }
  248. if (isset($params_array['side_menu'])
  249. && $params_array['side_menu'] == 'true'
  250. ) {
  251. $classes_array['side_menu'] = 'M_butt_Selected_down';
  252. } else {
  253. $classes_array['side_menu'] = 'M_butt';
  254. }
  255. return $classes_array;
  256. }
  257. /**
  258. * Returns HTML for the canvas element
  259. *
  260. * @return string html
  261. */
  262. public function getHtmlCanvas()
  263. {
  264. return Template::get('database/designer/canvas')->render();
  265. }
  266. /**
  267. * Return HTML for the table list
  268. *
  269. * @return string html
  270. */
  271. public function getHtmlTableList()
  272. {
  273. return Template::get('database/designer/table_list')->render([
  274. 'theme' => $GLOBALS['PMA_Theme'],
  275. ]);
  276. }
  277. /**
  278. * Get HTML to display tables on designer page
  279. *
  280. * @param string $db The database name from the request
  281. * @param array $designerTables The designer tables
  282. * @param array $tab_pos tables positions
  283. * @param int $display_page page number of the selected page
  284. * @param array $tab_column table column info
  285. * @param array $tables_all_keys all indices
  286. * @param array $tables_pk_or_unique_keys unique or primary indices
  287. *
  288. * @return string html
  289. */
  290. public function getDatabaseTables(
  291. $db,
  292. array $designerTables,
  293. array $tab_pos,
  294. $display_page,
  295. array $tab_column,
  296. array $tables_all_keys,
  297. array $tables_pk_or_unique_keys
  298. ) {
  299. return Template::get('database/designer/database_tables')->render([
  300. 'db' => $GLOBALS['db'],
  301. 'get_db' => $db,
  302. 'has_query' => isset($_REQUEST['query']),
  303. 'tab_pos' => $tab_pos,
  304. 'display_page' => $display_page,
  305. 'tab_column' => $tab_column,
  306. 'tables_all_keys' => $tables_all_keys,
  307. 'tables_pk_or_unique_keys' => $tables_pk_or_unique_keys,
  308. 'tables' => $designerTables,
  309. 'theme' => $GLOBALS['PMA_Theme'],
  310. ]);
  311. }
  312. /**
  313. * Returns HTML for the new relations panel.
  314. *
  315. * @return string html
  316. */
  317. public function getNewRelationPanel()
  318. {
  319. return Template::get('database/designer/new_relation_panel')
  320. ->render();
  321. }
  322. /**
  323. * Returns HTML for the relations delete panel
  324. *
  325. * @return string html
  326. */
  327. public function getDeleteRelationPanel()
  328. {
  329. return Template::get('database/designer/delete_relation_panel')
  330. ->render();
  331. }
  332. /**
  333. * Returns HTML for the options panel
  334. *
  335. * @return string html
  336. */
  337. public function getOptionsPanel()
  338. {
  339. return Template::get('database/designer/options_panel')->render();
  340. }
  341. /**
  342. * Get HTML for the 'rename to' panel
  343. *
  344. * @return string html
  345. */
  346. public function getRenameToPanel()
  347. {
  348. return Template::get('database/designer/rename_to_panel')
  349. ->render();
  350. }
  351. /**
  352. * Returns HTML for the 'having' panel
  353. *
  354. * @return string html
  355. */
  356. public function getHavingQueryPanel()
  357. {
  358. return Template::get('database/designer/having_query_panel')
  359. ->render();
  360. }
  361. /**
  362. * Returns HTML for the 'aggregate' panel
  363. *
  364. * @return string html
  365. */
  366. public function getAggregateQueryPanel()
  367. {
  368. return Template::get('database/designer/aggregate_query_panel')
  369. ->render();
  370. }
  371. /**
  372. * Returns HTML for the 'where' panel
  373. *
  374. * @return string html
  375. */
  376. public function getWhereQueryPanel()
  377. {
  378. return Template::get('database/designer/where_query_panel')
  379. ->render();
  380. }
  381. /**
  382. * Returns HTML for the query details panel
  383. *
  384. * @param string $db Database name
  385. *
  386. * @return string html
  387. */
  388. public function getQueryDetails($db)
  389. {
  390. return Template::get('database/designer/query_details')->render([
  391. 'db' => $db,
  392. ]);
  393. }
  394. }