TableStats.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. <?php
  2. /**
  3. * Contains abstract class to hold table preferences/statistics
  4. */
  5. declare(strict_types=1);
  6. namespace PhpMyAdmin\Plugins\Schema;
  7. use PhpMyAdmin\DatabaseInterface;
  8. use PhpMyAdmin\Font;
  9. use PhpMyAdmin\Index;
  10. use PhpMyAdmin\Relation;
  11. use PhpMyAdmin\Util;
  12. use function array_flip;
  13. use function array_keys;
  14. use function array_merge;
  15. use function rawurldecode;
  16. use function sprintf;
  17. /**
  18. * Table preferences/statistics
  19. *
  20. * This class preserves the table co-ordinates,fields
  21. * and helps in drawing/generating the tables.
  22. *
  23. * @abstract
  24. */
  25. abstract class TableStats
  26. {
  27. /** @var Dia\Dia|Eps\Eps|Pdf\Pdf|Svg\Svg */
  28. protected $diagram;
  29. /** @var string */
  30. protected $db;
  31. /** @var int */
  32. protected $pageNumber;
  33. /** @var string */
  34. protected $tableName;
  35. /** @var bool */
  36. protected $showKeys;
  37. /** @var bool */
  38. protected $tableDimension;
  39. /** @var mixed */
  40. public $displayfield;
  41. /** @var array */
  42. public $fields = [];
  43. /** @var array */
  44. public $primary = [];
  45. /** @var int|float */
  46. public $x;
  47. /** @var int|float */
  48. public $y;
  49. /** @var int */
  50. public $width = 0;
  51. /** @var int */
  52. public $heightCell = 0;
  53. /** @var bool */
  54. protected $offline;
  55. /** @var Relation */
  56. protected $relation;
  57. /** @var Font */
  58. protected $font;
  59. /**
  60. * @param Pdf\Pdf|Svg\Svg|Eps\Eps|Dia\Dia|Pdf\Pdf $diagram schema diagram
  61. * @param string $db current db name
  62. * @param int $pageNumber current page number (from the
  63. * $cfg['Servers'][$i]['table_coords'] table)
  64. * @param string $tableName table name
  65. * @param bool $showKeys whether to display keys or not
  66. * @param bool $tableDimension whether to display table position or not
  67. * @param bool $offline whether the coordinates are sent
  68. * from the browser
  69. */
  70. public function __construct(
  71. $diagram,
  72. $db,
  73. $pageNumber,
  74. $tableName,
  75. $showKeys,
  76. $tableDimension,
  77. $offline
  78. ) {
  79. global $dbi;
  80. $this->diagram = $diagram;
  81. $this->db = $db;
  82. $this->pageNumber = $pageNumber;
  83. $this->tableName = $tableName;
  84. $this->showKeys = $showKeys;
  85. $this->tableDimension = $tableDimension;
  86. $this->offline = $offline;
  87. $this->relation = new Relation($dbi);
  88. $this->font = new Font();
  89. // checks whether the table exists
  90. // and loads fields
  91. $this->validateTableAndLoadFields();
  92. // load table coordinates
  93. $this->loadCoordinates();
  94. // loads display field
  95. $this->loadDisplayField();
  96. // loads primary keys
  97. $this->loadPrimaryKey();
  98. }
  99. /**
  100. * Validate whether the table exists.
  101. *
  102. * @return void
  103. */
  104. protected function validateTableAndLoadFields()
  105. {
  106. global $dbi;
  107. $sql = 'DESCRIBE ' . Util::backquote($this->tableName);
  108. $result = $dbi->tryQuery(
  109. $sql,
  110. DatabaseInterface::CONNECT_USER,
  111. DatabaseInterface::QUERY_STORE
  112. );
  113. if (! $result || ! $dbi->numRows($result)) {
  114. $this->showMissingTableError();
  115. }
  116. if ($this->showKeys) {
  117. $indexes = Index::getFromTable($this->tableName, $this->db);
  118. $all_columns = [];
  119. foreach ($indexes as $index) {
  120. $all_columns = array_merge(
  121. $all_columns,
  122. array_flip(array_keys($index->getColumns()))
  123. );
  124. }
  125. $this->fields = array_keys($all_columns);
  126. } else {
  127. while ($row = $dbi->fetchRow($result)) {
  128. $this->fields[] = $row[0];
  129. }
  130. }
  131. }
  132. /**
  133. * Displays an error when the table cannot be found.
  134. *
  135. * @return void
  136. *
  137. * @abstract
  138. */
  139. abstract protected function showMissingTableError();
  140. /**
  141. * Loads coordinates of a table
  142. *
  143. * @return void
  144. */
  145. protected function loadCoordinates()
  146. {
  147. if (! isset($_POST['t_h'])) {
  148. return;
  149. }
  150. foreach ($_POST['t_h'] as $key => $value) {
  151. $db = rawurldecode($_POST['t_db'][$key]);
  152. $tbl = rawurldecode($_POST['t_tbl'][$key]);
  153. if ($this->db . '.' . $this->tableName === $db . '.' . $tbl) {
  154. $this->x = (float) $_POST['t_x'][$key];
  155. $this->y = (float) $_POST['t_y'][$key];
  156. break;
  157. }
  158. }
  159. }
  160. /**
  161. * Loads the table's display field
  162. *
  163. * @return void
  164. */
  165. protected function loadDisplayField()
  166. {
  167. $this->displayfield = $this->relation->getDisplayField($this->db, $this->tableName);
  168. }
  169. /**
  170. * Loads the PRIMARY key.
  171. *
  172. * @return void
  173. */
  174. protected function loadPrimaryKey()
  175. {
  176. global $dbi;
  177. $result = $dbi->query(
  178. 'SHOW INDEX FROM ' . Util::backquote($this->tableName) . ';',
  179. DatabaseInterface::CONNECT_USER,
  180. DatabaseInterface::QUERY_STORE
  181. );
  182. if ($dbi->numRows($result) <= 0) {
  183. return;
  184. }
  185. while ($row = $dbi->fetchAssoc($result)) {
  186. if ($row['Key_name'] !== 'PRIMARY') {
  187. continue;
  188. }
  189. $this->primary[] = $row['Column_name'];
  190. }
  191. }
  192. /**
  193. * Returns title of the current table,
  194. * title can have the dimensions/co-ordinates of the table
  195. *
  196. * @return string title of the current table
  197. */
  198. protected function getTitle()
  199. {
  200. return ($this->tableDimension
  201. ? sprintf('%.0fx%0.f', $this->width, $this->heightCell)
  202. : ''
  203. )
  204. . ' ' . $this->tableName;
  205. }
  206. }