NodeTable.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Functionality for the navigation tree
  5. *
  6. * @package PhpMyAdmin-Navigation
  7. */
  8. declare(strict_types=1);
  9. namespace PhpMyAdmin\Navigation\Nodes;
  10. use PhpMyAdmin\Util;
  11. /**
  12. * Represents a columns node in the navigation tree
  13. *
  14. * @package PhpMyAdmin-Navigation
  15. */
  16. class NodeTable extends NodeDatabaseChild
  17. {
  18. /**
  19. * Initialises the class
  20. *
  21. * @param string $name An identifier for the new node
  22. * @param int $type Type of node, may be one of CONTAINER or OBJECT
  23. * @param bool $isGroup Whether this object has been created
  24. * while grouping nodes
  25. */
  26. public function __construct($name, $type = Node::OBJECT, $isGroup = false)
  27. {
  28. parent::__construct($name, $type, $isGroup);
  29. $this->icon = [];
  30. $this->addIcon(
  31. Util::getScriptNameForOption(
  32. $GLOBALS['cfg']['NavigationTreeDefaultTabTable'],
  33. 'table'
  34. )
  35. );
  36. $this->addIcon(
  37. Util::getScriptNameForOption(
  38. $GLOBALS['cfg']['NavigationTreeDefaultTabTable2'],
  39. 'table'
  40. )
  41. );
  42. $title = Util::getTitleForTarget(
  43. $GLOBALS['cfg']['DefaultTabTable']
  44. );
  45. $this->title = $title;
  46. $scriptName = Util::getScriptNameForOption(
  47. $GLOBALS['cfg']['DefaultTabTable'],
  48. 'table'
  49. );
  50. $this->links = [
  51. 'text' => $scriptName
  52. . '?server=' . $GLOBALS['server']
  53. . '&amp;db=%2$s&amp;table=%1$s'
  54. . '&amp;pos=0',
  55. 'icon' => [
  56. Util::getScriptNameForOption(
  57. $GLOBALS['cfg']['NavigationTreeDefaultTabTable'],
  58. 'table'
  59. )
  60. . '?server=' . $GLOBALS['server']
  61. . '&amp;db=%2$s&amp;table=%1$s',
  62. Util::getScriptNameForOption(
  63. $GLOBALS['cfg']['NavigationTreeDefaultTabTable2'],
  64. 'table'
  65. )
  66. . '?server=' . $GLOBALS['server']
  67. . '&amp;db=%2$s&amp;table=%1$s',
  68. ],
  69. 'title' => $this->title,
  70. ];
  71. $this->classes = 'table';
  72. }
  73. /**
  74. * Returns the number of children of type $type present inside this container
  75. * This method is overridden by the PhpMyAdmin\Navigation\Nodes\NodeDatabase
  76. * and PhpMyAdmin\Navigation\Nodes\NodeTable classes
  77. *
  78. * @param string $type The type of item we are looking for
  79. * ('columns' or 'indexes')
  80. * @param string $searchClause A string used to filter the results of the query
  81. *
  82. * @return int
  83. */
  84. public function getPresence($type = '', $searchClause = '')
  85. {
  86. $retval = 0;
  87. $db = $this->realParent()->realName;
  88. $table = $this->realName;
  89. switch ($type) {
  90. case 'columns':
  91. if (! $GLOBALS['cfg']['Server']['DisableIS']) {
  92. $db = $GLOBALS['dbi']->escapeString($db);
  93. $table = $GLOBALS['dbi']->escapeString($table);
  94. $query = "SELECT COUNT(*) ";
  95. $query .= "FROM `INFORMATION_SCHEMA`.`COLUMNS` ";
  96. $query .= "WHERE `TABLE_NAME`='$table' ";
  97. $query .= "AND `TABLE_SCHEMA`='$db'";
  98. $retval = (int) $GLOBALS['dbi']->fetchValue($query);
  99. } else {
  100. $db = Util::backquote($db);
  101. $table = Util::backquote($table);
  102. $query = "SHOW COLUMNS FROM $table FROM $db";
  103. $retval = (int) $GLOBALS['dbi']->numRows(
  104. $GLOBALS['dbi']->tryQuery($query)
  105. );
  106. }
  107. break;
  108. case 'indexes':
  109. $db = Util::backquote($db);
  110. $table = Util::backquote($table);
  111. $query = "SHOW INDEXES FROM $table FROM $db";
  112. $retval = (int) $GLOBALS['dbi']->numRows(
  113. $GLOBALS['dbi']->tryQuery($query)
  114. );
  115. break;
  116. case 'triggers':
  117. if (! $GLOBALS['cfg']['Server']['DisableIS']) {
  118. $db = $GLOBALS['dbi']->escapeString($db);
  119. $table = $GLOBALS['dbi']->escapeString($table);
  120. $query = "SELECT COUNT(*) ";
  121. $query .= "FROM `INFORMATION_SCHEMA`.`TRIGGERS` ";
  122. $query .= "WHERE `EVENT_OBJECT_SCHEMA` "
  123. . Util::getCollateForIS() . "='$db' ";
  124. $query .= "AND `EVENT_OBJECT_TABLE` "
  125. . Util::getCollateForIS() . "='$table'";
  126. $retval = (int) $GLOBALS['dbi']->fetchValue($query);
  127. } else {
  128. $db = Util::backquote($db);
  129. $table = $GLOBALS['dbi']->escapeString($table);
  130. $query = "SHOW TRIGGERS FROM $db WHERE `Table` = '$table'";
  131. $retval = (int) $GLOBALS['dbi']->numRows(
  132. $GLOBALS['dbi']->tryQuery($query)
  133. );
  134. }
  135. break;
  136. default:
  137. break;
  138. }
  139. return $retval;
  140. }
  141. /**
  142. * Returns the names of children of type $type present inside this container
  143. * This method is overridden by the PhpMyAdmin\Navigation\Nodes\NodeDatabase
  144. * and PhpMyAdmin\Navigation\Nodes\NodeTable classes
  145. *
  146. * @param string $type The type of item we are looking for
  147. * ('tables', 'views', etc)
  148. * @param int $pos The offset of the list within the results
  149. * @param string $searchClause A string used to filter the results of the query
  150. *
  151. * @return array
  152. */
  153. public function getData($type, $pos, $searchClause = '')
  154. {
  155. $maxItems = $GLOBALS['cfg']['MaxNavigationItems'];
  156. $retval = [];
  157. $db = $this->realParent()->realName;
  158. $table = $this->realName;
  159. switch ($type) {
  160. case 'columns':
  161. if (! $GLOBALS['cfg']['Server']['DisableIS']) {
  162. $db = $GLOBALS['dbi']->escapeString($db);
  163. $table = $GLOBALS['dbi']->escapeString($table);
  164. $query = "SELECT `COLUMN_NAME` AS `name` ";
  165. $query .= ",`COLUMN_KEY` AS `key` ";
  166. $query .= ",`DATA_TYPE` AS `type` ";
  167. $query .= ",`COLUMN_DEFAULT` AS `default` ";
  168. $query .= ",IF (`IS_NULLABLE` = 'NO', '', 'nullable') AS `nullable` ";
  169. $query .= "FROM `INFORMATION_SCHEMA`.`COLUMNS` ";
  170. $query .= "WHERE `TABLE_NAME`='$table' ";
  171. $query .= "AND `TABLE_SCHEMA`='$db' ";
  172. $query .= "ORDER BY `COLUMN_NAME` ASC ";
  173. $query .= "LIMIT " . intval($pos) . ", $maxItems";
  174. $retval = $GLOBALS['dbi']->fetchResult($query);
  175. break;
  176. }
  177. $db = Util::backquote($db);
  178. $table = Util::backquote($table);
  179. $query = "SHOW COLUMNS FROM $table FROM $db";
  180. $handle = $GLOBALS['dbi']->tryQuery($query);
  181. if ($handle === false) {
  182. break;
  183. }
  184. $count = 0;
  185. if ($GLOBALS['dbi']->dataSeek($handle, $pos)) {
  186. while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
  187. if ($count < $maxItems) {
  188. $retval[] = $arr['Field'];
  189. $count++;
  190. } else {
  191. break;
  192. }
  193. }
  194. }
  195. break;
  196. case 'indexes':
  197. $db = Util::backquote($db);
  198. $table = Util::backquote($table);
  199. $query = "SHOW INDEXES FROM $table FROM $db";
  200. $handle = $GLOBALS['dbi']->tryQuery($query);
  201. if ($handle === false) {
  202. break;
  203. }
  204. $count = 0;
  205. while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
  206. if (in_array($arr['Key_name'], $retval)) {
  207. continue;
  208. }
  209. if ($pos <= 0 && $count < $maxItems) {
  210. $retval[] = $arr['Key_name'];
  211. $count++;
  212. }
  213. $pos--;
  214. }
  215. break;
  216. case 'triggers':
  217. if (! $GLOBALS['cfg']['Server']['DisableIS']) {
  218. $db = $GLOBALS['dbi']->escapeString($db);
  219. $table = $GLOBALS['dbi']->escapeString($table);
  220. $query = "SELECT `TRIGGER_NAME` AS `name` ";
  221. $query .= "FROM `INFORMATION_SCHEMA`.`TRIGGERS` ";
  222. $query .= "WHERE `EVENT_OBJECT_SCHEMA` "
  223. . Util::getCollateForIS() . "='$db' ";
  224. $query .= "AND `EVENT_OBJECT_TABLE` "
  225. . Util::getCollateForIS() . "='$table' ";
  226. $query .= "ORDER BY `TRIGGER_NAME` ASC ";
  227. $query .= "LIMIT " . intval($pos) . ", $maxItems";
  228. $retval = $GLOBALS['dbi']->fetchResult($query);
  229. break;
  230. }
  231. $db = Util::backquote($db);
  232. $table = $GLOBALS['dbi']->escapeString($table);
  233. $query = "SHOW TRIGGERS FROM $db WHERE `Table` = '$table'";
  234. $handle = $GLOBALS['dbi']->tryQuery($query);
  235. if ($handle === false) {
  236. break;
  237. }
  238. $count = 0;
  239. if ($GLOBALS['dbi']->dataSeek($handle, $pos)) {
  240. while ($arr = $GLOBALS['dbi']->fetchArray($handle)) {
  241. if ($count < $maxItems) {
  242. $retval[] = $arr['Trigger'];
  243. $count++;
  244. } else {
  245. break;
  246. }
  247. }
  248. }
  249. break;
  250. default:
  251. break;
  252. }
  253. return $retval;
  254. }
  255. /**
  256. * Returns the type of the item represented by the node.
  257. *
  258. * @return string type of the item
  259. */
  260. protected function getItemType()
  261. {
  262. return 'table';
  263. }
  264. /**
  265. * Add an icon to navigation tree
  266. *
  267. * @param string $page Page name to redirect
  268. *
  269. * @return void
  270. */
  271. private function addIcon($page)
  272. {
  273. if (empty($page)) {
  274. return;
  275. }
  276. switch ($page) {
  277. case 'tbl_structure.php':
  278. $this->icon[] = Util::getImage('b_props', __('Structure'));
  279. break;
  280. case 'tbl_select.php':
  281. $this->icon[] = Util::getImage('b_search', __('Search'));
  282. break;
  283. case 'tbl_change.php':
  284. $this->icon[] = Util::getImage('b_insrow', __('Insert'));
  285. break;
  286. case 'tbl_sql.php':
  287. $this->icon[] = Util::getImage('b_sql', __('SQL'));
  288. break;
  289. case 'sql.php':
  290. $this->icon[] = Util::getImage('b_browse', __('Browse'));
  291. break;
  292. }
  293. }
  294. }