ProcessesController.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Holds the PhpMyAdmin\Controllers\Server\Status\ProcessesController
  5. *
  6. * @package PhpMyAdmin\Controllers
  7. */
  8. declare(strict_types=1);
  9. namespace PhpMyAdmin\Controllers\Server\Status;
  10. use PhpMyAdmin\Message;
  11. use PhpMyAdmin\Util;
  12. /**
  13. * Class ProcessesController
  14. * @package PhpMyAdmin\Controllers\Server\Status
  15. */
  16. class ProcessesController extends AbstractController
  17. {
  18. /**
  19. * @param array $params Request parameters
  20. * @return string
  21. */
  22. public function index(array $params): string
  23. {
  24. $isChecked = false;
  25. if (! empty($params['showExecuting'])) {
  26. $isChecked = true;
  27. }
  28. $urlParams = [
  29. 'ajax_request' => true,
  30. 'full' => $params['full'] ?? '',
  31. 'column_name' => $params['column_name'] ?? '',
  32. 'order_by_field' => $params['order_by_field'] ?? '',
  33. 'sort_order' => $params['sort_order'] ?? '',
  34. ];
  35. $serverProcessList = $this->getList($params);
  36. return $this->template->render('server/status/processes/index', [
  37. 'url_params' => $urlParams,
  38. 'is_checked' => $isChecked,
  39. 'server_process_list' => $serverProcessList,
  40. ]);
  41. }
  42. /**
  43. * Only sends the process list table
  44. *
  45. * @param array $params Request parameters
  46. * @return string
  47. */
  48. public function refresh(array $params): string
  49. {
  50. return $this->getList($params);
  51. }
  52. /**
  53. * @param array $params Request parameters
  54. * @return array
  55. */
  56. public function kill(array $params): array
  57. {
  58. $kill = (int) $params['kill'];
  59. $query = $this->dbi->getKillQuery($kill);
  60. if ($this->dbi->tryQuery($query)) {
  61. $message = Message::success(
  62. __('Thread %s was successfully killed.')
  63. );
  64. $this->response->setRequestStatus(true);
  65. } else {
  66. $message = Message::error(
  67. __(
  68. 'phpMyAdmin was unable to kill thread %s.'
  69. . ' It probably has already been closed.'
  70. )
  71. );
  72. $this->response->setRequestStatus(false);
  73. }
  74. $message->addParam($kill);
  75. $json = [];
  76. $json['message'] = $message;
  77. return $json;
  78. }
  79. /**
  80. * @param array $params Request parameters
  81. * @return string
  82. */
  83. private function getList(array $params): string
  84. {
  85. $urlParams = [];
  86. $showFullSql = ! empty($params['full']);
  87. if ($showFullSql) {
  88. $urlParams['full'] = '';
  89. } else {
  90. $urlParams['full'] = 1;
  91. }
  92. // This array contains display name and real column name of each
  93. // sortable column in the table
  94. $sortableColumns = [
  95. [
  96. 'column_name' => __('ID'),
  97. 'order_by_field' => 'Id',
  98. ],
  99. [
  100. 'column_name' => __('User'),
  101. 'order_by_field' => 'User',
  102. ],
  103. [
  104. 'column_name' => __('Host'),
  105. 'order_by_field' => 'Host',
  106. ],
  107. [
  108. 'column_name' => __('Database'),
  109. 'order_by_field' => 'db',
  110. ],
  111. [
  112. 'column_name' => __('Command'),
  113. 'order_by_field' => 'Command',
  114. ],
  115. [
  116. 'column_name' => __('Time'),
  117. 'order_by_field' => 'Time',
  118. ],
  119. [
  120. 'column_name' => __('Status'),
  121. 'order_by_field' => 'State',
  122. ],
  123. [
  124. 'column_name' => __('Progress'),
  125. 'order_by_field' => 'Progress',
  126. ],
  127. [
  128. 'column_name' => __('SQL query'),
  129. 'order_by_field' => 'Info',
  130. ],
  131. ];
  132. $sortableColCount = count($sortableColumns);
  133. $sqlQuery = $showFullSql
  134. ? 'SHOW FULL PROCESSLIST'
  135. : 'SHOW PROCESSLIST';
  136. if ((! empty($params['order_by_field'])
  137. && ! empty($params['sort_order']))
  138. || ! empty($params['showExecuting'])
  139. ) {
  140. $urlParams['order_by_field'] = $params['order_by_field'];
  141. $urlParams['sort_order'] = $params['sort_order'];
  142. $urlParams['showExecuting'] = $params['showExecuting'];
  143. $sqlQuery = 'SELECT * FROM `INFORMATION_SCHEMA`.`PROCESSLIST` ';
  144. }
  145. if (! empty($params['showExecuting'])) {
  146. $sqlQuery .= ' WHERE state != "" ';
  147. }
  148. if (! empty($params['order_by_field']) && ! empty($params['sort_order'])) {
  149. $sqlQuery .= ' ORDER BY '
  150. . Util::backquote($params['order_by_field'])
  151. . ' ' . $params['sort_order'];
  152. }
  153. $result = $this->dbi->query($sqlQuery);
  154. $columns = [];
  155. foreach ($sortableColumns as $columnKey => $column) {
  156. $is_sorted = ! empty($params['order_by_field'])
  157. && ! empty($params['sort_order'])
  158. && ($params['order_by_field'] == $column['order_by_field']);
  159. $column['sort_order'] = 'ASC';
  160. if ($is_sorted && $params['sort_order'] === 'ASC') {
  161. $column['sort_order'] = 'DESC';
  162. }
  163. if (isset($params['showExecuting'])) {
  164. $column['showExecuting'] = 'on';
  165. }
  166. $columns[$columnKey] = [
  167. 'name' => $column['column_name'],
  168. 'params' => $column,
  169. 'is_sorted' => $is_sorted,
  170. 'sort_order' => $column['sort_order'],
  171. 'has_full_query' => false,
  172. 'is_full' => false,
  173. ];
  174. if (0 === --$sortableColCount) {
  175. $columns[$columnKey]['has_full_query'] = true;
  176. if ($showFullSql) {
  177. $columns[$columnKey]['is_full'] = true;
  178. }
  179. }
  180. }
  181. $rows = [];
  182. while ($process = $this->dbi->fetchAssoc($result)) {
  183. // Array keys need to modify due to the way it has used
  184. // to display column values
  185. if ((! empty($params['order_by_field']) && ! empty($params['sort_order']))
  186. || ! empty($params['showExecuting'])
  187. ) {
  188. foreach (array_keys($process) as $key) {
  189. $newKey = ucfirst(mb_strtolower($key));
  190. if ($newKey !== $key) {
  191. $process[$newKey] = $process[$key];
  192. unset($process[$key]);
  193. }
  194. }
  195. }
  196. $rows[] = [
  197. 'id' => $process['Id'],
  198. 'user' => $process['User'],
  199. 'host' => $process['Host'],
  200. 'db' => ! isset($process['db']) || strlen($process['db']) === 0 ? '' : $process['db'],
  201. 'command' => $process['Command'],
  202. 'time' => $process['Time'],
  203. 'state' => ! empty($process['State']) ? $process['State'] : '---',
  204. 'progress' => ! empty($process['Progress']) ? $process['Progress'] : '---',
  205. 'info' => ! empty($process['Info']) ? Util::formatSql(
  206. $process['Info'],
  207. ! $showFullSql
  208. ) : '---',
  209. ];
  210. }
  211. return $this->template->render('server/status/processes/list', [
  212. 'columns' => $columns,
  213. 'rows' => $rows,
  214. 'refresh_params' => $urlParams,
  215. ]);
  216. }
  217. }