Pdf_Relation_Schema.class.php 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * PDF schema handling
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. /**
  12. * Skip the plugin if TCPDF is not available.
  13. */
  14. if (! file_exists(TCPDF_INC)) {
  15. $GLOBALS['skip_import'] = true;
  16. return;
  17. }
  18. /**
  19. * block attempts to directly run this script
  20. */
  21. if (getcwd() == dirname(__FILE__)) {
  22. die('Attack stopped');
  23. }
  24. require_once 'libraries/plugins/schema/Export_Relation_Schema.class.php';
  25. require_once 'libraries/plugins/schema/pdf/RelationStatsPdf.class.php';
  26. require_once 'libraries/plugins/schema/pdf/TableStatsPdf.class.php';
  27. require_once 'libraries/PDF.class.php';
  28. require_once 'libraries/transformations.lib.php';
  29. /**
  30. * Extends the "TCPDF" class and helps
  31. * in developing the structure of PDF Schema Export
  32. *
  33. * @access public
  34. * @package PhpMyAdmin
  35. * @see TCPDF
  36. */
  37. class PMA_Schema_PDF extends PMA_PDF
  38. {
  39. /**
  40. * Defines properties
  41. */
  42. var $_xMin;
  43. var $_yMin;
  44. var $leftMargin = 10;
  45. var $topMargin = 10;
  46. var $scale;
  47. var $PMA_links;
  48. var $Outlines = array();
  49. var $def_outlines;
  50. var $widths;
  51. private $_ff = PMA_PDF_FONT;
  52. private $_offline;
  53. private $_pageNumber;
  54. private $_withDoc;
  55. private $_db;
  56. /**
  57. * Constructs PDF for schema export.
  58. *
  59. * @param string $orientation page orientation
  60. * @param string $unit unit
  61. * @param string $paper the format used for pages
  62. * @param int $pageNumber schema page number that is being exported
  63. * @param boolean $withDoc with document dictionary
  64. * @param string $db the database name
  65. *
  66. * @access public
  67. */
  68. public function __construct(
  69. $orientation, $unit, $paper, $pageNumber, $withDoc, $db
  70. ) {
  71. parent::__construct($orientation, $unit, $paper);
  72. $this->_pageNumber = $pageNumber;
  73. $this->_withDoc = $withDoc;
  74. $this->_db = $db;
  75. }
  76. /**
  77. * Sets the value for margins
  78. *
  79. * @param float $c_margin margin
  80. *
  81. * @return void
  82. */
  83. public function setCMargin($c_margin)
  84. {
  85. $this->cMargin = $c_margin;
  86. }
  87. /**
  88. * Sets the scaling factor, defines minimum coordinates and margins
  89. *
  90. * @param float|int $scale The scaling factor
  91. * @param float|int $xMin The minimum X coordinate
  92. * @param float|int $yMin The minimum Y coordinate
  93. * @param float|int $leftMargin The left margin
  94. * @param float|int $topMargin The top margin
  95. *
  96. * @return void
  97. */
  98. public function setScale($scale = 1, $xMin = 0, $yMin = 0,
  99. $leftMargin = -1, $topMargin = -1
  100. ) {
  101. $this->scale = $scale;
  102. $this->_xMin = $xMin;
  103. $this->_yMin = $yMin;
  104. if ($this->leftMargin != -1) {
  105. $this->leftMargin = $leftMargin;
  106. }
  107. if ($this->topMargin != -1) {
  108. $this->topMargin = $topMargin;
  109. }
  110. }
  111. /**
  112. * Outputs a scaled cell
  113. *
  114. * @param float|int $w The cell width
  115. * @param float|int $h The cell height
  116. * @param string $txt The text to output
  117. * @param mixed $border Whether to add borders or not
  118. * @param integer $ln Where to put the cursor once the output is done
  119. * @param string $align Align mode
  120. * @param integer $fill Whether to fill the cell with a color or not
  121. * @param string $link Link
  122. *
  123. * @return void
  124. *
  125. * @see TCPDF::Cell()
  126. */
  127. public function cellScale($w, $h = 0, $txt = '', $border = 0, $ln = 0,
  128. $align = '', $fill = 0, $link = ''
  129. ) {
  130. $h = $h / $this->scale;
  131. $w = $w / $this->scale;
  132. $this->Cell($w, $h, $txt, $border, $ln, $align, $fill, $link);
  133. }
  134. /**
  135. * Draws a scaled line
  136. *
  137. * @param float $x1 The horizontal position of the starting point
  138. * @param float $y1 The vertical position of the starting point
  139. * @param float $x2 The horizontal position of the ending point
  140. * @param float $y2 The vertical position of the ending point
  141. *
  142. * @return void
  143. *
  144. * @see TCPDF::Line()
  145. */
  146. public function lineScale($x1, $y1, $x2, $y2)
  147. {
  148. $x1 = ($x1 - $this->_xMin) / $this->scale + $this->leftMargin;
  149. $y1 = ($y1 - $this->_yMin) / $this->scale + $this->topMargin;
  150. $x2 = ($x2 - $this->_xMin) / $this->scale + $this->leftMargin;
  151. $y2 = ($y2 - $this->_yMin) / $this->scale + $this->topMargin;
  152. $this->Line($x1, $y1, $x2, $y2);
  153. }
  154. /**
  155. * Sets x and y scaled positions
  156. *
  157. * @param float $x The x position
  158. * @param float $y The y position
  159. *
  160. * @return void
  161. *
  162. * @see TCPDF::SetXY()
  163. */
  164. public function setXyScale($x, $y)
  165. {
  166. $x = ($x - $this->_xMin) / $this->scale + $this->leftMargin;
  167. $y = ($y - $this->_yMin) / $this->scale + $this->topMargin;
  168. $this->SetXY($x, $y);
  169. }
  170. /**
  171. * Sets the X scaled positions
  172. *
  173. * @param float $x The x position
  174. *
  175. * @return void
  176. *
  177. * @see TCPDF::SetX()
  178. */
  179. public function setXScale($x)
  180. {
  181. $x = ($x - $this->_xMin) / $this->scale + $this->leftMargin;
  182. $this->SetX($x);
  183. }
  184. /**
  185. * Sets the scaled font size
  186. *
  187. * @param float $size The font size (in points)
  188. *
  189. * @return void
  190. *
  191. * @see TCPDF::SetFontSize()
  192. */
  193. public function setFontSizeScale($size)
  194. {
  195. // Set font size in points
  196. $size = $size / $this->scale;
  197. $this->SetFontSize($size);
  198. }
  199. /**
  200. * Sets the scaled line width
  201. *
  202. * @param float $width The line width
  203. *
  204. * @return void
  205. *
  206. * @see TCPDF::SetLineWidth()
  207. */
  208. public function setLineWidthScale($width)
  209. {
  210. $width = $width / $this->scale;
  211. $this->SetLineWidth($width);
  212. }
  213. /**
  214. * This method is used to render the page header.
  215. *
  216. * @return void
  217. *
  218. * @see TCPDF::Header()
  219. */
  220. public function Header()
  221. {
  222. // We only show this if we find something in the new pdf_pages table
  223. // This function must be named "Header" to work with the TCPDF library
  224. if ($this->_withDoc) {
  225. if ($this->_offline || $this->_pageNumber == -1) {
  226. $pg_name = __("PDF export page");
  227. } else {
  228. $test_query = 'SELECT * FROM '
  229. . PMA_Util::backquote($GLOBALS['cfgRelation']['db']) . '.'
  230. . PMA_Util::backquote($GLOBALS['cfgRelation']['pdf_pages'])
  231. . ' WHERE db_name = \'' . PMA_Util::sqlAddSlashes($this->_db)
  232. . '\' AND page_nr = \'' . $this->_pageNumber . '\'';
  233. $test_rs = PMA_queryAsControlUser($test_query);
  234. $pages = @$GLOBALS['dbi']->fetchAssoc($test_rs);
  235. $pg_name = ucfirst($pages['page_descr']);
  236. }
  237. $this->SetFont($this->_ff, 'B', 14);
  238. $this->Cell(0, 6, $pg_name, 'B', 1, 'C');
  239. $this->SetFont($this->_ff, '');
  240. $this->Ln();
  241. }
  242. }
  243. /**
  244. * This function must be named "Footer" to work with the TCPDF library
  245. *
  246. * @return void
  247. *
  248. * @see PMA_PDF::Footer()
  249. */
  250. public function Footer()
  251. {
  252. if ($this->_withDoc) {
  253. parent::Footer();
  254. }
  255. }
  256. /**
  257. * Sets widths
  258. *
  259. * @param array $w array of widths
  260. *
  261. * @return void
  262. */
  263. public function SetWidths($w)
  264. {
  265. // column widths
  266. $this->widths = $w;
  267. }
  268. /**
  269. * Generates table row.
  270. *
  271. * @param array $data Data for table
  272. * @param array $links Links for table cells
  273. *
  274. * @return void
  275. */
  276. public function Row($data, $links)
  277. {
  278. // line height
  279. $nb = 0;
  280. $data_cnt = count($data);
  281. for ($i = 0;$i < $data_cnt;$i++) {
  282. $nb = max($nb, $this->NbLines($this->widths[$i], $data[$i]));
  283. }
  284. $il = $this->FontSize;
  285. $h = ($il + 1) * $nb;
  286. // page break if necessary
  287. $this->CheckPageBreak($h);
  288. // draw the cells
  289. $data_cnt = count($data);
  290. for ($i = 0;$i < $data_cnt;$i++) {
  291. $w = $this->widths[$i];
  292. // save current position
  293. $x = $this->GetX();
  294. $y = $this->GetY();
  295. // draw the border
  296. $this->Rect($x, $y, $w, $h);
  297. if (isset($links[$i])) {
  298. $this->Link($x, $y, $w, $h, $links[$i]);
  299. }
  300. // print text
  301. $this->MultiCell($w, $il + 1, $data[$i], 0, 'L');
  302. // go to right side
  303. $this->SetXY($x + $w, $y);
  304. }
  305. // go to line
  306. $this->Ln($h);
  307. }
  308. /**
  309. * Compute number of lines used by a multicell of width w
  310. *
  311. * @param int $w width
  312. * @param string $txt text
  313. *
  314. * @return int
  315. */
  316. public function NbLines($w, $txt)
  317. {
  318. $cw = &$this->CurrentFont['cw'];
  319. if ($w == 0) {
  320. $w = $this->w - $this->rMargin - $this->x;
  321. }
  322. $wmax = ($w-2 * $this->cMargin) * 1000 / $this->FontSize;
  323. $s = str_replace("\r", '', $txt);
  324. $nb = /*overload*/mb_strlen($s);
  325. if ($nb > 0 and $s[$nb-1] == "\n") {
  326. $nb--;
  327. }
  328. $sep = -1;
  329. $i = 0;
  330. $j = 0;
  331. $l = 0;
  332. $nl = 1;
  333. while ($i < $nb) {
  334. $c = $s[$i];
  335. if ($c == "\n") {
  336. $i++;
  337. $sep = -1;
  338. $j = $i;
  339. $l = 0;
  340. $nl++;
  341. continue;
  342. }
  343. if ($c == ' ') {
  344. $sep = $i;
  345. }
  346. $l += isset($cw[/*overload*/mb_ord($c)])?$cw[/*overload*/mb_ord($c)]:0 ;
  347. if ($l > $wmax) {
  348. if ($sep == -1) {
  349. if ($i == $j) {
  350. $i++;
  351. }
  352. } else {
  353. $i = $sep + 1;
  354. }
  355. $sep = -1;
  356. $j = $i;
  357. $l = 0;
  358. $nl++;
  359. } else {
  360. $i++;
  361. }
  362. }
  363. return $nl;
  364. }
  365. /**
  366. * Set whether the document is generated from client side DB
  367. *
  368. * @param string $value whether offline
  369. *
  370. * @return void
  371. *
  372. * @access private
  373. */
  374. public function setOffline($value)
  375. {
  376. $this->_offline = $value;
  377. }
  378. }
  379. /**
  380. * Pdf Relation Schema Class
  381. *
  382. * Purpose of this class is to generate the PDF Document. PDF is widely
  383. * used format for documenting text,fonts,images and 3d vector graphics.
  384. *
  385. * This class inherits Export_Relation_Schema class has common functionality added
  386. * to this class
  387. *
  388. * @name Pdf_Relation_Schema
  389. * @package PhpMyAdmin
  390. */
  391. class PMA_Pdf_Relation_Schema extends PMA_Export_Relation_Schema
  392. {
  393. /**
  394. * Defines properties
  395. */
  396. private $_showGrid;
  397. private $_withDoc;
  398. private $_tableOrder;
  399. /**
  400. * @var Table_Stats_Pdf[]
  401. */
  402. private $_tables = array();
  403. private $_ff = PMA_PDF_FONT;
  404. private $_xMax = 0;
  405. private $_yMax = 0;
  406. private $_scale;
  407. private $_xMin = 100000;
  408. private $_yMin = 100000;
  409. private $_topMargin = 10;
  410. private $_bottomMargin = 10;
  411. private $_leftMargin = 10;
  412. private $_rightMargin = 10;
  413. private $_tablewidth;
  414. /**
  415. * @var Relation_Stats_Pdf[]
  416. */
  417. protected $relations = array();
  418. /**
  419. * The "PMA_Pdf_Relation_Schema" constructor
  420. *
  421. * @param string $db database name
  422. *
  423. * @see PMA_Schema_PDF
  424. */
  425. public function __construct($db)
  426. {
  427. $this->setShowGrid(isset($_REQUEST['pdf_show_grid']));
  428. $this->setShowColor(isset($_REQUEST['pdf_show_color']));
  429. $this->setShowKeys(isset($_REQUEST['pdf_show_keys']));
  430. $this->setTableDimension(isset($_REQUEST['pdf_show_table_dimension']));
  431. $this->setAllTablesSameWidth(isset($_REQUEST['pdf_all_tables_same_width']));
  432. $this->setWithDataDictionary(isset($_REQUEST['pdf_with_doc']));
  433. $this->setTableOrder($_REQUEST['pdf_table_order']);
  434. $this->setOrientation($_REQUEST['pdf_orientation']);
  435. $this->setPaper($_REQUEST['pdf_paper']);
  436. // Initializes a new document
  437. parent::__construct(
  438. $db,
  439. new PMA_Schema_PDF(
  440. $this->orientation, 'mm', $this->paper,
  441. $this->pageNumber, $this->_withDoc, $db
  442. )
  443. );
  444. $this->diagram->SetTitle(
  445. sprintf(
  446. __('Schema of the %s database'),
  447. $this->db
  448. )
  449. );
  450. $this->diagram->setCMargin(0);
  451. $this->diagram->Open();
  452. $this->diagram->SetAutoPageBreak('auto');
  453. $this->diagram->setOffline($this->offline);
  454. $alltables = $this->getTablesFromRequest();
  455. if ($this->getTableOrder() == 'name_asc') {
  456. sort($alltables);
  457. } else if ($this->getTableOrder() == 'name_desc') {
  458. rsort($alltables);
  459. }
  460. if ($this->_withDoc) {
  461. $this->diagram->SetAutoPageBreak('auto', 15);
  462. $this->diagram->setCMargin(1);
  463. $this->dataDictionaryDoc($alltables);
  464. $this->diagram->SetAutoPageBreak('auto');
  465. $this->diagram->setCMargin(0);
  466. }
  467. $this->diagram->Addpage();
  468. if ($this->_withDoc) {
  469. $this->diagram->SetLink($this->diagram->PMA_links['RT']['-'], -1);
  470. $this->diagram->Bookmark(__('Relational schema'));
  471. $this->diagram->SetAlias('{00}', $this->diagram->PageNo());
  472. $this->_topMargin = 28;
  473. $this->_bottomMargin = 28;
  474. }
  475. /* snip */
  476. foreach ($alltables as $table) {
  477. if (! isset($this->_tables[$table])) {
  478. $this->_tables[$table] = new Table_Stats_Pdf(
  479. $this->diagram,
  480. $this->db,
  481. $table,
  482. null,
  483. $this->pageNumber,
  484. $this->_tablewidth,
  485. $this->showKeys,
  486. $this->tableDimension,
  487. $this->offline
  488. );
  489. }
  490. if ($this->sameWide) {
  491. $this->_tables[$table]->width = $this->_tablewidth;
  492. }
  493. $this->_setMinMax($this->_tables[$table]);
  494. }
  495. // Defines the scale factor
  496. $innerWidth = $this->diagram->getPageWidth() - $this->_rightMargin
  497. - $this->_leftMargin;
  498. $innerHeight = $this->diagram->getPageHeight() - $this->_topMargin
  499. - $this->_bottomMargin;
  500. $this->_scale = ceil(
  501. max(
  502. ($this->_xMax - $this->_xMin) / $innerWidth,
  503. ($this->_yMax - $this->_yMin) / $innerHeight
  504. ) * 100
  505. ) / 100;
  506. $this->diagram->setScale(
  507. $this->_scale,
  508. $this->_xMin,
  509. $this->_yMin,
  510. $this->_leftMargin,
  511. $this->_topMargin
  512. );
  513. // Builds and save the PDF document
  514. $this->diagram->setLineWidthScale(0.1);
  515. if ($this->_showGrid) {
  516. $this->diagram->SetFontSize(10);
  517. $this->_strokeGrid();
  518. }
  519. $this->diagram->setFontSizeScale(14);
  520. // previous logic was checking master tables and foreign tables
  521. // but I think that looping on every table of the pdf page as a master
  522. // and finding its foreigns is OK (then we can support innodb)
  523. $seen_a_relation = false;
  524. foreach ($alltables as $one_table) {
  525. $exist_rel = PMA_getForeigners($this->db, $one_table, '', 'both');
  526. if (!$exist_rel) {
  527. continue;
  528. }
  529. $seen_a_relation = true;
  530. foreach ($exist_rel as $master_field => $rel) {
  531. // put the foreign table on the schema only if selected
  532. // by the user
  533. // (do not use array_search() because we would have to
  534. // to do a === false and this is not PHP3 compatible)
  535. if ($master_field != 'foreign_keys_data') {
  536. if (in_array($rel['foreign_table'], $alltables)) {
  537. $this->_addRelation(
  538. $one_table,
  539. $master_field,
  540. $rel['foreign_table'],
  541. $rel['foreign_field']
  542. );
  543. }
  544. continue;
  545. }
  546. foreach ($rel as $one_key) {
  547. if (!in_array($one_key['ref_table_name'], $alltables)) {
  548. continue;
  549. }
  550. foreach ($one_key['index_list']
  551. as $index => $one_field
  552. ) {
  553. $this->_addRelation(
  554. $one_table,
  555. $one_field,
  556. $one_key['ref_table_name'],
  557. $one_key['ref_index_list'][$index]
  558. );
  559. }
  560. }
  561. } // end while
  562. } // end while
  563. if ($seen_a_relation) {
  564. $this->_drawRelations();
  565. }
  566. $this->_drawTables();
  567. }
  568. /**
  569. * Set Show Grid
  570. *
  571. * @param boolean $value show grid of the document or not
  572. *
  573. * @return void
  574. */
  575. public function setShowGrid($value)
  576. {
  577. $this->_showGrid = $value;
  578. }
  579. /**
  580. * Returns whether to show grid
  581. *
  582. * @return boolean whether to show grid
  583. */
  584. public function isShowGrid()
  585. {
  586. return $this->_showGrid;
  587. }
  588. /**
  589. * Set Data Dictionary
  590. *
  591. * @param boolean $value show selected database data dictionary or not
  592. *
  593. * @return void
  594. */
  595. public function setWithDataDictionary($value)
  596. {
  597. $this->_withDoc = $value;
  598. }
  599. /**
  600. * Return whether to show selected database data dictionary or not
  601. *
  602. * @return boolean whether to show selected database data dictionary or not
  603. */
  604. public function isWithDataDictionary()
  605. {
  606. return $this->_withDoc;
  607. }
  608. /**
  609. * Sets the order of the table in data dictionary
  610. *
  611. * @param string $value table order
  612. *
  613. * @return void
  614. */
  615. public function setTableOrder($value)
  616. {
  617. $this->_tableOrder = $value;
  618. }
  619. /**
  620. * Returns the order of the table in data dictionary
  621. *
  622. * @return string table order
  623. */
  624. public function getTableOrder()
  625. {
  626. return $this->_tableOrder;
  627. }
  628. /**
  629. * Output Pdf Document for download
  630. *
  631. * @return void
  632. */
  633. public function showOutput()
  634. {
  635. $this->diagram->Download($this->getFileName('.pdf'));
  636. }
  637. /**
  638. * Sets X and Y minimum and maximum for a table cell
  639. *
  640. * @param Table_Stats_Pdf $table The table name of which sets XY co-ordinates
  641. *
  642. * @return void
  643. */
  644. private function _setMinMax($table)
  645. {
  646. $this->_xMax = max($this->_xMax, $table->x + $table->width);
  647. $this->_yMax = max($this->_yMax, $table->y + $table->height);
  648. $this->_xMin = min($this->_xMin, $table->x);
  649. $this->_yMin = min($this->_yMin, $table->y);
  650. }
  651. /**
  652. * Defines relation objects
  653. *
  654. * @param string $masterTable The master table name
  655. * @param string $masterField The relation field in the master table
  656. * @param string $foreignTable The foreign table name
  657. * @param string $foreignField The relation field in the foreign table
  658. *
  659. * @return void
  660. *
  661. * @see _setMinMax
  662. */
  663. private function _addRelation($masterTable, $masterField, $foreignTable,
  664. $foreignField
  665. ) {
  666. if (! isset($this->_tables[$masterTable])) {
  667. $this->_tables[$masterTable] = new Table_Stats_Pdf(
  668. $this->diagram,
  669. $this->db,
  670. $masterTable,
  671. null,
  672. $this->pageNumber,
  673. $this->_tablewidth,
  674. $this->showKeys,
  675. $this->tableDimension
  676. );
  677. $this->_setMinMax($this->_tables[$masterTable]);
  678. }
  679. if (! isset($this->_tables[$foreignTable])) {
  680. $this->_tables[$foreignTable] = new Table_Stats_Pdf(
  681. $this->diagram,
  682. $this->db,
  683. $foreignTable,
  684. null,
  685. $this->pageNumber,
  686. $this->_tablewidth,
  687. $this->showKeys,
  688. $this->tableDimension
  689. );
  690. $this->_setMinMax($this->_tables[$foreignTable]);
  691. }
  692. $this->relations[] = new Relation_Stats_Pdf(
  693. $this->diagram,
  694. $this->_tables[$masterTable],
  695. $masterField,
  696. $this->_tables[$foreignTable],
  697. $foreignField
  698. );
  699. }
  700. /**
  701. * Draws the grid
  702. *
  703. * @return void
  704. *
  705. * @see PMA_Schema_PDF
  706. */
  707. private function _strokeGrid()
  708. {
  709. $gridSize = 10;
  710. $labelHeight = 4;
  711. $labelWidth = 5;
  712. if ($this->_withDoc) {
  713. $topSpace = 6;
  714. $bottomSpace = 15;
  715. } else {
  716. $topSpace = 0;
  717. $bottomSpace = 0;
  718. }
  719. $this->diagram->SetMargins(0, 0);
  720. $this->diagram->SetDrawColor(200, 200, 200);
  721. // Draws horizontal lines
  722. $innerHeight = $this->diagram->getPageHeight() - $topSpace - $bottomSpace;
  723. for ($l = 0,
  724. $size = intval($innerHeight / $gridSize);
  725. $l <= $size;
  726. $l++
  727. ) {
  728. $this->diagram->line(
  729. 0, $l * $gridSize + $topSpace,
  730. $this->diagram->getPageWidth(), $l * $gridSize + $topSpace
  731. );
  732. // Avoid duplicates
  733. if ($l > 0
  734. && $l <= intval(($innerHeight - $labelHeight) / $gridSize)
  735. ) {
  736. $this->diagram->SetXY(0, $l * $gridSize + $topSpace);
  737. $label = (string) sprintf(
  738. '%.0f',
  739. ($l * $gridSize + $topSpace - $this->_topMargin)
  740. * $this->_scale + $this->_yMin
  741. );
  742. $this->diagram->Cell($labelWidth, $labelHeight, ' ' . $label);
  743. } // end if
  744. } // end for
  745. // Draws vertical lines
  746. for (
  747. $j = 0, $size = intval($this->diagram->getPageWidth() / $gridSize);
  748. $j <= $size;
  749. $j++
  750. ) {
  751. $this->diagram->line(
  752. $j * $gridSize,
  753. $topSpace,
  754. $j * $gridSize,
  755. $this->diagram->getPageHeight() - $bottomSpace
  756. );
  757. $this->diagram->SetXY($j * $gridSize, $topSpace);
  758. $label = (string) sprintf(
  759. '%.0f',
  760. ($j * $gridSize - $this->_leftMargin) * $this->_scale + $this->_xMin
  761. );
  762. $this->diagram->Cell($labelWidth, $labelHeight, $label);
  763. }
  764. }
  765. /**
  766. * Draws relation arrows
  767. *
  768. * @return void
  769. *
  770. * @see Relation_Stats_Pdf::relationdraw()
  771. */
  772. private function _drawRelations()
  773. {
  774. $i = 0;
  775. foreach ($this->relations as $relation) {
  776. $relation->relationDraw($this->showColor, $i);
  777. $i++;
  778. }
  779. }
  780. /**
  781. * Draws tables
  782. *
  783. * @return void
  784. *
  785. * @see Table_Stats_Pdf::tableDraw()
  786. */
  787. private function _drawTables()
  788. {
  789. foreach ($this->_tables as $table) {
  790. $table->tableDraw(null, $this->_withDoc, $this->showColor);
  791. }
  792. }
  793. /**
  794. * Generates data dictionary pages.
  795. *
  796. * @param array $alltables Tables to document.
  797. *
  798. * @return void
  799. */
  800. public function dataDictionaryDoc($alltables)
  801. {
  802. // TOC
  803. $this->diagram->addpage($this->orientation);
  804. $this->diagram->Cell(0, 9, __('Table of contents'), 1, 0, 'C');
  805. $this->diagram->Ln(15);
  806. $i = 1;
  807. foreach ($alltables as $table) {
  808. $this->diagram->PMA_links['doc'][$table]['-']
  809. = $this->diagram->AddLink();
  810. $this->diagram->SetX(10);
  811. // $this->diagram->Ln(1);
  812. $this->diagram->Cell(
  813. 0, 6, __('Page number:') . ' {' . sprintf("%02d", $i) . '}', 0, 0,
  814. 'R', 0, $this->diagram->PMA_links['doc'][$table]['-']
  815. );
  816. $this->diagram->SetX(10);
  817. $this->diagram->Cell(
  818. 0, 6, $i . ' ' . $table, 0, 1,
  819. 'L', 0, $this->diagram->PMA_links['doc'][$table]['-']
  820. );
  821. // $this->diagram->Ln(1);
  822. $fields = $GLOBALS['dbi']->getColumns($this->db, $table);
  823. foreach ($fields as $row) {
  824. $this->diagram->SetX(20);
  825. $field_name = $row['Field'];
  826. $this->diagram->PMA_links['doc'][$table][$field_name]
  827. = $this->diagram->AddLink();
  828. //$this->diagram->Cell(
  829. // 0, 6, $field_name, 0, 1,
  830. // 'L', 0, $this->diagram->PMA_links['doc'][$table][$field_name]
  831. //);
  832. }
  833. $i++;
  834. }
  835. $this->diagram->PMA_links['RT']['-'] = $this->diagram->AddLink();
  836. $this->diagram->SetX(10);
  837. $this->diagram->Cell(
  838. 0, 6, __('Page number:') . ' {00}', 0, 0,
  839. 'R', 0, $this->diagram->PMA_links['RT']['-']
  840. );
  841. $this->diagram->SetX(10);
  842. $this->diagram->Cell(
  843. 0, 6, $i . ' ' . __('Relational schema'), 0, 1,
  844. 'L', 0, $this->diagram->PMA_links['RT']['-']
  845. );
  846. $z = 0;
  847. foreach ($alltables as $table) {
  848. $z++;
  849. $this->diagram->SetAutoPageBreak(true, 15);
  850. $this->diagram->addpage($this->orientation);
  851. $this->diagram->Bookmark($table);
  852. $this->diagram->SetAlias(
  853. '{' . sprintf("%02d", $z) . '}', $this->diagram->PageNo()
  854. );
  855. $this->diagram->PMA_links['RT'][$table]['-']
  856. = $this->diagram->AddLink();
  857. $this->diagram->SetLink(
  858. $this->diagram->PMA_links['doc'][$table]['-'], -1
  859. );
  860. $this->diagram->SetFont($this->_ff, 'B', 18);
  861. $this->diagram->Cell(
  862. 0, 8, $z . ' ' . $table, 1, 1,
  863. 'C', 0, $this->diagram->PMA_links['RT'][$table]['-']
  864. );
  865. $this->diagram->SetFont($this->_ff, '', 8);
  866. $this->diagram->ln();
  867. $cfgRelation = PMA_getRelationsParam();
  868. $comments = PMA_getComments($this->db, $table);
  869. if ($cfgRelation['mimework']) {
  870. $mime_map = PMA_getMIME($this->db, $table, true);
  871. }
  872. /**
  873. * Gets table information
  874. */
  875. $showtable = $GLOBALS['dbi']->getTable($this->db, $table)
  876. ->getStatusInfo();
  877. $show_comment = isset($showtable['Comment'])
  878. ? $showtable['Comment']
  879. : '';
  880. $create_time = isset($showtable['Create_time'])
  881. ? PMA_Util::localisedDate(
  882. strtotime($showtable['Create_time'])
  883. )
  884. : '';
  885. $update_time = isset($showtable['Update_time'])
  886. ? PMA_Util::localisedDate(
  887. strtotime($showtable['Update_time'])
  888. )
  889. : '';
  890. $check_time = isset($showtable['Check_time'])
  891. ? PMA_Util::localisedDate(
  892. strtotime($showtable['Check_time'])
  893. )
  894. : '';
  895. /**
  896. * Gets fields properties
  897. */
  898. $columns = $GLOBALS['dbi']->getColumns($this->db, $table);
  899. // Find which tables are related with the current one and write it in
  900. // an array
  901. $res_rel = PMA_getForeigners($this->db, $table);
  902. /**
  903. * Displays the comments of the table if MySQL >= 3.23
  904. */
  905. $break = false;
  906. if (! empty($show_comment)) {
  907. $this->diagram->Cell(
  908. 0, 3, __('Table comments:') . ' ' . $show_comment, 0, 1
  909. );
  910. $break = true;
  911. }
  912. if (! empty($create_time)) {
  913. $this->diagram->Cell(
  914. 0, 3, __('Creation:') . ' ' . $create_time, 0, 1
  915. );
  916. $break = true;
  917. }
  918. if (! empty($update_time)) {
  919. $this->diagram->Cell(
  920. 0, 3, __('Last update:') . ' ' . $update_time, 0, 1
  921. );
  922. $break = true;
  923. }
  924. if (! empty($check_time)) {
  925. $this->diagram->Cell(
  926. 0, 3, __('Last check:') . ' ' . $check_time, 0, 1
  927. );
  928. $break = true;
  929. }
  930. if ($break == true) {
  931. $this->diagram->Cell(0, 3, '', 0, 1);
  932. $this->diagram->Ln();
  933. }
  934. $this->diagram->SetFont($this->_ff, 'B');
  935. if (isset($this->orientation) && $this->orientation == 'L') {
  936. $this->diagram->Cell(25, 8, __('Column'), 1, 0, 'C');
  937. $this->diagram->Cell(20, 8, __('Type'), 1, 0, 'C');
  938. $this->diagram->Cell(20, 8, __('Attributes'), 1, 0, 'C');
  939. $this->diagram->Cell(10, 8, __('Null'), 1, 0, 'C');
  940. $this->diagram->Cell(20, 8, __('Default'), 1, 0, 'C');
  941. $this->diagram->Cell(25, 8, __('Extra'), 1, 0, 'C');
  942. $this->diagram->Cell(45, 8, __('Links to'), 1, 0, 'C');
  943. if ($this->paper == 'A4') {
  944. $comments_width = 67;
  945. } else {
  946. // this is really intended for 'letter'
  947. /**
  948. * @todo find optimal width for all formats
  949. */
  950. $comments_width = 50;
  951. }
  952. $this->diagram->Cell($comments_width, 8, __('Comments'), 1, 0, 'C');
  953. $this->diagram->Cell(45, 8, 'MIME', 1, 1, 'C');
  954. $this->diagram->SetWidths(
  955. array(25, 20, 20, 10, 20, 25, 45, $comments_width, 45)
  956. );
  957. } else {
  958. $this->diagram->Cell(20, 8, __('Column'), 1, 0, 'C');
  959. $this->diagram->Cell(20, 8, __('Type'), 1, 0, 'C');
  960. $this->diagram->Cell(20, 8, __('Attributes'), 1, 0, 'C');
  961. $this->diagram->Cell(10, 8, __('Null'), 1, 0, 'C');
  962. $this->diagram->Cell(15, 8, __('Default'), 1, 0, 'C');
  963. $this->diagram->Cell(15, 8, __('Extra'), 1, 0, 'C');
  964. $this->diagram->Cell(30, 8, __('Links to'), 1, 0, 'C');
  965. $this->diagram->Cell(30, 8, __('Comments'), 1, 0, 'C');
  966. $this->diagram->Cell(30, 8, 'MIME', 1, 1, 'C');
  967. $this->diagram->SetWidths(array(20, 20, 20, 10, 15, 15, 30, 30, 30));
  968. }
  969. $this->diagram->SetFont($this->_ff, '');
  970. foreach ($columns as $row) {
  971. $extracted_columnspec
  972. = PMA_Util::extractColumnSpec($row['Type']);
  973. $type = $extracted_columnspec['print_type'];
  974. $attribute = $extracted_columnspec['attribute'];
  975. if (! isset($row['Default'])) {
  976. if ($row['Null'] != '' && $row['Null'] != 'NO') {
  977. $row['Default'] = 'NULL';
  978. }
  979. }
  980. $field_name = $row['Field'];
  981. // $this->diagram->Ln();
  982. $this->diagram->PMA_links['RT'][$table][$field_name]
  983. = $this->diagram->AddLink();
  984. $this->diagram->Bookmark($field_name, 1, -1);
  985. $this->diagram->SetLink(
  986. $this->diagram->PMA_links['doc'][$table][$field_name], -1
  987. );
  988. $foreigner = PMA_searchColumnInForeigners($res_rel, $field_name);
  989. $linksTo = '';
  990. if ($foreigner) {
  991. $linksTo = '-> ';
  992. if ($foreigner['foreign_db'] != $this->db) {
  993. $linksTo .= $foreigner['foreign_db'] . '.';
  994. }
  995. $linksTo .= $foreigner['foreign_table']
  996. . '.' . $foreigner['foreign_field'];
  997. if (isset($foreigner['on_update'])) { // not set for internal
  998. $linksTo .= "\n" . 'ON UPDATE ' . $foreigner['on_update'];
  999. $linksTo .= "\n" . 'ON DELETE ' . $foreigner['on_delete'];
  1000. }
  1001. }
  1002. $this->diagram_row = array(
  1003. $field_name,
  1004. $type,
  1005. $attribute,
  1006. (($row['Null'] == '' || $row['Null'] == 'NO')
  1007. ? __('No')
  1008. : __('Yes')),
  1009. (isset($row['Default']) ? $row['Default'] : ''),
  1010. $row['Extra'],
  1011. $linksTo,
  1012. (isset($comments[$field_name])
  1013. ? $comments[$field_name]
  1014. : ''),
  1015. (isset($mime_map) && isset($mime_map[$field_name])
  1016. ? str_replace('_', '/', $mime_map[$field_name]['mimetype'])
  1017. : '')
  1018. );
  1019. $links = array();
  1020. $links[0] = $this->diagram->PMA_links['RT'][$table][$field_name];
  1021. if ($foreigner
  1022. && isset($this->diagram->PMA_links['doc'][$foreigner['foreign_table']][$foreigner['foreign_field']])
  1023. ) {
  1024. $links[6] = $this->diagram->PMA_links['doc']
  1025. [$foreigner['foreign_table']][$foreigner['foreign_field']];
  1026. } else {
  1027. unset($links[6]);
  1028. }
  1029. $this->diagram->Row($this->diagram_row, $links);
  1030. } // end foreach
  1031. $this->diagram->SetFont($this->_ff, '', 14);
  1032. } //end each
  1033. }
  1034. }