Console.class.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Used to render the console of PMA's pages
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. require_once 'libraries/Scripts.class.php';
  12. require_once 'libraries/Util.class.php';
  13. require_once 'libraries/bookmark.lib.php';
  14. /**
  15. * Class used to output the console
  16. *
  17. * @package PhpMyAdmin
  18. */
  19. class PMA_Console
  20. {
  21. /**
  22. * Whether to display anything
  23. *
  24. * @access private
  25. * @var bool
  26. */
  27. private $_isEnabled;
  28. /**
  29. * Creates a new class instance
  30. */
  31. public function __construct()
  32. {
  33. $this->_isEnabled = true;
  34. }
  35. /**
  36. * Whether we are servicing an ajax request.
  37. * We can't simply use $GLOBALS['is_ajax_request']
  38. * here since it may have not been initialised yet.
  39. *
  40. * @access private
  41. * @var bool
  42. */
  43. private $_isAjax;
  44. /**
  45. * Set the ajax flag to indicate whether
  46. * we are servicing an ajax request
  47. *
  48. * @param bool $isAjax Whether we are servicing an ajax request
  49. *
  50. * @return void
  51. */
  52. public function setAjax($isAjax)
  53. {
  54. $this->_isAjax = !!$isAjax;
  55. }
  56. /**
  57. * Disables the rendering of the footer
  58. *
  59. * @return void
  60. */
  61. public function disable()
  62. {
  63. $this->_isEnabled = false;
  64. }
  65. /**
  66. * Renders the bookmark content
  67. *
  68. * @access public
  69. * @return string
  70. */
  71. public static function getBookmarkContent()
  72. {
  73. $output = '';
  74. $cfgBookmark = PMA_Bookmark_getParams();
  75. if ($cfgBookmark) {
  76. $tpl_bookmark_actions
  77. = '<span class="action collapse">' . __('Collapse') . '</span> '
  78. . '<span class="action expand">' . __('Expand') . '</span> '
  79. . '<span class="action requery">' . __('Requery') . '</span> '
  80. . '<span class="action edit_bookmark">' . __('Edit') . '</span> '
  81. . '<span class="action delete_bookmark">' . __('Delete')
  82. . '</span> '
  83. . '<span class="text targetdb">' . __('Database')
  84. . ': <span>%s</span></span>';
  85. $bookmarks = PMA_Bookmark_getList();
  86. $output .= '<div class="message welcome"><span>';
  87. $count_bookmarks = count($bookmarks);
  88. if ($count_bookmarks > 0) {
  89. $bookmarks_message = sprintf(
  90. _ngettext(
  91. 'Total %d bookmark',
  92. 'Total %d bookmarks',
  93. $count_bookmarks
  94. ),
  95. $count_bookmarks
  96. );
  97. $private_message = sprintf(
  98. '<span class="bookmark_label">%1$s</span>',
  99. __('private')
  100. );
  101. $shared_message = sprintf(
  102. '<span class="bookmark_label shared">%1$s</span>',
  103. __('shared')
  104. );
  105. $output .= sprintf(
  106. /* l10n: First parameter will be replaced with the translation for Total and the number of bookmarks, second one with the translation for private and the third one, with the translation for shared */
  107. __('%1$s, %2$s and %3$s bookmarks included'),
  108. $bookmarks_message,
  109. $private_message,
  110. $shared_message
  111. );
  112. } else {
  113. $output .= __('No bookmarks');
  114. }
  115. unset($count_bookmarks, $private_message, $shared_message);
  116. $output .= '</span></div>';
  117. foreach ($bookmarks as $val) {
  118. $output .= '<div class="message collapsed bookmark" bookmarkid="'
  119. . $val['id'] . '" targetdb="' . htmlspecialchars($val['db'])
  120. . '"><div class="action_content">'
  121. . sprintf($tpl_bookmark_actions, htmlspecialchars($val['db']))
  122. . '</div><span class="bookmark_label '
  123. . ($val['shared'] ? 'shared' : '') . '">'
  124. . htmlspecialchars($val['label'])
  125. . '</span> <span class="query">'
  126. . htmlspecialchars($val['query'])
  127. . '</span></div>';
  128. }
  129. }
  130. return $output;
  131. }
  132. /**
  133. * Returns the list of JS scripts required by console
  134. *
  135. * @return array list of scripts
  136. */
  137. public function getScripts()
  138. {
  139. return array('console.js');
  140. }
  141. /**
  142. * Gets the history
  143. *
  144. * @param string $tpl_query_actions the template for query actions
  145. *
  146. * @return string $output the generated HTML for history
  147. *
  148. * @access private
  149. *
  150. */
  151. private function _getHistory($tpl_query_actions)
  152. {
  153. $output = '';
  154. $_sql_history = PMA_getHistory($GLOBALS['cfg']['Server']['user']);
  155. if (! empty($_sql_history)) {
  156. foreach (array_reverse($_sql_history) as $record) {
  157. $isSelect = preg_match(
  158. '@^SELECT[[:space:]]+@i', $record['sqlquery']
  159. );
  160. $output .= '<div class="message history collapsed hide'
  161. . ($isSelect ? ' select' : '')
  162. . '" targetdb="'
  163. . htmlspecialchars($record['db'])
  164. . '" targettable="' . htmlspecialchars($record['table'])
  165. . '"><div class="action_content">'
  166. . sprintf(
  167. $tpl_query_actions,
  168. htmlspecialchars($record['db']),
  169. (isset($record['timevalue'])
  170. ? $record['timevalue']
  171. : __('During current session')
  172. )
  173. )
  174. . '</div><span class="query">'
  175. . htmlspecialchars($record['sqlquery'])
  176. . '</span></div>';
  177. }
  178. }
  179. return $output;
  180. }
  181. /**
  182. * Renders the console
  183. *
  184. * @access public
  185. * @return string
  186. */
  187. public function getDisplay()
  188. {
  189. $output = '';
  190. if ((! $this->_isAjax) && $this->_isEnabled) {
  191. $cfgBookmark = PMA_Bookmark_getParams();
  192. $output .= '<div id="pma_console_container"><div id="pma_console">';
  193. // The templates, use sprintf() to output them
  194. // There're white space at the end of every <span>,
  195. // for double-click selection
  196. $tpl_query_actions = '<span class="action collapse">' . __('Collapse')
  197. . '</span> '
  198. . '<span class="action expand">' . __('Expand') . '</span> '
  199. . '<span class="action requery">' . __('Requery') . '</span> '
  200. . '<span class="action edit">' . __('Edit') . '</span> '
  201. . '<span class="action explain">' . __('Explain') . '</span> '
  202. . '<span class="action profiling">' . __('Profiling') . '</span> '
  203. . ($cfgBookmark ? '<span class="action bookmark">'
  204. . __('Bookmark') . '</span> ' : '')
  205. . '<span class="text failed">' . __('Query failed') . '</span> '
  206. . '<span class="text targetdb">' . __('Database')
  207. . ': <span>%s</span></span> '
  208. . '<span class="text query_time">' . __(
  209. 'Queried time'
  210. ) . ': <span>%s</span></span> ';
  211. // Console toolbar
  212. $output .= '<div class="toolbar collapsed">';
  213. $output .= '<div class="switch_button console_switch">';
  214. $output .= PMA_Util::getImage('console.png', __('SQL Query Console'));
  215. $output .= '<span>' . __('Console') . '</span></div>';
  216. $output .= '<div class="button clear"><span>'
  217. . __('Clear') . '</span></div>';
  218. $output .= '<div class="button history"><span>'
  219. . __('History') . '</span></div>';
  220. $output .= '<div class="button options"><span>'
  221. . __('Options') . '</span></div>';
  222. if ($cfgBookmark) {
  223. $output .= '<div class="button bookmarks"><span>'
  224. . __('Bookmarks') . '</span></div>';
  225. }
  226. $output .= '<div class="button debug hide"><span>'
  227. . __('Debug SQL') . '</span></div>';
  228. $output .= '</div>'; // Toolbar end
  229. // Console messages
  230. $output .= '<div class="content">';
  231. $output .= '<div class="console_message_container">'
  232. . '<div class="message welcome"><span>'
  233. . '<span id="instructions-0">'
  234. . __('Press Ctrl+Enter to execute query') . '</span>'
  235. . '<span class="hide" id="instructions-1">'
  236. . __('Press Enter to execute query') . '</span>'
  237. . '</span></div>';
  238. $output .= $this->_getHistory($tpl_query_actions);
  239. $output .= '</div>'; // .console_message_container
  240. $output .= '<div class="query_input">'
  241. . '<span class="console_query_input"></span>'
  242. . '</div>';
  243. $output .= '</div>'; // Messages end
  244. // Dark the console while other cards cover it
  245. $output .= '<div class="mid_layer"></div>';
  246. // Debug SQL card
  247. $output .= '<div class="card" id="debug_console">';
  248. $output .= '<div class="toolbar">'
  249. . '<div class="button order order_asc">'
  250. . '<span>' . __('ascending') . '</span>'
  251. . '</div>'
  252. . '<div class="button order order_desc">'
  253. . '<span>' . __('descending') . '</span>'
  254. . '</div>'
  255. . '<div class="text">'
  256. . '<span>' . __('Order:') . '</span>'
  257. . '</div>'
  258. . '<div class="switch_button">'
  259. . '<span>' . __('Debug SQL') . '</span>'
  260. . '</div>'
  261. . '<div class="button order_by sort_count">'
  262. . '<span>' . __('Count') . '</span>'
  263. . '</div>'
  264. . '<div class="button order_by sort_exec">'
  265. . '<span>' . __('Execution order') . '</span>'
  266. . '</div>'
  267. . '<div class="button order_by sort_time">'
  268. . '<span>' . __('Time taken') . '</span>'
  269. . '</div>'
  270. . '<div class="text">'
  271. . '<span>' . __('Order by:') . '</span>'
  272. . '</div>'
  273. . '<div class="button group_queries">'
  274. . '<span>' . __('Group queries') . '</span>'
  275. . '</div>'
  276. . '<div class="button ungroup_queries">'
  277. . '<span>' . __('Ungroup queries') . '</span>'
  278. . '</div>'
  279. . '</div>'; // Toolbar
  280. $output .= '<div class="content debug">';
  281. $output .= '<div class="message welcome"></div>';
  282. $output .= '<div class="debugLog"></div>';
  283. $output .= '</div>'; // Content
  284. $output .= '<div class="templates">'
  285. . '<div class="debug_query action_content">'
  286. . '<span class="action collapse">' . __('Collapse') . '</span> '
  287. . '<span class="action expand">' . __('Expand') . '</span> '
  288. . '<span class="action dbg_show_trace">' . __('Show trace')
  289. . '</span> '
  290. . '<span class="action dbg_hide_trace">' . __('Hide trace')
  291. . '</span> '
  292. . '<span class="text count hide">' . __('Count:')
  293. . ' <span></span></span>'
  294. . '<span class="text time">' . __('Time taken:')
  295. . ' <span></span></span>'
  296. . '</div>'
  297. . '</div>'; // Template
  298. $output .= '</div>'; // Debug SQL card
  299. // Bookmarks card:
  300. if ($cfgBookmark) {
  301. $output .= '<div class="card" id="pma_bookmarks">';
  302. $output .= '<div class="toolbar">'
  303. . '<div class="switch_button"><span>' . __('Bookmarks')
  304. . '</span></div>';
  305. $output .= '<div class="button refresh"><span>'
  306. . __('Refresh') . '</span></div>';
  307. $output .= '<div class="button add"><span>'
  308. . __('Add') . '</span></div>';
  309. $output .= '</div><div class="content bookmark">';
  310. $output .= $this->getBookmarkContent();
  311. $output .= '</div>';
  312. $output .= '<div class="mid_layer"></div>';
  313. $output .= '<div class="card add">';
  314. $output .= '<div class="toolbar">'
  315. . '<div class="switch_button"><span>'
  316. . __('Add bookmark')
  317. . '</span></div>';
  318. $output .= '</div><div class="content add_bookmark">'
  319. . '<div class="options">'
  320. . '<label>' . __('Label')
  321. . ': <input type="text" name="label"></label> '
  322. . '<label>' . __('Target database')
  323. . ': <input type="text" name="targetdb"></label> '
  324. . '<label><input type="checkbox" name="shared">'
  325. . __('Share this bookmark') . '</label>'
  326. . '<button type="submit" name="submit">Ok</button>'
  327. . '</div>' // .options
  328. . '<div class="query_input">'
  329. . '<span class="bookmark_add_input"></span></div>';
  330. $output .= '</div>';
  331. $output .= '</div>'; // Add bookmark card
  332. $output .= '</div>'; // Bookmarks card
  333. }
  334. // Options card:
  335. $output .= '<div class="card" id="pma_console_options">';
  336. $output .= '<div class="toolbar">'
  337. . '<div class="switch_button"><span>' . __('Options')
  338. . '</span></div>';
  339. $output .= '<div class="button default"><span>'
  340. . __('Set default') . '</span></div>';
  341. $output .= '</div><div class="content">'
  342. . '<label><input type="checkbox" name="always_expand">'
  343. . __('Always expand query messages') . '</label><br>'
  344. . '<label><input type="checkbox" name="start_history">'
  345. . __('Show query history at start') . '</label><br>'
  346. . '<label><input type="checkbox" name="current_query">'
  347. . __('Show current browsing query') . '</label><br>'
  348. . '<label><input type="checkbox" name="enter_executes">'
  349. . __(
  350. 'Execute queries on Enter and insert new line with Shift + '
  351. . 'Enter. To make this permanent, view settings.'
  352. ) . '</label><br>'
  353. . '<label><input type="checkbox" name="dark_theme">'
  354. . __('Switch to dark theme') . '</label><br>'
  355. . '</div>';
  356. $output .= '</div>'; // Options card
  357. $output .= '<div class="templates">'
  358. // Templates for console message actions
  359. . '<div class="query_actions">'
  360. . sprintf($tpl_query_actions, '', '')
  361. . '</div>'
  362. . '</div>';
  363. $output .= '</div></div>'; // #console and #pma_console_container ends
  364. }
  365. return $output;
  366. }
  367. }