PageRenderTime 26ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/phpmyadmin/libraries/export/pdf.php

https://github.com/md-tech/openemr
PHP | 466 lines | 293 code | 46 blank | 127 comment | 44 complexity | abd2c042b02d0df401bd2a8dc6565f21 MD5 | raw file
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Produce a PDF report (export) from a query
  5. *
  6. * @version $Id$
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. /**
  12. *
  13. */
  14. if (isset($plugin_list)) {
  15. $plugin_list['pdf'] = array(
  16. 'text' => 'strPDF',
  17. 'extension' => 'pdf',
  18. 'mime_type' => 'application/pdf',
  19. 'force_file' => true,
  20. 'options' => array(
  21. array('type' => 'message_only', 'name' => 'explanation', 'text' => 'strPDFReportExplanation'),
  22. array('type' => 'text', 'name' => 'report_title', 'text' => 'strPDFReportTitle'),
  23. array('type' => 'hidden', 'name' => 'data'),
  24. ),
  25. 'options_text' => 'strOptions',
  26. );
  27. } else {
  28. /**
  29. * Font used in PDF.
  30. *
  31. * @todo Make this configuratble (at least Sans/Serif).
  32. */
  33. define('PMA_PDF_FONT', 'DejaVuSans');
  34. require_once './libraries/tcpdf/tcpdf.php';
  35. // Adapted from a LGPL script by Philip Clarke
  36. class PMA_PDF extends TCPDF
  37. {
  38. var $tablewidths;
  39. var $headerset;
  40. var $footerset;
  41. // overloading of a tcpdf function:
  42. function _beginpage($orientation)
  43. {
  44. $this->page++;
  45. // solved the problem of overwriting a page, if it already exists
  46. if (!isset($this->pages[$this->page])) {
  47. $this->pages[$this->page] = '';
  48. }
  49. $this->state = 2;
  50. $this->x = $this->lMargin;
  51. $this->y = $this->tMargin;
  52. $this->lasth = 0;
  53. $this->FontFamily = '';
  54. //Page orientation
  55. if (!$orientation) {
  56. $orientation = $this->DefOrientation;
  57. } else {
  58. $orientation = strtoupper($orientation{0});
  59. if ($orientation != $this->DefOrientation) {
  60. $this->OrientationChanges[$this->page] = true;
  61. }
  62. }
  63. if ($orientation != $this->CurOrientation) {
  64. //Change orientation
  65. if ($orientation == 'P') {
  66. $this->wPt = $this->fwPt;
  67. $this->hPt = $this->fhPt;
  68. $this->w = $this->fw;
  69. $this->h = $this->fh;
  70. } else {
  71. $this->wPt = $this->fhPt;
  72. $this->hPt = $this->fwPt;
  73. $this->w = $this->fh;
  74. $this->h = $this->fw;
  75. }
  76. $this->PageBreakTrigger = $this->h - $this->bMargin;
  77. $this->CurOrientation = $orientation;
  78. }
  79. }
  80. function Header()
  81. {
  82. global $maxY;
  83. // Check if header for this page already exists
  84. if (!isset($this->headerset[$this->page])) {
  85. $fullwidth = 0;
  86. foreach ($this->tablewidths as $width) {
  87. $fullwidth += $width;
  88. }
  89. $this->SetY(($this->tMargin) - ($this->FontSizePt/$this->k)*2);
  90. $this->cellFontSize = $this->FontSizePt ;
  91. $this->SetFont(PMA_PDF_FONT, '', ($this->titleFontSize ? $this->titleFontSize : $this->FontSizePt));
  92. $this->Cell(0, $this->FontSizePt, $this->titleText, 0, 1, 'C');
  93. $l = ($this->lMargin);
  94. $this->SetFont(PMA_PDF_FONT, '', $this->cellFontSize);
  95. foreach ($this->colTitles as $col => $txt) {
  96. $this->SetXY($l, ($this->tMargin));
  97. $this->MultiCell($this->tablewidths[$col], $this->FontSizePt, $txt);
  98. $l += $this->tablewidths[$col] ;
  99. $maxY = ($maxY < $this->getY()) ? $this->getY() : $maxY ;
  100. }
  101. $this->SetXY($this->lMargin, $this->tMargin);
  102. $this->setFillColor(200, 200, 200);
  103. $l = ($this->lMargin);
  104. foreach ($this->colTitles as $col => $txt) {
  105. $this->SetXY($l, $this->tMargin);
  106. $this->cell($this->tablewidths[$col], $maxY-($this->tMargin), '', 1, 0, 'L', 1);
  107. $this->SetXY($l, $this->tMargin);
  108. $this->MultiCell($this->tablewidths[$col], $this->FontSizePt, $txt, 0, 'C');
  109. $l += $this->tablewidths[$col];
  110. }
  111. $this->setFillColor(255, 255, 255);
  112. // set headerset
  113. $this->headerset[$this->page] = 1;
  114. }
  115. $this->SetY($maxY);
  116. }
  117. function Footer()
  118. {
  119. // Check if footer for this page already exists
  120. if (!isset($this->footerset[$this->page])) {
  121. $this->SetY(-15);
  122. //Page number
  123. $this->Cell(0, 10, $GLOBALS['strPageNumber'] .' '.$this->PageNo() .'/{nb}', 'T', 0, 'C');
  124. // set footerset
  125. $this->footerset[$this->page] = 1;
  126. }
  127. }
  128. function morepagestable($lineheight=8)
  129. {
  130. // some things to set and 'remember'
  131. $l = $this->lMargin;
  132. $startheight = $h = $this->GetY();
  133. $startpage = $currpage = $this->page;
  134. // calculate the whole width
  135. $fullwidth = 0;
  136. foreach ($this->tablewidths as $width) {
  137. $fullwidth += $width;
  138. }
  139. // Now let's start to write the table
  140. $row = 0;
  141. $tmpheight = array();
  142. $maxpage = 0;
  143. while ($data = PMA_DBI_fetch_row($this->results)) {
  144. $this->page = $currpage;
  145. // write the horizontal borders
  146. $this->Line($l, $h, $fullwidth+$l, $h);
  147. // write the content and remember the height of the highest col
  148. foreach ($data as $col => $txt) {
  149. $this->page = $currpage;
  150. $this->SetXY($l, $h);
  151. if ($this->tablewidths[$col] > 0) {
  152. $this->MultiCell($this->tablewidths[$col], $lineheight, $txt, 0, $this->colAlign[$col]);
  153. $l += $this->tablewidths[$col];
  154. }
  155. if (!isset($tmpheight[$row.'-'.$this->page])) {
  156. $tmpheight[$row.'-'.$this->page] = 0;
  157. }
  158. if ($tmpheight[$row.'-'.$this->page] < $this->GetY()) {
  159. $tmpheight[$row.'-'.$this->page] = $this->GetY();
  160. }
  161. if ($this->page > $maxpage) {
  162. $maxpage = $this->page;
  163. }
  164. unset($data[$col]);
  165. }
  166. // get the height we were in the last used page
  167. $h = $tmpheight[$row.'-'.$maxpage];
  168. // set the "pointer" to the left margin
  169. $l = $this->lMargin;
  170. // set the $currpage to the last page
  171. $currpage = $maxpage;
  172. unset($data[$row]);
  173. $row++;
  174. }
  175. // draw the borders
  176. // we start adding a horizontal line on the last page
  177. $this->page = $maxpage;
  178. $this->Line($l, $h, $fullwidth+$l, $h);
  179. // now we start at the top of the document and walk down
  180. for ($i = $startpage; $i <= $maxpage; $i++) {
  181. $this->page = $i;
  182. $l = $this->lMargin;
  183. $t = ($i == $startpage) ? $startheight : $this->tMargin;
  184. $lh = ($i == $maxpage) ? $h : $this->h-$this->bMargin;
  185. $this->Line($l, $t, $l, $lh);
  186. foreach ($this->tablewidths as $width) {
  187. $l += $width;
  188. $this->Line($l, $t, $l, $lh);
  189. }
  190. }
  191. // set it to the last page, if not it'll cause some problems
  192. $this->page = $maxpage;
  193. }
  194. function mysql_report($query, $attr = array())
  195. {
  196. foreach ($attr as $key => $val){
  197. $this->$key = $val ;
  198. }
  199. /**
  200. * Pass 1 for column widths
  201. */
  202. $this->results = PMA_DBI_query($query, null, PMA_DBI_QUERY_UNBUFFERED);
  203. $this->numFields = PMA_DBI_num_fields($this->results);
  204. $this->fields = PMA_DBI_get_fields_meta($this->results);
  205. // if column widths not set
  206. if (!isset($this->tablewidths)){
  207. // sColWidth = starting col width (an average size width)
  208. $availableWidth = $this->w - $this->lMargin - $this->rMargin;
  209. $this->sColWidth = $availableWidth / $this->numFields;
  210. $totalTitleWidth = 0;
  211. // loop through results header and set initial col widths/ titles/ alignment
  212. // if a col title is less than the starting col width, reduce that column size
  213. for ($i = 0; $i < $this->numFields; $i++){
  214. $stringWidth = $this->getstringwidth($this->fields[$i]->name) + 6 ;
  215. // save the real title's width
  216. $titleWidth[$i] = $stringWidth;
  217. $totalTitleWidth += $stringWidth;
  218. // set any column titles less than the start width to the column title width
  219. if ($stringWidth < $this->sColWidth){
  220. $colFits[$i] = $stringWidth ;
  221. }
  222. $this->colTitles[$i] = $this->fields[$i]->name;
  223. $this->display_column[$i] = true;
  224. switch ($this->fields[$i]->type){
  225. case 'int':
  226. $this->colAlign[$i] = 'R';
  227. break;
  228. case 'blob':
  229. case 'tinyblob':
  230. case 'mediumblob':
  231. case 'longblob':
  232. /**
  233. * @todo do not deactivate completely the display
  234. * but show the field's name and [BLOB]
  235. */
  236. if (stristr($this->fields[$i]->flags, 'BINARY')) {
  237. $this->display_column[$i] = false;
  238. unset($this->colTitles[$i]);
  239. }
  240. $this->colAlign[$i] = 'L';
  241. break;
  242. default:
  243. $this->colAlign[$i] = 'L';
  244. }
  245. }
  246. // title width verification
  247. if ($totalTitleWidth > $availableWidth) {
  248. $adjustingMode = true;
  249. } else {
  250. $adjustingMode = false;
  251. // we have enough space for all the titles at their
  252. // original width so use the true title's width
  253. foreach ($titleWidth as $key => $val) {
  254. $colFits[$key] = $val;
  255. }
  256. }
  257. // loop through the data, any column whose contents is bigger
  258. // than the col size is resized
  259. /**
  260. * @todo force here a LIMIT to avoid reading all rows
  261. */
  262. while ($row = PMA_DBI_fetch_row($this->results)) {
  263. foreach ($colFits as $key => $val) {
  264. $stringWidth = $this->getstringwidth($row[$key]) + 6 ;
  265. if ($adjustingMode && ($stringWidth > $this->sColWidth)) {
  266. // any column whose data's width is bigger than the start width is now discarded
  267. unset($colFits[$key]);
  268. } else {
  269. // if data's width is bigger than the current column width,
  270. // enlarge the column (but avoid enlarging it if the
  271. // data's width is very big)
  272. if ($stringWidth > $val && $stringWidth < ($this->sColWidth * 3)) {
  273. $colFits[$key] = $stringWidth ;
  274. }
  275. }
  276. }
  277. }
  278. $totAlreadyFitted = 0;
  279. foreach ($colFits as $key => $val){
  280. // set fitted columns to smallest size
  281. $this->tablewidths[$key] = $val;
  282. // to work out how much (if any) space has been freed up
  283. $totAlreadyFitted += $val;
  284. }
  285. if ($adjustingMode) {
  286. $surplus = (sizeof($colFits) * $this->sColWidth) - $totAlreadyFitted;
  287. $surplusToAdd = $surplus / ($this->numFields - sizeof($colFits));
  288. } else {
  289. $surplusToAdd = 0;
  290. }
  291. for ($i=0; $i < $this->numFields; $i++) {
  292. if (!in_array($i, array_keys($colFits))) {
  293. $this->tablewidths[$i] = $this->sColWidth + $surplusToAdd;
  294. }
  295. if ($this->display_column[$i] == false) {
  296. $this->tablewidths[$i] = 0;
  297. }
  298. }
  299. ksort($this->tablewidths);
  300. }
  301. PMA_DBI_free_result($this->results);
  302. // Pass 2
  303. $this->results = PMA_DBI_query($query, null, PMA_DBI_QUERY_UNBUFFERED);
  304. $this->Open();
  305. $this->setY($this->tMargin);
  306. $this->AddPage();
  307. $this->morepagestable($this->FontSizePt);
  308. PMA_DBI_free_result($this->results);
  309. } // end of mysql_report function
  310. } // end of PMA_PDF class
  311. /**
  312. * Outputs comment
  313. *
  314. * @param string Text of comment
  315. *
  316. * @return bool Whether it suceeded
  317. */
  318. function PMA_exportComment($text)
  319. {
  320. return TRUE;
  321. }
  322. /**
  323. * Outputs export footer
  324. *
  325. * @return bool Whether it suceeded
  326. *
  327. * @access public
  328. */
  329. function PMA_exportFooter()
  330. {
  331. return TRUE;
  332. }
  333. /**
  334. * Outputs export header
  335. *
  336. * @return bool Whether it suceeded
  337. *
  338. * @access public
  339. */
  340. function PMA_exportHeader()
  341. {
  342. return TRUE;
  343. }
  344. /**
  345. * Outputs database header
  346. *
  347. * @param string Database name
  348. *
  349. * @return bool Whether it suceeded
  350. *
  351. * @access public
  352. */
  353. function PMA_exportDBHeader($db)
  354. {
  355. return TRUE;
  356. }
  357. /**
  358. * Outputs database footer
  359. *
  360. * @param string Database name
  361. *
  362. * @return bool Whether it suceeded
  363. *
  364. * @access public
  365. */
  366. function PMA_exportDBFooter($db)
  367. {
  368. return TRUE;
  369. }
  370. /**
  371. * Outputs create database database
  372. *
  373. * @param string Database name
  374. *
  375. * @return bool Whether it suceeded
  376. *
  377. * @access public
  378. */
  379. function PMA_exportDBCreate($db)
  380. {
  381. return TRUE;
  382. }
  383. /**
  384. * Outputs the content of a table in PDF format
  385. *
  386. * @todo user-defined page orientation, paper size
  387. * @param string the database name
  388. * @param string the table name
  389. * @param string the end of line sequence
  390. * @param string the url to go back in case of error
  391. * @param string SQL query for obtaining data
  392. *
  393. * @return bool Whether it suceeded
  394. *
  395. * @access public
  396. */
  397. function PMA_exportData($db, $table, $crlf, $error_url, $sql_query)
  398. {
  399. global $what;
  400. global $pdf_report_title;
  401. $pdf = new PMA_PDF('L', 'pt', 'A3');
  402. $pdf->AddFont('DejaVuSans', '', 'dejavusans.php');
  403. $pdf->AddFont('DejaVuSans', 'B', 'dejavusans-bold.php');
  404. $pdf->AddFont('DejaVuSerif', '', 'dejavuserif.php');
  405. $pdf->AddFont('DejaVuSerif', 'B', 'dejavuserif-bold.php');
  406. $pdf->SetFont(PMA_PDF_FONT, '', 11.5);
  407. $pdf->AliasNbPages();
  408. $attr=array('titleFontSize' => 18, 'titleText' => $pdf_report_title);
  409. $pdf->mysql_report($sql_query, $attr);
  410. // instead of $pdf->Output():
  411. if ($pdf->state < 3) {
  412. $pdf->Close();
  413. }
  414. if (!PMA_exportOutputHandler($pdf->buffer)) {
  415. return FALSE;
  416. }
  417. return TRUE;
  418. } // end of the 'PMA_exportData()' function
  419. }
  420. ?>