Svg_Relation_Schema.class.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Classes to create relation schema in SVG format.
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. require_once 'libraries/plugins/schema/Export_Relation_Schema.class.php';
  12. require_once 'libraries/plugins/schema/svg/RelationStatsSvg.class.php';
  13. require_once 'libraries/plugins/schema/svg/TableStatsSvg.class.php';
  14. require_once 'libraries/Font.class.php';
  15. /**
  16. * This Class inherits the XMLwriter class and
  17. * helps in developing structure of SVG Schema Export
  18. *
  19. * @package PhpMyAdmin
  20. * @access public
  21. * @see http://php.net/manual/en/book.xmlwriter.php
  22. */
  23. class PMA_SVG extends XMLWriter
  24. {
  25. public $title;
  26. public $author;
  27. public $font;
  28. public $fontSize;
  29. /**
  30. * The "PMA_SVG" constructor
  31. *
  32. * Upon instantiation This starts writing the Svg XML document
  33. *
  34. * @see XMLWriter::openMemory(),XMLWriter::setIndent(),XMLWriter::startDocument()
  35. */
  36. public function __construct()
  37. {
  38. $this->openMemory();
  39. /*
  40. * Set indenting using three spaces,
  41. * so output is formatted
  42. */
  43. $this->setIndent(true);
  44. $this->setIndentString(' ');
  45. /*
  46. * Create the XML document
  47. */
  48. $this->startDocument('1.0', 'UTF-8');
  49. $this->startDtd(
  50. 'svg', '-//W3C//DTD SVG 1.1//EN',
  51. 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'
  52. );
  53. $this->endDtd();
  54. }
  55. /**
  56. * Set document title
  57. *
  58. * @param string $value sets the title text
  59. *
  60. * @return void
  61. */
  62. public function setTitle($value)
  63. {
  64. $this->title = $value;
  65. }
  66. /**
  67. * Set document author
  68. *
  69. * @param string $value sets the author
  70. *
  71. * @return void
  72. */
  73. public function setAuthor($value)
  74. {
  75. $this->author = $value;
  76. }
  77. /**
  78. * Set document font
  79. *
  80. * @param string $value sets the font e.g Arial, Sans-serif etc
  81. *
  82. * @return void
  83. */
  84. public function setFont($value)
  85. {
  86. $this->font = $value;
  87. }
  88. /**
  89. * Get document font
  90. *
  91. * @return string returns the font name
  92. */
  93. public function getFont()
  94. {
  95. return $this->font;
  96. }
  97. /**
  98. * Set document font size
  99. *
  100. * @param string $value sets the font size in pixels
  101. *
  102. * @return void
  103. */
  104. public function setFontSize($value)
  105. {
  106. $this->fontSize = $value;
  107. }
  108. /**
  109. * Get document font size
  110. *
  111. * @return string returns the font size
  112. */
  113. public function getFontSize()
  114. {
  115. return $this->fontSize;
  116. }
  117. /**
  118. * Starts Svg Document
  119. *
  120. * svg document starts by first initializing svg tag
  121. * which contains all the attributes and namespace that needed
  122. * to define the svg document
  123. *
  124. * @param integer $width total width of the Svg document
  125. * @param integer $height total height of the Svg document
  126. * @param integer $x min-x of the view box
  127. * @param integer $y min-y of the view box
  128. *
  129. * @return void
  130. *
  131. * @see XMLWriter::startElement(),XMLWriter::writeAttribute()
  132. */
  133. public function startSvgDoc($width, $height, $x = 0, $y = 0)
  134. {
  135. $this->startElement('svg');
  136. if (!is_int($width)) {
  137. $width = intval($width);
  138. }
  139. if (!is_int($height)) {
  140. $height = intval($height);
  141. }
  142. if ($x != 0 || $y != 0) {
  143. $this->writeAttribute('viewBox', "$x $y $width $height");
  144. }
  145. $this->writeAttribute('width', ($width - $x) . 'px');
  146. $this->writeAttribute('height', ($height - $y) . 'px');
  147. $this->writeAttribute('xmlns', 'http://www.w3.org/2000/svg');
  148. $this->writeAttribute('version', '1.1');
  149. }
  150. /**
  151. * Ends Svg Document
  152. *
  153. * @return void
  154. * @see XMLWriter::endElement(),XMLWriter::endDocument()
  155. */
  156. public function endSvgDoc()
  157. {
  158. $this->endElement();
  159. $this->endDocument();
  160. }
  161. /**
  162. * output Svg Document
  163. *
  164. * svg document prompted to the user for download
  165. * Svg document saved in .svg extension and can be
  166. * easily changeable by using any svg IDE
  167. *
  168. * @param string $fileName file name
  169. *
  170. * @return void
  171. * @see XMLWriter::startElement(),XMLWriter::writeAttribute()
  172. */
  173. public function showOutput($fileName)
  174. {
  175. //ob_get_clean();
  176. $output = $this->flush();
  177. PMA_Response::getInstance()->disable();
  178. PMA_downloadHeader(
  179. $fileName,
  180. 'image/svg+xml',
  181. /*overload*/mb_strlen($output)
  182. );
  183. print $output;
  184. }
  185. /**
  186. * Draws Svg elements
  187. *
  188. * SVG has some predefined shape elements like rectangle & text
  189. * and other elements who have x,y co-ordinates are drawn.
  190. * specify their width and height and can give styles too.
  191. *
  192. * @param string $name Svg element name
  193. * @param int $x The x attr defines the left position of the element
  194. * (e.g. x="0" places the element 0 pixels from the left of the browser window)
  195. * @param integer $y The y attribute defines the top position of the
  196. * element (e.g. y="0" places the element 0 pixels from the top of the browser
  197. * window)
  198. * @param int|string $width The width attribute defines the width the element
  199. * @param int|string $height The height attribute defines the height the element
  200. * @param string $text The text attribute defines the text the element
  201. * @param string $styles The style attribute defines the style the element
  202. * styles can be defined like CSS styles
  203. *
  204. * @return void
  205. *
  206. * @see XMLWriter::startElement(), XMLWriter::writeAttribute(),
  207. * XMLWriter::text(), XMLWriter::endElement()
  208. */
  209. public function printElement($name, $x, $y, $width = '', $height = '',
  210. $text = '', $styles = ''
  211. ) {
  212. $this->startElement($name);
  213. $this->writeAttribute('width', $width);
  214. $this->writeAttribute('height', $height);
  215. $this->writeAttribute('x', $x);
  216. $this->writeAttribute('y', $y);
  217. $this->writeAttribute('style', $styles);
  218. if (isset($text)) {
  219. $this->writeAttribute('font-family', $this->font);
  220. $this->writeAttribute('font-size', $this->fontSize);
  221. $this->text($text);
  222. }
  223. $this->endElement();
  224. }
  225. /**
  226. * Draws Svg Line element
  227. *
  228. * Svg line element is drawn for connecting the tables.
  229. * arrows are also drawn by specify its start and ending
  230. * co-ordinates
  231. *
  232. * @param string $name Svg element name i.e line
  233. * @param integer $x1 Defines the start of the line on the x-axis
  234. * @param integer $y1 Defines the start of the line on the y-axis
  235. * @param integer $x2 Defines the end of the line on the x-axis
  236. * @param integer $y2 Defines the end of the line on the y-axis
  237. * @param string $styles The style attribute defines the style the element
  238. * styles can be defined like CSS styles
  239. *
  240. * @return void
  241. *
  242. * @see XMLWriter::startElement(), XMLWriter::writeAttribute(),
  243. * XMLWriter::endElement()
  244. */
  245. public function printElementLine($name,$x1,$y1,$x2,$y2,$styles)
  246. {
  247. $this->startElement($name);
  248. $this->writeAttribute('x1', $x1);
  249. $this->writeAttribute('y1', $y1);
  250. $this->writeAttribute('x2', $x2);
  251. $this->writeAttribute('y2', $y2);
  252. $this->writeAttribute('style', $styles);
  253. $this->endElement();
  254. }
  255. }
  256. /**
  257. * Svg Relation Schema Class
  258. *
  259. * Purpose of this class is to generate the SVG XML Document because
  260. * SVG defines the graphics in XML format which is used for representing
  261. * the database diagrams as vector image. This class actually helps
  262. * in preparing SVG XML format.
  263. *
  264. * SVG XML is generated by using XMLWriter php extension and this class
  265. * inherits Export_Relation_Schema class has common functionality added
  266. * to this class
  267. *
  268. * @package PhpMyAdmin
  269. * @name Svg_Relation_Schema
  270. */
  271. class PMA_Svg_Relation_Schema extends PMA_Export_Relation_Schema
  272. {
  273. /**
  274. * @var Table_Stats_Dia[]|Table_Stats_Eps[]|Table_Stats_Pdf[]|Table_Stats_Svg[]
  275. */
  276. private $_tables = array();
  277. /** @var Relation_Stats_Dia[] Relations */
  278. private $_relations = array();
  279. private $_xMax = 0;
  280. private $_yMax = 0;
  281. private $_xMin = 100000;
  282. private $_yMin = 100000;
  283. private $_tablewidth;
  284. /**
  285. * The "PMA_Svg_Relation_Schema" constructor
  286. *
  287. * Upon instantiation This starts writing the SVG XML document
  288. * user will be prompted for download as .svg extension
  289. *
  290. * @param string $db database name
  291. *
  292. * @see PMA_SVG
  293. */
  294. function __construct($db)
  295. {
  296. parent::__construct($db, new PMA_SVG());
  297. $this->setShowColor(isset($_REQUEST['svg_show_color']));
  298. $this->setShowKeys(isset($_REQUEST['svg_show_keys']));
  299. $this->setTableDimension(isset($_REQUEST['svg_show_table_dimension']));
  300. $this->setAllTablesSameWidth(isset($_REQUEST['svg_all_tables_same_width']));
  301. $this->diagram->setTitle(
  302. sprintf(
  303. __('Schema of the %s database - Page %s'),
  304. $this->db,
  305. $this->pageNumber
  306. )
  307. );
  308. $this->diagram->SetAuthor('phpMyAdmin ' . PMA_VERSION);
  309. $this->diagram->setFont('Arial');
  310. $this->diagram->setFontSize('16px');
  311. $alltables = $this->getTablesFromRequest();
  312. foreach ($alltables as $table) {
  313. if (! isset($this->_tables[$table])) {
  314. $this->_tables[$table] = new Table_Stats_Svg(
  315. $this->diagram, $this->db,
  316. $table, $this->diagram->getFont(),
  317. $this->diagram->getFontSize(), $this->pageNumber,
  318. $this->_tablewidth, $this->showKeys, $this->tableDimension,
  319. $this->offline
  320. );
  321. }
  322. if ($this->sameWide) {
  323. $this->_tables[$table]->width = &$this->_tablewidth;
  324. }
  325. $this->_setMinMax($this->_tables[$table]);
  326. }
  327. $border = 15;
  328. $this->diagram->startSvgDoc(
  329. $this->_xMax + $border,
  330. $this->_yMax + $border,
  331. $this->_xMin - $border,
  332. $this->_yMin - $border
  333. );
  334. $seen_a_relation = false;
  335. foreach ($alltables as $one_table) {
  336. $exist_rel = PMA_getForeigners($this->db, $one_table, '', 'both');
  337. if (!$exist_rel) {
  338. continue;
  339. }
  340. $seen_a_relation = true;
  341. foreach ($exist_rel as $master_field => $rel) {
  342. /* put the foreign table on the schema only if selected
  343. * by the user
  344. * (do not use array_search() because we would have to
  345. * to do a === false and this is not PHP3 compatible)
  346. */
  347. if ($master_field != 'foreign_keys_data') {
  348. if (in_array($rel['foreign_table'], $alltables)) {
  349. $this->_addRelation(
  350. $one_table,
  351. $this->diagram->getFont(),
  352. $this->diagram->getFontSize(),
  353. $master_field,
  354. $rel['foreign_table'],
  355. $rel['foreign_field'],
  356. $this->tableDimension
  357. );
  358. }
  359. continue;
  360. }
  361. foreach ($rel as $one_key) {
  362. if (!in_array($one_key['ref_table_name'], $alltables)) {
  363. continue;
  364. }
  365. foreach ($one_key['index_list']
  366. as $index => $one_field
  367. ) {
  368. $this->_addRelation(
  369. $one_table, $this->diagram->getFont(),
  370. $this->diagram->getFontSize(),
  371. $one_field, $one_key['ref_table_name'],
  372. $one_key['ref_index_list'][$index],
  373. $this->tableDimension
  374. );
  375. }
  376. }
  377. }
  378. }
  379. if ($seen_a_relation) {
  380. $this->_drawRelations();
  381. }
  382. $this->_drawTables();
  383. $this->diagram->endSvgDoc();
  384. }
  385. /**
  386. * Output Svg Document for download
  387. *
  388. * @return void
  389. */
  390. public function showOutput()
  391. {
  392. $this->diagram->showOutput($this->getFileName('.svg'));
  393. }
  394. /**
  395. * Sets X and Y minimum and maximum for a table cell
  396. *
  397. * @param string $table The table name
  398. *
  399. * @return void
  400. */
  401. private function _setMinMax($table)
  402. {
  403. $this->_xMax = max($this->_xMax, $table->x + $table->width);
  404. $this->_yMax = max($this->_yMax, $table->y + $table->height);
  405. $this->_xMin = min($this->_xMin, $table->x);
  406. $this->_yMin = min($this->_yMin, $table->y);
  407. }
  408. /**
  409. * Defines relation objects
  410. *
  411. * @param string $masterTable The master table name
  412. * @param string $font The font face
  413. * @param int $fontSize Font size
  414. * @param string $masterField The relation field in the master table
  415. * @param string $foreignTable The foreign table name
  416. * @param string $foreignField The relation field in the foreign table
  417. * @param boolean $tableDimension Whether to display table position or not
  418. *
  419. * @return void
  420. *
  421. * @see _setMinMax,Table_Stats_Svg::__construct(),
  422. * Relation_Stats_Svg::__construct()
  423. */
  424. private function _addRelation(
  425. $masterTable,$font,$fontSize, $masterField,
  426. $foreignTable, $foreignField, $tableDimension
  427. ) {
  428. if (! isset($this->_tables[$masterTable])) {
  429. $this->_tables[$masterTable] = new Table_Stats_Svg(
  430. $this->diagram, $this->db,
  431. $masterTable, $font, $fontSize, $this->pageNumber,
  432. $this->_tablewidth, false, $tableDimension
  433. );
  434. $this->_setMinMax($this->_tables[$masterTable]);
  435. }
  436. if (! isset($this->_tables[$foreignTable])) {
  437. $this->_tables[$foreignTable] = new Table_Stats_Svg(
  438. $this->diagram, $this->db,
  439. $foreignTable, $font, $fontSize, $this->pageNumber,
  440. $this->_tablewidth, false, $tableDimension
  441. );
  442. $this->_setMinMax($this->_tables[$foreignTable]);
  443. }
  444. $this->_relations[] = new Relation_Stats_Svg(
  445. $this->diagram,
  446. $this->_tables[$masterTable],
  447. $masterField,
  448. $this->_tables[$foreignTable],
  449. $foreignField
  450. );
  451. }
  452. /**
  453. * Draws relation arrows and lines
  454. * connects master table's master field to
  455. * foreign table's foreign field
  456. *
  457. * @return void
  458. *
  459. * @see Relation_Stats_Svg::relationDraw()
  460. */
  461. private function _drawRelations()
  462. {
  463. foreach ($this->_relations as $relation) {
  464. $relation->relationDraw($this->showColor);
  465. }
  466. }
  467. /**
  468. * Draws tables
  469. *
  470. * @return void
  471. *
  472. * @see Table_Stats_Svg::Table_Stats_tableDraw()
  473. */
  474. private function _drawTables()
  475. {
  476. foreach ($this->_tables as $table) {
  477. $table->tableDraw($this->showColor);
  478. }
  479. }
  480. }