TableStats.php 5.7 KB

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